Recent

Author Topic: Length of String is not fixed inside For?  (Read 3045 times)

Zvoni

  • Hero Member
  • *****
  • Posts: 2897
Re: Length of String is not fixed inside For?
« Reply #30 on: February 10, 2025, 01:02:23 pm »
Yes, I agree, that's a nice piece of work Zvoni, I am already thinking where I can use that particular trick.

But what about the reverse ? Imagine a text 'document' that contains lots of LF,CR characters in Windows style, and converting that to Unix single char model. Does FPC adjust the memory allocation for every delete() ?   I do something like that and am not aware that its particularly slow.

Davo
Something like this?
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. Var s,r:String;
  4.  
  5. Function ConvertLineEndingToUnix(Const aStr:String):String;
  6. Var
  7.   i:Integer;
  8.   x:Integer;
  9.   y:Integer;
  10.   c:Integer;
  11. Begin
  12.   c:=0;
  13.   x:=Length(aStr);
  14.   //Count CR's
  15.   For i:=1 To x Do If aStr[i]=#13 Then Inc(c);
  16.   SetLength(Result,x-c);  //Resize Result
  17.   i:=1;
  18.   y:=1;
  19.   Repeat
  20.     If aStr[i]=#13 Then
  21.        Inc(i)         //Skip
  22.     Else
  23.       Begin
  24.         Result[y]:=aStr[i];
  25.         Inc(i);
  26.         Inc(y);
  27.       End;
  28.   until i>x;
  29. End;
  30.  
  31. begin
  32.   s:='I always arrive late at the office,'+#13#10+' but I make up for it by leaving early';
  33.   r:=ConvertLineEndingToUnix(s);
  34.   Writeln(r);
  35.   Readln;
  36. end.

But this only makes sense, when "converting" a textfile, and then it's a question, if it makes sense to run through a whole textfile char by char, or just to fire off a Replace, and be done with it
« Last Edit: February 10, 2025, 01:21:46 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10906
  • Debugger - SynEdit - and more
    • wiki
Re: Length of String is not fixed inside For?
« Reply #31 on: February 10, 2025, 02:21:26 pm »
But what about the reverse ? Imagine a text 'document' that contains lots of LF,CR characters in Windows style, and converting that to Unix single char model. Does FPC adjust the memory allocation for every delete() ? 

When talking about strings (refcounted longstring, e.g. ansistring, also widestring / not shortstring) then memory reallocation is only part of it.

And while I don't know (and it may depend on the memory manager used (fpc's own vs cmem or other), it might well be, that the shorter memory is not "moved", and only the freed part at the end returned to the mem pool.

But Insert/delete may do more...

But there is another
Code: Pascal  [Select][+][-]
  1. MyStr[i] := '?';
as well as insert/delete

=> they all need to ensure the string has a refcount of 1 (as otherwise they need to trigger copy on write).
That too, has a cost.

So usually you want to do:
Code: Pascal  [Select][+][-]
  1. uniquestring(MyStr); // now it has a refcount of 1
  2. pMyStr := PChar(MyStr);
  3. //SetLength(MyStr, NewLen); // If you need more space
  4. pMyStr[i-1]  := '?'; // 0 based index // The pchar changes the content of MyStr
  5. SetLength(MyStr, NewLen); // If you shortened it
  6.  
And of course if you insert delete chars, then call "move()".

BrunoK

  • Hero Member
  • *****
  • Posts: 682
  • Retired programmer
Re: Length of String is not fixed inside For?
« Reply #32 on: February 10, 2025, 04:03:35 pm »
But what about the reverse ? Imagine a text 'document' that contains lots of LF,CR characters in Windows style, and converting that to Unix single char model. Does FPC adjust the memory allocation for every delete() ?   I do something like that and am not aware that its particularly slow.

Davo
FPC 3.2.2, unit rtl\inc\astrings.inc (lines may not exactly match because of some private experiences).

Delete uses fpc_ansistr_delete (~l 1386) which calls fpc_AnsiStr_SetLength (~l 789) see note { allow shrinking string if that saves at least half of current size }.

When using HEAP.INC, strings exploit as much memory possible in the allocated GetMem block before allocating a larger block. When shrinking a string length, a ReallocMem occurs if the new length if smaller than half the currently allocated memory block size.

With cmem, the behavior is a bit different and the cmem implementation of ReallocMem decides if the requested block must be reallocated or if it stays in place.

Seems that FPC trunk does initially and voluntarily over allocate a bit thus making cmem a bit more equal. I experimented it with 3.2.2 and didn't notice much speed change while using cmem.

 



d2010

  • Full Member
  • ***
  • Posts: 117
Re: Length of String is not fixed inside For?
« Reply #33 on: February 11, 2025, 11:07:29 am »
See example below, it will output from 1 to 5. Even though, that "val" will change to 10.
It only matters that "val" was 5 when the loop started.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var
  3.   i, val: integer;
  4. begin
  5.   val := 5;
  6.   for i := 1 to val do begin
  7.     writeln(i);
  8.     val := 10;
  9.   end;
  10.   readln;
  11. end.
  12.  
As said by others, use "while" or "repeat" if you need a changing end-point.

I think for are more faster than while and repeat.

Zvoni

  • Hero Member
  • *****
  • Posts: 2897
Re: Length of String is not fixed inside For?
« Reply #34 on: February 11, 2025, 11:15:36 am »
I think for are more faster than while and repeat.
Yes, it tends/seems to be faster, since while/repeat checks the Exit-condition on each iteration, while a For-Loop doesn't care for that.

But as always in programming: What's more important?
A "fast" For-Loop, which doesn't do what you want,
or a slightly "slower" while/repeat, which does do what you want?
« Last Edit: February 11, 2025, 11:17:45 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

d2010

  • Full Member
  • ***
  • Posts: 117
Re: Length of String is not fixed inside For?
« Reply #35 on: February 11, 2025, 11:34:52 am »
Hi
Hmmm, if not stringreplace, then maybe like this:
Code: Pascal  [Select][+][-]
  1. function PhpAddSlashes(const aStr: ansistring): ansistring;
  2. var li, lr: integer; ch: char; cnt: cardinal = 0;
  3. begin
  4.   if aStr = '' then exit(aStr);
  5.   SetLength(Result,Length(aStr)*2); { make room for an extra '/' for each char }
  6.   lr:= 1; { local result idx }
  7.   for li:= 1 to Length(aStr) do begin { run local idx through the string }
  8.     ch:= aStr[li];
  9.     if ch = '/' then begin
  10.       Result[lr]:= '/'; { first insert an extra '/' @ this position }
  11.       inc(lr); { increment result idx }
  12.       inc(cnt); { keep track of insertions }
  13.     end;
  14.     Result[lr]:= ch; { for all chars, copy the actual char to result }
  15.     inc(lr); { increment result idx }
  16.   end;
  17.   SetLength(Result,Length(aStr) + cnt); { now set the actual length for real }
  18. end;

I dunno, but like this it makes some sense to me ...at least.
Regards Benny

 please you add at head, this-protection
You forced the other users, to set max limits at level-developer or at level code-writer,
not at level

Code: [Select]
function PhpAddSlashes(const aStr: ansistring;maxlimit:integer): ansistring;
var li, lr: integer; ch: char; cnt: cardinal = 0;
begin
  li:=00;
  lr:=000;
  if aStr = '' then exit(aStr);
  if (maxlimit<256) then maxlimit:=511 else
   if (maxlimit>4095) then maxlimit:=4095;   
   li:=length(aStr);
   if (li>4095) then RaiseError('PhpAddSlashes is broken max limits 0..4095
idem as FmtStr');
   if (li>maxlimit) then li:=maxlimit;
   SetLength(Result,li*02); { make room for an extra '/' for each char }
Eu multumesc ArsenieBoca.
Thank you :'(
Thank you :'(
« Last Edit: February 11, 2025, 12:17:06 pm by d2010 »

cdbc

  • Hero Member
  • *****
  • Posts: 1953
    • http://www.cdbc.dk
Re: Length of String is not fixed inside For?
« Reply #36 on: February 11, 2025, 03:52:45 pm »
Hi
Is this better for you:
Code: Pascal  [Select][+][-]
  1. function PhpAddSlashes(const aStr: ansistring;aMaxLimit: cardinal): ansistring;
  2. var ch: char; cnt: cardinal = 0; len: cardinal = 0; li: cardinal = 0; lr: cardinal = 0;
  3.   { nested function to find min-value }
  4.   function lmin(a,b: cardinal): cardinal; begin if a <= b then result:= a else result:= b; end;
  5. begin
  6.   if aStr = '' then exit(aStr); { first check }
  7.   len:= Length(aStr);
  8.   if len > 4095 then
  9.     raise Exception.Create('ERROR! PhpAddSlashes input is broken, max limit: 0..4095 idem as FmtStr');
  10.   if aMaxLimit < 256 then aMaxLimit:= 511 { make sure the string is between 512 }
  11.   else if (aMaxLimit > 4095) then aMaxLimit:= 4095;       { and 4096 bytes long }
  12.   len:= lmin(len,4096); { use nested func to find min-length of input string }
  13.   SetLength(Result,len*2); { make room for an extra '/' for each char }
  14.   lr:= 1; { local result idx }
  15.   for li:= 1 to len do begin { run local idx through the string }
  16.     ch:= aStr[li];
  17.     if ch = '/' then begin
  18.       Result[lr]:= '/'; { first insert an extra '/' @ this position }
  19.       inc(lr); { increment result idx }
  20.       inc(cnt); { keep track of insertions }
  21.     end;
  22.     Result[lr]:= ch; { for all chars, copy the actual char to result }
  23.     inc(lr); { increment result idx }
  24.   end;
  25.   SetLength(Result,Length(aStr) + cnt); { now set the actual length for real }
  26. end;
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

dbannon

  • Hero Member
  • *****
  • Posts: 3294
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Length of String is not fixed inside For?
« Reply #37 on: February 13, 2025, 02:31:24 am »
....
Something like this?

OK, sorry to drag the thread off topic again. Getting back to Zvoni's code (thanks Z) to remove #13 from a string of text. He calls a function that returns (in Result) the new string, that appears to me to involve one extra memory allocation, to Result. Better to pass the destination string (r) to a procedure that writes directly to r ?

Code: Pascal  [Select][+][-]
  1.     procedure MyConvertLineEndingToUnix(Const aStr:String; bStr:string);
  2.     Var
  3.       i:Integer;
  4.       x:Integer;
  5.       y:Integer;
  6.       c:Integer;
  7.     Begin
  8.       c:=0;
  9.       x:=Length(aStr);
  10.       //Count CR's
  11.           writeln('aStr at ', longint(@aStr));
  12.       For i:=1 To x Do If aStr[i]=#13 Then Inc(c);
  13.           //bStr := '';
  14.       SetLength(bStr,x-c);  //Resize "Result"
  15.       i:=1;
  16.       y:=1;
  17.       Repeat
  18.         If aStr[i]<>#13 Then
  19.           Begin
  20.             bStr[y]:=aStr[i];    // write directly to bStr which is, really, r
  21.             Inc(y);
  22.           End;
  23.           Inc(i);
  24.       until i>x;
  25.     End;

On the other hand, as Bruno pointed out, reallocation only happens (when using delete()) when the string gets down to half its original length. And that is not this use case anyway ! 

Thanks everyone, that clarified a lot in my mind.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

Zvoni

  • Hero Member
  • *****
  • Posts: 2897
Re: Length of String is not fixed inside For?
« Reply #38 on: February 13, 2025, 08:00:55 am »
Shouldn't that be "var bstr" or "out bstr"?
Code: Pascal  [Select][+][-]
  1. procedure MyConvertLineEndingToUnix(Const aStr:String;var bStr:string);
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

dbannon

  • Hero Member
  • *****
  • Posts: 3294
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Length of String is not fixed inside For?
« Reply #39 on: February 13, 2025, 09:25:04 am »
Shouldn't that be "var bstr" or "out bstr"?
Code: Pascal  [Select][+][-]
  1. procedure MyConvertLineEndingToUnix(Const aStr:String;var bStr:string);

Ahh, copied wrong version !  Definitely should be 'out' !

Code: Bash  [Select][+][-]
  1. dbannon@dell:~/Pascal/CLI$ ./zvoni
  2. s starts at 4390816
  3. r starts at 4391072
  4. aStr at 4390816
  5. r starts at 4391072
  6. I always arrive late at the office,
  7.  but I make up for it by leaving early

 :D

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

TRon

  • Hero Member
  • *****
  • Posts: 4140
Re: Length of String is not fixed inside For?
« Reply #40 on: February 13, 2025, 09:40:38 am »
Only required in case caring about the result otherwise .. mew...  ;)
Today is tomorrow's yesterday.

VisualLab

  • Hero Member
  • *****
  • Posts: 639
Re: Length of String is not fixed inside For?
« Reply #41 on: February 13, 2025, 01:06:53 pm »
WTF is "Virtual Pascal"?

https://en.wikipedia.org/wiki/Virtual_Pascal

It might surprise you, but there's more than one kid on the block...

It turns out I remembered correctly. It (i.e. VirtualPascal) has been out of date for about 20 years (abandoned). Of the Pascal variants compiled to machine code "on the battlefield", only Delphi and FPC remain.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8320
Re: Length of String is not fixed inside For?
« Reply #42 on: February 13, 2025, 01:25:03 pm »
It turns out I remembered correctly. It (i.e. VirtualPascal) has been out of date for about 20 years (abandoned). Of the Pascal variants compiled to machine code "on the battlefield", only Delphi and FPC remain.

https://sourceforge.net/projects/vectorpascalcom/  Last Update: 2025-02-02

Plus of course we obviously don't know the precise state of proprietary Pascal on IBM mainframes etc.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 16652
  • Kallstadt seems a good place to evict Trump to.
Re: Length of String is not fixed inside For?
« Reply #43 on: February 13, 2025, 01:36:45 pm »
And definitely not self hosting, which to me is a no go.
You can't compile virtual pascal in virtual pascal, only in Java.
So just like GNU pascal was (C) it is a bastard child.
But I am sure they don't want the Trumps back...

MarkMLl

  • Hero Member
  • *****
  • Posts: 8320
Re: Length of String is not fixed inside For?
« Reply #44 on: February 13, 2025, 01:51:47 pm »
Same criticism obviously applies to Vector Pascal. However whether or not a particular implementation is self-hosting, and whether or not we'd find reason to use it, isn't really relevant: all that's relevant is that there's still multiple implementations of the language, even if some of them are special-purpose or intentionally "under the radar".

Updated: Anyway, I'd suggest that the bottom line is that FPC is still alive and offers OP a reasonable migration path: /if/ he is so inclined and /if/ the extent that this thread wandered away from his original request hasn't deterred him.

MarkMLl
« Last Edit: February 13, 2025, 02:33:50 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018