Textdatei öffnen und gezielt bearbeiten
lima-city → Forum → Programmiersprachen → C/C++ und D
arbeiten
beispiel
block
buffer
code
compiler
datei
fenster
frage
funktion
funktionieren
http
problem
programm
sagen
teil
unterschied
url
windows
zeile
-
Hallo,
ich möchte eine Textdatei verarbeiten und da es bei mir bald über 5 Jahre her ist, dass ich C++ programmiert habe, merke ich gerade, dass ich sehr eingerostet bin.
Bei meiner Problematik sollte es reichen ein Konsolenprojekt zu machen.
Um eine Datei zu öffnen, habe ich schon von der Funktion fopen gelesen, aber auch von OPENFILENAME.
Gibt es da einen großen Unterschied? Letzteres hat wohl viel mehr Parameter.
Was ich tun möchte ist folgendes:
1. Eine Datei öffnen
2. bestimmte Zeilen herauslöschen
3. gezielt einen Char in der Zeile überprüfen, ob er sich ändert
4. bestimmte Chars aus mehreren Zeilen auslesen und daraus einen Mittelwert bilden und sie danach löschen
=> also bestimmte Chars in der Zeile ändern / ersetzen
5. das ganze unter einem neuen Dateinamen speichern
Meine Textdatei ist nach folgendem Schema aufgebaut
Anzahl: 335.380 Start: 22.08.2011 11:11:18 Stop: 22.08.2011 11:57:49 AD= 01 t90= min. tCL= OFF Min: 299,0°C Max: 739,6°C Sekunden No. Datum Zeit nach 0:00h Temp. Emi 1 22.08.2011 11:11:18 40278,761 299,0 °C 0,940 2 22.08.2011 11:11:18 40278,769 299,0 °C 0,940 3 22.08.2011 11:11:18 40278,777 299,0 °C 0,940 4 22.08.2011 11:11:18 40278,784 299,0 °C 0,940 5 22.08.2011 11:11:18 40278,792 299,0 °C 0,940 6 22.08.2011 11:11:18 40278,813 299,0 °C 0,940 7 22.08.2011 11:11:18 40278,821 299,0 °C 0,940 8 22.08.2011 11:11:18 40278,829 299,0 °C 0,940 9 22.08.2011 11:11:18 40278,837 299,0 °C 0,940 10 22.08.2011 11:11:18 40278,844 299,0 °C 0,940 11 22.08.2011 11:11:18 40278,852 299,0 °C 0,940 12 22.08.2011 11:11:18 40278,860 299,0 °C 0,940 13 22.08.2011 11:11:18 40278,868 299,0 °C 0,940 14 22.08.2011 11:11:18 40278,876 299,0 °C 0,940 15 22.08.2011 11:11:18 40278,883 299,0 °C 0,940 16 22.08.2011 11:11:18 40278,891 299,0 °C 0,940 usw.
Da es zu viele Werte pro Sekunde sind, möchte ich also unnötige Werte herauslöschen und später, wenn sich die Temperatur ändert, einen Mittelwert bilden und die Zeilen herauslöschen und nur 2 Zeilen behalten.
Könnte mir jemand kleine Beispielschnippsel für die gefragten Aufgaben zeigen? Das wäre wirklich super :)
Und welche Funktion wäre für meine Zwecke besser? fopen oder OPENFILENAME?
Gruß,
Alex
Beitrag zuletzt geändert: 4.11.2011 17:56:24 von karikato -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hi karikato,
Zu Openfilename kann ich jetzt wenig sagen, dafür aber mehr zu fopen, welches du ruhig verwenden kannst. fopen stammt ursprünglich aus C, kann aber natürlich auch in C++ genutzt werden. Mit fopen kannst du die Datei nur öffnen und einen Dateizeiger erzeugen. Lesen musst du mit einer anderen Funktion.
Bevor es ans Eingemachte geht, muss ich dir noch folgende Fragen stellen, da ich die Umstände noch nicht 100%-ig verstanden habe.
- Wer bzw. welches Programm schreibt diese Datei?
- In welchen Intervallen wird diese Datei aktualisiert?
- Oder soll dein Programm auf einer Kopie der Datei arbeiten?
Warum ich diese Fragen stelle? Prinzipiell kann nur ein Programm auf eine Datei zugreifen, aus diesem Grund muss man auch den Dateizeiger wieder mit fclose schliessen.
Ein Beispielcode, der deinem Beispiel recht ähnlich ist, findest du hier (Kapitel 16.9). Schau dir da die arbeitsweise der Funktion fscanf an, die bietet einen ziemlich bequemen Zugriff auf die Werte. Du musst nur aufpassen, dass du dich in der richtigen Zeile in der Datei befindest... Achso, in dem Kapitel 16 steht generell etwas zur Dateiein- und -ausgabe. -
Hallo tangoal,
danke sehr für den Hinweis mit den Beispielen, werd ich mir mal morgen in Ruhe durchlesen :)
Also der Einsatz des Programmes soll der Datenverarbeitung dienen. Das heißt, ich habe eine txt Datei vorliegen und möchte diese kopieren und die Kopie bearbeiten (kürzen, da die rohe Messdatendatei trotz des txt Formates häufig über 50 MB groß ist)
Deshalb wäre es auch immer nur dieses eine Programm, das auf die Datei zugreift.
Entsprechend ist es egal, in welchem Intervall es aktualisiert werden soll. Hauptsache, es liegt ein Endprodukt vor.
Ach ja, was mir noch eingefallen ist. Die Funktionen fscanf usw. arbeiten ja rein in der Konsole, wodurch man den absoluten Pfad immer von selbst eintippen muss. Da es sehr mühselig ist, wäre es schön eine Lösung mit einem aufploppenden Fenster zu haben, deshalb kam ich auch auf OpenFileName, oder GetOpenFileName (wenn ich mich gerade nicht irre).
Gibt es da eine gute Lösung? -
Achso, ok. Dann stellt das Lesen aus der Datei kein Problem dar. Es klang bei deinem ersten Beitrag so, als ob das Messprogramm (welches weitere Daten hinzufügt) und dein Programm gleichzeitig darauf zugreifen wollen. Von daher mein Hinweis. Ist aber nicht der Fall und alles ist also in Butter
Du arbeitest mit Visual C++ von Microsoft nehme ich an? GetOpenFilename ist ein Befehl mit dem man ein Dialogfenster öffnet, um einen Dateinamen auszuwählen. Das musst du natürlich machen, wenn du eine fensterbasierte Benutzeroberfläche hast. Ich kenn den Befehl eigentlich nur aus VBA, aber du meinst wohl diesen hier in VC++. Vielleicht hilft dir dieses Beispielweiter.
Das du GetOpenFilename oder so verwendest heißt nicht, dass du die Datei nicht auch auswerten musst (öffnen, auslesen u. ändern, schließen). Dies kannst du mit den Befehlen fopen, fscanf, fprintf und fclose machen.
Viele Grüße
-
Ich habe gehofft nicht unbedingt mit VC++ arbeiten zu müssen, da ich auch mal ein Beispiel gesehen habe, bei dem das ganze Programm in der Konsole abläuft, man aber dennoch nur diesen einen Aufruf von einem aufploppenden Fenster hat.
Müsste ja gehen, wenn man die windows.h einbindet.
Auf den Eintrag bei MSDN bin ich auch schon mal gestoßen, da ich bei GetOpenFilename leider auch das Problem hatte, dass er diese Funktion als nicht deklariert erkennt und die Comdlg32 als Library bzw. als dll finde ich leider nicht.
Aber du hast natürlich recht, ich müsste ja nur mit Hilfe eines Fensters den Pfad der ausgewählten Datei an fopen und Konsorten übergeben können :) -
Genau, dann versuch erst die Funktionalität des Programms herzustellen. Die Auswahl eines Dateinamens über ein Dialogfenster kann man immer noch machen, wenn das ganze Programm richtig funktioniert. Konsolenprogrammen kann man aber auch Parameter übergeben, sodass ein Dialogfenster nicht mal notwendig wäre.
-
Hallo karikato,
wenn Du uns verraten würdest, welchen Compiler Du verwendest, dann könnte man Dir wahrscheinlich auch sagen, was Du verlinken musst, damit der Dialog funktioniert.
Beim gcc sollte es z.B. mit "-lcommdlg32" als Linker- bzw. Compiler-Flag funktionieren. Windows.h sollte mitgeliefert und bereits im Pfad sein.
Um die Datei dann zu öffnen kannst Du das bereits erwähnte fopen() verwenden. Wenn es mehr in Richtung C++ gehen soll, dann kann man es mit der ifstream-Klasse für das Einlesen und der ofstream-Klasse zum Schreiben machen.
Nachdem das Format der Datei für eine automatische Verarbeitung jetzt etwas ungünstig ist, wirst Du einigen Aufwand beim Parsen haben.
Ich würde die Datei an Deiner stelle zeilenweise einlesen. Die eingelesen Zeile würde ich dann Splitten, d.h. bei den Leerzeichen bzw. Tabulatoren in einzelne, kleinere Strings zerlegen. Das kannst Du mit strtok() machen. Auf jeden Fall musst Du die ',' (Kommas) durch '.' (Punkt) ersetzen weil sscanf sonst die Zahlen nicht als Fließkommazahl einlist und Du nur den Ganzzahlteil bis zum Komma erhälst.
Der Rest sollte dann nicht mehr so schwer sein. -
Hallo darkpandemic,
zu Hause habe ich bisher mit Code:Blocks als IDE gearbeitet und wxWidgets als Compiler eingestellt (wenn ich mich grad nicht vertue).
Bei der Arbeit seh ich grad, dass ich Visual Studio 2010 habe.
Macht es einen großen Unterschied? Muss ich bei VS 2010 auch die -lcomdlg32 includen, oder reicht da die windows.h?
Habe nämlich bei einem Beispiel gesehen, dass der Autor nur windows.h inkludiert hat und es hat bei ihm dennoch problemlos geklappt GetOpenFilename zu benutzen.
Noch eine Frage:
Wie kann ich explizit die Datei zeilenweise auslesen? Denn genau das müsste ich ja sowieso machen.
Und wenn ich die Zeilen als Strings habe, kann ich ja mit string[xx] einzelne Werte auslesen und als Integer konvertieren und rechnen, richtig? -
Hallo karikato,
wenn Du Code::Blocks hast, dann ist wahrscheinlich gcc der Compiler. wxWidgets ist ein GUI-Toolkit, d.h. damit kann man graphische Benutzeroberflächen gestallten.
Um comdlg32 zu verlinken musst Du in Code::Blocks auf das Menü 'Project'->'Build options...' klicken. Im erscheinenden Dialog wählst Du dann das Register 'Linker settings'. Dort musst Du dann auf die 'Add'-Schaltfläche klicken und im erscheinenden Dialog 'comdlg32' eintragen. Dann noch alles mit 'Ok' bestätigen (2x) und dann sollte GetOpenFilename() funktionieren (windows.h inkludieren).
Das zeilenweise Einlesen der Datei kannst Du mit fgets() machen.
Das sieht dann so aus:
Die Zeile steht immer in 'buffer'.Man sollte darauf achten, dass man 'buffer' so groß wählt, dass eine Zeile darin locker platz hat. Sonst erhält man nämlich nur einen Teil der Zeile.#include <stdio.h> #include <stdlib.h> int main(int argc, char ** argv) { FILE * fin; char buffer[256]; int linenumber; if(!(fin = fopen("test.dat", "r"))) { fprintf(stderr, "Error: main: fopen() failed.\n"); return -1; } linenumber = 1; while(fgets(buffer, sizeof(buffer), fin)) { printf("%03d: %s", linenumber, buffer); linenumber++; } if(ferror(fin)) { fprintf(stderr, "Error: main: fgets() failed.\n"); fclose(fin); return -1; } fclose(fin); return 0; }
Wie ich schon weiter oben erwähnt habe würde ich die Zeile dann mit strtok() splitten. Anschließend kannst Du die Werte dann mit sscanf() konvertieren. Allerdings würde ich nicht Integer sonder float oder double nehmen, da die Werte in der Datei ja zum Teil keine ganzen sondern Fließkommazahlen sind. Das ist dann auch für Mittelwertberechnungen besser.
#include <stdio.h> #include <stdlib.h> int main(int argc, char ** argv) { char token[256] = "2.134"; float value_f; double value_d; sscanf(token, "%f", &value_f); sscanf(token, "%lf", &value_d); printf("%f, %lf\n", value_f, value_d); return 0; }
Beitrag zuletzt geändert: 7.11.2011 20:10:51 von darkpandemic -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage