Frage zu File IO



  • Wollte gerade mein projekt serialisieren, und stieß dabei auf ein Problemchen. Vielleicht kann mir jemand erklären was ich in meiner Naivität falsch mache?

    #include <vector>
    #include <fstream>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main (int argc, char* argv[])
    {	
    	string tmpstring;
    	vector<string> data;
    // ein paar daten generieren
    	data.push_back("bla");
    	data.push_back("sabbel");
    	data.push_back("sülz");
    
    	ofstream outstream("testfile.txt");
    
    	int count = 0;
    	vector<string>::iterator iter;
    
    // daten abspeichern
    	for(iter = data.begin(); iter != data.end(); iter++)
    	{
    		cout << count << ": "<<" writing " << *iter << endl;
    		outstream << *iter << endl;
    		count++;
    	}
    
    	cout << endl;
    
    	data.clear();
    	outstream.close();
    
    // daten wieder einlesen
    	ifstream instream("testfile.txt");
    	while (! instream.eof())
    	{
    		instream >> tmpstring;
    		data.push_back(tmpstring);
    	}
    
    	count = 0;
    // anschauen was eingelesen wurde
    	for(iter = data.begin(); iter != data.end(); iter++)
    	{
    		cout << count << ": "<<" reading " << *iter << endl;
    		outstream << *iter << endl;
    		count++;
    	}
    
    	instream.close();
    
    	return (0);
    }
    

    Ausgabe sieht folgendermaßen aus

    0: writing bla
    1: writing sabbel
    2: writing sülz

    0: reading bla
    1: reading sabbel
    2: reading s³lz
    3:

    Frage 1: was ist mit meinem 'ü' in 'sülz' passiert?

    Frage 2: Warum bekomme ich immer eine Zeile mehr beim auslesen als beim reinschreiben?



  • 1. Ich tippe auf verschiedene Codepages (ASCII vs. ANSI - die Umlaute liegen jenseits des standardisierten Bereiches)

    2. eof() wird erst ausgelöst, wenn der letzte Leseversuch schiefgegangen ist. Ändere deine Leseschleife mal in:

    ifstream instream("testfile.txt");
    while (instream>>tmpstring)
    {
      data.push_back(tmpstring);
    }
    

    (und den Eingabestream (nur) auf EOF zu testen, kann problematisch werden - bei einem Eingabefehler wird das failbit gesetzt und du landest in einer Endlosschleife)



  • OK, das mit den codepages muss ich mir nochmal zu gemüte führen (ist zwar im wirklichen programm kein problem, da alles auf englisch...aber man weiss ja nie wo einen sowas mal eider beisst)

    das mit dem lesefehler kann ich doch umgehen, wenn ich auf

    !instream.good()

    teste, oder?



  • Fast, allerdings fragt !good() genau das Gegenteil von dem ab, was du brauchst - entweder good() oder !fail(), aber noch kürzer ist es, einfach instream abzufragen 😉

    Das ursprüngliche Problem wird allerdings nicht dadurch gelöst - der Stream setzt erst einen Fehler-Status, wenn wirklich eine Eingabe schiefgegangen ist, das heißt, im letzten Schleifendurchlauf steht kein gültiger Wert mehr in deiner Hilfsvariable - und den hängst du noch an den vector<> an.

    Die ausführliche Lösung wäre es, den Stream-Status zwischen Einlesen und Weiterverarbeitung abzufragen:

    while (! instream.fail())
    {
      instream >> tmpstring;
      if(instream.bad()) break;
      data.push_back(tmpstring);
    }
    

    Wenn man jetzt noch dazunimmt, daß op>> den Stream zurückliefert und dieser dank eines eingebauten operator void* auch als Abbruchkriterium der Schleife verwendet werden kann, kommst du auf den Ansatz dort oben.


Anmelden zum Antworten