Zahlen unterteilungs Punkte
-
Moin Moin,
Wie kann ich wen ich mit printf einen int Wert ausgebe, zur besseren lesbarkeit großer Zahlen, unterteilungs Punkte setzen lassen?
Also das z.B nicht 105538654 sondern 105.538.654 angezeigt wird.
-
Also theoretisch kannst du eine entsprechende locale setzen. Die muss dann aber auf dem System installiert sein. Die einzige Standardlocale "C" hat jedenfalls keine Zifferngruppierung. Und wenn ich mal die Locales auf meinem Computer angucke, hat auch keine davon Zifferngruppierung.
Wenn das Programm also unbedingt diese Gruppierung haben muss und du dem Nutzer diese Entscheidung nicht selber überlassen möchtest, dann musst du es wohl auf die harte Tour machen und das selber programmieren. Sollte mathematisch nicht zu schwer sein. Muss halt durch 10^9, 10^6 und 10^3 teilen um zu sehen, was die Milliarden, Millionen und die Tausenderstelle sind.
-
Der C Standard bietet hierfür nichts an, aber POSIX mit dem Apostroph im Formatspezifizierer:
#ifndef _POSIX_SOURCE #error nix da #endif int main() { setlocale(LC_ALL,""); printf("%'d",INT_MAX); return 0; }
Wenn du dort Kommas erhälst aber Punkte haben willst, wird es noch mehr plattformabhängig, du kannst verschiedene dort verfügbare locales ausprobieren, "German", "german", "deutsch", ...
-
Wutz schrieb:
Wenn du dort Kommas erhälst aber Punkte haben willst, wird es noch mehr plattformabhängig, du kannst verschiedene dort verfügbare locales ausprobieren, "German", "german", "deutsch", ...
Ich denke, in dem Fall ist es eigentlich eine recht gute Idee, so wie du es vormachst, die Entscheidung darüber bei der Systemlocale "" zu lassen.
-
Danke für die Hilfe,
hab es hinbekommen hier die fertige Funktion
void punkte_setzen( int a ) { int t = 0; int tr = a % 1000; int mr = a % 1000000 / 1000; int cr = a % 1000000000 / 1000000; if ( a >= 1000 && a <= 999999 ) { t = a / 1000; printf( "%d.%03d\n", t, tr ); } if ( a >= 1000000 && a <= 999999999 ) { t = a / 1000000; printf( "%d.%03d.%03d\n", t, mr, tr ); } if ( a >= 1000000000 && a <= 4000000000 ) { t = a / 1000000000; printf( "%d.%03d.%03d.%03d\n", t, cr, mr, tr ); } }
da ich noch Anfäner bin würde ich mich über verbesserungs Vorschläge freuen.
-
Wird bei Dir 105538007 als 105.538.7 angezeigt?
-
Vielleicht ist das eine weitere Überlegung wert. Nicht, weil es besser wäre, sondern weil es durch die Rekursion so hübsch kompliziert ist.
#include <stdio.h> void punkte_setzen(int a) { int vorne=a/1000;//vorne nenne ich die Ziffern vor dem letzten Tausenderpunkt int hinten=a%1000;//und hinten nenne ich die letzten drei Ziffern if(vorne==0)//wenn vorne nichts ist, dann { printf("%d",hinten);//normal ausgeben } else//aber wenn vorne doch etwas ist, dann { punkte_setzen(vorne);//erst vorne ausgeben, und zwar ganz normal, mit ebendieser Funktion punkte_setzen() printf(".%03d",a%1000);//und dann den punkt und mit durch 0 auf drei Stellen aufgefüllt hinten } } int main() { punkte_setzen(15538007); return 0; }
-
Hab den Fehler mit den 0 Stellen behoben. Danke war mir garnicht aufgefallen.
-
void punkte_setzen(int a) { int vorne=a/1000;//vorne nenne ich die Ziffern vor dem letzten Tausenderpunkt int hinten=a%1000;//und hinten nenne ich die letzten drei Ziffern if(vorne==0)//wenn vorne nichts ist, dann { printf("%d",hinten);//normal ausgeben } else//aber wenn vorne doch etwas ist, dann { punkte_setzen(vorne);//erst vorne ausgeben, und zwar ganz normal, mit ebendieser Funktion punkte_setzen() printf(".%03d",a%1000);//und dann den punkt und mit durch 0 auf drei Stellen aufgefüllt hinten } }
Warum hinten=a%1000, wenn vorne 0 wäre?
Warum im else bei printf a%1000, wenn du doch schon in "hinten" ausgerechnet hast?void punkte_setzen(int a) { int vorne=a/1000;//vorne nenne ich die Ziffern vor dem letzten Tausenderpunkt int hinten;//und hinten nenne ich die letzten drei Ziffern if(vorne==0)//wenn vorne nichts ist, dann { printf("%d",a);//normal ausgeben } else//aber wenn vorne doch etwas ist, dann { hinten=a%1000; punkte_setzen(vorne);//erst vorne ausgeben, und zwar ganz normal, mit ebendieser Funktion punkte_setzen() printf(".%03d",hinten);//und dann den punkt und mit durch 0 auf drei Stellen aufgefüllt hinten } }
Oder lass ich mich gerade durch die Rekursion verwirren?
-
DaRe schrieb:
Warum im else bei printf a%1000, wenn du doch schon in "hinten" ausgerechnet hast?
Schussligkeit. Natürlich will ich hinten auch benutzen, wenn ich es schon ausgerechnet habe.
-
DaRe schrieb:
Warum hinten=a%1000, wenn vorne 0 wäre?
Die beiden Variablen hatte ich nur ausgelagert, um bessere Kommentare schreiben zu können.
Vielleicht sollte man auf a<1000 testen.
-
Shinigami schrieb:
Moin Moin,
Wie kann ich wen ich mit printf einen int Wert ausgebe, zur besseren lesbarkeit großer Zahlen, unterteilungs Punkte setzen lassen?
Also das z.B nicht 105538654 sondern 105.538.654 angezeigt wird.
Vor einiger Zeit hatte ich ein ähnliches Problem. Vielleich hilfts ja:
#include <stdio.h> #include<string.h> #include<stdlib.h> #include <ctype.h> int num_to_pic (char * dest, char * source, char * pic, int length) { int i,j,k,s_flag=0,z_flag; j = length-1; memset(dest, ' ', (size_t) length); // clear Destination field // First pass initilizes the zero digits and decimalpont z_flag = 0; for (i = j;i >= 0;i--) { if (pic[i] == 'Z') { dest[i] = '0'; // Initialize dest with zero if "Z" is defined if (z_flag == 0) z_flag = -1; } else { if (pic[i] != '#' && pic[i] != 'c' && pic[i] != 'd') { if (z_flag == -1) // First zero pic alrady found? { dest[i] = pic[i]; // decimalpoint or -comma z_flag = 1; // Flag comma now set } } } } // Second pass completes the string for (i = j;i >= 0;i--) { if (isdigit(source[i])) // Numeric field { if ((pic[j] == '#') || (pic[j] == 'Z')) // Pic numeric? { dest[j] = source[i]; // copy digit j--; } else { if (pic[j] == 'd' || pic[j] == 'c') // Debitor, creditor? { s_flag = -1; // yes --> numeric value without sign j--; if ((pic[j] == '#') || (pic[j] == 'Z')) // next entry numeric pic? { dest[j] = source[i]; // yes --> copy digit j--; } else { return 1; // No --> Invalid Picture String } } else { dest[j] = pic[j]; // copy Pic j--; if ((pic[j] == '#') || (pic[j] == 'Z')) // next entry numeric pic? { dest[j] = source[i]; // yes --> copy digit j--; } else { return 1; // No --> Invalid Picture String } } } } else { if ((source[i] == '+' || source[i] == '-') && (s_flag == 0)) //overread all except + and - { for (k=j; k >= 0; k--) // Search the first free place for the sign { if (dest[k] == ' ') { dest[k] = source[i]; break; } } } } } return 0; }
Das ganze funktioniert ganz einfach. Man definiert einen Formatierunsstring mit den Werten "#,Z,-,+,',',.". Also auch der Dezimalpunkt/Komma, das Vorzeichen und das Tausenderkennzeichen werden berücksichtigt.
Hier ein Beispiielaufruf:#include <stdio.h> #include<string.h> #include<stdlib.h> #include <ctype.h> extern int num_to_pic (char*a,char*b,char*c,int i); int main() { char ergebnis[15]; //Source char ergebnisdb[15]; // Destination char ergebnispic[15]="####.###.###,##"; // Picture int i=15, // length of decleration ret; // signed long int zahl; char testdisplay[21]; // zahl = -1234567890; sprintf (ergebnis,"%+li",zahl); // ergibt source[15]="-1234567890 " printf("%s\n",ergebnis); // Test purpose // ret = num_to_pic (ergebnisdb, ergebnis, ergebnispic, i); if (ret != 0) printf("Invalid Picturestring\nCode: %i\n",ret); // strncpy(testdisplay,ergebnisdb,(size_t) i); // Result " -12.345.678,90" testdisplay[i] = 0; // "\0" // printf("%s\n",testdisplay); // Test purpose return 0; }
Aus dem Formatierungsstring "####.###.###,##" und dem Wert "-1234567890" wird "-12.345.678,90".
Mit dem "Z" Wert kann man "0" erzwingen z.B. "0,01". Also: aus "1" wird mit dem Formatierungsstring "#.##Z,ZZ" "0,01".
Auch kann man bei negativen Werten das Vorzeichen unterdrücken (etwa für ein Bilanzkonto), indem man ein "d" oder "c" rechts an den Formatierungsstring anfügt. Aus "-1" und dem Formatierungsstring "Z,ZZd" wird dann ebenfalls "0,01"
ohne "d" wäre es "-0,01".
Ich hoffe, dass die Profis hier nicht mühsam lächeln, es war eine meiner ersten Funktionen in C...
Ach ja ... auf das Längenfeld könnte man verzichten - ich weiss (es soll aber auch Strings ohne "\0" unterstützen). Und wie man eine externe Funktion einbindet, sollte eigentlich jeder hier wissen.