Tausendertrennzeichen mit printf (o.ä.) möglich?



  • Hallo,

    gibt es eine einfache Möglichkeit eine beliebig große double-Variable (zur Not auch int) in einen String mit Tausendertrennzeichen (also . oder , ist egal) ausgeben zu lassen? 1000000.5 soll also z.B. zu 1,000,000.5 werden.

    sprintf(text, "Zahl = %.2f", dZahl);
    

    gibt mir die Variable mit 2 Stellen hinterm Komma zurück. Wie kann ich nun noch die Stellen vor dem Komma mit den Tausendertrennzeichen versehen?

    Dass man sich das irgendwie selbst schreiben kann ist schon klar, geht nur darum ob es da eine Standardversion gibt die ich übersehe... 🙂

    Gruß und danke,
    Martin



  • Hallo,
    die printf-Familie unterstützt das von Haus aus nicht. Du musst also entweder auf die iostreams ausweichen oder dir selbst eine Funktion schreiben.

    Siehe auch:
    http://www.eskimo.com/~scs/c-faq.com/stdio/commaprint.html



  • Hallo Martin,

    wenn Du auf C++-IO - also cout & Co - ausweichen kannst (sowieso zu empfehlen), so sieht der Standard eine Möglichkeit vor. Der Trick besteht darin, die sogenannte numpunct-Facette zu überladen und dort die Tausenderstellentrennung zu aktivieren.

    Im Detail geht das so:

    #include <iostream>
    #include <string>
    #include <iomanip>
    
    class ThousandGrouping : public std::numpunct< char >
    {
    protected:
        virtual std::string do_grouping() const
        {
            return "\003"; // alle 3 Dezimalstellen den Tausendertrenner
        }
    };
    
    int main()
    {
        using namespace std;
        cout.imbue( locale( cout.getloc(), new ThousandGrouping ) );
        cout << fixed << setprecision(2);
    
        double d = 1000000.5;
        cout << d << endl;
        return 0;
    }
    

    Ausgabe:

    1,000,000.50
    

    Bem.: das fixed und setprecision dient nur dazu, dass die großen Zahlen nicht gerundet und im scientific Format geschrieben werden.

    Gruß
    Werner



  • Werner Salomon schrieb:

    wenn Du auf C++-IO - also cout & Co - ausweichen kannst

    .. natürlich kannst Du ausweichen. Du machst ja ein (S)printf. Das geht wie oben beschrieben, Du benötigst noch einen ostringstream - also:

    #include <sstream>
    // usw. wie oben; includes & class ThousandGrouping
    
    int main()
    {
        using namespace std;
        ostringstream buf;
        buf.imbue( locale( buf.getloc(), new ThousandGrouping ) );
        buf << fixed << setprecision(2);
    
        double d = 1000000.5;
        buf << "Zahl = " << d;  // mit setprecision(2) & fixed wie "Zahl = %.2f"
        string text = buf.str();
        // .. usw.
        return 0
    }
    

    Es ist aber grundsätzlich immer zu empfehlen, die Ausgabe gleich über einen ostream mit dem Zieldevice zu machen. Wo soll der String 'text' denn anschließend hin?

    Gruß
    Werner



  • Hi,

    vielleicht hilft Dir das hier weiter ? : http://cplus.kompf.de/artikel/locale.html



  • danke @all.

    @Werner:
    Der Text soll danach über TextOut (ist eine MFC-Funktion) in ein Fenster geschrieben werden, sobald das aber in irgendeiner Art String/char* ist, schaffe ich den Rest dann alleine.

    Code sieht soweit gut aus, MSVS C++ 6 meckert allerdings an einer Stelle (in beiden vorgeschlagenen Versionen):
    error C2665: 'locale::locale' : none of the 7 overloads can convert parameter 1 from type 'class std::locale'

    Ich hab stattdessen wie in der Hilfe angedacht mal

    buf.imbue( _ADDFAC(cout.getloc(), new ThousandGrouping ) );
    

    geschrieben, kompiliert nun auch, gibt denn String aber ohne die Trennzeichen zurück, also 1000000.50

    @SciFi:
    Das sieht perfekt aus, genau was ich dachte, einfach strfmon und fertig. Leider scheint strfmon zumindest bei mir nicht dabei zu sein ("undeclared identifier").
    Wenn man hier guckt, scheint das auch kein Standard zu sein, es wird eine "monetary.h" benötigt:
    http://publib.boulder.ibm.com/infocenter/iadthelp/v6r0/index.jsp?topic=/com.ibm.etools.iseries.langref.doc/rzan5mst262.htm



  • Hallo Martin,

    Bei MS-VC6 _ADDFAC zu benutzen ist ok, da dieser Compiler die Standard-Konstruktion irgendwie nicht kann. Ich habe es gerade mit dem MS-VC6 ausprobiert und gedebugged; die mitgelieferte STL unterstützt den Tausendertrenner überhaupt nicht 👎 .

    Kann man nur sagen; persönliches Pech - nicht mit dieser Umgebung.

    Gruß
    Werner



  • Hallo Werner,

    vielen dank trotzdem für die Mühe. Große klasse.
    So ist MS eben... 😉

    Gruß, Martin



  • Wieso benutzt du nicht MSVC Express? Der Compiler davon ist um Welten besser als der von MSVC6.0.



  • habe hier leider keine Wahl. 🙂


Anmelden zum Antworten