121

我从昨天开始尝试学习 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(数量)类型的变量。”

我的印象是该函数将获取字符串的组成部分并将其用作输入。

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

4

4 回答 4

180

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

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

stringstream 类的基本成员函数是

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

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

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

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

结果是dec: 15 hex: f

istringstream或多或少具有相同的用法。

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

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

字符串流类

于 2013-12-15T13:28:25.330 回答
25

来自C++ 入门

istringstream类型读取字符串ostringstream写入字符串,而stringstream读取和写入字符串

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

情况1

它来自这个 leetcode 问题的解决方案之一。它演示了一个非常适合使用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,就很难写出如此简洁的代码。

于 2017-06-27T14:22:02.983 回答
20

回答问题。stringstream基本上允许您将string对象视为 a 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;
};

也许它有点复杂,但它相当复杂。您创建stringstreamobject ss,修改其标志,使用 将数字放入其中operator<<,然后通过 提取它str()。估计operator>>可以用。

同样在这个例子中,string缓冲区是隐藏的,没有明确使用。但是写一篇关于所有可能的方面和用例的帖子太长了。

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

于 2013-12-15T12:47:19.670 回答
2

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

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

第一个代币是 RS,它未能转换为int,为 myprice 留下零,我们都知道零乘以任何东西的收益率。

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

是虚假的 RS 导致您的代码失败。

于 2015-08-11T02:09:19.793 回答