ifstream не читает символ EOF - PullRequest
1 голос
/ 28 июня 2011

Я создаю программу (на C ++), которая принимает файл ASCII и считывает несколько значений из каждой строки, пока не достигнет конца файла.Я использую ifstream для чтения файла, и у меня никогда не возникало проблем с его остановкой при использовании метода ifstream.eof().Однако на этот раз, несмотря на то, что он обнаружил символ eof в моем тестовом примере, когда я анализировал другие мои файлы, это бесконечный цикл, потому что он никогда не находит символ eof.Это проблема кодирования или проблема с моими файлами?

string line = "";
unsigned long pos = 0;
ifstream curfile(input.c_str());
getline(curfile, line);
int linenumber = 0;
cout<<"About to try to read the file"<<endl;
if (!curfile.good())
    cout<<"Bad file read"<<endl;
while (!curfile.eof())
{

    cout<<"Getting line "<<linenumber<<endl;
    linenumber++;
    pos = line.find_first_of(' ');
    line = line.substr(pos+1, line.size()-1);
    pos = line.find_first_of(' ');
    current.push_back(atof(line.substr(0, pos).c_str()));
    for (int i = 0; i<4; i++)
    {
        pos = line.find_first_of(' ');
        line = line.substr(pos+1, line.size()-1);
    }
    pos = line.find_first_of(' ');
    dx.push_back(atof(line.substr(0, pos).c_str()));
    pos = line.find_first_of(' ');
    line = line.substr(pos+1, line.size()-1);
    pos = line.find_first_of(' ');
    dy.push_back(atof(line.substr(0, pos).c_str()));
    getline(curfile, line);
}

РЕДАКТИРОВАТЬ: Когда я впервые запускаю цикл, currentfile.good () возвращает false ... что я делаю, что заставляет его возвращатьчто?

Ответы [ 4 ]

4 голосов
/ 28 июня 2011

Во-первых, во-первых, вы не должны так проверять.eof() не возвращает true до после неудачного чтения.Но вы можете сделать лучше (и проще)!

проверить состояние потока с помощью неявного преобразования в void*, которое можно использовать в bool контексте .Поскольку большинство операций чтения в потоках возвращают ссылку на поток, вы можете написать очень полезный код, подобный следующему:

std::string line;
while(std::getline(currentfile, line)) {
    // process line
}

В основном то, что он делает, говорит: «хотя я мог бы успешно извлечь строку изcurrentfile, сделайте следующее ", это то, что вы действительно хотели сказать; -);

Как я уже говорил, это относится к большинству потоковых операций, поэтому вы можете делать такие вещи:

int x;
std::string y;
if(std::cin >> x >> y) {
    // successfully read an integer and a string from cin!
}

РЕДАКТИРОВАТЬ : Я бы переписал ваш код следующим образом:

string line;
unsigned long pos = 0;
int linenumber = 0;

ifstream curfile(input.c_str());

std::cout << "About to try to read the file" << std::endl;
while (std::getline(curfile, line)) {

    std::cout << "Getting line " << linenumber << std::endl;
    linenumber++;

    // do the rest of the work with line
}
2 голосов
/ 28 июня 2011

Ваш первый вызов getline вызывает один из битов сбоя объекта ifstream.Вот почему, если вы проверяете бит ошибки с помощью ios::good(), вы никогда не входите в цикл чтения.Я бы проверил, чтобы узнать значение line ... возможно, оно пустое, что означает, что у вас есть другая проблема при чтении файла, например, проблемы с разрешениями и т. Д.

2 голосов
/ 28 июня 2011

Не делайте так.

EOF - не единственное, с чем вы столкнетесь во время чтения.Вы можете получить кучу ошибок, поэтому лучше всего просто протестировать сам поток:

while(currentfile)
{
    // read somehow
}

Если вы читаете строки, тогда самый простой способ:

std::string line;
while(std::getline(currentfile, line))
{
    // use line
}
1 голос
/ 29 июня 2011

Проблема здесь:

if (!curfile.good())
    cout<<"Bad file read"<<endl;   // OK you print bad.
while (!curfile.eof())             // But the loop is still entered.
                                   // Another reason to **NEVER** to use 
                                   // while (file.eof()) // as bad does not mean eof
                                                         // though eof is bad

Попробуйте это:

void readFile(std::istream& str)
{   
    std::string     line;
    while(std::getline(str, line))
    {
        std::stringstream   lineStream(line);
        std::string         ignoreWord;
        int                 number[3];

        lineStream >> ignoreWord   // reads one space seporated word
                   >> number[0]    // reads a number
                   >> ignoreWord >> ignoreWord >> ignoreWords  // reads three words 
                   >> number[1]    // reads a number
                   >> number[2];   // reads a number

        current.push_back(number[0]);
        dx.push_back(number[1]);
        dy.push_back(number[2]);
    }   
}   
...