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.
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.
Wenn Ihr printf die Option '
Flagge (wie von POSIX 2008 gefordert) printf()
), können Sie es wahrscheinlich einfach tun, indem Sie Ihr Gebietsschema entsprechend einstellen. Beispiel:
#include <stdio.h>
#include <locale.h>
int main(void)
{
setlocale(LC_NUMERIC, "");
printf("%'d\n", 1123456789);
return 0;
}
Und bauen und laufen lassen:
$ ./example
1,123,456,789
Getestet unter Mac OS X und Linux (Ubuntu 10.10).
Sie können dies wie folgt rekursiv tun (Vorsicht INT_MIN
wenn Sie das Zweierkomplement verwenden, benötigen Sie zusätzlichen Code, um dies zu verwalten):
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);
}
Ein Resümee:
printfcomma
mit einer ganzen Zahl wird der spezielle Fall negativer Zahlen behandelt, indem einfach "-" gedruckt und die Zahl positiv gemacht wird (das ist der Teil, der nicht mit INT_MIN
).printfcomma2
Eine Zahl unter 1.000 wird einfach gedruckt und zurückgegeben.Es gibt auch die knappere Version, die allerdings unnötige Verarbeitung bei der Prüfung auf negative Zahlen bei jede Ebene (nicht dass dies angesichts der begrenzten Anzahl von Rekursionsebenen eine Rolle spielen würde). Dies ist ein vollständiges Programm zum Testen:
#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;
}
und die Ausgabe ist:
-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
Eine iterative Lösung für diejenigen, die der Rekursion nicht trauen (obwohl das einzige Problem bei der Rekursion der Stapelplatz ist, der hier kein Problem darstellt, da er selbst bei einer 64-Bit-Ganzzahl nur ein paar Ebenen tief ist):
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);
}
}
Beide erzeugen 2,147,483,647
para INT_MAX
.
Der gesamte obige Code ist für durch Komma getrennte dreistellige Gruppen gedacht, aber Sie können auch andere Zeichen verwenden, z. B. ein Leerzeichen:
void printfspace2 (int n) {
if (n < 1000) {
printf ("%d", n);
return;
}
printfspace2 (n/1000);
printf (" %03d", n%1000);
}
void printfspace (int n) {
if (n < 0) {
printf ("-");
n = -n;
}
printfspace2 (n);
}
Hier ist eine sehr einfache Umsetzung. Diese Funktion enthält keine Fehlerprüfung, Puffergrößen müssen vom Aufrufer überprüft werden. Sie funktioniert auch nicht bei negativen Zahlen. Solche Verbesserungen bleiben dem Leser als Übung überlassen.
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;
}
Oh je! Ich tue dies die ganze Zeit, mit gcc/g++ und glibc auf Linux und ja, der ' Operator kann nicht standardisiert sein, aber ich mag die Einfachheit der es.
#include <stdio.h>
#include <locale.h>
int main()
{
int bignum=12345678;
setlocale(LC_ALL,"");
printf("Big number: %'d\n",bignum);
return 0;
}
Ergibt eine Ausgabe von:
Große Zahl: 12.345.678
Sie müssen sich nur an den Aufruf "setlocale" erinnern, sonst wird nichts formatiert.
Vielleicht wäre eine ortsabhängige Version interessant.
#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
Es gibt einen Fehler (den ich aber als relativ geringfügig ansehen würde). Auf Zweierkomplement-Hardware wird die negativste Zahl nicht korrekt konvertiert, weil versucht wird, eine negative Zahl in ihre äquivalente positive Zahl zu konvertieren mit N = -N;
Im Zweierkomplement hat die maximal negative Zahl keine entsprechende positive Zahl, es sei denn, man erhöht sie auf einen größeren Typ. Eine Möglichkeit, dies zu umgehen, besteht darin, die Zahl in den entsprechenden vorzeichenlosen Typ zu überführen (dies ist jedoch nicht ganz trivial).
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.