0

在我的程序中,我已将标准输出重定向到打印到文件“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);
    }

通常,console.txt 在readLogFile被调用时是空的。我希望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.)
4

2 回答 2

1

在您尝试读取之前,不会设置 eof() 状态。您应该将读取循环更改为执行 getline(),然后检查 fail() 状态,而不是依赖 eof(),这并不能涵盖尝试读取文件时可能出错的范围。

于 2010-06-24T19:09:36.563 回答
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() 方法返回对流的引用。

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

请注意,您的版本失败是因为您在读取 ​​(getline()) 之后没有测试 eof()。这是因为最后一次良好读取读取了 EOF 之前的所有字符。但这意味着没有设置 eof 标志。直到您尝试实际读取 EOF 之后(仅当您在最后一次读取读取所有其他字符之后读取某些内容时才会发生这种情况)才会设置 EOF 标志。

PS。有一个从流中读入字符串的自由函数。

std::string line;
std::getline(log, line);
于 2010-06-24T20:42:13.923 回答