Как отформатировать число от 1123456789 до 1,123,456,789 в C? - PullRequest
66 голосов
/ 20 сентября 2009

Как я могу на языке C отформатировать число от 1123456789 до 1,123,456,789? Я пытался использовать printf("%'10d\n", 1123456789);, но это не работает.

Не могли бы вы что-нибудь посоветовать? Чем проще решение, тем лучше.

Ответы [ 19 ]

1 голос
/ 02 апреля 2017

Я новичок в программировании на Си. Вот мой простой код.

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;
}
1 голос
/ 28 октября 2015

Защищенные format_commas, с отрицательными числами:

Поскольку VS <2015 не поддерживает snprintf, вам нужно сделать это </p>

#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);
1 голос
/ 26 сентября 2013

Вот самая тонкая, эффективная по размеру и скорости реализация этого вида форматирования десятичных цифр:

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, что ужасно медленно и всегда зависит от контекста.

  • Минимальное количество операторов деления (/,%).
0 голосов
/ 02 мая 2017
#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 голосов
/ 21 февраля 2016

модифицированная версия решения @paxdiablo, но с использованием WCHAR и wsprinf:

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 голосов
/ 20 сентября 2009

Нет реального простого способа сделать это в 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 голосов
/ 12 июля 2014
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(",");
           }

}
0 голосов
/ 28 февраля 2014
        // 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';
        }
0 голосов
/ 20 сентября 2009

Можно сделать довольно легко ...

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