为何StringStream使用noskipws提取字符后,后续字符串提取异常?
问题分析:stringstream提取字符后后续字符串提取失效的原因
预期输出Thisisatest.,但实际仅输出Thi。程序先通过noskipws从stringstream中提取前3个字符,后续尝试提取剩余字符串却失效,移除noskipws后问题解决,具体原因如下:
原代码
#include <sstream> #include <iostream> using namespace std; int main() { string test = "This is just a test."; stringstream ss(test); char c; int i = 0; while (ss >> noskipws >> c) { int ascii = (int)c; if (i > 2) { // break after writing 2 characters break; } i++; cout << c; } // continue using the same sstring, // but with a string instead of a char // notice that there is no noskipws here string s; while(ss >> s) { cout << s; } // program exits with only "Thi" printed return 0; }
核心原因
noskipws是流的持久化状态:noskipws不是单次提取的临时设置,一旦通过ss >> noskipws设置,这个标志会一直保留在stringstream的状态中,直到被手动修改。第一个循环结束后,流仍然处于“不跳过空白字符”的模式。- 循环终止时的流位置:第一个循环在
i>2时break,此时已经提取了前3个字符(T、h、i),流的下一个待读取字符是原字符串中This后面的空格。 - 字符串提取的行为冲突:
ss >> s提取字符串的默认逻辑是跳过所有空白字符,直到遇到非空白字符才开始读取。但因为流的noskipws标志仍处于开启状态,跳过空白的行为被禁用了。此时流的第一个待读取字符是空格,>>尝试读取非空白字符失败,导致ss >> s返回false,循环直接终止,没有任何后续输出。
解决办法
- 方法一:第一个循环结束后,手动恢复流的默认空白跳过状态:
// 在第二个循环前添加 ss >> skipws; - 方法二:避免在循环提取中直接设置
noskipws,改为临时设置后恢复:// 第一个循环修改为,只在单次提取时临时生效 while (i <= 2 && ss >> noskipws >> c) { cout << c; i++; } ss >> skipws; // 恢复默认状态
内容的提问来源于stack exchange,提问作者Ashkan Arabi
相关产品推荐
相关产品推荐

