| Autor |
Beitrag |
TomPIII866
      
Beiträge: 27
|
Verfasst: Do 08.05.08 22:57
Hallo!
Ich habe eine ListBox. In dieser stehen in jeder Zeile solche Strings wie:
Aussenkontur nach: 0; 40
Aussenkontur nach: 40; 300
Aussenkontur nach: 300; 0
So, jetzt möchte ich immer den vorletzen Eintrag der Listbox auslesen.
Soweit, so gut, hier im Bsp. wäre das also 'Aussenkontur nach: 40; 300'.
Nun möchte ich den Variablen nextep_x und nextep_y die beiden Werte zuweisen, also 40 und 300.
Ich habe es wie folgt gelöst:
Delphi-Quelltext 1: 2: 3:
| s := listbox_kontur.Items[listbox_kontur.Items.Count - 2]; nextep_x := strtoint(Copy(s, Pos(':', s) + 2, Pos(';', s) - Pos(':', s) + 2)); nextep_y := strtoint(Copy(s, Pos(';', s) + 1, Length(s))); |
Aber leider funktioniert das nicht so, wie es soll.
Könnt ihr mir helfen, die richitge Lösung zu finden?
Danke!
Tom
Moderiert von AXMD: Code- durch Delphi-Tags ersetzt
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: Do 08.05.08 23:14
"Geht nicht" ist KEINE Fehlerbeschreibung!
Was genau funktioniert nicht? Was steht denn hinterher in den Variablen? Lass erstmal das StrToInt weg, und schau, dass der String wenigstens stimmt.
|
|
Grenzgaenger
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 08.05.08 23:48
mal davon abgesehen, wie kommen die strings eigentlich in die listbox?
evtl. kann man bei der aufnahme der items in die listbox, diese auch gleich noch mit dranhängen ... dann ersparst du dir die ganze konvertiererrei ...
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 09.05.08 08:08
Generell sollte man Datenhaltung und Datendarstellung von einander trennen, dann hat man solche Probleme erst gar nicht.
|
|
oldmax
      
Beiträge: 380
D3 Prof, D4 Prof
|
Verfasst: Fr 09.05.08 08:29
Hi
Wenn du in jede Zeile "Aussenkontur nach:" scheibst, dann kannst du gleich ein Label über die Listbox setzen und die Caption mit "Aussenkontur nach:" belegen.
Nun fällt das Wegkopieren vom Text schonmal weg und es ist trotzdem klar, was die Zahlen bewirken....
Nachtrag:
Etwas aufwändiger, aber besser wäre ein Stringgrid zu benutzen und von vorn herein Werte in eine x-Spalte und eine y-Spalte einzutragen.
Gruß oldmax
_________________ Zier dich nich so, ich krieg dich schon....
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Fr 09.05.08 08:43
Danke für eure ganzen Antworten!
Das "Aussenkontur nach: " kann ich nicht drüber schrauben, da manchmal auch andere Beschreibungen in der Listbox stehen.
Der Nutzer kann Werte eingeben und diese werden dann in die Listbox geschrieben.
Das "Aussenkontur nach: " wird automatisch vor diese eigegebenen Werte gesetzt.
Hier mal die Werte, die er mir bei dem o.g. Quelltext ausgibt:
s: 'Aussenkontur nach: 400; 50' --> das stimmt
nextep_x: '400; 50' --> kein gültiger Integer, eigentlich soll er '400' auslesen --> Abbruch
Der mit der Trennung von Datenspeicherung und Datenanzeige finde ich gut.
Wie sollte ich eurer Meinung nach die Daten denn am Besten speichern, um einfach darauf zugreifen zu können?
Wäre es sinnvoll, sie in ein dynamisches Array zu speichern, das immer nur so groß ist, wie Eingaben von Wertepaaren existieren?
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 09.05.08 09:34
Das hängt von dem Aufbau deiner Daten ab. Wenn ich eine List habe, mache ich es meist so, dass jedes Element ein Objekt ist, welche in einer Containerklasse (der Liste) verwaltet werden: www.michael-puff.de/...ontainer_Klassen.php
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Sa 10.05.08 11:43
Hab das jetzt erstmal mit einem dynamischen Array probiert.
Das Array soll 3 Spalten haben und eben soviele Zeilen, wie benötigt.
Deklaration:
Delphi-Quelltext 1:
| history : array of array [0..2] of String; |
So, dann kann der Nutzer Werte eingeben, die dann in das Array geschrieben werden sollen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| SetLength(history, Length(history) + 1); if aussenkontur = True then history[0, High(history)] := 'Aussenkontur' else history[0, High(history)] := 'Innenkontur'; history[1, High(history)] := inttostr(nextep_x); history[2, High(history)] := inttostr(nextep_y); |
Und dann soll immer die letzte Zeile in die ListBox geschrieben werden:
Delphi-Quelltext 1:
| listbox_kontur.Items.Add((history[0, High(history)]) + ' nach: ' + (history[1, High(history)]) + '; ' + (history[2, High(history)])); |
Aber komischerweise gibt er mir beim Springen von der letzten Zeile des Schreibzugriffes aufs Array auf die Zeile zum schreiben in die ListBox immer folgende Fehlermeldung aus:
"Exception der Klasse EAccessViolation mit der Meldung "Zugriffsverletzung bei Adresse 00404722 im Modul 'Dateiname'. Lesen von Adresse 352C382A aufgetreten."
Woran liegt das?
Danke für eure Hilfe!
Tom
Moderiert von AXMD: Code- durch Delphi-Tags ersetzt
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Sa 10.05.08 11:55
Ich hab den Fehler gefunden:
Muss ja natürlich erstmal
SetLength(history, 1)
setzen. 
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 10.05.08 15:28
TomPIII866 hat folgendes geschrieben: | Delphi-Quelltext 1:
| SetLength(history, Length(history) + 1); | |
Das ist ein Perfomancekiller. Wenn der Speichermanager von Delphi ein dynamisches Array vergrößert, reserviert er neuen, zusammenhängenden Speichern, der um ein Element größer ist das ursprüngliche Array (Jetzt auf deinen Fall bezogen.) und kopiert dann den Inhalt des ursprünglichen Arrays in das neue.
Besser ist es ungefähr abzuschätzen wie viele Elemente gebraucht werden und dann gleich das Array auf diese Größe zu setzen. Braucht man dann noch Platz für weitere Elemente vergrößert man das Array gleich um mehrere Elemete. Um wie viele Elemente du es vergrößert, musst du selber rausfinden. Als Richtwert kann man so 20% bis 25% Prozent nehmen, um die man es vergrößern sollte.
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Mi 14.05.08 19:12
Ich muss nochmal was fragen, denn ganz so gut klappt es noch nicht.
Wahrscheinlich ist meine Array-Deklaration falsch.
Wie deklariert ihr denn ein dynamisches Array mit beliebig vielen Zeilen und drei Spalten?
Die Anzahl der Zeilen weise ich dann über SetLength zu.
Oder kann ich auch gleich in der Deklaration 50 Zeilen angeben, die ich dann aber beliebig erweitern kann?
Würde das dann so machen, wie Lucky es sagte, also immer gleich um 20% "verlängern".
Danke! 
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Mo 19.05.08 19:09
keiner ne Idee? 
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Mo 19.05.08 19:19
TomPIII866 hat folgendes geschrieben: |
Wie deklariert ihr denn ein dynamisches Array mit beliebig vielen Zeilen und drei Spalten?
Die Anzahl der Zeilen weise ich dann über SetLength zu. |
Via SetLength in etwa so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| ar: Array[1..3] of Array of String;
... SetLength(ar[1], 10); SetLength(ar[2], 10); ar[1][0] := 'ABC'; ar[2][4] := 'BED'; |
€: Hattest Du das nicht bereits so? Habe ich was übersehen?
Ich habe leider vor dem Posten die die anderen Antworten nur überflogen.
Grüße,
Marc
Zuletzt bearbeitet von Marc. am Mo 19.05.08 19:23, insgesamt 1-mal bearbeitet
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 19.05.08 19:23
Moin!
TomPIII866 hat folgendes geschrieben: | | Wie deklariert ihr denn ein dynamisches Array mit beliebig vielen Zeilen und drei Spalten? |
Dreh das Ding doch mal im Geiste im 90°, dann hast du drei Zeilen mit beliebig vielen Spalten.  Das sollte für deinen Ansatz leichter sein.
TomPIII866 hat folgendes geschrieben: | | Würde das dann so machen, wie Lucky es sagte, also immer gleich um 20% "verlängern". |
Ich würde mir diesen ganzen Verwaltungskram gar nicht erst ans Bein binden, sondern die schon existierenden Implementationen davon verwenden, z.B. eine TObjectList:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| type THistoryElement = class(TObject) private FAussenkontur: Boolean; FStepX, FStepY: Integer; protected function GetLogStr: String; public constructor Create(const AAussenkontur: Boolean; const StepX, StepY: Integer); property Aussenkontur: Boolean read FAussenkontur write FAussenkontur; property StepX: Integer read FStepX write FStepY; property StepY: Integer read FStepY write FStepY; property LogStr: String read GetLogStr; end;
var History: TObjectList;
History.Add(THistoryElement.Create(True,123,456));
for i := 0 to History.Count-1 do ShowMessage(THistoryElement(History.Items[i]).LogStr); | So mal als Grobansatz, ist so nicht lauffähig, die Klasse ist nicht komplett implementiert.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
TomPIII866 
      
Beiträge: 27
|
Verfasst: Di 20.05.08 08:08
Danke für die zwei super Ansätze!
Da probiere ich heute gleich mal etwas herum...
Viele Grüße!
Tom
|
|
ZeitGeist87
      
Beiträge: 1593
Erhaltene Danke: 20
Win95-Win10
Delphi 10 Seattle, Rad Studio 2007, Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP, Delphi X2
|
Verfasst: Di 20.05.08 08:53
Auch wenn es eventuell jetzt irrelevant ist, hier mal eine schnell gebaute Funktion, mit Ausgangsbasis deines Lösungsansatzes:
Funktionsdeklaration
Delphi-Quelltext 1:
| parseKontur(Zeichenkette: String; var X: Integer; var Y: Integer): Boolean; |
Die Funktion selbst
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| function TForm_Main.parseKontur(Zeichenkette: String; var X: Integer; var Y: Integer): Boolean; var erg: String; str_x, str_y: String; begin
parseKontur:= false;
str_x:= copy(Zeichenkette, pos(':', Zeichenkette)+2, (pos(';', Zeichenkette)-pos(':', Zeichenkette))-2);
str_y:= copy(Zeichenkette, pos(';', Zeichenkette)+2, length(Zeichenkette) - pos(';', Zeichenkette));
str_x:= trim(str_x); str_y:= trim(str_y);
if not trystrtoint(str_x, x) then begin parseKontur:= false; exit; end;
if not trystrtoint(str_y, y) then begin parseKontur:= false; exit; end;
parseKontur:= true;
end; |
Ein möglicher Funktionsaufruf
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForm1.Button1Click(Sender: TObject); var x, y: integer; begin if parseKontur(liste.Items.strings[2], x, y) then end; |
LG
Stefan
_________________ Wer Provokationen, Ironie, Sarkasmus oder Zynismus herauslesen kann soll sie ignorieren um den Inhalt meiner Beiträge ungetrübt erfassen zu können.
|
|
|