Dear GPC Users,
I use long strings to pass numerical data into and out of a shared library I compile from Pascal. Right now, I generate a long string of numbers like this.
program string_demo;
var long_string:string(100000); i:integer;
begin long_string:=''; for i:=1 to 10000 do writestr(long_string,long_string,i:1,' '); end.
Clearly, this is inefficient. It takes 200 ms on my machine. If I use an array of characters instead of a string, and append each new entry to the array, execution time drops to 10 ms.
I can't see a way of using GPC's writestr, concat, or trim functions to accelerate my string generation. I can't alter the long_string.length field directly. If I could fill up the string with spaces first, I could use the string as an array, then trim the spaces off the end. But filling up the string with spaces requires multiple calls to writestr, so I'm back where I started.
It seems to me that I'm missing an obvious solution to my problem, and I thought you might point it out to me.
Yours, Kevan
Dear Adriaan,
But why don't you pass the numerical data in binary form ?
The library is interacting with a Tcl interpreter, which deals with strings. I could pass the data in binary format and then translate into a character string for processing in Tcl. But I'd rather pass the string directly.
Now, it seems to me that the SetLength routine is what I'm looking for.
Yours, Kevan
Kevan Hashemi a écrit :
Dear GPC Users,
I use long strings to pass numerical data into and out of a shared library I compile from Pascal. Right now, I generate a long string of numbers like this.
program string_demo;
var long_string:string(100000); i:integer;
begin long_string:=''; for i:=1 to 10000 do writestr(long_string,long_string,i:1,' '); end.
Clearly, this is inefficient. It takes 200 ms on my machine. If I use an array of characters instead of a string, and append each new entry to the array, execution time drops to 10 ms.
I can't see a way of using GPC's writestr, concat, or trim functions to accelerate my string generation. I can't alter the long_string.length field directly.
SetLength(long_string, 999999).
If I could fill up the string with spaces first, I could
use the string as an array, then trim the spaces off the end. But filling up the string with spaces requires multiple calls to writestr, so I'm back where I started.
It seems to me that I'm missing an obvious solution to my problem, and I thought you might point it out to me.
Maurice
I get a factor of 30 decrease in execution time while making a string out of 10,000 integers when using the following routine to append to append each new interger string to the existing string.
procedure string_append(var s,p:string);
var i,num_to_add,old_length:integer; begin old_length:=length(s); if (s.capacity-old_length<length(p)) then begin num_to_add:=s.capacity-old_length; setlength(s,s.capacity); end else begin num_to_add:=length(p); setlength(s,old_length+length(p)); end; for i:=1 to num_to_add do s[old_length+i]:=p[i]; end;
So, SetLength is all I needed.
Yours, Kevan
Kevan Hashemi wrote:
I get a factor of 30 decrease in execution time while making a string out of 10,000 integers when using the following routine to append to append each new interger string to the existing string.
procedure string_append(var s,p:string);
var i,num_to_add,old_length:integer;
begin old_length:=length(s); if (s.capacity-old_length<length(p)) then begin num_to_add:=s.capacity-old_length; setlength(s,s.capacity); end else begin num_to_add:=length(p); setlength(s,old_length+length(p)); end; for i:=1 to num_to_add do s[old_length+i]:=p[i]; end;
So, SetLength is all I needed.
Or simply (this routine is also defined in stringutils.pas which comes which GPC):
procedure AppendStr (var s: String; const Source: String); begin Insert (Source, s, Length (s) + 1) end;
Frank
I see: the Insert routine. That makes my append routine redundant. Thank you for pointing it out. Yours, Kevan