Board index » delphi » How to search for a string within another string

How to search for a string within another string

Hi

How can I search for a string within another string. I have a comma
delimited file containing lines of text in the following format, this
is created by another program, one line for each user.

User1,name,house,car,plane,boat
User2,plane,boat
User3,car,house
User4,car,plane,boat,name

I would like to be able to check which "name house car plane boat" has
been selected.

Note: The entries are not always in the same order

Many thanks for your help
Andy

 

Re:How to search for a string within another string


Quote
"Andy" <m...@andyhemmings.com> wrote in message

news:aeba6f2c.0303112325.68f75813@posting.google.com...

Quote
> Hi

> How can I search for a string within another string. I have a comma
> delimited file containing lines of text in the following format, this
> is created by another program, one line for each user.

> User1,name,house,car,plane,boat
> User2,plane,boat
> User3,car,house
> User4,car,plane,boat,name

> I would like to be able to check which "name house car plane boat" has
> been selected.

> Note: The entries are not always in the same order

> Many thanks for your help
> Andy

k:=pos(string1,string2)
// k will return index of first occurrence of string 1 in string2 or zero if
absent
// eg pos(',','name,house') will return 5

to search for second occurrence you need to remove first occurrence, eg

repeat
  k:=pos(',',myString);
  // do somthing with this knowledge
  myString:=copy(myString,k+1,maxInt)
until k=0;

Re:How to search for a string within another string


"Andy" <m...@andyhemmings.com> skrev i melding
news:aeba6f2c.0303112325.68f75813@posting.google.com...

Quote
> Hi

> How can I search for a string within another string. I have a comma
> delimited file containing lines of text in the following format, this
> is created by another program, one line for each user.

> User1,name,house,car,plane,boat
> User2,plane,boat
> User3,car,house
> User4,car,plane,boat,name

> I would like to be able to check which "name house car plane boat" has
> been selected.

> Note: The entries are not always in the same order

The "quick'n dirty way":

// Selection = 'User1,name,house,car,plane,boat';
// To have commas before and after all words:
TmpSelection:=Selection+',';

chName.Checked:=Pos(',name,', TmpSelection);
chBoat.Checked:=Pos(',boat,', TmpSelection);

...etc...

--
Regards,

Bj?rge S?ther
bjorge@haha_itte.no

Re:How to search for a string within another string


Quote
"Andy" <m...@andyhemmings.com> wrote in message

news:aeba6f2c.0303112325.68f75813@posting.google.com...

Quote
> Hi

> How can I search for a string within another string. I have a comma
> delimited file containing lines of text in the following format, this
> is created by another program, one line for each user.

> User1,name,house,car,plane,boat
> User2,plane,boat
> User3,car,house
> User4,car,plane,boat,name

> I would like to be able to check which "name house car plane boat" has
> been selected.

> Note: The entries are not always in the same order

I'm trying to figure out what it is you are asking. In the subject line you
indicate that you are looking for a method to locate a sub-string within
another string. Yet your outline indicates that you may be doing a text file
scan. But then you say that you want to find which ??? has been "selected".
Perhaps you could actually pose a question, i.e. an interrogative sentence
that ends with ?. (Instead of a general question, you might get more helpful
responses if you provide details and get very specific.)

Re:How to search for a string within another string


Quote
> I'm trying to figure out what it is you are asking. In the subject line you
> indicate that you are looking for a method to locate a sub-string within
> another string. Yet your outline indicates that you may be doing a text file
> scan. But then you say that you want to find which ??? has been "selected".
> Perhaps you could actually pose a question, i.e. an interrogative sentence
> that ends with ?. (Instead of a general question, you might get more helpful
> responses if you provide details and get very specific.)

Hi

Sorry for not being clear, I am very new to delphi / pascal and have
confused
things. However, I would like to be able to search each line and find
out if a user has a house, boat, car ect, and display the results.

eg if 'car' is found then 'Ford Focus' is outputted to screen
   if 'plane' is found then 'Boeing' is the output

User1,name,house,car,plane,boat

Thanks
Andy

Re:How to search for a string within another string


 S := 'User1,name,house,car,plane,boat' + ',' ;

If Pos( ',plane,' , S ) Then

However, you may wish to pre-digest the data :-

unit Unit1;

// String to Array - 12/03/03 JF

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.DFM}

// SetLength requires a definitely typed Array
Type TStrArray = Array Of String;

Procedure StrBreak( Const Src:String; Const BreakChar:Char; Var
Ar:TStrArray) ;
Var
  L9, StartPos, Count:Integer;
  // Utility
  Procedure BumpCount;
  Begin
    If Count > High( Ar ) Then
       SetLength( Ar, High(Ar) + 100 );
    Count := Count + 1;
  End;
Begin
  Count := 0;

  StartPos := 1;
  For L9 := 1 To Length( Src ) Do
      If Src[L9] = BreakChar Then
         Begin
           BumpCount;
           Ar[Count-1] := Copy( Src, StartPos, L9 - StartPos );
           StartPos := L9 + 1;
         End;
  // handle anything like 'A,bbb'<EOS> or just 'aaa'
  If Length( Src ) > 0 Then
     Begin
       BumpCount;
       Ar[Count-1] := Copy( Src, StartPos, Length(Src) + 1 - StartPos
);
     End;
  // Adjust Array
  SetLength( Ar, Count );

End;

procedure TForm1.Button1Click(Sender: TObject);
Var
  Ar :TStrArray;
  L9 :Integer;
  S :String;
begin
  Ar := Nil;
  StrBreak( Edit1.Text, ',', Ar );
  S := '';
  For L9 := Low( Ar ) To High( Ar ) Do
      S := S + IntToStr(L9)+ ':' + Ar[L9] + #13;
  ShowMessage( S );
end;

end.

On 12 Mar 2003 22:52:01 -0800, m...@andyhemmings.com (Andy) wrote:

Quote
>> I'm trying to figure out what it is you are asking. In the subject line you
>> indicate that you are looking for a method to locate a sub-string within
>> another string. Yet your outline indicates that you may be doing a text file
>> scan. But then you say that you want to find which ??? has been "selected".
>> Perhaps you could actually pose a question, i.e. an interrogative sentence
>> that ends with ?. (Instead of a general question, you might get more helpful
>> responses if you provide details and get very specific.)

>Hi

>Sorry for not being clear, I am very new to delphi / pascal and have
>confused
>things. However, I would like to be able to search each line and find
>out if a user has a house, boat, car ect, and display the results.

>eg if 'car' is found then 'Ford Focus' is outputted to screen
>   if 'plane' is found then 'Boeing' is the output

>User1,name,house,car,plane,boat

>Thanks
>Andy

Re:How to search for a string within another string


In other words, you want for each line to extract
what is listed between the n'th and the n+1'th comma (if anything) ?

If so
   p:=pos(',',MainString);
  ExtractString:=copy(MainString,1,p-1); //1st entry
     Store ExtractString in ?? (house, car, dog, cat, birdie or whatever is first
:-)

  for the following
  TempString:=MainString;  //Do not do any changes to input string !!
                                          //You might want it untouched for later
use.

  **** Repeat code below once for each of the next entries in the

  TempString:=copy(TempString, p+1, "A big enough integer");
   p:=pos(',',TempString);
  ExtractString:=copy(TempString,1,p-1);
     Store ExtractString in ?? (house, car, dog, cat, birdie or whatever is next
:-)

  |
  |

For the last entry you will most likely not need to search for the next comma.

  ExtractString:=copy(TempString, p+1, "A big enough integer");
     Store ExtractString in ?? (house, car, dog, cat, birdie or whatever is last
:-)

Quote
Andy wrote:
> Hi

> Sorry for not being clear, I am very new to delphi / pascal and have
> confused
> things. However, I would like to be able to search each line and find
> out if a user has a house, boat, car ect, and display the results.

> eg if 'car' is found then 'Ford Focus' is outputted to screen
>    if 'plane' is found then 'Boeing' is the output

> User1,name,house,car,plane,boat

> Thanks
> Andy

Re:How to search for a string within another string


Quote
> Sorry for not being clear, I am very new to delphi / pascal and have
> confused
> things. However, I would like to be able to search each line and find
> out if a user has a house, boat, car ect, and display the results.

> eg if 'car' is found then 'Ford Focus' is outputted to screen
>    if 'plane' is found then 'Boeing' is the output

> User1,name,house,car,plane,boat

So, your input lines would look like:
'U1,Andy,bungalow,Ford,,rowboat'
'U8,Tom,flat,Alfa Romeo,pipercup,,'

I.e. empty strings between comma's if one has no boat, house, etc.

Then process as follows:

while NOT EOF(sourceFile) do
begin readln(line);
        k:=pos(',',line); user:=copy(line,1,k-1);
line:=copy(line,k+1,maxInt);
        k:=pos(',',line); name:=copy(line,1,k-1);
line:=copy(line,k+1,maxInt);
        k:=pos(',',line); house:=copy(line,1,k-1);
line:=copy(line,k+1,maxInt);
        k:=pos(',',line); car:=copy(line,1,k-1);
line:=copy(line,k+1,maxInt);
        k:=pos(',',line); plane:=copy(line,1,k-1);
line:=copy(line,k+1,maxInt);
        boat:=line;
end;

Re:How to search for a string within another string


On 12 Mar 2003 22:52:01 -0800, m...@andyhemmings.com (Andy) wrote:

Quote
>eg if 'car' is found then 'Ford Focus' is outputted to screen
>   if 'plane' is found then 'Boeing' is the output

>User1,name,house,car,plane,boat

You could also try a text based database.  Check www.mylittlebase.org, they have a freeware one that
works pretty nicely.

Andy
The Perpetual Novice Programmer

Re:How to search for a string within another string


On Thu, 13 Mar 2003 12:07:17 +0100, "Tom de Neef" <tden...@qolor.nl>
wrote:

Quote
>> Sorry for not being clear, I am very new to delphi / pascal and have
>> confused
>> things. However, I would like to be able to search each line and find
>> out if a user has a house, boat, car ect, and display the results.

>> eg if 'car' is found then 'Ford Focus' is outputted to screen
>>    if 'plane' is found then 'Boeing' is the output

>> User1,name,house,car,plane,boat

>So, your input lines would look like:
>'U1,Andy,bungalow,Ford,,rowboat'
>'U8,Tom,flat,Alfa Romeo,pipercup,,'

>I.e. empty strings between comma's if one has no boat, house, etc.

Hmm, perhaps this will help, it gets the Nth item from a delineated
string
- I really must tart it up and get rid of Pos()

{ ########################################################

Quote
}

Function StrExtStr( Const HSrc: String; Const Delim: String;
                    Const Count: Integer ) : String ;
  Var
  S : Integer ;
  E : Integer ;
  L9 : Integer ;
  Src : String ;
  Begin

  Src := HSrc + Delim ;
  S := 1 ;
  For L9 := 1 To Count - 1 Do
      Begin
      S := Pos( Delim, Src );                 { S = Instr( Src$, ',' }
      IF S > 0 Then
         Delete( Src, S, Length( Delim ) )    {delete all before}
         else
         Break ;
  End ;

  Result := '' ;
  If S > 0 Then
     Begin
     E := Pos( Delim, Src + Delim ) ;
     Result := Copy( Src, S, E - S ) ;
  End;

End; {StrExtStr}

Re:How to search for a string within another string


Quote
> Hmm, perhaps this will help, it gets the Nth item from a delineated
> string
> - I really must tart it up and get rid of Pos()

I find POS extremely fast, much faster then array wise character handling of
the string. It's a petty there isn't a POSn to find the n-th occurrence.

Re:How to search for a string within another string


"Tom de Neef" <tden...@qolor.nl> wrote in message
news:3e70670a$0$49098$e4fe514c@news.xs4all.nl...

Quote
> > Sorry for not being clear, I am very new to delphi / pascal and have
> > confused
> > things. However, I would like to be able to search each line and find
> > out if a user has a house, boat, car ect, and display the results.

> > eg if 'car' is found then 'Ford Focus' is outputted to screen
> >    if 'plane' is found then 'Boeing' is the output

> > User1,name,house,car,plane,boat

> So, your input lines would look like:
> 'U1,Andy,bungalow,Ford,,rowboat'
> 'U8,Tom,flat,Alfa Romeo,pipercup,,'

> I.e. empty strings between comma's if one has no boat, house, etc.

> Then process as follows:

An alternativie is (presuming no embedded spaces) - untested :)

function ReturnNthField (const s : string; index : integer) : string;

var sl : tStringList;

begin
sl := tStringList.Create;
try
    sl.CommaText := s;
    result := sl [index];
finally
    sl.Free;
    end;
end;

If one has to cope with embedded spaces then

function ReturnNthField (const s : string; index : integer) : string;

var i, j, lth : integer;

begin
i := 1;
lth := Length (s);
while (index > 0) do
    begin
    while (i <= lth) and (s [i] <> ',') do
        inc (i);
    dec (index);
    inc (i);
    end;
if ((lth > 0) and (s [i] = ',')) or (index <> 0)
then result := ''
else begin
    j := succ (i);
    while (j <= lth) and (s [j] <> ',') do
        inc (j);
    result := copy (s, i, j - i);
    end;
end;

Re:How to search for a string within another string


On Thu, 13 Mar 2003 18:50:11 +0100, "Tom de Neef" <tden...@qolor.nl>
wrote:

Quote
>> Hmm, perhaps this will help, it gets the Nth item from a delineated
>> string
>> - I really must tart it up and get rid of Pos()

>I find POS extremely fast, much faster then array wise character handling of
>the string. It's a petty there isn't a POSn to find the n-th occurrence.

I am surprized that you find it that fast
- ironically code written in pure Delphi generally runs faster than
the libraries
- look what I found in _Pos in System.pas
           REPNE   SCASB
- elegant, terse but totally obvious
- just much less efficient than 'noddy' ASM which since the .486 is
significantly faster due to the RISC branching
- of course the Delphi compiler knows this
- it is just that the library writers 'forgot' about it

Actually my hunch is that they wrote elegant code with a view to
macro-izing it, but somebody pointed out that a Macro in an ASM block
would open up Macros to us devious coders

Just for the hell of it, here is my implementation of InStr() which is
IMNVHO what Pos() should really do

POSn becomes pretty easy from it

More follows

{#########################################################

 Result := InStr( 2, 'ABCDEF', 'BCD' )  rev: 20/6/02 JF

Quote
}

Function InStr( Start:Integer; Const BigStr,SmallStr:String):Integer;
  Var
  L9, L8, Max, P: Integer;
  BigL, SmallL: Integer;
  C : Char;
  Begin
  Result := 0; // Set Default

  // Should be illegal
  If Start <= 0 Then
     Start := 1;

  // Take String Lengths
  BigL := Length( BigStr );
  SmallL := Length( SmallStr );

  // '' Target always returns 0
  If BigL = 0 Then
     Exit;

  // '' Convention returns Start
  If SmallL = 0 Then
     Begin
       Result := Start;
       Exit;
     End;

  // Find last possible Start pos
  Max := BigL - SmallL + 1;
  If Max < Start Then
     Exit;

  // Take First Char of Search String
  C := SmallStr[1];

  // Hunt Forwards for a match
  For L9 := Start To Max Do
      If BigStr[L9] = C Then  // If first Char Found
         Begin
           P := L9 + SmallL - 1;
           For L8 := SmallL DownTo 2 Do // Scan Backwards
               Begin
                 If BigStr[P] <> SmallStr[L8] Then
                    Break;
                 P := P - 1;
               End;
           // Success - we know first Char matches
           If P = L9 Then
              Begin
                Result := L9;
                Break;
              End;
         End;

End;{InStr}

Realistically I could make it faster in ASM, but because of the .486
stuff the code would be horrible.
- this is sad, and somewhat ironic
- because I only used Delphi in the first place as a method of writing
ASM under Winders ... and then got intrigued

Re:How to search for a string within another string


Quote

> {#########################################################

>  Result := InStr( 2, 'ABCDEF', 'BCD' )  rev: 20/6/02 JF
> }
> Function InStr( Start:Integer; Const BigStr,SmallStr:String):Integer;
>   Var
>   L9, L8, Max, P: Integer;
>   BigL, SmallL: Integer;
>   C : Char;
>   Begin
>   Result := 0; // Set Default

>   // Should be illegal
>   If Start <= 0 Then
>      Start := 1;

>   // Take String Lengths
>   BigL := Length( BigStr );
>   SmallL := Length( SmallStr );

>   // '' Target always returns 0
>   If BigL = 0 Then
>      Exit;

>   // '' Convention returns Start
>   If SmallL = 0 Then
>      Begin
>        Result := Start;
>        Exit;
>      End;

>   // Find last possible Start pos
>   Max := BigL - SmallL + 1;
>   If Max < Start Then
>      Exit;

>   // Take First Char of Search String
>   C := SmallStr[1];

>   // Hunt Forwards for a match
>   For L9 := Start To Max Do
>       If BigStr[L9] = C Then  // If first Char Found
>          Begin
>            P := L9 + SmallL - 1;
>            For L8 := SmallL DownTo 2 Do // Scan Backwards
>                Begin
>                  If BigStr[P] <> SmallStr[L8] Then
>                     Break;
>                  P := P - 1;
>                End;
>            // Success - we know first Char matches
>            If P = L9 Then
>               Begin
>                 Result := L9;
>                 Break;
>               End;
>          End;

> End;{InStr}

This is indeed a good start. But it could be better. And I expect that POS
implements that improvement, but haven't checked. The idea in forward
stringmatching is that you do not continue with the next char if you can
deduce that it can not lead to a match anyway. Eg if 'ABCD' doesn't match at
the position where the string reads 'ABCEF..' then skip 3 chars instead of
1. This requires building a small table at the start of your function to
determine the overlaps in SmallStr.

Re:How to search for a string within another string


On Thu, 13 Mar 2003 23:58:57 +0100, "Tom de Neef" <tden...@qolor.nl>
wrote:

<snip>

Quote
>This is indeed a good start. But it could be better. And I expect that POS
>implements that improvement, but haven't checked. The idea in forward
>stringmatching is that you do not continue with the next char if you can
>deduce that it can not lead to a match anyway. Eg if 'ABCD' doesn't match at
>the position where the string reads 'ABCEF..' then skip 3 chars instead of
>1. This requires building a small table at the start of your function to
>determine the overlaps in SmallStr.

Yes, I know the method (just can't remember the name rigth now),
basically you mark a table of 0-255 with whether or not each byte is
in the search string

Then you look at the last byte etc.

I am not convinced that it would make that much difference in 'normal'
strings, since there is some overhead in generating the table.

POS certainly does not do anything of the sort
- I had a poke around it earlier, as I often do, just to refresh my
memory of how neat but slow code works.

I'm tempted to suggest that you have a touching belief that the
Library Programmers are super-human.

I shall of course refrain from suggesting otherwise ...

Go to page: [1] [2]

Other Threads