basic_istream :: seekg()似乎无法正常工作

时间:2018-05-22 09:56:01

标签: c++ istream

以下程序应输出如下内容:

Begin found
space found
End found

但事实并非如此。

#include <sstream>
#include <istream>
#include <string>
#include <cctype>
#include <iostream>

bool Match(std::istream& stream, const std::string& str)
{
    std::istream::pos_type cursorPos = stream.tellg();

    std::string readStr(str.size(),'\0');

    stream.read(&readStr[0],str.size());
    stream.seekg(cursorPos);
    if(std::size_t(stream.gcount()) < str.size() || readStr != str)
        return false;

    return true;
}

bool Take(std::istream& stream, const std::string& str)
{
    if(!Match(stream,str))
        return false;

    for(std::string::size_type i = 0; i < str.size(); ++i)
        stream.get();

    return true;
}

int main()
{
    std::string testFile = "BEGIN END";

    std::stringstream ss(testFile);
    auto c = ss.peek();
    while(!ss.eof() && ss.tellg() != -1)
    {
        if(Take(ss,"BEGIN"))
            std::cout << "Begin found" << std::endl;
        else if(Take(ss,"END"))
            std::cout << "End found" << std::endl;
        else if(std::isspace(c))
        {
            ss.get();
            std::cout << "space found" << std::endl;
        }
        else
            std::cout << "Something else found" << std::endl;
    }

    return 0;
}

我注意到它输出

Begin found
Something else found

当我单步执行调试器时,看起来当我到达空格字符时,它首先检查是否有Match()"BEGIN",它通过{{1}检索光标位置},其值为tellg()。但是当它预期失败然后用5检查Match()时,光标位于"END",即结束。

因此-1调用似乎无效,或者我没有正确使用它。

1 个答案:

答案 0 :(得分:1)

当你的程序进入主循环时,它首先用输入流和“BEGIN”作为参数执行take。匹配返回true,并且get被调用5次,因为它是BEGIN的长度。

然后它再次进入循环。它再次调用匹配。此时pos位于5,BEGIN的长度。它试图读取len(BEGIN)字符,但是你的字符串流没有那么多字符,因此它将循环保留在-1位置,并设置错误标记。

由于流是错误状态,因此以下搜索调用没有预期的效果,解释了程序的行为。