PDA

View Full Version : word count in a memo box



yawbird
23-11-2002, 04:25 PM
hi there

can anybody shed some light on this. I am trying to implement a word count in a memo box I am having problems tryings to tackle this. I know it will involve checking for a space/./etc.

some code will be greatly appreciated

regards

Derek

Alimonster
23-11-2002, 05:52 PM
The following code appears to do the trick:

[background=#FFFFFF][normal=#000000][number=#FF0000][string=#0000FF][comment=#8080FF][reserved=#000000]function WordCount(const Text: String): Integer;
const
Whitespace: set of char = [#0..#32]; // chars to skip
var
i: Integer;
TextLength: Integer;
DoingWord: Boolean;
begin
Result := 0;

TextLength := Length(Text);
DoingWord := False;

for i := 1 to TextLength do
begin
// if not in whitespace, we've found a word. Next,
// we check if we weren't parsing a word - if we weren't
// then this is the start of another word, so we add
// one more to the result
if not (Text[i ] in Whitespace) then
begin
if not DoingWord then
begin
DoingWord := True;
Inc(Result);
end;
end
else // not doing a word
begin
DoingWord := False;
end;
end;
end;

// and an example use:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(WordCount(Memo1.Text)));
end;

Note that you can use "SomeMemo.Text" to get the memo's contents as a string.

The above works by going through each char and checking whether it's whitespace (or a control character). If so, it means no word is there - so the next time a non-control-char, non-space is found it's considered the start of the word.

You can bung more values into the set depending on your needs - for example:

Whitespace: set of char = [#0..#32, '.', ',', '[', ']', '(', ')']; // chars to skip

...which would also include periods, commas and parentheses there. Put whatever ones you need. You could also take the opposite approach and use a set to represent allowed characters, and say "if not (text[i] in allowedChars) then... deal with whitespace else deal with allowed letter".

There's probably a Windows message for this, though I don't know of it (anyone?).

The above function could be optimised using PChars (pointer-to-chars) and using some other tricks. That's left as an exercise :wink:

[EDIT: Oops! Off-by-one error there - the loop goes from 1 to length, not 0 to length-1!]

yawbird
23-11-2002, 08:23 PM
Thanks for the speedy reply Alimonster
thats great!! However I have another problem now I need to write the contents of this memo into a txt file. I've figured out how to open a txt file to the memo but saving seems to be tricky at the moment i can create a new file but the contents of the memo never appears in it. At the moment I'm attempting this by using a save dialog.

thanks again

Derek

{MSX}
23-11-2002, 08:39 PM
now I need to write the contents of this memo into a txt file.


memo1.lines.savetofile('memo.txt');


It's simple 8)

yawbird
27-11-2002, 06:35 PM
Hey again!!

I've been given an extension to this task. Basically I have to get the program to display the number of 1,2...,10 and >10 letter words. Once again I'm stuck and havent the faintest idea how to tackle this.

some code would be greatly appreciated

thanks

Derek

Alimonster
27-11-2002, 08:44 PM
The above code checks whether a char is part of a word - "if not (text[i ] in Whitespace) then..."

Each time that condition is true, you've found a word This means that you can change it to have a counter for the word length - you just have to figure out whether you're doing a *new* word (just started, first letter of it) or are continuing to see the current word.

"if not DoingWord" means that you've just hit a new word. if that's the case, you set the counter to 1 (first letter). Otherwise, you're still on the same word - add one to that counter.

You'd also want to set the counter to 0 if it *was whitespace*. Before that, you'd want to check the length of the counter. If 0, do nothing (no word was there). If 1..10 then add to the 1..10 bundle. Otherwise, put it in the greater than ten count. Example pseudocode, based on above:

[background=#FFFFFF][normal=#000080][number=#C00000]
[string=#00C000][comment=#8080FF][reserved=#000000]function ...
const
...
var
...
WordLength: Integer;
OneToTen: Integer;
OverTen: Integer;
begin
...

WordLength := 0;
OneToTen := 0;
OverTen := 0;

for ...
begin
if not (text[i ] in whitespace) then // *not* whitespace, = a valid word
begin
if not DoingWord then
begin
...
WordLength := 1; // start of new word
end
else
begin
Inc(WordLength); // continuing this word
end;
end
else // found whitespace
begin
// Not a word. If WordLength > 0 then
// we've recently been doing a word, but have found
// the end. Therefore, check its length and increase
// the appropriate count

if WordLength > 0 then
begin
if WordLength in [1..10] then
Inc(OneToTen)
else
Inc(OverTen);
end

DoingWord := False;
WordLength := 0;
end;
end;
end;
Gotta love string manipulation :mrgreen: