Regroupement de chiffres dans le printf de C

Je souhaite produire de grands nombres avec des milliers de séparateurs (virgules ou espaces) – essentiellement les mêmes que dans Comment afficher numérique en regroupement à 3 chiffres mais en utilisant printf en C (GNU, 99).

Si printf ne prend pas en charge le regroupement de chiffres de manière native, comment puis-je y parvenir avec quelque chose comme printf("%s", group_digits(number)) ?

Il doit supporter les entiers négatifs et de préférence les flottants.

Si vous pouvez utiliser POSIX printf , essayez

 #include  setlocale(LC_ALL, ""); /* use user selected locale */ printf("%'d", 1000000); 

Voici un moyen compact de le faire:

 // format 1234567.89 -> 1 234 567.89 extern char *strmoney(double value){ static char result[64]; char *result_p = result; char separator = ' '; size_t tail; snprintf(result, sizeof(result), "%.2f", value); while(*result_p != 0 && *result_p != '.') result_p++; tail = result + sizeof(result) - result_p; while(result_p - result > 3){ result_p -= 3; memmove(result_p + 1, result_p, tail); *result_p = separator; tail += 4; } return result; } 

Par exemple, un appel à strmoney(1234567891.4568) renvoie la chaîne "1 234 567 891.46" . Vous pouvez facilement remplacer l’espace par un autre séparateur (une virgule, par exemple) en modifiant la variable de separator en haut de la fonction.

Un moyen sécurisé de formater des milliers de séparateurs, avec prise en charge des nombres négatifs:

Parce que VS <2015 n'implémente pas snprintf, vous devez le faire.

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

Et alors

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

Exemple d'utilisation:

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

Ma propre version pour non signé int64:

 char* toSsortingng_DigitGrouping( unsigned __int64 val ) { static char result[ 128 ]; _snprintf(result, sizeof(result), "%lld", val); size_t i = strlen(result) - 1; size_t i2 = i + (i / 3); int c = 0; result[i2 + 1] = 0; for( ; i != 0; i-- ) { result[i2--] = result[i]; c++; if( c % 3 == 0 ) result[i2--] = '\''; } //for return result; } //toSsortingng_DigitGrouping 
 #include  #include  #include  #include  char *commify(char *numstr){ char *wk, *wks, *p, *ret=numstr; int i; wks=wk=strrev(strdup(numstr)); p = strchr(wk, '.'); if(p){//include '.' while(wk != p)//skip until '.' *numstr++ = *wk++; *numstr++=*wk++; } for(i=1;*wk;++i){ if(isdigit(*wk)){ *numstr++=*wk++; if(isdigit(*wk) && i % 3 == 0) *numstr++ = ','; } else { break; } } while(*numstr++=*wk++); free(wks); return strrev(ret); } int main(){ char buff[64];//To provide a sufficient size after conversion. sprintf(buff, "%d", 100); printf("%s\n", commify(buff)); sprintf(buff, "%d", 123456); printf("%s\n", commify(buff)); sprintf(buff, "%.2f", 1234.56f); printf("%s\n", commify(buff)); sprintf(buff, "%d", -123456); printf("%s\n", commify(buff)); sprintf(buff, "%.2lf", -12345678.99); printf("%s\n", commify(buff)); return 0; } 

AJOUTER:

 /* char *strrev(char *str){ char c,*front,*back; for(front=str,back=str+strlen(str)-1;front < back;front++,back--){ c=*front;*front=*back;*back=c; } return(str); } */