Думайте об этом как о расширенном комментарии к уже превосходному ответу Наваза.
Относительно вашего первого варианта,
while (fs.good()) {
std::string line;
std::getline(fs, line);
...
У этого есть многократные проблемы. Проблема № 1 в том, что условие while
находится не в том месте и является излишним. Это не в том месте, потому что fs.good()
указывает, было ли последнее действие, выполненное над файлом, нормальным. Некоторое время должно быть в отношении предстоящих действий, а не предыдущих. Нет никакого способа узнать, будет ли предстоящее действие над файлом в порядке. Какие предстоящие действия? fs.good()
не читает ваш код, чтобы увидеть, что это за предстоящее действие.
Проблема номер два в том, что вы игнорируете статус возврата с std::getline()
. Это нормально, если вы сразу проверите статус с помощью fs.good()
. Итак, исправляя это немного,
while (true) {
std::string line;
if (std::getline(fs, line)) {
...
}
else {
break;
}
}
В качестве альтернативы вы можете сделать if (! std::getline(fs, line)) { break; }
, но теперь у вас есть break
в середине цикла. Yech. Гораздо лучше сделать условия выхода частью самого оператора цикла, если это вообще возможно.
Сравните это с
std::string line;
while (std::getline(fs, line)) {
...
}
Это стандартная идиома для чтения строк из файла. Очень похожая идиома существует в C. Эта идиома очень старая, очень широко используется и очень широко рассматривается как правильный способ чтения строк из файла.
Что, если вы приехали из магазина, где запрещены условные предложения с побочными эффектами? (Существует множество стандартов программирования, которые делают именно это.) Есть способ обойти это, не прибегая к разрыву в середине цикла:
std::string line;
for (std::getline(fs, line); fs.good(); std::getline(fs, line)) {
...
}
Не такой уродливый, как подход с перерывом, но большинство согласится, что это не так красиво, как стандартная идиома.
Я рекомендую использовать стандартную идиому, если какой-то стандартный идиот не запретил ее использование.
Добавление
Относительно for (std::getline(fs, line); fs.good(); std::getline(fs, line))
: Это ужасно по двум причинам. Одним из них является тот очевидный кусок реплицированного кода.
Менее очевидно, что вызов getline
, а затем good
нарушает атомарность. Что, если какой-то другой поток также читает из файла? Это не так уж важно сейчас, потому что ввод / вывод C ++ в настоящее время не является потокобезопасным. Это будет в предстоящем C ++ 11. Нарушение атомарности только для того, чтобы исполнители стандартов были довольны, - это путь к катастрофе.