Мне известно о происхождении этого поведения, так как оно было очень хорошо объяснено в нескольких постах здесь, в SO, некоторые примечательные примеры:
Почему iostream :: eof внутри условия цикласчитается неправильным?
Использовать getline () без установки failbit
std :: getline бросать при достижении eof
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
EDIT:
while(std::getline(file, line).good()){...}
повторяет проблему.