Recent

Author Topic: Delete-Insert Logic escapes me!  (Read 3519 times)

J-G

  • Hero Member
  • *****
  • Posts: 953
Delete-Insert Logic escapes me!
« on: September 21, 2017, 03:18:19 pm »
Processing a string which contains asterisks (*) (#42) which I want to replace with a space (#32) my code goes into an infinite loop.

The string is a buffer and in this case starts at '*Processor **' and after going through the procedure :

Code: Pascal  [Select][+][-]
  1. procedure ReplaceAst;
  2. Var
  3.   p : word;
  4. begin
  5.   p:=1;
  6.   while p>0 do
  7.     begin
  8.       p:=pos('*',buffer);
  9.       if p>0 then
  10.         begin
  11.           Delete(Buffer,p,1);
  12.           Insert(' ',buffer,p);
  13.         end;
  14.     end;
  15. end;
  16.  

... ought to become ' Processor  ' but what actually happens is that after the asterisks have been replaced, 'p' continues to return 3 and the buffer vacillates between ' Processor  ' and ' P ocessor  ',  which still returns p=3 even though there are now no asterisks in the string and the character at 3 is #114  (r)   :o %)

I've also tried with the 'Delete' and 'Insert' reversed (with p+1 as the delete position) but still get the same result.

Anyone any idea why ?

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

fred

  • Full Member
  • ***
  • Posts: 201
Re: Delete-Insert Logic escapes me!
« Reply #1 on: September 21, 2017, 04:18:15 pm »
No idea why yet, buffer is a string?
You could use (strutils) ReplaceStr or (sysutils) StringReplace.
Code: Pascal  [Select][+][-]
  1. buffer := ReplaceStr(buffer, '*', ' ');

rvk

  • Hero Member
  • *****
  • Posts: 6056
Re: Delete-Insert Logic escapes me!
« Reply #2 on: September 21, 2017, 04:30:50 pm »
Your code works perfectly here so there must be something else in your code messing it up (a different insert procedure or buffer isn't a string).

Although I would do it like this:
Code: Pascal  [Select][+][-]
  1.   p := pos('*', buffer);
  2.   while p > 0 do
  3.   begin
  4.     Delete(Buffer, p, 1);
  5.     Insert(' ', buffer, p);
  6.     p := pos('*', buffer);
  7.   end;
or with a repeat loop
Code: Pascal  [Select][+][-]
  1.   repeat
  2.     p := pos('*', buffer);
  3.     if p > 0 then
  4.     begin
  5.       Delete(Buffer, p, 1);
  6.       Insert(' ', buffer, p);
  7.     end;
  8.   until p = 0;

But of course freds suggestion to use ReplaceStr or StringReplace is better.

ReplaceStr eventually uses StringReplace internally so you can also just call that directly.
Code: Pascal  [Select][+][-]
  1.   buffer := StringReplace(buffer, '*', ' ', [rfReplaceAll]);

wp

  • Hero Member
  • *****
  • Posts: 11831
Re: Delete-Insert Logic escapes me!
« Reply #3 on: September 21, 2017, 04:52:18 pm »
If you want to replace the '*' by a single character a simple "for" loop might be more efficient than the sequence of Delete/Insert and probably even ReplaceStr:

Code: Pascal  [Select][+][-]
  1. var
  2.   i: Integer;
  3. begin
  4.   for i:=1 to Length(Buffer) do
  5.     if Buffer[i] = '*' then Buffer[i] := ' ';
  6. end;

J-G

  • Hero Member
  • *****
  • Posts: 953
Re: Delete-Insert Logic escapes me!
« Reply #4 on: September 21, 2017, 05:08:15 pm »
Thanks Fred/RVK  -  my mind is still stuck in the realms of Turbo Pascal :(   so I haven't fully investigated SysUtils and this project was going to be a 'ten minute' job about 3 hours ago!!

Yes 'Buffer' is a string - rather than a short string - I haven't done much string handling where the length is greater than 255 and this was one of the reasons for the project.

I have found a reason for the error - and as RVK suggests it is something else in the code. There are a number of search and replace routines and one of them involved a semicolon which I mistakenly thought would always be present after an ampersand and when it wasn't, the further processing made the buffer length 'infinite' --- well certainly greater than 'word' --- which totally confused the 'pos' function by 'wrapping' the pos when > 65535!

Now StringReplace and ReplaceStr have been brought to my attention I'll look at them  - - -  though WPs suggestion (thanks) might be better  - - -  I'll see which is the quickest.

« Last Edit: September 22, 2017, 10:12:43 am by J-G »
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: Delete-Insert Logic escapes me!
« Reply #5 on: September 21, 2017, 05:16:14 pm »
A For loop ist definitely faster than Delete and/or Insert, but if you really need some speed then check out this post...

Search: LazForum:
Best way to clean large text files: Reply #4 (himitsu StrReplace) = Really F A S T   !!!
Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

Thaddy

  • Hero Member
  • *****
  • Posts: 14169
  • Probably until I exterminate Putin.
Re: Delete-Insert Logic escapes me!
« Reply #6 on: September 21, 2017, 05:19:01 pm »
Note you can also do (AnsiString assumed):
Code: Pascal  [Select][+][-]
  1. program program1;
  2. {$ifdef fpc}{$mode delphi}{$H+}{$endif}
  3. uses sysutils;
  4. var buffer:string = '*blaat*;*,blaat,blaat blaat*,bl*at';
  5. begin
  6.  writeln(buffer.replace('*',' ',[rfReplaceAll]));
  7. end.

Uses the new typehelpers for string... fast enough..It does only delete when necessary ('') else it replaces. It is usually fast enough even on long strings or stringlists.text  :D
« Last Edit: September 21, 2017, 05:30:55 pm by Thaddy »
Specialize a type, not a var.

wp

  • Hero Member
  • *****
  • Posts: 11831
Re: Delete-Insert Logic escapes me!
« Reply #7 on: September 21, 2017, 05:42:09 pm »
A For loop ist definitely faster than Delete and/or Insert, but if you really need some speed then check out this post...

Search: LazForum:
Best way to clean large text files: Reply #4 (himitsu StrReplace) = Really F A S T   !!!
Just looking at the lines of code in this unit I do not believe that they will be faster than the simple "for" loop in this particular case. The only two methods to speed it up are, in my opinion, using assembler or using PChar instead of the character indexes.

Thaddy

  • Hero Member
  • *****
  • Posts: 14169
  • Probably until I exterminate Putin.
Re: Delete-Insert Logic escapes me!
« Reply #8 on: September 21, 2017, 05:57:06 pm »
Same here, wp. I can't see the speedup.
Specialize a type, not a var.

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: Delete-Insert Logic escapes me!
« Reply #9 on: September 21, 2017, 07:05:33 pm »
Quote
Just looking at the lines of code in this unit I do not believe that they will be faster than the simple "for" loop in this particular case. The only two methods to speed it up are, in my opinion, using assembler or using PChar instead of the character indexes.
Yes... I was thinking about string replacement in general....
I thougth this could be of interest, I didn't look at the exact problem here...  :)

Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Delete-Insert Logic escapes me!
« Reply #10 on: September 22, 2017, 01:49:55 am »
replacing should be simple but, there is always that chance of utf8 in the mix but in this
case it should be simple..

 For L := 1 to Length(S) do
   If S[L] ='*' Then S[L] :=' ';
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018