![]() |
Wie speichere ich einen String am besten?
Ich möchte dem Nutzer in meinem Sudoku-Programm die Möglichkeit geben, Sudokus zu speichern, z.B. damit man es nicht an einem Stück machen muss. Selbstverständlich soll es auch möglich sein, ein Sudoku zu laden.
Der Ansatz ist dabei der, dass das Sudoku in einem String gespeichert wird, die String[1] ist die Zahl links oben, String[10] die Zahl darunter. Nach dem ich verschiedene Möglichkeiten abgewogen hat (sprich: entweder Ini oder Savedialog, aber ich will, dass der Nutzer so komfortabel wie möglich speichern und laden kann) möchte ich TSaveDialog und TLoadDialog benutzen. Auf Knopfdruck (nur Entwicklungsphase, packe ich später bei der Save-Prozedur rein) wird das Sudoku zeichenweise in eine Zeile eines TMemos gepackt, mögliche Zeichen sind halt '1'..'9' und ' '. In der Save-Prozedur soll diese Zeile gespeichert werden, in der Load-Prozedur soll aus der Datei der String ans TMemo geaddet werden. Dazu speichere ich eine TStringList als .txt-Datei. Die TMemo dient dabei nur als visuelle Überprüfung, später reduziere ich das ganze auf TStringList. Try und finally kommen später noch.
Delphi-Quellcode:
procedure TForm1.Speichern(Sender: TObject);
var Sudoku:TStringList; begin Sudoku:=TStringList.create; SaveDialog1.Filter:='*.txt|*.TXT'; if SaveDialog1.execute then begin Sudoku[0]:=Memo1.lines[0]; Sudoku.SaveToFile(SaveDialog1.FileName); end; Sudoku.Free; end; procedure TForm1.Sudokuladen1Click(Sender: TObject); var Sudoku:TStringList; begin Sudoku:=TStringList.create; OpenDialog1.Filter:='*.txt|*.TXT'; if OpenDialog1.execute then Sudoku.LoadFromFile(OpenDialog1.FileName); Memo1.Lines.add(Sudoku[0]); end; Sudoku.Free; end; Wenn ich aber versuche, ein Sudoku zu speichern, gibt er eine Fehlermeldung "Out of bound " aus. Was mache ich falsch? PS: Diese .txt-Datei ist ja sehr manipulationsanfällig (würde dem Nutzer nichts bringen, aber...), kann man das auch in einem Format schreiben, auf das der Nutzer nicht per Explorer öffnen kann? [edit=SirThornberry]Titel korrigiert - Mfg, SirThornberry[/edit] |
Re: Wie speichere ich am einen String am besten?
Wenn die StringList grade erst erstellt wurde, dann ist sie leer und es gibt keine Zeilen (hier die Zeile 0)
Delphi-Quellcode:
Sudoku.Add(Memo1.lines[0]);
|
Re: Wie speichere ich am einen String am besten?
[offtopic]
Wenn du nur Zahlen von 1-9 abspeicherst, hast du leere Felder übersprungen und du bekommst am Ende nicht das raus, was du eigentlich haben wolltest, sondern die Zahlen sind dann alle verschoben. Vielleicht noch eine "0" für ein leeres Feld ergänzen ;) [/offtopic] |
Re: Wie speichere ich am einen String am besten?
Immer diese Flüchtigkeitsfehler :oops:
Hab jetzt den Quelltext verändert, so dass es klappt. Jedoch stehe ich jetzt vor dem nächsten Problem (wobei ich zugeben muss, dass ich TSaveDialog bisher nur für Bilder benutzt habe und daher nur mit Formaten wie Bmp oder JPEG gearbeitet habe): Und zwar kann man die Datei speichern, wenn man sie aber laden möchte, bemerkt man, dass sie nicht im .txt-Format gespeichert ist, sondern in einem "Datei"-Format. Da der Filter beim OpenDialog aber nur die vorher gespeicherten Sudokus anzeigen soll (wie siehts eigentlich mit einem selbst definierten Format .sud aus? Spontan hat es nicht funktioniert), diese aber in dem .txt-Format sind (wie ja eigentlich im SaveDialog-Filter deklariert) werden diese nicht im Dialog angezeigt. Zwar lädt der Dialog bei korrekter Namensangabe das richtige Sudoku, aber diesen Namen sieht man im OpenDialog ja nicht wegen dem Filter. Ich könnte das ganze filterlos machen, so dass alle Dateien im Ordner angezeigt werden, was zwar theoretisch ginge, da der Ordner ja dann im Ordner der Projektdatei sein soll, aber praktisch halte ich das ganze für... unelegant. :-D Könnt ihr mir helfen, entweder ein Format .sud zu definieren und den Save-Filter zum Funktionieren bringen oder mir die Sache erklären? PS: @Noedel Da hat mir doch jetzt jemand dazwischen gefunkt bei meinem kleinen Beitrag :-D. Dein Tipp ist zwar sehr nett, aber an nicht ausgefüllten Stellen schreibt er ein ' ' und daher klappt das schon, aber trotzdem danke :) Wobei ich gerade bemerke, das mir das Forum den Ausdruck 'Leerzeichen' zu '' verkürzt, bei PS und im ersten Post soll es natürlich '*hierStehtEinLeerzeichen* heißen, aber naja... Wie gesagt trotzdem danke :mrgreen: |
Re: Wie speichere ich am einen String am besten?
Guten Morgen...
Zitat:
:hi: |
Re: Wie speichere ich am einen String am besten?
Zitat:
Da ich für mich nicht viel von diesen Dateinamenfiltern halte, verstehe ich die geistigen Klimmzüge nicht ganz, die Du um den Dateinamen machst. Nenn deine Dateien *.SOD, *.SUD, *.SDK oder wie auch immer, pass den Filter entsprechend an und gut ist. Gruß K-H |
Re: Wie speichere ich am einen String am besten?
Zitat:
|
Re: Wie speichere ich am einen String am besten?
Meine Güte, es handelt sich um ein einfaches Sudoku, dass man auf dem PC spielt. Wenn jemand unbedingt an der Save-Datei rumfummeln will, lass ihn doch, ist ja sein Problem, wenn er sich dadurch den Spielspaß nimmt.
|
Re: Wie speichere ich einen String am besten?
Erstmal vielen Dank für die große Resonanz. :mrgreen:
@haentschman Den String erstelle ich mit
Delphi-Quellcode:
und verarbeiten mit
Memo1.clear;
Datei:=''; For Zeile:=0 to 8 do For Spalte:=0 to 8 do Datei:=Datei+StringGrid1.cells[Spalte,Zeile]; // in OnCreate wurde jedes Feld mit ' ' belegt Memo1.Lines.Add(Datei);
Delphi-Quellcode:
Ich verstehe jetzt nicht was daran so schwer sein soll? Oder habe ich einen Denkfehler, der das Problem unzulässig vereinfacht?
For i:=1 to 81 do
begin Spalte:=(i-1) mod 9; Zeile:=(i-1) div 9; // i-1 da Zellen/Spalten von 0..8 StringGrid1.Cells[Spalte,Zeile]:=Datei[i]; end; @p80286 Das ist ja das Problem mit dem Anpassen des Filters.
Delphi-Quellcode:
Im OpenDialog kann ich dann nur *.sud als Filter auswählen. Dennoch zeigt er keinerlei Anstalten mir dann die gespeicherte(n) Dateie(n) anzuzeigen. Und über den Explorer mit Rechtsklick>Eigenschaften zeigt er mir als Format nur "Datei" an.
procedure TForm1.Speichern(Sender: TObject);
var Sudoku:TStringList; begin Sudoku:=TStringList.create; SaveDialog1.Filter:='*.sud|*.Sud'; if SaveDialog1.execute then begin Sudoku[0]:=Memo1.lines[0]; Sudoku.SaveToFile(SaveDialog1.FileName); end; Sudoku.Free; end; procedure TForm1.Sudokuladen1Click(Sender: TObject); var Sudoku:TStringList; begin Sudoku:=TStringList.create; OpenDialog1.Filter:='*.sud|*.SUD'; if OpenDialog1.execute then Sudoku.LoadFromFile(OpenDialog1.FileName); Memo1.Lines.add(Sudoku[0]); end; Sudoku.Free; end; Ich möchte aber, dass er mir im OpenDialog sämtliche *.sud-Dateien anzeigt. Aber irgendwie ignoriert er den Filter beim Speichern. So funktioniert es auf alle Fälle nicht. :? Und wenn ich als Filter *.txt eingebe, speichert er das auch im "Datei"-Format. Im Explorer zeigt er es mir aber nicht als WordPad-Datei oder so an. Sowohl .txt als auch .sud kann man mit Rechtsklick>Öffnen>Programm aus Liste auswählen>Wordpad(oder Editor) öffnen. @Die Muhkuh Aber wenn er "ausversehen" mal darin rumspielt, verändert er damit die gespeicherten Sudokus. Sind die Sudokus verändert, ist das nicht mehr umkehrbar und der Nutzer müsste sie löschen. Das möchte ich ihm nicht antun :angel: |
Re: Wie speichere ich einen String am besten?
Hi
Eine Möglichkeit die Daten in ein prpitäres Format zu speichern:
Delphi-Quellcode:
Nicht getestet!!!
procedure SaveToFile(const FileName : String)
var Stream : TStream; begin Stream := TFileStream.Create(FileName, fmCreate); try SaveToStream(Stream); finally Stream.Free; end; end; procedure LoadFromFile(const FileName : String) var Stream : TStream; begin Stream := TFileStream.Create(FileName, fmOpen); try LoadFromStream(Stream); finally Stream.Free; end; end; procedure SaveToStream(Stream : TStream); var Zeile, Splate, I : Integer; begin for I := 1 to 81 do begin Spalte := (I-1) mod 9; Zeile := (I-1) div 9; Stream.WriteBuffer(StrToInt(StringGrid.Cells[Spalte, Zeile]), SizeOf(Integer)); end; end; procedure LoadFromStream(Stream : TStream); var Zeile, Splate, I : Integer; begin for Zeile := 0 to 8 do for Spalte := 0 to 8 do begin Stream.ReadBuffer(I), SizeOf(Integer)); StringGrid.Cells[Spalte, Zeile] := IntToStr(I); end; end; Zitat:
Damit der Explorer eine '*.sud' als Sudoko-Datei idenifiziert must du die Dateiendung registrieren, siehe ![]() Viele Grüße |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz