Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Array ---> string?

Posted on 2000-03-18
19
Medium Priority
?
429 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +6
19 Comments
 

Expert Comment

by:HamidHossain
ID: 2631254
lestining ...
0
 

Expert Comment

by:HamidHossain
ID: 2631261
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
ID: 2631262
for I := Low(a) to High(a) do begin
  S := S + a[I];
  Application.ProcessMessage;
end;


ProcessMessage will avoid system buissy

Regards,
Hamid

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 27

Expert Comment

by:kretzschmar
ID: 2631295
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
ID: 2631362
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 200 total points
ID: 2631443
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
ID: 2632135
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
ID: 2632198
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
ID: 2632984
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
 
LVL 9

Expert Comment

by:ITugay
ID: 2633027
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
ID: 2633181
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
ID: 2633200
lestining ,,,,
0
 
LVL 20

Expert Comment

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

Expert Comment

by:heathprovost
ID: 2633302
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
ID: 2633437
Nice to hear. I hope your earnings have changed along with your position?   =:O))
0
 

Author Comment

by:nyt
ID: 2634676
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
ID: 2637442
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
ID: 2637490
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
ID: 2637515
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
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…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

722 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