SRL Archive - SRL Archives

NextPos


Ron

2008-07-29 16:47:54

Hoorah! This is a sweet function if anyone is into parsing strings/text or for anyone who is sick of the lack of functionality with the pos function.

Function code:

// Will find the next position of a substr inside a str, after X
// number of substrs. OR set AfterFirst to -1 to find the last pos.
// Made by Ron :)
function NextPos(Substr, Str : String; AfterFirst : Integer) : Integer;
var
i, Pos1, TotalPos : Integer;
begin
Pos1 := 0;
i := -1;
repeat
inc(i);
Pos1 := Pos(Substr, Str);
if (Pos1 = 0) then
Break;
Str := Copy(Str, Pos1 + 1, Length(Str));
TotalPos := TotalPos + Pos1;
WriteLn(IntToStr(TotalPos));
until (i >= AfterFirst) and (AfterFirst > -1);
Result := TotalPos;
end;

Test function:

program NextPosFunctionTestByRon;

const
Substr = 'holy';
Str = 'Have you read the holy book? Holy shit! No not the holy bible! The holy hotties book.';
AfterFirst = 1;
CaseSens = False;

// Will find the next position of a substr inside a str, after X
// number of substrs. OR set AfterFirst to -1 to find the last pos.
// Made by Ron :)
function NextPos(Substr, Str : String; AfterFirst : Integer; CaseSens : Boolean) : Integer;
var
i, Pos1, TotalPos : Integer;
begin
if not(CaseSens) then
begin
Substr := Lowercase(Substr);
Str := Lowercase(Str);
end;
Pos1 := 0;
i := -1;
repeat
inc(i);
Pos1 := Pos(Substr, Str);
if (Pos1 = 0) then
Break;
Str := Copy(Str, Pos1 + 1, Length(Str));
TotalPos := TotalPos + Pos1;
WriteLn(IntToStr(TotalPos));
until (i >= AfterFirst) and (AfterFirst > -1);
Result := TotalPos;
end;

begin
ClearDebug;
WriteLn(IntToStr(NextPos(Substr, Str, AfterFirst, CaseSens)));
end.

~Ron

mastaraymond

2008-07-29 17:41:38

PosEx ?

bullzeye95

2008-07-29 17:44:19

Nice idea. Although there is a function called "PosEx", which is just like Pos, but it finds it after an inputted position. I remade your function to show you. (Sorry :p)
function NextPos(Substr, Str : String; AfterFirst : Integer; CaseSens : Boolean) : Integer;
var
I: Integer;
begin
if(not(CaseSens))then
begin
SubStr:= Lowercase(SubStr);
Str:= Lowercase(Str);
end;
if(AfterFirst = -1)then
Result:= LastPos(SubStr, Str)
else
for I:= 0 to AfterFirst do
Result:= PosEx(SubStr, Str, Result + 1);
end;
EDIT: Beat by Ray…

Ron

2008-07-29 18:13:18

Ahh I see. I haven't been using SCAR in a while. Looks like I should read up some of the new functions. :)

Thanks for the helpful comment Bullzeye.

Ron

2008-07-29 18:43:22

This is interesting… Turns out Freddy's function has a bug. Unless I'm using the function incorrectly.

Here is the code.

program New;

const
Test = 'if (TextBetw(DFM[i], ''ob''''ject '', '''''''', True) = -1) then';

// Will find the next position of a substr inside a str, after X
// number of substrs. OR set AfterFirst to -1 to find the last pos.
// Made by Ron :)
function NextPos(Substr, Str : String; AfterFirst : Integer; CaseSens : Boolean) : Integer;
var
i, Pos1, TotalPos : Integer;
begin
if not(CaseSens) then
begin
Substr := Lowercase(Substr);
Str := Lowercase(Str);
end;
Pos1 := 0;
i := -1;
repeat
inc(i);
Pos1 := Pos(Substr, Str);
if (Pos1 = 0) then
Break;
Str := Copy(Str, Pos1 + 1, Length(Str));
TotalPos := TotalPos + Pos1;
until (i >= AfterFirst) and (AfterFirst > -1);
Result := TotalPos;
end;

var
pos1, pos2, i : Integer;
Text : String;

begin
ClearDebug;

{********** CODE WORKS ***********}
Text := Test;
pos1 := NextPos(#39, Text, 0, True);
pos2 := NextPos(#39, Text, 1, True);
i := 2;
while (Text[pos2 + 1] = #39) or (Text[pos2 - 1] = #39) do
begin
pos2 := NextPos(#39, Text, i, True);
inc(i);
end;
WriteLn('"' + Copy(Text, pos1 + 1, pos2 - pos1 - 1) + '"');

{*********** CODE DOES NOT WORK ***********}
Text := Test;
pos1 := PosEx(#39, Text, 0);
pos2 := PosEx(#39, Text, 1);
i := 2;
while (Text[pos2 + 1] = #39) or (Text[pos2 - 1] = #39) do
begin
pos2 := PosEx(#39, Text, i);
inc(i);
end;
WriteLn('"' + Copy(Text, pos1 + 1, pos2 - pos1) + '"');
end.

~Ron

mastaraymond

2008-07-29 18:48:14

From: Ron
This is interesting… Turns out Freddy's function has a bug. Unless I'm using the function incorrectly.

Here is the code.

program New;

const
Test = 'if (TextBetw(DFM[i], ''ob''''ject '', '''''''', True) = -1) then';

// Will find the next position of a substr inside a str, after X
// number of substrs. OR set AfterFirst to -1 to find the last pos.
// Made by Ron :)
function NextPos(Substr, Str : String; AfterFirst : Integer; CaseSens : Boolean) : Integer;
var
i, Pos1, TotalPos : Integer;
begin
if not(CaseSens) then
begin
Substr := Lowercase(Substr);
Str := Lowercase(Str);
end;
Pos1 := 0;
i := -1;
repeat
inc(i);
Pos1 := Pos(Substr, Str);
if (Pos1 = 0) then
Break;
Str := Copy(Str, Pos1 + 1, Length(Str));
TotalPos := TotalPos + Pos1;
until (i >= AfterFirst) and (AfterFirst > -1);
Result := TotalPos;
end;

var
pos1, pos2, i : Integer;
Text : String;

begin
ClearDebug;

{********** CODE WORKS ***********}
Text := Test;
pos1 := NextPos(#39, Text, 0, True);
pos2 := NextPos(#39, Text, 1, True);
i := 2;
while (Text[pos2 + 1] = #39) or (Text[pos2 - 1] = #39) do
begin
pos2 := NextPos(#39, Text, i, True);
inc(i);
end;
WriteLn('"' + Copy(Text, pos1 + 1, pos2 - pos1 - 1) + '"');

{*********** CODE DOES NOT WORK ***********}
Text := Test;
pos1 := PosEx(#39, Text, 0);
pos2 := PosEx(#39, Text, 1);
i := 2;
while (Text[pos2 + 1] = #39) or (Text[pos2 - 1] = #39) do
begin
pos2 := PosEx(#39, Text, i);
inc(i);
end;
WriteLn('"' + Copy(Text, pos1 + 1, pos2 - pos1) + '"');
end.

~Ron

PosEx search from the 3d parameter you have given.. So you should put in "pos2 := PosEx(#39,Text,pos1 +1)".. (Not sure about the +1, try it).

Ron

2008-07-29 19:07:46

Ahh I see now. The from parameter is not the same as the one in the function I made. I kept thinking it was, that's why it wasn't working.

My parameter goes from the first item found, to the next time it was found, whereas the other one searches from the index of the string.

Anyway, here is the working code.

{*********** CODE NOW WORKS ***********}
Text := Test;
pos1 := PosEx(#39, Text, 1);
pos2 := PosEx(#39, Text, pos1 + 1);
i := 1;
while (Text[pos2 + 1] = #39) or (Text[pos2 - 1] = #39) do
begin
pos2 := PosEx(#39, Text, pos1 + i);
WriteLn(IntToStr(pos2));
inc(i);
end;
WriteLn('"' + Copy(Text, pos1 + 1, pos2 - pos1 - 1) + '"');

Freddy1990

2008-07-30 05:07:03

Well, newbiehacker wrote PosEx and several other string functions, it's possible they have bugs, but aside from 1 function so far they've all worked fine….

nielsie95

2008-07-30 05:23:15

Why don't you use the Delphi version?

Freddy1990

2008-07-30 05:52:01

Because I assumed nbh had checked if it already existed in delphi before telling me to add them… Well, I'll do that then…

Ron

2008-07-30 17:35:13

no no no freddy, it didn't have a bug. I was using it exactly like my function. And both of the functions are similar, but the find parameter in PosEx and the parameter AfterFirst in my function are different. But I was using them the same. :)

Freddy1990

2008-07-30 18:44:31

I don't say it has a bug… One of nbh's sting functions had a bug a while ago, but that's been sorted out for some time