我正在尝试做这个简单的任务。只是使用C或C ++格式化数字,但在Windows CE编程下。
在这种环境中,inbue和setlocale方法都不起作用。
最后我这样做没有成功:
char szValue[10];
sprintf(szValue, "%'8d", iValue);
有什么想法吗?
答案 0 :(得分:1)
这是一种方法 - 创建自定义区域设置并使用适当自定义的方面填充它:
#include <locale>
#include <iostream>
#include <memory>
struct separate_thousands : std::numpunct<char> {
char_type do_thousands_sep() const override { return ','; } // separate with commas
string_type do_grouping() const override { return "\3"; } // groups of 3 digit
};
int main()
{
int number = 123'456'789;
std::cout << "default locale: " << number << '\n';
auto thousands = std::make_unique<separate_thousands>();
std::cout.imbue(std::locale(std::cout.getloc(), thousands.release()));
std::cout << "locale with modified thousands: " << number << '\n';
}
预期产出:
default locale: 123456789
locale with modified thousands: 123,456,789
答案 1 :(得分:1)
为什么要重新发明轮子而不使用为此提供的功能?请参阅GetNumberFormat。
可以使用正确的NUMBERFMT结构值完成自定义格式设置。例如(伪代码):
//Display three digits after the decimal point.
.NumDigits = 3
//Display zeros after the decimal point.
.LeadingZero = 1
//Group every three digits to the left of the decimal.
.Grouping = 3
//Use a comma to as the decimal point (like they do in France and Spain).
.lpDecimalSep = ","
//Likewise, use a period as the grouping separator.
.lpThousandSep = "."
//Put the negative sign immediately after the number.
.NegativeOrder = 3
答案 2 :(得分:1)
我用这个:
string thousands_separator(long long k, string symbol=",") {
int l, c, i;
string fin, s, u, rev;
bool min = false;
fin = "";
c = 0;
if(k < -999){
k *= -1;
min = true;
}
s = to_string(k);
if(k > 999){
l = s.length() - 1;
for (i = l; i >= 0; i--) {
fin += s[i];
c++;
if(c%3 == 0){
fin += symbol;
}
}
rev = fin;
fin = "";
l = rev.length() - 1;
for (i = l; i >= 0; i--) {
fin += rev[i];
}
u = fin[0];
if(u == symbol){
fin.erase(fin.begin());
}
if(min){
fin.insert(0, "-");
}
return fin;
} else {
return s;
}
}
答案 3 :(得分:-1)
最后,我开发了自己的功能:
std::string CFormat::GetInteger(int iValue)
{
std::string sValue;
std::string sDot = ".";
for(int iTmp = iValue; iTmp; iTmp /= 1000)
{
if ((int)(iTmp / 1000) == 0)
sDot.clear();
sValue = sDot + SSTR(iTmp % 1000) + sValue;
}
if (sValue.empty())
sValue = "0";
return sValue;
}
我认为它更简单,并且它不依赖于除std :: string之外的其他类,我知道它可以在Windows Mobile设备中使用。
答案 4 :(得分:-1)
这些函数在C ++中适用于字符串形式的数字(带或不带小数)。
下一个函数不支持负数或十进制分隔符,但是非常简单:
std::string quickAddThousandSeparators(std::string value, char thousandSep = ',')
{
int len = value.length();
int dlen = 3;
while (len > dlen) {
value.insert(len - dlen, 1, thousandSep);
dlen += 4;
len += 1;
}
return value;
}
下一个函数支持负数字符串和小数点分隔符:
std::string addThousandSeparators(std::string value, char thousandSep = ',', char decimalSep = '.', char sourceDecimalSep = '.')
{
int len = value.length();
int negative = ((len && value[0] == '-') ? 1: 0);
int dpos = value.find_last_of(sourceDecimalSep);
int dlen = 3 + (dpos == std::string::npos ? 0 : (len - dpos));
if (dpos != std::string::npos && decimalSep != sourceDecimalSep) {
value[dpos] = decimalSep;
}
while ((len - negative) > dlen) {
value.insert(len - dlen, 1, thousandSep);
dlen += 4;
len += 1;
}
return value;
}
并且gtest通过了测试:
TEST (quickAddThousandSeparators, basicNumbers) {
EXPECT_EQ("", quickAddThousandSeparators(""));
EXPECT_EQ("1", quickAddThousandSeparators("1"));
EXPECT_EQ("100", quickAddThousandSeparators("100"));
EXPECT_EQ("1,000", quickAddThousandSeparators("1000"));
EXPECT_EQ("10,000", quickAddThousandSeparators("10000"));
EXPECT_EQ("100,000", quickAddThousandSeparators("100000"));
EXPECT_EQ("1,000,000", quickAddThousandSeparators("1000000"));
EXPECT_EQ("1,000,000,000", quickAddThousandSeparators("1000000000"));
EXPECT_EQ("1,012,789,345,456,123,678,456,345,809", quickAddThousandSeparators("1012789345456123678456345809"));
}
TEST (quickAddThousandSeparators, changeThousandSeparator) {
EXPECT_EQ("", quickAddThousandSeparators("",'.'));
EXPECT_EQ("1", quickAddThousandSeparators("1",'.'));
EXPECT_EQ("100", quickAddThousandSeparators("100", '.'));
EXPECT_EQ("1.000", quickAddThousandSeparators("1000", '.'));
EXPECT_EQ("1.000.000.000", quickAddThousandSeparators("1000000000", '.'));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809", quickAddThousandSeparators("1012789345456123678456345809", '.'));
}
TEST (addThousandSeparators, basicNumbers) {
EXPECT_EQ("", addThousandSeparators(""));
EXPECT_EQ("1", addThousandSeparators("1"));
EXPECT_EQ("100", addThousandSeparators("100"));
EXPECT_EQ("1,000", addThousandSeparators("1000"));
EXPECT_EQ("10,000", addThousandSeparators("10000"));
EXPECT_EQ("100,000", addThousandSeparators("100000"));
EXPECT_EQ("1,000,000", addThousandSeparators("1000000"));
EXPECT_EQ("1,000,000,000", addThousandSeparators("1000000000"));
EXPECT_EQ("1,012,789,345,456,123,678,456,345,809", addThousandSeparators("1012789345456123678456345809"));
}
TEST (addThousandSeparators, negativeBasicNumbers) {
EXPECT_EQ("", addThousandSeparators(""));
EXPECT_EQ("-1", addThousandSeparators("-1"));
EXPECT_EQ("-100", addThousandSeparators("-100"));
EXPECT_EQ("-1,000", addThousandSeparators("-1000"));
EXPECT_EQ("-10,000", addThousandSeparators("-10000"));
EXPECT_EQ("-100,000", addThousandSeparators("-100000"));
EXPECT_EQ("-1,000,000", addThousandSeparators("-1000000"));
EXPECT_EQ("-1,000,000,000", addThousandSeparators("-1000000000"));
EXPECT_EQ("-1,012,789,345,456,123,678,456,345,809", addThousandSeparators("-1012789345456123678456345809"));
}
TEST (addThousandSeparators, changeThousandSeparator) {
EXPECT_EQ("", addThousandSeparators("",'.'));
EXPECT_EQ("-1", addThousandSeparators("-1",'.'));
EXPECT_EQ("100", addThousandSeparators("100", '.'));
EXPECT_EQ("-1.000", addThousandSeparators("-1000", '.'));
EXPECT_EQ("-1.000.000.000", addThousandSeparators("-1000000000", '.'));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809", addThousandSeparators("1012789345456123678456345809", '.'));
}
TEST (addThousandSeparators, changeDecimalSeparator) {
EXPECT_EQ("0,5", addThousandSeparators("0.5",'.',','));
EXPECT_EQ("0", addThousandSeparators("0",'.',','));
EXPECT_EQ("-1,23", addThousandSeparators("-1.23",'.',','));
EXPECT_EQ("100,56", addThousandSeparators("100.56", '.',','));
EXPECT_EQ("-1.000,786", addThousandSeparators("-1000.786", '.',','));
EXPECT_EQ("-1.000.000.000,4859", addThousandSeparators("-1000000000.4859", '.', ','));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809,6785960", addThousandSeparators("1012789345456123678456345809.6785960", '.',','));
}
TEST (addThousandSeparators, changeSourceDecimalSeparator) {
EXPECT_EQ("0,5", addThousandSeparators("0,5",'.',',',','));
EXPECT_EQ("0", addThousandSeparators("0",'.',',',','));
EXPECT_EQ("-1,23", addThousandSeparators("-1,23",'.',',',','));
EXPECT_EQ("100,56", addThousandSeparators("100,56", '.',',',','));
EXPECT_EQ("-1.000,786", addThousandSeparators("-1000,786", '.',',',','));
EXPECT_EQ("-1.000.000.000,4859", addThousandSeparators("-1000000000,4859", '.', ',',','));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809,6785960", addThousandSeparators("1012789345456123678456345809,6785960", '.',',',','));
}
答案 5 :(得分:-2)
这是另一种方式,使用手动操作:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
int number = 123'456'789;
auto src = std::to_string(number);
auto dest = std::string();
auto count = 3;
for(auto i = src.crbegin() ; i != src.crend() ; ++i) {
if (count == 0)
{
dest.push_back(',');
count = 3;
}
if (count--) {
dest.push_back(*i);
}
}
std::reverse(dest.begin(), dest.end());
std::cout << dest << '\n';
}
答案 6 :(得分:-2)
注意:在提交此答案时,帖子被标记为C / C ++。现在它被标记为C.我怀疑它可能会再次发生变化。
如果您想要推出使用C99的自己的C解决方案,下面将构成在各种区域设置下在我的Windows gcc上运行的基础。
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define INT_STR_SIZE (CHAR_BIT*sizeof(int)*3/10 + 2)
#define INT_SEP_STR_SIZE (INT_STR_SIZE * 3/2 + 1)
#define INT_SEP(x) int_sep((char[INT_SEP_STR_SIZE]) { "" }, INT_SEP_STR_SIZE, x)
char *int_sep(char *s, size_t sz, int x) {
struct lconv *locale_ptr = localeconv();
const char *grouping = locale_ptr->grouping;
char sep = locale_ptr->thousands_sep[0];
if (sz > 0) {
int x0 = x;
char *ptr = s + sz;
*--ptr = '\0';
char count = 0;
do {
if (count >= grouping[0]) {
*--ptr = sep;
if (grouping[1]) grouping++;
count = 0;
}
count++;
//printf("%d %d <%s> %p\n", count, n, locale_ptr->grouping, (void*)locale_ptr);
*--ptr = (char) (abs(x % 10) + '0');
} while (x /= 10);
if (x0 < 0) {
*--ptr = '-';
}
memmove(s, ptr, (size_t) (&s[sz] - ptr));
}
return s;
}
主
int main(void) {
puts(setlocale(LC_ALL,"en_US"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_SEP_STR_SIZE), INT_SEP(12345678), INT_SEP(1234));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(-1), INT_SEP(0), INT_SEP(1));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"C"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"it_IT"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"as_IN"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"be_BY"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
return 0;
}
输出
en_US
: 17: : 12,345,678: : 1,234:
: -1: : 0: : 1:
: -2,147,483,648: : -2,147,483,647: : 2,147,483,647:
C
: -2147483648: : -2147483647: : 2147483647:
it_IT
: -2.147.483.648: : -2.147.483.647: : 2.147.483.647:
as_IN
:-2,14,74,83,648: :-2,14,74,83,647: : 2,14,74,83,647:
be_BY
: -2 147 483 648: : -2 147 483 647: : 2 147 483 647: