Boyer-Moore-Horspool text searching #41
function search(pat: string; text: string): integer; var i, j, k, m, n: integer; skip: array [0..MAXCHAR] of integer; found: boolean; begin found := FALSE; search := 0; m := length(pat); if m=0 then begin search := 1; found := TRUE; end; for k:=0 to MAXCHAR do skip[k] := m; {*** Preprocessing ***} for k:= m-1 downto 1 do skip[ord(pat[k])] := m-k; k := m; n := length(text); {*** Search ***} while not found and (k <= n) do begin i := k; j := m; while (j >= 1) do begin if text[i] <> pat[j] then j := -1 else begin j := j-1; i := i-1; end; if j = 0 then begin search := i+1; found := TRUE; end; k := k + skip[ord(text[k])]; end; end; end;
Demo code
A ready made project containing this demo code is available. View the project.
This demo will use the search function provided in this tip to search a memo control for text entered in an edit control.
Create a new Delphi VCL application and proceed as follows:
- Drop a TMemo on the form and set its HideSelection property to False and its ScrollBars property to ssVertical. You can also enter some text in the memo's Lines property.
- Drop a TEdit and a TButton on the form.
- Create an OnClick event handler for the button.
-
Name the form "Form1" and save the form unit as
Unit1.pas
.
Now code Unit1 as below:
unit Unit1; interface uses Windows, Forms, Dialogs, StdCtrls, Classes, Controls; type TForm1 = class(TForm) Memo1: TMemo; Edit1: TEdit; Button1: TButton; procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} function search(pat: string; text: string): integer; var i, j, k, m, n: integer; skip: array [0..MAXCHAR] of integer; found: boolean; begin found := FALSE; search := 0; m := length(pat); if m=0 then begin search := 1; found := TRUE; end; for k:=0 to MAXCHAR do skip[k] := m; {*** Preprocessing ***} for k:= m-1 downto 1 do skip[ord(pat[k])] := m-k; k := m; n := length(text); {*** Search ***} while not found and (k <= n) do begin i := k; j := m; while (j >= 1) do begin if text[i] <> pat[j] then j := -1 else begin j := j-1; i := i-1; end; if j = 0 then begin search := i+1; found := TRUE; end; k := k + skip[ord(text[k])]; end; end; end; procedure TForm1.Button1Click(Sender: TObject); var FoundIdx: Integer; begin // search() returns 0 if the text isn't found or the index of the // start of the string if the text is found FoundIdx := search(Edit1.Text, Memo1.Text); if FoundIdx > 0 then begin // Found text: highlight it in memo (TMemo.HideSelection must be // false for this to work). Since memo selections are 0 based, we // subtract 1 from the found index, which is 1 based. Memo1.SelStart := FoundIdx - 1; Memo1.SelLength := Length(Edit1.Text); end else ShowMessage('Text not found'); end; end.
Run the application. Enter some text in the memo if you didn't do this at design time. Now enter some search text in the edit control and click the button. If the text is found it will be highlighted in the memo control. A message will be displayed if the text is not found. Note that the search is case sensitive.
Demo code by Peter Johnson
Author: | Unknown |
---|---|
Added: | 2007/06/11 |
Last updated: | 2010/03/16 |