![]() |
Textdatei (txt) in Stringgrid einlesen
Hey
Ich will etwas in einen Stringgrid einlesen aus einer Textdatei (*.txt). Es geht darum Buchstaben + der zugehörigen Häufigkeit einzulesen. Dabei ist es wichtig, dass der Häufigste Buchstabe mit der Häufigkeit oben steht. Die Häufigkeit und der Buchstabe sollen aber in getrennte Zeilen. Vielleicht könnte man eine Textdatei nach diesem Muster erstellen: A(17%) B(2%) C(4,5%) ... Dabei die Buchstaben in das eine, die Zahlen in das andere einlesen. Was vermutlich viel aufwändiger wäre, dann noch alles nach größe zu sortieren. Daher ist es wohl besser die Zahlen schon in der Textdatei geordnet vorzuliegen zu haben. Wichtig ist mir hierbei auch, dass ich gerne Denkanstöße annehme, jedoch nichts vorprogrammiert haben will. Ich weiß gar nicht wie man erwarten kann, wenn man sich Programmieren selber beibringt, gesagt zu bekommen: Benutze das und das. Wenn man dann nochmal nachfragt heißt es gleich: Musst du schon selber machen. Den Lerneffekt verstehe ich dabei gar nicht. (War nicht hier) Vielen Dank Pascall |
Re: Textdatei (txt) in Stringgrid einlesen
Teile die Aufgabe auf:
1. Textdatei einlesen und Buchstaben zählen. Ausgabe z.B. mit WriteLn als konsolenanwendung. 2. Die Ausgabe (also das Ergebnis) sortieren. 2. Wenn das Ergebnis stimmt, dann die Ergebnisse in ein Stringgrid schreiben. Dazu musst du dann ein neues Projekt starten, kannst aber die Ergebnisse (den Code) aus 1 und 2 verwenden... |
Re: Textdatei (txt) in Stringgrid einlesen
Was ist denn jetzt dein konkretes Problem? Was hast du schon an Code? Was erwartest du jetzt von uns?
|
Re: Textdatei (txt) in Stringgrid einlesen
Hallo Pascall,
Ich würde es so lösen: 1) array [0..255] of integer wobei jede Array-Zelle für einen Buchstabe/Zeichen steht. mit 0 initialisieren. 2) Textdatei Zeichen für Zeichen lesen und das Zeichen als Index des Arrays verwenden und dann inc(a[ord(Zeichen)],1); (natürlich gepuffert alles andere wäre zu langsam) 3) Im Stringgrid die erste Spale mit den Zeichen vorbelegen, in der zweiten Spalte die im Array gespeicherten Zählungen. Gruß K-H |
Re: Textdatei (txt) in Stringgrid einlesen
Also, habe ich jetzt die Frage falsch verstanden?
Ich interpretiere das so, daß er den Inhalt des Stringgrids aus einer Textdatei laden will, in der die einzelnen Buchstaben zusammen mit ihrer Häufigkeit stehen. Wie diese Textdatei zustande kommt, hat damit gar nichts zu tun. Vielleicht gibt es ja solche Buchstabenhäufigkeitsdateien für verschiedene Sprachen oder sonstige Kriterien bereits. Man könnte die Textdatei einfach nach dem Name=Value Prinzip aufbauen, einfach in eine Stringlist laden und daraus dann das Stringgrid füllen.
Delphi-Quellcode:
lst := TStringList.Create; try lst.LoadFromFile(FileName); for I := 0 to lst.Count - 1 do begin StringGrid[0, I] := lst.Names[I]; StringGrid[1, I] := lst.ValueFromIndex[I]; end; finally lst.Free; end; |
Re: Textdatei (txt) in Stringgrid einlesen
Hey
Folgendes: Ich habe einen Stringgrid und will dort eine Textdatei einlesen. Die Textdatei soll etwa so aussehen: E (17,7) A (35,7) X (0,03) B (33,6) Dabei will ich die Buchstaben in die 4 Zeile einlesen und die Zahlen entsprechen passend in die 5. Zeile. Danach sollen Buchstaben + Zahlen sortiert werden (nach den Zahlen, aber Buchstaben müssen natürlich dabei bleiben) Das habe ich aber schon. Mir fehlt nur noch das einlesen Pascall @ Uwe: Deinen Ansatz verstehe ich leider nicht, sorry: Loadfromfile ist klar, mit try und finally habe ich noch nie gearbeitet @ p80286: Das mit dem puffern interessiert mich, ist das einfach zu programmieren? Das bräuchte ich nämlich auch noch für eine andere Sache... |
Re: Textdatei (txt) in Stringgrid einlesen
Hallo pascall,
das mit Try finally funktioniert so, daß wenn ein Fehler zwischen try und finally auftritt, die Verarbeitung sofort zur Anweisung nach finally springt. In Uwes Beispiel befindet sich vor Finally der "Leseabschnitt" und hinter finally der "Aufräumabschnitt" der auf jeden Fall ausgeführt werden sollte. Man könnte darüber streiten ob das unbedingt notwendig ist, ein Fehler ist es aber auf keinen Fall, da dann sicher gestellt ist, daß z.B. lst wieder aus dem Speicher verschwindet. [Edit] wenn Die Daten so erfasst sind, wie Du beschrieben hast, dann kommst Du mit CommaText oder Value nicht weiter, dann mßt Du mit pos('(',...) die eingelesenen Zeilen auseinander nehmen. [/Edit] "Puffern":
Delphi-Quellcode:
So in etwa sieht eine solche Leseroutine aus. Wobei für Dich der maxPuff der interessanteste Teil ist, da sollte man nicht zu sparsam sein. Puffer kann allerdings auch ein array of byte, oder array of char oder ... sein.
const
maxpuff = $FFFF; var puffer : array [0..maxPuff] of byte; fs : tfilestream; ... fs:=tfilestream.create(MyFilename,myAttributes); repeat gelesen:=fs.read(puffer,sizeof(puffer)); for i:=0 to gelesen do //....verarbeite puffer[i] ......... until gelesen<>sizeof(puffer); fs.free; wichtig ist hier nur, daß Du das nicht zu klein wählst. Gruß K-H |
Re: Textdatei (txt) in Stringgrid einlesen
Ich würde mir einen Record oder noch besser eine Klasse deklarieren, die die zusammenhängenden Daten beinhaltet. Dann die Textdatei einlesen, die einzelne Zeile parsen und dem Record/der Klasse die Einzelwerte zuweisen. Die Records/Objekte werden dann in einer Liste verwaltet, sortiert und im StringGrid ausgegeben. Hier das Ganze einmal in Code gepackt:
Delphi-Quellcode:
uses math;
//Deklaration der Klasse type TDatensatz = class private FBuchstabe: Char; FZahl: Double; public property Buchstabe: Char read FBuchstabe write FBuchstabe; property Zahl: Double read FZahl write FZahl; end; //Sortierfunktion function CompareFunc(Item1, Item2: Pointer): integer; begin if SameValue(TDatensatz(Item1).Zahl, TDatensatz(Item2).Zahl) then Result := 0 else if TDatensatz(Item1).Zahl < TDatensatz(Item2).Zahl then Result := -1 else Result := 1; end; procedure TfrmStringGridDemo.Button1Click(Sender: TObject); const Pfad = 'C:\Test\Test.txt'; //nur zum Testen hartkodiert var aObject: TDatensatz; aList: TStringlist; i, FirstBracket, SecondBracket: integer; s: string; begin //evtl. bereits enthaltene Objekte löschen FObjects.Clear; //Stringliste erzeugen und aus Datei einlesen aList := TStringlist.Create; try aList.LoadFromFile(Pfad); //Dafür sorgen, dass genügend Zellen im StringGrid verfügbar sind if (StringGrid1.ColCount - StringGrid1.FixedCols) < aList.Count then StringGrid1.ColCount := aList.Count + StringGrid1.FixedCols; if (StringGrid1.RowCount - StringGrid1.FixedRows) < 5 then StringGrid1.RowCount := StringGrid1.FixedRows + 5; //Datei zeilenweise auswerten, Objekt erzeugen, Werte zuweisen for i := 0 to aList.Count - 1 do begin aObject := TDatensatz.Create; if trim(aList[i]) <> '' then aObject.Buchstabe := trim(aList[i])[1]; FirstBracket := Pos('(',aList[i]); SecondBracket := Pos(')',aList[i]); s := Copy(aList[i],FirstBracket + 1, SecondBracket - FirstBracket - 1); aObject.Zahl := StrToFloatDef(s,0); //... und der Liste hinzufügen FObjects.Add(aObject); end; //Liste sortieren FObjects.Sort(@CompareFunc); StringGrid1.Rows[StringGrid1.FixedRows + 3].BeginUpdate; StringGrid1.Rows[StringGrid1.FixedRows + 4].BeginUpdate; try //... und Werte in der StringGrid ausgeben for i := 0 to FObjects.Count - 1 do begin StringGrid1.Cells[StringGrid1.FixedCols + i,StringGrid1.FixedRows + 3] := TDatensatz(FObjects[i]).Buchstabe; StringGrid1.Cells[StringGrid1.FixedCols + i,StringGrid1.FixedRows + 4] := FloatToStr(TDatensatz(FObjects[i]).Zahl); end; finally StringGrid1.Rows[StringGrid1.FixedRows + 3].EndUpdate; StringGrid1.Rows[StringGrid1.FixedRows + 4].EndUpdate; end; finally //Stringliste wieder freigeben aList.Free; end; end; //mit dem Formular Objektliste erzeugen procedure TfrmStringGridDemo.FormCreate(Sender: TObject); begin FObjects := TObjectList.Create; end; //und am Ende entsorgen procedure TfrmStringGridDemo.FormDestroy(Sender: TObject); begin FObjects.Free; end; |
Re: Textdatei (txt) in Stringgrid einlesen
@DeddyH
Ist die frühe Festlegung von RowCount und ColCount notwendig oder Dein pers. Stil? Gruß K-H |
Re: Textdatei (txt) in Stringgrid einlesen
@DeddyH: So werde ich es vermutlich machen, danke
@ p80286: Danke, dass mit dem try + finally habe ich kapiert. Was sinnvolles neues gelernt =). Jedoch das mit dem Puffern ist wohl eine Nummer zu hoch für mich, da blicke ich überhaupt nicht durch. Trotzdem vielen Dank für den Versuch. Bin ein Pascal Anfänger und das reicht mir auch erst Mal. Wenn ich die Schule beendet habe werde ich mich mit C++ vertraut machen und ich denke dafür reicht mein bisheriges kleines Wissen schon aus. Ein wirklich sehr nettes Forum hier, vielen Dank für eure ganze Hilfe. Ich wette es war nicht das letzte Mal, dass ich hier geschrieben habe =) |
Re: Textdatei (txt) in Stringgrid einlesen
Zitat:
|
Re: Textdatei (txt) in Stringgrid einlesen
Zitat:
|
Re: Textdatei (txt) in Stringgrid einlesen
@DeddyH
Zitat:
Delphi-Quellcode:
wichtig ist nur daß RowCount nicht kleiner 2 wird, damit die "grauen Überschriften" nicht verschwinden.
for i:=0 to xxxx.count-1 do
....... yyy.rowcount:=xxxx.count+1; Mein Vorgehen scheint nicht logisch aber es klappt. Oder hab ich nur Glück gehabt? Ich meine mich erinnern zu können, daß RowCount für die sichtbaren/anzeigbaren Zeilen steht, bin mir aber nicht sicher. (über den Speicher, den man da verbraten kann mach ich mir jetzt mal keine Gedanken) Gruß K-H |
Re: Textdatei (txt) in Stringgrid einlesen
Wenn ich von vornherein weiß, wieviele Zeilen/Spalten ich benötige, ist die Erhöhung innerhalb einer Schleife IMHO suboptimal. Und für die "grauen" Spalten/Zeilen habe ich ja FixedRows bzw. FixedCols mit berücksichtigt :zwinker:
|
Re: Textdatei (txt) in Stringgrid einlesen
Welche Schleife?
so ists deutlicher:
Delphi-Quellcode:
und wenn RowCount<2 ist, dann klappt das mit den FixedRows nicht mehr. (D2006 und D7)
for i:=0 to xxxx.count-1 do
begin ....... end; yyy.rowcount:=xxxx.count+1; Gruß K-H |
Re: Textdatei (txt) in Stringgrid einlesen
Ach, so war das gemeint. OK, dann spielt es keine Rolle, wann man RowCount/ColCount setzt, Hauptsache, vor dem ersten indizierten Zugriff. Und ja, Du hast recht, nur fixe Spalten oder Zeilen akzeptiert das Dingen nicht. Aber in meinen Augen ist das eh nicht die dollste Komponente der VCL, daher meide ich sie nach Möglichkeit.
|
Re: Textdatei (txt) in Stringgrid einlesen
Hallo,
und ich bevorzuge sie :wink: Es ist kein Problem das Array Cells mit Werten zu belegen auch wenn RowCount/ColCount kleiner als der Index für Cells ist. Auch ein Zugriff auf die Inhalte des Cells-Array verursacht keine Zugriffsverletzungen.
Delphi-Quellcode:
Grid.Cells[c,r], Grid.Cols[c] und Grid.Rows[r] sind unabhängig vom dem durch ColCount/RowCount definierten Bereich.
Grid.Cells[Grid.ColCount + 1000, Grid.RowCount + 1000] := 'Test';
Showmessage(Grid.Cells[Grid.ColCount + 1000, Grid.RowCount + 1000]); //erst wenn man was selectieren will, knallt es Grid.Row := Grid.RowCount + 1000;// "Gitterindex außerhalb" |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:40 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