我正在尝试使用
istringstream
将一个简单的字符串拆分为一系列整数:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main(){
string s = "1 2 3";
istringstream iss(s);
while (iss)
{
int n;
iss >> n;
cout << "* " << n << endl;
}
}
我得到:
* 1
* 2
* 3
* 3
为什么最后一个元素总是出现两次?怎么解决?
它出现了两次,因为你的循环是错误的,正如(间接)在http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5(
while (iss)
不是与本场景中的 while (iss.eof())
不同)。
具体来说,在第三次循环迭代中,
iss >> n
成功并获取您的3
,并使流保持良好状态。然后,由于这个良好的状态,循环第四次运行,直到下一个(第四次)iss >> n
随后失败,循环条件才被打破。但在第四次迭代结束之前,您仍然第四次输出 n
...。
尝试:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
string s = "1 2 3";
istringstream iss(s);
int n;
while (iss >> n) {
cout << "* " << n << endl;
}
}
希望这有帮助:
国际空间站:1 2 3
迭代 1
iss:1 2 3(初始)
n=1
国际空间站:2 3
//* 打印 1
迭代 2:
iss:2 3(初始)
n=2
国际空间站:3
//* 打印 2
迭代 3
国际空间站:3
n=3
伊丝:''
迭代 4
伊丝:''
n 未更改//为 iss 的 eof 设置标志,因为没有来自流的进一步输入
伊丝 : ''
正如上面的帖子所正确提到的, while (iss) 与 while (iss.eof()) 没有什么不同。
在内部,函数(istream::operator>>) 通过首先构造一个 sentry 对象来访问输入序列(noskipws 设置为 false[这意味着空格是分隔符,您的列表将为 1,2,3])。然后(如果 good[此处 eof 未达到]),它调用 num_get::get [获取下一个整数] 来执行提取和解析操作,相应地调整流的内部状态标志。最后,它在返回之前销毁哨兵对象。
参考:http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
常见的情况是分割成一个向量,完全避免混乱的
while
循环和EOF陷阱(参见这个答案,它很好地阐述了为什么OP的代码不起作用):
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::string s = "1 2 3";
std::istringstream istr(s);
const std::vector<int> values{std::istream_iterator<int>(istr),
std::istream_iterator<int>()};
for (const int n : values) {
std::cout << n << "\n";
}
}