83 votes

c++ : Formater un nombre avec des virgules ?

Je veux écrire une méthode qui prendra un entier et retournera un std::string de ce nombre 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 façon C++ de formater un nombre en tant que string avec des virgules ?

(Le bonus serait de gérer double également).

0 votes

1 votes

1 votes

Ce qui est boiteux dans ces déclarations en double, c'est que j'ai cherché cette question avant en utilisant les termes de recherche les plus évidents et je n'ai trouvé aucune de ces questions. Mon titre est meilleur et plus pertinent, et la réponse acceptée à ma question est meilleure que les réponses à toutes ces questions.

1voto

Radif Sharafullin Points 415

En me basant sur les réponses ci-dessus, je me suis retrouvé 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();
}

0 votes

Ceci invoque un comportement non défini ( double libre ou corruption dans mon test) parce que vous passez un pointeur vers une facette qui n'a pas été allouée par new . Soit utiliser new comme dans les autres réponses, ou mettez le refcount de la classe de base à 1 dans le constructeur de votre facette !

0 votes

Merci de le signaler. Je l'ai testé uniquement sur iOS où cela a fonctionné. Cela n'a pas fonctionné pour Mac.

-1voto

Marcel Points 1

Pour plus de souplesse, vous pourriez construire la facette avec une chaîne de milliers sep et de regroupement personnalisée. De cette façon, vous pouvez la définir au moment de l'exécution.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X