Solved

Array ---> string?

Posted on 2000-03-18
19
421 Views
Last Modified: 2010-04-04
Hi,
For example:
var
a: array[1..1024] of char;
s: string;
What is the fastest way to convert the chars in the array into the string variable, ie. s:=a[1]+a[2]+a[3].......+a[1024];
I know a for loop may help, but I suppose it's a time consuming process if the array is very large, say, [1..1024000].
So is there a function or procedure can do this??
Thanks in advance!
0
Comment
Question by:nyt
  • 5
  • 4
  • 3
  • +6
19 Comments
 

Expert Comment

by:HamidHossain
Comment Utility
lestining ...
0
 

Expert Comment

by:HamidHossain
Comment Utility
for I := Low(a) to High(a) do begin
  S := a[I];
  Application.ProcessMessage;
end;


ProcessMessage will avoid system buissy

Regards,
Hamid

0
 

Expert Comment

by:HamidHossain
Comment Utility
for I := Low(a) to High(a) do begin
  S := S + a[I];
  Application.ProcessMessage;
end;


ProcessMessage will avoid system buissy

Regards,
Hamid

0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
hi nyt,

what about

  SetString(s,PChar(@a),sizeOf(a));

sample

var
  a: array[1..1024] of char;
  s : String;


procedure Init_a;   //just for init the array
var I : Integer;
begin
  for i := low(a) to high(a) do
    a[i] := Chr((i mod 26) + 65);  //only capital letters
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  init_a;
  SetString(s,PChar(@a),sizeOf(a));
  memo1.text := s;  //just for output
end;

meikl
0
 

Expert Comment

by:HamidHossain
Comment Utility
for I := Low(a) to High(a) do begin
  S := S + a[I];
  Application.ProcessMessage;
end;


ProcessMessage will avoid system buissy

Regards,
Hamid

0
 
LVL 2

Accepted Solution

by:
kubeerja earned 50 total points
Comment Utility
why dont use S:=A ;
string in delphi is an array of char, so when you say
a: array[1..1024] of char;
this equals A : String[1024] ;
actually you can use A directly as string and say for example  label1.Caption:=A ;
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
meikl is right. And kubeerja is right, too - but only in some parts of his comment.
The easiest way is to do this:

var s1 : string;
    arrCh : array [1..1024] of char;
begin
  s1 := arrCh;

But the reason why you can do this is NOT that a Delphi string would be equal to an array of char - it is NOT!!!
If you define "String[1024]", this is something like "record length: byte; data: array [1..1024] of char end;". You see the difference? Delphi's short strings have a length byte in the beginning.
And normally we should even forget short strings at all. We should be using long strings, that is simply "string". And a string is a quite complex structure, that Delphi handles completely automatically. E.g. if you do this:

var s: string;
begin
  s := 'test';

Delphi now allocates memory for this string PLUS size for a little record, puts the characters "test" to the allocated memory and fills the record. In the record there are integer (32-bit) values for the size of the string (so long strings can be 4 GB long), for the allocation size and for the reference count. Yes, Delphi long strings are being administered by Delphi using reference counting, just like COM objects are, but much faster.

If you do "stringVar := pcharVar" or "stringVar := arrayOfCharVar", Delphi accepts this as a valid syntax and does ALL the work for you. It's the fastest you can do. It will result in a call to SetString. So in the end it is equal to meikl's suggestion, but easier to write/understand.

Using a loop like Hamid suggested would work alright, but is several times slower, because Delphi has to reallocate the string several times.

Regards, Madshi.
0
 
LVL 2

Expert Comment

by:alexstewart@beta
Comment Utility
Another way...

Use Setlength to allocate the string memory in one shot.

Use the built-in move procedure to copy the memory efficiently.

This will be the fastest for long multimegabyte data.

(well not quite, see..
http://www.econos.com/optimize/
for move and alignment tricks)

const
  MaxDataLength=1024;
var
Data:array[0..MaxDataLength-1] of char;
///note Data is zero based in my example
DataLength:word=973;
///maybe data is shorter than 1024
TargetString:string;

....

assert(
  DataLength<=MaxDataLength,
  'Length Error');
///check

setlength(TargetString,datalength);
move(
  data[low(Data)],
///low returns zero here
  TargetString[1],
  datalength);
....

also, if you do use the simple mechanism
TargetString:=pChar(@Data[0]);
///or similar, I dont have delphi handy
Be sure to preceed it by...
Data[low(Data)+DataLength]:=#0;

This is because the length of a pchar string is set by the terminating null (#0).

-Alex
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hi Alex, I'm sorry to say, but your suggestion is NO WAY faster than simply assigning "strVar := arrOfCharVar". You can believe me, I've just done some timing tests. Your suggestion needs EXACTLY the same time as the simple assignment (or SetString) needs. So no difference - so no reason to go the complicated way.

>> Be sure to preceed it by...
>> Data[low(Data)+DataLength]:=#0;
>> This is because the length of a pchar string is set by the terminating null (#0).

NO! Delphi does that for you. Well, if you use the simple assignment (or SetString), THEN Delphi does it for you. It's different of course, if you use Move, then you have to look for that #0 yourself.

Regards, Madshi.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 9

Expert Comment

by:ITugay
Comment Utility
hi nyt.

-------
var
   a: array[1..1024] of char;
   s: string;

begin
   SetLength(S,1024);
   move(A,pointer(S)^,1024);
....

Is it applicable?

Cheers,
Igor.
   
0
 
LVL 5

Expert Comment

by:heathprovost
Comment Utility
Hi Madshi :) been a while...  Anyway, I just wanted to put in my 2 cents on this.  This seems like basic stuff to me, and I completely agree with Madshi.  Character arrays are completely assignment compatible with strings....  why would you want to do any of this hocus pocus stuff when you can just do s:=a; ???  Am I missing something?

Heath
0
 

Expert Comment

by:zaferms
Comment Utility
lestining ,,,,
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hi Heath!  (-:  How are things goin?
0
 
LVL 5

Expert Comment

by:heathprovost
Comment Utility
Pretty good.  I am still working for the same web development company, but my position changed about 4 months ago from Network Administrator to Network Administrator/Lead Programmer because of a couple of programmers leaving the company...  It is really fun having 2 jobs, NOT :P  At first I was just sort of helping with the programming and stuff, but after those other guys left I was like the only programmer here.  I have been meaning to drop in here but just keep getting buried in work.  But now that I have a little free time I will be able to play with Delphi again (they just hired a couple of new programmers who seem to be doing well).  Cold Fusion is cool and all, but it isnt Delphi :)

Heath
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Nice to hear. I hope your earnings have changed along with your position?   =:O))
0
 

Author Comment

by:nyt
Comment Utility
Most of the answers work.  I just accept the comment submitted first as the answer.
Thank you all.
0
 
LVL 2

Expert Comment

by:alexstewart@beta
Comment Utility
Well, I can see we are flogging this problem beyond the realms of utility, but I cant resist another comment...

Using the crude (but simple) timing code below, I measure assigning the char array data (300 mbytes) (D5 on a P2-500 machine with 1GByte ram)
We Compare
....
bigstring:='';
setlength(BigString,DataLength);
move(BigCharArray[low(BigCharArray)],
  BigString[1],
  datalength);
....
and the simpler syntax
....
bigstring:='';
bigstring:=BigCharArray;
....

For Big arrays (300 Mbytes) the setlength-move is over 2 times faster than the simplest syntax. (3.8 secs vs 8.5 secs)

For midsize arrays (50 Mbytes) the setlength-move is about 3 times faster than the simplest syntax.

For short arrays (1 Mbyte) the setlength-move is about 2.5 times faster than the simplest syntax.

So unlike Madshi, I do find a real speed difference with a single cpu. A major advantage with using the setlength-move is that you can then apply optimised moves, especially if you have multiple processors. Another advantage is that this makes a good way to copy sub regions from your char array, without the creation of hidden temporary strings which the use of 'copy/delete' would incur(how much?).

The thread safe string stuff can also slow string things down.

Also, suprisingly (to me anyway)
....
BigString:=pchar(@BigCharArray[0]);
....
is consistently faster than
....
bigstring:=BigCharArray;
....
(but not as fast as SetLength-Move)
The pchar approach has to scan the string to find a null, but why is it faster? I dont know.
---------------------------------------
This is the ez-timing code
(you can use gettickcount instead of timegettime), or the QueryPerf.. functions
---------------------------------------
const
     siz=1048576*300;
     DataLength=siz;
var
  BigCharArray:array[0..siz-1]of char;
  BigString:string;
  t0:integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
bigstring:='';
t0:=timegettime;
setlength(BigString,DataLength);
move(
  BigCharArray[low(BigCharArray)],
  BigString[1],
  datalength);
label1.caption:=inttostr(timegettime-t0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
bigstring:='';
t0:=timegettime;
bigstring:=BigCharArray;
label1.caption:=inttostr(timegettime-t0);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
   n:integer;
begin
t0:=timegettime;
for n:=0 to siz-1 do BigCharArray[n]:=char(random(64)+32);
label1.caption:=inttostr(timegettime-t0);
end;
---------------------------------------
---------------------------------------
Alex

ps My previous advice to ...
>>Data[low(Data)+DataLength]:=#0;
was because many times (and in the example I gave) the DataLength might not be equal to the ArraySize. It is a useful trick for copying substrings out of long (multimegabyte) buffers, (but you might want to save and restore the previous buffer value).

All these timings were sensitive to relative cache allignment, (aliasing of cache addresses occurrs since the buffers are a power of two in size),
there is a 50% speedup change to be had if you vary the data allignment in dword chunks over the size of a cache line.

0
 
LVL 2

Expert Comment

by:alexstewart@beta
Comment Utility
For kicks I timed the 1024 byte case
using the clock cycle counter on the >=pentium cpus.
(*
function  RDTSC:int64;
var
   tscrec:record
   case byte of
     1:(tsc:int64);
     2:(tsclo,tschi:longint);
     end;
begin
asm
db $0f, $31
mov tscrec.tsclo, eax
mov tscrec.tschi, edx
end;
result:=tscrec.tsc;
end;
*)

"SetLength;Move" is >2x faster, on this machine than "string:=array" for tiny strings.

To do timings like this you really need to do stuff like turning off the dram refresh.

Alex
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hi Alex...   :-)

Well, I've not copied one mega-sized string, but instead I've copied a mid-sized string 10000 times or so. Don't know why I didn't have any timing differences there.

However, I can explain, why Move is faster than the assignment:
If you do the assignment, Delphi looks through the array to find the first #0 character to find the real length of the string. This search for the #0 character is most probably the delay your timing test has shown.

Okay, so if you need to copy a 300 MB string, Move is faster. Okay...  :-))  Just joking. But this is meant serious: Most of the time, when you want to convert a pchar or an array of character to a Delphi string, you WANT Delphi to look for that #0 character, right? Because pchar is defined this way. Say, Alex, have you tried SetString, as meikl has suggested? Because there you give in the length, so Delphi doesn't have to search. Probably you have then the same speed as Move again...
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now