| Autor |
Beitrag |
thorbenZ
Hält's aus hier
Beiträge: 12
|
Verfasst: So 21.03.04 13:44
Hallo,
ich habe ein TListView und möchte jetzt jedem Item eine (lange) Zeichenkette zuordnen. Eigentlich möchte ich dafür gerne die Eigenschaft Data verwenden, nur habe ich da jetzt ein Problem: Wie kriege ich einen Pointer auf einen String gespeichert?
Delphi-Quelltext
geht schonmal nicht. Schließlich kann ich ja mit
Delphi-Quelltext 1:
| GetMem(s, sizeof(string)); |
auch keinen Speicher reservieren. Woher soll er schließlich wissen, wie lang das Ding wird?
Als Zeiger auf Strings, so fiel mir dann später ein, müsste doch PChar taugen. Also:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var s: PChar; begin s := 'Hallo Welt'; lstView.Selected.Data := s; ShowMessage(String(PChar(lstView.Selected.Data))); end; |
jetzt habe ich aber das Problem, dass vom PChar (und irgendwie nicht richtig nachvollziehbar) manchmal am Ende ein bis zwei Zeichen abgeschnitten werden, manchmal aber nicht.
Dann habe ich noch ein wenig rumprobiert und es so gemacht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TStringRecord = record cnt: String; end;
... var s: ^TStringRecord; begin GetMem(s, sizeof(TStringRecord)); s^.cnt := "Hallo Welt"; lstView.Selected.Data := s; s := lstView.Selected.Data; ShowMessage(s^.cnt); end; |
Das letzte Beispiel funktioniert interessanterweise - aber leider nur manchmal!!! Wenn ich den Dialog, indem das ganze vorkommt, mehrmals öffne und schließe, kommt irgendwann eine "ungültige Zeigeroperation". Wenn ich im Typ TStringRecord das Feld cnt so deklariere:
Delphi-Quelltext
herrscht plötzlich Chaos - keine Fehlermeldungen mehr, aber der String wird irgendwie chaotisch auseinandergepflückt.
--------------------
Ich frage Euch also, wenn Ihr euch diesen schrecklichen Beitrag schon angetan habt, wie Ihr einen String als Pointer irgendwo abspeichern würdet, oder ob euch zum Thema "ungültige Zeigeroperation" was einfällt. Delphi zeigt mir nämlich auch nicht, in welcher Zeile diese angeblich auftritt.
Vielen Dank
Thorben
Moderiert von Motzi: Topic Verschoben
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 21.03.04 14:01
Strings sind bereits Zeiger und PChars sehr ähnlich. Ich hab dazu vor kurzem ein String-Tutorial geschrieben, das die String-Internals behandelt. Du findest es unter www.manuel-poeter.de ... schau dir das mal an und schau ob du selbst die Lösung findest, sonst meld dich nochmal und ich helf dir auf die Sprünge.. 
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
MSCH
      
Beiträge: 1448
Erhaltene Danke: 3
W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
|
Verfasst: So 21.03.04 15:36
Dein Ansatz mit dem Record war schon gut, machs aber mit 'ner Class und dann hast du keine Probleme mehr:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| Type TMyClass = Class Inhalt: String; constructor Create(NewString: String); end;
constructor TMyClass.Create; begin Inhalt:= NewString; end;
.... lstView.Selected.Data := TMyClass.Create('Hallo du bist ein langer String'); ... ShowMessage(TMyClass(lstView.Selected.Data).Inhalt); ... |
grez
msch
_________________ ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 21.03.04 21:09
Der Weg über die Klasse ist vollkommen unnötig..! Ein String ist bereits ein Pointer, man muss diesen also nicht erst kompliziert in einen Record oder eine Klasse verpacken, sondern (über einen entsprechenden Typecast) gleich direkt zuweisen oder aber statt des Typecasts den @-Operator verwenden und die Adresse des Strings übergeben und dann entsprechend als PAnsiChar dereferenzieren..!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
thorbenZ 
Hält's aus hier
Beiträge: 12
|
Verfasst: So 21.03.04 21:10
Vielen Dank euch beiden. Ich habe die letzte Lösung erstmal so übernommen und es läuft. Das Tutorial werde ich mir bei Gelegenheit mal zu Gemüte führen, es scheint sehr interessant zu sein.
Thorben
|
|
MSCH
      
Beiträge: 1448
Erhaltene Danke: 3
W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
|
Verfasst: So 21.03.04 21:20
viel Spass
@Motzi,
solange du nur Strings nimmst, mag es gehen; aber was ist, wenn du mehr als ein String verwerten willst, oder den String validieren möchtest? Schreibst du dann jedesmal eine Prüfroutine, oder kapselst du das gleich in eine eigene Klasse? Du hast doch eine selbst eine 19 seitige Ausarbeitung zur objektorientierten Programmierung in Pascal geschrieben.
Einer der Vorteile gegenüber C* ist ja, dass das ganze Zeiger-Geraffe quasi unsichtbar ist, warum den dann mit @ und ^ noch viel rumexperimentieren?
grez
msch
_________________ ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 21.03.04 21:34
| MSCH hat folgendes geschrieben: | @Motzi,
solange du nur Strings nimmst, mag es gehen; aber was ist, wenn du mehr als ein String verwerten willst, oder den String validieren möchtest? Schreibst du dann jedesmal eine Prüfroutine, oder kapselst du das gleich in eine eigene Klasse? Du hast doch eine selbst eine 19 seitige Ausarbeitung zur objektorientierten Programmierung in Pascal geschrieben.
Einer der Vorteile gegenüber C* ist ja, dass das ganze Zeiger-Geraffe quasi unsichtbar ist, warum den dann mit @ und ^ noch viel rumexperimentieren? |
Gut, für mehrere Strings oder andere Kombinationen mag das stimmen..! In so einem Fall ist man mit einer Klasse sicher besser beraten, aber solange es nur um einen einzigen simplen String geht würde ich trotzdem den direkten Weg über ein simples Typecasting Pointer(String) gehen...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
AndyB
      
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: So 21.03.04 23:56
| Motzi hat folgendes geschrieben: | | Ich hab dazu vor kurzem ein String-Tutorial geschrieben, das die String-Internals behandelt. |
Dazu kann ich noch folgende "Kritik" geben:
| Zitat: | Es gibt also kein Längenbyte mehr,
sondern der String kann (theoretisch) beliebig lang werden, vorrausgesetzt, es kommt
dazwischen kein Nullzeichen vor. |
Das mit dem Nullzeichen stimmt nicht, wie du weiter unten im Text dann auch klar stellst. Ein String kann auch eine gesamte Exe-Datei mit beliebig vielen Nullzeichen aufnehmen. Wenn er aber an eine Funktion übergeben wird, die einen PChar (ohne zusätzliche Längenangabe) erwartet, so geht die Längeninformation verlohren und das Nullzeichen terminiert.
| Zitat: | 1. “normaler” Parameter
2. const-Parameter
3. var-Parameter
4. als Pointer |
Hier fehlt noch "out", bei dem der Compiler noch etwas einfügt, das du noch herausfinden musst.
Was zählt der Längenzähler denn? Die Längen des Strings? Ich dachte ein String hat nur eine Länge. Ich würde das eher als Längenfeld (es steckt ja auch ein record dahinter) oder Längenangabe bezeichnen
Kannst du dich auch mal entscheiden, wie du PChar schreiben willst.
_________________ Ist Zeit wirklich Geld?
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 22.03.04 00:15
| AndyB hat folgendes geschrieben: | | Zitat: | Es gibt also kein Längenbyte mehr,
sondern der String kann (theoretisch) beliebig lang werden, vorrausgesetzt, es kommt
dazwischen kein Nullzeichen vor. |
Das mit dem Nullzeichen stimmt nicht, wie du weiter unten im Text dann auch klar stellst. Ein String kann auch eine gesamte Exe-Datei mit beliebig vielen Nullzeichen aufnehmen. Wenn er aber an eine Funktion übergeben wird, die einen PChar (ohne zusätzliche Längenangabe) erwartet, so geht die Längeninformation verlohren und das Nullzeichen terminiert. |
Naja, es kommt immer darauf an wie man es betrachtet.. beim Ausgeben wird der String beim Nullzeichen beendet...
| Zitat: | | Zitat: | 1. “normaler” Parameter
2. const-Parameter
3. var-Parameter
4. als Pointer |
Hier fehlt noch "out", bei dem der Compiler noch etwas einfügt, das du noch herausfinden musst. |
Stimmt, out-Parameter hab ich nicht behandelt.. füg ich vielleicht noch dazu..
| Zitat: |
Was zählt der Längenzähler denn? Die Längen des Strings? Ich dachte ein String hat nur eine Länge. Ich würde das eher als Längenfeld (es steckt ja auch ein record dahinter) oder Längenangabe bezeichnen |
Hm.. werd ich vielleicht ändern..
| Zitat: |
Kannst du dich auch mal entscheiden, wie du PChar schreiben willst. |
Das liegt an der automatischen Korrektur vom Word.. dachte eigentlich ich hätte alles auf "PChar" ausgebessert..
Aber danke für deine Kritik!! 
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
|