2015-11-07 7 views
4

Я пытаюсь сделать мою программу прочитанной в данных из файла данных (.dat) (который на самом деле является только текстовым файлом). Поэтому, конечно, я использую условие цикла while(!file.eof()), но это никогда не возвращается. Вот моя функция:Почему eof() никогда не возвращается?

void Table::readIn(const char finput[]){ 
    std::ifstream file; 

    file.open(finput); 

    if (!file.is_open()) 
    { 
     std::cout << "Cannot open " << finput << std::endl; 
     return; 
    } 
    char key[100]; 
    file.get(key, 99, '\n'); 
    while (!file.eof()) 
    { 
     stock * item = new stock; 
     item->setTick(key); 
     file.get(key, 99, '\n'); 
     item->setName(key); 
     file.get(key, 99, '\n'); 
     item->setValue(atof(key)); 
     file.get(key, 99, '\n'); 
     item->setDate(key); 
     file.get(key, 99, '\n'); 
     item->setYearReturn(atof(key)); 
     file.get(key, 99, '\n'); 
     addStock(item); 
    } 
} 

и вот что в моем файле данных:

TSLA 
Tesla Motors, Inc. 
30160000000 
November 6, 2015 
13.1 

Я хотел бы дать вам, ребята, больше информации, но тот факт, что программа зацикливается через петлю while (!file.eof()) в течение неопределенного времени все, что я знаю об этой проблеме.

Редактировать: Я провел это через отладчик с точкой разрыва в каждой строке цикла while. Я обнаружил, что первый вызов get() (до цикла while) устанавливает key в правильное значение, но каждый вызов get() после этого устанавливает key в "". Я предполагаю, что это потому, что программа никогда не читает первый символ '\n' в файле. Вы, ребята, знаете, как это исправить?

Редактировать 2: Этот вопрос отличается от: Why is iostream::eof inside a loop condition considered wrong?, потому что я должен читать более чем в одной строке каждый раз, когда пробегу через цикл while.

+0

Для начала флаги 'eofbit' не установлены до тех пор, пока вы не попытаетесь прочитать из-за конца файла, что означает, что ваш цикл не будет работать так, как вы ожидаете. Чтобы продолжить, попробуйте выполнить код по строкам в отладчике, ваше чтение не будет работать так, как вы ожидаете. –

+1

@JoachimPileborg Итак, первый вызов 'get()' (до цикла while) устанавливает 'ключ' в правильное значение, но каждый вызов' get() 'после этого устанавливает' key' в "". Я предполагаю, что это потому, что программа никогда не читает первый символ «\ n» в файле. Вы знаете, как я это исправим? – LarryK

+0

Простейшее решение? Используйте строки 'std :: string' и' std :: getline' для чтения строк. –

ответ

0

Вам придется заменить эту строку while (!file.eof()) по

while (true) 
    { 
     /*code*/ 
     file.get(key, 99, '\n'); 
     if (file.eof()) { break; } // and similarly for other usages where you are reading the stream 
     /*code*/ 
    } 

Edit: Ok. Похоже, ваша проблема лежит здесь, цитата из documentation of ifstream::get:

the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted

Таким образом, после каждого вызова получить ваш искать указатель все еще указывает на deliminator. Поэтому после первого вызова get продолжает сталкиваться с символом новой строки и, следовательно, возвращает вам пустые данные. Вы можете либо добавить фиктивное чтение, чтобы использовать этот разделитель, либо даже лучше использовать getline

+1

Это не решило проблему. – LarryK

+0

@ LarryK вы можете обновить код с тем, что вы изменили. – bashrc

+0

Почему вы ожидаете, что это будет работать лучше, чем у него? Файл не собирается переходить из состояния eof в состояние non-eof, если он не очистит флаг ошибки. –

3

Проблема с вашим использованием std::istream::get заключается в том, что он не использует разделитель. Он будет работать нормально для первого вызова, но затем следующий вызов немедленно увидит новую строку, оставшуюся от предыдущего вызова, и не прочитает ничего.

Если вы хотите прочитать строки, используйте либо std::istream::getline (если вы продолжаете использовать массивы символов) или std::getline с std::string, что и я рекомендую.


Вы также не нужны явные eof чеки, а не полагаться на то, что все функции возвращает (ссылка) поток и что потоки могут быть used directly in conditions, так что, например,

if (!std::getline(...)) 
    // end of file or error 
+1

Я получаю 'Ошибка: getline() не определено' – LarryK

+1

Предполагая, что код, который у меня был до Edit 3, я смог исправить это, заменив все мои вызовы' file.get() 'на вызовы' file.getline'. Вы должны уточнить свой ответ, чтобы указать это (поскольку 'getline()' отбрасывает разделитель из входного потока, а 'get()' is not). – LarryK

+0

@LarryK: 'std :: getline' находится в' '. Вы должны включить этот заголовок, чтобы использовать его. –