有可能以这种方式串流吗?从字符串转换为int?
Posted
技术标签:
【中文标题】有可能以这种方式串流吗?从字符串转换为int?【英文标题】:Is is possible to stringstream this way? to convert from string to int? 【发布时间】:2011-02-20 05:16:41 【问题描述】:可以这样串流吗? 我正在尝试使用 ifstream 读取并转换它。
string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;
stringstream into;
into << things;
into >> i1;
into >> i2;
into >> i3;
into >> i4;
我希望它是:
i1 = 10
i2 = 11
i3 = 12
i4 = -10
对吗?
同一个stringstream变量可以多次使用吗?
当我尝试时,第一次还可以,但后来一切都只是 0。
【问题讨论】:
这不是你得到的结果吗? 如何编译该代码并亲自查看? 因为在一个实例中产生正确结果的可编译代码总是意味着它是 100% 正确的,尤其是在 C++ 中... 【参考方案1】:那肯定行得通。您甚至可以混合类型,如下所示:
string things = "10 Nawaz 87.87 A";
int i;
std::string s;
float f;
char c;
stringstream into;
into << things;
into >> i >> s >> f >> c; //all are different types!
cout << i <<" "<< s <<" "<< f <<" "<< c;
输出:
10 Nawaz 87.87 A
ideone 演示:http://www.ideone.com/eb0dR
【讨论】:
【参考方案2】:有效吗?我的做法是:
istringstream into(things);
into >> i1;
等等。这将产生您发布的输出。
【讨论】:
【参考方案3】:您发布的内容以及 Jeremiah Willcock 使用 istringstream
的解决方案都有效。但是也可以考虑使用scanf 系列函数(对于几个整数来说并没有太大的区别,但对于更高级的输入,使用 scanf 可能比使用流操纵器更简洁):
string things = "10 11 12 -10";
int i1, i2, i3, i4, i5, i6;
sscanf(things.c_str(), "%d %d %d %d", &i1, &i2, &i3, &i4);
您的示例在此之后只给出 0 的原因是因为 stringstream
缓冲区在您提取 -10 后为空:您必须先向缓冲区插入更多内容,然后才能提取更多内容。您可以多次使用同一个 stringstream
实例,但您要么每次都需要完全使用缓冲区,要么意识到在您插入下一个项目之前缓冲区中还有更多内容:
string things = "10 11 12 -10", temp;
int i1, i2, i3, i4;
stringstream into;
into << things; //buffer is now "10 11 12 -10"
into >> i1; //buffer is now " 11 12 -10"
into >> i2; //" 12 -10"
into >> i3; //" -10"
into >> i4; //""
//more code here...
//come back and use the instance again
into << "more: 1 2 3"; //"more: 1 2 3"
into >> temp; //temp is "more:"; into's buffer is " 1 2 3"
into >> i1; //buffer is " 2 3"
//more code here...
//reuse into once again
into << "4 5 6"; // buffer is now " 2 3 4 5 6"
into >> i1; //i1 gets the 2 from before, not the 4 just inserted; buffer now " 3 4 5 6"
into >> i2; //i2==3; buffer is " 4 5 6"
此外,ios
(stringstream
从中继承)还定义了 !
运算符和对 void*
的强制转换,以便您可以方便地检查提取是否失败(技术上检查是否 failbit
或 badbit
已设置,我相信failbit
是与eofbit
一起设置的缓冲区,当缓冲区不够时):
string things = "10 11 12 -10";
int i1, i2, i3, i4;
stringstream into;
into << things;
into >> i1 >> i2 >> i3 >> i4;
if (into >> i5)
cout << "extraction to i5 succeeded" << endl;
if (!(into >> i6))
cout << "extraction to i6 failed" << endl;
【讨论】:
使用stringstream
和sscanf
有很大区别。前者在输出时消耗流中的数据,但后者不消耗。可以反复写sscanf(things.c_str(), "%d %d %d %d", &i1, &i2, &i3, &i4);
感谢您的知识和帮助。我还有一个问题是可以清除字符串流缓冲区吗?
您也可以通过寻求偏移零来重置字符串流。使用 sscanf 是最后的手段,并且仅限于大师。例如,更改 i3 的类型会严重破坏 sscanf 的代码,而 stringstream 只会为 operator>> 选择另一个重载。【参考方案4】:
是的,它会起作用。 我要做的唯一区别是:
string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;
stringstream into(things); // Initialize in the constructor
into >> i1 >> i2 >> i3 >> i4; // Chain the inputs.
注意 linestream 就像一个普通的流,当你读完它的结尾时它会用完项目并设置失败状态。
stringstream into(things)
int val;
while(into >> val) // loop exits after 4 numbers as into.eof()
// returns true after trying to read the 5 number.
std::cout << "G(" << val << ")\n";
例如,我喜欢在读取包含 4 个数字的多行时执行以下操作:
std::string line;
while(std::getline(std::cin, line))
/*
* This way if a line is formatted incorrectly (only 3 numbers)
* The error is local to the line and we will pick it up in linestream
* without affecting the scanning of subsequent lines
*/
std::stringstream linestream(line);
int i1,i2,i3,i4;
linestream >> i1 >> i2 >> i3 >> i4;
【讨论】:
【参考方案5】:关于你的第二个问题
同一个stringstream变量可以多次使用吗?,
重用之前可能需要流的clear
和seek
。
例如,以下代码将解决您的第二个问题:
int main()
string s = "-1 2";
stringstream ss;
ss << s;
int i, j;
ss >> i >> j;
cout<< i <<' '<< j <<endl;
ss.clear();
ss.seekg( 0 );
i = j = 0;
ss >> i >> j;
cout<< i <<' '<< j <<endl;
希望这会有所帮助。
【讨论】:
以上是关于有可能以这种方式串流吗?从字符串转换为int?的主要内容,如果未能解决你的问题,请参考以下文章