簡體   English   中英

getline設置failbit以及eof

[英]getline setting failbit along with eof

我知道這種行為的起源,因為它在SO中的多個帖子中得到了很好的解釋,一些值得注意的例子是:

為什么循環條件中的iostream :: eof被認為是錯誤的?

使用getline()而不設置failbit

當它擊中eof時std :: getline投擲

C ++ istream EOF不保證failbit?

它也包含在std::getline標准中

3)如果由於某種原因沒有提取任何字符(甚至沒有丟棄的分隔符),getline設置failbit並返回。

我的問題是如何處理這種行為,你希望你的流為所有情況捕獲一個failbit異常,除了由於到達eof而導致的最后一行空文件。 有什么明顯的東西讓我失蹤嗎?

MWE:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>


void f(const std::string & file_name, char comment) {

std::ifstream file(file_name);
file.exceptions(file.failbit);
    try {
          std::string line;

          while (std::getline(file, line).good()) {
          // empty getline sets failbit throwing an exception
            if ((line[0] != comment) && (line.size() != 0)) {
                std::stringstream ss(line);
                // do stuff
            }
        }
    }

    catch (const std::ios_base::failure& e) {
        std::cerr << "Caught an ios_base::failure.\n"
        << "Explanatory string: " << e.what() << '\n'
        << "Error code: " << e.code() << '\n';

        }
}


int main() {

    f("example.txt", '#');
}

其中example.txt是制表符分隔的文件,其最后一行只是\\n char:

# This is a text file meant for testing
0   9
1   8
2   7

編輯:

while(std::getline(file, line).good()){...}復制問題。

編輯:我誤解了OP,請參閱David的上述答案。 此答案用於檢查文件是否具有終止換行符。

while (getline)循環結束while (getline) ,檢查file.eof()

假設你剛剛為文件的最后一行做了std::getline()

  • 如果后面有\\n ,那么std::getline()已經讀取了分隔符並且沒有設置eofbit (在這種情況下,下一個std::getline()將設置eofbit 。)

  • 然而,如果它之后沒有\\n ,那么std::getline()已經讀取了EOF並且確實設置了eofbit

在這兩種情況下,下一個std::getline()將觸發failbit並輸入您的異常處理程序。

PS:行if ((line[0] != comment) && (line.size() != 0)) {如果line為空則為UB。 條件的順序需要顛倒。

避免設置failbit另一種方法是簡單地重構if測試以檢測空行的讀取。 由於這是你在這種情況下的最后一行,你可以簡單地return以避免拋出錯誤,例如:

    std::ifstream file (file_name);
    file.exceptions (file.failbit);
    try {
        std::string line;

        while (std::getline(file, line)) {
            // detect empty line and return
            if (line.size() == 0)
                return;
            if (line[0] != comment) {
                std::stringstream ss(line);
                // do stuff
            }
        }
    }
    ...

另一種方法是檢查eofbit是否設置為catch 如果設置了eofbit - 讀取成功完成。 例如

    catch (const std::ios_base::failure& e) {
        if (!file.eof())
            std::cerr << "Caught an ios_base::failure.\n"
            << "Explanatory string: " << e.what() << '\n'
            << "Error code: " /* << e.code() */ << '\n';
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM