kostenloser Webspace werbefrei: lima-city


Textdatei öffnen und gezielt bearbeiten

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    karikato

    Kostenloser Webspace von karikato

    karikato hat kostenlosen Webspace.

    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
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. 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.
  4. Autor dieses Themas

    karikato

    Kostenloser Webspace von karikato

    karikato hat kostenlosen Webspace.

    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?
  5. 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

  6. Autor dieses Themas

    karikato

    Kostenloser Webspace von karikato

    karikato hat kostenlosen Webspace.

    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 :)
  7. 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.
  8. 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.
  9. Autor dieses Themas

    karikato

    Kostenloser Webspace von karikato

    karikato hat kostenlosen Webspace.

    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?
  10. 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:
    #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;
    }
    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.
    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
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!