Autor Beitrag
thorbenZ
Hält's aus hier
Beiträge: 12



BeitragVerfasst: 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?

ausblenden Delphi-Quelltext
1:
2:
var
 s: ^string;


geht schonmal nicht. Schließlich kann ich ja mit

ausblenden 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:

ausblenden 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:

ausblenden 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:

ausblenden Delphi-Quelltext
1:
cnt: String[255];					


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 user profile iconMotzi: Topic Verschoben
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: 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.



Zitat:
Längenzähler

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


Zitat:
PChar
Pchar

Kannst du dich auch mal entscheiden, wie du PChar schreiben willst.

_________________
Ist Zeit wirklich Geld?
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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:
Zitat:
Längenzähler

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:
Zitat:
PChar
Pchar

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!