Вы также можете захотеть увидеть этот FAQ по сериализации и, возможно, следующие вопросы, которые относятся к сериализации в C: (a) , (b) , (c) для достижения ваших реальных целей.
moooeeeep
2
Мой обычный питомец семантическая мозоль здесь. Вы не хотите ничего конвертировать; Вы хотите получить строку, содержащую (основание 10?) представление значения int. Да, я знаю. Это очень распространенный вариант, но он все еще меня беспокоит.
РЕДАКТИРОВАТЬ: Как указано в комментарии, itoa()это не стандарт, поэтому лучше использовать подход sprintf (), предложенный в ответе соперника!
Вы можете использовать itoa()функцию для преобразования вашего целочисленного значения в строку.
Вот пример:
int num =321;char snum[5];// convert 123 to string [buf]
itoa(num, snum,10);// print our string
printf("%s\n", snum);
Если вы хотите вывести свою структуру в файл, нет необходимости предварительно преобразовывать какое-либо значение. Вы можете просто использовать спецификацию формата printf, чтобы указать, как выводить ваши значения, и использовать любой из операторов семейства printf для вывода ваших данных.
Чтобы быть уверенным, что тата ENOUGHдостаточно, мы можем сделать этоmalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@ Хаулет Или даже +2, учитывая, что (int)log10(42)это так 1.
Кристиан Рау
23
Или вы можете рассчитать его во время компиляции:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
caf
4
@hauleth Все равно +2 вместо +1, даже с ceil: ceil (log (100)) = 2.0, а не 3. Так что +1 для точных степеней-10, и еще +1 для завершения нуля.
не только йети
24
Вы не учитываете знак минуса и локаль: разделитель тысяч и группировка. Пожалуйста, сделайте это следующим образом: используйте int length = snprintf(NULL, 0,"%d",42);для получения длины, а затем выделите length+1символы для строки.
user2622016
70
Краткий ответ:
snprintf( str, size,"%d", x );
Чем дольше: для начала нужно выяснить достаточный размер. snprintfговорит вам длину, если вы называете это в NULL, 0качестве первых параметров:
snprintf( NULL,0,"%d", x );
Выделите еще один символ для нулевого терминатора.
#include<stdio.h>#include<stdlib.h>int x =-42;int length = snprintf( NULL,0,"%d", x );char* str = malloc( length +1);
snprintf( str, length +1,"%d", x );...
free(str);
Если работает для каждой строки формата, поэтому вы можете конвертировать число с плавающей запятой или двойное в строку с помощью "%g", вы можете преобразовать int в шестнадцатеричное с помощью "%x", и так далее.
@ user1821961 Спасибо, нужно отметить, что эти файлы заголовков должны быть включены.
byxor
Я люблю этот, будучи самым надежным и «по книге».
Мотти Шнеор
30
Изучив различные версии itoa для gcc, я обнаружил, что самая гибкая версия, способная обрабатывать преобразования в двоичные, десятичные и шестнадцатеричные, как положительные, так и отрицательные, - четвертая версия, найденная на http://www.strudel.org. .uk / itoa / . Хотя sprintf/ snprintfимеют преимущества, они не будут обрабатывать отрицательные числа ни для чего, кроме десятичного преобразования. Так как ссылка выше отключена или больше не активна, я включил их 4-ю версию ниже:
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/char* itoa(int value,char* result,int base){// check that the base if validif(base <2|| base >36){*result ='\0';return result;}char* ptr = result,*ptr1 = result, tmp_char;int tmp_value;do{
tmp_value = value;
value /= base;*ptr++="zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35+(tmp_value - value * base)];}while( value );// Apply negative signif(tmp_value <0)*ptr++='-';*ptr--='\0';while(ptr1 < ptr){
tmp_char =*ptr;*ptr--=*ptr1;*ptr1++= tmp_char;}return result;}
Кроме того, это значительно быстрее, чем sprintf. Может быть важно при выгрузке больших файлов.
Евгений Рябцев
@Eugene Ryabtsev C не указывает рейтинг производительности, sprintf()и «это значительно быстрее, чем sprintf» может быть верно для вашего компилятора, но не всегда верно. Компилятор может изучить sprintf(str, "%d", 42);и оптимизировать его для оптимизированной itoa()подобной функции - конечно, быстрее, чем этот пользователь. код.
Chux - Восстановить Монику
3
@chux Да, компилятор может оптимизировать sprintf(str, "%d", 42);как добавление двух константных символов, но это теория. На практике люди не разбираются в константных значениях, и вышеупомянутая itoa почти настолько же оптимизирована, насколько это возможно. По крайней мере, вы можете быть на 100% уверены, что не получите понижения порядка общего спринта. Было бы неплохо увидеть любой контрпример, который вы имеете в виду, с версией компилятора и настройками.
Евгений Рябцев
1
@chux Если он заканчивается вызовом, он ничего не объясняет, если мы не сравним вызываемую процедуру с приведенной выше процедурой (вплоть до того, что вызовов больше не будет; в сборке, если хотите). Если вы сделаете это в качестве ответа с версией и настройками компилятора, я опишу это как полезное.
Преобразование чего-либо в строку должно либо 1) выделить результирующую строку, либо 2) передать в char * адресат и размер. Пример кода ниже:
Оба работают для всех в intтом числе INT_MIN. Они обеспечивают последовательный выход в отличие отsnprintf() которого зависит от текущей локали.
Способ 1: возвращает нехватку NULLпамяти.
#define INT_DECIMAL_STRING_SIZE(int_type)((CHAR_BIT*sizeof(int_type)-1)*10/33+3)char*int_to_string_alloc(int x){int i = x;char buf[INT_DECIMAL_STRING_SIZE(int)];char*p =&buf[sizeof buf -1];*p ='\0';if(i >=0){
i =-i;}do{
p--;*p =(char)('0'- i %10);
i /=10;}while(i);if(x <0){
p--;*p ='-';}size_t len =(size_t)(&buf[sizeof buf]- p);char*s = malloc(len);if(s){
memcpy(s, p, len);}return s;}
Способ 2: возвращается, NULLесли буфер был слишком маленьким.
staticchar*int_to_string_helper(char*dest,size_t n,int x){if(n ==0){return NULL;}if(x <=-10){
dest = int_to_string_helper(dest, n -1, x /10);if(dest == NULL)return NULL;}*dest =(char)('0'- x %10);return dest +1;}char*int_to_string(char*dest,size_t n,int x){char*p = dest;if(n ==0){return NULL;}
n--;if(x <0){if(n ==0)return NULL;
n--;*p++='-';}else{
x =-x;}
p = int_to_string_helper(p, n, x);if(p == NULL)return NULL;*p =0;return dest;}
[Редактировать] как запрос @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3это как минимум максимальное количество, charнеобходимое для кодирования некоторого целого типа со знаком в виде строки, состоящей из необязательного отрицательного знака, цифр и нулевого символа.
Количество не знаковых битов в знаковое целое число не более чем CHAR_BIT*sizeof(int_type)-1. Основное-10 представление n-битного двоичного числа занимает до n*log10(2) + 1цифр. 10/33чуть больше чем log10(2). +1 для знака charи +1 для нулевого символа. Другие фракции могут быть использованы как 28/93.
Метод 3: Если кто-то хочет жить на грани, и переполнение буфера не является проблемой, следует простое решение C99 или более поздней версии, которое обрабатывает всеint .
@CiroSantilli 法轮功 改造 中心 g 事件 法轮功 Я не знаком с внутренней реализацией glibc.
chux - Восстановить Монику
3
/*Function return size of string and convert signed *
*integer to ascii value and store them in array of *
*character with NULL at the end of the array */int itoa(int value,char*ptr){int count=0,temp;if(ptr==NULL)return0;if(value==0){*ptr='0';return1;}if(value<0){
value*=(-1);*ptr++='-';
count++;}for(temp=value;temp>0;temp/=10,ptr++);*ptr='\0';for(temp=value;temp>0;temp/=10){*--ptr=temp%10+'0';
count++;}return count;}
Если вы хотите вывести свою структуру в файл, нет необходимости предварительно преобразовывать какое-либо значение. Вы можете просто использовать спецификацию формата printf, чтобы указать, как выводить ваши значения, и использовать любой из операторов семейства printf для вывода ваших данных.
printf
или один из его двоюродных братьев должен сделать трюкint
. Да, я знаю. Это очень распространенный вариант, но он все еще меня беспокоит.Ответы:
РЕДАКТИРОВАТЬ: Как указано в комментарии,
itoa()
это не стандарт, поэтому лучше использовать подход sprintf (), предложенный в ответе соперника!Вы можете использовать
itoa()
функцию для преобразования вашего целочисленного значения в строку.Вот пример:
Если вы хотите вывести свою структуру в файл, нет необходимости предварительно преобразовывать какое-либо значение. Вы можете просто использовать спецификацию формата printf, чтобы указать, как выводить ваши значения, и использовать любой из операторов семейства printf для вывода ваших данных.
источник
itoa
не является стандартным - см., например, stackoverflow.com/questions/190229/…itoa()
имеет тот же потенциал переполнения буфера, что иgets()
.Вы можете использовать
sprintf
для этого, или, может быть,snprintf
если у вас есть:Где количество символов (плюс завершающий символ) в
str
может быть рассчитано с помощью:источник
ENOUGH
достаточно, мы можем сделать этоmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
это так1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
для получения длины, а затем выделитеlength+1
символы для строки.Краткий ответ:
Чем дольше: для начала нужно выяснить достаточный размер.
snprintf
говорит вам длину, если вы называете это вNULL, 0
качестве первых параметров:Выделите еще один символ для нулевого терминатора.
Если работает для каждой строки формата, поэтому вы можете конвертировать число с плавающей запятой или двойное в строку с помощью
"%g"
, вы можете преобразовать int в шестнадцатеричное с помощью"%x"
, и так далее.источник
Изучив различные версии itoa для gcc, я обнаружил, что самая гибкая версия, способная обрабатывать преобразования в двоичные, десятичные и шестнадцатеричные, как положительные, так и отрицательные, - четвертая версия, найденная на http://www.strudel.org. .uk / itoa / . Хотя
sprintf
/snprintf
имеют преимущества, они не будут обрабатывать отрицательные числа ни для чего, кроме десятичного преобразования. Так как ссылка выше отключена или больше не активна, я включил их 4-ю версию ниже:источник
sprintf()
и «это значительно быстрее, чем sprintf» может быть верно для вашего компилятора, но не всегда верно. Компилятор может изучитьsprintf(str, "%d", 42);
и оптимизировать его для оптимизированнойitoa()
подобной функции - конечно, быстрее, чем этот пользователь. код.sprintf(str, "%d", 42);
как добавление двух константных символов, но это теория. На практике люди не разбираются в константных значениях, и вышеупомянутая itoa почти настолько же оптимизирована, насколько это возможно. По крайней мере, вы можете быть на 100% уверены, что не получите понижения порядка общего спринта. Было бы неплохо увидеть любой контрпример, который вы имеете в виду, с версией компилятора и настройками.Это старый, но вот другой способ.
источник
Если вы используете GCC, вы можете использовать функцию asprintf расширения GNU.
источник
Преобразование чего-либо в строку должно либо 1) выделить результирующую строку, либо 2) передать в
char *
адресат и размер. Пример кода ниже:Оба работают для всех в
int
том числеINT_MIN
. Они обеспечивают последовательный выход в отличие отsnprintf()
которого зависит от текущей локали.Способ 1: возвращает нехватку
NULL
памяти.Способ 2: возвращается,
NULL
если буфер был слишком маленьким.[Редактировать] как запрос @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
это как минимум максимальное количество,char
необходимое для кодирования некоторого целого типа со знаком в виде строки, состоящей из необязательного отрицательного знака, цифр и нулевого символа.Количество не знаковых битов в знаковое целое число не более чем
CHAR_BIT*sizeof(int_type)-1
. Основное-10 представлениеn
-битного двоичного числа занимает доn*log10(2) + 1
цифр.10/33
чуть больше чемlog10(2)
. +1 для знакаchar
и +1 для нулевого символа. Другие фракции могут быть использованы как 28/93.Метод 3: Если кто-то хочет жить на грани, и переполнение буфера не является проблемой, следует простое решение C99 или более поздней версии, которое обрабатывает все
int
.Образец вывода
источник
источник
Если вы хотите вывести свою структуру в файл, нет необходимости предварительно преобразовывать какое-либо значение. Вы можете просто использовать спецификацию формата printf, чтобы указать, как выводить ваши значения, и использовать любой из операторов семейства printf для вывода ваших данных.
источник
Используйте функцию
itoa()
для преобразования целого числа в строкуНапример:
источник