Zahlen mit Kommas in C++ formatieren

Lesezeit: 7 Minuten

Benutzer-Avatar
Benutzer

Ich möchte eine Methode schreiben, die eine ganze Zahl nimmt und a zurückgibt std::string dieser Ganzzahl mit Kommas formatiert.

Beispiel Deklaration:

std::string FormatWithCommas(long value);

Beispielnutzung:

std::string result1 = FormatWithCommas(7800);
std::string result2 = FormatWithCommas(5100100);
std::string result3 = FormatWithCommas(201234567890);
// result1 = "7,800"
// result2 = "5,100,100"
// result3 = "201,234,567,890"

Wie formatiert C++ eine Zahl als string mit Kommas?

(Bonus wäre zu handhaben doubles auch.)

  • mögliches Duplikat von Wie fügt man Leerzeichen in eine große Zahl ein, um sie besser lesbar zu machen?

    – Rob Kennedy

    1. September 2011 um 22:09 Uhr

  • Mögliches Duplikat von Wie stellen Sie das cout-Gebietsschema so ein, dass Kommas als Tausendertrennzeichen eingefügt werden?

    – Matthias M.

    2. September 2011 um 7:16 Uhr

  • Was an diesen doppelten Aussagen lahm ist, ist, dass ich nach dieser Frage gesucht habe, bevor ich die offensichtlichsten Suchbegriffe verwendet habe, und keine dieser Fragen gefunden habe. Mein Titel ist besser und treffender und ich mag die akzeptierte Antwort auf meine Frage besser als die Antworten auf alle diese.

    – Benutzer

    2. September 2011 um 14:09 Uhr

  • Wenn hohe Leistung ein Problem ist, können Sie meine verwandte Frage sehen: Wie kann ich die Formatierung von Zahlen mit Kommasleistung verbessern?

    – Benutzer

    25. Oktober 2012 um 18:28 Uhr

Benutzer-Avatar
Jacob

Verwenden std::locale mit std::stringstream

#include <iomanip>
#include <locale>

template<class T>
std::string FormatWithCommas(T value)
{
    std::stringstream ss;
    ss.imbue(std::locale(""));
    ss << std::fixed << value;
    return ss.str();
}

Haftungsausschluss: Portabilität könnte ein Problem sein und Sie sollten sich wahrscheinlich ansehen, welches Gebietsschema wann verwendet wird "" ist bestanden

  • @Rob Kennedy: stackoverflow.com/questions/4406895/…

    – Jacob

    1. September 2011 um 22:14 Uhr

  • Diese Funktion hat für mich keine Kommas gesetzt. Welches Gebietsschema soll ich einstellen? Welches Gebietsschema soll ich von meinen Benutzern verlangen? Scheitern.

    – Jonny

    28. Mai 2015 um 9:35 Uhr

  • Die Antwort ist ohne ein Beispiel für die Verwendung eines bestimmten Gebietsschemas nicht vollständig. Um es zum Laufen zu bringen, müssen Sie die gesamte lokale Maschinerie lernen.

    – Reb.Kabine

    1. September 2015 um 13:13 Uhr


  • Genauer gesagt hat die Antwort abgelehnt, dass die Portabilität ein Problem sein könnte, und Sie sollten sich wahrscheinlich ansehen, welches Gebietsschema verwendet wird, wenn “” übergeben wird. Es stellt sich heraus, dass diese Antwort auf meinem Mac nicht sofort einsatzbereit ist, aber “nachsehen, welches Gebietsschema verwendet wird”, erfordert, dass Sie das Gebietsschema-Kaninchenloch hinuntergehen. Siehe diese Frage für eine bessere Antwort, die sofort funktioniert: stackoverflow.com/questions/3479485

    – Reb.Kabine

    1. September 2015 um 13:29 Uhr

  • Spuckt die Zahl mit Kommas in UK im Jahr 2021 aus mit ‘gcc version 10.3.0 (Ubuntu 10.3.0-1ubuntu1)’

    – ahcox

    2. September 2021 um 23:25 Uhr

Benutzer-Avatar
Knoten

Sie können tun, was Jacob vorgeschlagen hat, und imbue mit dem "" locale – aber dies wird den Systemstandard verwenden, der nicht garantiert, dass Sie das Komma erhalten. Wenn Sie das Komma erzwingen möchten (unabhängig von den Standardgebietsschemaeinstellungen des Systems), können Sie dies tun, indem Sie Ihr eigenes angeben numpunct Facette. Zum Beispiel:

#include <locale>
#include <iostream>
#include <iomanip>

class comma_numpunct : public std::numpunct<char>
{
  protected:
    virtual char do_thousands_sep() const
    {
        return ',';
    }

    virtual std::string do_grouping() const
    {
        return "\03";
    }
};

int main()
{
    // this creates a new locale based on the current application default
    // (which is either the one given on startup, but can be overriden with
    // std::locale::global) - then extends it with an extra facet that 
    // controls numeric output.
    std::locale comma_locale(std::locale(), new comma_numpunct());

    // tell cout to use our new locale.
    std::cout.imbue(comma_locale);

    std::cout << std::setprecision(2) << std::fixed << 1000000.1234;
}

  • Ich bin nur neugierig, ob Sie Ihr Beispiel lange bearbeiten können, anstatt zu schweben, da ich danach gesucht habe (und das ist es, was die Frage stellt.)

    – Mitreisender

    29. Oktober 2012 um 11:58 Uhr

  • @FellowTraveler es ist dasselbe, mach es einfach std::cout << myLongValue;.

    – Knoten

    29. Oktober 2012 um 13:23 Uhr

  • Warum funktioniert das für die Longs auch ohne Piping std::fixed? (Ich habe die Doppel nicht probiert).

    – aje

    16. April 2014 um 17:36 Uhr

  • Das ist toll! Jetzt müssen Sie sich nicht mehr mit UTF-8-Locales herumschlagen!

    – ForceBru

    1. April 2016 um 15:00 Uhr

  • Bei weitem eine der besten Möglichkeiten, dies zu tun

    – Vivic

    1. November 2017 um 15:04 Uhr

Benutzer-Avatar
carljalal

Ich halte die folgende Antwort für einfacher als die anderen:

#include <iostream>
int main() {
   int v = 7654321;
   auto s = std::to_string(v);

   int n = s.length() - 3;
   int end = (v >= 0) ? 0 : 1; // Support for negative numbers
   while (n > end) {
      s.insert(n, ",");
      n -= 3;
   }
   std::cout << (s == "7,654,321") << std::endl;
}   

Dadurch werden Kommas schnell und korrekt in Ihre Ziffernfolge eingefügt.

  • Dies funktioniert nicht mit Werten mit vorangestellten Nullen wie 010100

    – PapaDiHatti

    6. Mai 2017 um 0:32 Uhr

  • @Homer6 Das Problem mit negativen Zahlen könnte durch eine geringfügige Anpassung des Codes überwunden werden. Wenn die Zahl negativ ist, sollte das While-Schleifenkriterium insertPosition>1 sein … für -106 würde insertPosition bei 1 beginnen und es würde kein Komma eingefügt werden.

    – Cardiff-Weltraummann

    14. Juni 2017 um 19:27 Uhr

  • @Kapil-Nummern mit vorangestellten Nullen wie 010100 würden funktionieren: Sie würden zu Beginn insertPosition == 3 erhalten, Ihr Komma würde zwischen der 3. und 4. Ziffer stehen und das war’s. Könnten Sie weiter erklären, wie eine solche Ziffernfolge fehlschlagen würde?

    – Cardiff-Weltraummann

    14. Juni 2017 um 19:30 Uhr

  • @arljalal Ich mag den Code sehr. Der einzige Fehler meiner Meinung nach ist, wenn wirklich lange Zahlen üblich sind, ist es O (Länge zum Quadrat). Die While-Schleife läuft O(Länge) Mal und überträgt jedes Mal O(Länge) Ziffern. Ein Algorithmus, der mit durch Kommas getrennten Blöcken arbeitet, könnte insgesamt O (Länge) sein. Die meisten von uns werden 32-Bit- oder 64-Bit-Zahlen formatieren, daher ist das Problem gering.

    – Cardiff-Weltraummann

    14. Juni 2017 um 19:33 Uhr

  • @cardiffspaceman Die größte Zahl, die Sie in einem uint64_t speichern können, ist 18.446.744.073.709.551.615. Das sind 20 Ziffern. Wenn Sie mit größeren Zahlen arbeiten und diese tatsächlich lesbar haben möchten, ist die wissenschaftliche Notation wahrscheinlich der richtige Weg. Die 18-stellige Nummer ist schwer genug zu lesen. tl;dr: Ich glaube nicht, dass die große O-Laufzeit hier wirklich relevant ist. Vielleicht, wenn Sie mit Zahlen arbeiten, die Millionen von Ziffern lang sind und Sie Genauigkeit bis auf die Einerstelle benötigen.😸

    – Justin T. Conroy

    23. September 2021 um 18:31 Uhr


Benutzer-Avatar
Tom Serink

Das ist ziemlich altmodisch, ich verwende es in großen Schleifen, um zu vermeiden, dass ein weiterer Zeichenfolgenpuffer instanziiert wird.

void tocout(long a)
{
    long c = 1;

    if(a<0) {a*=-1;cout<<"-";}
    while((c*=1000)<a);
    while(c>1)
    {
       int t = (a%c)/(c/1000);
       cout << (((c>a)||(t>99))?"":((t>9)?"0":"00")) << t;
       cout << (((c/=1000)==1)?"":",");
    }
}

Benutzer-Avatar
Tro

Wenn Sie Qt verwenden, können Sie diesen Code verwenden:

const QLocale& cLocale = QLocale::c();
QString resultString = cLocale.toString(number);

Vergessen Sie auch nicht, hinzuzufügen #include <QLocale>.

Basierend auf den obigen Antworten habe ich diesen Code erhalten:

#include <iomanip>
#include <locale> 

template<class T>
std::string numberFormatWithCommas(T value){
    struct Numpunct: public std::numpunct<char>{
    protected:
        virtual char do_thousands_sep() const{return ',';}
        virtual std::string do_grouping() const{return "\03";}
    };
    std::stringstream ss;
    ss.imbue({std::locale(), new Numpunct});
    ss << std::setprecision(2) << std::fixed << value;
    return ss.str();
}

Benutzer-Avatar
Vinzenz Doba

Ich habe die Lösung gefunden! Kopieren Sie dies einfach in eine Ihrer Funktionen, diese Funktion ist in einer statischen Funktion geschrieben.

// Convert 100000000 to 100,000,000, put commas on the numbers!

std::string AppManager::convertNumberToString(int number) {
    std::string s = std::to_string(number);
    std::string result = "";
    std::string tempResult = "";
    unsigned long n = s.length() - 3;
    int j = 0;
    for (int i=s.size()-1; i>=0; i--) {
        if (j%3 == 0) {
            result.append(",");
        }
        result.append(s, i, 1);
        j++;
    }
    
    result = result.substr(1, result.size()-1);
    
    //now revert back
    for (int i=result.size()-1; i>=0; i--) {
        tempResult.append(result, i, 1);
    }
    
    return tempResult;
}

Hier ist das Ergebnis dieses Codes:

Klicken Sie hier, um das Ergebnis oben zu sehen!

1019590cookie-checkZahlen mit Kommas in C++ formatieren

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy