【问题标题】:How to peek at the remaining stringstream characters after using getline?使用 getline 后如何查看剩余的字符串流字符?
【发布时间】:2013-05-10 12:17:18
【问题描述】:
std::string s;
std::stringstream ss;
ss << "a=b+c" << std::endl << "d=e+f";

std::getline(ss, s, '=');   // gives me "a"
std::getline(ss, s);        /* gives me "b+c"  <- just want to peek: don't
                                                  want to change state of ss */
std::getline(ss, s, '+');   // BUT still want "b" here, not "d=e"

s 现在包含"a" 现在,我如何查看 行的剩余字符 ("b+c")?也就是说,不会导致下一个操作从下一行开始?

(我知道这是人为的例子。)

【问题讨论】:

    标签: c++ getline stringstream


    【解决方案1】:

    您可以像这样使用 istream::seekg() 恢复字符串流:

    ss.seekg(ss.beg);
    

    然后你可以再读一遍。这比创建一个新的要好,因为它可以节省内存,而且速度会快一点。

    【讨论】:

    • 谢谢 - 看起来很有希望。如果我不想从头开始seekg,我怎样才能获得字符串流的当前位置(这样我可以稍后存储该位置和seekg)?
    • 我相信你可以使用ss.cur,但我不是100%肯定。试试看:)
    • 不,不是这样。即使在使用 getline 后仍显示 1,这应该已经占用了很大一部分。
    • 那我不太确定。我不能留下来帮忙,所以尝试谷歌搜索;)
    • 您可以使用tellg()获取当前位置。在阅读之前执行此操作。然后你可以在阅读后回到它。或者,您可以使用seekg() 相对于当前位置移动。 seekg(-s.size(), std::ios_base::cur)
    【解决方案2】:

    试试:

    std::getline(ss, s, '=');                     // gives me "a"
    std::getline(ss, s);                          // gives me "b+c"
    ss.seekg(-(s.size()+1) ,std::ios_base::cur);  // Roll back
                                                  // Need to +1 becuase we throw away a character
                                                  // with std::getline() that is not in the string.
    
    std::getline(ss, s, '+');                     // gives me "b"
    

    上面的问题是std::getline() 如果在eof 之前找到'\n' 会丢弃它。但是如果它首先找到 eof 那么我们就有问题了,因为 +1 把我们放在了错误的地方。所以它适用于上面的例子,但它会在最后一行失败,除非你保证每一行都以 '\n' 终止

    所以如果你不能提供保证,我们可以使用tellg():

    std::getline(ss, s, '=');                     // gives me "a"
    std::streampos  save = ss.tellg(); 
    std::getline(ss, s);                          // gives me "b+c"
    ss.seekg(save);                               // Roll back
    
    
    std::getline(ss, s, '+');                     // gives me "b"
    

    【讨论】:

    • 是的……tellg 是唯一的方法,或者使用二进制模式。
    • @Potatoswatter:或者我们可以试试:ss.seekg(-(s.size()+ (ss?1:0)) ,std::ios_base::cur); 可能需要同时重置一些标志。但tellg() 版本也是如此。
    【解决方案3】:

    你要么需要在s之后创建一个新的stringstream

    std::getline(ss, s);        // gives me "b+c"
    std::stringstream ss2(s);
    std::getline(ss2,s, '+');   // will give b and maintain position in original ss
    

    或者使用以下代替:

    std::getline(ss, s, '+');   // will give b
    

    编辑:第二个选项改变了 ss 的状态,所以不符合你的编辑标准。

    【讨论】:

    • 怎么样而不是 peeking 在剩余的 line ("b+c"),我偷看剩余的 string ("b+c\nd=e+f" )?那会更容易吗?我希望会有一些缓冲区成员来保存所有剩余的字符。
    【解决方案4】:

    解决您的问题的一个简单方法是使用另一个std::stringstream 代替s

    std::getline(ss, s, '='); // get "a"
    std::getline(ss, s);
    
    std::stringstream ss2(s); // create a stringstream with "b+c"
    std::getline(ss2, s, '+'); // gets "b"
    

    编辑:再说一次,你为什么要读"b+c" 而不是先读"b" 然后读"c"? (我不知道你的实现)

    【讨论】:

    • 谢谢 - 我如何在 ss 中的整个剩余字符串中使用 peek
    • 当我意识到 peek 有一个字符并且可能不合适时,我删除了我的评论。不过不确定。
    • 怎么样而不是 peeking 在剩余的 line ("b+c"),我偷看剩余的 string ("b+c\nd=e+f" )?那会更容易吗?我希望会有一些缓冲区成员来保存所有剩余的字符。
    • 我用 ideone 做了一些测试,我的结论是从 std::stringstream 偷看会从剩余的缓冲区偷看。不幸的是,你只能得到一个字符,所以这个解决方案并不是最好的。事实上,这很糟糕;_;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    相关资源
    最近更新 更多