c ++: форматировать число запятыми? - PullRequest
61 голосов
/ 02 сентября 2011

Я хочу написать метод, который будет принимать целое число и возвращать std::string этого целого числа, отформатированного запятыми.

Пример объявления:

std::string FormatWithCommas(long value);

Пример использования:

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"

Что такое C ++ способ форматирования числа как string с запятыми?

(Бонус будет также обрабатывать double с.)

Ответы [ 7 ]

49 голосов
/ 02 сентября 2011

Использование std::locale с 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();
}

Отказ от ответственности: Переносимость может быть проблемой, и вы, вероятно, должны посмотретьв котором используется локаль, когда передается ""

46 голосов
/ 02 сентября 2011

Вы можете сделать, как предложил Джейкоб, и imbue с языком "" - но при этом будет использоваться системное значение по умолчанию, которое не гарантирует получение запятой.Если вы хотите ввести запятую (независимо от системных настроек по умолчанию), вы можете сделать это, указав свой numpunct фасет.Например:

#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;
}
30 голосов
/ 12 июня 2014

Я считаю, что следующий ответ проще, чем другие:

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

Это быстро и правильно вставит запятые в вашу строку цифр.

2 голосов
/ 10 июня 2016

Это довольно старая школа, я использую ее в больших циклах, чтобы избежать создания другого строкового буфера.

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 голосов
/ 21 июля 2015

Если вы используете Qt, вы можете использовать этот код:

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

Также не забудьте добавить #include <QLocale>.

2 голосов
/ 06 сентября 2013

основываясь на ответах выше, я получил этот код:

#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 голосов
/ 16 июня 2015

Чтобы сделать его более гибким, вы можете создать фасет с помощью пользовательской строки с тысячами сегментов и групп.Таким образом, вы можете установить его во время выполнения.

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