🚪 はじめてのC
🎯 scanfの3大トラップ(&忘れ・型違い入力・改行残り)の症状と対処を説明できる
Cの入門でいちばん多く聞く悲鳴が、scanf まわりです。「実行した瞬間に落ちた」「何も入力していないのに勝手に進んだ」「同じ質問が無限に出続ける」。どれも原因ははっきりしていて、対処も決まっています。ここを越えれば、入力は怖くなくなります。
罠1——& を忘れる
#include <stdio.h>
int main(void) {
int n;
scanf("%d", n); // & が無い!
printf("%d\n", n);
return 0;
}症状は、実行した瞬間の異常終了(Windowsなら「動作を停止しました」、Linuxなら Segmentation fault)。scanf は「n の中に入っている値」を番地だと思い込み、まったく無関係な場所へ書き込もうとします。多くのコンパイラは warning: format '%d' expects argument of type 'int *' と教えてくれます。警告を読む習慣が、そのまま防具になります。
罠2——%d に文字を入れられる
数を聞いているのに abc と入力されたとき、何が起きるか。scanf は「数として読めない」と判断して何も読まずに戻ります。このとき abc は入力バッファに残ったままです。もう一度同じ scanf を実行しても、また同じ文字が残っていて読めない——これが「同じ質問が無限に出続ける」の正体です。
#include <stdio.h>
int main(void) {
int n;
int r = scanf("%d", &n);
if (r != 1) {
printf("数字ではありませんでした\n");
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
// 行末まで読み捨てる
}
}
return 0;
}対処は2段構えです。まず戻り値を必ず見る。そして読めなかったら、getcharで改行まで1文字ずつ読み捨てて、バッファを空にします。この「掃除」をしないと、次の入力もすべて道連れになります。
罠3——改行が残る(%c の事件)
#include <stdio.h>
int main(void) {
int nen;
char kigou;
scanf("%d", &nen);
scanf("%c", &kigou); // ここで改行を拾ってしまう
printf("[%d] [%c]\n", nen, kigou);
return 0;
}2026 と入力して Enter を押すと、バッファには 2026 と改行が入ります。%d は数字部分だけを読み、改行は残します。次の %c は「1文字」を素直に読むので、残っていた改行を掴んでしまう。ユーザーからは「文字を入力する前に勝手に進んだ」ように見えます。
対処は、%c の書式の前に半角スペースを1つ入れることです。
scanf(" %c", &kigou); // 先頭の空白が「空白類を読み飛ばせ」の指示書式の中の空白は「空白・タブ・改行を読み飛ばせ」という命令になります。%d や %lf は自動で読み飛ばすので、この対策が要るのは %c と %[ のときだけです。
まとめ
& を付けたか、戻り値を見たか、バッファに何が残っているか。この3つを確認する癖がつけば、scanfの事故はほぼ全部防げます。%c の前には空白を1つ。読めなかった行は getchar で掃除する。この2つは定型文として覚えてしまって構いません。
キーボードからの入力を読み取り、変数に格納する標準ライブラリの関数のこと。変数の前に&を付け忘れるミスが定番の罠として知られる。戻り値として、正しく読み取れた個数が返ってくる点も覚えておくとよい。
printfやscanfで使う%dや%fのような記号のこと。続けて渡す値をどんな型・どんな見た目として扱うかを指定する役割を持つ。指定する型と実際に渡す値の型がずれると、思わぬ表示結果になることがある。
プログラムの何が・どこで間違っているかを、コンパイラや実行環境が知らせてくれる文章のこと。読めば直し方のヒントが詰まっている味方。英語で書かれていることが多いが、落ち着いて読めば重要な情報が含まれている。
もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。