在C语言中,如何将大数字格式化为例如 1123456789
到 1,123,456,789
?
我尝试使用 printf("%'10d\n", 1123456789)
,但这并不起作用。
你有什么建议吗?解决方案越简单越好。
在C语言中,如何将大数字格式化为例如 1123456789
到 1,123,456,789
?
我尝试使用 printf("%'10d\n", 1123456789)
,但这并不起作用。
你有什么建议吗?解决方案越简单越好。
这是最精简、尺寸和速度效率最高的实现此类小数数字格式化的方法:
const char *formatNumber (
int value,
char *endOfbuffer,
bool plus)
{
int savedValue;
int charCount;
savedValue = value;
if (unlikely (value < 0))
value = - value;
*--endOfbuffer = 0;
charCount = -1;
do
{
if (unlikely (++charCount == 3))
{
charCount = 0;
*--endOfbuffer = ',';
}
*--endOfbuffer = (char) (value % 10 + '0');
}
while ((value /= 10) != 0);
if (unlikely (savedValue < 0))
*--endOfbuffer = '-';
else if (unlikely (plus))
*--endOfbuffer = '+';
return endOfbuffer;
}
使用方法如下:
char buffer[16];
fprintf (stderr, "test : %s.", formatNumber (1234567890, buffer + 16, true));
输出:
test : +1,234,567,890.
一些优点:
函数采用字符串缓冲区的末尾,因为格式化是反向的。最终,不需要翻转生成的字符串(strrev)。
此函数生成一个字符串,可在任何算法之后使用。它既不依赖于多个printf/sprintf调用,也不需要它们,这很慢且始终是上下文特定的。
unlikely
? - Dan Bechardunlikely
可能是向优化器提示条件不太可能为真的一种方式。有关更多信息,请参见 Linux 内核中的 likely()
/unlikely()
宏。 - Jonathan Leffler我是C语言编程的新手。这是我的简单代码。
int main()
{
// 1223 => 1,223
int n;
int a[10];
printf(" n: ");
scanf_s("%d", &n);
int i = 0;
while (n > 0)
{
int temp = n % 1000;
a[i] = temp;
n /= 1000;
i++;
}
for (int j = i - 1; j >= 0; j--)
{
if (j == 0)
{
printf("%d.", a[j]);
}
else printf("%d,",a[j]);
}
getch();
return 0;
}
setlocale(LC_NUMERIC, getenv("LC_NUMERIC"));
可以相当容易地完成...
//Make sure output buffer is big enough and that input is a valid null terminated string
void pretty_number(const char* input, char * output)
{
int iInputLen = strlen(input);
int iOutputBufferPos = 0;
for(int i = 0; i < iInputLen; i++)
{
if((iInputLen-i) % 3 == 0 && i != 0)
{
output[iOutputBufferPos++] = ',';
}
output[iOutputBufferPos++] = input[i];
}
output[iOutputBufferPos] = '\0';
}
示例调用:
char szBuffer[512];
pretty_number("1234567", szBuffer);
//strcmp(szBuffer, "1,234,567") == 0
// separate thousands
int digit;
int idx = 0;
static char buffer[32];
char* p = &buffer[32];
*--p = '\0';
for (int i = fCounter; i != 0; i /= 10)
{
digit = i % 10;
if ((p - buffer) % 4 == 0)
*--p = ' ';
*--p = digit + '0';
}
idx
可以删除。该代码对于0没有任何输出。它也无法处理负数。没有明显的理由使buffer
成为一个static
变量(它限制了代码的可重入性)。没有解释它的作用,或者提到在代码完成后,由p
指向的字符串包含格式化的字符串。最不严重的问题是它使用空格而不是逗号作为千位分隔符。然而,它不能处理零是致命的问题。 - Jonathan Lefflervoid printfcomma ( long long unsigned int n)
{
char nstring[100];
int m;
int ptr;
int i,j;
sprintf(nstring,"%llu",n);
m=strlen(nstring);
ptr=m%3;
if (ptr)
{ for (i=0;i<ptr;i++) // print first digits before comma
printf("%c", nstring[i]);
printf(",");
}
j=0;
for (i=ptr;i<m;i++) // print the rest inserting commas
{
printf("%c",nstring[i]);
j++;
if (j%3==0)
if(i<(m-1)) printf(",");
}
}
printf()
而不是putchar()
,使用误导性的名称,混乱的缩进和过多的代码。 - chqrlie
printf()
系列格式化IO函数的“千位分隔符”标志(单引号字符:')是一个非标准标志,仅受到少数库实现的支持。很遗憾它不是标准的。 - Michael BurrLC_NUMERIC
。然而,我不知道有哪个区域支持这个。 - Joey AdamsLC_NUMERIC
区域设置为当前的""
可以使得'
在我的Mac和我刚刚检查过的Linux机器上正常工作。 - Carl Norumprintf()
函数系列标准化了使用'
(单引号或撇号)字符与十进制数格式转换规范,以指定应使用千位分隔符格式化数字。 - Jonathan Lefflersetlocale(LC_ALL, "");
可以完成这项工作 - 除了空字符串之外,语言环境名称的其他值都是实现定义的。 - Jonathan Leffler