从ifstream读取时无关的空行

时间:2010-06-24 18:57:41

标签: c++ infinite-loop ifstream

在我的程序中,我已将stdout重定向到打印到'console.txt'文件。函数会像这样写入该文件:

void printToConsole(const std::string& text, const TCODColor& fc, const TCODColor& bc)
    {
        // write the string
        cout << text << "@";

        // write the two color values
        cout << static_cast<int>(fc.r) << " "
             << static_cast<int>(fc.g) << " " 
             << static_cast<int>(fc.b) << " "
             << static_cast<int>(bc.r) << " "
             << static_cast<int>(bc.g) << " " 
             << static_cast<int>(bc.b) << " " << endl;
    }

我有一个从该文件中读取的函数,如下所示:

   void Console::readLogFile()
   {
        ifstream log("console.txt", ifstream::in);
        if(!log.is_open())
        {
            cerr << "ERROR: console.txt not found!" << endl;
            return;
        }

        // read new input into the stack
        char str[256];
        while(!log.eof())
        {
            log.getline(str, 256);
            cerr << "str: " << str << endl;
            stk.push(static_cast<string>(str));
            // stk is a std::stack<std::string> member of the class this function
            // belongs to.
        }
        cerr << endl;

        /* Do some stuff with str and stk here */

        log.close();
        clearLogFile();
    }

    void Console::clearLogFile()
    {
        FILE* log;
        log = fopen("console.txt", "w");
        fclose(log);
    }

通常,调用readLogFile时console.txt为空。我希望在这种情况下while(!log.eof())循环永远不会执行,但确实如此。文件中始终至少有一个无关的空白行,有时是两行,当从文件中读取输入时,输入行夹在两个空行之间。在调用此函数后,while(!log.eof())循环进入无限循环,从文件中拉出空行。该程序的典型代表如下:

str: 

str: Player moved.@191 191 191 0 0 0
str: 

str: 
str: Player moved.@191 191 191 0 0 0 
str: 

str: // there should be a 'Player moved.' line in here
str:

str: // here as well
str:

str: // also here
str:

str: 
str: Player moved.@191 191 191 0 0 0 
str: 

str:
str:
str:
str:
str:
str:
(onto infinite loop)

谁能看到我在这里做错了什么?

编辑:正如Amardeep建议的那样,我将while(!log.eof())循环更改为do{...}while(!log.fail);循环。这解决了无限循环问题,但没有解决外来线。该程序的行为与以前一样,除非它曾经进入无限循环,它现在只读取空白行,它应该读取输入,如下所示:

str:

str:

str:

str: 
(etc.)

2 个答案:

答案 0 :(得分:1)

在尝试读取之前,不会设置

eof()状态。您应该更改您的读取循环以执行getline()然后检查fail()状态而不是依赖于eof(),这不包括尝试读取文件时可能出错的广度。

答案 1 :(得分:1)

用于读取文件的标准反模式。

    while(!log.eof())
    {
        log.getline(str, 256);
        cerr << "str: " << str << endl;
        stk.push(static_cast<string>(str));
        // stk is a std::stack<std::string> member of the class this function
        // belongs to.
    }

试试这个:

    while(log.getline(str, 256))
    {
        cerr << "str: " << str << endl;
        stk.push(string(str));
    }

这是有效的,因为getline()方法返回对流的引用。

当一个流在布尔上下文中使用时,它会被转换为bool(对于迂腐而言不是真的,但对于初学者来说就好了)。如果在读取之后流(即读取工作)仍处于良好状态,则将其转换为true。如果流处于错误状态(即读取失败),则将其转换为false。因此,如果读取工作,则进入循环。如果读取失败(因为可能读取了EOL),则不输入循环。

请注意您的版本失败,因为您在读取(getline())后未测试eof()。这是因为最后一次好的读取读取了EOF之前的所有字符。但这意味着未设置eof标志。直到您尝试实际读取EOF(只有在最后一次读取后读取所有其他字符后才会读到的内容)才能读取EOF标志。

PS。 有一个自由函数可以从流中读取字符串。

std::string line;
std::getline(log, line);