string formatieren



  • SeppJ schrieb:

    Ich bin jetzt zu faul, CString.Format nachzuschlagen

    Die CString.Format(..) Formatangaben sind dieselben wie bei printf(..).


  • Mod

    theta schrieb:

    SeppJ schrieb:

    Ich bin jetzt zu faul, CString.Format nachzuschlagen

    Die CString.Format(..) Formatangaben sind dieselben wie bei printf(..).

    Gut, dann habe ich ja richtig geraten.



  • nö hab aber das gefunden was ich wollte:

    heißt sprintf 🙂
    danke trotzdem



  • Warum sprintf und damit C-Stil?
    Warum nicht C++ Stil? Oder erfüllen die C++ Varianten deine Anforderungen nicht?


  • Mod

    f.-th. schrieb:

    Warum sprintf und damit C-Stil?
    Warum nicht C++ Stil? Oder erfüllen die C++ Varianten deine Anforderungen nicht?

    Ich vermute die Anforderung ist minimalster Aufwand, koste es was es wolle. Bei den C++-Mitteln könnte er tatsächlich noch was Lernen 😮 .



  • In unserer Anwendung haben wir aberhunderte von printf()-Formatstrings fürs Logging.
    (In der Art "Knoten %d: Unterschreitung Minimaldruck: %f, %f\n" )
    Und zwar auf Deutsch, Englisch, Polnisch...
    Mit reinem cout << wüßte ich nicht, wie ich die Mehrsprachigkeit erreichen soll.
    boost::format ist derzeit die einzige mir bekannte Alternative. Gibt's da noch was anderes, wenn man x printf() vermeiden will?


  • Mod

    Caligulaminus schrieb:

    Gibt's da noch was anderes, wenn man x printf() vermeiden will?

    Boost kocht auch nur mit Wasser, das kann man sich auch nachbauen (und haben bestimmt auch andere schon gemacht). Man kann sich mit den neuen variadischen Templates aus C++11 auch relativ leicht ein typsicheres printf bauen.



  • Wenn ihr C++0x verwenden dürft, könnte ich euch ein C++-printf anbieten, das Mehrsprachigkeit über std::cout kann.



  • Hallo Sepp, die variadic templates muß ich mir noch anschauen. Aber ich glaube, MSVC10 kann die noch gar nicht. Naja, boost::format kann die printf()-Strings, warum also selber kochen.
    Vielleicht kann ich sogar noch ein wenig Performanz rauschlagen, wenn ich die formater static mache?

    `static boost::format fmt("%1, %2\n");

    cout << fmt % varx % vary;`

    Zumindest an den stark frequentierten Stellen.

    Allerdings wird bisweilen aus einem ganzen Strauß Threads gleichzeitig gelogt. Das funktioniert mit printf() prächtig, aber cout << fmt %varx % vary; sind doch drei Aufrufe. Ich fürchte, daß mir das alles durcheinanderwürfelt.
    Naja, probieren...

    P.S. Ich kann mir nicht helfen, aber die I/O mit cout ist mir von Anfang an aufgestoßen.



  • Du darfst auch printf() nicht aus mehreren Threads einfach so aufrufen, das ist verboten. Ich bastle mal ein C++-printf bis 5 Argumente, Thread Safety und den Rest darfst du dir dann selbst überlegen 😉



  • Hallo π, immer her damit ;).
    Wie gesagt benutzen wir printf() erfolgreich aus -zig Threads. Daher kann ich nicht recht glauben, daß das nicht erlaubt sein soll.
    Anschauen will ich mir Deine Variante gerne.

    Gruß


  • Mod

    Wenn die Ausgabe bei dir wirklich der Flaschenhals ist (recht ungewöhnlich, aber möglich), dann würde ich allgemein überlegen, ob ich nicht die C Funktionen nehme. Nicht wegen der Formatierung (das kann man ja mit boost genau so machen), sondern wegen der Geschwindigkeit. Oftmals sind die nämlich deutlich schneller, weil sie viel weniger können (die schleppen z.B. nicht die ganzen änderbaren Facets mit sich rum). Wobei ein komplexer printf-String auch jedes mal zur Laufzeit ausgewertet werden muss, was im Endeffekt wieder langsamer sein kann als eine cout-Kette die zur Compilezeit feststeht und dadurch gegebenenfalls optimiert werden kann. Eventuell kann man auch noch eigene Formatierungsfunktionen schreiben, die noch weniger können (und dann intern nur noch puts benutzen), falls man mit diesen beschränkten Mitteln auskommt.


  • Mod

    Caligulaminus schrieb:

    Hallo π, immer her damit ;).
    Wie gesagt benutzen wir printf() erfolgreich aus -zig Threads. Daher kann ich nicht recht glauben, daß das nicht erlaubt sein soll.

    Der (bisher) aktuelle Standard macht gar keine Aussagen zur Threadsicherheit. Aber manche Implementierungen tun dies als Zusatzfeature. Die GNU glibc hat z.B. ein garantiert threadsicheres printf. Das kann halt fehlschlagen, wenn du dein Program mal irgendwann wohin portierst, wo diese Annahme nicht mehr gilt.



  • Flaschenhals eigentlich nur wirklich, wenn wir den Log-Level hochdrehen. Dennoch liegt mein Hauptaugenmerk auf der Performance, weil wir wirklich viel loggen, und gelegentlich auch mal Läufe von mehreren Tagen Dauer vorkommen.
    Da alle Threads in die selben Dateien schreiben, ist mir wichtig, daß wenigstens die einzelnen Zeilen nicht zerbröselt und neu gemixt werden. U.U. muß ich dann noch synchronisieren. Oder ich bohre den Logger auf und schreibe in x Dateien parallel, oder...
    Ich muß halt einfach mal all die Varianten timen. 😞



  • So, hier ist mal meines.

    namespace detail
            {
                    template <typename T0>
                    void print_helper(const char*& str, const T0& t0)
                    {
                            while(*str != '%' && *str)
                                    std::cout << *str++;
    
                            if(!*str)
                                    throw std::invalid_argument("too much arguments passed to pi::printf()");
    
                            std::cout << t0;
                            ++str;
                    }
    
                    void print_helper(const char* str)
                    {
                            while(*str != '%' && *str)
                                    std::cout << *str++;
    
                            if(*str)
                                    throw std::invalid_argument("not enough arguments passed to pi::printf()");
                    }
            }
    
            void printf(const char* str)
            {
                    detail::print_helper(str);
            }
    
            template <typename T0>
            void printf(const char* str, const T0& t0)
            {
                    detail::print_helper(str, t0);
                    printf(str);
            }
    
            template <typename T0, typename T1>
            void printf(const char* str, const T0& t0, const T1& t1)
            {
                    detail::print_helper(str, t0);
                    printf(str, t1);
            }
    
            template <typename T0, typename T1, typename T2>
            void printf(const char* str, const T0& t0, const T1& t1, const T2& t2)
            {
                    detail::print_helper(str, t0);
                    printf(str, t1, t2);
            }
    
            template <typename T0, typename T1, typename T2, typename T3>
            void printf(const char* str, const T0& t0, const T1& t1, const T2& t2, const T3& t3)
            {
                    detail::print_helper(str, t0);
                    printf(str, t1, t2, t3);
            }
    
            template <typename T0, typename T1, typename T2, typename T3, typename T4>
            void printf(const char* str, const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4)
            {
                    detail::print_helper(str, t0);
                    printf(str, t1, t2, t3, t4);
            }
    

    Ich habe hier Exceptions hingemacht, da man bei assert() keinen Text angeben kann. Vielleicht könnt ihr das ja mit einem Debug/Release Schalter machen. Außerdem ist die Erstellung der Funktionen etwas redundant, vielleicht lässt sich da was mit Makros vereinfachen. Ein kompiliertes Beispiel mit Ausgabe ist hier (Alles im namespace pi, da printf() schon im globalen namespace ist): http://ideone.com/wfjK6



  • much -> many.



  • Stimmt, danke 😃



  • Redundanz verringert 🤡
    Wieder mal direkt nachdem ich gepostet habe.



  • Danke π, kommt auf meine Liste.
    Danke Sepp, für die Hinweise.



  • Michael E. schrieb:

    much -> many.

    Sicher? Argumente sind zählbar.


Anmelden zum Antworten