Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Inhalt eines dynamischen Array in einen String kopieren (https://www.delphipraxis.net/144549-inhalt-eines-dynamischen-array-einen-string-kopieren.html)

oki 10. Dez 2009 14:34


Inhalt eines dynamischen Array in einen String kopieren
 
Hi Leute,

ich entschuldige mich schon mal im Voraus für die Frage. Bei der Suche bin ich wahnsinnig geworden; bekomme alle Threads mit den Stichworten String und Array; einfach zu viel.

Folgende Aufgabe:
Ich habe ein dynamisches Array A : Array of Byte und möchte deren Inhalt in einen String kopieren. Ich stell mich grad zu blöd an. Muss dabei bemerken, dass ich das nicht über eine Schleife sondern mittels move oder Copy mit "einem Ruck" erledigen will.

Mach ich es so:
Delphi-Quellcode:
      SetLength(SData, Length(FReceivedData));
      system.Move(@FReceivedData[0], SData[1], Length(FReceivedData));
      SetLength(FReceivedData, 0);
bekomme ich Fehlermeldungen wie:
Zitat:

[DCC Fehler] USBPort_Classes.pas(357): E2036 Variable erforderlich
Ich hatte eigentlich nicht erwartet, dass ich damit Schwierigkeiten habe, ist aber wohl so. :oops:

Ich denke, hier kann mir sicher einer schnell aus meinem Dilemma helfen.

Dank und Gruß oki

Uwe Raabe 10. Dez 2009 14:40

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Lass doch mal das @ weg:
Delphi-Quellcode:
system.Move(FReceivedData[0], SData[1], Length(FReceivedData));

oki 10. Dez 2009 14:49

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Hi,

dann meckert zwar der Compiler nicht mehr, aber in SData steht nur Müll. Auf jeden Fall nicht das, was in FReceivedData steht.

Gruß Oki

DeddyH 10. Dez 2009 14:55

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Und wenn Du das letzte SetLength einmal weglässt?
Delphi-Quellcode:
SetLength(SData, Length(FReceivedData));
system.Move(FReceivedData[0], SData[1], Length(FReceivedData));
//SetLength(FReceivedData, 0);

Uwe Raabe 10. Dez 2009 14:56

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Zitat:

Zitat von oki
dann meckert zwar der Compiler nicht mehr, aber in SData steht nur Müll. Auf jeden Fall nicht das, was in FReceivedData steht.

Dann gib doch mal folgendes bekannt:

Wie sind FReceivedData und SData deklariert?
Welche Delphi-Version setzt du ein?

oki 10. Dez 2009 15:00

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Hi Leute,

muss grad für 1,5 h weg. Hier noch schnell:

FReceiveData setze ich 0 um die empfangenen Daten zu löschen (hole sie mit Sdata ab). SData ist ein string, den ich mit den Daten als String hochreichen möchte. Manchmal empfange ich nur ASCII.

Gruß oki

p80286 10. Dez 2009 15:01

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Ich hab's mal für mich umgesetzt, so klappt es:

Delphi-Quellcode:
var
  i : integer;
  a1: array of byte;
  s1: string;
begin
  setlength(s1,50);
  setlength(a1,50);
  for i:=0 to 49 do a1[i]:=$20+i;
  move(a1[0],s1[1],50);
  showmessage(s1);
Gruß
K-H

himitsu 10. Dez 2009 15:10

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Wenn FReceivedData ein "Array of Byte" und SData ein "AnsiString" (oder Ähnliches) ist:
Delphi-Quellcode:
SData := AnsiString(Pointer(FReceivedData));
UniqueString(SData);
FReceivedData := nil;
Wobei das mit dem Move eigentlich auch funktionieren sollte :gruebel:
Delphi-Quellcode:
SetLength(SData, Length(FReceivedData));
MoveMemory(@SData[1], @FReceivedData[0], Length(FReceivedData));
FReceivedData := nil;
Bist du ganz sicher, daß "aber in SData steht nur Müll" an diesen Befehlen liegt?

Medium 10. Dez 2009 15:13

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Nur so am Rande: Move ist intern meine ich auch nichts weiter als eine Schleife über Bytes.

Uwe Raabe 10. Dez 2009 15:18

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Zitat:

Zitat von Medium
Nur so am Rande: Move ist intern meine ich auch nichts weiter als eine Schleife über Bytes.

Richtig, nur daß diese Schleife als ein einzelner OpCode realisiert und damit geringfügig schneller als eine ausprogrammierte Schleife ist.

Uwe Raabe 10. Dez 2009 15:23

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Zitat:

Zitat von oki
FReceiveData setze ich 0 um die empfangenen Daten zu löschen (hole sie mit Sdata ab). SData ist ein string, den ich mit den Daten als String hochreichen möchte. Manchmal empfange ich nur ASCII.

Das beantwortet leider nur einen Teil meiner Fragen - insbesondere nicht, welche Delphi-Version du einsetzt. Sollte das Ganze nämlich unter Delphi 2009/2010 laufen, funktioniert das Move eines ByteArray in einen String nämlich nicht, da die einzelnen Zeichen im String jeweils 2 Byte groß sind! Das würde auch deinen Müll erklären.

himitsu 10. Dez 2009 15:26

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Zitat:

Zitat von Medium
Nur so am Rande: Move ist intern meine ich auch nichts weiter als eine Schleife über Bytes.

Nein, Move wurde in "neueren" Delphis durch etwas aus'm FastCodeProjekt ersetzt und kopiert jetzt etwas optimaler. :stupid:

oki 10. Dez 2009 17:14

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Hallo Leute!

Erst mal Dank für die vielen Antworten während meiner Abwesenheit. Ich möchte gleich mal Stück für Stück antworten.


Zitat:

Zitat von p80286
Ich hab's mal für mich umgesetzt, so klappt es:

Delphi-Quellcode:
var
  i : integer;
  a1: array of byte;
  s1: string;
begin
  setlength(s1,50);
  setlength(a1,50);
  for i:=0 to 49 do a1[i]:=$20+i;
  move(a1[0],s1[1],50);
  showmessage(s1);
Gruß
K-H

Joop, genau das funzt nicht. Da ich etwas weiter gelesen habe denke ich, dass könnte mein Ansi-Problem sein. Sorry, hatte nicht dran gedacht Bescheid zu sagen, dass ich das grad unter D2010 teste.

@himitzu: Den Ansatz mit dem Casten werd ich mal testen. Ja, ich hab das mit dem Müll echt im Debugger geprüft. Aber auch hier wird mir sicher das D2010-Thema auf die Füße gefallen sein.

@Medium: Da Move mit asm-Code gestrickt ist hab ich einfach unterstellt, dass es schneller als eine eigene Schleife ist. Haben sich ja einige zu geäußert. Kann ich selber aber wenig zu sagen.

@Uwe Raabe: Danke für deinen Hinweis. Ich denke, da liegt der Hund begraben. Ich habe erst seit 1 Monat D2010 auf dem Rechner und hier jetzt gar nicht mehr an das UniCode-Thema gedacht. Ich glaube jetzt echt das ist der Fehler. Werde mal testweise SData als AnsiString definieren und den Move noch mal testen.

Ich mach jetzt mal meine Tests und sag dann Bescheid.

Dank und Gruß oki

oki 10. Dez 2009 17:23

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Joop, da war das Problem: Delphi2010 mit UniCode nicht beachtet. Hier der Code der klappt:
Delphi-Quellcode:
procedure TListenerThread.DoReceivedData;
var SData : AnsiString;
begin
  SData := '';
  if Assigned(FOnReceivedData) then begin
    if (FReceivedData <> nil) and (Length(FReceivedData) >= 200) then begin
      SetLength(SData, Length(FReceivedData));
      system.Move(FReceivedData[0], SData[1], Length(FReceivedData));
      SetLength(FReceivedData, 0);

      FOnReceivedData(self, SData);
    end;
  end;
end;
Hätte ich auch dran denken können.

Dank und Gruß an alle, die mir geholfen haben.

oki

himitsu 10. Dez 2009 17:31

Re: Inhalt eines dynamischen Array in einen String kopieren
 
tja, das Böse Unicode :nerd:

Zitat:

Den Ansatz mit dem Casten werd ich mal testen
Ein AnsiString ist auch "nur" ein erweitertes Array of Byte, mit einem zusätzlichen Feld (die #0) hinten drann.

Drum auch das UniqueString, wobei man hier auch ein Copy hätte nutzen können.
Anderrum String auf Byte-Array geht auch so (ohne UniqueString), da hier ein "zuviel" nicht stört. :angel:

oki 10. Dez 2009 17:35

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Hi himitzu, hatte das Casten getestet, aber die #0 in der Eile vergessen und damit erst mal verworfen. nach dem Casten hatte der String eine Länge 0 :( Ich denke mal das lag an der #0. Move funzt, ich denke, dass reicht mir. Hänge schon wieder in der nächsten Thematik :-D

Dank und Gruß oki

himitsu 10. Dez 2009 17:53

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Nimm ab Delphi 2009 statt dem AnsiString lieber den RawByteString für soetwas, denn dort wurde unter Anderem eine automatische CodePageUmwandlung eingeführt, welche für diesen String-Typen deaktiviert ist.

oki 10. Dez 2009 17:56

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Zitat:

Zitat von himitsu
Nimm ab Delphi 2009 statt dem AnsiString lieber den RawByteString für soetwas, denn dort wurde unter Anderem eine automatische CodePageUmwandlung eingeführt, welche für diesen String-Typen deaktiviert ist.

Und wieder was gelernt :lol:

Gruß oki

himitsu 10. Dez 2009 19:13

Re: Inhalt eines dynamischen Array in einen String kopieren
 
Arg, beim Test hab ich jetzt noch festgestellt, daß die Typeninfos von einem String auf einen Anderen übertragen werden können :wall:
(das macht überhaupt keinen Spaß :cry: )

z.B. würde man hinter R (also dem UTF8-String genannt "R(UTF)") auch UTF8-kodierte Zeichen vermuten/erwarten
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
type
  PStrRec = ^StrRec;
  StrRec = packed record
    codePage: Word;
    elemSize: Word;
    refCnt: Longint;
    length: Longint;
  end;

type
  TMyString = type AnsiString(28597); // ISO-8859-7 aka CodePage:28597
var
  R: RawByteString;
  A: AnsiString;
  M: TMyString;
  S1, S2, S3, S4, S5: String;

begin
  R := UTF8Encode('ÈÒú');
  A := 'ÈÒú';
  //M := 'ÈÒú';
  //M := #200#210#250;
  SetLength(M, 3); M[1] := #200; M[2] := #210; M[3] := #250;

  S1 := R;
  S2 := A;
  S3 := M;
  UniqueString(AnsiString(R));
  PStrRec(Integer(R) - SizeOf(StrRec)).codePage := CP_NONE;
  UniqueString(AnsiString(M));
  PStrRec(Integer(M) - SizeOf(StrRec)).codePage := CP_NONE;
  S4 := R;
  S5 := M;

  ShowMessage(Format('R(UTF) = %s'#10'A         = %s'#10'M(ISO) = %s'#10
    + 'R         = %s'#10'M         = %s', [S1, S2, S3, S4, S5]));
end;
Vielleicht erkennt man auch, was man für einen Aufwand hat, wenn man sich selber um die Kodierung oder Nicht-Kodierung kümmern möchte.

Gut, dafür kann man diese Automatik auch ausnutzen

früher (vor D2009) sah es so aus
Delphi-Quellcode:
Var S: WideString;
  D: {Ansi}String;

D := UTF8Encode(S);
jetzt (ab D2009) sieht es so aus
Delphi-Quellcode:
Var S: (Unicode)String;
  D: UTF8String;

D := S;
eigentlich würden hier ja die "asiatischen" Schriftzeichen nicht überleben:
Delphi-Quellcode:
var U: String;   // ist ein Unicode-String
  A: UTF8String; // ist intern nur ein AnsiString

U := #23456#34567#45678;
A := U;
ShowMessage(A);


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz