我希望输出带有千位分隔符(逗号或空格)的大数——与如何在 3 位分组中显示数字但printf
在 C 中使用(GNU,99)中的基本相同。
如果 printf 本身不支持数字分组,我该如何使用类似的东西来实现这一点printf("%s", group_digits(number))
?
它必须支持负整数,最好也支持浮点数。
我希望输出带有千位分隔符(逗号或空格)的大数——与如何在 3 位分组中显示数字但printf
在 C 中使用(GNU,99)中的基本相同。
如果 printf 本身不支持数字分组,我该如何使用类似的东西来实现这一点printf("%s", group_digits(number))
?
它必须支持负整数,最好也支持浮点数。
如果您可以使用POSIX printf,请尝试
#include <locale.h>
setlocale(LC_ALL, ""); /* use user selected locale */
printf("%'d", 1000000);
这是一种紧凑的方法:
// 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;
}
例如,调用strmoney(1234567891.4568)
返回字符串"1 234 567 891.46"
。separator
通过更改函数顶部的变量,您可以轻松地将空格替换为另一个分隔符(例如逗号) 。
一种格式化千位分隔符的安全方法,支持负数:
因为VS < 2015没有实现snprintf,所以需要这样做
#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);
我自己的 unsigned int64 版本:
char* toString_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;
} //toString_DigitGrouping
#include <stdio.h>
int main() {
char str[50];
int len = 0;
scanf("%48[^\n]%n", str, &len);
int start = len % 3;
for(int i = 0; i < len; i++) {
if(i == start && i != 0) {
printf(" ");
} else if((i - start) % 3 == 0 && i != 0) {
printf(" ");
}
printf("%c", str[i]);
}
return 0;
}
#include <stdio.h>
void punt(int 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(){
int a;
scanf("%d",&a);
punt(a);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
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;
}
添加:
/*
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);
}
*/