1) I am forced to use an array of pointers because I cannot know beforehand how
many words will be in the sentence. Is there any way to create an array of variable
length on the fly?
2) The method I am using is long, clumsy, and confusing, even to me -- and I wrote
it! Does anyone know of a better technique? Ideally, it should be a function that
reads words in a sentence, creates an array of size equal to number of words in the
sentence (see problem 1(!)), and places each word in an element of the array, minus
the punctuation. The return value would be the array, or a pointer to it, or
something of the sort (I'm flexible!).
Please e-mail replies, as I rarely check the group. I'd appreciate replies before
Thursday, 12/14/95, since the complete project is due on Friday. Thanks very much
in advance!
For your reference, I've included the relevant code snippets. This is the way my
code is set up now:
procedure TLREForm.OKButtonClick(Sender: TObject);
Type
{The types are actually included in a separate unit,
but I've included them here for reference}
WordPtr = ^WordRec;
WordRec = Record
ActualWord : String;
WordType:String;
end; {Record}
Const
EnteredLength = 100;
{The maximum number of words that can be entered}
UsedLength = EnteredLength - 1;
{The program counts from 0 to 99, so 100 words
looks like 99 to it}
var
Holder,
{A one-letter string representing
the letter of the sentence being
processed}
Sentence,
{The user-entered sentence}
Counter,
{A Loop index counter}
WordIndex,
{The record number of the word
being pointed to}
PositionHolder,
{The start of a new word}
LetterCounter,
{The number of letters in the
current word}
NumOfWords :Integer;
{The number of words}
DSS :Array [0..UsedLength] of WordPtr;
{Due to this restriction, the
sentence length is restricted to
100 words (!)}
{Blah blah blah -- irrelevant code}
begin {Main procedure}
{Blah blah blah -- irrelevant code}
{Get Sentence info code snipped}
{Count number of words. The program assumes each word
is terminated by a space or a period.}
NumOfWords := 0;
LetterCounter:=0;
WordIndex:=0;
For Counter := 0 to (Length(Sentence)-1) do
begin
Holder:= Copy(Sentence, Counter, 1);
If (Holder = ' ') or (Holder = '.') then
{If Holder signifies the end of a word}
Begin
NumOfWords := NumOfWords + 1;
{Add one to word counter}
New(DSS[WordIndex]);
{Allocate memory for the new word record}
DSS[WordIndex]^.ActualWord:= Copy(Sentence, PositionHolder,
LetterCounter);
{Copy word into array. Since the space
or period is not included (LetterCounter
has not been updated), only the word
itself is copied.}
WordIndex := WordIndex + 1;
{Increment Array Counter}
LetterCounter := 0;
{Reset word length counter}
PositionHolder := Counter + 1;
{Set start of next word}
end {if}
else {if it is a character}
LetterCounter := LetterCounter + 1;
{Increment number of letters in the word}
end; {FOR}
{Blah blah blah -- irrelevant code}
end; {Main Procedure}
Whew! Thanks again!
>I need help extracting words from a string. I currently have a String called
>"Sentence" which contains an unknown number of words -- it depends on the user's
>entry. Sentnece is all in caps. I need to break Sentence up into its component
>words, and put them in an array -- and here lie the problems.
>1) I am forced to use an array of pointers because I cannot know beforehand how
>many words will be in the sentence. Is there any way to create an array of variable
>length on the fly?
>2) The method I am using is long, clumsy, and confusing, even to me -- and I wrote
>it! Does anyone know of a better technique? Ideally, it should be a function that
>reads words in a sentence, creates an array of size equal to number of words in the
>sentence (see problem 1(!)), and places each word in an element of the array, minus
>the punctuation. The return value would be the array, or a pointer to it, or
>something of the sort (I'm flexible!).
>Please e-mail replies, as I rarely check the group. I'd appreciate replies before
>Thursday, 12/14/95, since the complete project is due on Friday. Thanks very much
>in advance!
I think that the "TStringList" type would serve you well here..
(extemporaneous undebugged code follows):
wordList.Clear;
inWord := false;
startLoc := 0;
for i := 1 to Length(s) do begin
if Pos(SEPARATORS, s[i]) <> 0 then begin {separator seen}
if inWord then begin
wordList.Add(Copy(s, startLoc, i-1)); { grab a word }
inWord := false;
end;
end else begin {non-separator seen}
if not inWord then begin
startLoc := i;
inWord := true;
end;
end;
end; {for words}
if inWord then begin
wordList.Add(Copy(s, startLoc, 255)); {add last word}
inWord := false;
end;
-Mike (gee, I *can* do this off the top of my head!) Robinson
(Did I get an "A"?)
>I need help extracting words from a string. I currently have a String called
>"Sentence" which contains an unknown number of words -- it depends on the user's
>entry. Sentnece is all in caps. I need to break Sentence up into its component
>words, and put them in an array -- and here lie the problems.
Have you tried using a TStringList. Basically it is a dynamic array of
strings. No need for you to rewrite it. Here are a couple functions you
can try (warning: this is off the top of my head - debug this):
function ExtractFromPChar (APChar: PChar): TStringList;
{-extracts words from a pchar}
Type
TBigBuffer = [1..$FFFF] of char;
PBugBuffer = ^TBugBuffer;
var
MyList: TStringList;
WordSt: string; {current word}
Buffer: PBigBuffer; {buffer}
p: pChar; {pointer to current position in buffer}
Size: Longint; {size of buffer}
CurPos: Longint; {current position in buffer}
BeginPos: Longint; {beginning position of current word}
EndPos: Longint; {ending position of current word}
function GetNextWord: string;
{-returns the next word in the buffer}
const
ValidChars: Set Of Char =
[#39{'}, 'a'..'z', 'A'..'Z', #130{é},
#160{á}..#165{Ņ}];
var
S: string; {string being constructed}
begin
BeginPos := CurPos;
EndPos := CurPos;
S := '';
{find the first letter of the next word}
while (not (Char (p^) in ValidChars)) and
(CurPos<Size) do
begin
Inc (CurPos, 1);
p := @Buffer^[CurPos];
end; { while }
if CurPos<Size then
begin
BeginPos := CurPos;
{goto the end of the word}
while ((Char (p^) in ValidChars) and
(CurPos<Size)) do
begin
S := ConCat (S, Char (p^));
Inc (CurPos, 1);
p := @Buffer^[CurPos];
EndPos := CurPos;
end; { while }
Result := S;
end {:} else
Result := '';
end; { GetNextWord }
begin
MyList := TStringList.Create;
Buffer := APChar;
Size := StrLen (APChar);
p := @Buffer^[1];
CurPos := 1;
repeat
WordSt := GetNextWord;
if WordSt <> '' then
MyList.Add (WordSt);
until WordSt = '';
Result := MyList;
end; { ExtractFromPChar }
function ExtractFromString (AString: String): TStringList;
{-extracts words from a string (limited to 255 characters)}
begin
AString := AString + #0;
Result := ExtractFromPChar (@AString[1]);
end; { ExtractFromString }
Good Luck,
-Ed Salgado
Eminent Domain Software
>I need help extracting words from a string. I currently have a String called
>"Sentence" which contains an unknown number of words -- it depends on the
>user's entry. Sentnece is all in caps. I need to break Sentence up into its
>component words, and put them in an array -- and here lie the problems.
>
>1) I am forced to use an array of pointers because I cannot know beforehand
>how many words will be in the sentence. Is there any way to create an array
>of variable length on the fly?
>
>2) The method I am using is long, clumsy, and confusing, even to me -- and I
>wrote it! Does anyone know of a better technique? Ideally, it should be a
>function that reads words in a sentence, creates an array of size equal to
>number of words in the sentence (see problem 1(!)), and places each word in
>an element of the array, minus the punctuation. The return value would be
>the array, or a pointer to it, or something of the sort (I'm flexible!).
I would use a TStringList object with each item in the list being a
separate word. You will have to create the TStringList before using
it and destroy it afterward.
>Please e-mail replies, as I rarely check the group. I'd appreciate replies
> before Thursday, 12/14/95, since the complete project is due on Friday.
Copied by email
--
Donald Oddy
Grove Systems Ltd. 0161-224 4465