?
Solved

Dynamic Array of Chars to String

Posted on 2003-03-05
16
Medium Priority
?
859 Views
Last Modified: 2010-04-04
Hi all,

Can I copy the content of a dynamic array of chars to one string? Can StrPas work with dynamic arrays? I'm using D5.

Thanks in advance.

Beginner
0
Comment
Question by:brockes
[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
  • 7
  • 4
  • 2
  • +2
16 Comments
 
LVL 6

Expert Comment

by:Stuart_Johnson
ID: 8075542
StrPas won't do it as far as I can tell, but this will:

var
  A: Array of Char;
  S: String;
  I: Integer;
begin
  SetLength(A, 4); //define length of array

  A[0] := 'B';  //assign some stuff to each element
  A[1] := 'O';
  A[2] := 'O';
  A[3] := '!';

  S := '';
  for I := 0 to high(A) do  //loop through each element
    S := S + A[I];          //and add to our string

  ShowMessage(S);
end;

HTH.

Stu
0
 
LVL 6

Expert Comment

by:Stuart_Johnson
ID: 8075548
(note- there maybe a nicer way of doing this, I'm not sure).
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8075564
type
  TCharArray = array of char;

function DynaToStr(dync: TCharArray): string;
begin
  Result := string(copy(dync, 0, length(dync)));
end;

or

function DynaToStr(dync: TCharArray): string;
var L: integer;
begin
  L := Length(dync);
  SetLength(Result, L);
  Move(dync[0], Result[1], L);
end;

wbr, mo.
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 6

Expert Comment

by:swift99
ID: 8075691
If you always terminate the array of char with a chr(0) then StrPas will work nicely.
0
 

Author Comment

by:brockes
ID: 8077439
Sorry, You all are right, If I had more points I would accept the answer now, but as I only have more 5 points, I will ask one more question, who answer it takes the 55 points. I try your answers in my code but it do not work. I found that I'm trying to use an old rc4 encription component wich not accept dynamic arrays as output arrays and I need to set the output array length in function of Length(Edit1.Text). If static arrays don't accept SetLength or a var (outarray[0..L]) as argument, how can I create an array with same length of Edit1.Text in execution time? For example, if the user types 5 characters in Edit1.Text, I need to create a static array of the same size (array[0..4] of char).
0
 
LVL 3

Expert Comment

by:Slavak
ID: 8078630
You can do it by simple assignments:

procedure TForm1.Button1Click(Sender: TObject);
var
 A: Array of Char;
 S: String;
begin
 SetLength(A, 4); //define length of array

 A[0] := 'B';  //init array
 A[1] := 'O';
 A[2] := 'O';
 A[3] := '!';

 S := PChar(A); // assignments

 ShowMessage(S);
end;

Some points:

-- StrPas function will work too. But, from Delphi help:
"This function is provided for backwards compatibility only. To convert a null terminated string to a Pascal-type string, use a typecast or an assignment."

-- Using "array of char" dynamic array type is make no sense because it actually String(long).
 
-- To swift99:
Dynamic arrays and Strings (long) in delphi always ends by #0, so you not need to worry about.

-- You cannot dynamically create static array if you not defined this type before. But you can define the type big enough (for example, 65535 characters) and provide actual size as parameter:

PMyArray = ^TMyArray;
TMyArray = array[0..65535] of char;
...
MyArray : PMyArray;
...
// create array
GetMem(MyArray, Length(Edit1.Text) + 1);
Move(PChar(Edit1.Text), MyArray^, Length(Edit1.Text) + 1);





0
 
LVL 3

Expert Comment

by:Slavak
ID: 8078634
Sorry,
Last line:
Move(PChar(Edit1.Text)^, MyArray^, Length(Edit1.Text) + 1);

0
 
LVL 9

Expert Comment

by:mocarts
ID: 8079037
can you post here your encryption function declaration you call? (something like function Encrypt(what, key: string; var BufOut; bufLen: integer)
mo.
0
 

Author Comment

by:brockes
ID: 8085783
I am trying encript and decript a string, if the old rc4 component would accept dynamic arrays as output arrays, the following code would work, but this old rc4 component appears not implemented to work with dynamic arrays because when I try to run this code the system freezes and the hard drive light don't stop to blink.

var
  Form1: TForm1;
  RC41IVector: String;
  outarray1: array of char; //dynamic arrays
  outarray2: array of char;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
RC41 := TRC4.Create(Self);
 try
 RC41.InputType := SourceString;
 RC41.InputString := Edit1.Text;
 SetLength(outarray1, Length(Edit1.Text));
 RC41.pOutputArray := @outarray1;
 RC41.Key := 'abcdefghijklmnop';
 RC41.CipherMode := ECBMode;
 RC41.EncipherData(False);
 RC41IVector := RC41.IVector;
 Edit2.Text := StrPas(outarray1);
 finally
 RC41.free;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
outarray: array of Char;
begin
RC41 := TRC4.Create(Self);
 try
 RC41.InputType := SourceString;
 RC41.InputString := Edit2.Text;
 RC41.pOutputArray := @outarray2;
 RC41.Key := 'abcdefghijklmnop';
 RC41.CipherMode := ECBMode;
 RC41.IVector := RC41IVector;
 RC41.DecipherData(False);
 Edit2.Text := StrPas(outarray2);
 finally
 RC41.free;
 end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Edit2.Text := '';
Edit3.Text := '';
Edit1.SetFocus;
Edit1.SelectAll;
end;

I will try Slavak's comment on this code, I thinking that it will work.
0
 

Author Comment

by:brockes
ID: 8085937
I would try Slavak's comment, it compiles, but when I try to encript one string the program hangs showing an error in the line below with the comment: 'ERROR HERE!' Please Slavak, help me to close this question.

type
POutputArray = ^TOutputArray;
TOutputArray = array[0..65535] of Char;

var
  Form1: TForm1;
  RC41IVector: String;
  outarray1, outarray2: POutputArray;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
GetMem(outarray1, Length(Edit1.Text) + 1);
//Move(PChar(Edit1.Text), outarray1^, Length(Edit1.Text) + 1);
RC41 := TRC4.Create(Self);
 try
 RC41.InputType := SourceString;
 RC41.InputString := Edit1.Text;
 RC41.pOutputArray := @outarray1;
 RC41.Key := 'abcdefghijklmnop';
 RC41.CipherMode := ECBMode;
 RC41.EncipherData(False);
 RC41IVector := RC41.IVector;
 Edit2.Text := '';
  for i := 1 to Length(Edit1.Text) do
  begin
  Edit2.Text := Edit2.Text + outarray1[i]; //ERROR HERE!
  end;
 finally
 RC41.free;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
begin
GetMem(outarray2, Length(Edit2.Text) + 1);
//Move(PChar(Edit2.Text), outarray2^, Length(Edit2.Text) + 1);
RC41 := TRC4.Create(Self);
 try
 RC41.InputType := SourceString;
 RC41.InputString := Edit2.Text;
 RC41.pOutputArray := @outarray2;
 RC41.Key := 'abcdefghijklmnop';
 RC41.CipherMode := ECBMode;
 RC41.IVector := RC41IVector;
 RC41.DecipherData(False);
 Edit3.Text := '';
  for i := 1 to Length(Edit2.Text) - 1 do
  begin
  Edit3.Text := Edit3.Text + outarray2[i];
  end;
 finally
 RC41.free;
 end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Edit2.Text := '';
Edit3.Text := '';
Edit1.SetFocus;
Edit1.SelectAll;
end;
0
 
LVL 3

Expert Comment

by:Slavak
ID: 8096950
Hi, brockes.

I don't know what TRC4 class does, but some points.

You allocate memory for output steam at same size as input:

GetMem(outarray1, Length(Edit1.Text) + 1);

If it true (input size = output size), then may be you should place #0 char at end of allocated memory:

outarray1^[Length(Edit1.Text)] := #0;

Usually, I prefer to init allocated memory :

FillChar(OutArray1^, Length(Edit1.Text) + 1, 0);

Now, outarray1 declared as POutputArray (pointer to array of char). So, it is error to reference to address of this variable (@outputarray1). I suppose that you compile your project with disabled "Range checking" compiler option. I recomend you always enable "checking" compiler options in development phase (I prefer to remain it enable even in non performance critical parts of release version).

I cannot compile your code without TRC4 class, but it should look like this:

procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
GetMem(outarray1, Length(Edit1.Text) + 1);
FillChar(outarray1^, Length(Edit1.Text) + 1, 0); // <-- change

RC41 := TRC4.Create(Self);
try
RC41.InputType := SourceString;
RC41.InputString := Edit1.Text;
RC41.pOutputArray := outarray1; // <-- change
RC41.Key := 'abcdefghijklmnop';
RC41.CipherMode := ECBMode;
RC41.EncipherData(False);
RC41IVector := RC41.IVector;

Edit2.Text := outarray1^; // <-- change

finally
RC41.free;
end;
end;



 







You should know size of output steam.
0
 

Author Comment

by:brockes
ID: 8100547
Slavak,

TRC4 is an old encription component. Check next comment to see source code.

I try your last suggestion but it do not compiles due an error in the following line:

RC41.pOutputArray := outarray1; // <-- change

[Error] message is:
[Error] RC4Main.pas(51): Incompatible types: 'TOutputArray' and 'BArray'



0
 

Author Comment

by:brockes
ID: 8100552
unit Rc4unit;
{*****************************************************************************
 UNIT: TRC5Unit
 Description:  This unit contains an Object Pascal Object which can be used to
               perform TRC4 ciphers. 'RC4' is a trademark of RSA security
               corporation, this code is an implementation of the algorithm which
               RSA referers to as 'RC4'. TRC4 is a stream cipher, it is slightly
               different from the other ciphers included in this library.
               In 16bit code it is the fastest of the encryption algorithms.
               RSA has NOT made RC4 public, this is an implementation of the
               'rumored' algorithm.  It is only included here incase RSA
               decides to make RC4 public.  DO NOT use it, unless you have
               authorization from RSA.

               For more information on the algorithm see 'Applied Cryptography',
               Bruce Snheier or visit RSA's www page.  http://www.rsa.com

 The RC4 Algorithm was produced by Ronald Rivest.(See LEGAL)
 -----------------------------------------------------------------------------
 Code Author:  Greg Carter, gregc@cryptocard.com
 Organization: CRYPTOCard Corporation, info@cryptocard.com
               R&D Division, Carleton Place, ON, CANADA, K7C 3T2
               1-613-253-3152 Voice, 1-613-253-4685 Fax.
 Date of V.1:  Jan. 3 1996.

 Compatibility & Testing with BP7.0: Anne Marcel Roorda, garfield@xs4all.nl
 -----------------------------------------------------------------------------}
 {Useage:  Below is typical usage(for File)of the TRC4 Object,
           Follow these steps:
           1) Declare and Create Variable of type TRC4.
           2) Set InputSource Type, either SourceFile, SourceByteArray, or
              SourceString(Pascal style string).
           3) Point to Input Source and set Input Length(If needed)
           4) Point to Output Structure(array, file).
           5) Set Key;
           6) Call BF_EncipherData Method.
           7) Reference the Output. Thats it.
 **** Note **** Steps 2..6 can occure in any order.
 Here is a procedure in Delphi used to encrypt a file:
procedure Tcryptfrm.OpenCiphButtonClick(Sender: TObject);
var
 RC4: TRC4; (*Step 1*)
begin
RC4 := TRC4.Create;(*Step 1b*)
 try
  If OpenDialog1.Execute then
  begin
   RC4.InputType := SourceFile; (*Step 2*)
   RC4.InputFilePath := OpenDialog1.FileName; (*Step 3*)
   RC4.OutputFilePath := ChangeFileExt(OpenDialog1.FileName, '.ccc'); (*Step 4*)
   RC4.Key := 'abcdefghijklmnopqrstuvwxyz'; (*Step 5*)
   RC4.BF_EncipherData(False);  (*Step 6*)
  end;
 finally
  RC4.free;
 end;
end;

{-----------------------------------------------------------------------------}
{LEGAL:        The algorithm is in the process of being patented, and its name
               'RC4' is trademarked.  Please oontact RSA Data Security for
               licensing arrangements. This code is copyright by
               CRYPTOCard.  CRYPTOCard grants anyone who may wish to use, modify
               or redistribute this code privileges to do so, provided the user
               agrees to the following three(3) rules:

               1)Any Applications, (ie exes which make use of this
               Object...), for-profit or non-profit,
               must acknowledge the author of this Object(ie.
               TRC4 Implementation provided by Greg Carter, CRYPTOCard
               Corporation) somewhere in the accompanying Application
               documentation(ie AboutBox, HelpFile, readme...).  NO runtime
               or licensing fees are required!

               2)Any Developer Component(ie Delphi Component, Visual Basic VBX,
               DLL) derived from this software must acknowledge that it is
               derived from "TRC4 Object Pascal Implementation Originated by
               Greg Carter, CRYPTOCard Corporation 1996". Also all efforts should
               be made to point out any changes from the original.
               !!!!!Further, any Developer Components based on this code
               *MAY NOT* be sold for profit.  This Object was placed into the
               public domain, and therefore any derived components should
               also.!!!!!

               3)CRYPTOCard Corporation makes no representations concerning this
               software or the suitability of this software for any particular
               purpose. It is provided "as is" without express or implied
               warranty of any kind. CRYPTOCard accepts no liability from any
               loss or damage as a result of using this software.

CRYPTOCard Corporation is in no way affiliated with RSA Data Security Inc.
The RC4 Algorithm was produced by Ronald Rivest.
-----------------------------------------------------------------------------
Why Use this instead of a freely available C DLL?

The goal was to provide a number of Encryption/Hash implementations in Object
Pascal, so that the Pascal Developer has considerably more freedom.  These
Implementations are geared toward the PC(Intel) Microsoft Windows developer,
who will be using Borland's New 32bit developement environment(Delphi32).  The
code generated by this new compiler is considerablely faster then 16bit versions.
And should provide the Developer with faster implementations then those using
C DLLs.
-----------------------------------------------------------------------------
NOTES: Make sure to read the LEGAL notes.
------------------------------------------------------------------------------
Revised:  00/00/00 BY: ******* Reason: ******
------------------------------------------------------------------------------
}
interface
{Declare the compiler defines}
{$I CRYPTDEF.INC}
{------Changeable compiler switches-----------------------------------}
{$A+   Word align variables }
{$F+   Force Far calls }
{$K+   Use smart callbacks
{$N+   Allow coprocessor instructions }
{$P+   Open parameters enabled }
{$S+   Stack checking }
{$T-   @ operator is NOT typed }
{$IFDEF DELPHI}
{$U-   Non Pentium safe FDIV }
{$Z-   No automatic word-sized enumerations}
{$ENDIF}
{---------------------------------------------------------------------}
{.$DEFINE TEST}
uses SysUtils, Cryptcon{$IFDEF DELPHI}, Classes, Controls{$ENDIF}
     {$IFDEF BP7},objects{$ENDIF};

type
{$IFDEF DELPHI}
 TRC4 = class(TCrypto)
{$ENDIF}
{$IFDEF BP7}
 PRC4 = ^TRC4;   {For BP7 Objects}
 TRC4 = object(TCrypto)
{$ENDIF}
 Private
  {RC4 Key Elements}
  FState: Array[0..255] of BYTE;
  FI: BYTE;
  FJ: BYTE;
 {$IFDEF DELPHI}
  Procedure SetKeys;       override; {Sets up En\DecipherKey SubKeys}
  Procedure Encipher_Bytes;override;
  Procedure Decipher_Bytes;override;
{$ENDIF}
{$IFDEF BP7}
  Procedure Encipher_Bytes; virtual;
  Procedure Decipher_Bytes; virtual;
  Procedure SetKeys;        virtual; {Sets up En\DecipherKey SubKeys}
{$ENDIF}
 public
    { Public declarations }
{$IFDEF DELPHI}
  constructor Create(Owner: TComponent);override;
{$ENDIF}
{$IFDEF BP7}
  constructor Init;
{$ENDIF}
end;{TRC4}

{$IFDEF DELPHI}
 procedure Register;{register the component to the Delphi toolbar}
{$ENDIF}

implementation

{$IFDEF DELPHI}
procedure Register;
  {Registers the Component to the toobar, on the tab named 'Crypto'}
  {Now all a Delphi programmer needs to do is drag n drop to have
   Blowfish encryption}
begin
  RegisterComponents('Crypto', [TRC4]);
end;
{$ENDIF}

{==================================TRC4========================================}

{$IFDEF DELPHI}
constructor TRC4.Create(Owner: TComponent);
{$ENDIF}
{$IFDEF BP7}
constructor TRC4.Init;
{$ENDIF}
begin
{ Decipher_Bytes := @Encipher_Bytes;}
{$IFDEF DELPHI}
  inherited Create(Owner);
{$ENDIF}
end;

Procedure TRC4.SetKeys;
{------------------------------------------------------------------------------
 Initializing the S-Box.  First fill it linearly: So=0, S1=1...S255=255.
 Then fill another 256byte array with the key, repeating the key as necessary
 to fill the entire array: K0, K1..K255.
 Then
 j=0
 for i=0 to 255
  j = (j + Si + Ki) mod 256
  swap Si and Sj
-------------------------------------------------------------------------------}
var
 KeyLen, j: WORD; i, swapbyte: BYTE;
 K: Array[0..255] of BYTE;

begin
 KeyLen := Length(FKey);
 FI := 0; FJ := 0;j := 0;
 for i:= 0 to 255 do begin
  FState[i] := i; K[i] := BYTE(FKey[(i MOD KeyLen) + 1]);
 end;
 for i := 0 to 255 do begin
  j := (j + FState[i] + K[i]) MOD 256;
  swapbyte := FState[i]; FState[i] := FState[j]; FState[j] := swapbyte;
 end;
end;{SetKeys}

Procedure TRC4.Encipher_Bytes;
{------------------------------------------------------------------------------
 i=j=0

 i=(i + 1) mod 256
 j=(j + Si) mod 256
 swap Si and Sj
 t = (Si + Sj) mod 256
 K = St

 the BYTE K is XOR withe plaintext to produce ciphertext or XORED with
 the ciphertext to produce plaintext

 We assume that the data to encipher is in FBuffer, and FInputLength holds the
 length of FBuffer.
 ------------------------------------------------------------------------------}
 var
  i, j, t, swapbyte: BYTE;
  x: WORD;
 begin
  i:= FI; j:= FJ;

  For x := 0 to (FInputLength - 1) do begin
   i := (i + 1) MOD 256;
   j := (j + FState[i]) MOD 256;
   swapbyte := FState[i]; FState[i] := FState[j]; FState[j] := swapbyte;
   t := (FState[i] + FState[j]) MOD 256;
   FOutputArray^[x] := FState[t] Xor FBuffer[x];
  end;

  FI := i;
  FJ := j;
 end;

Procedure TRC4.Decipher_Bytes;
begin
 Encipher_Bytes;
end;
end.
0
 
LVL 3

Accepted Solution

by:
Slavak earned 165 total points
ID: 8101310
I still cannot compile it (missing files).

If you want, send your code to slavak@programmer.net and I will try to fix it.
0
 

Author Comment

by:brockes
ID: 8117224
The old encription component that I was using is: http://www.torry.net/vcl/security/strong/cryptov1.zip
Sorry to waste your time Slavak. However I get to solve this question, look the code below, it works! But I should recognize that you helps a lot. I will give you the points. Thank you.

unit BlowFishM;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Cryptcon, Ideaunit, Blowunit, HKSafeForm;

type
  TForm1 = class(TForm)
    Edit2: TEdit;
    Edit3: TEdit;
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    HKSafeForm1: THKSafeForm;
    BlowFish1: TBlowFish;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  outarray1, outarray2: array[0..255] of Char;
  BFIVector: String;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
BlowFish: TBlowFish;
begin
BlowFish := TBlowFish.Create(Self);
 try
 BlowFish.InputType := SourceString;
 BlowFish.InputLength := Length(Edit1.Text);
 BlowFish.InputString := Edit1.Text;
 BlowFish.Key := 'abcdefghijklmnopqrstuvwxyz';
 BlowFish.CipherMode := ECBMode;
 FillChar(outarray1, 255, #0);
 BlowFish.pOutputArray := @outarray1;
 BlowFish.EncipherData(False);
 BFIVector := BlowFish.IVector;
 Edit2.Text := StrPas(outarray1);
 finally
 BlowFish.free;
 end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Edit2.Text := '';
Edit3.Text := '';
Edit1.SetFocus;
Edit1.SelectAll;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
BlowFish: TBlowFish;
begin
BlowFish := TBlowFish.Create(Self);
 try
 BlowFish.InputType := SourceByteArray;
 BlowFish.InputLength := Length(Edit2.Text);
 BlowFish.pInputArray := @outarray1;
 BlowFish.Key := 'abcdefghijklmnopqrstuvwxyz';
 BlowFish.CipherMode := ECBMode;
 FillChar(outarray2, 255, #0);
 BlowFish.pOutputArray := @outarray2;
 BlowFish.IVector := BFIVector;
 BlowFish.DecipherData(False);
 Edit3.Text := StrPas(outarray2);
 finally
 BlowFish.free;
 end;
end;

end.
0
 

Author Comment

by:brockes
ID: 8117242
You answer do not solve the question, but help me to solve it, thanks.
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
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…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
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
Course of the Month12 days, 15 hours left to enroll

777 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