Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Problem mit #0 im String (https://www.delphipraxis.net/133226-problem-mit-0-im-string.html)

R2009 28. Apr 2009 08:36


Problem mit #0 im String
 
Hi DP'ler,

ein kleines Problem:
In edit1 steht Hex (z.B. 0C4B3A). In edit2 soll nacher der Text als solches stehen.
Problem:
Sobald in edit1 eine "00" (Beispiel: 0C54003A übrig bleibt nur oC54) auftaucht geht der Rest des Strings bei der Zuweisung zu edit2 verloren.
Da edit2 aber nur ein "Zwischenspeicher" für den String ist darf das keinesfalls passieren.
Hat jemand eine Idee? (INVHEXB ist eine Funktion von mir und funktioniert einwandfrei)

Delphi-Quellcode:
  b:=edit1.text;
  a:='';
  while length(b)>1 do
    Begin
      t:=INVHEXB(b[1]+b[2]);
      a:=a+chr(t);
      delete(b,1,2);
    end;
  edit2.Text:=a;
Danke im Vorraus!

taaktaak 28. Apr 2009 08:43

Re: Problem mit #0 im String
 
Moin, Moin.
Zitat:

In edit1 steht Hex (z.B. 0C4B3A). In edit2 soll nacher der Text als solches stehen.
Hmmm, verstehe ich nicht: In Edit1 ist ein String und der soll nach Edit2? Wozu der Umweg? Was passiert da? Und wieso ist die Zahl 0 = #0?? 0=#48!!

chaosben 28. Apr 2009 08:43

Re: Problem mit #0 im String
 
Tschaaa ... was soll man dazu sagen.

Sobald du eine binäre 0 im String hast, ist für die meisten Delphi-String-Routinen (und imho 99% aller anderen Sprachen + Windows) der String beendet. Das ist so eine Art Naturgesetz.

Um die Null darzustellen musst du dir irgendetwas einfallen lassen.

//Edit: obiger Text wurde dem revidierten Wissenstand angepasst :)

Zoot 28. Apr 2009 08:44

Re: Problem mit #0 im String
 
Du solltest deine InvHexB so umschreiben, dass sie für alle Steuerzeichen (0..31) eine Sonderbehandlung durchführt, sonst wirst du keinen Spass daran haben.

taaktaak 28. Apr 2009 08:48

Re: Problem mit #0 im String
 
... und wie kommt #0 in das EditFeld hinein?
Bevor ich die Symptome kuriere,
wäre es doch besser die Ursache zu beseitigen, oder?

Satty67 28. Apr 2009 08:59

Re: Problem mit #0 im String
 
Zitat:

Zitat von chaosben
Das ist so eine Art Naturgesetz.

Nicht ganz...
Delphi-Quellcode:
s := '1234'#0'6789';
Edit1.Text := s; // Anzeige 1234
ShowMessage(IntToStr(Length(s))); // 9!
String ist in Delphi durchaus in der Lage, auch #0 aufzunehmen, ohne die Länge zu kürzen. Nur Edit.Text ist wohl am Ende ein PChar, das dann bei der Anzeige tatsächlich abgeschnitten wird.

sirius 28. Apr 2009 09:01

Re: Problem mit #0 im String
 
Wie? Du benutzt Edit2 nur als Zwischenspeicher?

@Chaosben
Die Delphi-Strings haben ja gerade die Besonderheit sich nicht an einer #0 zu stören. Solange man auch nur mit DelphiStrings arbeitet ist das auch kein Problem. Nur die Übergabe zu dem von Windows verwalteten Edit erfolgt über PChar. Und erst da wird der String gekürzt.

chaosben 28. Apr 2009 12:10

Re: Problem mit #0 im String
 
Ja, ok ... das Obige war nicht korrekt.

Strings können auch 0-Zeichen enthalten. Die Einschränkung ist eben nur, das 90% der String-Routinen hintenrum auf PChars basieren und deswegen mit 0-Zeichen nichts anfangen können.

Und in diesem Fall gehts nicht, weil der Text eines Fenster/Edits per PChar gesetzt wird.

R2009 29. Apr 2009 06:31

Re: Problem mit #0 im String
 
Hi,

ich wollte hier keine Diskussion anfangen warum ich das so oder so mache!

Hier nocheinmal eine kurze Erläuterung zur Problematik:
Beispiel:
ich muss den als Hex-Code voliegenden String zu einem Gerät binär übertragen (bei uns sind das Rundsteuerempfänger).
Hex als char
30313233 -->'0123'
das kann ich ohne weiteres übernehmen, kommt ja keine absolute 0 drin vor.
Sobald ich 30310033 übertragen will krieg ich nur noch 3031, weil ja plötzlich im zu sendenden String eine '0' steht.
'01'#0'2'
Dass da Nullen vorkommen ist ein 'Naturgesetz' und nicht umgehbar! Das Übertragungsprotokoll kann ich auch nicht ändern!
Wie machen das eigentlich die "C" Freaks?

Ich habe die Edit-felder gegen 'normale' Strings ausgetauscht jetzt funktioniert das alles.

Was mich stört ist:
Wieso wird der String in tedit (tedit.text ist nichts anderes als ein String) anders behandelt als ein normaler String.
Das ist doch Sch.... oder?

Für alle die immer alles besser wissen:
Die edit-Felder hab ich nur benutzt um zu sehen was passiert. Da das Ganze mit einer hohen Dynamik abläuft
kommt der Debugger nicht in Frage. Hab mir halt auf diese Art beholfen.

Vielen Dank für alle konstruktiven Beiträge!

Satty67 29. Apr 2009 06:58

Re: Problem mit #0 im String
 
Zitat:

Zitat von R2009
Was mich stört ist:
Wieso wird der String in tedit (tedit.text ist nichts anderes als ein String) anders behandelt als ein normaler String.
Das ist doch Sch.... oder?

Also zur Speicherung der binären Daten hast Du jetzt einen Datentyp genommen, der auch alle binären Zeichen speichern kann (Delphi-String, array of Byte wäre auch gegangen etc.)

Zur Anzeige musst Du die Daten aber aufbereiten, also Zeichen 0-31 und 127 ersetzen (Parser). Den TEdit.Text wurde zwar in Delphi als String implementiert, ist aber eigentlich ein PChar (das eben keine #0 als Datenbestandteil aufnehmen kann). Das kann mit dem Standard TEdit auch nicht geändert werden, ist ja ein Windows-Objekt.

Der einfachste Weg wäre, zur Datenspeicherung/Übermittlung Deine funktionierende Lösung und zur Anzeige den String aufbereiten.

#0 = '<NUL>'
...
#127 = '<ESC>'

alzaimar 29. Apr 2009 07:14

Re: Problem mit #0 im String
 
Das ist mal wieder ein typischer Anwendungsfall von 'Trenne Funktion und Darstellung'.

Die Funktion (hier: HEX->binär) funktioniert, mur für die Darstellung muss man eine andere Form wählen (z.B. wie Satty67 es vorgeschlagen hat).

Falsch im Sinne des o.g. Paradigmas ist es, ein Darstellungselement (Edit2) als Funktionselement zu verwenden (Zwischenspeicher).

R2009 5. Mai 2009 06:32

Re: Problem mit #0 im String
 
Hi alzaimar,

Zitat:

Falsch im Sinne des o.g. Paradigmas ist es, ein Darstellungselement (Edit2) als Funktionselement zu verwenden (Zwischenspeicher).
Im Prinzip stimme ich dir zu!
Ich finde es halt schade, dass an dieser Stelle plötzlich die Philosophie (interne Darstellung von Variablen) einfach gewechselt wird.
Ich bin davon ausgegangen, dass in Object pascal, alle Strings auch als "Delphi Strings" behandelt werden.
Wer kommt denn auf die Idee, dass da plötzlich mit "0" terminierten Strings operiert wird.
Das hat nichts mit Darstellungs oder Funktionselementen zu tun sondern mit der Konsequenz mit der eine Programmiersprache
realisiert wird.

Viele Grüsse

Bernhard Geyer 5. Mai 2009 06:37

Re: Problem mit #0 im String
 
Zitat:

Zitat von R2009
Ich finde es halt schade, dass an dieser Stelle plötzlich die Philosophie (interne Darstellung von Variablen) einfach gewechselt wird.
Ich bin davon ausgegangen, dass in Object pascal, alle Strings auch als "Delphi Strings" behandelt werden.
Wer kommt denn auf die Idee, dass da plötzlich mit "0" terminierten Strings operiert wird.

Delphi hat bei Strings schon eine durchgehende Philosophie. Da jedoch alle Controls (TEdit, ...) nur Wrapper um die entsprechenden Win32-API-Controls sind wird auf dieser Ebene zwangsweise #0 als Trenner angesehen da die Win32-API eine C-Kompatible schnittstelle darstellt. Und dort heißt nunmal #0 = String-Ende

Satty67 5. Mai 2009 06:42

Re: Problem mit #0 im String
 
Zitat:

Zitat von R2009
Wer kommt denn auf die Idee, dass da plötzlich mit "0" terminierten Strings operiert wird.

Das ist die Forderung des ComControl von Windows, da kann Delphi nichts dafür. Windows arbeitet schon immer mit NUL-terminierten Strings, ich glaube nicht, dass das irgendwann einmal unter Windows ging. :gruebel:

Delphi übergibt an das Windows-Element evtl. sogar ein '1234'#0'6789'#0#0. Nur schneiden Windows Funktion den String vor seiner Sichtbarkeit ab. Ich bin sogar relativ sicher, dass Du in keiner Programmiersprache ein #0 in einem Windows-Edit sichtbar machen kannst.

R2009 5. Mai 2009 07:07

Re: Problem mit #0 im String
 
Hi,

Bernhard Geyer schrieb:
Zitat:

nur Wrapper um die entsprechenden Win32-API-Controls
OK, das muss man wissen.
Was mich stört ist weniger, dass man die "0" nicht sieht, (damit hab ich gerechnet)
Mich stört, dass wenn ich edit1.text einen String zuweise der eine "0" enthält entweder die Setter Methode oder die Getter Methode den Rest abschneidet.
Täusch ich mich oder ist das Object Pascal?
Oder existiert edit1.text als String überhaupt nicht?
Das heisst wird das direkt dem Windows Steuerelement zugewiesen und von da auch wieder geholt?

Naja eine einfache Lösung hab ich jetzt ich stelle die Dinge halt in Hex dar.

Vielen Dank!

mkinzler 5. Mai 2009 07:10

Re: Problem mit #0 im String
 
Ist aus der Vererbungshierarchie ersichtlich -> TWinControl

Bernhard Geyer 5. Mai 2009 07:32

Re: Problem mit #0 im String
 
Zitat:

Zitat von R2009
Bernhard Geyer schrieb:
Zitat:

nur Wrapper um die entsprechenden Win32-API-Controls
OK, das muss man wissen.

Das war ja die Absicht der VCL. Die Kapslung der Win32 möglichst gut durch zuführen.
Aber auch wenn es ein Wrapper um KDE oder MacOS-Controls wäre, würde zu 99,9% das gleiche passieren.

generic 5. Mai 2009 08:30

Re: Problem mit #0 im String
 
Eigentlich ist das Thema hier, die aus C bekannten Null terminierten Strings.
Das #0 Zeichen gibt das Ende des Strings an.
Bei Pascalstrings steht die Länge des Strings vor dem ersten Zeichen im Speicher.
Da Windows in C geschrieben ist, kommt das #0 zum Tragen bei der Anzeige.

Delphi hat C kompatible Strings. Diese haben wie Pascal die Länge vor dem ersten Zeichen gespeichert und Terminieren noch zusätzlich den String mit #0.
Daher kann die Windows API so Klasse angesprochen werden.

QuickAndDirty 5. Mai 2009 08:33

Re: Problem mit #0 im String
 
Gibt es eine fertige C-Escape Funktion? Also eine Funktion die automatisch alles was in C-Escaped werden muss in einem PChar mit vernünftigen Escape Zeichen umwandelt?

'c:\dummesBeispiel\' -> 'c:\\dummesBeispiel\\'
'Meintext'#9'deintext' -> 'Meintext\tdeintext'
#0 -> '\0'
&c.

thkerkmann 5. Mai 2009 09:10

Re: Problem mit #0 im String
 
Das würde dir auch nicht helfen, da das nur die Darstellung für den Compiler ist, und nicht die interne binäre Speicherung.

QuickAndDirty 5. Mai 2009 09:14

Re: Problem mit #0 im String
 
Stimmt ja.
gibt es keinen offiziellen standard wie man 0 in C Strings verpackt?
Funktioniert '^A' ?

Medium 5. Mai 2009 09:20

Re: Problem mit #0 im String
 
Steuerzeichen sind Steuerzeichen. Selbst WENN #0 einen String nicht abschneiden würde, gäbe es kein darstellbares Zeichen dafür, wie auch für die meisten der unteren ASCII Zeichen. Sie sind eben nicht dafür gedacht, waren es auch nie und nirgends. End of Story.
Daher ist es auch seit Anbeginn aller Tage ein no-go Binärdaten in Strings zu halten. Dafür gibt es Arrays und Streams.

Bernhard Geyer 5. Mai 2009 09:26

Re: Problem mit #0 im String
 
Zitat:

Zitat von QuickAndDirty
gibt es keinen offiziellen standard wie man 0 in C Strings verpackt?

Gibt es. Es geht einfach nicht! Ein C-String kann kein #0 beinhalten. Was du meinst wäre Escapen. Und dort gibt es viele Lösungsmöglichkeiten. Einer ist. z.b. die Darstellung als Hex für den gesamten String. WinMerge als alternative nimmt hierfür ein eigenes Glyph, Hex-Editoren stellen alle Zeichen < #$20 z.B. teilweise nur als "." dar, ...

Satty67 5. Mai 2009 09:50

Re: Problem mit #0 im String
 
Zur Visualisierung kann man sich ja auch schnell was basteln:
Delphi-Quellcode:
function VisualizeASCII(Text : String; SpaceToo : Boolean) : String;
const
  ASCII_Codes : array[#0..#31] of String = (
    '<NUL>', '<SOH>', '<STX>', '<ETX>', '<EOT>', '<ENQ>', '<ACK>', '<BEL>',
    '<BS>', '<TAB>', '<LF>', '<VT>', '<FF>', '<CR>', '<SO>', '<SI>', '<DLE>',
    '<DC1>', '<DC2>', '<DC3>', '<DC4>', '<NAK>', '<SYN>', '<ETB>', '<CAN>',
    '[i]', '<SUB>', '<ESC>', '<FS>', '<GS>', '<RS>','<US>');
  DEL_Code = '<DEL>';
  SPACE_Code = '<SPACE>';
var
  i : Integer;
begin
  Result := '';
  for i := 1 to Length(Text) do
    case Text[i] of
      #0..#31 : Result := Result + ASCII_Codes[Text[i]];
      #32  : if SpaceToo then Result := Result + SPACE_Code
               else Result := Result + ' ';
      #127 : Result := Result + DEL_Code;
    else
      Result := Result + Text[i];
    end;
end;
Bei Bedarf auch #32 als <SPACE> ...€: Done
€2: 127 ist DEL nicht ESC :oops:

generic 5. Mai 2009 15:32

Re: Problem mit #0 im String
 
Zitat:

Zitat von R2009
Wie machen das eigentlich die "C" Freaks?

Die Übertragen/Empfangen Bytes und keine Strings.
Es wird nur zur Einfachheit das oft als String dargestellt.

Gelegentlich werden auch andere Endzeichen genutzt. Aber das kommt auf das Protokoll an.

QuickAndDirty 5. Mai 2009 15:42

Re: Problem mit #0 im String
 
Zitat:

Zitat von Bernhard Geyer
Zitat:

Zitat von QuickAndDirty
gibt es keinen offiziellen standard wie man 0 in C Strings verpackt?

Gibt es. Es geht einfach nicht! Ein C-String kann kein #0 beinhalten. Was du meinst wäre Escapen. Und dort gibt es viele Lösungsmöglichkeiten. Einer ist. z.b. die Darstellung als Hex für den gesamten String. WinMerge als alternative nimmt hierfür ein eigenes Glyph, Hex-Editoren stellen alle Zeichen < #$20 z.B. teilweise nur als "." dar, ...

Man könnte auch gleich alles base64 codiert übertragen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:04 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