Cでintを文字列に変換する方法は?


225

int(整数)をどのように文字列に変換しますか?aのデータをstruct文字列に変換してファイルに保存する関数を作成しようとしています。


3
printfまたはそのいとこの1人がトリックを実行する必要があります
pmg


1
また、シリアライゼーションに関するこのFAQ、およびCでのシリアライゼーションに関連する次の質問を参照することもできます:(a)(b)(c)実際の意図を達成するため
moooeeeep

2
私のいつものペットのセマンティックピーブはここです。何も変換したくない。の値の(base 10?)表現を含む文字列を取得したいint。ええ、私は知っています。これは非常に一般的なショートカットですが、それでも私にはバグがあります。
dmckee ---元モデレーターの子猫2014

回答:


92

編集: コメントで指摘されているように、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ファミリーの任意の演算子を使用してデータを出力できます。


30
itoa標準ではありません-たとえば、stackoverflow.com
Paul R

1
@PaulR今、私はそれを知りませんでした!説明をありがとう。
クリスチャンラウ

1
@PaulRありがとう、私はそれを知りませんでした!
Alexander Galkin

@SeanRameyこれにitoa()は、と同じバッファオーバーフローの可能性がありgets()ます。
chux-モニカを2018年

itoaはCでは使用できません(少なくともC99)。C ++でより多く利用可能
Motti Shneor

211

あなたsprintfはそれを行うために使うことができます、あるいはsnprintfあなたがそれを持っているなら多分:

char str[ENOUGH];
sprintf(str, "%d", 42);

の文字数(および終了文字)は、str以下を使用して計算できます。

(int)((ceil(log10(num))+1)*sizeof(char))

9
tat ENOUGHで十分であることを確認するには、次の方法でそれを行うことができますmalloc(sizeof(char)*(int)log10(num))
Hauleth

2
@Haulethまたは+2、それを考えると(int)log10(42)です1
Christian Rau

23
それとも、コンパイル時にそれを計算することができます:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
CAF

4
@hauleth ceilを使用しても、+ 1ではなく+2:ceil(log(100))= 2.0、3ではありません。つまり、exact-powers-of-10の場合は+ 1、nullを終了する場合は+1です。
not-just-yeti 2015

24
マイナス記号とロケールは考慮しません。3桁ごとの区切りとグループ化です。このようにしてください:を使用int length = snprintf(NULL, 0,"%d",42);して長さを取得length+1し、文字列に文字を割り当てます。
user2622016 2015

70

短い答えは:

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"


3
#include <stdio.h> #include <stdlib.h>
user1821961 2017年

@ user1821961おかげで、これらのヘッダーファイルをインクルードする必要があることを本当に言及する必要があります。
byxor

私はこれが大好きで、最も堅固で、「本ごと」の方法です。
Motti Shneor

30

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;
}

4
また、これはsprintfよりもかなり高速です。大きなファイルをダンプするときに重要になる可能性があります。
Eugene Ryabtsev 2014年

@Eugene Ryabtsev Cはのパフォーマンスレーティングを指定していません。sprintf()「これはsprintfよりもかなり高速です」は、コンパイラでは当てはまるかもしれませんが、常に成立するとは限りません。コンパイラーはsprintf(str, "%d", 42);それを調べて、最適化されたitoa()like関数に最適化します。このユーザーよりも確実に高速です。コード。
chux-モニカを2015年

3
@chuxはい、コンパイラはsprintf(str, "%d", 42);2つのconst文字を追加するように最適化できますが、それは理論です。実際には、人々はconst intをsprintfせず、上記のitoaはそれと同じくらい最適化されています。少なくとも、汎用のsprintfを桁違いにダウングレードしないことを100%確信できます。コンパイラのバージョンと設定を使用して、あなたが考えている反例を見るとよいでしょう。
Eugene Ryabtsev 2015

1
@chux呼び出しで終了する場合、呼び出されたルーチンを上記のルーチンと比較しない限り、説明が不十分です(必要に応じて、アセンブリで、呼び出しがなくなるまで)。コンパイラのバージョンと設定の答えとしてそれを行うなら、私はそれを役に立つと賛成します。
Eugene Ryabtsev 2015年

2
出力の長さを元に戻す方法を提供するとよいでしょう。私はここでそれを行いました:stackoverflow.com/a/52111436/895245 +単体テスト。
Ciro Santilli郝海东冠状病六四事件法轮功

9

これは古いですが、別の方法があります。

#include <stdio.h>

#define atoa(x) #x

int main(int argc, char *argv[])
{
    char *string = atoa(1234567890);
    printf("%s\n", string);
    return 0;
}

32
定数に対してのみ機能し、変数に対しては機能しません。
Nakedible

7

GCCを使用している場合は、GNU拡張asprintf関数を使用できます。

char* str;
asprintf (&str, "%i", 12313);
free(str);

7

何かを文字列に変換するには、1)結果の文字列を割り当てるか、2)char *宛先とサイズを渡す必要があります。以下のサンプルコード:

どちらもintを含むすべてで機能しますINT_MINsnprintf()現在のロケールに依存しない、一貫した出力を提供します。

方法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

こんにちは、glibcの内部実装を公開する方法があるかどうか知っていますか?sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/...
チロSantilli郝海东冠状病六四事件法轮功

1
@CiroSantilli新疆改造中心六四事件法轮功私はglibcの内部実装に詳しくありません。
chux-モニカを2018年

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)
            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;
     }

2

構造をファイルに出力する場合は、事前に値を変換する必要はありません。printfフォーマット仕様を使用して、値を出力する方法を示し、printfファミリーの任意の演算子を使用してデータを出力できます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.