Entwickler-Ecke
Dateizugriff - txt Datei: Bis zu Zeichen auslesen
Thunfisch - Do 23.06.11 11:22
Titel: txt Datei: Bis zu Zeichen auslesen
Hallo :) (ist glaube ich mein erster Post)
Ich habe Informatik in der Schule im 4. Jahr aber mache erst seit einem 3/4 Jahr Delphi.
Wir sollten uns gegen Schluss des Schuljahres ein Projekt aussuchen, was wir dann selbst verwirklichen.
Ich habe mir einen Vokabeltrainer vorgenommen :)
Da ich (grade mal) mit txt-dateien umgehen kann, speicher ich die eingegebenen Vokabeln in einer txt-Datei.
Mein Problem besteht beim Auslesen:
Ich möchte, dass man die ausgelesene Vokabel zum Abfragen benutzen kann sowie dass man aus den ganzen Vokablen bspw. 20 random ausliest.
Meine Lösung dafür wäre, dass ich alle Vokabeln auslese und dann in ein Array speicher. Aber wie ich die einzelnen Eigenschaften der Vokabeln abspeichern kann ist mir ein Rätsel.
Hier nochmal ein Beispiel aus meiner Vokabel.txt :
1#fisch#fish#chicken
2#Haus#House#House
3#Haus#House#House
4#Hallo#hi#hi
5#Brother#Bruder#Bruder
6# Frieden#Peace# war
7#Mutter#mother#UNBEKANNT
8#Maus#Mouse#Mouse
9#Auto#Car#
ID;#;Deutsch;#;Englisch1;#;Englisch2
# soll als Trennzeichen dienen
MFG Thunfisch
PS: ich benutze delphi 6 !
MaxWurzel - Do 23.06.11 11:38
Du kannst z.B. ein record benutzen
Delphi-Quelltext
1: 2: 3: 4: 5:
| type Vokabel = record deutsch: string; englisch1: string; englisch2: string; end; |
[quote="[user]5#Brother#Bruder#Bruder
ID;#;Deutsch;#;Englisch1;#;Englisch2
quote]
?
Thunfisch - Do 23.06.11 11:44
Jo fast genau den benutze ich ;)
Aber mir gehts ja mehr ums Auslesen
Jann1k - Do 23.06.11 11:52
Hast du Probleme beim Auslesen der Zeilen aus deiner .txt Datei oder beim Auslesen der einzelnen Eigenschaften?
Für letzteres gibt es die Funktionen Pos und PosEx, damit kannst du in deiner Zeile nach den Trennzeichen suchen und dir dann mithilfe von Copy die passenden Stringteile auslesen lassen.
MaxWurzel - Do 23.06.11 12:08
Du kannst die txt-Datei in eine Stringlist laden
Delphi-Quelltext
1: 2: 3: 4:
| var vokabelliste: TStringlist;
vokabelliste := TStringlist.Create; vokabelliste.LoadFromFile(xxx.txt); |
und dann auf die Zeilen mit
Delphi-Quelltext
1:
| vokabelliste.Strings[i] |
zugreifen.
Webo - Do 23.06.11 12:36
Also, wenn es es ums Auslesen geht werfe ich mal ein paar Begriffe in den Raum:
Einlesen kannst du die Datei wie
MaxWurzel schreibt, die Wörter dann wie folgt.
(Situation: Du hast z.B. die erste Zeile der Textdatei in einen String s geladen)
- s[i] gibt dir das Zeichen an i-ter Position zurück
- pos('ch',s) gibt dir die Position des ersten Vorkommens von "ch" wieder, wenn es in s vorhanden ist (-1 wenn nicht)
- posex('ch', s, 3) wie pos, jedoch sucht es erst ab Position 3
- copy(s,2,5) gibt dir den Bereich des String zwischen der Position 2 und 5 wieder (kopiert also den Bereich)
Wenn du dir damit Gedanken machst hast du genug Möglichkeiten wie du die Wörter einliest.
Thunfisch - Do 23.06.11 13:34
Super :D
Vielen Dank an euch :)
Läuft jetzt sogut wie alles
Thunfisch
Stundenplan - Do 23.06.11 15:46
Webo hat folgendes geschrieben : |
copy(s,2,5) gibt dir den Bereich des String zwischen der Position 2 und 5 wieder (kopiert also den Bereich) |
Nicht ganz. ;-)
Copy(s, 2, 5) kopiert dir den Bereich ab Position 2
mit der Länge 5! :idea:
Viele Grüße,
Stundenplan.
Bergmann89 - Do 23.06.11 16:19
Hey,
als Ergänzung: dafür gibts es auch vorgefertigte Methoden. z.B. über eine Stringlist:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var List: TStringList;
List := TStringList.Create; try List.Delimiter := '#'; List.DelimitedText := '1#fisch#fish#chicken'; List[0] List[1] finally List.Free; end; |
MfG Bergmann.
Webo - Do 23.06.11 16:34
Stundenplan hat folgendes geschrieben : |
Nicht ganz. ;-) Copy(s, 2, 5) kopiert dir den Bereich ab Position 2 mit der Länge 5! :idea: |
Stimmt, jetzt wo du es sagst 8) Gut, dass immer wer aufpasst ...
jaenicke - Do 23.06.11 16:52
Bergmann89 hat folgendes geschrieben : |
als Ergänzung: dafür gibts es auch vorgefertigte Methoden. z.B. über eine Stringlist: |
Die Stringlist trennt aber auch bei Leerzeichen, wenn keine Anführungszeichen gesetzt sind. Erst bei neueren Delphiversionen gibt es dagegen StrictDelimiter, aber das kam erst mit Delphi 2006 oder so, evtl. auch schon D7. Aber bei D6, das er nutzt, gab es das auf jeden Fall noch nicht.
Thunfisch - Do 23.06.11 19:13
Habe mir grade ne neuere Version von meinem Lehrer zukommen lassen.
Die ist 7.0 - kann ich damit StrictDelimiter benutzen?
jaenicke - Do 23.06.11 19:28
Jetzt zu Hause habe ich gerade nachgeschaut, nein, wie ich schon dachte geht es da noch nicht. StrictDelimiter wurde mit Delphi 2006 eingeführt, Delphi 1-7 und 2005 kannten das noch nicht.
Es selbst zu machen ist aber ohnehin die bessere Übung. ;-)
Thunfisch - Di 28.06.11 22:21
Bergmann89 hat folgendes geschrieben : |
Hey,
als Ergänzung: dafür gibts es auch vorgefertigte Methoden. z.B. über eine Stringlist:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var List: TStringList;
List := TStringList.Create; try List.Delimiter := '#'; List.DelimitedText := '1#fisch#fish#chicken'; List[0] List[1] finally List.Free; end; |
MfG Bergmann. |
Dazu habe ich nochmal eine Frage:
Bei
List.DelimitedText := '1#fisch#fish#chicken'; was genau muss ich da eintragen? Nimmt der diesen String dann als Muster? Oder sollte ich da Variablen eintragen? (Vok.deutsch, Vok.Id , usw.?)
Sorry wenn ich den Thread unnötigerweise pushe, aber einen neuen Thread zu erstellen erschien mir überflüssig.
Mfg Thunfisch :)
MDX - Di 28.06.11 23:18
Mhm, also für die Trennung von einer Vokabel in die "drei" Sprachen kannst du auch Explode nutzen...
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:
| function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; var SepLen: Integer; F, P: PChar; ALen, Index: Integer; begin SetLength(Result, 0); if (S = '') or (Limit < 0) then Exit; if Separator = '' then begin SetLength(Result, 1); Result[0] := S; Exit; end; SepLen := Length(Separator); ALen := Limit; SetLength(Result, ALen);
Index := 0; P := PChar(S); while P^ <> #0 do begin F := P; P := AnsiStrPos(P, PChar(Separator)); if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); if Index >= ALen then begin Inc(ALen, 5); SetLength(Result, ALen); end; SetString(Result[Index], F, P - F); Inc(Index); if P^ <> #0 then Inc(P, SepLen); end; if Index < ALen then SetLength(Result, Index); end; |
Thunfisch - Di 28.06.11 23:43
Das ist mir um ehrlich zu sein ein bisschen zu kompliziert :/
Da würde ich lieber die obengenannte Problemlösung nehmen ..
MDX - Di 28.06.11 23:51
Mh eigentlich ganz easy, du deklarierst einfach:
Delphi-Quelltext
1:
| type TSTringdynarray = array of String; |
Dann deklarierst du eine Variable als Array und machst dann einfach:
Delphi-Quelltext
1:
| Variable:=Explode(String,'#'); |
dann hast du zum Beispiel Deutsch in
Variable[0]; und Englisch1 in
Variable[1];
jaenicke - Mi 29.06.11 05:55
Thunfisch hat folgendes geschrieben : |
Bei List.DelimitedText := '1#fisch#fish#chicken'; was genau muss ich da eintragen? |
Den String, den du auseinander nehmen willst.
Aber wie gesagt: Es dürfen bei dieser Methode keine Leerzeichen drin vorkommen, sonst wird bei deinem Delphi dort auch getrennt.
Thunfisch - Mi 29.06.11 15:42
Es kommen keine Leerzeichen vor
Dafür habe ich schon gesorgt :D
@ Jaenicke
Kann ich da auch Tstringarray[i] eintragen?
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:
| function TForm1.StrToVokabelInfo(Str: String): TVokabelInfo;
var temp: TVokabelInfo; i, j: Integer; tempID: String; begin j := 1;
for i := 1 to Length(Str) do begin if Str[i] = '#' then Inc(j);
if j = 1 then begin if Str[i] <> '#' then begin tempID := TempID + Str[i]; end; end;
if j = 2 then begin if Str[i] <> '#' then begin temp.Deutsch := temp.Deutsch + Str[i]; end; end;
if j = 3 then begin if Str[i] <> '#' then begin temp.Englisch := temp.Englisch + Str[i]; end; end;
end;
temp.ID := STRTOINT(tempID);
if ADMIN then ShowMessage('Vokabel ' + IntToStr(temp.Id) + ', deutsch: ' + temp.Deutsch + ', englisch: ' + temp.Englisch); |
Kann mir einer sagen, wo da der fehler ist :D?
jaenicke - Mi 29.06.11 16:22
Thunfisch hat folgendes geschrieben : |
Kann mir einer sagen, wo da der fehler ist :D? |
Der Fehler ist, dass du die Fehlerbeschreibung vergessen hast. :zwinker:
Jedenfalls hat j den Wert 1. Da du den nie änderst, können die anderen if-abfragen auf j = 2 und j = 3 nie true ergeben.
Thunfisch - Mi 29.06.11 16:52
Oh mann :/
Ich schaffs einfach nicht. Immer irgendwelche komischen Fehler. Langsam verzweifle ich :(
Ich muss im Prinzip nur wissen, wie ich 1#fisch#fish sowas auslese und in einem record speichere
Also eine ganze Textdatei mit mehreren solcher Strings...
Jann1k - Mi 29.06.11 19:20
Zitat: |
Immer irgendwelche komischen Fehler. |
Wie jaenicke auch schon angemerkt hat: Wenn du uns nicht sagst, welche komischen Fehler bei dir auftauchen, können wir nur schlecht helfen. Der Code oben sieht korrekt aus und scheint zu funktionieren (jdf. bekomme ich die richtige showmessage ausgabe).
Thunfisch - Mi 29.06.11 19:34
wenn ich versuche die funktion aufzurufen kommt : Nicht genügend wirkliche parameter
Habe ich shcon gegoogelt und dort stand, dass man sich den quellcode nochmal ganz genau anschauen sollte
Jann1k - Mi 29.06.11 19:46
Nicht genügend wirkliche parameter, sagt doch eigentlich was da fehlt, dir fehlt ein (oder mehrere) Parameter ;) Zeig mal wie du die Funktion im Quelltext benutzt.
Thunfisch - Mi 29.06.11 19:52
Ich hab es einfach so ausprobiert :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.b_testClick(Sender: TObject);
begin
StrToVokabelInfo() ;
end; |
Und wie kann ich eine einfache Abfrage gestalten von allen vokabeln die in der text datei liegen ?
Jann1k - Mi 29.06.11 20:00
Hast du die Funktion selbst geschrieben? In der Signatur steht doch, dass der du Funktion auch einen String als Parameter übergeben musst (dieser wird dann in ein TVokabelInfo umgewandelt). Also ungefähr so:
Delphi-Quelltext
1:
| StrToVokabelInfo('12#mutig#brave') ; |
Thunfisch - Mi 29.06.11 20:02
Und wie kann ich eine einfache Abfrage gestalten von allen vokabeln die in der text datei liegen ?
Aber kann ich da auch meine ganze vokabel list reinsetzen? also wenn ich die vorher in eine Tstringlist geladen habe
Jann1k - Mi 29.06.11 20:06
Am einfachsten wäre es, wenn du alle Einträge der TStringlist durchgehst und für jeden Eintrag die Funktion aufrufst.
Achte aber drauf, dass du mit den Rückgabewerten der Funktion auch was anstellst, sonst sind die nämlich weg ;)
Thunfisch - Mi 29.06.11 20:13
Ja mensch cih hab total den Blackout
Wie wäre es mit :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var testlist : Tstringlist; ShortSpeicher : array[3..,500..];
begin testlist := tstringlist.create ; testlist.loadfromfile('vokabeln.txt') ;
For i := 1 to ID begin StrToVokabelInfo(testlist[i]) ;
ShortSpeicher[1,i] := testlist[i].ID; Shortspeicher[2,i] := testlist[i].detusch; Shortspeicher[3,i] := testlist[i].englisch;
end; |
Ich bekomme immer, wenn ich StrtoVokabelinfo() aufrufe eine fehlermeldung: [Fehler] Unit1.pas(275): Inkompatible Typen: 'String' und 'TStringList'
Jann1k - Mi 29.06.11 20:25
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var i:integer; testlist : Tstringlist; ShortSpeicher : array[0..500] of TVokabelInfo;
begin testlist := tstringlist.create ; testlist.loadfromfile('vokabeln.txt') ;
For i := 0 to testlist.count-1 ShortSpeicher[i]:=StrToVokabelInfo(testlist.lines[i]) ;
testlist.free(); end; |
Das klappt immerhin schonmal, wenn insgesamt weniger als 500 Vokabeln vorhanden sind (besser wäre es die Anzahl der Vokabeln dynamisch auszulesen). ShortSpeicher sollte aber global definiert werden, sonst sind die eingelesenen Daten am Ende der Prozedur auch wieder weg.
Thunfisch - Mi 29.06.11 20:40
Warum denn keine Matrix mehr?
Jann1k - Mi 29.06.11 20:41
Wofür willst du die Matrix haben? Du hast doch schon dein Record TVokabelInfo, dann kommst du mit ShortSpeicher[i].deutsch etc. bequem an die Werte.
Thunfisch - Mi 29.06.11 21:07
Hier habe ich mir eine neue funktion geschrieben aber mittels alt+v eingefügt und jetzt meldet mir delhpi eine Menge komischer Probleme.
Wie muss ich diese procedure oben in die types einfügen?
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:
| procedure TForm1.StrToVokabelInfo(str: string; var vokabel: TVokabel); var i, j: integer; temp1: string; begin vokabel.id ''; vokabel.Deutsch := ''; vokabel.Englisch := ''; i := 1; while str[i] <> '#' do begin vokabel.id := vokabel.id + str[i]; i := i + 1; end;
i := i + 1; while str[i] <> '#' do begin vokabel.Deutsch := vokabel.Deutsch + str[i]; i := i + 1; end; for j := i + 1 to length(str) do begin vokabel.Englisch := vokabel.Englisch + str[j]; end; end; |
Jann1k - Mi 29.06.11 21:26
"Eine Menge komischer Probleme" ist eine saubere Fehlerbeschreibung.
Weißt du eigentlich was du da machst? In der ersten zeile fehlt dir ein Zuweisungsoperator und wenn du aus ID nicht jetzt einen String gemacht hast (vorher wars ein integer) klappt deine erste Teilschleife so nicht.
P.S: Die Meldungen der komischen probleme sagen dir eigentlich recht deutlich wo etwas im argen liegt.
Thunfisch - Mi 29.06.11 21:39
sorry für die ungenaue beschreibung. Hier nochmal alle fehlermeldungen, die ich bekomme (Ich denke durch die richtige definierung in type lösen sich die meisten):
[Fehler] Unit1.pas(41): Undefinierter Bezeichner: 'TVokabel' (habe ich definiert)
[Fehler] Unit1.pas(56): Bezeichner redefiniert: 'TVokabel'
[Fehler] Unit1.pas(93): Operator oder Semikolon fehlt (mitten in der zeile bzw befehl)
[Fehler] Unit1.pas(94): Operator oder Semikolon fehlt (mitten in der zeile bzw befehl)
[Fehler] Unit1.pas(104): ',' oder ')' erwartet, aber Bezeichner 'D' gefunden
[Fehler] Unit1.pas(104): Operator oder Semikolon fehlt
[Fehler] Unit1.pas(201): Inkompatible Typen: 'TObject' und 'String'
[Fehler] Unit1.pas(213): Deklaration von 'StrToVokabelInfo' unterscheidet sich von vorheriger Deklaration
[Fehler] Unit1.pas(218): Operator oder Semikolon fehlt
Und noch ca 10 mal operator oder semikolon fehlt
Wie gesagt
Zitat: |
Ich denke durch die richtige definierung in type lösen sich die meisten |
Also ich brauch nur wissen wie man die prozedur manuell in die type deklaration einträgt. Den Rest bekomme ich selbst hin
Oliver Maas - Mo 04.07.11 17:47
Hi
ich bin vermutlich spät dran, aber du hast ja (nehme ich an) ein Formular der Klasse TForm1,
darunter gibt es dann ja private ... public ... end;
Wenn du die procedure private haben willst, dann schreib unter private
Quelltext
1:
| procedure StrToVokabelInfo(str: string; var vokabel: TVokabel); |
zudem kannst du ja TVokabel vor TForm1 deklarieren.
viele Grüße
Olli
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!