Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Info-Arbeit: Fragen zum Speichern von Ketten (Pointern)
Danillson - Mi 14.09.11 21:13
Titel: Info-Arbeit: Fragen zum Speichern von Ketten (Pointern)
Hallo Zusammen,
ich frage mich gerade, wie ich eine verkettete Liste speichere und dann wieder öffnen kann. Am Freitag schreibe ich eine Arbeit über Pointer. Einfügen am Anfang, in der Mitte und am Ende kann ich. Auch das Löschen an bestimmten Stelle funktioniert. Wie ich allerdings speichere und öffne (mit Open- und Savedialog) ist mir ein Rätstel.
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:
| procedure TForm1.Speichern1Click(Sender: TObject); begin savedialog1.Execute; assignfile(vocdb, savedialog1.FileName); rewrite(vocdb); zhilf:=zkopf; while zhilf<>nil do begin write (vocdb, zhilf); zhilf:=zhilf^.next; end; end;
procedure TForm1.ffnen1Click(Sender: TObject); begin opendialog1.Execute; assignfile(vocdb, opendialog1.FileName); if fileexists (opendialog1.FileName) then begin reset(vocdb); while zkopf<>nil do begin read (vocdb, zhilf); zkopf:=zhilf; end end else showmessage('Noch keine Datei vorhanden'); |
Das ist der Quelltext. Dass das Öffnen völlig falsch ist, ist mir klar. Ich würde mich über Lösungsvorschläge freuen...
Moderiert von
Narses: I- durch Delphi-Tags ersetzt
bole - Mi 14.09.11 21:25
Hallo im Forum :welcome:
Die Pointer musst Du nicht speichern. In das File werden nur die Daten geschrieben.
Beim Lesen musst Du die Liste neu aufbauen. (Datenstatz lesen, einfügen, nächsten Datensatz lesen...)
Gruss
Bole
Danillson - Mi 14.09.11 21:32
Wie genau stelle ich das an? Könnte mir einer ein Beispiel in Form eines Quelltextes schicken?
Die Deklaration sieht übrigens so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| type tzeiger=^tknoten; tknoten=record de:string[15]; en:string[15]; next:tzeiger; end; |
Moderiert von
Narses: Delphi-Tags hinzugefügt
Mitmischer 1703 - Mi 14.09.11 21:37
Hi!
Ich hab grad wenig Zeit aber du musst (ich denke, du hast ein Array von tzeigern) über dieses iterieren, den Pointer dereferenzieren und in ein file of tknoten schreiben (das ist am einfachsten), einfach
writeln(f, knoten). Beim Lesen dasselbe, nur dass du hier in eine Variable liest:
Delphi-Quelltext
1: 2:
| var knoten : tknoten; Readln(knoten); |
Hoffe, das hat erstmal geholfen, wenn nicht schreib ich es dir morgen nochmal genauer.
Danillson - Mi 14.09.11 21:45
Moderiert von
Narses: Komplett-Zitat des letzten Beitrags entfernt.
Nope, ich habe kein Array von TZeiger. Ich dachte man kann mit einem Hilfszeiger sich entlang hangeln und das dann in die Datei schreiben.
Wir haben Pointer bisher nur theoretisch besprochen und noch nichts dazu programmiert. Das ist auch der Grund, warum ich nicht weiß, wie ich in diesem Fall arbeiten muss.
Das ist der ganze Quelltext:
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: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90:
| type tzeiger=^tknoten; tknoten=record de:string[15]; en:string[15]; next:tzeiger; end;
var Form1: TForm1; zkopf, zneu, zaktuell,zhilf:tzeiger; vocdb: file of tzeiger;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); begin new(zneu); zneu^.de:=edit1.Text; zneu^.en:=edit2.Text; zneu^.next:=nil;
if zkopf=nil then zkopf:=zneu else begin zaktuell:=zkopf; while zaktuell^.next<>nil do zaktuell:=zaktuell^.next; zaktuell^.next:=zneu; end; edit1.Text:=''; edit2.Text:=''; end;
procedure TForm1.FormCreate(Sender: TObject); begin zkopf:=nil; end;
procedure TForm1.Button2Click(Sender: TObject); begin zaktuell:=zkopf; while zaktuell<>nil do begin listbox1.Items.add(zaktuell^.de +' = '+ zaktuell^.en); zaktuell:=zaktuell^.next; end; end;
procedure TForm1.Speichern1Click(Sender: TObject); begin savedialog1.Execute; assignfile(datei, savedialog1.FileName); rewrite(datei); if zkopf=nil then showmessage('Noch keine Vokabeln vorhanden!') else zhilf:=zkopf; while zhilf <> nil do begin write(datei,zhilf^.inhalt); zhilf:=zhilf^.next; end; closefile(datei); end;
end;
procedure TForm1.ffnen1Click(Sender: TObject); begin opendialog1.Execute; assignfile(vocdb, opendialog1.FileName); if fileexists (opendialog1.FileName) then begin reset(vocdb); while zkopf<>nil do begin read (vocdb, zhilf); zkopf:=zhilf; end end else showmessage('noch keine Datei vorhanden');
end;
end. |
Moderiert von
Narses: Quote- durch Delphi-Tags ersetzt
Narses - Do 15.09.11 00:26
Moin und :welcome: in der Entwickler-Ecke!
Danillson hat folgendes geschrieben : |
Wir haben Pointer bisher nur theoretisch besprochen und noch nichts dazu programmiert. Das ist auch der Grund, warum ich nicht weiß, wie ich in diesem Fall arbeiten muss. |
Danillson hat folgendes geschrieben : |
Am Freitag schreibe ich eine Arbeit über Pointer. |
Sollte dein Lehrer tatsächlich etwas in einer Klausur abfragen, was er nachweislich vorher nicht erklärt hat, dann hätte er sich eine ziemlich tiefe Grube gegraben, in die er beabsichtigt zu fallen - was ich mal so pauschal nicht glaube. :nixweiss: Warum auch immer du also diese Begründung verwendet, Sinn macht sie nicht. :suspect: Wenn du einfach nur den Quelltext absaugen willst, weil du gepennt hast, sag´s doch gleich, kommt eh irgendwann raus... :mrgreen:
bole hat folgendes geschrieben : |
Die Pointer musst Du nicht speichern. In das File werden nur die Daten geschrieben.
Beim Lesen musst Du die Liste neu aufbauen. (Datenstatz lesen, einfügen, nächsten Datensatz lesen...) |
Das ist der entscheidende Tipp! :idea:
Mitmischer 1703 hat folgendes geschrieben : |
in ein file of tknoten schreiben (das ist am einfachsten), einfach writeln(f, knoten). Beim Lesen dasselbe, nur dass du hier in eine Variable liest:
Delphi-Quelltext 1: 2:
| var knoten : tknoten; Readln(knoten); | |
Das ist leider nicht richtig, denn in dem Record ist ja auch der Pointer enthalten - der hat aber in der Datei nix zu suchen (ist eh unbrauchbar). ;)
Ich schlage mal vor, einfach eine Textdatei als Kontainer zu verwenden, jeweils zwei Zeilen ergeben einen Datensatz, zuerst kommt der deutsche Text. :idea: Und weil ich eh grad noch auf was warten muss, hier mal dein Quelltext etwas überarbeitet: ;)
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: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144:
| type TZeiger = ^TKnoten; TKnoten = record de: String; en: String; next: TZeiger; end;
TForm1 = class(TForm) btnAdd: TButton; Edit1: TEdit; Edit2: TEdit; ListBox1: TListBox; btnList: TButton; btnClear: TButton; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; btnSave: TButton; btnLoad: TButton; procedure btnAddClick(Sender: TObject); procedure btnListClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure btnClearClick(Sender: TObject); procedure btnSaveClick(Sender: TObject); procedure btnLoadClick(Sender: TObject); public zKopf: TZeiger; end;
var Form1: TForm1;
implementation
procedure TForm1.btnAddClick(Sender: TObject); var zNeu, zAktuell: TZeiger; begin New(zNeu); zNeu^.de := Edit1.Text; zNeu^.en := Edit2.Text; zNeu^.next := nil; if zKopf = nil then zKopf := zNeu else begin zAktuell := zKopf; while zAktuell^.next <> nil do zAktuell := zAktuell^.next; zAktuell^.next := zNeu; end; Edit1.Clear; Edit2.Clear; end;
procedure TForm1.btnListClick(Sender: TObject); var zAktuell: TZeiger; begin ListBox1.Clear; zAktuell := zKopf; while zAktuell <> nil do begin ListBox1.Items.Add(zAktuell^.de + ' = ' + zAktuell^.en); zAktuell := zAktuell^.next; end; end;
procedure TForm1.btnClearClick(Sender: TObject);
procedure KillEntry(const zAktuell: TZeiger); begin if zAktuell <> nil then begin KillEntry(zAktuell^.next); Dispose(zAktuell); end; end;
begin ListBox1.Clear; KillEntry(zKopf); zKopf := nil; end;
procedure TForm1.btnSaveClick(Sender: TObject); var Datei: TStringList; zAktuell: TZeiger; begin if SaveDialog1.Execute then begin Datei := TStringList.Create; try zAktuell := zKopf; while zAktuell <> nil do begin Datei.Add(zAktuell^.de); Datei.Add(zAktuell^.en); zAktuell := zAktuell^.next; end; Datei.SaveToFile(SaveDialog1.FileName); finally Datei.Free; end; end; end;
procedure TForm1.btnLoadClick(Sender: TObject); var Datei: TStringList; zNeu, zAktuell: TZeiger; begin if OpenDialog1.Execute then begin btnClearClick(Self); Datei := TStringList.Create; try Datei.LoadFromFile(SaveDialog1.FileName); zAktuell := nil; while Datei.Count > 1 do begin New(zNeu); zNeu^.de := Datei.Strings[0]; zNeu^.en := Datei.Strings[1]; zNeu^.next := nil; if zAktuell = nil then zKopf := zNeu else zAktuell^.next := zNeu; zAktuell := zNeu; Datei.Delete(0); Datei.Delete(0); end; finally Datei.Free; end; btnListClick(Self); end; end;
procedure TForm1.FormDestroy(Sender: TObject); begin btnClearClick(Self); end; |
Bei Fragen - Fragen! :P
cu
Narses
BenBE - Do 15.09.11 00:43
Und weil wir hier grad so schön am Nörgeln sind, mal etwas zum Style Guide:
Pointer-Typen sollten in Delphi mit einem P beginnen, gefolgt von dem Namen des Typen, auf den sie zeigen, ohne das typische T.
Konkret also:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| type PKnoten = ^TKnoten; TKnoten = record de: string; en: string; next: PKnoten; end; |
Die nächste Sache ist eher eine Formsache, erleichtert aber die Strukturierung etwas: Jede Gruppe von zusammengehörigen Typen sollte in einem eigenen Type-Block stehen. Vor TForm1 also noch ein
Type schreiben. Hat auch was mit der Gültigkeit von Forward-Deklarationen zu tun, aber das ist eine andere Geschichte.
Ach ja: In Sachen Einrückung: Bitte keine Hängenden Gärten der Semiramis veranstalten, wenn man pro Syntax/Block-Ebene jeweils 2 (
Borland/
Inprise/
CodeGear/Embarcadero) oder 4 (im DF häufig anzutreffen) verwendet, dann reicht das. Einrückung nach = oder anderen Trennzeichen verschwendet oft nur unnötig Platz auf der Zeile, ohne dass es die Lesbarkeit steigert.
@
Narses: Für
Mitmischer 1703 wäre ich für die Einführung eines Oink!!!-Buttons.
Ach ja, abschließend noch was: Trennung von Code und GUI ;-)
Mitmischer 1703 - So 25.09.11 22:04
Ein Oink? Wieso das :P?
Moderiert von
Narses: ZItat repariert.
Knulli - Fr 21.10.11 17:44
Kann mir mal einer erklären, was ein Oink ist? :P
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!