Получение failbit при чтении из txt файла, заканчивающегося новой строкой - PullRequest
2 голосов
/ 21 марта 2020

Я пытаюсь прочитать из простого текстового файла в указанном c порядке. В этом случае я читаю int, затем string, затем double. Вот текстовый файл:

54321 Television
250
46782 Laptop
1200
23461 Ipad
500
87612 Playstation
400

Вот функция, которую я использую для проверки файла на наличие ошибок (неправильные типы или неправильное имя файла):

void Electronics::ReadData(istream& electronicsFile)
{
    int barcode;
    string name;
    double price;

    while (electronicsFile.good()) {
        electronicsFile >> barcode >> name >> price;
    }
    if (electronicsFile.fail()) {
        throw runtime_error("Error reading electronics file");
    }
}

Проблема, с которой я столкнулся В результате мой текстовый файл заканчивается новой строкой, в результате чего моя программа выдает ошибку времени выполнения каждый раз, когда читает файл до конца. Как я могу прочитать весь файл, чтобы он не возвращал сбой?

Ответы [ 2 ]

0 голосов
/ 21 марта 2020

Проблема, с которой я сталкиваюсь, заключается в том, что мой текстовый файл заканчивается новой строкой

Это не проблема. Когда вы пытаетесь читать элементы как можно дольше (и для этого ваш код должен быть while (electronicsFile >> barcode >> name >> price);), вы будете сталкиваться с установленным битом сбоя, потому что это то, что вам мешает чтение с electronicsFile до бесконечности . Вы всегда можете clear() поток, хотя.

Если вы действительно хотите проверить, является ли файл некорректным во время чтения, вы можете проверить каждый оператор чтения отдельно плюс * проверка .eof(), а не .fail():

int main() {
   std::fstream electronicsFile {"logi.txt"};

   int barcode = 0;
   std::string name;
   double price = 0.0;

   try {
       for (auto c = electronicsFile.get(); !electronicsFile.eof();) {
           electronicsFile.putback(c);
           const auto message = "Error reading electronics file";
           if (!(electronicsFile >> barcode)) throw std::runtime_error(message);
           if (!(electronicsFile >> name)) throw std::runtime_error(message);
           if (!(electronicsFile >> price)) throw std::runtime_error(message);
       }
   } catch (const std::runtime_error& ex) {
       std::cerr << ex.what();
   }
}

Это будет правильно проходить через процесс выполнения для правильных данных, хранящихся в файле, и будет прервано, а также напечатает сообщение об исключении в случае неверных данных файла.

0 голосов
/ 21 марта 2020

Во-первых, вашим условием l oop должна быть сама операция ввода.

while (electronicsFile >> barcode >> name >> price) {
  ; // empty body
}

После этого electronicsFile.fail() всегда будет истинным после завершения l oop. Выход l oop возможен только в том случае, если было недопустимое чтение или оно достигло конца файла.

Таким образом, вы должны изменить свое условие на бросать только в том случае, если оно не достигло конца файл.

if (!electronicsFile.eof()) {
  throw runtime_error("Error reading electronics file");
}
...