Board index » delphi » What's wrong with this Procedure???

What's wrong with this Procedure???

Hello All,

The Procedure I'm refering to is Getword which is supposed split a sentence
up into seperate words and put them into an array.  The Procedure keeps
printing a lot of Garbage afterwords and I can't figure out why .. can
anyone Help??

Thanking you all,

David

Program Tester;

Uses Crt;

Type
  Str255 = string[255];

Var
  AB:Str255;
  Ar:array[1..15] of string;

Procedure getword(S:Str255);

Var
   I: Integer;
   Output: Str255;
   ArN:Integer;

Begin
     Output := '';
     I := 1;  ArN:=1;
     Repeat
       Repeat
           Output := Output + S[I];
           Inc(I);
       until (S[I] = ' ');
       inc(I);
       if Output = '' then Output := ' ';
       Ar[Arn]:=Output;
       output:='';
       inc(arn);
    until ((arn=10) or (I+1 = length(S)));
    clrscr;
    for Arn:= 1 to 10 do
    writeln(Ar[arn]);
end;

Begin
  Writeln('start');
  Readln(AB);
  Getword(ab);
  readln;

end.

 

Re:What's wrong with this Procedure???


Quote
David wrote in message <38e6a...@news.waldonet.ent.mt>...
>Hello All,

>The Procedure I'm refering to is Getword which is supposed split a sentence
>up into seperate words and put them into an array.  The Procedure keeps
>printing a lot of Garbage afterwords and I can't figure out why .. can
>anyone Help??

>Thanking you all,

>David

>Program Tester;

>Uses Crt;

>Type
>  Str255 = string[255];

>Var
>  AB:Str255;
>  Ar:array[1..15] of string;

>Procedure getword(S:Str255);

>Var
>   I: Integer;
>   Output: Str255;
>   ArN:Integer;

>Begin
>     Output := '';
>     I := 1;  ArN:=1;
>     Repeat
>       Repeat
>           Output := Output + S[I];
>           Inc(I);
>       until (S[I] = ' ');
>       inc(I);
>       if Output = '' then Output := ' ';
>       Ar[Arn]:=Output;
>       output:='';
>       inc(arn);
>    until ((arn=10) or (I+1 = length(S)));
>    clrscr;
>    for Arn:= 1 to 10 do
>    writeln(Ar[arn]);
>end;

>Begin
>  Writeln('start');
>  Readln(AB);
>  Getword(ab);
>  readln;

>end.

David,

Your general approach is OK. Have a look at these items:
- When parsing words, you look for the nearest space char.
  What about the last word? You should add a space char
  to the input string AB.
- Your program terminates when your index I is one greater
  than the length of S. You will have problems if S has lots
  of trailing spaces. You should trim all leading and trailing
  spaces, then add exactly one trailing space (see above
  para).
- Your program does not keep track of the number of words
  it has parsed. You always print out ten words. This generates
  the rubbish you mention above.
- "Output" is more or less a reserved word in Pascal. You
  should not really use it as a variable name.
- You declare Ar as a global variable but use it in procedure
  GetWord only. I suggest you declare it locally instead.

Once you have addressed these issues you might consider
an alternative approach to parsing. It goes like this:

1. Remove all leading & trailing spaces from your input string X.
2. Call PARSE(X, Element). This procedure will do two things:
   a) It will extract one word, and return it in Element
   b) It will remove that one word from X, and delete any leading spaces
from X.
3. Add Element to your array of words
4. If X is a null string, your work is done. Otherwise go back to 2.

KlausL

Re:What's wrong with this Procedure???


there are two errors that jump out at me right now:

1. you don't check to see if you're at the end of S while in the middle of
   inputting each word
2. your repeat loop only gathers 9 strings, but you try to print 10

here's some fixed code..  i tested it with every special case that came to
mind (empty string in S, space or multiple spaces at end of S, etc)
---
Program Tester;

Uses Crt;

Type
  Str255 = string[255];

Var
  AB:Str255;
  Ar:array[1..15] of string;

Procedure getword(S:Str255);

Var
   I: Integer;
   Output: Str255;
   ArN,count:Integer;
   eofstr:boolean;

Begin
     Output := '';
     I := 0;  ArN:=1;
     eofstr:=FALSE;

     if (S<>'') then  {don't bother if S if empty}
     Repeat
       repeat
           Inc(I);
           if (S[I] <> ' ') then Output := Output + S[I];
           if (I = length(S) ) then eofstr:=TRUE;
       until (S[I] = ' ') OR eofstr;

       if (Output <> '') then begin  {output=='' if there is space
                                      at end of string}
        Ar[ArN]:=Output;
        Output:='';
        inc(ArN);
       end;

     until (ArN=11) or eofstr;

     writeln('here is an array of the words entered: ');

     if (ArN=1) then writeln('No words were entered.');
     for count:= 1 to (ArN-1) do
      writeln(Ar[count]);

end; {procedure getword}

Begin
  clrscr;
  Writeln('start.  enter up to 10 words, separated by spaces');
  Readln(AB);
  Getword(ab);
  readln;
end.
---

assas...@reality.halo.nu

In comp.lang.pascal.borland David <da...@fastnet.net.mt> wrote:
: Hello All,

: The Procedure I'm refering to is Getword which is supposed split a sentence
: up into seperate words and put them into an array.  The Procedure keeps
: printing a lot of Garbage afterwords and I can't figure out why .. can
: anyone Help??

: Thanking you all,

: David

: Program Tester;

: Uses Crt;

: Type
:   Str255 = string[255];

: Var
:   AB:Str255;
:   Ar:array[1..15] of string;

: Procedure getword(S:Str255);

: Var
:    I: Integer;
:    Output: Str255;
:    ArN:Integer;

: Begin
:      Output := '';
:      I := 1;  ArN:=1;
:      Repeat
:        Repeat
:            Output := Output + S[I];
:            Inc(I);
:        until (S[I] = ' ');
:        inc(I);
:        if Output = '' then Output := ' ';
:        Ar[Arn]:=Output;
:        output:='';
:        inc(arn);
:     until ((arn=10) or (I+1 = length(S)));
:     clrscr;
:     for Arn:= 1 to 10 do
:     writeln(Ar[arn]);
: end;

: Begin
:   Writeln('start');
:   Readln(AB);
:   Getword(ab);
:   readln;

: end.

Re:What's wrong with this Procedure???


Quote
On Sun, 2 Apr 2000 03:57:02 +0200, David wrote:
> Getword ... keeps printing a lot of Garbage afterwords and I can't figure
> out why .. can anyone Help??
...
>        Repeat
>            Output := Output + S[I];
>            Inc(I);
>        until (S[I] = ' ');

This loop doesn't terminate until it sees a space. But the final word in
the sentence has (presumably) no space after it. Hence, you read past the
end of the string. Also, your index counting is a little off.

Make that last line above:

        until (I > length(S)) or (S[I] = ' ');

or something. Then change this:

Quote
>    until ((arn=10) or (I+1 = length(S)));

to this:

    until ((arn=10) or (I > length(S)));

--
William McBrine * wmcbr...@clark.net * http://www.clark.net/~wmcbrine/

Re:What's wrong with this Procedure???


(please do not cross post. usually, posting to c.l.p.borland is enough)

The following loop:

Quote
>       Repeat
>           Output := Output + S[I];
>           Inc(I);
>       until (S[I] = ' ');

Will not end correctly when the end of line S is reached.
suppose S='pq rst' (length=6)
after getting the word 'pq',
it will skip the space and read 'rst'
However, the character S[7] is not assigned, and there is no range check on
the length of string. It may contain garbage characters.
Therefore the ending condition (S[I]=' ') may or may not work (depending on
the garbage), so it will continue to give meaningless words afterwards.

A solution (not efficient, but very simple) is to add a space to the input
string.

For the so called 'good practice', a check on the string length is performed
in the inner loop.
repeat ... until I>length(s);

Another improvement (not important) is:

Quote
> until ((arn=10) or (I+1 = length(S)));

The latter condition may fail. For example, the first problem mentioned
above causes [I] to overshoot, say, length(s)+2. Then this condition will no
longer stop the REPEAT..UNTIL loop.
An alternative is to use > (bigger than) comparison, which works even if [I]
overshoots.

David ???g??31 <38e6a...@news.waldonet.ent.mt>...

Quote
>Hello All,

>The Procedure I'm refering to is Getword which is supposed split a sentence
>up into seperate words and put them into an array.  The Procedure keeps
>printing a lot of Garbage afterwords and I can't figure out why .. can
>anyone Help??

>Thanking you all,

>David

>Program Tester;

>Uses Crt;

>Type
>  Str255 = string[255];

>Var
>  AB:Str255;
>  Ar:array[1..15] of string;

>Procedure getword(S:Str255);

>Var
>   I: Integer;
>   Output: Str255;
>   ArN:Integer;

>Begin
>     Output := '';
>     I := 1;  ArN:=1;
>     Repeat
>       Repeat
>           Output := Output + S[I];
>           Inc(I);
>       until (S[I] = ' ');
>       inc(I);
>       if Output = '' then Output := ' ';
>       Ar[Arn]:=Output;
>       output:='';
>       inc(arn);
>    until ((arn=10) or (I+1 = length(S)));
>    clrscr;
>    for Arn:= 1 to 10 do
>    writeln(Ar[arn]);
>end;

>Begin
>  Writeln('start');
>  Readln(AB);
>  Getword(ab);
>  readln;

>end.

Other Threads