首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ iostreams 狀態旗標完整解析:badbit、failbit、eofbit、goodbit 與狀態查詢函式

     編輯:關於C++

iostreams 以四個狀態旗標追蹤流物件健康狀態。本文系統整理旗標含義、查詢函式、清除機制與實戰錯誤處理模式。

四大狀態旗標

旗標含義觸發情境可恢復性
goodbit無錯誤(值為 0)所有操作成功正常狀態
eofbit抵達檔案結尾讀取操作遇到 EOF不可恢復(需重開檔案)
failbit邏輯錯誤/格式不符型別不匹配(如讀 int 遇到 "abc")、寬度限制**可恢復**(清除旗標+清空緩衝區)
badbit系統級/不可恢復錯誤硬碟故障、記憶體不足、緩衝區損毀不可恢復

狀態查詢成員函式

bool good() const;  // rdstate() == goodbit(最常用)
bool eof()  const;  // rdstate() & eofbit
bool fail() const;  // rdstate() & (failbit | badbit)
bool bad()  const;  // rdstate() & badbit

注意:fail() 包含 badbit,good() 僅在完全無錯誤時為 true。

狀態操作函式

iostate rdstate() const;                    // 讀取完整旗標組合
void clear(iostate state = goodbit);        // 設定旗標(預設清除所有)
void setstate(iostate state);               // 新增旗標(等同 rdstate() | state)
void exceptions(iostate except_mask);       // 設定觸發異常的旗標

實戰錯誤處理模式

模式一:迴圈讀取直到失敗

std::ifstream fin("data.txt");
int value;
while (fin >> value) {  // operator>> 回傳 stream&,隱性轉換為 bool 呼叫 good()
    process(value);
}
if (fin.eof()) {
    std::cout << "正常讀完檔案" << std::endl;
} else if (fin.fail()) {
    std::cout << "格式錯誤,清除並嘗試恢復" << std::endl;
    fin.clear();                    // 清除 failbit
    fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 跳過壞行
    // 可繼續後續讀取
} else if (fin.bad()) {
    std::cerr << "嚴重 I/O 錯誤" << std::endl;
}

模式二:啟用異常機制

std::ifstream fin("data.txt");
fin.exceptions(std::ifstream::failbit | std::ifstream::badbit);  // eofbit 不拋出

try {
    int a, b;
    fin >> a >> b;
    // 任何 fail/bad 直接拋出 ios_base::failure
} catch (const std::ios_base::failure& e) {
    std::cerr << "I/O 異常: " << e.what() << std::endl;
}

模式三:格式化輸入失敗恢復

std::istream& safe_read_int(std::istream& is, int& out) {
    if (is >> out) return is;  // 成功

    if (is.fail()) {           // 格式錯誤
        is.clear();            // 必須先清除旗標
        is.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 丟棄該行
    }
    // badbit/eofbit 不處理,讓上層決定
    return is;
}

狀態旗標位元操作

// 手動檢查特定旗標
if (fin.rdstate() & std::ios::eofbit) { ... }

// 組合旗標
std::ios::iostate err = std::ios::failbit | std::ios::badbit;
if (fin.rdstate() & err) { ... }

常見誤區

  1. while (!fin.eof()) **錯誤**:EOF 旗標在讀取**失敗後**才設定,會多執行一次迴圈。
  2. fin.clear() 不會移動檔案指標,僅重設旗標;需搭配 seekg 重新定位。
  3. operator bool()(舊標準 operator void*())回傳 !fail(),即 good() || eofbit。
  4. 輸出流同樣擁有旗標,磁碟滿、管道破裂會設定 badbit。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved