iostream: stream states



  • manni66 schrieb:

    Es sind, wie der Name schon sagt, Bits. Da können halt auch mehrere gesetzt sein. Der stream hat aber auch Funktionen (eof, fail, ...) um sie abzufragen. Die if-Abfrage ist nicht notwendig, benutze einfach die eof Funktion für das return.

    Danke, das funktioniert, allerdings irritiert mich nur irgendwie das Konzept dahinter.

    Ich meine das bedeutet, dass bei jeder I/O Streamoperation am Ende ein logischer I/O Error (failbit) kommt.

    Kann denn ein logischer I/O Error(failbit) auch an einer anderen Stelle geschehen, als bei der letzten read Operation oder ist der logische I/O Error eigentlich gleichbedeutend mit eof?



  • Fail passiert immer, wenn man versucht etwas zu lesen, was nicht da ist:

    #include <string>
    #include <sstream>
    #include <iostream>
    
    void print_state( std::istream const & is )
    {
    	if( is.eof() )
    		std::cout << "eof ";
    	if( is.fail() )
    		std::cout << "fail ";
    	if( is.bad() )
    		std::cout << "bad ";
    	if( is.good() )
    		std::cout << "good";
    
    	std::cout.put( '\n' );
    }
    
    int main()
    {
    	std::stringstream ss{ "foo 42 bar" };
    
    	std::string str;
    	unsigned number;
    
    	// vielleicht eine Zahl lesen?
    	ss >> number;
    	print_state( ss ); // -> fail
    	ss.clear();
    
    	// Nein? Dann halt einen String
    	ss >> str;
    	print_state( ss ); // -> good	
    
    	// jetzt vielleicht eine Zahl?
    	ss >> number;
    	print_state( ss ); // -> good
    
    	// noch eine?
    	ss >> number;
    	print_state( ss ); // -> fail. Njet.
    	ss.clear();
    
    	// Dann halt einen String
    	ss >> str;
    	print_state( ss ); // -> jep, kein fail. aber eof -> es kommt nichts mehr.
    }
    


  • Swordfish schrieb:

    void print_state( std::istream const & is )
    {
    	if( is.eof() )
    		std::cout << "eof ";
    	if( is.fail() )
    		std::cout << "fail ";
    	if( is.bad() )
    		std::cout << "bad ";
    	if( is.good() )
    		std::cout << "good";
    
    	std::cout.put( '\n' );
    }
    

    Gute Funktion. Könnte in die FAQ rein.



  • Ruvi schrieb:

    manni66 schrieb:

    1+2=3
    Das Fail- und das Eofbit sind gesetzt. Wenn deine Datei am Ende keinen Zeilenumbruch hat, wird bis zum Dateiende gelesen, deshalb ist EOF schon gefunden.

    o_O
    Er addiert die States?
    Wenn nach eofbit ein badbit kommt ist der State dann 5 ?
    Wie baut man denn dann solide Abfragen?

    Nein, er verodert die einzelnen States. Und das ist auch der Grund warum das nur die Zweierpotenzen sind. Zufällig sieht dann die Oder-Operation so aus wie ein Plus.

    Und du kannst dir die einzelnen States mit einem Und wieder da raus holen:

    enum {
    	GOOD = 0,
    	EOF = 1,
    	FAIL = 2,
    	BAD = 4
    };
    
    int flags = EOF | BAD;
    
    if ( flags == GOOD )
    {
    }
    else
    {
    	if ( flags & EOF == EOF )
    	{}
    	if ( flags & FAIL == FAIL )
    	{}
    	if ( flags & BAD == BAD )
    	{}
    }
    

  • Mod

    Gute Funktion. Könnte in die FAQ rein.

    Wie wäre es mit

    #include <iostream>
    
    std::ios& print_state( std::ios& is )
    {
    	std::ostream& out = (&is == &std::cout? std::clog : std::cout); // Falls cout das failbit gesetzt hat
    	if (is.good())
    		out << "good";
    	else
    	{
    		if (is.bad())
    			out << "*bad* ";
    		if (is.eof())
    			out << "eof ";
    		if (is.fail())
    			out << "fail ";
    	}
    
    	out << '\n';
    	return is;
    }
    
    int main()
    {
    	std::cout << print_state;
    	std::cin >> print_state;
    }
    


  • Arcoth schrieb:

    std::cin >> print_state;
    

    Semkantik daneben!?



  • Arcoth schrieb:

    std::ios& print_state( std::ios& is )
    

    Super nützlicher Rückgabewert!

    Arcoth schrieb:

    std::ostream& out = (&is == &std::cout? std::clog : std::cout); // Falls cout das failbit gesetzt hat
    

    100% POLA-konform!

    Arcoth schrieb:

    out << "*bad* ";
    

    *bad* bedarf ganz sicher besondere Aufmerksamkeit.

    Die Leerzeichen sind sicher auch sehr nützlich vor dem Linebreak

    Arcoth schrieb:

    out << '\n';
    

    der in jede unscheinbare Ausgabefunktion hineingehört.

    Arcoth schrieb:

    std::cout << print_state << '\n';
    

    Compile error. Aha, deshalb das '\n' . POLA ftw.

    Arcoth schrieb:

    std::cin >> print_state;
    

    Ok, ich gebs auf. Da läuft was ganz grundsätzlich schief.



  • Wundert mich eh, daß es ohne template vonstatten ging.



  • thedailywtf schrieb:

    Arcoth schrieb:

    std::cout << print_state << '\n';
    

    Compile error. Aha, deshalb das '\n' . POLA ftw.

    Eigentlich kein Comile error. Höchstens, wenn Du den komischen Rückgabetyp geändert hättest.


  • Mod

    thedailywtf schrieb:

    *bad* bedarf ganz sicher besondere Aufmerksamkeit.

    Ja, warum nicht? Deutet schließlich auf einen irreparablen Fehler hin und sollte entsprechend gekennzeichnet werden.

    thedailywtf schrieb:

    Die Leerzeichen sind sicher auch sehr nützlich vor dem Linebreak

    Nein, aber es ist ganz nützlich zwischen Wörtern. "eoffail" wäre nicht so lesbar, weißt du.
    Falls du dich allerdings auf das eine Leerzeichen in "fail " aufregst, muss ich dir sowohl zu deinen Adleraugen als auch zu deinem Scharfsinn gratulieren.

    thedailywtf schrieb:

    der in jede unscheinbare Ausgabefunktion hineingehört.

    Komisch - bei Swordfish's Variante hast du dich nicht beschwert. Diesen Einwand hast du aber vorausgesehen und das Wörtchen unscheinbar eingebaut. Ich muss dir abermals zu deinem Scharfsinn gratulieren!

    thedailywtf schrieb:

    Compile error

    Die Signatur der aufgerufenen Operatorfunktion ist übrigens

    basic_ostream& operator<<( std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
    

    Zitieren musst du auch noch lernen.



  • Wenn man es mehr "fancy" haben will...

    Könnte man nen Wrapper für std::ios_base::iostate machen und für diesen dann nen Stream-Insertion-Operator definieren.

    Oder der Swordfish Variante nen zusätzlichen Output-Stream Parameter verpassen der zum Output verwendet wird.

    Arcoth schrieb:

    thedailywtf schrieb:

    der in jede unscheinbare Ausgabefunktion hineingehört.

    Komisch - bei Swordfish's Variante hast du dich nicht beschwert. Diesen Einwand hast du aber vorausgesehen und das Wörtchen unscheinbar eingebaut. Ich muss dir abermals zu deinem Scharfsinn gratulieren!

    Swordfish's Variante ist eine benannte Funktion. Bei benannten Funktionen kommt es schonmal vor dass die nen "\n" rausschreiben.
    Bei einem Stream-Operator bzw. -Manipulator erwartet man es aber eher nicht.
    Wobei die eigentliche POLA Verletzung mMn. die ist dass ein Stream-Manipulator nicht "seinen" Stream manipuliert sondern stattdessen auf einem anderen Stream etwas ausgibt.



  • Ihr habt doch alle einen an der Waffel.



  • Kellerautomat schrieb:

    Ihr habt doch alle einen an der Waffel.

    Ach quatsch, wir sind nur gründlich.

    hustbaer schrieb:

    Bei benannten Funktionen kommt es schonmal vor dass die nen "\n" rausschreiben.

    Gemeint war natürlich '\n'. 💡



  • volkard schrieb:

    hustbaer schrieb:

    Bei benannten Funktionen kommt es schonmal vor dass die nen "\n" rausschreiben.

    Gemeint war natürlich '\n'. 💡

    Verstehe ich nicht.
    Was ist da der (relevante) Unterschied?



  • hustbaer schrieb:

    volkard schrieb:

    Gemeint war natürlich '\n'. 💡

    Was ist da der (relevante) Unterschied?

    Vergiss es. Volkard will mich bloß verarschen.


Anmelden zum Antworten