0Pricing
C++ Academy · レッスン

エラー処理と状態

ストリームの状態を確認します

「エラー処理と状態」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

ストリームの状態ビット

すべてのストリームは、状態フラグによって自身の状態を追跡します。

  • goodbit:すべて正常です。
  • eofbit:ファイル末尾に到達しました。
  • failbit:論理エラー(形式が不正)です。
  • badbit:重大なI/Oエラーです。
#include <iostream>
#include <fstream>

int main() {
    std::ifstream in("missing_98765.txt");
    std::cout << std::boolalpha << "good: " << in.good() << '\n';
    return 0;
}

ストリームをテストする

ストリームはboolに変換できます。使用可能な場合はtrueになります。if (!in)と書くと、失敗を簡潔に検出できます。

#include <iostream>
#include <fstream>

int main() {
    std::ifstream in("nope_55555.txt");
    if (!in) std::cout << "stream not usable\n";
    else std::cout << "ok\n";
    return 0;
}

good、eof、fail、bad

各フラグには、good()、eof()、fail()、bad()という確認用メソッドがあります。

#include <iostream>
#include <sstream>

int main() {
    std::istringstream s("abc");
    int x;
    s >> x; // fails: not a number
    std::cout << std::boolalpha;
    std::cout << "fail: " << s.fail() << '\n';
    std::cout << "bad: " << s.bad() << '\n';
    return 0;
}

抽出の失敗

>>で期待した型を解析できない場合、failbitが設定され、対象の値は変更されません。

#include <iostream>
#include <sstream>

int main() {
    std::istringstream s("hello");
    int n = -1;
    if (!(s >> n)) std::cout << "could not read an int, n stays " << n << '\n';
    return 0;
}

状態をクリアする

失敗フラグが設定されると、clear()を呼び出してリセットするまで、ストリームは使用できない状態のままです。

#include <iostream>
#include <sstream>

int main() {
    std::istringstream s("x 42");
    int n;
    s >> n;          // fails on 'x'
    s.clear();       // reset state
    std::string word;
    s >> word;       // now reads 'x'
    std::cout << "recovered: " << word << '\n';
    return 0;
}

不正な入力を無視する

clear()の後、再試行する前にignore()を使って問題のある文字を破棄します。

#include <iostream>
#include <sstream>
#include <limits>

int main() {
    std::istringstream s("bad 100");
    int n;
    while (!(s >> n)) {
        s.clear();
        s.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
    }
    std::cout << "read " << n << '\n';
    return 0;
}

EOFとエラーを区別する

読み取りループが終了した後、正常なeof()による終了なのか、実際のbad()エラーなのかを確認します。

#include <iostream>
#include <sstream>

int main() {
    std::istringstream s("1 2 3");
    int x;
    while (s >> x) {}
    std::cout << std::boolalpha << "reached eof: " << s.eof() << '\n';
    std::cout << "hardware error: " << s.bad() << '\n';
    return 0;
}

オープン直後に確認する

ファイルを開いた直後には必ずストリームを確認し、存在しないパスや読み取れないパスを早期に検出してください。

#include <iostream>
#include <fstream>

int main() {
    std::ifstream in("absent_11111.txt");
    if (!in.is_open()) {
        std::cout << "open failed, aborting\n";
        return 1;
    }
    std::cout << "never reached\n";
    return 0;
}

例外を有効にする

exceptions()を使うと、エラー発生時にストリームが例外をスローするように設定できます。これにより、暗黙に失敗する処理を捕捉可能なstd::ios_base::failureに変えられます。

#include <iostream>
#include <fstream>

int main() {
    std::ifstream in;
    in.exceptions(std::ios::failbit);
    try {
        in.open("ghost_22222.txt");
    } catch (const std::exception& e) {
        std::cout << "caught open failure\n";
    }
    return 0;
}

読み取り数を検証する

バイナリreadの後、gcount()は実際に読み取ったバイト数を返します。これにより、読み取り不足を検出できます。

#include <iostream>
#include <fstream>

int main() {
    int v = 9;
    std::ofstream("g.bin", std::ios::binary).write(reinterpret_cast<const char*>(&v), sizeof(v));
    int out;
    std::ifstream in("g.bin", std::ios::binary);
    in.read(reinterpret_cast<char*>(&out), sizeof(out));
    std::cout << "read " << in.gcount() << " bytes\n";
    return 0;
}

堅牢な読み取りループ

これまでの方法を組み合わせます。ループ内でストリームをテストし、終了後に正常終了とエラーを区別します。

#include <iostream>
#include <sstream>

int main() {
    std::istringstream s("5 10 15");
    int total = 0, x;
    while (s >> x) total += x;
    if (s.eof()) std::cout << "sum = " << total << " (clean)\n";
    else std::cout << "error during read\n";
    return 0;
}

クイックチェック

ストリームの状態について理解度を確認しましょう。

まとめ

ストリームのエラー処理について、次のことを学びました。

  • 状態フラグはgood/eof/fail/badで、各メソッドを使うか、ストリームをboolとしてテストして確認します
  • clear()は状態をリセットし、ignore()は不正な入力を破棄します
  • 正常なeof()と実際のエラーを区別します。exceptions()で例外をスローでき、gcount()でバイナリ読み取りを検証できます

次のコースでは、<random>を使って乱数を生成します。

よくある質問

「エラー処理と状態」レッスンは無料ですか?

はい。「エラー処理と状態」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「エラー処理と状態」で何を学びますか?

ストリームの状態を確認します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「エラー処理と状態」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. ifstreamによるファイル読み込み
  2. ofstreamによるファイル書き込み
  3. バイナリファイルI/O
  4. エラー処理と状態
← C++ Academyに戻る