Amber
Amber

Reputation: 171

How to find and count a word in a text string?

The user needs to enter a sentence where the code should display the number of times the word "in" appears in the sentence. It should only count the word "in" and not words that contain "in".

Problem: My code only counts the word "in" one time when it appears, even if it appears more than one time.

Note: *We haven't started with arrays yet. *This code is delphi, please don't identify it as a duplicate to a question involving another programming language. *This is homework BUT it shouldn't be handed in, only I will ever see it(I take an online course).

What I've tried:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    redOut: TRichEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var sentence : string;
    WordCount : integer;
begin
    WordCount := 0;
    sentence := Inputbox ('Sentence input', 'Input a sentence (The word "in" will be counted','');
    if Pos('in',sentence) > 0 then

    WordCount := WordCount + 1;

    RedOut.Lines.Add('The number of times "in" appears in the sentence is ' + inttostr(WordCount) + ' time(s)');


end;

end.

Upvotes: 4

Views: 2588

Answers (2)

MartynA
MartynA

Reputation: 30735

One way to count the number of times one string occurs in another is shown below. The slightly tricky thing is to avoid counting 'in' when it's a substring of another string. The nested NextWord function takes care of that.

I'm not saying that it's the most efficient way to do it, but it does illustrate a few points about using Object Pascal for string manipulation.

If it's not obvious how it works, trace it under the debugger.

Btw, if you "haven't done arrays yet", I'm sure you'll be able to resist any temptation to hand it in as your homework, in case you get asked to explain it :=)

Btw, the code is for D7, which is what I've notivced that quite a lot of students here at SO use. If you are using D2009 or later you should replace CH in ['a'..'z', 'A'..'Z'] by a call to CharInSet which you'll maybe need to look up in the online help.

function WordCount(Target, Input : String; IgnoreCase : Boolean) : Integer;
var
  SP : Integer;
  TempStr : String;

  function IsLetter(CH : Char) : Boolean;
  begin
    Result := CH in ['a'..'z', 'A'..'Z'];
  end;

  function NextWord : String;
  begin
    Result := '';
    while (SP <= Length(Input)) and not (IsLetter(Input[SP])) do
      Inc(SP);

    while (SP <= Length(Input)) and IsLetter(Input[SP]) do begin
      Result := Result + Input[SP];
      Inc(SP);
    end;
  end;

begin
  Result := 0;
  if IgnoreCase then begin
    Target := LowerCase(Target);
    Input  := LowerCase(Input);
  end;

  SP := 1;
  repeat
    TempStr := NextWord;
    if TempStr = Target then
      inc(Result);
  until TempStr = '';
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Target : String;
  Input : String;
begin
  Target := 'In';
  Input := 'in outing in ';
  ShowMessageFmt('%s contains %d occurrences of %s', [Input, WordCount(Target, Input, True), Target]);

  Input := 'a';
  ShowMessageFmt('%s contains %d occurrences of %s', [Input, WordCount(Target, Input, True), Target]);
end;

Upvotes: 3

Tom Brunberg
Tom Brunberg

Reputation: 21045

Your current code counts only one occurance because you check the presence of the word only once.

Not to spoil your homework, I don't write the code for you but here's some food for thought:

You need to choose a useful loop statement in which you do your check repeatedly and increment the counter when the word is found. Delphi has three different loop statements: For counter := x to y do <statement block>, while condition=true do <statement block> and repeat <statement block> until condition=true. The docs describe these.

You also need to avoid counting the same position more than once. Pos() always searches from the beginning of the string. PosEx() allows you to specify an offset from where to search.

You need to consider what the difference is between a separate word "in", and those characters being contained. How can you rule out those contained from the count?

Define a set of strings for testing your program. Possible test strings that comes to mind are: "In", "Included in contain", "In the minimum interest whitin"

Upvotes: 3

Related Questions