Jak przekonwertować int
(liczbę całkowitą) na ciąg? Próbuję utworzyć funkcję, która konwertuje dane ciągu struct
na ciąg znaków, aby zapisać go w pliku.
int
. Tak, wiem. Jest to bardzo popularny skrót, ale wciąż mnie wkurza.
Jak przekonwertować int
(liczbę całkowitą) na ciąg? Próbuję utworzyć funkcję, która konwertuje dane ciągu struct
na ciąg znaków, aby zapisać go w pliku.
int
. Tak, wiem. Jest to bardzo popularny skrót, ale wciąż mnie wkurza.
Odpowiedzi:
EDYCJA: Jak wskazano w komentarzu, itoa()
nie jest standardem, dlatego lepiej zastosować podejście sprintf () sugerowane w odpowiedzi rywalizującej!
Możesz użyć itoa()
funkcji do konwersji wartości całkowitej na ciąg.
Oto przykład:
int num = 321;
char snum[5];
// convert 123 to string [buf]
itoa(num, snum, 10);
// print our string
printf("%s\n", snum);
Jeśli chcesz wyprowadzić swoją strukturę do pliku, nie musisz wcześniej konwertować żadnej wartości. Możesz po prostu użyć specyfikacji formatu printf, aby wskazać, jak wyprowadzać swoje wartości, i użyć dowolnego operatora z rodziny printf do wyprowadzenia danych.
itoa
nie jest standardem - patrz np. stackoverflow.com/questions/190229/…
itoa()
to taki sam potencjał przepełnienia bufora jak gets()
.
Możesz sprintf
to zrobić, a snprintf
jeśli masz:
char str[ENOUGH];
sprintf(str, "%d", 42);
Gdzie liczbę znaków (plus znak kończący) w str
można obliczyć za pomocą:
(int)((ceil(log10(num))+1)*sizeof(char))
ENOUGH
wystarczy, możemy to zrobićmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
jest 1
.
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
aby uzyskać długość, a następnie przydziel length+1
znaki do łańcucha.
Krótka odpowiedź brzmi:
snprintf( str, size, "%d", x );
Im dłużej: najpierw musisz znaleźć odpowiedni rozmiar. snprintf
podaje długość, jeśli wywołasz ją NULL, 0
jako pierwsze parametry:
snprintf( NULL, 0, "%d", x );
Przydziel jeszcze jeden znak dla null-terminator.
#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);
Jeśli działa dla każdego formatu formatu, więc możesz przekonwertować zmiennoprzecinkowe lub podwójne na łańcuch przy użyciu "%g"
, możesz przekonwertować int na hex przy użyciu "%x"
i tak dalej.
Po przejrzeniu różnych wersji itoa dla gcc, najbardziej elastyczną wersją, jaką znalazłem, która jest w stanie obsługiwać konwersje na binarne, dziesiętne i szesnastkowe, zarówno pozytywne, jak i negatywne, jest czwarta wersja znaleziona na http://www.strudel.org .uk / itoa / . Chociaż sprintf
/ snprintf
mają zalety, nie będą obsługiwać liczb ujemnych dla niczego innego niż konwersja dziesiętna. Ponieważ powyższy link jest offline lub nie jest już aktywny, zamieściłem poniżej jego czwartą wersję:
/**
* 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()
a „to jest znacznie szybsze niż sprintf” może być prawdą w twoim kompilatorze, ale nie zawsze się utrzymuje. Kompilator może go przeanalizować sprintf(str, "%d", 42);
i zoptymalizować do zoptymalizowanej itoa()
funkcji podobnej - na pewno szybciej niż ten użytkownik. kod.
sprintf(str, "%d", 42);
jako dodanie dwóch stałych, ale taka jest teoria. W praktyce ludzie nie sprintf constints i powyższe itoa jest prawie tak zoptymalizowane, jak to możliwe. Przynajmniej możesz być w 100% pewien, że nie dostaniesz obniżenia rzędów wielkości ogólnego sprintu. Byłoby miło zobaczyć cokolwiek kontrprzykład, jaki masz na myśli, z wersją kompilatora i ustawieniami.
To jest stare, ale oto inny sposób.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
Jeśli używasz GCC, możesz użyć funkcji rozszerzenia asprintf GNU.
char* str;
asprintf (&str, "%i", 12313);
free(str);
Konwersja czegokolwiek na ciąg powinna albo 1) przydzielić wynikowy ciąg, albo 2) przekazać w miejscu char *
docelowym i rozmiarze. Przykładowy kod poniżej:
Oba działają dla wszystkich, w int
tym INT_MIN
. Zapewniają one spójne wyniki, w przeciwieństwie snprintf()
do aktualnych ustawień regionalnych.
Metoda 1: Zwraca brak NULL
pamięci.
#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;
}
Metoda 2: Zwraca, NULL
jeśli bufor był zbyt mały.
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;
}
[Edytuj] na żądanie @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
to co najmniej maksymalna liczba char
potrzebna do zakodowania jakiegoś podpisanego typu liczby całkowitej jako ciągu składającego się z opcjonalnego znaku ujemnego, cyfr i znaku zerowego.
Liczba bitów niebędących znakami w całkowitej liczbie ze znakiem jest nie większa niż CHAR_BIT*sizeof(int_type)-1
. Reprezentacja 10- n
bitowej liczby binarnej zajmuje n*log10(2) + 1
cyfry. 10/33
jest nieco więcej niż log10(2)
. +1 za znak char
i +1 za znak zerowy. Można stosować inne frakcje, takie jak 28/93.
Metoda 3: Jeśli ktoś chce żyć na krawędzi, a przepełnienie bufora nie stanowi problemu, następuje proste rozwiązanie C99 lub nowsze, które obsługuje wszystkie 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));
}
Próbka wyjściowa
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;
}
Jeśli chcesz wyprowadzić swoją strukturę do pliku, nie musisz wcześniej konwertować żadnej wartości. Możesz po prostu użyć specyfikacji formatu printf, aby wskazać, jak wyprowadzać swoje wartości, i użyć dowolnego operatora z rodziny printf do wyprowadzenia danych.
Użyj funkcji, itoa()
aby przekonwertować liczbę całkowitą na ciąg
Na przykład:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
lub jeden z jego kuzynów powinien załatwić