ande
ande

Reputation: 67

Delete short words in a Pascal string

I need to delete short words (shorter that three symbols) in a string ended by a dot. And after to display that string without these words.

So we need a string from a user as an input like this: "This is a simple string a man types." And in this string the program should delete each word that is shorter than three symbols. In our string these are: "is, a, a". So the output should be "This simple string man types."

It's Pascal/Delphi task for my programming course.

I've been thinking about this simple problem for a couple of days and apparently ran out of ideas how to solve it and ask for your help. I tried different loops for the main part which is to basically find sequence of less then three symbols between spaces. I am trying to debug it for quite some time, but to no results.

I use Lazarus 1.6.2, FPC 3.0, and Mac OS X v10.11 (El Capitan). My code is the following:

 VAR
   UserString: string;
   i, n: byte;    // Counters for the symbols in the string. 'i' counts every symbol.
   again: boolean;   // In case we need to repeat the program again
   UserAnswerRepeat: char;
   label repeat_again;

 BEGIN
   again:=false;
 repeat_again:                 // Label to repeat the program
   Writeln('Enter your string (ended by a dot):');
   Readln(UserString);

   // MAIN LOOP:
   n:=1;              // 'n' counts symbols in the words
   for i:=1 to length(UserString) do
   begin
     while (UserString[i] <> ' ') do inc(n); // Here I have Range Check Error. Don't know how to get rid of it.
     if (UserString[n] <> ' ') and (n<3) then
     begin
       delete(UserString, i-n, n);
       n:=1
     end;
   end;

   Writeln('The result is: ', UserString);

   Writeln('Do you want to repeat the program? (Y/N)');
   Readln(UserAnswerRepeat);
   if (UserAnswerRepeat = 'Y') or (UserAnswerRepeat = 'y')  then
     again:=true;
   if (again = true) then
     goto repeat_again;
 END.

Another minor question is: How do you make your console application repeat after the successful run? Here I used labels and goto. Maybe there's another nice way to do it again?

Upvotes: 1

Views: 1191

Answers (4)

Nasreddine Galfout
Nasreddine Galfout

Reputation: 2591

In this situation look for the word separator. In your case it is 'space'. Also, count for the last word before the dot as it is not followed with 'space'.

One way to write your main loop is:

var
  LastPos, I: Integer;
  Tmp, UserString: String;
begin
  LastPos := 1;
  Tmp := '';
  for I := 1 to Length(UserString) do
  begin
    if (UserString[I] = ' ') or (I = Length(UserString)) then
    begin
      if (I - LastPos >= 3) then Tmp := Tmp + Copy(UserString, LastPos, I - LastPos + 1);
        LastPos := I + 1;
    end;
  end;
  UserString: = Tmp; 
end;

Upvotes: 2

Marco van de Voort
Marco van de Voort

Reputation: 26376

A different approach:

uses classes;

var v : TStringlist;
    i : integer;
begin
 v :=TStringlist.create;
 v.strictdelimiter:=true;
 v.delimiter:=' ';
 v.delimitedtext:='This is a simple string a man types';
 for i:=v.count-1 downto 0 do
    if length(v[i])<3 then
       v.delete(i);
 writeln(v.delimitedtext);
 v.free;
end.

Upvotes: 1

ande
ande

Reputation: 67

Thank you all again for pointing to the right direction. I finally managed to came up with the solution I initially intended, so that the program actually deletes the short (less then 3 symbols) words. Here's what I got:

VAR
UserString: string; //должна быть строка на 40 символов и точку в конце
i, n: byte;

BEGIN
Writeln('Enter the string:');
Readln(UserString);

i:=0;
n:=1;    

repeat       //MAIN LOOP:

  inc(i);
  if (UserString[i] = ' ') or (UserString[i] = '.') then

     begin
        if (i-n<3)then
        begin
        delete(UserString, n, i-n+1);
        i:=n-1;
        end;
        n:=i+1
     end

until (UserString[i] = '.') or (i>length(UserString));

Writeln('Result String: ', UserString);
END.

Any suggestions welcomed! Also there's an open question about making the program repeat in console mode. Is labels the best way to do it (see first code in question part)?

Upvotes: 1

Tom Brunberg
Tom Brunberg

Reputation: 21045

A for loop start and end values for the control variable are evaluated only once. You set the end value to the length of the string. However, during the loop you remove parts from the string, and therefore the end value is past the end of the string. Try with a while loop or repeat .. until loop.

The actual reason for the error is in the line

  while (UserString[i] <> ' ') do inc(n);

How long will the loop continue? What ends the loop?

You also need to rethink how you calculate characters using n.

Upvotes: 1

Related Questions