Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to search a string with wildcards Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
30-Aug-02
Category
Algorithm
Language
Delphi All Versions
Views
33
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Tomas Rutkauskas

I have a body of text. I want to allow the user to enter a string that could 
contain wildcards (well, just the " * ") and search for it.

Answer:

Your first task is to split the paragraph into words (since i take it from your 
description that the match has to be inside a word). The next is to match each word 
to the mask. The following implementation is certainly not the fastest possible but 
it should make the algorithm clear.

1   
2   procedure SplitTextIntoWords(const S: string; words: TStringlist);
3   var
4     startpos, endpos: Integer;
5   begin
6     Assert(Assigned(words));
7     words.clear;
8     startpos := 1;
9     while startpos <= Length(S) do
10    begin
11      {skip non-letters }
12      while (startpos <= Length(S)) and not IsCharAlpha(S[startpos]) do
13        Inc(startpos);
14      if startpos <= Length(S) then
15      begin
16        {find next non-letter}
17        endpos := startpos + 1;
18        while (endpos <= Length(S)) and IsCharAlpha(S[endpos]) do
19          Inc(endpos);
20        words.add(Copy(S, startpos, endpos - startpos));
21        startpos := endpos + 1;
22      end;
23    end;
24  end;
25  
26  function StringMatchesMask(S, mask: string; case_sensitive: Boolean): Boolean;
27  var
28    sIndex, maskIndex: Integer;
29  begin
30    if not case_sensitive then
31    begin
32      S := AnsiUpperCase(S);
33      mask := AnsiUpperCase(mask);
34    end;
35    Result := True; {blatant optimism}
36    sIndex := 1;
37    maskIndex := 1;
38    while (sIndex <= Length(S)) and (maskIndex <= Length(mask)) do
39    begin
40      case mask[maskIndex] of
41        '?':
42          begin
43            {matches any character}
44            Inc(sIndex);
45            Inc(maskIndex);
46          end;
47        '*':
48          begin
49            {matches 0 or more characters, so need to check for next character in 
50  mask}
51            Inc(maskIndex);
52            if maskIndex > Length(mask) then
53              { * at end matches rest of string}
54              Exit
55            else if mask[maskindex] in ['*', '?'] then
56              raise Exception.Create('Invalid mask');
57            {look for mask character in S}
58            while (sIndex <= Length(S)) and (S[sIndex] <> mask[maskIndex]) do
59              Inc(sIndex);
60            if sIndex > Length(S) then
61            begin
62              {character not found, no match}
63              Result := false;
64              Exit;
65            end;
66          end;
67      else
68        if S[sIndex] = mask[maskIndex] then
69        begin
70          Inc(sIndex);
71          Inc(maskIndex);
72        end
73        else
74        begin
75          {no match}
76          Result := False;
77          Exit;
78        end;
79      end;
80    end;
81    {if we have reached the end of both S and mask we have a complete match,
82    otherwise we only have a partial match}
83    if (sIndex <= Length(S)) or (maskIndex <= Length(mask)) then
84      Result := false;
85  end;
86  
87  procedure FindMatchingWords(const S, mask: string; case_sensitive: Boolean;
88    matches: TStringlist);
89  var
90    words: TStringlist;
91    i: Integer;
92  begin
93    Assert(Assigned(matches));
94    words := TStringlist.Create;
95    try
96      SplitTextIntoWords(S, words);
97      matches.clear;
98      for i := 0 to words.count - 1 do
99      begin
100       if StringMatchesMask(words[i], mask, case_sensitive) then
101         matches.Add(words[i]);
102     end;
103   finally
104     words.free;
105   end;
106 end;
107 
108 {Form has one memo for the text to check, one edit for the mask, one checkbox
109 (check = case sensitive), one listbox for the results, one button }
110 
111 procedure TForm1.Button1Click(Sender: TObject);
112 begin
113   FindMatchingWords(memo1.text, edit1.text, checkbox1.checked, listbox1.items);
114 end;


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC