104 Stimmen

Wie formatiert man eine Zahl von 1123456789 bis 1.123.456.789 in C?

Wie kann ich in der Sprache C eine Zahl von 1123456789 a 1,123,456,789 ? Ich habe versucht, mit printf("%'10d\n", 1123456789); aber das funktioniert nicht.

Können Sie etwas empfehlen? Je einfacher die Lösung ist, desto besser.

2voto

ideasman42 Punkte 35167

Basiert auf @Greg Hewgill's, berücksichtigt aber negative Zahlen und gibt die Stringgröße zurück.

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);
}

2voto

Kranka Punkte 21

Ich musste selbst etwas Ähnliches machen, aber anstatt direkt zu drucken, musste ich in einen Puffer gehen. Hier ist, was ich kam mit. Funktioniert rückwärts.

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

Beachten Sie, dass es nur für vorzeichenlose Ganzzahlen ausgelegt ist und Sie sicherstellen müssen, dass der Puffer groß genug ist.

2voto

aah134 Punkte 810

Eine andere Lösung ist die Speicherung des Ergebnisses in einer int Array, maximale Größe von 7, da die long long int Typ kann Zahlen im Bereich von 9,223,372,036,854,775,807 a -9,223,372,036,854,775,807 . (Beachten Sie, dass es sich nicht um einen Wert ohne Vorzeichen handelt).

Nicht-rekursive Druckfunktion

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]);
            }
        }
    }
}

Aufruf der Hauptfunktion

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
}

Prüfleistung

-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

In der Funktion main():

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

Wenn Drucken alles ist, was benötigt wird, dann verschieben Sie int numberSeparated[8]; innerhalb der Funktion getNumWcommas und nennen Sie es folgendermaßen getNumWcommas(number) .

2voto

Clifford Punkte 82130

Ohne Rekursion oder String-Handling, ein mathematischer Ansatz:

#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) ) ;
    }
}

Im Prinzip ähnlich wie die rekursive Lösung von Pax, aber durch die Berechnung der Größenordnung im Voraus wird die Rekursion vermieden (vielleicht mit erheblichem Aufwand).

Beachten Sie auch, dass das tatsächliche Zeichen, das zur Trennung von Tausendern verwendet wird, vom jeweiligen Gebietsschema abhängt.

bearbeiten Siehe die Kommentare von @Chux unten für Verbesserungen.

1voto

user1683793 Punkte 1155

Diese Frage ist alt und es gibt viele Antworten, aber die Frage war nicht "wie kann ich eine Routine schreiben, um Kommas hinzuzufügen", sondern "wie kann das in C gemacht werden"? Die Kommentare wiesen in diese Richtung, aber auf meinem Linux-System mit GCC funktioniert das bei mir:

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

Wenn dies ausgeführt wird, erhalte ich:

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

Wenn ich die Option LC_ALL vor der Ausführung des Programms die Variable unsetenv ist nicht erforderlich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X