CおよびC ++でcharをintに変換する


401

CおよびC ++でa charをに変換するにはどうすればよいintですか?


1
@マット:より具体的にすることをお勧めします。一般化について尋ねると、単にあなたのタスクに当てはまらない、あるいは正しいとは言えない一般化された答えが出てくるだけです。あなたが尋ねなければならないとき、あなたはおそらく正しく一般化するのに十分なことを覚えていません。
乾杯とhth。-Alf

@Alf P. Steinbach:元の質問はどの言語について曖昧でした。キーワードcとでc++、両方の言語が直面する答えは合理的だと思います。
Matt Joiner

8
他のテクニカルフォーラムでの豊富な経験から、私の直感は、OP 「数値のテキスト表現を(基数10で)取得し、対応する数値に変換するにはどうすればよいですか?」一般的に言って、CとC ++の初心者は通常、これらの言語でのテキストの動作と実際の意味について信じられないほどあいまいな考えを持っていますchar
Karl Knechtel、2011

3
@KarlKnechtel:それが本当なら(ASCIIは全範囲をカバーしていませんが、多くの初期のチュートリアルでもASCII値を文字から取得することを奨励しているので、50/50程度にします)、OPは明確にする必要がありますが、それは間違いですstackoverflow.com/questions/439573/...
フレッドナーク

3
OPはこの質問を明確にするために3時間を要しましたが、失敗しました。現状では、実際に何が要求されているかを知る方法はありません。閉鎖に投票しました。
sbi

回答:


551

あなたが何をしたいかに依存します:

値をASCIIコードとして読み取るには、次のように記述します。

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

文字を変換する'0' -> 0'1' -> 1など、あなたが書くことができます

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

説明:はと
a - '0'同等((int)a) - ((int)'0')です。つまり、文字のASCII値が互いに減算されます。はasciiテーブルの0直前1にくるので(以降9同様)、2つの間の差が文字がa表す数字になります。


14
ia =(a-'0')%48;
Kshitij Banerjee 2013

@KshitijBanerjeeこれは、2つの理由で良い考えではありません。「0」より前のASCII文字の負の数値(&-> -10など)と、10より大きい数値(x-> 26など)を
取得

2
int ia = a-
funk

5
@ kevin001 charをintに変換し、文字がで'1'ないASCII番号を提供する1場合は、オフセット'0'を削除して、0〜9にカウントするように再配置する必要があります。連続した番号1から9は、ASCII整数で隣接しています。
krisdestruction 2015年

キャストは不要/不要
Craig Estey、2015年

97

まあ、ASCIIコードでは、数字(数字)は48から始まります。あなたがする必要があるのは:

int x = (int)character - 48;

19
@chad:読みやすくなるだけでなく、移植性も向上します。CおよびC ++は、ASCII表現を保証しませんが、使用されている表現が何であれ、10進数の10桁の表現が連続していて番号順になっていることを保証します。
Ben Voigt 2017

私が変更した唯一のことは48歳になることです。これは少し「魔法」のようです'0'
ArielGro

59

CおよびC ++は常に型を少なくともに昇格させますint。さらに、文字リテラルはintCおよびcharC ++ の型です。

にをchar割り当てるだけでタイプを変換できintます。

char c = 'a'; // narrowing on C
int a = c;

3
あまり評価されていない単項 operator+()をこの目的に使用することもできます。
Cubbi

24
-1質問の意味のある唯一の解釈に対して、答えは正しくありません。これ(コードint a = c;)は、C標準ライブラリ関数が処理できない負の値を保持します。C標準ライブラリ関数は、char値をとして処理することの意味の標準を設定しますint
乾杯とhth。-Alf

6
@マット:私は反対投票を続けています。できれば強化したい!あなたや他の人が想定している質問の解釈は意味がありません。なぜなら、それはまったく取るに足らないことであり、OPの特定のタイプの組み合わせについては、それほど重要ではない非常に重要な実用的な問題があるためです。あなたが与えるアドバイスは初心者にとって直接危険です。C標準ライブラリの文字分類関数を使用するプログラムで、未定義の動作が発生する可能性が最も高くなります。再参照 @Sayamの答えに、彼はその答えを削除しました。
乾杯とhth。-Alf

3
正しくない場合は-1:1252ハイビット文字を渡すと、isupper()の結果は未定義になります。
クリスベッケ

1
「常に宣伝」とはどういう意味ですか?値は、暗黙的な変換、特定のタイプのパラメーター(varargs関数など)の受け渡し、およびオペレーターがそのオペランドを互換性のあるタイプにする必要がある場合に昇格されます。ただし、値が昇格されない場合(たとえば、charを期待する関数にcharを渡す場合など)は確かにあります。そうでない場合、intよりも小さい型はありません。
エイドリアン・マッカーシー

31

charは1バイトの整数です。charタイプには魔法はありません。shortをintに、またはintをlongに割り当てることができるように、charをintに割り当てることができます。

はい、プリミティブデータ型の名前はたまたま "char"であり、これは文字のみを含む必要があることを示唆しています。しかし、実際には、「char」は、言語を学ぼうとするすべての人を混乱させるための単なる貧弱な名前です。より適切な名前はint8_tです。コンパイラが最新のC標準に準拠している場合は、代わりにその名前を使用できます。

もちろん、古典的なASCIIテーブルのインデックスは1バイトに収まるため、文字列処理を行うときはchar型使用する必要があります。ただし、通常のintを使用して文字列処理を行うこともできますが、これを実行する理由は実際にはありません。たとえば、次のコードは完全に機能します。

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

文字や文字列は、コンピュータの他のすべてのものと同じように、単なる数字であることを理解する必要があります。ソースコードで「a」を記述すると、整数定数である数値97に前処理されます。

したがって、次のような式を書くと

char ch = '5';
ch = ch - '0';

これは実際には

char ch = (int)53;
ch = ch - (int)48;

その後、C言語の整数プロモーションが行われます

ch = (int)ch - (int)48;

結果の型に合わせてcharに切り捨てられます

ch = (char)( (int)ch - (int)48 );

行の間にこのような微妙なことがたくさんあり、charは暗黙的にintとして扱われます。


質問にはのタグが付いてasciiいないため、特定のエンコーディングを想定しないでください。またはに等しくなる可能性があるため、char等しいに設定することint8_tは間違っています。uint8_tuint24_t
Roland Illig

1
@RolandIlligいいえ、a charは常に1バイトであり、タイプint8_t/ uint8_tが所定のシステムに存在する場合(これは非常に可能性が高い)、char8ビットになるため、それらはの結果に適合できます。時代遅れのさまざまなDSPなどの非常にエキゾチックなシステムでcharは、16ビットとなり、uint8_t存在しません。廃止されたDSPとの互換性のためにコードを書くことは、人の補数または符号と大きさのシステムとの互換性のために書くことと同様に、ナンセンスです。そのようなシステムは現実の世界にはほとんど存在しないため、膨大な時間の無駄です。
ランディン

18

(この回答はC ++側の問題に対処していますが、Cにも符号拡張の問題が存在します。)

すべての3つの処理charの種類を(signedunsignedchar)それが最初に現れるよりも繊細です。0〜SCHAR_MAX(8ビットの場合は127)の範囲の値charは簡単です。

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

ただし、somevalueがその範囲外の場合は、3つのタイプすべてでunsigned char「同じ」char値に対して一貫した結果が得られます。

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

or などのctype.hの関数を使用するisupper場合toupper、これは符号拡張のために重要です。

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

intによる変換は暗黙的であることに注意してください。これは同じUBを持っています:

char c = negative_char;
bool b = isupper(c);

これを修正するには、を通過しますunsigned char。これは、safe_ctypeを介してctype.h関数をラップすることで簡単に実行できます

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

これは、3つのchar型のいずれかを取る関数は他の2つのchar型も受け取ることができるため機能します。これは、任意のタイプを処理できる2つの関数につながります。

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)負渡された場合でも-いつもあなたの非負値を与えるcharか、否定をsigned char-とchr、任意の値取りord生産をして戻ってまったく同じ提供しますchar

実際には、おそらくunsigned charこれらを使用する代わりに単にキャストするだけですが、キャストを簡潔にラップし、int-to-のエラーチェックを追加するための便利な場所を提供charします。近接。



7

それは一種の「変換」が何を意味するかに依存します。

「123456」のような整数を表す一連の文字がある場合、Cでそれを行うには2つの一般的な方法があります。atoi()strtol()などの特殊目的の変換、または汎用のsscanfを使用します。 ()。C ++(これは実際にはアップグレードを装った別の言語です)は、3番目の文字列ストリームを追加します。

int変数の1つにある正確なビットパターンをとして処理したい場合はchar、より簡単です。Cでは、さまざまな整数型は、実際の個別の「型」よりも本当に心の状態です。charsが要求された場所で使用を開始するだけで、大丈夫です。コンパイラーが時々泣き言をやめるように明示的な変換が必要な場合がありますが、行うべきことは、256を超えて余分なビットをドロップすることだけです。


6

私はnullCのスキルは絶対にありますが、単純な解析の場合:

char* something = "123456";

int number = parseInt(something);

...これは私のために働きました:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}

このコードは未定義の動作をすぐに呼び出すため、コピーと貼り付けには適していません。(intオーバーフロー)
Roland Illig

4

おそらく、C標準ライブラリの関数を使用するためにこの変換が必要です。

その場合、次のようにします(C ++構文)

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

式は、EOFを除いてC関数でサポートされていない負の値を取り除くためににUChar( c )変換さunsigned charれます。

次に、その式の結果がint仮引数の実引数として使用されます。に自動昇格する場所int。または、最後のステップをのようint( UChar( c ) )に明示的に書くこともできますが、個人的には冗長すぎます。

乾杯&hth。、


0

のよう"7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"にchar配列を実際の整数値に変換する際に問題がありました。これは、1つの16進値として「7C」で表すことができます。それで、助けを求めて巡航した後、私はこれを作成し、共有するのは素晴らしいことだと思いました。

これにより、文字列が適切な整数に分離され、私だけでなく、より多くの人に役立つ場合があります;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

それが役に立てば幸い!


このコードをテストしたことがありますか?50は48にする必要があります。55は大文字のASCII文字に対してのみ機能しますが、例には小文字が含まれています。
Roland Illig

0

charまたはshortからintの場合は、値を割り当てるだけです。

char ch = 16;
int in = ch;

int64と同じです。

long long lo = ch;

すべての値は16になります。


-1
int charToint(char a){
char *p = &a;
int k = atoi(p);
return k;
}

このatoiメソッドを使用して、charをintに変換できます。詳細については、あなたはこれを参照することができhttp://www.cplusplus.com/reference/cstdlib/atoi/http://www.cplusplus.com/reference/string/stoi/


1
これは未定義の動作です。char変数のアドレスを取得すると、char *が提供されますが、atoiが期待するC文字列は提供されません。
luizfls
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.