ToString()



  • Hallo zusammen,

    kann man das ein Wenig schöner machen? Wie kann man bei sprintf alle Nachkommastellen eines double ausgeben lassen?

    string ToString() const
    {
    	string s("Node ");
    	char temp[50];
    	itoa(this->index, temp, 10);
    	s.append(temp);
    	s.append("\n----------\nx: ");
    	sprintf(temp, "%f", this->x);
    	s.append(temp);
    	s.append(" y: ");
    	sprintf(temp, "%f", this->y);
    	s.append(temp);
    	s.append(" z: ");
    	sprintf(temp, "%f", this->z);
    	s.append(temp);
    	s.append("\nNeighbors: ");
    	itoa(this->n0, temp, 10);
    	s.append(temp);
    	s.append(" and ");
    	itoa(this->n1, temp, 10);
    	s.append(temp);
    	return s;
    }
    

    Gruß
    Patrick



  • Japp, mit C++ 😉

    #include <sstream>
    
    string ToString() const
    {
       ostringstream ost;
    // Zeilenumbrüche nur wg. Übersichtlichkeit; kannst auch alles in eine Zeile packen
       ost << "Node " << index  
           << "\n----------\nx: " << x 
           << " y: " << y 
           << " z: " << z 
           << "\nNeighbors: " << n0  << " and " << n1;
       return ost.str();
    }
    

    Gruß,

    Simon2.



  • Das ist kein C++ (weder vom Stil noch vom Code her (itoa ist nichtmal C-Standard)).

    Wenn du etwas in einen String umwandelst, dann tust du das mit einer faszinierend großen Wahrscheinlichkeit zur Ausgabe (wenn dem nicht so sein sollte, dann müsste der String die Daten tatsächlich repräsentieren).

    In C++ benutzt man zur Ein- und Ausgabe Streams (std::cout << "bla"). Du kannst mit vergleichsweise wenig Aufwand deiner Klasse diese Funktionalität spendieren:

    class bla
    {
    public:
        inline friend std::ostream& operator<< (std::ostream& os, bla const& obj)
        {
            os << "Node: x=" << obj.x << " y=" << obj.y << " z=" << obj.z;
        }
    // bla
    };
    


  • Schönen Dank. Kann man die Anzahl der Nachkommastellen beeinflussen und wenn ja, wie?

    Gruß
    Patrick



  • Hi .filmor,
    ein Vorteil von Memberfunktionen ist, dass man sie virtual machen und sich dann die operator<<-en für Kinder sparen kann...
    Allerdings hätte ich auch kein ToString(), sondern ein (public) ostream& print(ostream&) genommen...

    Gruß,

    Simon2.



  • Mein Posting war an PACoSys gerichtet, ich war nur zu lahm 😉
    Mit deinem Code könnte ich micht durchaus anfreunden, nur sehe ich im Moment nicht den Vorteil gegenüber meiner Version, die das ganze mit jedem beliebigen ostream funktionieren lässt.
    Wenn ich dich richtig verstanden habe, dann meinst du, dass sich das in der operator<<-Form nicht so toll mit Polymorphie versteht, oder?
    Aber dafür benutzt man doch in C++ ein (zumindest bei mir ;)) immer wiederkehrendes Konstrukt (was genau deine virtuelle Methode verwendet, sie aber nicht veröffentlicht):

    class bla
    {
    public:
        inline friend std::ostream& operator<< (std::ostream& os, bla const& obj)
        {
            obj.do_print (os);
        }
    protected:
        virtual void do_print () const;
    // bla
    };
    

    Das tuts genauso und fügt sich sauberer in den Streamkram ein.

    PACoSys schrieb:

    Schönen Dank. Kann man die Anzahl der Nachkommastellen beeinflussen und wenn ja, wie?

    Kannst du. Entweder über den Manipulator setprecision aus <iomanip> oder über die Elementfunktion precision des ostream-Objektes:

    float f = 3.141592654f;
    
    // 1.
    os << setprecision (10) << f;
    // 2.
    os.precision (10);
    os << f;
    

    In beiden Fällen solltest du (falls du nicht vor /jeder/ Eingabe den Status neu setzen willst) io_state_saver benutzen, damit der Stream nach deiner Ausgabe wieder in den Ausgangszustand versetzt wird.



  • Müsste es nicht eher so aussehen?

    class bla
    {
    public:
        inline friend ostream & operator << (const bla & obj)
        {
            return obj.do_print();
        }
    protected:
        virtual ostream & do_print () const;
    };
    

    Gruß
    Patrick



  • @filmor Du hast die Referenz für das print vergessen:

    class bla 
    { 
    public: 
        virtual std::ostream& print (std::ostream& os) const; 
    };
    
    std::ostream& operator<<(std::ostream& os, const bla& obj) 
    { 
        return obj.print(os); 
    }
    


  • .filmor schrieb:

    Mein Posting war an PACoSys gerichtet, ...

    Das hatte ich auch so verstanden. 😃
    Mir ging es im ersten Blick um die Technik "Wie kann ich Klassenattribute ausgeben ?" .... vA mit den netten C++-Mitteln und ohne das ganze char*-Geraffel.

    Dein Code ist genau das, was ich meinte: Eine virtuelle Funktion und ein genereller und "freier" operator<<(). Habe das vielleicht ein wenig zu kurz gefasst mit:

    Simon2 schrieb:

    ...
    ein Vorteil von Memberfunktionen ist, dass man sie virtual machen und sich dann die operator<<-en für Kinder sparen kann...

    PACoSys' ToString()-Methode habe ich als erste Version dieser virtuellen Funktion gesehen (auch wenn ich sie ebenfalls eher print() genannt hätte).

    Egal - wir sind uns einig 😋

    Gruß,

    Simon2.



  • Ich blick's irgendwie nicht mehr ganz. Kann mal bitte jemand das Beispiel berichtigen bzw. vervollständigen?

    point.h

    #ifndef POINT_H
    #define POINT_H
    
    #include <string>
    
    class Point
    {
    public:
    	Point(double x, double y, double z) : x(x), y(y), z(z) { }
    	double GetX() const { return x; }
    	double GetY() const { return y; }
    	double GetZ() const { return z; }
    	string ToString() const
    	{
    		ostringstream ost;
    		ost << "Node " << index << "\n----------\nx: " << x << " y: " << y << " z: " << z;
        	return ost.str();
    	}
    	bool operator == (const Point & crP2) const { return ((x == crP2.GetX()) && (y == crP2.GetY()) && (z == crP2.GetZ())); }
    private:
    	double x;
    	double y;
    	double z;
    };
    
    #endif
    

    point.cpp => keine

    Gruß
    Patrick



  • Wenn du jetzt noch den Header <sstream> ergänzt und die Bezeichner string und ostringstream mit std:: korrekt zuordnest, sollte das eigentlich passen.

    (und natürlich sollte 'index' auch irgendwo definiert sein, wenn du es verwenden willst ;))



  • viande schrieb:

    @filmor Du hast die Referenz für das print vergessen

    Jau.

    Simon2 schrieb:

    Egal - wir sind uns einig 😋

    Jau.

    PACoSys schrieb:

    Ich blick's irgendwie nicht mehr ganz. Kann mal bitte jemand das Beispiel berichtigen bzw. vervollständigen?

    Entweder so wie CStoll sagte, oder du gehst den C++-igen Weg.
    Ich gehe jetzt einfach mal davon aus, dass Point so primitiv bleiben soll, dann erübrigt sich nämlich die Diskussion um virtuelle Funktionen:

    #ifndef POINT_H
    #define POINT_H
    
    #include <iosfwd>
    
    class Point
    {
    public:
        Point(double x, double y, double z) : x(x), y(y), z(z) { }
        double GetX() const { return x; }
        double GetY() const { return y; }
        double GetZ() const { return z; }
    
        inline friend std::ostream& operator<< (std::ostream& os, Point const& p);
        {
            os << "Node " << p.index << "\n----------\nx: " << p.x << " y: " << p.y << " z: " << p.z;
            return os;
        }
        bool operator == (const Point & crP2) const { return ((x == crP2.GetX()) && (y == crP2.GetY()) && (z == crP2.GetZ())); }
    private:
        double x;
        double y;
        double z;
    };
    
    #endif
    

    Jetzt kannst du beliebige Point Objekte in beliebige Streams stopfen. Du kannst also folgendes alles tun:

    Point e3 (0.0, 0.0, 1.0);
    
    std::cout << e3;
    
    ostringstream ost;
    ost << e3;
    std::string s = ost.str();
    
    ofstream file ("bla");
    file << e3;
    

    Na, is das was? 😉


Anmelden zum Antworten