よくある I/O の落とし穴
バッファーと改行の問題です。
「よくある I/O の落とし穴」はCoddyKit上の無料C Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。
よくあるI/Oのバグ
Cの入力と出力には、典型的な落とし穴がいくつかあります。これらを知っておくと、デバッグにかかる時間を大幅に短縮できます。
#include <stdio.h>
int main(void) {
printf("Let us study I/O pitfalls\n");
return 0;
}残った改行文字
scanf("%d", ...)の後では、Enterキーによって\nがバッファーに残ります。その後の%cは、実際の入力ではなく、この改行文字を読み取ってしまいます。
#include <stdio.h>
int main(void) {
char c = 'A';
printf("Use a space before %%c to skip the leftover newline\n");
printf("c = %c\n", c);
return 0;
}スペースで解決する
先頭にスペースを付けたscanf(" %c", &c)と書くと、最初に空白文字を読み飛ばすようscanfに指示できます。
#include <stdio.h>
int main(void) {
char c = 'Z';
printf("scanf(\" %%c\", &c) skips whitespace\n");
printf("c = %c\n", c);
return 0;
}アンパサンドの付け忘れ
&を付けずに変数をscanfへ渡すと、誤ったアドレスに書き込み、クラッシュする可能性が高くなります。
#include <stdio.h>
int main(void) {
int n = 9;
printf("Always pass &n, not n, to scanf for an int\n");
printf("n = %d\n", n);
return 0;
}指定子の不一致
scanfで%lfの代わりに%fを使ってdoubleを読み取ると、値が壊れます。出力ではどちらも%fを使いますが、入力では異なります。
#include <stdio.h>
int main(void) {
double d = 2.5;
printf("scanf needs %%lf for double; printf uses %%f\n");
printf("d = %.1f\n", d);
return 0;
}出力のバッファリング
出力はバッファーに蓄えられ、すぐに表示されないことがあります。\nで終えるか、fflush(stdout)を呼び出すとフラッシュされます。
#include <stdio.h>
int main(void) {
printf("Flushed by newline\n");
fflush(stdout);
return 0;
}getsは危険
古いgets関数には境界チェックがなく、現代のCから削除されています。代わりにfgetsを使用してください。
#include <stdio.h>
int main(void) {
char buf[10];
/* fgets(buf, sizeof buf, stdin); */
buf[0] = 'H'; buf[1] = 'i'; buf[2] = 0;
printf("buf = %s\n", buf);
return 0;
}%sによるバッファーオーバーフロー
scanfで単純な%sを使うと、小さな配列の範囲を超えて書き込む可能性があります。%19sのように幅を指定して制限してください。
#include <stdio.h>
int main(void) {
char name[20];
printf("Use %%19s to leave room for the null terminator\n");
name[0] = 0;
printf("name length cap protects buffer\n");
return 0;
}fgetsは改行を保持する
fgetsは末尾の改行を格納します。そのため、多くの場合は改行を取り除く必要があります。
#include <stdio.h>
#include <string.h>
int main(void) {
char line[] = "hello\n";
line[strcspn(line, "\n")] = 0;
printf("[%s]\n", line);
return 0;
}戻り値の無視
scanfの戻り値を確認しないと、不正な入力が何も検出されないまま通ってしまいます。必ず確認してください。
#include <stdio.h>
int main(void) {
int n = 3;
int items = 1;
if (items != 1)
printf("bad input\n");
else
printf("ok: %d\n", n);
return 0;
}安全に組み合わせる
堅牢なパターンは、fgetsで読み取り、sscanfで解析し、結果を確認することです。
#include <stdio.h>
int main(void) {
char line[] = "123";
int n;
if (sscanf(line, "%d", &n) == 1)
printf("parsed %d\n", n);
return 0;
}クイックチェック
I/Oの落とし穴についての理解度を確認しましょう。
まとめ:よくあるI/Oの落とし穴
よくあるミスを避ける方法を学びました。
- 残った改行文字は
%cの読み取りを妨げます。先頭にスペースを付けてください - 必ず
&を付けてアドレスを渡します - doubleの読み取りには
%lfを使用します getsよりfgetsを優先し、%sには幅を指定します- 戻り値を確認し、出力をフラッシュします
よくある質問
「よくある I/O の落とし穴」レッスンは無料ですか?
はい。「よくある I/O の落とし穴」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。
「よくある I/O の落とし穴」で何を学びますか?
バッファーと改行の問題です。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「よくある I/O の落とし穴」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC Academyレッスンでコードを書いて実行できますか?
はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- printf の書式指定子
- scanf と入力
- 幅、精度、フラグ
- よくある I/O の落とし穴