Як перетворити int
(ціле) на рядок? Я намагаюся зробити функцію, яка перетворює дані a struct
в рядок, щоб зберегти його у файлі.
int
. Так, я знаю. Це дуже поширена коротка шортка, але вона все ще клопоче мене.
Як перетворити int
(ціле) на рядок? Я намагаюся зробити функцію, яка перетворює дані a struct
в рядок, щоб зберегти його у файлі.
int
. Так, я знаю. Це дуже поширена коротка шортка, але вона все ще клопоче мене.
Відповіді:
EDIT: Як зазначено в коментарі, 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 для виведення даних.
itoa
не є стандартним - див., наприклад, stackoverflow.com/questions/190229/…
itoa()
страждає тим же потенціалом переповнення буфера, що і gets()
.
Ви можете використовувати sprintf
це, а може, snprintf
якщо у вас є:
char str[ENOUGH];
sprintf(str, "%d", 42);
Де кількість символів (плюс кінцевий знак) у банці str
може бути обчислена, використовуючи:
(int)((ceil(log10(num))+1)*sizeof(char))
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( str, size, "%d", x );
Що довше: спочатку потрібно з’ясувати достатній розмір. snprintf
повідомляє довжину, якщо ви називаєте це NULL, 0
як перші параметри:
snprintf( NULL, 0, "%d", x );
Виділіть ще один символ для null-термінатора.
#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);
Якщо працює для кожного рядка формату, тож ви можете перетворити float або double у рядок за допомогою "%g"
, ви можете перетворити int в hex за допомогою "%x"
тощо.
Переглянувши різні версії itoa для gcc, я виявив найбільш гнучку версію, яка здатна обробляти перетворення у двійкові, десяткові та шістнадцяткові, і позитивні, і негативні - четверта версія, знайдена на веб- сайті http://www.strudel.org .uk / itoa / . Хоча sprintf
/ snprintf
мають переваги, вони не оброблятимуть негативні числа для нічого іншого, крім десяткового перетворення. Оскільки вищевказане посилання або офлайн, або більше не активне, я включив їх четверту версію нижче:
/**
* 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 valid
if (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 sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
sprintf()
і "це значно швидше, ніж sprintf" може бути правдою для вашого компілятора, але не завжди має місце. Компілятор може розглянути sprintf(str, "%d", 42);
та оптимізувати його під оптимізовану itoa()
функцію - звичайно швидше, ніж цей користувач. код.
sprintf(str, "%d", 42);
додавання двох символів const, але це теорія. На практиці люди не спринтерствують, і itaa вище майже оптимізована. Принаймні, ви можете бути на 100% впевнені, що не отримаєте порядків зменшення загального спринту. Було б добре побачити будь-який контрприклад, який ви маєте на увазі, з версією компілятора та налаштуваннями.
Це старе, але ось інший спосіб.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
Якщо ви використовуєте GCC, ви можете використовувати функцію розширення GNU asprintf.
char* str;
asprintf (&str, "%i", 12313);
free(str);
Перетворення чого-небудь у рядок повинно або: 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
якщо буфера було занадто мало.
static char *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
. Базове представлення n
-бітового бінарного числа -10 доходить до n*log10(2) + 1
цифр. 10/33
трохи більше, ніж log10(2)
. +1 для знака char
і +1 для нульового символу. Інші фракції можуть бути використані, наприклад, 28/93.
Спосіб 3: Якщо хочеться жити на межі, і переповнення буфера не викликає особливих проблем, випливає просте рішення C99 або новіших версій, яке обробляє всіх int
.
#include <limits.h>
#include <stdio.h>
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main() {
char s[100];
puts(itoa_simple(s, 0));
puts(itoa_simple(s, 1));
puts(itoa_simple(s, -1));
puts(itoa_simple(s, 12345));
puts(itoa_simple(s, INT_MAX-1));
puts(itoa_simple(s, INT_MAX));
puts(itoa_simple(s, INT_MIN+1));
puts(itoa_simple(s, INT_MIN));
}
Вибірка зразка
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
/*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)
return 0;
if(value==0)
{
*ptr='0';
return 1;
}
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 для виведення даних.
Використовуйте функцію itoa()
для перетворення цілого числа в a рядок
Наприклад:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
або хтось із його двоюрідних братів повинен зробити трюк