istream末尾的字符问题

Issues with characters at the end of an istream

本文关键字:字符 问题 istream      更新时间:2023-10-16

我正在编写一个解析器,以前当我试图在输入结束时解析标识符(任何对C++变量名有效的东西)和未闭合的字符串文字(任何以"开头但缺少闭合的"的东西)时,我遇到了麻烦。我认为这是因为lexer(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))一直在执行,为什么每次循环都只打印读取的最后一个字符

让我们逐行查看有问题的循环

    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
}