C++: Strings in .txt anfügen und NICHT überschreiben



  • Guten Tag Freunde,
    habe mich hier frisch angemeldet, da ich eine wichtige Frage hab und nicht mal mein Ausbilder die Lösung weiß.
    Es geht um folgenden Code:

    int main() {
    
    ofstream("klassennamen.txt", ios::in | ios::out | ios::ate);
    ofstream outfile2; 
    outfile2.open("klassennamen.txt");
    
    	for (int i = 0; i < 10; i++) {	
    
    		stringstream ss;
    		ss << i;
    		string namedata = ss.str();
    		outfile2 << "klasse" + namedata << endl;
    		
    	}
    	outfile2.close();
    	system("pause");
    
    	outfile2.open("klassennamen.txt");
    	for (int j = 10; j < 20; j++) {
    
    		stringstream ss;
    		ss << j;
    		string namedata = ss.str();
    		outfile2 << "klasse" + namedata << endl;
    
    	}
    	
    	outfile2.close();
    	system("pause");
    
    
     ... Code ... 
    

    Nun ist das Problem wie folgt: Ich möchte, dass die Daten in der *.txt nicht überschrieben werden, sondern bleiben und neue Daten bzw Strings angefügt werden.
    Der Code war ein Test dazu.
    Schreibt zu erst den Ersten "Datensatz" in die Datei und soll dann nach einer Bestätigung via Eingabetaste den zweiten "Datensatz" an den ersten ANFÜGEN(!). Dies geschieht nicht, denn die Datei wird mit dem zweiten Datensatz überschrieben.

    Bitte um Hilfe von euch Allwissenden Programmierern 🙂
    Vielen Dank und LG



  • Du machst die Datei zweimal auf. Einmal erzeugst du einen temporären ofstream mit den korrekten Flags. Dann erzeugst du einen weiteren ofstream, diesmal als Variable. Und rufst dessen open-Memberfunktion auf, allerdings dann ohne Flags, so dass ios::ate natürlich nicht zum tragen kommt.

    Dass dein Ausbilder das nicht gesehen hat ... 🤔

    Richtig wäre es jedenfalls ungefähr so:

    ofstream outfile("klassennamen.txt", ios::in | ios::out | ios::ate); // man kann auch ios::app nehmen zum Anhängen
    // kein open(), das macht der Konstruktor
    ...
    outfile << "klasse" + namedata << endl;
    ...
    // kein close(), das macht der Destruktor
    


  • Ich verstehe das Problem noch nicht so ganz, insbesondere warum da so viele ostreams im Code sind. Ein paar Kommentare inline. Aber wenn dein Ausbilder das nicht weiß, wie sollst du dann C++ von ihm lernen? Ausnahmsweise extrem klarer Fall von YAIT (yet another incompetent teacher)!

    int main() {
        ofstream("klassennamen.txt", ios::in | ios::out | ios::ate);
        // Was soll diese Zeile bewirken? 
        // Du hast nicht einmal ein benanntes Objekt! D.h. nach
        // dem ofstream-Constructor wird sofort der Destructor aufgerufen.
        
        ofstream outfile2;
        outfile2.open("klassennamen.txt");
        // Warum ein zweites Mal? Dieses Mal Dateiname nicht im Constructor?
        
        for (int i = 0; i < 10; i++) {
            stringstream ss;
            ss << i;
            string namedata = ss.str();
            outfile2 << "klasse" + namedata << endl;
            
            // Was soll der ganze Umweg mit dem stringstream?
            // Warum nicht outfile2 << "klasse" << i << "\n";
        }
        outfile2.close();
        system("pause");
    
        outfile2.open("klassennamen.txt");
        // Hier ÜBERSCHREIBST du die Datei wieder
        // Mit ios::app hängst du ran.
        for (int j = 10; j < 20; j++) {
            stringstream ss;
            ss << j;
            string namedata = ss.str();
            // Hier wieder der gleiche stringstream-Blödsinn.
            outfile2 << "klasse" + namedata << endl;
        }
    
        outfile2.close();
        system("pause");
    }
    


  • Also erst mal vielen Dank an euch beide (@Bashar , @wob ) !

    cout << "Nachfolgender Absatz nicht relevant für das Problem" << endl;
    

    Muss zudem aber auch sagen ich bin nicht grad der erfahrenste C++ Programmierer, es ist mehr so ein Hobby nebenher was man mal vor langer Zeit angefangen hat und jetzt durch den Beruf wieder so richtig einsteigt. 🙂 Ein paar "Grundkenntnisse" sind schon vorhanden. Mein Ausbilder ist eigentlich auch nur so ein Hobby Programmierer und SMD Löten, Mikrokontroller programmieren sein Hobby, er macht gerade noch seinen Bachelor nach, da er Ausbilder für Elektroniker ist. Er macht das mit uns so als Vorbereitung fürs Studium, also ein wenig programmieren, für uns.

    cout << "Ab hier gehts ernst weiter" << endl;
    

    Ich habe das so wie ich es geschrieben hab auch sehr oft im Netz so gefunden, als ich danach gesucht hab. Und nie eine andere Methode gesehen. Aber gut, dass mir das mal einer bzw. zwei erklären. 🙂
    Zudem ist dies nur ein "Testprogramm" für ein viel größeres Programm zu dem ich noch einen Thread aufmachen werden weil es glaube ich gut ist, wenn dort mal jemand drüber schaut wie "schlecht" (eher unerfahren) es programmiert ist.
    Denn ich studiere jetzt dann dual Elektrotechnik.



  • @wob
    Und ich dachte hier

    int main() {
        ofstream("klassennamen.txt", ios::in | ios::out | ios::ate);
        // Was soll diese Zeile bewirken? 
        // Du hast nicht einmal ein benanntes Objekt! D.h. nach
        // dem ofstream-Constructor wird sofort der Destructor aufgerufen.
        
        ofstream outfile2;
        outfile2.open("klassennamen.txt");
        // Warum ein zweites Mal? Dieses Mal Dateiname nicht im Constructor?
        
    

    dass das oben das "ofstream" mit dem Pfad definiert wird und darunter noch als Variable zugleich, praktisch dass es das übernimmt.

    for (int i = 0; i < 10; i++) {
        stringstream ss;
        ss << i;
        string namedata = ss.str();
        outfile2 << "klasse" + namedata << endl;
        
        // Was soll der ganze Umweg mit dem stringstream?
        // Warum nicht outfile2 << "klasse" << i << "\n";
    }
    

    Anderer Grund hat was mit .txt einlesen zu tun hatte da immer fehler so hat es geklappt.
    und das kam dabei raus als ich es weggelassen habe:

    Cannot dereference value-initialized string iterator
    


  • @bashar Du machst die Datei zweimal auf. Einmal erzeugst du einen temporären ofstream mit den korrekten Flags. Dann erzeugst du einen weiteren ofstream, diesmal als Variable. Und rufst dessen open-Memberfunktion auf, allerdings dann ohne Flags, so dass ios::ate natürlich nicht zum tragen kommt.

    hab ich von hier .



  • Was da steht ist zwar richtig -- insbesondere steht da nicht sowas wie bei dir --, aber diese Art von 2-Phasen-Initialisierung (erst ein leeres Objekt konstruieren und es dann erst mit einer open-Methode in einen sinnvollen Zustand versetzen) macht man heute nicht mehr. Hat man auch vor 20 Jahren eigentlich nicht gemacht, aber da hatte sich diese Philosophie vielleicht noch nicht ganz so durchgesetzt.

    Aber zurück zu deinem Code, hast du denn jetzt verstanden, was das Problem ist?



  • @bashar Ehm ja das Problem habe ich dann auch verdtanden.
    Dennoch würde ich mich freuen wenn du/ihr Mal über meinen anderen Code drüber schauen könnten in geraumer Zeit dann.



  • @lexon
    a) Auf welchen anderen Code? Wie sieht dein Code jetzt aus?
    b) Dein Fehler: Cannot dereference value-initialized string iterator: Bitte zeig den Code, der dazu führt. Und vollständige Fehlermeldung (copy+paste).
    c) Warum ist das hier eigentlich in "MFC"? Scheint sich doch um normales Standard-C++ zu handeln.



  • @wob
    a) ich poste es in den anderen Teil wo es wirklich um C++ geht
    b) Hat sich irgendwie gelöst
    c) Ich bin neu hier hab das noch nicht so ganz gerafft wo und wie ich einen thread erstelle, ich hoffe ihr seht es mir nach.



  • Also Leute vielen Dank!
    Es hat nun endlich geklappt. 🙂



  • @lexon sagte in C++: Strings in .txt anfügen und NICHT überschreiben:

    @wob
    a) ich poste es in den anderen Teil wo es wirklich um C++ geht

    Indem Du die entsprechende richtige Kategorie wählst, in die ich auch dieses Posting jetzt verschoben habe.
    https://www.c-plusplus.net/forum/category/33/c-alle-iso-standards


Log in to reply