【问题标题】:Issues with characters at the end of an istreamistream 结尾处的字符问题
【发布时间】:2014-09-23 01:14:32
【问题描述】:

我正在编写一个解析器,之前我在尝试解析标识符(任何对 C++ 变量名有效的)和未封闭的字符串文字(任何以 " 开头,但缺少结束 @987654322 @) 在我输入的末尾。我认为这是因为词法分析器 (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-&gt;eof() 解决了这个问题,但我的问题是:

为什么当我到达流的末尾时循环(在 cmets 中标记为 1))继续执行,为什么它只打印每次通过循环读取的最后一个字符? p>

【问题讨论】:

  • 检查输入是否成功或执行std::string s(1, c);有问题?

标签: c++ iostream


【解决方案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

}

【讨论】:

  • 啊,我明白了。所以(*input) &gt;&gt; d 没有得到任何新的东西(可能返回false),而d 没有改变,所以它显然不是我们想要打破的。对我来说似乎是一个愚蠢的疏忽,我应该以前看到过。呃,好吧。非常感谢!
  • (*input) &gt;&gt; d 返回(*input)。但是是的,因为d 没有改变,所以它永远不会中断。
猜你喜欢
  • 2023-03-15
  • 2021-09-03
  • 2015-07-25
  • 2019-01-04
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
相关资源
最近更新 更多