Как может, я на языке C форматирую число от 1123456789
кому: 1,123,456,789
? Я пытался использовать printf("%'10d\n", 1123456789);
но это не работает.
Вы могли советовать чему-нибудь? Чем более простой решение, тем лучше.
Это довольно легко сделать ...
//Make sure output buffer is big enough and that input is a valid null terminated string
void pretty_number(const char* input, char * output)
{
int iInputLen = strlen(input);
int iOutputBufferPos = 0;
for(int i = 0; i < iInputLen; i++)
{
if((iInputLen-i) % 3 == 0 && i != 0)
{
output[iOutputBufferPos++] = ',';
}
output[iOutputBufferPos++] = input[i];
}
output[iOutputBufferPos] = '\0';
}
Пример вызова:
char szBuffer[512];
pretty_number("1234567", szBuffer);
//strcmp(szBuffer, "1,234,567") == 0
Другая итерационная функция
int p(int n) {
if(n < 0) {
printf("-");
n = -n;
}
int a[sizeof(int) * CHAR_BIT / 3] = { 0 };
int *pa = a;
while(n > 0) {
*++pa = n % 1000;
n /= 1000;
}
printf("%d", *pa);
while(pa > a + 1) {
printf(",%03d", *--pa);
}
}
Математический подход без рекурсии или обработки строк:
#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) ) ;
}
}
В принципе аналогичен рекурсивному решению Пакса, но при предварительном расчете порядка величины рекурсия избегается (возможно, за счет значительных затрат).
Обратите внимание также, что фактический символ, используемый для разделения тысяч, зависит от локали.
Изменить : См. комментарии @ Chux ниже для улучшения.
Вот очень простая реализация. Эта функция не содержит проверки ошибок , размеры буфера должны быть проверены вызывающей стороной. Это также не работает для отрицательных чисел. Такие улучшения оставлены в качестве упражнения для читателя.
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;
}
Это будет полностью зависеть от того, в каком домене вы работаете. Для некоторых это будут номера телефонов и SSN, а для других - адреса электронной почты, IP-адреса, URL-адреса. Самое важное - знать, когда вам нужно регулярное выражение, а когда нет. Например, если вы пытаетесь проанализировать данные из файла XML или HTML, обычно лучше использовать библиотеку, специально разработанную для анализа этого содержимого, чем пытаться написать что-нибудь самостоятельно.
Существует также более сжатая версия, хотя она выполняет ненужную обработку при проверке отрицательного числа на на каждом уровне (не то чтобы это будет иметь значение, учитывая ограниченное количество уровней рекурсии). Это полная программа для тестирования:
#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;
}
, а результат:
-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
Итерационное решение для тех, кто не доверяет рекурсии (хотя единственная проблема с рекурсией, как правило, связана с пространством стека, которое здесь не будет проблемой поскольку это будет только несколько уровней глубины даже для 64-битного целого числа):
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);
}
}
Оба они генерируют 2 147 483 647
для INT_MAX
.
Существует также более сжатая версия, хотя она выполняет ненужную обработку при проверке отрицательных чисел на на каждом уровне (не то чтобы это имеет значение, учитывая ограниченное число уровней рекурсии). Это полная программа для тестирования:
#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;
}
, а результат:
-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
Итерационное решение для тех, кто не доверяет рекурсии (хотя единственная проблема с рекурсией, как правило, связана с пространством стека, которое здесь не будет проблемой поскольку это будет только несколько уровней глубины даже для 64-битного целого числа):
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);
}
}
Оба они генерируют 2 147 483 647
для INT_MAX
.
Существует также более сжатая версия, хотя она выполняет ненужную обработку при проверке отрицательных чисел на на каждом уровне (не то чтобы это имеет значение, учитывая ограниченное число уровней рекурсии). Это полная программа для тестирования:
#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;
}
, а результат:
-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
Итерационное решение для тех, кто не доверяет рекурсии (хотя единственная проблема с рекурсией, как правило, связана с пространством стека, которое здесь не будет проблемой поскольку это будет только несколько уровней глубины даже для 64-битного целого числа):
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);
}
}
Оба они генерируют 2 147 483 647
для INT_MAX
.
Существует также более сжатая версия, хотя она выполняет ненужную обработку при проверке отрицательных чисел на на каждом уровне (не то чтобы это будет иметь значение, учитывая ограниченное количество уровней рекурсии). Это полная программа для тестирования:
#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;
}
, а результат:
-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
Итеративное решение для тех, кто не доверяет рекурсии (хотя единственная проблема с рекурсией, как правило, связана с пространством стека, которое здесь не будет проблемой поскольку это будет только несколько уровней глубины даже для 64-битного целого числа):
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);
}
}
Оба они генерируют 2 147 483 647
для INT_MAX
.
Существует также более сжатая версия, хотя она выполняет ненужную обработку при проверке отрицательных чисел на на каждом уровне (не то чтобы это будет иметь значение, учитывая ограниченное количество уровней рекурсии). Это полная программа для тестирования:
#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;
}
, а результат:
-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
Итеративное решение для тех, кто не доверяет рекурсии (хотя единственная проблема с рекурсией, как правило, связана с пространством стека, которое здесь не будет проблемой поскольку это будет только несколько уровней глубины даже для 64-битного целого числа):
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);
}
}
Оба они генерируют 2 147 483 647
для INT_MAX
.
В языке C нет простого способа сделать это. Я бы просто изменил для этого функцию преобразования int в строку:
void format_number(int n, char * out) {
int i;
int digit;
int out_index = 0;
for (i = n; i != 0; i /= 10) {
digit = i % 10;
if ((out_index + 1) % 4 == 0) {
out[out_index++] = ',';
}
out[out_index++] = digit + '0';
}
out[out_index] = '\0';
// then you reverse the out string as it was converted backwards (it's easier that way).
// I'll let you figure that one out.
strrev(out);
}