stringstream到底做什么?


107

自昨天以来,我一直在尝试学习C ++,并且正在使用以下文档:http : //www.cplusplus.com/files/tutorial.pdf(第32页)。我在文档中找到了代码,然后运行了它。我尝试输入5.5卢比的价格,输入整数作为数量,输出为0。我尝试输入5.5和6,输出正确。

// stringstreams
#include <iostream> 
#include <string> 
#include <sstream> 

using namespace std; 

int main () 
{ 
  string mystr; 
  float price = 0; 
  int quantity = 0; 

  cout << "Enter price: "; 
  getline (cin,mystr); 
  stringstream(mystr) >> price; 
  cout << "Enter quantity: "; 
  getline (cin,mystr); 
  stringstream(mystr) >> quantity; 
  cout << "Total price: " << price*quantity << endl; 
  return 0; 
}

问题:mystring命令的作用是什么?引用文档:

“在此示例中,我们间接地从标准输入中获取数值。不是直接从标准输入中提取数值,而是从标准输入(cin)获取行到字符串对象(mystr),然后提取整数该字符串中的值转换为int(数量)类型的变量。”

我的印象是该函数将采用字符串的整数部分并将其用作输入。

(我不完全知道如何在这里问问题。我也是编程的新手)谢谢。


18
这个例子有点奇怪,我从未见过stringstream用过这种方式。我通常会加载该行,然后对其进行转换,然后按部分进行提取,但是在这里,这显然没有什么优势,因为cin 已经输入流了……所以cin >> price >> quantity;要简单得多。那将是使用cplusplus.com教程的一个很好的理由。
Bartek Banachewicz

6
有趣的是,该教程是我第一次接触C ++。事后看来,这是非常糟糕和不完整的。我会推荐一本好书
jrok 2013年

@BartekBanachewicz也许他们只是想出例子来展示其stringstream工作原理。这是一个奇怪的问题,甚至可能是一个坏问题=),但是它表明您可以将字符串视为流。
luk32 2013年

如果这不是对更高级用法的介绍,stringstream那肯定是错误的例子。即使是这样,也应该以不同的方式编写。
j_kubik 2013年

1
@trojansdestroy如果不了解字符串流,则无法理解它所基于的所有原语,因此,我看不到阅读教程在这方面有何帮助。
Bartek Banachewicz

Answers:


163

有时,使用stringstream在字符串和其他数字类型之间进行转换非常方便。的用法stringstream类似于的用法iostream,因此它不是学习的负担。

Stringstreams可用于读取字符串和将数据写入字符串。它主要与字符串缓冲区一起使用,但没有真正的I / O通道。

stringstream类的基本成员函数是

  • str(),它以字符串类型返回其缓冲区的内容。

  • str(string),它将缓冲区的内容设置为string参数。

这是如何使用字符串流的示例。

ostringstream os;
os << "dec: " << 15 << " hex: " << std::hex << 15 << endl;
cout << os.str() << endl;

结果是 dec: 15 hex: f

istringstream 大致相同的用法。

总而言之,stringstream是一种像独立I / O设备一样操作字符串的便捷方法

仅供参考,类之间的继承关系为:

字符串流类


19

回答问题。stringstream基本上可以让您string像对待一个对象stream,并使用所有stream在其上函数和运算符。

我看到它主要用于格式化输出/输入。

一个很好的例子是 c++将数字转换为流对象的实现。

可能的例子:

template <class T>
string num2str(const T& num, unsigned int prec = 12) {
    string ret;
    stringstream ss;
    ios_base::fmtflags ff = ss.flags();
    ff |= ios_base::floatfield;
    ff |= ios_base::fixed;
    ss.flags(ff);
    ss.precision(prec);
    ss << num;
    ret = ss.str();
    return ret;
};

也许有点复杂,但是却很复杂。您可以创建stringstream对象ss,修改其标志,使用添加数字operator<<,然后通过提取对象str()。我猜可能是operator>>可以用。

同样在此示例中,string缓冲区是隐藏的,没有显式使用。但是写一篇有关每个可能方面和用例的文章太长了。

注意:我可能是从SO上的某人那里偷来的并进行了改进,但我没有注明原始作者。


3
注意:的使用ret是不必要的,可以写return ss.str();
Matthieu M.

@MatthieuM。我想我不确定RVO是否会这样写,或者ss.str()返回的对象是否会在退出点幸免。通过这种方式,我知道我正在复制,并且RVO可以工作。但是你很可能是对的。
luk32 2013年

实际上,有两种形式的RVO:URVO(对于未命名的是临时的)和NRVO(对于命名的);大多数编译器都实现RVO,但是有些编译器仅将其限制为URVO(取决于构建选项)。在一般情况下,虽然,有很多其他的因素来考虑,所以你应该只写干净的代码可能,并且不会过分担心RVO是否会一命呜呼
马修M.

NRVO很常见(URVO也很常见),但是由于移动构造函数而没有发行。
拉普兹

18

C ++ Primer

istringstream型读取一个字符串ostringstream写入字符串,以及字符串流读取和写入字符串

我遇到了一些使用stringstream既方便又简洁的情况。

情况1

这是从解决方案之一这个问题本文给出了。它展示了一个非常合适的情况,其中stringstream的使用高效且简洁。

假设ab在字符串格式表示的复数,我们想要得到的相乘的结果a,并b同时在字符串格式。代码如下:

string a = "1+2i", b = "1+3i";
istringstream sa(a), sb(b);
ostringstream out;

int ra, ia, rb, ib;
char buff;
// only read integer values to get the real and imaginary part of 
// of the original complex number
sa >> ra >> buff >> ia >> buff;
sb >> rb >> buff >> ib >> buff;

out << ra*rb-ia*ib << '+' << ra*ib+ia*rb << 'i';

// final result in string format
string result = out.str() 

情况2

这也是源于leetcode问题,它要求您简化给定的路径字符串,使用stringstream的解决方案之一是我所见过的最优雅的解决方案

string simplifyPath(string path) {
    string res, tmp;
    vector<string> stk;
    stringstream ss(path);
    while(getline(ss,tmp,'/')) {
        if (tmp == "" or tmp == ".") continue;
        if (tmp == ".." and !stk.empty()) stk.pop_back();
        else if (tmp != "..") stk.push_back(tmp);
    }
    for(auto str : stk) res += "/"+str;
    return res.empty() ? "/" : res; 
 }

如果不使用stringstream,将很难编写这样的简洁代码。


2

您输入了一个字母数字和整数,在中用空格分隔mystr

然后,您尝试将第一个标记(用空格分隔)转换为 int

第一个令牌是RS,未能转换为 int,因此我的价格为零,我们都知道零的乘积是多少。

当您第二次仅输入int值时,一切都按预期工作。

伪造的RS导致您的代码失败。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.