int
(整数)をどのように文字列に変換しますか?aのデータをstruct
文字列に変換してファイルに保存する関数を作成しようとしています。
int
。ええ、私は知っています。これは非常に一般的なショートカットですが、それでも私にはバグがあります。
int
(整数)をどのように文字列に変換しますか?aのデータをstruct
文字列に変換してファイルに保存する関数を作成しようとしています。
int
。ええ、私は知っています。これは非常に一般的なショートカットですが、それでも私にはバグがあります。
回答:
編集: コメントで指摘されているように、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
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ターミネータに1文字以上割り当てます。
#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を16進数に変換できます"%x"
。
gccのitoaのさまざまなバージョンを調べた後、2進数、10進数、16進数への変換を処理できる最も柔軟なバージョンであり、正と負の両方がhttp://www.strudel.orgにある4番目のバージョンです。 .uk / itoa /。一方でsprintf
/ snprintf
利点を持って、彼らは小数変換以外で負の数を扱うことはありません。上記のリンクはオフラインであるか、アクティブではなくなっているため、以下の4番目のバージョンを含めました。
/**
* 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()
like関数に最適化します。このユーザーよりも確実に高速です。コード。
sprintf(str, "%d", 42);
2つのconst文字を追加するように最適化できますが、それは理論です。実際には、人々はconst intをsprintfせず、上記のitoaはそれと同じくらい最適化されています。少なくとも、汎用のsprintfを桁違いにダウングレードしないことを100%確信できます。コンパイラのバージョンと設定を使用して、あなたが考えている反例を見るとよいでしょう。
何かを文字列に変換するには、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
いくつかの符号付き整数型を、オプションの負符号、数字、およびnull文字で構成される文字列としてエンコードするために必要な最大数です。
符号付き整数の非符号ビットの数はを超えませんCHAR_BIT*sizeof(int_type)-1
。10 n
進数の2ビットの2進数の表現は、最大で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()
を使用して整数を文字列に変換する
例えば:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
またはそのいとこの1人がトリックを実行する必要があります