0Pricing
C Academy · レッスン

よくある 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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. printf の書式指定子
  2. scanf と入力
  3. 幅、精度、フラグ
  4. よくある I/O の落とし穴
← C Academyに戻る