从 ifstream 读取时出现无关的空行
在我的程序中,我已将标准输出重定向到打印到文件“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.)
In my program, I've redirected stdout to print to a file 'console.txt'. A function writes to that file like this:
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;
}
I have a function that reads from that file that looks like this:
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);
}
Often, console.txt is empty when readLogFile
is called. I would expect that the while(!log.eof())
loop would never execute in that case, but it does. There is always at least one extraneous blank line in the file, sometimes two, and when input is read from the file, the input line is sandwiched between two blank lines. After a few calls to this function, the while(!log.eof())
loop then goes into an infinite loop pulling blank lines from the file. A typical runthrough of the program looks like this:
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)
Can anyone see what I'm doing wrong here?
EDIT: As Amardeep suggested, I changed the while(!log.eof())
loop to a do{...}while(!log.fail);
loop. This fixed the infinite loop problem, but not the extraneous lines. The program behaves as before, except where it once went into the infinite loop, it now reads nothing but blank lines where it should read input, like this:
str:
str:
str:
str:
(etc.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在尝试读取之前,不会设置 eof() 状态。您应该更改读取循环以执行 getline(),然后检查 failed() 状态,而不是依赖 eof(),后者不涵盖尝试读取文件时可能出错的广泛情况。
eof() status is not set until you attempt a read. You should change your read loop to do the getline() then check the fail() status instead of relying on eof(), which doesn't cover the breadth of things that can go wrong trying to read the file.
用于读取文件的标准反模式。
试试这个:
这有效,因为 getline() 方法返回对流的引用。
当在布尔上下文中使用流时,它会转换为布尔值(对于迂腐的人来说不是这样,但对于初学者来说也是如此)。如果读取后流仍处于良好状态(即读取有效),则将其转换为 true。如果流处于错误状态(即读取失败),则将其转换为 false。因此,如果读取有效,则进入循环。如果读取失败(因为可能读取了 EOL),则不会进入循环。
请注意,您的版本失败,因为您在读取(getline())后没有测试eof()。这是因为最后一次好的读取读取了 EOF 之前的所有字符。但这意味着 eof 标志没有设置。直到您尝试实际读取超过 EOF 的内容(仅当您在上次读取所有其他字符后读取某些内容时才会发生这种情况),EOF 标志才会被设置。
附言。
有一个自由函数可以从流读取到字符串中。
Standard anti patter for reading a file.
try this:
This works because the getline() method returns a reference to the stream.
When a stream is used in a boolean context it gets converted into a bool (for the pedantic not really but for the beginner as good as). If the stream is still in a good state after the read (ie the read worked) then it is converted to true. If the stream is in a bad state (ie the read failed) then it is converted to false. Therefore if the read worked the loop is entered. If the read failed (because maybe EOL is read) then the loop is not entered.
Note your version failed because you did not test the eof() after the read (getline()). The is because the last good read reads all the characters upto the EOF. But this means the eof flag is not set. It is not until you try to actually read past the EOF (this only happens if you read something after the last read read all the other characters) that the EOF flag is set.
PS.
There is a free function that reads from a stream into a string.