有可能以这种方式串流吗?从字符串转换为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"

此外,iosstringstream 从中继承)还定义了 ! 运算符和对 void* 的强制转换,以便您可以方便地检查提取是否失败(技术上检查是否 failbitbadbit已设置,我相信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;

【讨论】:

使用stringstreamsscanf有很大区别。前者在输出时消耗流中的数据,但后者不消耗。可以反复写sscanf(things.c_str(), "%d %d %d %d", &amp;i1, &amp;i2, &amp;i3, &amp;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变量可以多次使用吗?, 重用之前可能需要流的clearseek。 例如,以下代码将解决您的第二个问题:

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?的主要内容,如果未能解决你的问题,请参考以下文章

从字符串读取到字符串流

字符串流数学运算

对和字符串流

C++学习50 对字符串流的读写

为啥将 C++ 字符串转换为 int?

如何将 intptr_t 转换为字符串 [重复]