Autor Beitrag
TomPIII866
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



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

ausblenden 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 user profile iconAXMD: Code- durch Delphi-Tags ersetzt
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: 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



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



BeitragVerfasst: Fr 09.05.08 08:08 
Generell sollte man Datenhaltung und Datendarstellung von einander trennen, dann hat man solche Probleme erst gar nicht.
oldmax
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 380


D3 Prof, D4 Prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



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



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
//Werte in das History-Array schreiben
          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:
ausblenden 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 user profile iconAXMD: Code- durch Delphi-Tags ersetzt
TomPIII866 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



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



BeitragVerfasst: Sa 10.05.08 15:28 
user profile iconTomPIII866 hat folgendes geschrieben:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Mo 19.05.08 19:09 
keiner ne Idee? :(
Marc.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1876
Erhaltene Danke: 129

Win 8.1, Xubuntu 15.10

BeitragVerfasst: Mo 19.05.08 19:19 
user profile iconTomPIII866 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:
ausblenden 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?:gruebel:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 19.05.08 19:23 
Moin!

user profile iconTomPIII866 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.

user profile iconTomPIII866 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: :idea:

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

// Werte in die History-Liste schreiben
  History.Add(THistoryElement.Create(True,123,456));

// Ausgabe
  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. :nixweiss:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
TomPIII866 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1593
Erhaltene Danke: 20

Win95-Win10
Delphi 10 Seattle, Rad Studio 2007, Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP, Delphi X2
BeitragVerfasst: 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
ausblenden Delphi-Quelltext
1:
parseKontur(Zeichenkette: String; var X: Integer; var Y: Integer): Boolean;					


Die Funktion selbst

ausblenden volle Höhe 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:
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

 //Standardfunktionsrückgabe
 parseKontur:= false;

 //X extrahieren
 //                             +2, da auf : ein Leerzeichen folgt         -2 analog zu +2
 str_x:= copy(Zeichenkette, pos(':', Zeichenkette)+2, (pos(';', Zeichenkette)-pos(':', Zeichenkette))-2);

 //Y extrahieren
 str_y:= copy(Zeichenkette, pos(';', Zeichenkette)+2, length(Zeichenkette) - pos(';', Zeichenkette));


 //Mögliche Leerzeichen entfernen
 str_x:= trim(str_x);
 str_y:= trim(str_y);

 //Umwandeln (Versuch)
 if not trystrtoint(str_x, x) then
 begin
  parseKontur:= false;
  exit;
 end;

 //Umwandeln (Versuch)
 if not trystrtoint(str_y, y) then
 begin
  parseKontur:= false;
  exit;
 end;

 //Erfolgreich
 parseKontur:= true;

end;



Ein möglicher Funktionsaufruf
ausblenden 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
  //Verarbeitung
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.