C言語基礎|文字コードと数字文字

「見た目は同じ0でも、中身は別モノ!―文字コードを知ると数字処理が一気にラクになる」

文字と数値が“ごっちゃ”になる瞬間を卒業しよう

C言語では、文字はただの飾りではなく 整数値(文字コード) として扱われます。
だからこそ、数字の 0 と、文字の '0' は見た目は似ていても まったく別の値 です。

この違いを理解すると、

  • 数字文字のカウント
  • 文字から数値への変換
  • EOF を使った入力終了判定

がスムーズにつながります。

この記事では、元の「EOF と '0'〜'9' を表示」する例にして、文字コードと数字文字の関係、そして 可搬性(環境が違っても正しく動く) まで丁寧に整理しますね。

文字コードってなに?C言語では文字は整数として扱う

文字は“整数のラベル付き”

'0' という文字  →  内部では整数(文字コード)
'A' という文字  →  内部では整数(文字コード)

図の説明
C言語の式の中で 'A' や '0' を使えるのは、実体が「整数値」だからです。
この整数値を 文字コード と呼びます。

数字文字 '0'〜'9' の文字コード(代表例)

多くの環境では ASCII 互換の並びになっていて、'0'〜'9' は連続した値になります。

数字文字のコード例(ASCII互換)

文字16進数10進数
'0'0x3048
'1'0x3149
'2'0x3250
'3'0x3351
'9'0x3957

表の説明
ここで大事なのは「数字文字の値が 0〜9 ではない」こと。
文字の '0' は 48(例)で、数値の 0 とは別物です。

EOF も整数:だから getchar の受け取りは int が定番

getchar は 1文字を返しますが、読み込みに失敗したときは EOF を返します。
EOF はたいてい負の値なので、受け取り側は int が安心です。

getchar と EOF の関係

項目内容
getchar の戻り値型int
返ってくる値読んだ文字のコード、または EOF
EOF入力終了やエラーを表す特別な値(多くは負)
受け取り変数int ch; が安全

サンプルプログラム

入力した1文字が数字なら “数値として” 表示するシンプル例に変更します(メッセージも別の日本語)。

例:数字文字なら数値にして表示、数字以外は文字コードを表示

プロジェクト名:chap8-13-1 ソースファイル名:chap8-13-1.c

#include <stdio.h>

int main(void)
{
    int ch;

    puts("1文字入力してください(終了は Ctrl+D または Ctrl+Z)。");

    while ((ch = getchar()) != EOF) {
        if (ch == '\n')
            continue;

        if ('0' <= ch && ch <= '9') {
            printf("数字文字です:%d\n", ch - '0');
        } else {
            printf("数字ではありません:文字=%c コード=%d\n", ch, ch);
        }
    }

    return 0;
}

実行例(イメージ)

1文字入力してください(終了は Ctrl+D または Ctrl+Z)。
7
数字文字です:7
A
数字ではありません:文字=A コード=65

なぜ ch - '0' で 0〜9 になるの?

ここが一番おいしいところです。

文字から添字や数値を作る仕組み

'0' を基準にすると…
'0' - '0' = 0
'5' - '0' = 5
'9' - '0' = 9

説明
'0'〜'9' が連続して増える(1ずつ増える)なら、差を取れば 0〜9 が作れます。
これが「数字文字カウント」や「文字→数値変換」で大活躍します。

switch(数値ベタ書き)→ if(数値)→ if(文字)へ:可搬性の進化

A/B/C の比較(可搬性と読みやすさ)

方式良いところ弱点
A:switch(数値コード)case 48, 49…仕組みは分かりやすい48 という値に依存しやすい
B:if(数値範囲)ch >= 48 && ch <= 57短い48〜57 に依存しやすい
C:if(文字で判定)ch >= '0' && ch <= '9'読みやすい、移植に強い特になし(推奨)

表の説明
48 や 57 を直接書くと、「その環境の文字コードでたまたまそう」という前提が入りやすくなります。
一方で '0' と '9' を使う書き方は、C言語が保証しているルール(後述)に乗れるので強いです。

重要:C言語が保証してくれるルール

環境によって '0' の数値(コード)そのものは違う可能性があります。
でも C言語では、次が保証されています。

保証される関係

'0','1',…,'9' は 1ずつ増える並び
だから '5' - '0' は必ず 5

説明
ここが「可搬性の核心」です。
'0' が 48 かどうかは環境で違っても、'0' からの差分で 0〜9 が作れることが保証されています。

数字文字カウントが短く書ける理由

数字文字の出現回数を数えるなら、switch で10個 case を並べるより、こう書けます。

数字文字カウントの最短パターン

やること書き方
数字か判定if ('0' <= ch && ch <= '9')
対応する箱を増やすcnt[ch - '0']++

表の説明
cnt の添字が 0〜9 なので、'0' を引いて 0〜9 に変換すればピッタリ対応します。

登場する命令・構文の書式と役割

getchar の書式

int getchar(void);

何をする?
標準入力から次の1文字を読み、読めた文字のコードを返します。入力終了やエラーでは EOF を返します。

puts の書式

int puts(const char *s);

何をする?
文字列を標準出力へ表示し、最後に改行を付けます。

printf の書式

int printf(const char *format, ...);

何をする?
書式に従って表示します。%c は文字、%d は整数を表示します。

while の書式(EOFまで読む定番)

while ((ch = getchar()) != EOF) {
    ...
}

何をする?
1文字ずつ読み、EOF が来るまで繰り返します。

if の書式(数字判定)

if ('0' <= ch && ch <= '9') {
    ...
}

何をする?
数字文字のときだけ処理する安全装置です。

まとめ:文字の '0' と数値の 0 を分けられると強い

  • 文字は整数(文字コード)として扱われる。
  • '0' は 0 ではなく、文字コード上の値(例:48)
  • getchar の戻り値は EOF も扱うので int で受ける。
  • 数字文字は '0'〜'9' が連続して増えるのが保証されている。
  • だから ch - '0' で 0〜9 を安全に作れて、カウントや変換が簡潔になる。