我想出了这个,因为stackoverflow上提供的其他示例都在C#
中string number_fmt(ulong n)
{
// cout << "(" << n << ")" << endl;
char s[128];
sprintf(s, "%lu", n);
string r(s);
reverse(r.begin(), r.end());
int space_inserted = 0;
size_t how_many_spaces = r.length() / 3;
if(r.length() % 3 != 0)
how_many_spaces += 1;
for(int i = 1; i < how_many_spaces; ++i)
{
r.insert(3 * i + space_inserted, " ");
space_inserted += 1;
}
reverse(r.begin(), r.end());
return r;
}
你知道更好的解决方案吗?
答案 0 :(得分:5)
我不知道“更好”,但此版本使用std::locale
等。
#include <iostream>
#include <locale>
#include <sstream>
template<class Char>
class MyFacet : public std::numpunct<Char> {
public:
std::string do_grouping() const { return "\3"; }
Char do_thousands_sep() const { return ' '; }
};
std::string number_fmt(unsigned long n)
{
std::ostringstream oss;
oss.imbue(std::locale(oss.getloc(), new MyFacet<char>));
oss << n;
return oss.str();
}
int main() {
std::cout << number_fmt(123456789) << "\n";
}
<小时/> 编辑:当然,如果您的最终目标是在
ostream
上打印值,则可以跳过将它们全部存储在string
中。
#include <iostream>
#include <locale>
#include <sstream>
#include <cwchar>
template <class Char>
class MyFacet : public std::numpunct<Char> {
public:
std::string do_grouping() const { return "\3"; }
Char do_thousands_sep() const { return ' '; }
};
int main(int ac, char **av) {
using std::locale;
using std::cout;
// Show how it works to start with
cout << 123456789 << "\n";
// Switch it to spacey mode
locale oldLoc =
cout.imbue(locale(cout.getloc(), new MyFacet<char>));
// How does it work now?
cout << 456789123 << "\n";
// You probably want to clean up after yourself
cout.imbue(oldLoc);
// Does it still work?
cout << 789123456 << "\n";
}
答案 1 :(得分:3)
这已由语言环境完成。
默认本地为“C”,不进行格式化。但您可以将其设置为当前特定语言的本地(通过将当前本地设置为main
的第一行来定义您的计算机设置。)
int main()
{
std::locale::global(std::locale("")); // Set the default local of the machine
// Will be used by all streams.
// The "" will find the machine specific local
// and use that instead of the "C" locale
// Note: The C local should only be used for programmers.
// Alternatively you can imbue particular stream with the local
// To achieve a localized effect
// std::cout.imbue(std::locale(""));
// Now all you do is print the number.
std::cout << "123456789\n"; // This will print the number according to your local
} // For me US-en this is 123,456,789
// Your may very.
如果您想明确地执行某些操作,则可以在本地设置构面以打印数字。
#include <iostream>
#include <locale>
#include <string>
template<typename CharT>
struct Sep : public std::numpunct<CharT>
{
virtual std::string do_grouping() const {return "\003";}
virtual CharT do_thousands_sep() const {return ':';}
};
int main()
{
std::cout.imbue(std::locale(std::cout.getloc(), new Sep <char>()));
std::cout << 123456789 << "\n"; // this prints 123:456:789
}
答案 2 :(得分:2)
这个是不同的,但更好是主观的。我认为它非常简洁明了,但它正在做什么:
string number_fmt(unsigned long long n, char sep = ',') {
stringstream fmt;
fmt << n;
string s = fmt.str();
s.reserve(s.length() + s.length() / 3);
// loop until the end of the string and use j to keep track of every
// third loop starting taking into account the leading x digits (this probably
// can be rewritten in terms of just i, but it seems more clear when you use
// a seperate variable)
for (int i = 0, j = 3 - s.length() % 3; i < s.length(); ++i, ++j)
if (i != 0 && j % 3 == 0)
s.insert(i++, 1, sep);
return s;
}
像
一样使用它cout << number_fmt(43615091387465) << endl;
打印
43,615,091,387,465
答案 3 :(得分:0)
如果“更好”意味着更高效,您应该:
在输出字符串上使用reserve
(你知道它的大小......)
避免字符串中间的insert
,因为每次执行此操作时都必须复制字符串的大部分内容。
我会说这样的话(未经测试):
std::string number_fmt (ulong n)
{
std::ostringstream buff;
buff << n;
std::string without_spaces = buff.str ();
std::string with_spaces;
with_spaces.reserve ((without_spaces.size () * 4) / 3);
std::size_t nb_inserted = 0;
for (auto it = without_spaces.rbegin (); it != without_spaces.rend (); ++it)
{
if (nb_inserted % 3 == 0 && nb_inserted != 0)
{
with_spaces.push_back (' ');
}
++ nb_inserted;
with_spaces.push_back (*it);
}
std::reverse (with_spaces.begin (), with_spaces.end ());
return with_spaces;
}
答案 4 :(得分:0)
不可否认,如果一个人想拥有最有效的版本并且不介意专门针对手头的情况,那么使用本地字符缓冲区可以提供很多帮助。
#include <iostream>
#include <string>
std::string format(unsigned long long i) {
char buffer[128]; // can be adapted more tightly with std::numeric_limits
char* p = buffer + 128;
*(--p) = '\0';
unsigned char count = 0;
while (i != 0) {
*(--p) = '0' + (i % 10);
i /= 10;
if (++count == 3) { count = 0; *(--p) = ' '; }
}
return p;
}
int main() {
std::cout << format(1234567890) << '\n';
}
ideone的行动:
1 234 567 890
(关键点:数字打印,向后)
答案 5 :(得分:0)
不是很好,但是很小
QString str = QString::number(d);
for (int i = 3; str.size() > i; i += 4)
str.insert(str.size() - i, ' ');