możesz również zapoznać się z często zadawanymi pytaniami na temat serializacji i być może z następującymi pytaniami, które dotyczą serializacji w C: (a) , (b) , (c), aby osiągnąć swój rzeczywisty zamiar.
moooeeeep 24.11.11
2
Moja zwykła semantyczna siusiu tutaj. Nie chcesz niczego konwertować; chcesz otrzymać ciąg zawierający (podstawową 10?) reprezentację wartości int. Tak, wiem. Jest to bardzo popularny skrót, ale wciąż mnie wkurza.
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.
Aby mieć pewność, że tat ENOUGHwystarczy, możemy to zrobićmalloc(sizeof(char)*(int)log10(num))
Hauleth,
2
@Hauleth Lub nawet +2, biorąc pod uwagę, że tak (int)log10(42)jest 1.
Christian Rau
23
Lub możesz to obliczyć w czasie kompilacji:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
caf
4
@hauleth Nadal +2 zamiast +1, nawet przy ceil: ceil (log (100)) = 2,0, a nie 3. Więc +1 za dokładną potęgę-10 i kolejne +1 za zakończenie zerowania.
not-just-yeti
24
Nie bierzesz pod uwagę znaku minus i lokalizacji: separator tysięcy i grupowanie. Zrób to w ten sposób: użyj, int length = snprintf(NULL, 0,"%d",42);aby uzyskać długość, a następnie przydziel length+1znaki do łańcucha.
user2622016
69
Krótka odpowiedź brzmi:
snprintf( str, size,"%d", x );
Im dłużej: najpierw musisz znaleźć odpowiedni rozmiar. snprintfpodaje długość, jeśli wywołasz ją NULL, 0jako 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.
@ user1821961 Dzięki, naprawdę należy wspomnieć, że te pliki nagłówkowe muszą zostać dołączone.
byxor
Uwielbiam ten, ponieważ jest najsolidniejszy i „z książki”.
Motti Shneor
30
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/ snprintfmają 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 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;}
Jest to także znacznie szybsze niż sprintf. Może to być ważne podczas zrzutu dużych plików.
Eugene Ryabtsev
@Eugene Ryabtsev C nie określa oceny wydajności, 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.
chux - Przywróć Monikę
3
@chux Tak, kompilator może zoptymalizować 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.
Eugene Ryabtsev
1
@chux Jeśli zakończy się wywołaniem, nie wyjaśnia wiele, chyba że porównamy wywoływaną procedurę z powyższą procedurą (aż do braku kolejnych wywołań; w assemblerze, jeśli chcesz). Jeśli zrobisz to jako odpowiedź z wersją kompilatora i ustawieniami, będę go głosować jako przydatny.
Eugene Ryabtsev
2
Dobrze byłoby zapewnić sposób na odzyskanie długości wyjściowej. Zrobiłem to tutaj: stackoverflow.com/a/52111436/895245 + testy jednostkowe.
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 inttym INT_MIN. Zapewniają one spójne wyniki, w przeciwieństwie snprintf()do aktualnych ustawień regionalnych.
Metoda 1: Zwraca brak NULLpamię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, NULLjeśli bufor był zbyt mały.
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;}
[Edytuj] na żądanie @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3to co najmniej maksymalna liczba charpotrzebna 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- nbitowej liczby binarnej zajmuje n*log10(2) + 1cyfry. 10/33jest nieco więcej niż log10(2). +1 za znak chari +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 wszystkieint .
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 Nie jestem zaznajomiony z wewnętrzną implementacją glibc.
chux - Przywróć Monikę
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;}
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.
printf
lub jeden z jego kuzynów powinien załatwić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:
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.
źródło
itoa
nie jest standardem - patrz np. stackoverflow.com/questions/190229/…itoa()
to taki sam potencjał przepełnienia bufora jakgets()
.Możesz
sprintf
to zrobić, asnprintf
jeśli masz:Gdzie liczbę znaków (plus znak kończący) w
str
można obliczyć za pomocą:źródło
ENOUGH
wystarczy, możemy to zrobićmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
jest1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
aby uzyskać długość, a następnie przydziellength+1
znaki do łańcucha.Krótka odpowiedź brzmi:
Im dłużej: najpierw musisz znaleźć odpowiedni rozmiar.
snprintf
podaje długość, jeśli wywołasz jąNULL, 0
jako pierwsze parametry:Przydziel jeszcze jeden znak dla null-terminator.
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.źródło
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ę:źródło
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 zoptymalizowanejitoa()
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.
źródło
Jeśli używasz GCC, możesz użyć funkcji rozszerzenia asprintf GNU.
źródło
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
tymINT_MIN
. Zapewniają one spójne wyniki, w przeciwieństwiesnprintf()
do aktualnych ustawień regionalnych.Metoda 1: Zwraca brak
NULL
pamięci.Metoda 2: Zwraca,
NULL
jeśli bufor był zbyt mały.[Edytuj] na żądanie @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
to co najmniej maksymalna liczbachar
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 zajmujen*log10(2) + 1
cyfry.10/33
jest nieco więcej niżlog10(2)
. +1 za znakchar
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
.Próbka wyjściowa
źródło
źródło
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.
źródło
Użyj funkcji,
itoa()
aby przekonwertować liczbę całkowitą na ciągNa przykład:
źródło