如何用C格式化从1123456789到1,123,456,789的数字?


83

如何用C语言将数字从格式化11234567891,123,456,789?我尝试使用,printf("%'10d\n", 1123456789);但这不起作用。

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


1
仅供参考:printf()格式化的IO函数系列的“千分隔符”标志(单引号字符:“)是非标准标志,仅在少数库实现中受支持。太糟糕了,它不是标准的。
Michael Burr

1
它取决于语言环境。根据Linux手册页,它看起来像LC_NUMERIC。但是,我不知道哪种语言环境支持此功能。
乔伊·亚当斯

1
@Joey,设定LC_NUMERIC区域设置为当前""'我的Mac,我只是检查一台Linux机器上工作。
卡尔·诺鲁姆

请注意,该printf()功能家族的POSIX 2008(2013)版本确实将'(单引号或单引号)字符与十进制数字格式转换规范一起使用,以指定数字应使用数千个分隔符进行格式化。
乔纳森·莱夫勒

2
还要注意,在默认"C"语言环境中,非货币千位分隔符是未定义的,因此"%'d"不会在该"C"语言环境中产生逗号。您需要使用适当的非货币千位分隔符设置区域设置。通常,setlocale(LC_ALL, "");这项工作会做得到-语言环境名称的其他值(空字符串除外)是实现定义的。
乔纳森·莱夫勒

Answers:


83

如果您的printf支持该'标志(如POSIX 2008所要求printf()),则可以仅通过适当地设置区域设置来实现。例:

#include <stdio.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_NUMERIC, "");
    printf("%'d\n", 1123456789);
    return 0;
}

并运行:

$ ./example 
1,123,456,789

在Mac OS X和Linux(Ubuntu 10.10)上进行了测试。


1
我测试过这对sprintf()在嵌入式系统中,它不是不工作(很明显,因为正如你所说,这将不支持'标志。
gbmhunter

我相信您可以找到一个可以轻松支持它的C库。
卡尔·诺鲁姆

我快速浏览了一下,没有找到合适的方法,并使用上面的一些想法实现了自己的想法。最好找到一个实际的库,以便可以在带小数位的浮点数和字符串上使用它。
gbmhunter 2013年

1
FWIW AtmelStudio的嵌入式系统printf()悲惨地似乎支持该'修饰符。从头开始:Copyright ... 2007 Joerg Wunsch ... 1993 Regents of the University of California即BSD派生词。
Bob Stein 2014年

2
尽管这很方便-您不一定要更改此功能的状态(setlocale)。
ideaman42

46

您可以按以下方式递归执行此操作(请注意,INT_MIN如果使用二进制补码,则需要额外的代码来管理它):

void printfcomma2 (int n) {
    if (n < 1000) {
        printf ("%d", n);
        return;
    }
    printfcomma2 (n/1000);
    printf (",%03d", n%1000);
}

void printfcomma (int n) {
    if (n < 0) {
        printf ("-");
        n = -n;
    }
    printfcomma2 (n);
}

总结:

  • 用户printfcomma使用整数进行调用,负数的特殊情况是通过简单地打印“-”并使数字为正数来处理(这与INT_MIN)。
  • 当您输入 printfcomma2,小于1,000的数字将被打印并返回。
  • 否则,递归将在下一级上调用(因此将调用1,234,567,先以1,234,然后是1),直到找到小于1,000的数字。
  • 然后将打印该数字,然后我们将返回递归树,在打印过程中打印逗号和下一个数字。

还有一个更简洁的版本,尽管它在检查每个级别的负数时进行了不必要的处理(这并不重要,因为递归级别的数量有限)。这是一个完整的测试程序:

#include <stdio.h>

void printfcomma (int n) {
    if (n < 0) {
        printf ("-");
        printfcomma (-n);
        return;
    }
    if (n < 1000) {
        printf ("%d", n);
        return;
    }
    printfcomma (n/1000);
    printf (",%03d", n%1000);
}

int main (void) {
    int x[] = {-1234567890, -123456, -12345, -1000, -999, -1,
               0, 1, 999, 1000, 12345, 123456, 1234567890};
    int *px = x;
    while (px != &(x[sizeof(x)/sizeof(*x)])) {
        printf ("%-15d: ", *px);
        printfcomma (*px);
        printf ("\n");
        px++;
    }
    return 0;
}

输出为:

-1234567890    : -1,234,567,890
-123456        : -123,456
-12345         : -12,345
-1000          : -1,000
-999           : -999
-1             : -1
0              : 0
1              : 1
999            : 999
1000           : 1,000
12345          : 12,345
123456         : 123,456
1234567890     : 1,234,567,890

一个不信任递归的迭代解决方案(尽管递归的唯一问题往往是堆栈空间,这在这里不会成为问题,因为即使对于64位整数也只有几层深度):

void printfcomma (int n) {
    int n2 = 0;
    int scale = 1;
    if (n < 0) {
        printf ("-");
        n = -n;
    }
    while (n >= 1000) {
        n2 = n2 + scale * (n % 1000);
        n /= 1000;
        scale *= 1000;
    }
    printf ("%d", n);
    while (scale != 1) {
        scale /= 1000;
        n = n2 / scale;
        n2 = n2  % scale;
        printf (",%03d", n);
    }
}

这两个产生2,147,483,647INT_MAX


我认为这应该迭代解决,因为问题更自然地是迭代的(“每三位数字分开”)而不是递归的(“从其余的数位分开,然后在其余的数位重复”)。
Joren

建议的MIN_INT修复:将printfcomma2更改为无符号整数。而已。并不是太多的“额外代码” :-)
史蒂夫·杰索普

@Joren:我添加了一个迭代解决方案,并且在某种程度上说明了为什么递归解决方案具有优点。尽管在许多情况下,避免递归是编码标准问题。
克利福德,

@Steve:仅仅更改参数类型并不能解决问题,因为在您取反n时会立即调用UB printfcomma。否定转换之前,您需要强制将其转换为无符号的。
R .. GitHub停止帮助ICE,

1
@Nehal,从当前所有进度都丢失的意义上讲,它不会再次开始。它递归地调用自己,然后返回到下一个语句printf
paxdiablo

11

这是一个非常简单的实现。此功能包含任何错误检查,缓冲区大小必须由调用进行验证。它也不适用于负数。这些改进留给读者练习。

void format_commas(int n, char *out)
{
    int c;
    char buf[20];
    char *p;

    sprintf(buf, "%d", n);
    c = 2 - strlen(buf) % 3;
    for (p = buf; *p != 0; p++) {
       *out++ = *p;
       if (c == 1) {
           *out++ = ',';
       }
       c = (c + 1) % 3;
    }
    *--out = 0;
}

我喜欢这一点,它使用sprintf而不是printf,这对于嵌入式系统很有用。
gbmhunter

1
很好,但是需要一些小的调整才能使负数起作用。
ideaman42 2014年

(修改后的版本为负数支持stackoverflow.com/a/24795133/432509
ideasman42

5

哎呀!我一直在Linux上使用gcc / g ++和glibc来执行此操作,是的,'运算符可能是非标准的,但我喜欢它的简单性。

#include <stdio.h>
#include <locale.h>

int main()
{
    int bignum=12345678;

    setlocale(LC_ALL,"");

    printf("Big number: %'d\n",bignum);

    return 0;
}

提供以下内容的输出:

大数:12,345,678

只需记住那里的“ setlocale”调用即可,否则它不会格式化任何内容。


2
可悲的是,这似乎在Windows / gcc 4.9.2中不起作用。
rdtsc

好啦,德拉特!我会发现,无论使用什么操作系统,任何平台上的gcc都会给出相似的结果。很高兴知道,我想知道为什么。

请注意,如果正在使用的C库不支持该'标志,那么您将无法获得所需的输出-并且该输出与编译器无关。编译器确保printf()使用格式字符串调用for的库函数;由库函数来解释它。在Windows上,CRT库很可能没有提供您所需的支持-与使用哪个编译器无关紧要。
乔纳森·莱夫勒

3

可能的语言环境感知版本可能会很有趣。

#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <limits.h>

static int next_group(char const **grouping) {
    if ((*grouping)[1] == CHAR_MAX)
        return 0;
    if ((*grouping)[1] != '\0')
        ++*grouping;
    return **grouping;
}

size_t commafmt(char   *buf,            /* Buffer for formatted string  */
                int     bufsize,        /* Size of buffer               */
                long    N)              /* Number to convert            */
{
    int i;
    int len = 1;
    int posn = 1;
    int sign = 1;
    char *ptr = buf + bufsize - 1;

    struct lconv *fmt_info = localeconv();
    char const *tsep = fmt_info->thousands_sep;
    char const *group = fmt_info->grouping;
    char const *neg = fmt_info->negative_sign;
    size_t sep_len = strlen(tsep);
    size_t group_len = strlen(group);
    size_t neg_len = strlen(neg);
    int places = (int)*group;

    if (bufsize < 2)
    {
ABORT:
        *buf = '\0';
        return 0;
    }

    *ptr-- = '\0';
    --bufsize;
    if (N < 0L)
    {
        sign = -1;
        N = -N;
    }

    for ( ; len <= bufsize; ++len, ++posn)
    {
        *ptr-- = (char)((N % 10L) + '0');
        if (0L == (N /= 10L))
            break;
        if (places && (0 == (posn % places)))
        {
            places = next_group(&group);
            for (int i=sep_len; i>0; i--) {
                *ptr-- = tsep[i-1];
                if (++len >= bufsize)
                    goto ABORT;
            }
        }
        if (len >= bufsize)
            goto ABORT;
    }

    if (sign < 0)
    {
        if (len >= bufsize)
            goto ABORT;
        for (int i=neg_len; i>0; i--) {
            *ptr-- = neg[i-1];
            if (++len >= bufsize)
                goto ABORT;
        }
    }

    memmove(buf, ++ptr, len + 1);
    return (size_t)len;
}

#ifdef TEST
#include <stdio.h>

#define elements(x) (sizeof(x)/sizeof(x[0]))

void show(long i) {
    char buffer[32];

    commafmt(buffer, sizeof(buffer), i);
    printf("%s\n", buffer);
    commafmt(buffer, sizeof(buffer), -i);
    printf("%s\n", buffer);
}


int main() {

    long inputs[] = {1, 12, 123, 1234, 12345, 123456, 1234567, 12345678 };

    for (int i=0; i<elements(inputs); i++) {
        setlocale(LC_ALL, "");
        show(inputs[i]);
    }
    return 0;
}

#endif

这确实有一个错误(但是我认为这个错误很小)。在二进制补码硬件上,它将无法正确转换最负数,因为它会尝试将负数转换为带有的正数。N = -N;在二进制补码中,最大负数没有对应的正数,除非您将其提升为更大的类型。解决此问题的一种方法是通过将数字升为相应的无符号类型(但这有点不平凡)。


我在这里提出了一个更直接地针对'-flag格式的跨平台实现的问题:stackoverflow.com/q/44523855/2642059我认为这个答案可以完美解决这一问题,现在进行更多测试。如果是这样,我想我应该将这个问题标记为欺骗吗?
乔纳森·梅

好的,我知道的第一件事是,它不会随着语言环境的调整而调整。为什么维护tsepplace_str以及neg_str在所有?为什么不直接使用fmt_info的成员呢?
乔纳森·梅

好吧,编号2的东西,此代码不能处理负数...而且我不完全知道该怎么做,while (*ptr-- = *neg_str++)对我来说没有多大意义。您将以相反的顺序插入负字符串字符。
乔纳森·梅

因此,...我消除了内存泄漏,并使用负数纠正了该错误:ideone.com/gTv8Z4不幸的是,仍然存在多个字符分隔符或向后写入字符串的多个字符负号的问题。我将尝试解决下一个问题...
Jonathan Mee

@JonathanMee:我已经更新了代码(并至少添加了一些测试用例,包括负数)。
杰里·科芬

2

没有递归或字符串处理,一种数学方法:

#include <stdio.h>
#include <math.h>

void print_number( int n )
{
    int order_of_magnitude = (n == 0) ? 1 : (int)pow( 10, ((int)floor(log10(abs(n))) / 3) * 3 ) ;

    printf( "%d", n / order_of_magnitude ) ;

    for( n = abs( n ) % order_of_magnitude, order_of_magnitude /= 1000;
        order_of_magnitude > 0;
        n %= order_of_magnitude, order_of_magnitude /= 1000 )
    {
        printf( ",%03d", abs(n / order_of_magnitude) ) ;
    }
}

原则上与Pax的递归解决方案相似,但是通过预先计算数量级,可以避免递归(也许要付出相当大的代价)。

还请注意,用于分隔数千个字符的实际字符是特定于语言环境的。

编辑:请参见下面的@Chux注释以进行改进。


1
进行更改 abs(n)fabs(n)防止2的恭维错误print_number(INT_MIN)
chux-恢复莫妮卡

@chux:好点,但是在%表达式中,LHS会被强制转换回int,并且仍然会被破坏。这是简单的也许只是接受勉强较小范围的可接受输入或添加测试和输出“-2,147,483,647”直接INT_MIN(或任何INT_MIN是平台的问题上-这其中就有蠕虫的另一个即可。
克利福德

在提出建议之前,我确实成功进行了测试。嗯 我看到我的想法仅适用于log10(abs(n)),而不适用于其他任何地方。有趣的是,您的解决方案仅适用于log10(fabs(n))和,print_number(INT_MIN)因为printf(..., abs(n / order_of_magnitude))这意味着n = abs(INT_MIN) % order_of_magnitude否定是可以的。如果我们放弃INT_MIN,则printf(..., abs(n / order_of_magnitude))可以变为printf(..., n / order_of_magnitude)。但是我想使用称为“ abs(INT_MIN)”的蠕虫通常是一件坏事。
chux-恢复莫妮卡

新思路:建议3个更改log10(fabs(n))n = abs(n% order_of_magnitude)然后printf(",%03d", n/order_of_magnitude)。顺便说一句:除非我认为您的解决方案是好的,否则我不会花费精力。没有UB,即使是INT_MIN。
chux-恢复莫妮卡

2

基于@Greg Hewgill,但考虑到负数并返回字符串大小。

size_t str_format_int_grouped(char dst[16], int num)
{
    char src[16];
    char *p_src = src;
    char *p_dst = dst;

    const char separator = ',';
    int num_len, commas;

    num_len = sprintf(src, "%d", num);

    if (*p_src == '-') {
        *p_dst++ = *p_src++;
        num_len--;
    }

    for (commas = 2 - num_len % 3;
         *p_src;
         commas = (commas + 1) % 3)
    {
        *p_dst++ = *p_src++;
        if (commas == 1) {
            *p_dst++ = separator;
        }
    }
    *--p_dst = '\0';

    return (size_t)(p_dst - dst);
}

1

我的回答并不完全按照问题中的说明来格式化结果,但是在某些情况下可以使用简单的单行代码或宏来满足实际需求。可以根据需要扩展它以生成更多的千组。

结果如下所示:

Value: 0'000'012'345

编码:

printf("Value: %llu'%03lu'%03lu'%03lu\n", (value / 1000 / 1000 / 1000), (value / 1000 / 1000) % 1000, (value / 1000) % 1000, value % 1000);

'一个标准的符号相当于,(数学,至少)的某些部分(S)的世界呢?
ysap

1
@ysap在世界某些地方,它是一千个分隔符。
罗兰·皮拉卡斯

0

在C中没有真正简单的方法可以做到这一点。我只需要修改一个int-to-string函数即可:

void format_number(int n, char * out) {
    int i;
    int digit;
    int out_index = 0;

    for (i = n; i != 0; i /= 10) {
        digit = i % 10;

        if ((out_index + 1) % 4 == 0) {
            out[out_index++] = ',';
        }
        out[out_index++] = digit + '0';
    }
    out[out_index] = '\0';

    // then you reverse the out string as it was converted backwards (it's easier that way).
    // I'll let you figure that one out.
    strrev(out);
}

0

另一个迭代功能

int p(int n) {
  if(n < 0) {
    printf("-");
    n = -n;
  }

  int a[sizeof(int) * CHAR_BIT / 3] = { 0 };
  int *pa = a;
  while(n > 0) {
    *++pa = n % 1000;
    n /= 1000;
  }
  printf("%d", *pa);
  while(pa > a + 1) {
    printf(",%03d", *--pa);
  }
}

我对用于确定数组维数的表达式很感兴趣!有数学上的理由吗?
克利福德

每个小数位数的ld(10)位。向下舍入到3。我们可以再次除以3(以说明我们一次最多存储3位数字的事实)。但我想将其保持在上限。
Johannes Schaub-litb

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()
乔纳森·莱夫勒

@JonathanLeffler呵呵。感谢您的链接。
丹·贝查德

0

安全的format_commas,带有负数:

由于VS <2015没有实现snprintf,因此您需要执行此操作

#if defined(_WIN32)
    #define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
#endif

然后

char* format_commas(int n, char *out)
{
    int c;
    char buf[100];
    char *p;
    char* q = out; // Backup pointer for return...

    if (n < 0)
    {
        *out++ = '-';
        n = abs(n);
    }


    snprintf(buf, 100, "%d", n);
    c = 2 - strlen(buf) % 3;

    for (p = buf; *p != 0; p++) {
        *out++ = *p;
        if (c == 1) {
            *out++ = '\'';
        }
        c = (c + 1) % 3;
    }
    *--out = 0;

    return q;
}

用法示例:

size_t currentSize = getCurrentRSS();
size_t peakSize = getPeakRSS();


printf("Current size: %d\n", currentSize);
printf("Peak size: %d\n\n\n", peakSize);

char* szcurrentSize = (char*)malloc(100 * sizeof(char));
char* szpeakSize = (char*)malloc(100 * sizeof(char));

printf("Current size (f): %s\n", format_commas((int)currentSize, szcurrentSize));
printf("Peak size (f): %s\n", format_commas((int)currentSize, szpeakSize));

free(szcurrentSize);
free(szpeakSize);

0

@paxdiablo解决方案的修改版,但使用WCHARwsprinf

static WCHAR buffer[10];
static int pos = 0;

void printfcomma(const int &n) {
    if (n < 0) {
        wsprintf(buffer + pos, TEXT("-"));
        pos = lstrlen(buffer);
        printfcomma(-n);
        return;
    }
    if (n < 1000) {
        wsprintf(buffer + pos, TEXT("%d"), n);
        pos = lstrlen(buffer);
        return;
    }
    printfcomma(n / 1000);
    wsprintf(buffer + pos, TEXT(",%03d"), n % 1000);
    pos = lstrlen(buffer);
}

void my_sprintf(const int &n)
{
    pos = 0;
    printfcomma(n);
}

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
#include <stdio.h>

void punt(long long n){
    char s[28];
    int i = 27;
    if(n<0){n=-n; putchar('-');} 
    do{
        s[i--] = n%10 + '0';
        if(!(i%4) && n>9)s[i--]='.';
        n /= 10;
    }while(n);
    puts(&s[++i]);
}


int main(){
    punt(2134567890);
    punt(987);
    punt(9876);
    punt(-987);
    punt(-9876);
    punt(-654321);
    punt(0);
    punt(1000000000);
    punt(0x7FFFFFFFFFFFFFFF);
    punt(0x8000000000000001); // -max + 1 ...
}

我的解决方案使用。而不是,留给读者更改。


0

这很古老,有很多答案,但问题不是“我如何编写添加逗号的例程”,而是“如何用C语言完成”?这些评论指出了这个方向,但是在我的带有GCC的Linux系统上,这对我有用:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
    unsetenv("LC_ALL");
    setlocale(LC_NUMERIC, "");
    printf("%'lld\n", 3141592653589);
}

运行此命令后,我得到:

$ cc -g comma.c -o comma && ./comma
3,141,592,653,589

如果我LC_ALL在运行程序之前unsetenv未设置变量,则没有必要。


0

需要自己做类似的事情,而不是直接打印,而是需要进入缓冲区。这是我想出的。向后工作。

unsigned int IntegerToCommaString(char *String, unsigned long long Integer)
{
    unsigned int Digits = 0, Offset, Loop;
    unsigned long long Copy = Integer;

    do {
        Digits++;
        Copy /= 10;
    } while (Copy);

    Digits = Offset = ((Digits - 1) / 3) + Digits;
    String[Offset--] = '\0';

    Copy = Integer;
    Loop = 0;
    do {
        String[Offset] = '0' + (Copy % 10);
        if (!Offset--)
            break;
        if (Loop++ % 3 == 2)
            String[Offset--] = ',';
        Copy /= 10;
    } while (1);

    return Digits;
}

请注意,它仅适用于无符号整数,并且必须确保缓冲区足够大。


0

另一种解决方案是,将结果保存到int数组中,最大大小为7,因为该long long int类型可以处理9,223,372,036,854,775,807-9,223,372,036,854,775,807范围内的数字。(请注意,这不是一个无符号值)。

非递归打印功能

static void printNumber (int numbers[8], int loc, int negative)
{
    if (negative)
    {
        printf("-");
    }
    if (numbers[1]==-1)//one number
    {
        printf("%d ", numbers[0]);
    }
    else
    {
        printf("%d,", numbers[loc]);
        while(loc--)
        {
            if(loc==0)
            {// last number
                printf("%03d ", numbers[loc]);
                break;
            }
            else
            { // number in between
                printf("%03d,", numbers[loc]);
            }
        }
    }
}

主函数调用

static void getNumWcommas (long long int n, int numbers[8])
{
    int i;
    int negative=0;
    if (n < 0)
    {
        negative = 1;
        n = -n;
    }
    for(i = 0; i < 7; i++)
    {
        if (n < 1000)
        {
            numbers[i] = n;
            numbers[i+1] = -1;
            break;
        }
        numbers[i] = n%1000;
        n/=1000;
    }

    printNumber(numbers, i, negative);// non recursive print
}

测试输出

-9223372036854775807: -9,223,372,036,854,775,807
-1234567890         : -1,234,567,890
-123456             : -123,456
-12345              : -12,345
-1000               : -1,000
-999                : -999
-1                  : -1
0                   : 0
1                   : 1
999                 : 999
1000                : 1,000
12345               : 12,345
123456              : 123,456
1234567890          : 1,234,567,890
9223372036854775807 : 9,223,372,036,854,775,807

在main()函数中:

int numberSeparated[8];
long long int number = 1234567890LL;
getNumWcommas(number, numberSeparated);

如果只需要打印,则int numberSeparated[8];在函数内部移动getNumWcommas并以此方式进行调用getNumWcommas(number)


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

}

1
发布代码时至少应使用适当的缩进。也许还要添加一些关于现有答案还没有做什么的解释。
EWit 2014年

这具有简单性的优点,一目了然。
史蒂夫·纽曼

1
伪造的解决方案,打印一个额外的,下面的数字100,用途printf(),其中putchar()就飞,使用误导性名称,乱缩进和太多的代码。
chqrlie 2015年

-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包含格式化的字符串。最不严重的问题是,它使用空白而不是逗号作为千位分隔符。但是,它不能处理零的事实是杀手problem。
乔纳森·莱夫勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.