Почему моя программа считывает дополнительную запись из файла на C++?

У меня есть файл с именем 1.txt, он содержит 3 строки, каждая строка хранится в объекте класса entry следующим образом:

1* 10/12/2020 5:30 a 11:15 p 0 0 0 0 -----
2* 11/12/2020 3:45 a 5:46 a 0 0 0 0 -----
3* 12/12/2020 5:46 a 4:56 p 34.6 0 0 0 blah

и я читаю из этого файла построчно в Entry e и сохраняю каждую запись в std::vector<Enrty>records следующим образом:

void read_records(std::ifstream file, Entry e, std::vector<Entry>&records)
{
    std::string line;
        std::cout << "READING TEXT FILE CONTENTS..." << std::endl;
        while (file)
        {
            getline(file, line);
            e.read_text(tokenize(line)); // tokenize tokenizes line to tokens and e.read_text stores data from that line into e
            records.push_back(e);
            e.reset(); // this resets e back to original state
        }
}

когда я отображаю records после вызова этой функции, это дает мне дополнительную запись в таких записях, как так, Содержимое std::<Entry>records:

1* 10/12/2020 5:30 a 11:15 p 0 0 0 0 -----
2* 11/12/2020 3:45 a 5:46 a 0 0 0 0 -----
3* 12/12/2020 5:46 a 4:56 p 34.6 0 0 0 blah
3* 12/12/2020 5:46 a 4:56 p 34.6 0 0 0 blah   // I'm getting this extra entry in records when the file only contains 3 entries.

Пожалуйста, объясните, почему это происходит, и теперь, чтобы исправить это в Visual Studio C++.

while (file) по-прежнему верно, потому что файл находится в хорошем состоянии до тех пор, пока он не прочитает eof
ChrisMM 11.12.2020 03:19

@ Кевин, это, кажется, проясняет это, я думаю, это может быть проблема, но как это исправить?

Pratap Biswakarma 11.12.2020 03:27

@PratapBiswakarma, как в ответе Аюши, замените while(file) на while(getline(file, line))

Kevin 11.12.2020 03:35

Теперь это имеет смысл. А также спасибо за отличную ссылку @Kevin

Pratap Biswakarma 11.12.2020 03:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
287
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что проблема здесь может заключаться в утверждении while - это добавит дополнительную итерацию к тому, что вы ожидаете, потому что это условие становится ложным только после того, как вы прошли конец файла.

while(file) {
// ...
}

getline считывает всю строку за раз, и, поскольку EOF не является строкой, вы избегаете нежелательной дополнительной итерации. Это правильный способ приема файлового потока в этом случае использования:

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

int main() {
  std::vector<std::string> records;
  std::ifstream infile("thefile.txt");
  std::string line;
  while (std::getline(infile, line)) {
    records.push_back(line);
  }
  for (std::string e : records) {
    std::cout << e << std::endl;
  }
}

Кажется, это решило проблему, но можно ли подробнее? Например, почему while (std::getline(infile, line)) лучше, чем while(file)? Разве while (std::getline(infile, line)) не должно работать так же, как while(file)?

Pratap Biswakarma 11.12.2020 03:32

@PratapBiswakarma - разница в том, что с while (file), когда вызов getline терпит неудачу из-за достижения конца ввода, код в остальной части тела цикла выполняется; только после этого выполняется тест в while (file). Проверяя результат вызова getline, когда ввод заканчивается, код немедленно выходит из цикла.

Pete Becker 11.12.2020 15:35

@PeteBecker Понятно! Спасибо! Можете ли вы объяснить, как этот метод будет, если я читаю записи из двоичного файла?

Pratap Biswakarma 12.12.2020 02:08

Я имею в виду двоичный файл, в котором мы просто пишем двоичные данные и не используем форматирование, такое как пробел или новая строка и т. д.

Pratap Biswakarma 12.12.2020 02:40

Другие вопросы по теме