Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jul 05, 2025 10:32

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: TStrings anstatt Memo zum auslesen
BeitragVerfasst: Di Feb 17, 2009 11:11 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
Hallöchen mal wieder^^,

also ich hatte nun eine kurze Pause eingelegt und wollte eigentlich gestern schon weitermachen (aus diversen Gründen tu ich es aber erst heute^^).

Ich hatte vor kurzem eine Variable vom Typ TStrings angelegt, die mein Programm als Speicher dient (SaveToFile, LoadFromFile, muss ich glaube nicht weiter erklären).
Nun kam jedesmal einen Fehler bezüglich irgendwelcher sinnlosen Adressen und hab auch einiges ausprobiert das zu umgehen... ERFOLGLOS... (Konstruktor hab ich auch schon verwendet, wobei das ebenfals einen Fehler ausspruckt, genauso wie alles andere was irgendwie mit dieser Variable zusammenhängt.)
Also hab ich die Delphi-Hilfe aufgerufen und das hier entdeckt:
"[...] TStrings enthalten abstrakte bzw. rein virtuelle (C++ Terminologie) Methoden und sollten nicht direkt instantiiert werden. [...]"
Wenn ich das richtig verstehe, dann soll man also keine Variablen direkt vom Typ TStrings deklarieren, als alternative wäre ein unsichtbares Memo-Feld sicher gut, aber ich finde das irgendwie blöd ein visuelles Objekt für etwas zu verwenden, was der Anwender eh nie sehen wird.

Gibt es eine sinnvolle Alternative?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 11:51 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
TStringList

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 12:17 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
Der Fehler (Zugriffsverletzung) ist immernoch da, egal ob ich vorher den Konstruktor aufrufe oder nicht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 12:41 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Dann machst du woanders einen Fehler. Ich nutze in meinem aktuellen Spiel mehrere dutzend Stringlisten (auch dynamisch) und habe keinerlei Probleme. Bemüh mal den Debugger (der ist in Delphi ja sehr gut gemacht) und schau woher die Exception genau kommt. Ansonsten kann man ohne Quellcode und genaue Problembeschreibung schlecht helfen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 12:51 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
Naja, der Fehler tritt nicht auf, wenn ich diese Zeilen mit den StringListen auskommentiere, also wirds daran irgendwie schon liegen. ;)
(Benutze übrigens Delphi 7).
Einige Durchläufe mit den Entkäferer brachte dasselbe Ergebnis...

KartenSpeicher ist vom Typ TStringList.
Code:
  1.  
  2. procedure TFormStart.TimerInitTimer(Sender: TObject);
  3. begin
  4.   TimerInit.Free;
  5.   //Texturen laden
  6.   TexturenErstellen('../Texturen/SandUL.bmp');
  7.   TexturenErstellen('../Texturen/SandUM.bmp');
  8.   TexturenErstellen('../Texturen/SandUR.bmp');
  9.   TexturenErstellen('../Texturen/SandML.bmp');
  10.   TexturenErstellen('../Texturen/SandMR.bmp');
  11.   TexturenErstellen('../Texturen/SandOL.bmp');
  12.   TexturenErstellen('../Texturen/SandOM.bmp');
  13.   TexturenErstellen('../Texturen/SandOR.bmp');
  14.   TexturenErstellen('../Texturen/Wolken.tga');
  15.   TexturenErstellen('../Texturen/Sand.bmp'  );
  16.   // ...
  17.   with FormKontrollStation do begin
  18.     Left := Screen.Width - Width;
  19.     Top  := 0;
  20.     Show;
  21.   end;
  22.   with FormTexturManager do begin
  23.     Left := Screen.Width - Width;
  24.     Top  := FormKontrollStation.Height;
  25.     LabelTexturName.Caption := TexturName.Strings[TexturNR[0,0,0]];
  26.     Show;
  27.   end;
  28.   KartenSpeicher.Create;
  29.   MenueEinzelnOeffnenClick(Self); //Ruft die Karten-öffnen-Prozedur auf
  30.   If KartenSpeicher.Strings[0] <> ''
  31.     Then MenueNeuClick(Self);
  32.   FormTexturManager.EditSchicht.MaxValue := KartenSchichten;
  33. end;


Die Fehler treten beim Konstruktor und bei der IF-Abfrage auf und sonst wird momentan nirgends sonst auf diese Variable zugegriffen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:00 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Sicher dass auch wirklich Einträge in der Stringliste sind? Du frägst ja ab ob der erste String ([0]) <> '' ist, und wenn in deiner Stringliste keine Strings enthalten sind gibt es natürlich Strings[0] nicht, was zu einer Zugriffsverletzung führt. Ansonsten hast du leider nicht die wirklich relevanten Teile gezeigt, aber der Fehler ist sichlerich auf deiner Seite, TStringList funktioniert tadellos. Und im Debugger siehst du übrigens auch was in einer Stringliste drin ist, da kannst du obige Aussage schnell nachprüfen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:07 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
Und wie Frage ich ab, ob irgendwas reingeladen wurde oder ob die Liste komplett leer ist?

Code:
  1. KartenSpeicher.Text <> ''

gibt nämlich ebenfals denselben Fehler aus (höchstens vielleicht eine andere Adresse).


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:09 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Klasseninstanzen werden anders erstellt als du das da machst.
Code:
  1. KartenSpeicher.Create // Falsch

Code:
  1. KartenSpeicher := TStringList.Create  // Richtig

In deinem Fall hast du kein existierendes Objekt. Du rufst zwar die Methode des Konstruktors auf aber der eigentliche Konstruktor wird in deinem Fall nicht aufgerufen. Entsprechend wird auch kein Speicher für das Objekt erstellt. Resultat kennst du.

Das ist im übrigen bei wirklich ALLEN Klassen so. Klassenname.Create (oder wie der Konstruktor heißt).

PS: Erfragen kannst du es mit KartenSpeicher.Count. Ist Count >= 1 dann kannst du auf KartenSpeicher[0] zugreifen. Ansonsten bekommst du ein Listindex out of bounds.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:14 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
KartenSpeicher := TStringList.Create;

MAN!!! Das weiß ich doch, wieso mach ich diesen billigen Standardfehler? :P

So, nach dieser ausgebesserten Konstruktion funktioniert
Code:
  1. KartenSpeicher.Text <> ''
auch wieder.

Damit wäre mein Problem wohl denke ich fürs erste gelöst.

Danke. ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:22 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Text enthält aber mitunter auch Zeilenumbrücke. Wenn du zum Beispiel einen leeren Text zur Liste hinzufügst stehen in Text 2 Zeichen (Zeilenumbruch) aber KartenSpeicher[0] ist trotzdem ''. Je nachdem wie und wo das befüllt wird solltest du darauf noch mal gesondert reagieren. Nichts ist so unberechenbar wie der Benutzer.

Bzw wenn du nur einen String in die Liste packst (auch später) dann wäre eventuell ein String einfacher zu handhaben. Allerdings denke ich jetzt einfach mal, dass es aus gutem Grund eine Liste sein wird.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:23 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Hättest evtl. dabeischreiben sollen das KartenSpeicher eine TStringList ist. Hab gedacht dass wär deine eigene Klasse, und KartenSpeicher.Strings wäre deine TStringList die im Konstruktur deiner eigenen Klasse erstellt werden würde...

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 13:36 
Offline
DGL Member

Registriert: Sa Okt 18, 2008 11:59
Beiträge: 180
Zitat: "KartenSpeicher ist vom Typ TStringList."

Das steht direkt über den großen Quelltext von der TimerInitTimer-Prozedur. ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 17:10 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Lossy eX hat geschrieben:
Klasseninstanzen werden anders erstellt als du das da machst.
Code:
  1. KartenSpeicher.Create // Falsch

Code:
  1. KartenSpeicher := TStringList.Create  // Richtig

In deinem Fall hast du kein existierendes Objekt. Du rufst zwar die Methode des Konstruktors auf aber der eigentliche Konstruktor wird in deinem Fall nicht aufgerufen. Entsprechend wird auch kein Speicher für das Objekt erstellt. Resultat kennst du.


'Tschuldige, dass ich da kurz dazwischenfunke, aber eine kleine korrektur: Man erzeugt eine Instanz, der Konstruktur wird auch ganz normal aufgerufen (genauso, wie man jede andere Class-Methode auch bei einem nicht initialisierten Objekt aufrufen kann), aber leider wird das Ergebniss nirgendwo aufgefangen (keine Zuweisung). Es wird also ein Objekt erzeugt, aber es wird nicht zugewiesen.

Achso: Und wenn du leerzeichen und so ausschließen willst, schau dir mal die Funktion Trim an. Die killt alle Leer- und Steuerzeichen am linken und rechten Stringende, bis sie auf ein "normales" zeichen stößt. Trim(' Hallo Welt!'+#13#10') würde also 'Hallo Welt!' zurückgeben.

Gruß Lord Horazont

P.S.: Das soll jetzt aber keine Ermutigung sein, anstatt TStringList.Create einfach KartenSpeicher.Create zu schreiben ;). Zumal man zumindest mit der FreePascal RTL einen Typecast bräuchte, weil TStringList keinen eigenen Construktor definiert und damit der von TObject aufgerufen wird - was zu inkompatiblen typen führt.

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 18:42 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Lord Horazont hat geschrieben:
'Tschuldige, dass ich da kurz dazwischenfunke, aber eine kleine korrektur: Man erzeugt eine Instanz, der Konstruktur wird auch ganz normal aufgerufen (genauso, wie man jede andere Class-Methode auch bei einem nicht initialisierten Objekt aufrufen kann), aber leider wird das Ergebniss nirgendwo aufgefangen (keine Zuweisung). Es wird also ein Objekt erzeugt, aber es wird nicht zugewiesen.

Tschuldige, dass ich da zwischenfunke. Aber unter Delphi ist das definitiv Falsch! Es ist ein Unterschied ob du "TStringList.Create" oder "KartenSpeicher.Create" machst. Ja. Es wird auch nur der Konstruktor aufgerufen. Aber die Parameter sind anders, die der Compiler an die Funktion übergibt. Bei "KartenSpeicher.Create" bekommst du unter Delphi nur die Instanz KartenSpeicher zurück. Ist sie nicht erstellt worden gibt es eine Zugriffsverletzung.

Lord Horazont hat geschrieben:
Achso: Und wenn du leerzeichen und so ausschließen willst, schau dir mal die Funktion Trim an. Die killt alle Leer- und Steuerzeichen am linken und rechten Stringende, bis sie auf ein "normales" zeichen stößt. Trim(' Hallo Welt!'+#13#10') würde also 'Hallo Welt!' zurückgeben.

Mit Trim hast du recht. Allerdings die Eigenschaft Text ist mit vorsicht zu genießen. Denn die Strings werden in der Liste seperat abgelegt und bei der Eigenschaft Text müssen diese erst alle zusammenkopiert werden und das kostet kurzzeitig Speicher und Leistung. Und sollte nur dann benutzt werden wenn man den Text auch wirklich als Ganzes benötigt sonst nicht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 17, 2009 19:36 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Zum Konstruktur: Hmm... In der tat, du hast recht. Offensichtlich versucht Delphi dem Constructor an dieser Stelle noch die Objektinstanz mit zu überreichen oder sowas... Nun, ich bin wohl etwas zu lange nicht mehr mit Delphi unterwegs gewesen. Du hast vollkommen recht, es gibt einen Fehler, wenn man das unter Delphi versucht.

Zu Trim/Text: Volle zustimmung.

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 9 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 14 Queries | GZIP : On ]