c ++ EOF работает слишком много раз? - PullRequest
1 голос
/ 23 ноября 2011

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

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

        while( !studentFile.eof() )
    {
        cout << "38\n";
        Student * temp = new Student();
        (*temp).input( studentFile );

        (*sdb).insert( (*temp) );           
    }

Этот кусок кода является рассматриваемым кодом. Кут >> 38 "n"; это номер строки и причина, по которой я полагаю, что она слишком часто повторяется.

Файл содержит данные только 4 учеников, но 38 появляется 5 раз, поэтому я считаю, что он зацикливается слишком много раз; Как только он получает последний бит данных, он, кажется, не регистрирует, что файл закончился, и снова зацикливается, но нет данных для ввода, поэтому мой код зависает.

Как мне это исправить? Правильна ли моя логика?

Спасибо.

Ответы [ 3 ]

3 голосов
/ 23 ноября 2011

Другие уже указали детали проблемы, которую вы заметили.

Однако вы должны понимать, что есть еще проблемы, которые вы еще не заметили.Одним из них является довольно очевидная утечка памяти.Каждая итерация цикла выполняется: Student * temp = new Student();, но вы никогда не выполняете соответствующий delete.

C ++, что делает управление памятью намного проще, чем некоторые другие языки (например, Java), для которых требуется newкаждый объект, который вы используете.В C ++ вы можете просто определить объект и использовать его:

Student temp;

temp.input(studentFile);

Это упрощает код и устраняет утечку памяти - ваш Student объект будет автоматически уничтожен в конце каждой итерации, и(концептуально) новый / другой, созданный в начале следующей итерации.

Хотя на самом деле это не ошибка как таковая , даже это все еще может быть несколько упрощено.Поскольку все, на что указывает sdb, по-видимому, имеет функцию-член insert, вы можете использовать ее как стандартный контейнер (который может на самом деле быть , хотя в любом случае это не имеет значения).Чтобы оптимизировать код, начните с написания оператора извлечения для Student:

std::istream &operator>>(std::istream &is, Student &s) {
    s.input(is);
    return is;
}

Затем вы можете просто скопировать данные из потока в коллекцию:

std::copy(std::istream_iterator<Student>(studentFile),
          std::istream_iterator<Student>(),
          std::inserter(*sdf));

Примечание.что это автоматизирует правильную обработку EOF, поэтому вам не нужно иметь дело с проблемами, с которыми вы начинали вообще (даже если вы хотели вызвать их, это было бы непросто).

3 голосов
/ 23 ноября 2011

Это потому, что флаг EOF устанавливается только после , когда вы пытаетесь прочитать и не получить данных.Таким образом, это будет идти

Test for EOF -> No EOF
Try to read one line -> Good, read first line
Test for EOF -> No EOF
Try to read one line -> Good, read second line
Test for EOF -> No EOF
Try to read one line -> Good, read third line
Test for EOF -> No EOF
Try to read one line -> Good, read fourth line
Test for EOF -> No EOF
Try to read one line -> EOF

Но к Try to read one line -> EOF вы уже находитесь в теле while на пятой итерации, поэтому вы видите, что цикл выполняется 5 раз.Поэтому вам нужно прочитать, прежде чем проверять EOF.

0 голосов
/ 23 ноября 2011

Вам необходимо проверить биты состояния потока сразу после выполнения операции с потоком. Вы не показываете код, но может показаться, что (*temp).input(studentFile) выполняет чтение из потока. Позвоните eof() (или другой проверке состояния) после выполнения чтения, но до обработки данных, которые вы (пытались) прочитать.

...