Double formatiert in txt-Datei schreiben



  • Hallo allerseits,

    ich möchte einen double-Wert formatiert in einer txt-Datei schreiben. Mein Ansatz lautet wie folgt.

    #include <iostream> 
    #include <fstream> 
    #include <string> 
    #include <cstdio>
    
    void output_funktion(double *daten, string dateiverzeichnis){
    std::fstream datei;
    
    datei.open(dateiverzeichnis, std::ios_base::binary | std::ios_base::out | std::ios_base::app);
    
    int tmp;
    
    // Länge von daten definieren ==> laenge_daten
    
    	for(unsigned int k = 0; k<laenge_daten; k++){  // laenge_daten ==> siehe oben
    			tmp =  fprintf(datei,"%.6e", daten[k]);
                            datei << ' '; // Leerzeichen zwischen den doublewerten
            }
    
    datei.close();
    
    return;
    }
    

    Natürlich meckert der Compiler:

    error C2664: 'fprintf': Konvertierung des Parameters 1 von 'std::fstream *' in 'FILE *' nicht möglich

    Mein Workaround wäre nun folgender:

    #include <iostream> 
    #include <fstream> 
    #include <string> 
    #include <cstdio>
    
    void output_funktion(double *daten, string dateiverzeichnis){
    // std::fstream datei;
    
    //datei.open(dateiverzeichnis, std::ios_base::binary | std::ios_base::out | std::ios_base::app);
    
    char *a=new char[dateiverzeichnis.size()+1];
    a[dateiverzeichnis.size()]=0;
    memcpy(a,dateiverzeichnis.c_str(),dateiverzeichnis.size());
    
    	freopen (a,"w",stdout);
    
    int tmp;
    
    // Länge von daten definieren ==> laenge_daten
    
    	for(unsigned int k = 0; k<laenge_daten; k++){  // laenge_daten ==> siehe oben
    			tmp =  printf("%.6e ", daten[k]);
                            //datei << ' '; // Leerzeichen zwischen den doublewerten
            }
    
    fclose (stdout);
    
    //datei.close();
    
    return;
    }
    

    Somit schreibe ich die formatierten double-Werte via stdout in meine Datei. Ich denke mir bloß, dass das noch geschickter gehen muss.

    Hat einer eine Idee, wie ich formatiert double Werte hintereinander in eine txt Datei schreibe?

    Ich möchte im Programm eine ähnliche Funktion benutzen, die Zeilenbrüche erstellt. Es wäre nicht schlecht, wenn im vorgeschlagenen Code so eine Option auch erwähnt wird.

    cu & Danke

    Jan++


  • Mod

    Was hast du vor? Wieso nicht einfach operator<<?

    Deine derzeitige Lösung kann man nicht nur geschickter machen, ein erster Schritt wäre, die Fehler zu korrigieren. Das kann ich aber erst, nachdem du die beiden Fragen oben beantwortet hast. Bis dahin leckt der Code Speicher wie ein Weltmeister, compiliert nur auf bestimmten Compilern mit unstandardgemäßen Erweiterungen, fliegt dir bei bösärtigen Nutzereingaben um die Ohren, usw.



  • 2 Sachen, die ich jetzt mal so anrate, oder sehe.

    1. Weshalb FILE fprintf etc und filestreams mischen?
    2. Wenn du die doubles binär speicherst, sparst du noch platz und die Trennzeichen.


  • Hallo,

    danke für die bisherigen Antworten.

    Ich möchte für eine andere Entwicklungsumgebung (MATLAB) eine Matrix mit double Werten, wie folgt, in eine *.txt schreiben lassen:

    Wert_{1,1} Wert_{1,2} ... Wert_{1,n}
    Wert_{2,1} Wert_{2,2} ... Wert_{2,n}
    ...
    Wert_{m,1} Wert_{m,2} ... Wert_{m,n}

    Das sollte, wenn möglich in dieser fprintf-Notation mit "%.6e" stattfinden, da sonst der MATLAB-Befehl zum Einlesen der txt-Datei Probleme hat.

    Wichtig für den Befehl ist, dass die Werte per Lerrzeichen getrennt und die Zeilen per '\n' abgeschlossen sind.

    Link zum MATLAB-Befehl: http://www.mathworks.de/de/help/matlab/ref/dlmread.html
    <- 'delimiter', '\t' wäre bei mir ' '
    ==> also kein Tabulator

    cu

    Jan


  • Mod

    Jan90++ schrieb:

    Das sollte, wenn möglich in dieser fprintf-Notation mit "%.6e" stattfinden, da sonst der MATLAB-Befehl zum Einlesen der txt-Datei Probleme hat.

    Du meinst also scientific, fixed mit precision 6. Somit reduziert sich dein gesamtes Programm auf das Setzen dieser drei Flags für deinen Ausgabestream.



  • Hallo & danke,

    meine Funktion arbeitet nun korrekt und fehlerfrei, so dass MATLAB die Dateien einlesen kann 🙂

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstdio>
    
    void output_funktion(double *daten, string dateiverzeichnis){
    std::fstream datei;
    
    datei.open(dateiverzeichnis, std::ios_base::binary | std::ios_base::out | std::ios_base::app);
    
    datei.precision(6);
    
    // Länge von daten definieren ==> laenge_daten
    
        for(unsigned int k = 0; k<laenge_daten; k++){  // laenge_daten ==> siehe oben
                datei << scientific << daten[k];
                datei << ' '; // Leerzeichen zwischen den doublewerten
            }
    
    datei.close();
    
    return;
    }
    

  • Mod

    Das scientific brauchst du nicht jedes Mal zu setzen.

    Ein paar weitere Sachen, um die du dir Gedanken machen solltest (Klartext: Mach dich mal kundig zu diesen Stichworten 🙂 ):
    Warum binary? Warum kein einfacher ofstream? Woher kommt laenge_daten? Wozu das close? Wozu das return?

    Deine Funktion wäre viel flexibler, würde sie einfach nur Anfang und Ende eines allgemeinen Bereichs (Iteratorpaar) annehmen, anstatt dass fest vorgegeben wird, dass es sich um ein double-Array handeln soll. Es wäre auch viel hübscher, wenn du auch gleich noch einen allgemeinen ostream als Ziel nehmen würdest, anstatt einen Dateinamen. Insbesondere bräuchte die Datei dann nicht immer wieder geöffnet und geschlossen werden. Insgesamt würde die Funktion dann jedoch bloß noch aus der for-Schleife mit einem einzigen Befehl drin bestehen, da kann man sich fast die Funktion gleich ganz sparen. Dein Compiler kann ja anscheinend C++11. Da könntest du auch ein range-based for benutzen und könntest damit den Code noch kürzer und noch unabhängiger von der eigentlichen Form der Daten schreiben. Das heißt insgesamt hättest du dann nur noch:

    // ... Irgendwo wird ein Stream erzeugt und die Flags gesetzt gesetzt ...
    for (auto d : deine_daten) out << d << ' ';
    // Das war es schon.
    

Anmelden zum Antworten