如何在C语言中使用逗号作为千位分隔符格式化数字?

105

在C语言中,如何将大数字格式化为例如 11234567891,123,456,789

我尝试使用 printf("%'10d\n", 1123456789),但这并不起作用。

你有什么建议吗?解决方案越简单越好。


2
只是提醒一下:printf()系列格式化IO函数的“千位分隔符”标志(单引号字符:')是一个非标准标志,仅受到少数库实现的支持。很遗憾它不是标准的。 - Michael Burr
1
它是区域依赖的。根据Linux man page所述,它查看LC_NUMERIC。然而,我不知道有哪个区域支持这个。 - Joey Adams
1
@Joey,将LC_NUMERIC区域设置为当前的""可以使得'在我的Mac和我刚刚检查过的Linux机器上正常工作。 - Carl Norum
请注意,POSIX 2008(2013)版本的printf()函数系列标准化了使用'(单引号或撇号)字符与十进制数格式转换规范,以指定应使用千位分隔符格式化数字。 - Jonathan Leffler
2
请注意,在默认的“C”语言环境中,非货币千位分隔符是未定义的,因此“%'d”在“C”语言环境中不会产生逗号。您需要设置一个具有适当的非货币千位分隔符的语言环境。通常,setlocale(LC_ALL, "");可以完成这项工作 - 除了空字符串之外,语言环境名称的其他值都是实现定义的。 - Jonathan Leffler
显示剩余2条评论
26个回答

0

这是最精简、尺寸和速度效率最高的实现此类小数数字格式化的方法:

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 Bechard
1
@Dan:unlikely 可能是向优化器提示条件不太可能为真的一种方式。有关更多信息,请参见 Linux 内核中的 likely()/unlikely() - Jonathan Leffler
@JonathanLeffler 噢,好的。谢谢你提供的链接。 - Dan Bechard

0

我是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;
}

0
这样做似乎很令人伤感:
setlocale(LC_NUMERIC, getenv("LC_NUMERIC"));

-1

可以相当容易地完成...

//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

-1
        // 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';
        }

1
这段代码存在各种问题。未使用的变量idx可以删除。该代码对于0没有任何输出。它也无法处理负数。没有明显的理由使buffer成为一个static变量(它限制了代码的可重入性)。没有解释它的作用,或者提到在代码完成后,由p指向的字符串包含格式化的字符串。最不严重的问题是它使用空格而不是逗号作为千位分隔符。然而,它不能处理零是致命的问题。 - Jonathan Leffler

-1
void 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(",");
           }

}

2
发布代码时,请至少使用适当的缩进。此外,也许可以添加一些解释,说明这个代码与现有答案的不同之处。 - EWit
这具有简单性的优点,一眼就能轻松理解。 - steve newman
1
虚假的解决方案,对于小于100的数字会多打印一个逗号,使用printf()而不是putchar(),使用误导性的名称,混乱的缩进和过多的代码。 - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接