![]() |
Delphi-Version: 5
Textdatei in Record Muster überführen
Hallo zusammen, ich habe folgendes Problem:
Vorweg, worum gehts: Programm soll auf Knopfdruck einen per Zufall ermittelten Spruch aussuchen und in ein Memofeld schreiben. Die Sprüche sind in einer Textdatei, aufgebaut aus (spruch;autor<nächste Zeile>spruch;autor<nächste Zeile> usw.). Das Programm soll den Spruch aus der Recorddatei holen, die zuvor erzeugt wird und in das Memofeld schreiben. Erstmal der Ansatz:
Delphi-Quellcode:
Anschließend soll unter Button1Click folgendes passieren:
type Tsprueche=record
spruch:string[200]; autor:string[50]; end; procedure speichern(hilfe:string); var s:Tsprueche; s1:string; posi:integer; f:textfile; //hier stehen ca. 20 Sprüche, Weisheiten, etc. drin datei:file of Tsprueche; //record vom Textfile begin assignfile(f,'C:\...'+'spruch.txt'); reset(f); AssignFile(datei,'C:\...'+'sprueche.dat'); IF fileexists('C:\...'+'sprueche.dat') THEN Reset(datei) ELSE Rewrite(datei); posi:=0; while not eof(f) do begin readln(f,hilfe); posi:=pos(';',hilfe); s1:=copy(hilfe,1,posi-1); case posi of 0: s.spruch:=s1; 1: s.autor:=s1; end; write(datei,s); end; closefile(f); closefile(datei); 1. per Zufall einen der Sprüche ermitteln, die ja jetzt im record Muster vorhanden sind, also über seek(datei, nr des zufallsspruchs) angesprochen werden können 2. Spruch ins Memo schreiben (<spruch> +'von'+ <autor>) Hier bekomme ich enorm Probleme mit den Typen der einzelnen Variablen und der Übernahme aus der anderen Prozedur. Kann mir an der Stelle jemand helfen? |
AW: Textdatei in Record Muster überführen
Ist das mit der typisierten Datei und dem Record eine Vorgabe, oder darfst Du das auch anders lösen? IMO ginge das z.B. mit einer T(Mem)IniFile bedeutend einfacher. Ansonsten sieht mir die case-Abfrage etwas sonderbar aus, was ist denn, wenn ";" gar nicht im String vorkommt? Möglicherweise habe ich den Code aber auch nur zu schnell überflogen und daher die Logik nicht begriffen.
|
AW: Textdatei in Record Muster überführen
Hallo,
musst Du die TextDatei so einlesen? Einfacher ginge es mit einer TStringList und dem entsprechenden Delimiter. Grüße Klaus |
AW: Textdatei in Record Muster überführen
Zitat:
Zitat:
Zitat:
|
AW: Textdatei in Record Muster überführen
Dann teil doch das Gesamtproblem einmal in Teilprobleme auf und schreib die schön einzeln als Funktionen bzw. Prozeduren. Eine ordentliche Einrückung hilft beim Code-Verständnis übrigens ungemein, Du solltest darauf achten.
|
AW: Textdatei in Record Muster überführen
.. auslesen könnte so gehen..
Delphi-Quellcode:
Einbauen könnte man noch eine gescheite Fehlerbehandlung.
procedure readRandomDataset(fileName: TFilename; var dataSet: TSprueche);
var dataFile : file of TSprueche; idx : longInt; begin assignFile(dataFile,fileName); reset(dataFile); //Datei öffnen, Dateizeiger auf Pos. 0 idx := random(sizeOf(dataFile)); // ermitteln eines zufälligen Datensatzes/Records seek(dataFile,idx); // setze Dateizeiger auf den zufälligen Datensatz read(dataFile,dataSet); // lese Datensatz/Record closeFile(dataFile); // Datei schliessen end; procedure TForm1.Button1Click(Sender: TObject); var dataSet : TSprueche; begin readRandomDataSet('...',dataSet); memo1.Lines.Add(format('%s von %s',[dataSet.author,dataSet.textValue])); end; Grüße Klaus |
AW: Textdatei in Record Muster überführen
Und hier noch ein Grobkonzept zur Konvertierung:
Delphi-Quellcode:
Ungetestet, da im Editor heruntergetippt.
type
Tsprueche=record spruch:string[200]; autor:string[50]; end; procedure StringToSpruch(const Line: string; var Spruch: TSprueche); const DELIM = ';'; var DelimPos: integer; begin FillChar(Spruch, SizeOf(Spruch), #0); DelimPos := Pos(DELIM, Line); Spruch.autor := Copy(Line, 1, DelimPos - 1); Spruch.spruch := Copy(Line, DelimPos + 1, MAXINT); end; procedure Konvertieren(const SrcFilename, DestFilename: string); var Spruch: Tsprueche; Zeile: string; Eingabe: textfile; Ausgabe: file of Tsprueche; begin (* Eingabe öffnen *) (* Ausgabe öffnen *) (* Schleife *) (* Zeile aus Eingabe lesen *) StringToSpruch(Zeile, Spruch); (* Spruch in Ausgabe schreiben *) (* Ende Schleife *) (* Ausgabe schließen *) (* Eingabe schließen *) end; |
AW: Textdatei in Record Muster überführen
puh da ist zu viel bei wovon ich noch nie etwas gehört habe. Probiere gerade eure Tips so umzusetzen, dass ich nur das nutze was wir auch bisher an Werkzeug an die Hand bekommen haben, leider erfolglos.
Teilprobleme sind meiner Meinung nach: 1. Recorddatei 'sprueche.db' erzeugen (klappt noch)
Code:
type Tsprueche=record
spruch:string[200]; autor:string[50]; end; procedure TForm1.FormCreate(Sender: TObject); begin AssignFile(datei,'C:\...\'+'sprueche.dat'); IF fileexists('C:\...\'+'sprueche.dat') THEN Reset(datei) ELSE Rewrite(datei); end; 2. Die Sprüche aus der sprüche.txt Textdatei in die record datei namens datei schreiben, dabei nach spruch und autor trennen :?: 3.Button1Click, also zufälligen Spruch ins Memo schreiben
Code:
Ich wäre für jeden weiteren Tipp sehr dankbar, dennoch habe ich die bereits vorhandenen Tipps auch noch nicht 100% durchschaut, daran arbeite ich gerade :wink:
procedure TForm1.Button1Click(Sender: TObject);
var spruch, autor:string; begin nr:=random(filesize(datei)); seek(datei,nr); //*Wie kann ich nun das was er da geseeked hat als string unter spruch speichern und den autor unter autor? spruch:= //alles vor ; autor:= //das nach ; memo1.Lines.Add(<spruch>+'von'+<autor>) end; |
AW: Textdatei in Record Muster überführen
Zitat:
write(dateivariable,von, bis) oder write(dateivariable, was) ?? |
AW: Textdatei in Record Muster überführen
Da steht Schleife, d.h. Du befindest Dich an der Stelle innerhalb einer solchen. Hier wurde die aktuell ausgelesene Zeile aus der Textdatei in den übergebenen Record geschrieben, es muss also heißen
Delphi-Quellcode:
wobei Ausgabe die Dateivariable der typisierten Datei und Spruch die Variable vom Typ des Records ist.
write(Ausgabe, Spruch);
|
AW: Textdatei in Record Muster überführen
Delphi-Quellcode:
Grüße
procedure TForm1.Button1Click(Sender: TObject);
var spruch, autor:string; dataSet : TSprueche; // dein Record begin nr:=random(filesize(datei)); seek(datei,nr); //*Wie kann ich nun das was er da geseeked hat als string unter spruch speichern und den autor unter autor? read(datei,dataSet); // den record aus der Datei lesen spruch:= //alles vor ; spruch := dataSet.spruch; autor:= //das nach ; autot := dataSet.autor; memo1.Lines.Add(<spruch>+'von'+<autor>) end; Klaus |
AW: Textdatei in Record Muster überführen
Danke für eure Hilfe, ich glaube ich bin jetzt sehr nah dran. Ich kann die Anwendung zumindest fehlerfrei starten. Betätige ich allerdings den Button1 erhalte ich folgende Fehlermeldung:
Projekt project1 hat Exception-Klasse >RunError(100)< ausgelöst. In Zeile 76, dies wäre hier:
Code:
unit Unit1;
{$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls; type Tsprueche=record spruch:string[200]; autor:string[50]; end; { TForm1 } TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { private declarations } public { public declarations } end; var Form1: TForm1; datei: file of Tsprueche; implementation {$R *.lfm} { TForm1 } procedure txttodb(uebergabe:string); var s:Tsprueche; //variable für datei:file of Tsprueche spruch:string; //das was vorm ; steht autor:string; //das was nach ; steht posi:integer; //position im string f:textfile; //var für den textfile quelle.txt datei:file of Tsprueche; //var für den data base file ziel.db begin assignfile(f,'quelle.txt'); //Eingabe öffnen reset(f); assignfile(datei,'ziel.db'); //Ausgabe öffnen rewrite(datei); posi:=0; while not eof(f) do begin readln(f,uebergabe); //liest in f und schreibt in den string uebergabe posi:=pos(';',uebergabe); //Position von ; in uebergabe s.spruch:=copy(uebergabe,1,posi-1); //das vorm ; s.autor:=copy(uebergabe, posi+ 1, MAXINT); //nach ; write(datei,s); end; closefile(f); closefile(datei); end; procedure readRandomDataset(fileName: TFilename; var dataSet: TSprueche); var datei : file of TSprueche; idx : longInt; begin assignFile(datei,'ziel.db'); if FileExists('ziel.db') then ReSet(datei) else ReWrite(datei); idx := random(sizeOf(datei)); seek(datei,idx); read(datei,dataSet); [COLOR="Red"] closefile(datei); [/COLOR] *//Zeile 76: hier hab ich den RunError end; procedure TForm1.Button1Click(Sender: TObject); var dataSet : TSprueche; spruch, autor:string; begin readRandomDataSet('ziel.db',dataSet); spruch:= dataSet.spruch; autor:= dataSet.autor; memo1.Lines.Add(spruch+'von'+autor); end; end. |
AW: Textdatei in Record Muster überführen
Relative Pfade sind schlecht. Außerdem: was willst Du denn aus einer Datei lesen, die Du gerade erst mit Rewrite angelegt hast? Wo wird txttodb aufgerufen, und wieso hat die einen Parameter, der intern als Variable benutzt wird, statt ihn gleich als Variable zu deklarieren?
|
AW: Textdatei in Record Muster überführen
Eure Hilfe ist nochmal gefragt, da ich immernoch hier dran sitze :wink:
Aufgabenstellung hat sich insofern geändert, dass ich nun eine .txt Datei habe in der 11 Adressen in dieser Form stehen: Nachname;Vorname;PLZ;Ort;Strasse;Hausnummer;usw... Die Aufgabe an sich besteht immernoch darin die .txt datei in ein Record Muster zu überführen... Hier mein Quelltext+Fragen:
Code:
*1: recordsize=.. war eine Vorgabe, was hat 2mal +1 zu bedeuten?
const
recordsize=1+20+20+5+20+30+3+4+9+1; //[B]*1[/B] type Tperson=record Nachname:string[20]; Vorname:string[20]; PLZ:string[5]; Ort:string[20]; Strasse:string[30]; Hausnummer:string[3]; Vorwahl:string[4]; Telefon:string[9]; end;
Code:
Beim Testen mit Ausgabe über seek() einer beliebigen Person aus der Adressdatei auf ein Memo fällt auf:
procedure person_linetorec(const Line: string; var person: Tperson);
const semi=';'; var semiPos: array [0..8] of integer; i:integer; begin FillChar(person, SizeOf(person), #0); FOR i:=0 TO 8 DO begin semiPos[i]:=Pos(semi, Line); person.nachname := Copy(Line, 0, semiPos[0]-1); person.vorname := Copy(Line, semiPos[0]+1,semiPos[1]-1); person.PLZ:= Copy(Line, semiPos[1]+1, semiPos[2]-1); //usw. - wollte erstmal testen bevor ich hier weiter tippe... end; end; - mal ist es richtig, mal falsch, je nach Länge von Nach,- und Vornamen der jeweiligen Person - erkenne aber leider keine Fehlersystematik. Hab ich bei der Copy(in,von,bis)-Sache was falsch gemacht?
Code:
Nur zum Verständnis, die prozedur macht was sie machen soll. :-D
procedure Konvertieren(const SrcFilename, DestFilename: string);
var srcfile: textfile; destfile:file of Tperson; line:string; person:Tperson; begin assignfile(srcfile,'adressen.txt'); reset(srcfile); assignfile(destfile,'adressen.db'); rewrite(destfile); while not eof(srcfile) do begin readln(srcfile,line); person_linetorec(line,person); write(destfile,person); end; closefile(destfile); closefile(srcfile); end; |
AW: Textdatei in Record Muster überführen
Besser
Delphi-Quellcode:
recordsize := SizeOf( TPerson);
|
AW: Textdatei in Record Muster überführen
Zitat:
Verlass dich nicht drauf. Du solltest dann so programmieren, das dein Programm nicht total abschmiert oder -schlimmer- total falsche Daten eingelesen werden. |
AW: Textdatei in Record Muster überführen
Zitat:
|
AW: Textdatei in Record Muster überführen
Ich halte das für einen Fehler, da für jeden String ein Längenbyte dazu addiert werden müßte.
Also für string[20] ist die Länge 20+1. Gruß K-H |
AW: Textdatei in Record Muster überführen
Zitat:
Falsch ist es, die Größe selbst ausrechnen zu wollen, denn man weiß nicht, wie Delphi die Recordfelder ausrichtet. Dies ist abhängig von den Compilereinstellungen und ob man das Record als 'packed' deklariert hat. |
AW: Textdatei in Record Muster überführen
@Furtbichler
Deine Antwort ist richtig, allerdings scheinst Du die Aussage von p80286 missverstanden zu haben. |
AW: Textdatei in Record Muster überführen
Zitat:
Wobei die "Packed"-Falle natürlich nicht beachtet wird. Ebenso ist es besser gleich mit
Delphi-Quellcode:
zu arbeiten.
Sizeof
Wenn mit den gemachten Vorgaben, das Programm wirklich funktioniert, dann ist das reines Glück! Gruß K-H |
AW: Textdatei in Record Muster überführen
Danke, verstanden.
Aber das Programm läuft immernoch nicht. Sieht jemand einen Fehler? Ich möchte aus der erstellten record datei einen bestimmten record auslesen - mehr eigentlich nicht :? Muss ich an die Datei vom Typ Tperson 'recadressen.??' eine Endung hängen?? Wenn ja, was?? Ich bekomme keinen Fehler, aber auch keinen Inhalt im Memo. ABER die Warnung, dass person nicht initialisiert wurde in Zeile (siehe Code). Aktueller Code:
Code:
[...]
type Tperson=record nachname:string[20]; vorname:string[10]; plz:string[5]; ort:string[20]; strasse:string[20]; hausnummer:string[5]; vorwahl:string[5]; telefon:string[10]; end; [...] const recordsize = sizeof(Tperson); var Form1: TForm1; [...] function linetorec(var s:string):Tperson; //hier sollen später wenn person.nachname funktioniert die weiteren const //Eigenschaften von Tperson zugewiesen werden, d.h. semi = ';'; //ich will den string bis zum ersten semikolon löschen und wieder var //über pos nach dem neuen ersten semikolon suchen, dann wieder semiPos: integer; //löschen usw. person: Tperson; begin semiPos:=0; semiPos:=Pos(semi, s); person.nachname:= copy(s, 0, semiPos -1); result:=person; end; procedure TForm1.Button1Click(Sender: TObject); //Konvertieren: inhalt textfile an record datei übergeben var srcfile: textfile; destfile: file of Tperson; line: string; person: Tperson; begin assignfile(srcfile,'adressen.txt'); //Quelle öffnen reset(srcfile); assignfile(destfile,'recadressen.dat'); //Ziel öffnen rewrite(destfile); memo1.clear; while not eof(srcfile) do begin repeat readln(srcfile, line) //Zeile lesen until line <> ''; //bis irgendwas in line drin ist linetorec(line); //aus der Zeile, person(Tperson) machen write(destfile, person); //die Zieldatei (record) beschreiben.*Warning: Local var person does //not seem to be initialized. end; closefile(destfile); closefile(srcfile); end; procedure TForm1.Button2Click(Sender: TObject); //destfile lesen + ins memo var rec_pos: integer; anz_recs: integer; person: Tperson; destfile: file of Tperson; begin rec_pos:=strtoint(edit1.text); //gewünschte Person aus Edit1 lesen anz_recs:=filesize('recadressen') div recordsize; //grenzt die Eingabemögl. für Edit1 ein von 0..anz_recs label1.caption:=inttostr(anz_recs); assignfile(destfile, 'recadressen'); //record Datei öffnen reset(destfile); seek(destfile, rec_pos); //an die gewünschte Stelle fahren und read(destfile, person); //Person x auslesen memo1.clear; memo1.lines.add(person.nachname+...); //hier folgen später die weiteren Eigenschaften closefile(destfile); end; end. |
AW: Textdatei in Record Muster überführen
nun, wenn du die Datei unter einem bestimmten Namen speicherst (recadressen.dat)
solltest Du sie auch wieder unter dem gleichen öffnen. Ich würde an Deiner Stelle beim Abspeichern und Laden den Pfad mit angeben. Edit1:
Delphi-Quellcode:
ist meines Erachtens falsch.
anz_recs:=filesize('recadressen') div recordsize;
Bei typisierten Dateien gibt fileSize die Anzahl der Datensätze zurück und die die Dateigröße in Byte. Grüße Klaus |
AW: Textdatei in Record Muster überführen
Ganze Pfade eingeben klappt leider auch nicht.
Gebe ich filesize('recadressen') auf ein Label aus erhalte ich 1133.= das entspricht der Größe in byte Gebe ich recordsize auf ein Label aus erhalte ich 103. = alle Stringlängen(20+10+5+20+20+5+5+10=95) + Anzahl Eigenschaften von Tperson(das sind 8)--> 95+8=103. filesize() div recordsize also 11. Ich habe 11 Personen in meiner Datei stehen. Kommt also zumindest hin. Bedeutet das, dass meine Datei recadressen nicht richtig typisiert wurde? |
AW: Textdatei in Record Muster überführen
aus der Delphi Hilfe:
Zitat:
Delphi-Quellcode:
Grüße
rec_pos:=strtoint(edit1.text); //gewünschte Person aus Edit1 lesen
für Edit1 ein von 0..anz_recs assignfile(destfile, 'recadressen'); //record Datei öffnen reset(destfile); anz_recs:=filesize(destFile); //grenzt die Eingabemögl. label1.caption:=inttostr(anz_recs); seek(destfile, rec_pos); //an die gewünschte Stelle fahren und read(destfile, person); //Person x auslesen memo1.clear; memo1.lines.add(person.nachname+...); //hier folgen später die weiteren Eigenschaften closefile(destfile); Klaus |
AW: Textdatei in Record Muster überführen
das hieße ja meine angebliche record datei wurde nicht so wirklich typisiert, oder? Aber was ist der Grund?
|
AW: Textdatei in Record Muster überführen
Delphi-Quellcode:
Grüße
procedure TForm1.Button1Click(Sender: TObject); //Konvertieren: inhalt textfile an record datei übergeben
var srcfile: textfile; destfile: file of Tperson; line: string; person: Tperson; begin assignfile(srcfile,'adressen.txt'); //Quelle öffnen reset(srcfile); assignfile(destfile,'recadressen.dat'); //Ziel öffnen rewrite(destfile); memo1.clear; while not eof(srcfile) do begin repeat readln(srcfile, line) //Zeile lesen until line <> ''; //bis irgendwas in line drin ist //linetorec(line); //lineToRec ist eine Funktion mit dem Rückgabewert TPerson person := lineToRec(line); write(destfile, person); //die Zieldatei (record) beschreiben.*Warning: Local var person does //not seem to be initialized. // oder write(destFile,lineToRec(line)); end; closefile(destfile); closefile(srcfile); end; Klaus |
AW: Textdatei in Record Muster überführen
Vielen vielen Dank. :-D
Das war der Haken, hatte irgendwie an Prozeduren gedacht! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:10 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