Anda mungkin juga ingin melihat FAQ ini tentang serialisasi, dan mungkin pertanyaan-pertanyaan berikut yang berkaitan dengan serialisasi dalam C: (a) , (b) , (c) untuk mencapai maksud Anda yang sebenarnya.
moooeeeep
2
Semantik hewan peliharaan saya seperti biasa di sini. Anda tidak ingin mengonversi apa pun; Anda ingin mendapatkan string yang berisi representasi (basis 10?) dari nilai int. Ya aku tahu. Ini jalan pintas yang sangat umum, tetapi masih mengganggu saya.
EDIT: Seperti yang ditunjukkan dalam komentar, itoa()bukan standar, jadi lebih baik gunakan pendekatan sprintf () yang disarankan dalam jawaban yang bersaing!
Anda bisa menggunakan itoa()fungsi untuk mengonversi nilai integer Anda menjadi sebuah string.
Berikut ini sebuah contoh:
int num =321;char snum[5];// convert 123 to string [buf]
itoa(num, snum,10);// print our string
printf("%s\n", snum);
Jika Anda ingin menampilkan struktur Anda menjadi file, Anda tidak perlu mengonversi nilai apa pun sebelumnya. Anda bisa menggunakan spesifikasi format printf untuk menunjukkan cara menampilkan nilai Anda dan menggunakan salah satu operator dari keluarga printf untuk menampilkan data Anda.
Yang pasti tat ENOUGHsudah cukup kita bisa melakukannya denganmalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@Hauleth Atau bahkan 2, mengingat (int)log10(42)ini 1.
Christian Rau
23
Atau Anda dapat menghitungnya pada waktu kompilasi:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
caf
4
@hauleth Still +2 bukannya +1, bahkan dengan ceil: ceil (log (100)) = 2.0, bukan 3. Jadi +1 untuk nilai tepat-of-10, dan +1 lainnya untuk mengakhiri nol.
not-just-yeti
24
Anda tidak mempertimbangkan tanda minus dan lokal: ribuan pemisah dan pengelompokan. Silakan lakukan seperti ini: gunakan int length = snprintf(NULL, 0,"%d",42);untuk mendapatkan panjang, dan kemudian alokasikan length+1karakter untuk string.
user2622016
70
Jawaban singkatnya adalah:
snprintf( str, size,"%d", x );
Semakin lama: pertama Anda perlu mengetahui ukuran yang cukup. snprintfmemberi tahu Anda panjangnya jika Anda menyebutnya dengan NULL, 0sebagai parameter pertama:
snprintf( NULL,0,"%d", x );
Alokasikan satu karakter lebih banyak untuk 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);
Jika berfungsi untuk setiap string format, jadi Anda bisa mengonversi float atau double ke string dengan menggunakan "%g", Anda bisa mengonversi int ke hex menggunakan "%x", dan sebagainya.
@ user1821961 Terima kasih, harus benar-benar disebutkan bahwa file header ini harus disertakan.
byxor
Saya suka yang ini, menjadi cara yang paling kuat dan "menurut buku".
Motti Shneor
30
Setelah melihat berbagai versi itoa untuk gcc, versi paling fleksibel yang saya temukan yang mampu menangani konversi ke biner, desimal dan heksadesimal, baik positif dan negatif adalah versi keempat yang ditemukan di http://www.strudel.org .uk / itoa / . Sementara sprintf/ snprintfmemiliki keunggulan, mereka tidak akan menangani angka negatif untuk apa saja selain konversi desimal. Karena tautan di atas tidak aktif atau tidak aktif lagi, saya telah menyertakan versi ke-4 di bawah ini:
/**
* 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;}
Juga, ini jauh lebih cepat daripada sprintf. Bisa jadi penting saat membuang file besar.
Eugene Ryabtsev
@Eugene Ryabtsev C tidak menentukan peringkat kinerja sprintf()dan "ini jauh lebih cepat daripada sprintf" mungkin benar pada kompiler Anda tetapi tidak selalu berlaku. Kompiler dapat melihat sprintf(str, "%d", 42);dan mengoptimalkannya ke itoa()fungsi seperti dioptimalkan - tentu saja lebih cepat dari pengguna ini. kode.
chux - Reinstate Monica
3
@ chux Ya, kompiler dapat dioptimalkan sprintf(str, "%d", 42);sebagai menambahkan dua karakter const, tapi itu teori. Dalam prakteknya orang tidak berlari cepat dan itoa di atas hampir sama optimalnya dengan yang didapat. Setidaknya Anda bisa 100% yakin Anda tidak akan mendapatkan pesanan penurunan peringkat dari sprintf generik. Akan lebih baik untuk melihat contoh balik apa pun yang ada dalam pikiran Anda, dengan versi dan pengaturan kompiler.
Eugene Ryabtsev
1
@ chux Jika berakhir dengan panggilan, itu tidak menjelaskan banyak kecuali kita membandingkan rutin yang dipanggil dengan rutin di atas (semua jalan ke tidak ada lagi panggilan; dalam perakitan, jika Anda suka). Jika Anda melakukannya sebagai jawaban dengan versi dan pengaturan kompiler, saya akan menambahkannya sebagai berguna.
Eugene Ryabtsev
2
Akan lebih baik untuk menyediakan cara untuk mendapatkan panjang output kembali. Saya sudah melakukannya di sini: stackoverflow.com/a/52111436/895245 + unit test.
Mengubah apapun menjadi string harus 1) mengalokasikan string yang dihasilkan atau 2) meneruskan a char * tujuan dan ukuran. Kode contoh di bawah ini:
Keduanya bekerja untuk semua inttermasuk INT_MIN. Mereka memberikan hasil yang konsisten tidak sepertisnprintf() yang tergantung pada lokal saat ini.
Metode 1: Mengembalikan NULLkehabisan memori.
#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;}
Metode 2: Ini kembali NULLjika buffer terlalu kecil.
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;}
[Sunting] sebagai permintaan oleh @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3paling tidak adalah jumlah maksimum yang chardiperlukan untuk menyandikan beberapa tipe integer yang ditandatangani sebagai string yang terdiri dari tanda negatif opsional, digit, dan karakter nol.
Jumlah bit non-masuk dalam bilangan bulat yang ditandatangani tidak lebih dari CHAR_BIT*sizeof(int_type)-1. Representasi basis-10 dari nangka biner -bit membutuhkan hingga n*log10(2) + 1digit. 10/33sedikit lebih dari log10(2). +1 untuk tanda chardan +1 untuk karakter nol. Fraksi lain dapat digunakan seperti 28/93.
Metode 3: Jika seseorang ingin hidup di tepi dan buffer overflow bukan masalah, solusi C99 sederhana atau lebih baru mengikuti yang menangani semuaint .
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 Saya tidak terbiasa dengan implementasi internal glibc.
chux - Reinstate Monica
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;}
Jika Anda ingin menampilkan struktur Anda menjadi file, Anda tidak perlu mengkonversi nilai apa pun sebelumnya. Anda bisa menggunakan spesifikasi format printf untuk menunjukkan cara menampilkan nilai Anda dan menggunakan salah satu operator dari keluarga printf untuk menampilkan data Anda.
printf
atau salah satu sepupunya harus melakukan trikint
. Ya aku tahu. Ini jalan pintas yang sangat umum, tetapi masih mengganggu saya.Jawaban:
EDIT: Seperti yang ditunjukkan dalam komentar,
itoa()
bukan standar, jadi lebih baik gunakan pendekatan sprintf () yang disarankan dalam jawaban yang bersaing!Anda bisa menggunakan
itoa()
fungsi untuk mengonversi nilai integer Anda menjadi sebuah string.Berikut ini sebuah contoh:
Jika Anda ingin menampilkan struktur Anda menjadi file, Anda tidak perlu mengonversi nilai apa pun sebelumnya. Anda bisa menggunakan spesifikasi format printf untuk menunjukkan cara menampilkan nilai Anda dan menggunakan salah satu operator dari keluarga printf untuk menampilkan data Anda.
sumber
itoa
tidak standar - lihat misalnya stackoverflow.com/questions/190229/…itoa()
mengalami potensi buffer overflow yang sama dengangets()
.Anda dapat menggunakannya
sprintf
untuk melakukannya, atau mungkinsnprintf
jika Anda memilikinya:Di mana jumlah karakter (plus karakter terminasi) di
str
dapat dihitung menggunakan:sumber
ENOUGH
sudah cukup kita bisa melakukannya denganmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
ini1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
untuk mendapatkan panjang, dan kemudian alokasikanlength+1
karakter untuk string.Jawaban singkatnya adalah:
Semakin lama: pertama Anda perlu mengetahui ukuran yang cukup.
snprintf
memberi tahu Anda panjangnya jika Anda menyebutnya denganNULL, 0
sebagai parameter pertama:Alokasikan satu karakter lebih banyak untuk null-terminator.
Jika berfungsi untuk setiap string format, jadi Anda bisa mengonversi float atau double ke string dengan menggunakan
"%g"
, Anda bisa mengonversi int ke hex menggunakan"%x"
, dan sebagainya.sumber
Setelah melihat berbagai versi itoa untuk gcc, versi paling fleksibel yang saya temukan yang mampu menangani konversi ke biner, desimal dan heksadesimal, baik positif dan negatif adalah versi keempat yang ditemukan di http://www.strudel.org .uk / itoa / . Sementara
sprintf
/snprintf
memiliki keunggulan, mereka tidak akan menangani angka negatif untuk apa saja selain konversi desimal. Karena tautan di atas tidak aktif atau tidak aktif lagi, saya telah menyertakan versi ke-4 di bawah ini:sumber
sprintf()
dan "ini jauh lebih cepat daripada sprintf" mungkin benar pada kompiler Anda tetapi tidak selalu berlaku. Kompiler dapat melihatsprintf(str, "%d", 42);
dan mengoptimalkannya keitoa()
fungsi seperti dioptimalkan - tentu saja lebih cepat dari pengguna ini. kode.sprintf(str, "%d", 42);
sebagai menambahkan dua karakter const, tapi itu teori. Dalam prakteknya orang tidak berlari cepat dan itoa di atas hampir sama optimalnya dengan yang didapat. Setidaknya Anda bisa 100% yakin Anda tidak akan mendapatkan pesanan penurunan peringkat dari sprintf generik. Akan lebih baik untuk melihat contoh balik apa pun yang ada dalam pikiran Anda, dengan versi dan pengaturan kompiler.Ini sudah tua tapi ini cara lain.
sumber
Jika Anda menggunakan GCC, Anda dapat menggunakan fungsi GNU extension asprintf.
sumber
Mengubah apapun menjadi string harus 1) mengalokasikan string yang dihasilkan atau 2) meneruskan a
char *
tujuan dan ukuran. Kode contoh di bawah ini:Keduanya bekerja untuk semua
int
termasukINT_MIN
. Mereka memberikan hasil yang konsisten tidak sepertisnprintf()
yang tergantung pada lokal saat ini.Metode 1: Mengembalikan
NULL
kehabisan memori.Metode 2: Ini kembali
NULL
jika buffer terlalu kecil.[Sunting] sebagai permintaan oleh @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
paling tidak adalah jumlah maksimum yangchar
diperlukan untuk menyandikan beberapa tipe integer yang ditandatangani sebagai string yang terdiri dari tanda negatif opsional, digit, dan karakter nol.Jumlah bit non-masuk dalam bilangan bulat yang ditandatangani tidak lebih dari
CHAR_BIT*sizeof(int_type)-1
. Representasi basis-10 darin
angka biner -bit membutuhkan hinggan*log10(2) + 1
digit.10/33
sedikit lebih darilog10(2)
. +1 untuk tandachar
dan +1 untuk karakter nol. Fraksi lain dapat digunakan seperti 28/93.Metode 3: Jika seseorang ingin hidup di tepi dan buffer overflow bukan masalah, solusi C99 sederhana atau lebih baru mengikuti yang menangani semua
int
.Output sampel
sumber
sumber
Jika Anda ingin menampilkan struktur Anda menjadi file, Anda tidak perlu mengkonversi nilai apa pun sebelumnya. Anda bisa menggunakan spesifikasi format printf untuk menunjukkan cara menampilkan nilai Anda dan menggunakan salah satu operator dari keluarga printf untuk menampilkan data Anda.
sumber
Gunakan fungsi
itoa()
untuk mengubah bilangan bulat menjadi stringSebagai contoh:
sumber