cout Manipulatoren



  • Hallo, es gibt ja zahlreiche cout Manipulatoren.

    Sagen wir ich habe einen operator<<, der eine Tabelle ausgeben soll:

    std::ostream& operator<<(std::ostream& o, const Foo& rhs) {
    float f
    o<< fixed << setw(9) << setprecision(2) << left << f << setw(9)<< f <<  setw(9) <<f << setw(9) << f << endl;
    o<< setw(9) << f << setw(9)<< f<< setw(9) << f<< setw(9) << f << endl;
    return o;
    }
    

    Was ich nun nicht verstehe: Wieso reicht es wenn ich nur einmal setprecision() angebe, aber setw() muss ich vor jeder Ausgabe immer und immer wieder benutzen.
    Manche Manipulatoren (wie setprecision) ändern offenbar cout dauerhaft, andere hingegen nicht. Ist das richtig? Wie weiß ich welcher Operator cout dauerhaft ändert?

    Oh noch eine kleine Frage. Bei diesem Code:

    float f = 14445454333.8934549f;
    cout  << fixed << setw(9) << setprecision(2) << left << f;
    

    Kriege ich folgende Ausgabe: 14445454336.00
    Wieso weicht das Ergebnis so krass vom echten Wert ab? (.00 statt .89 !)



  • Zwischen setprecision und setw besteht ein Unterschied, es gibt nämlich für precision immer einen Wert, egal ob du ihn angibst oder nicht. Die Breite richtet sich standardmäßig dagegen nach der Zahl, die ausgegeben werden soll. Andersrum gefragt: Was würdest du tun, wenn setw dauerhaft wirken würde und du deine Zahlen wieder ganz normal ausgeben willst?

    Zu der Abweichung: Schau mal genauer hin, die Zahlen stimmen schon eine Stelle vor dem Komma nicht überein. Das liegt an der Ungenauigkeit von Fließkommazahlen, sieh dir dazu mal das Konzept an, wie Fließkommazahlen gespeichert werden (IEEE 754). double liefert genauere Ergebnisse.



  • Ok, danke. @deine Frage: Es könnte ja einfach ein setDefaultWidth geben, das bestimmt, dass ab jetzt die Zahl wieder die Breite festlegt.

    Noch 2 kleine Fragen:

    Ich empfange in operator<< also meinen ostream&, manipuliere diesen mit Manipulatoren wie std::fixed etc. Wenn ich den dann returne, ist der ja nach wie vor editiert. Ich würde den aber gerne in dem Zustand zurückliefern, in dem er operator<< übergeben wurde. Damit für einen Aufrufer von operator<< keine sichtbaren Spuren am ostream bleiben. Wie geht das?

    Zweite Frage: Mich regt dieses cout mittlerweile richtig auf! 😡 Mit printf() konnte man mMn viel leichter Zahlen editieren. Grauenhaft dieses cout...
    Wie auch immer: Ich möchte in operator<< eine Matrix (sprich 2dim. Tabelle) ausgeben. Mein Code sieht so aus:

    template <class T>
    std::ostream& operator<<(std::ostream& o, const Matrix<T>& rhs) {
    	o << fixed << setprecision(3) << left;
    
    	for(uint i=0; i < rhs.getRowCount(); i++) {
    		o << "(";
    		for(uint j=0; j < rhs.getColCount(); j++) {
    			o << setw(8) << rhs(i, j);
    		}
    		o << ")" << endl;
    	}
    	return o;
    }
    

    Leider klappt das hinten und vorne nicht. Ich setze die Minimumbreite jeder Zahl auf 8. Das Problem ist nur: Wenn jetzt eine Zahl länger ist (z.B. 1234567.456), dann klebt die Zahl rechts davon direkt an der Zahl dran; es ist also kein Abstand zwischen den zwei Zahlen. Leider habe ich nirgends gefunden, ob man bei cout eine MAXIMALBREITE einstellen kann.
    Weiß jemand, wie Code aussehen könnte, der eine schöne 2D Matrix ausgibt?



  • manipulativ schrieb:

    Ok, danke. @deine Frage: Es könnte ja einfach ein setDefaultWidth geben, das bestimmt, dass ab jetzt die Zahl wieder die Breite festlegt.

    Gibts aber nicht, weil es unsinnig wäre. Denn die Ausgabebreite hängt im Standardfall nur von dem auszugebenden Wert ab. Dass man eine Mindestbreite erzwingen will, ist eher die Ausnahme.

    Noch 2 kleine Fragen:

    Ich empfange in operator<< also meinen ostream&, manipuliere diesen mit Manipulatoren wie std::fixed etc. Wenn ich den dann returne, ist der ja nach wie vor editiert. Ich würde den aber gerne in dem Zustand zurückliefern, in dem er operator<< übergeben wurde. Damit für einen Aufrufer von operator<< keine sichtbaren Spuren am ostream bleiben. Wie geht das?

    Dafür müsstest du die Flags erst auslesen, bevor du sie veränderst. Das geht mit o.flags().

    Zweite Frage: Mich regt dieses cout mittlerweile richtig auf! 😡 Mit printf() konnte man mMn viel leichter Zahlen editieren. Grauenhaft dieses cout...
    Wie auch immer: Ich möchte in operator<< eine Matrix (sprich 2dim. Tabelle) ausgeben. Mein Code sieht so aus:

    template <class T>
    std::ostream& operator<<(std::ostream& o, const Matrix<T>& rhs) {
    	o << fixed << setprecision(3) << left;
    	
    	for(uint i=0; i < rhs.getRowCount(); i++) {
    		o << "(";
    		for(uint j=0; j < rhs.getColCount(); j++) {
    			o << setw(8) << rhs(i, j);
    		}
    		o << ")" << endl;
    	}
    	return o;
    }
    

    Leider klappt das hinten und vorne nicht. Ich setze die Minimumbreite jeder Zahl auf 8. Das Problem ist nur: Wenn jetzt eine Zahl länger ist (z.B. 1234567.456), dann klebt die Zahl rechts davon direkt an der Zahl dran; es ist also kein Abstand zwischen den zwei Zahlen. Leider habe ich nirgends gefunden, ob man bei cout eine MAXIMALBREITE einstellen kann.
    Weiß jemand, wie Code aussehen könnte, der eine schöne 2D Matrix ausgibt?

    Wie wärs mit ner einfachen Abfrage, ob die Zahl zu groß ist?



  • Michael E. schrieb:

    Wie wärs mit ner einfachen Abfrage, ob die Zahl zu groß ist?

    Naja, mir fällt da nicht wirklich ein, wie ich das testen sollte, dass eine Zahl jetzt zu groß für eine Breite von 8 Stellen ist. Außerdem müsste ich das ja zuvor für ALLE Zahlen der Matrix machen um eine Mindestbreite zu finden, die für alle Zahlen reicht.
    Kann denn dieses räudige cout das nicht von alleine? 😡



  • manipulativ schrieb:

    Michael E. schrieb:

    Wie wärs mit ner einfachen Abfrage, ob die Zahl zu groß ist?

    Naja, mir fällt da nicht wirklich ein, wie ich das testen sollte, dass eine Zahl jetzt zu groß für eine Breite von 8 Stellen ist.

    zahl >= 10^7. Kann man sogar noch erweitern und die Zahl der Nachkommastellen an log10(zahl) anpassen.

    Außerdem müsste ich das ja zuvor für ALLE Zahlen der Matrix machen um eine Mindestbreite zu finden, die für alle Zahlen reicht.

    Wenn du es so machen willst... Such dir die größte Zahl und zähl die Stellen. Wo ist das Problem?



  • Michael E. schrieb:

    zahl >= 10^7.

    Das bringt mir alleine nichts, da sich die Breite auf Vorkomma- und Nachkommateil bezieht. 0.222222222222222 ist sauklein und dennoch zu groß für setw(8)

    Michael E. schrieb:

    Wenn du es so machen willst... Such dir die größte Zahl und zähl die Stellen. Wo ist das Problem?

    Das Problem ist doch offensichtlich. Es ist alles andere als elegant und EFFIZIENT als auf einer 20x30 Matrix für 100e Zahlen mit 10er Potenzen um logs rumzufrickeln, nur weil cout kein setMaxWidth bietet.



  • Dir wird aber nichts anderes übrig bleiben.
    Zähl die stellen! 😡



  • manipulativ schrieb:

    Michael E. schrieb:

    zahl >= 10^7.

    Das bringt mir alleine nichts, da sich die Breite auf Vorkomma- und Nachkommateil bezieht. 0.222222222222222 ist sauklein und dennoch zu groß für setw(8)

    Ach, ich dachte, du willst die Genauigkeit auf höchstens zwei Nachkommastellen reduzieren. Falls nicht, dann lies einfach weiter in meinem letzten Post.

    Michael E. schrieb:

    Wenn du es so machen willst... Such dir die größte Zahl und zähl die Stellen. Wo ist das Problem?

    Das Problem ist doch offensichtlich. Es ist alles andere als elegant und EFFIZIENT als auf einer 20x30 Matrix für 100e Zahlen mit 10er Potenzen um logs rumzufrickeln, nur weil cout kein setMaxWidth bietet.

    Nicht gleich pampig werden. Wie soll denn setMaxWidth funkionieren? Wie soll ich die Zahl 1234 bei maxWidth = 3 ausgeben? 123? 234? zgz (zu große Zahl)? Wie unterscheide ich dann 1234 von 123? Oder reden wir plötzlich von wissenschaftlicher Ausgabe? Das würde das Problem ganz schnell vereinfachen.

    Zum Thema Effizienz: Ich sehe überhaupt kein Problem darin, von 600 Zahlen die größte zu finden und von genau dieser Zahl die Stellen zu zählen. Das geht so schnell, das merkt man gar nicht.



  • Du kannst nicht Forenmitglieder fuer eine eventuelle Inkonsequenz oder Ineffizienz eines Bestandteils einer Programmiersprache verantwortlich machen, wofuer sie nunmal nicht verantwortlich sind. Mehr als dir zu versuchen zu erklaeren kann man hier nunmal nicht. Wenn dir printf besser gefaellt, warum loest du es dann nicht einfach damit? 🙄

    Michael E. schrieb:

    Zum Thema Effizienz: Ich sehe überhaupt kein Problem darin, von 600 Zahlen die größte zu finden und von genau dieser Zahl die Stellen zu zählen. Das geht so schnell, das merkt man gar nicht.

    Doch, mit einem Sinclair ZX Spectrum merkt man das! 😃


Anmelden zum Antworten