web-dev-qa-db-fra.com

c ++: Numéro de format avec des virgules?

Je veux écrire une méthode qui prendra un entier et renverra un std::string de cet entier formaté avec des virgules.

Exemple de déclaration:

std::string FormatWithCommas(long value);

Exemple d'utilisation:

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

Quelle est la méthode C++ pour formater un nombre sous la forme string avec des virgules?

(Le bonus serait de gérer doubles aussi.)

58
User

Utilisez std::locale avec 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();
}

Disclaimer: La portabilité pourrait être un problème et vous devriez probablement regarder quel paramètre régional est utilisé lorsque "" est passé

45
Jacob

Vous pouvez faire ce que Jacob a suggéré, et imbue avec les paramètres régionaux "" - mais cela utilisera la valeur par défaut du système, ce qui ne garantit pas que vous obtenez la virgule. Si vous souhaitez forcer la virgule (quels que soient les paramètres régionaux par défaut du système), vous pouvez le faire en fournissant votre propre numpunct facet. Par exemple:

#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;
}
43
Node

Je considère que la réponse suivante est plus facile que les autres:

string numWithCommas = to_string(value);
int insertPosition = numWithCommas.length() - 3;
while (insertPosition > 0) {
    numWithCommas.insert(insertPosition, ",");
    insertPosition-=3;
}

Cela va rapidement et correctement insérer des virgules dans votre chaîne de chiffres.

28
carljalal

sur la base des réponses ci-dessus, j'ai fini avec ce code:

#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();
}
2
Radif Sharafullin

Ceci est assez vieux école, je l'utilise dans les grandes boucles pour éviter d'instancier un autre tampon de chaîne.

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)?"":",");
    }
}
2
Tom Serink

Si vous utilisez Qt, vous pouvez utiliser ce code:

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

De plus, n'oubliez pas d'ajouter #include <QLocale>.

1
troyane

Pour le rendre plus flexible, vous pouvez construire la facette avec une chaîne de milliers et une chaîne de regroupement personnalisées .

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

class comma_numpunct : public std::numpunct<char>
{
public:
   comma_numpunct(char thousands_sep, const char* grouping)
      :m_thousands_sep(thousands_sep),
       m_grouping(grouping){}
protected:
   char do_thousands_sep() const{return m_thousands_sep;}
   std::string do_grouping() const {return m_grouping;}
private:
   char m_thousands_sep;
   std::string m_grouping;
};

int main()
{

    std::locale comma_locale(std::locale(), new comma_numpunct(',', "\03"));

    std::cout.imbue(comma_locale);
    std::cout << std::setprecision(2) << std::fixed << 1000000.1234;
}
0
Marcel