2016-03-29 2 views
4

Я новичок в C.Преобразование INT в строку в стандартном C

Я ищу пример, где я мог бы назвать функцию для преобразования int в строку. Я нашел itoa, но это не входит в стандарт C.

Я также нашел sprintf(str, "%d", aInt);, но проблема в том, что я не знаю размер требуемой строки. Следовательно, как я мог передать правильный размер для строки вывода

+2

Вы используете gcc? 'asprintf' - ваш друг, если да. – Dan

+1

Если 'aint' представляет собой 32-разрядную (подписанную или неподписанную) величину, то достаточно 12 символов (10 цифр, знак, завершающий нуль). Если это 64-разрядная подписанная величина, то достаточно 21 символа (19 цифр, знак, завершающий нуль); для беззнакового количества без знака 21 достаточно, но со знаком вам нужно 22. Обычный трюк состоит в том, чтобы выделить немного больше места, чем необходимо. Вы можете проверить возвращаемое значение из 'snprintf()' с нулевой строкой и нулевой длиной, чтобы найти, сколько места вам нужно. Вы можете посмотреть на 'asprintf()', как это было предложено, но оно довольно новое и по-прежнему имеет ограниченную переносимость. –

ответ

5

Существует оптимальный способ правильного размера массива для учета изменений в sizeof(int), но умножения на 4 достаточно для базы 10. +1 необходим для край корпус sizeof(int)==1.

int x; // assign a value to x 
char buffer[sizeof(int) * 4 + 1]; 
sprintf(buffer, "%d", x); 

Если вам необходимо вернуть указатель на строку из функции, вы должны выделить буфер вместо использования стека памяти:

char* integer_to_string(int x) 
{ 
    char* buffer = malloc(sizeof(char) * sizeof(int) * 4 + 1); 
    if (buffer) 
    { 
     sprintf(buffer, "%d", x); 
    } 
    return buffer; // caller is expected to invoke free() on this buffer to release memory 
} 
+0

Спасибо ... если я поставил вышеприведенный код внутри функции, что должна вернуть эта функция, char * или char []? – user836026

+2

@ user836026: вы не можете просто вернуть массив из функции. Вам нужно передать массив подходящего размера в функцию (проще всего), или вам нужно выполнить динамическое распределение памяти (с 'malloc()' и др. - что сложнее). Если вы передаете массив, также пропустите размер и используйте 'snprintf()' внутри функции для обеспечения безопасности. Если вы это сделаете, вы должны проверить ошибки переполнения - но тогда вы должны проверить большинство функций. –

+1

@ user836026 - То, что только что сказал Джонатан. Я обновил свой ответ, чтобы показать, как выделить массив с помощью malloc. – selbie

2

В портативном C, это простой в использовании snprintf для расчета размер требуемого массива, а затем sprintf для фактического преобразования. Например:

char buffer[snprintf(NULL, 0, "%d", x) + 1]; 
sprintf(buffer, "%d", x); 

Это стоит отметить, что это не будет работать до C99, и есть также аккуратнее альтернатива, которая работает до С99 и типа общих для всех целых. Это описано в another answer to this question using the multiplication trick, однако я заметил, что предложенный трюк не является строго переносимым. В средах, где CHAR_BIT не 8 (например, некоторые DSP используют 16- или 32-разрядные байты), вам нужно будет изменить множитель.

Я представил a similar trick in response to a different question. Этот код использовал CHAR_BIT, чтобы обеспечить переносимость, даже если CHAR_BIT изменяется. Он представлен как макрос, и поэтому он внутренне документирует; он говорит вам, что такое описание высокого уровня, которое само по себе не может сделать.

#include <limits.h> 
#include <stddef.h> 
#include <stdio.h> 

#define digit_count(num) (1        /* sign   */ \ 
         + sizeof (num) * CHAR_BIT/3  /* digits   */ \ 
         + (sizeof (num) * CHAR_BIT % 3 > 0)/* remaining digit */ \ 
         + 1)        /* NUL terminator */ 

int main(void) { 
    short short_number = -32767; 
    int int_number = 32767; 
    char short_buffer[digit_count(short_number)] = { 0 }; 
    char int_buffer[digit_count(int_number)]; 
    sprintf(short_buffer, "%d", short_number); 
    sprintf(int_buffer, "%d", int_number); 
} 
+0

+1 Для указания использования 'snprintf' для вычисления размера массива. Тем не менее, заслуживает упоминания, что такое поведение, по-видимому, не было определено как таковое до C99. From 'CONFORMING TO'' man snprintf': «SUSv2 и C99 противоречат друг другу: когда snprintf() вызывается с размером = 0, тогда SUSv2 оговаривает неопределенное возвращаемое значение меньше 1, тогда как C99 позволяет str быть NULL в этом случае , и дает возвращаемое значение (как всегда) как количество символов, которые были бы записаны в случае, если выходная строка была достаточно большой. " – Will

+0

@Will Правильно, вы, однако, просто tit nitpick, я бы предположил, поскольку SUS теперь определяет C, используя более современный стандарт, если не используются теги [SUSv2] или [C89], C - C99 или C11. Кроме того, VLA не будет работать на C89 ... Это может сделать хороший переход в часть, следующую за ним. Сейчас я отредактирую :) – Sebivor

+0

@Will Что вы думаете об этом ответе, сейчас? – Sebivor

1

C99 snprintf()10. Он вычисляет, сколько места потребуется

int needed = snprintf(NULL, 0, "%s", value); 
if (needed < 1) /* error */; 
char *representation = malloc(needed + 1); // add 1 for '\0' 
if (!representation) /* error */; 
sprintf(representation, "%d", value); 
// ... use representation ... 
free(representation); 
0

Существует способ сделать это без каких-либо функций, например, это (это может быть немного примитивно, но все же):

char dec_rev[255]; 
dec_rev[0] = '\0'; 
int i = 0; 

while (val != 0) { 
    int temp = val % 10; 
    dec_rev[i] = temp + '0'; 
    //printf("%c\n", dec_rev[i]); 
    val /= 10; 
    if (val == 0) { 
     dec_rev[i + 1] = '\0'; 
     break; 
    } 
    i++; 
} 

char dec[255]; 
i = 0; 
for (int j = strlen(dec_rev) - 1; j != -1; j--) { 
    dec[i] = dec_rev[j]; 
    i++; 
} 

В конце концов мы получаем наш int, хранящийся внутри dec [255].

0

странно, что это не упомянуто, но размер представления int в базе 10 равен ceil (log10 (value)); (Или log10 целое версия, если вы хотите написать его)

таким образом ceil(log10(5)) => 1

и ceil(log10(555)) => 3

ceil(log10(1000000000)) => 9 

очевидно вам нужно дополнительное место для знака, если вам это нужно, а другой для «\ 0' .

Смежные вопросы