Nasıl dönüştürür int
(tamsayı) bir dizeye ? Ben struct
bir dosyaya kaydetmek için bir dizeye veri dönüştüren bir işlev yapmaya çalışıyorum .
int
. Evet biliyorum. Bu çok yaygın bir kısa yol, ama yine de beni rahatsız ediyor.
Nasıl dönüştürür int
(tamsayı) bir dizeye ? Ben struct
bir dosyaya kaydetmek için bir dizeye veri dönüştüren bir işlev yapmaya çalışıyorum .
int
. Evet biliyorum. Bu çok yaygın bir kısa yol, ama yine de beni rahatsız ediyor.
Yanıtlar:
DÜZENLEME: Yorumda belirtildiği gibi, itoa()
bir standart değildir, bu yüzden rakip cevapta önerilen sprintf () yaklaşımını daha iyi kullanın!
Tamsayı değerinizi bir dizeye dönüştürmek için itoa()
işlevi kullanabilirsiniz .
İşte bir örnek:
int num = 321;
char snum[5];
// convert 123 to string [buf]
itoa(num, snum, 10);
// print our string
printf("%s\n", snum);
Yapınızı bir dosyaya çıktılamak istiyorsanız, önceden herhangi bir değeri dönüştürmenize gerek yoktur. Yalnızca değerlerinizin nasıl çıktı verileceğini belirtmek için printf formatı belirtimini kullanabilir ve verilerinizin çıktısını almak için printf ailesindeki operatörlerden herhangi birini kullanabilirsiniz .
itoa
standart değildir - bakınız örn. stackoverflow.com/questions/190229/…
itoa()
, aynı arabellek taşması potansiyeline sahiptir gets()
.
Bunu sprintf
yapmak için veya belki snprintf
de sahipseniz kullanabilirsiniz:
char str[ENOUGH];
sprintf(str, "%d", 42);
Burada karakter sayısı (artı sonlandırıcı karakter) str
kullanılarak hesaplanabilir:
(int)((ceil(log10(num))+1)*sizeof(char))
ENOUGH
için bunu yapabilirizmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
olduğunu 1
.
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
uzunluk almak için kullanın ve sonra length+1
dize için karakter ayırın .
Kısa cevap:
snprintf( str, size, "%d", x );
Daha uzun: ilk önce yeterli boyutu bulmanız gerekir. ilk parametre olarak snprintf
çağırırsanız uzunluğunu bildirir NULL, 0
:
snprintf( NULL, 0, "%d", x );
Boş sonlandırıcı için bir karakter daha ayırın.
#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);
Her biçim dizesi için çalışıyorsa, kullanarak float veya double öğesini dizeye "%g"
dönüştürebilirsiniz, int komutunu kullanarak hex'e dönüştürebilirsiniz "%x"
, vb.
Gcc için itoa'nın çeşitli sürümlerine baktıktan sonra, ikili, ondalık ve onaltılık dönüşümleri gerçekleştirebilen en esnek sürüm, hem olumlu hem de negatif http://www.strudel.org adresinde bulunan dördüncü sürümdür. .uk / itoa / . İken sprintf
/ snprintf
avantajlara sahip, bunlar ondalık dönüşüm dışında herhangi bir amaçla negatif sayılar ele olmayacaktır. Yukarıdaki bağlantı çevrimdışı olduğundan veya artık etkin olmadığından, 4. sürümlerini aşağıya ekledim:
/**
* 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()
ve "bu, sprintf'den oldukça hızlıdır" derleyicinizde doğru olabilir, ancak her zaman beklemez. Bir derleyici, bu kullanıcıdan daha hızlı sprintf(str, "%d", 42);
bir şekilde optimize edilmiş bir itoa()
işleve bakabilir ve optimize edebilir . kodu.
sprintf(str, "%d", 42);
iki sabit grafik ekleyerek optimizasyon yapabilir , ancak bu teoridir. Pratikte insanlar const in sprintf sprint değil ve yukarıdaki itoa neredeyse alır gibi optimize edilmiştir. En azından, genel bir sprintf'in büyüklüğünün düşürülme emirlerini almayacağınızdan% 100 emin olabilirsiniz. Derleyici sürümü ve ayarlarıyla aklınızda ne olursa olsun örnek görmek güzel olurdu.
Bu eski ama işte başka bir yol.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
GCC kullanıyorsanız, GNU uzantı asprintf işlevini kullanabilirsiniz.
char* str;
asprintf (&str, "%i", 12313);
free(str);
Bir şeyi bir dizgeye dönüştürmek, 1) sonuçtaki dizgiyi tahsis etmeli veya 2) bir char *
hedef ve boyutta geçmelidir . Aşağıdaki örnek kod:
Her ikisi de int
dahil herkes için çalışır INT_MIN
. snprintf()
Geçerli yerel ayara bağlı olarak tutarlı bir çıktı sağlarlar .
Yöntem 1: NULL
Bellek yetersiz döndürür .
#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;
}
Yöntem 2: NULL
Arabellek çok küçükse döndürür .
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 tarafından istek üzerine [Düzenle]
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
en azından char
bazı işaretli tam sayı türünü isteğe bağlı negatif işaret, rakam ve boş karakterden oluşan bir dize olarak kodlamak için gereken maksimum sayıdır.
İşaretli bir tamsayıdaki işaretsiz bit sayısı en fazla CHAR_BIT*sizeof(int_type)-1
. n
-Bit ikili sayının temel-10 temsili n*log10(2) + 1
rakam alır . 10/33
biraz daha fazladır log10(2)
. İşaret char
için +1 ve boş karakter için +1. Diğer fraksiyonlar 28/93 gibi kullanılabilir.
Yöntem 3: Bir kişi kenarda yaşamak istiyorsa ve arabellek taşması endişe verici değilse, hepsini işleyen basit bir C99 veya sonraki bir çözüm gelir 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));
}
Örnek çıktı
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;
}
Yapınızı bir dosyaya çıkarmak istiyorsanız, önceden herhangi bir değeri dönüştürmenize gerek yoktur. Yalnızca değerlerinizin nasıl çıktı verileceğini belirtmek için printf formatı belirtimini kullanabilir ve verilerinizin çıktısını almak için printf ailesindeki operatörlerden herhangi birini kullanabilirsiniz.
Kullanım işlevi itoa()
bir dönüştürme tamsayı a dize
Örneğin:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
ya da kuzenlerinden biri hile yapmalı