我正在编写一个解析器,当我尝试解析标识符(对C ++变量名有效的任何内容)和未关闭的字符串文字(以"
开头的任何内容时,我以前遇到了麻烦,但是错过了结束"
)在我的输入结束时。我认为这是因为词法分析器(TokenStream
)在这些情况下使用std::noskipws
并按字符构建标记字符。这是我认为我已经缩小了问题的范围(仅针对两种情况中的一种显示,因为另一种情况非常相似):
std::string TokenStream::get()
{
char c;
(*input) >> c; // input is of type istream*
// other cases...
if (c == '"')
{
std::string s = stringFromChar(c); // just makes a string from the char.
char d;
while (true) // 1)
{
(*input) >> std::noskipws >> d;
std::cout << d; // 2)
if (d == '"')
{
s += d;
(*input) >> std::skipws;
break;
}
s += d;
}
return s;
}
// other cases...
}
请注意,此函数应该只是以类似流的方式从输入生成标记。现在,如果我输入文字(如asdf
)或未关闭的字符串(如"asdf
),则程序将挂起,标记为2)
的行将只输出最后一个字符输入(在我的例子中,f
)一遍又一遍地重复。
我使用input->eof()
检查解决了这个问题,但我的问题是:
为什么循环(在评论中标记为1)
)在我到达流的末尾时继续执行,为什么它只是打印每次循环读取的最后一个字符?
答案 0 :(得分:1)
让我们逐行查看有问题的循环
while (true) // 1)
除非遇到休息,否则会循环播放
{
(*input) >> std::noskipws >> d;
读一个角色。如果无法读取字符,d
可能会保持不变。
std::cout << d; // 2)
打印刚读过的字符
if (d == '"')
不,最后一个字符不是"
(在问题中指定)
{
s += d;
(*input) >> std::skipws;
break;
}
s += d;
}
因此,永远不会遇到中断,并且最后一个字符以无限循环打印。
修复:总是使用一段时间看起来像输入:
char ch;
while (input >> ch) {
// ch contains a new letter, deal with it
}