C++ stringstream 简介

C++ stringstream 能够实现字符串流的输入输出操作,将字符串对象与流关联起来,允许像读取流一样读取字符串(如 cin)。能够很方便的从字符串中提取出以空格分割的子串、计算单词的频率,并且能够很方便地实现内置类型数据数据之间的转换(如 string 转 int)。🍦


🥗 iostream 和 stringstream 的继承关系

C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含 sstream 头文件。

  • istringstream类用于执行C++风格的字符串流的输入操作。
  • ostringstream类用于执行C++风格的字符串流的输出操作。
  • strstream类同时可以支持C++风格的字符串流的输入输出操作。

istringstream类是从istream和stringstreambase派生而来,ostringstream是从ostream和 stringstreambase派生而来, stringstream则是从iostream类和stringstreambase派生而来。

  

他们的继承关系如下图所示, 箭头代表继承的关系

c++标准输入输出流关系

c++标准输入输出流关系 ,可以看这篇文章 c++标准输入输出流关系梳理


🍦 istringstream

istringstream是由一个string对象构造而来,istringstream类从一个string对象读取字符。
istringstream的构造函数原形如下:
istringstream::istringstream(string str);

一些常用的方法有:

clear()—清除流

str()—获取并设置其内容存在于流中的字符串对象。

运算符<< —将字符串添加到stringstream对象。

运算符>> —从stringstream对象中读取内容,

看一个使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <sstream>

using namespace std;

int main()
{
istringstream istr;
istr.str("1 56.7");
//上述两个过程可以简单写成 istringstream istr("1 56.7");
cout << istr.str() << endl; // 让istringstream对象返回一个string字符串
int a(0);
float b(0);
istr >> a; // 给a赋值的同时自动转换位 int
cout << a << endl;
istr >> b;
cout << b << endl;


return 0;
}

输出

1
2
3
4
1 56.7
1
56.7

上例中,构造字符串流的时候,空格会成为字符串参数的内部分界,例子中对a,b对象的输入”赋值”操作证明了这一点,字符串的空格成为了整型数据与浮点型数据的分界点,利用分界获取的方法我们事实上完成了字符串到整型对象与浮点型对象的拆分转换过程。

str()成员函数的使用可以让istringstream对象返回一个string字符串(例如本例中的输出操作(cout<<istr.str();)。


🧃 ostringstream

ostringstream同样是由一个string对象构造而来,ostringstream类向一个string插入字符。
ostringstream的构造函数原形如下: ostringstream::ostringstream(string str);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<sstream>

int main()
{
//std::ostringstream ostr("abc");

//如果构造的时候设置了字符串参数,那么增长操作的时候不会从结尾开始增加,而是修改原有数据,超出的部分增长

std::ostringstream ostr;
ostr.put('d');
ostr.put('e');
ostr<<"fg";

std::cout<<ostr.str()<< std::endl;
std::string mystr=ostr.str();
std::cout<<mystr<< std::endl;


}

输出

1
2
defg
defg

在上例代码中,我们通过put()或者左移操作符可以不断向ostr插入单个字符或者是字符串,通过str()函数返回增长过后的完整字符串数据,但值 得注意的一点是,当构造的时候对象内已经存在字符串数据的时候,那么增长操作的时候不会从结尾开始增加,而是修改原有数据,超出的部分增长。


🥛 stringstream

stringstream 用于C++风格的字符串的输入输出的。
stringstream的构造函数原形如下:

stringstream::stringstream(string str);

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<sstream>
using namespace std;
int main()
{
stringstream iostr("xxx");
iostr.put('a');
iostr.put('b');
iostr<<"cde";

string mystr=iostr.str(); // 转换为字符串
cout<<mystr<<endl;
for(char &a:iostr.str()) // 遍历打印字符串
{
cout<<a<<" ";
}
cout<<endl;

char b;
while(iostr>>b) // 输出至 b 并打印
{
cout<<b<<" ";
}

return 0;

}

输出

1
2
3
abcde
a b c d e
a b c d e

🍹 内置类型数据之间的转换

除此而外,stringstream 类的对象我们还常用它进行string与各种内置类型数据之间的转换。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
#include<sstream>
using namespace std;

int main(int argc, char**argv)
{

stringstream sstr;
//--------int转string-----------
int a=100;
string str;
sstr<<a;
sstr>>str;
cout<<str<<endl;

//--------string转int-----------
sstr.clear();
sstr<<"10 20";
int temp;
while(sstr>>temp)
{
cout << temp << " ";
}
cout<<"\n";

//--------string转char[]--------
sstr.clear(); //如果你想通过使用同一stringstream对象实现多种类型的转换,请注意在每一次转换之后都必须调用clear()成员函数。
string blog="www.lifeee.top";
char cblog[200];
sstr<<blog;
sstr>>cblog;
cout<<cblog<<endl;

return 0;
}

输出

1
2
3
100
10 20
www.lifeee.top

实现任意类型的转换

1
2
3
4
5
6
7
8
    template<typename out_type, typename in_value>
    out_type convert(const in_value & t){
      stringstream stream;
      stream<<t;//向流中传值
      out_type result;//这里存储转换结果
      stream>>result;//向result中写入值
      return result;
    }

🥤 计算单词的频率

利用 stringstream 根据空格拆分字串的特性,可以很方便的对单词进行计数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
#include<sstream>
#include<map>

using namespace std;

// 计算单词频率
void printFrequency(string str)
{
map<string, int> mp;
stringstream ss(str);

string substr;
while (ss >> substr) // 遍历
{
mp[substr]++; // 计数
}

map<string, int>::iterator it;
for (it = mp.begin(); it != mp.end(); it++)
{
cout << it->first << " -> "
<< it->second << endl;
}

}

int main(int argc, char **argv)
{

string s="lifeee for lifeee learning";
printFrequency(s);
return 0;

}

输出

1
2
3
for -> 1
learning -> 1
lifeee -> 2

当然既然能计数,肯定也是可以去除字符串中的空格的,参见 Removing spaces from a string using Stringstream - GeeksforGeeks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Program 1: Using EOF.

程序1: 使用 EOF。


// C++ program to remove spaces using stringstream
#include <bits/stdc++.h>
using namespace std;

// Function to remove spaces
string removeSpaces(string str)
{
stringstream ss;
string temp;

// Storing the whole string
// into string stream
ss << str;

// Making the string empty
str = "";

// Running loop till end of stream
while (!ss.eof()) {

// Extracting word by word from stream
ss >> temp;

// Concatenating in the string to be
// returned
str = str + temp;
}
return str;
}

// Driver function
int main()
{
// Sample Inputs
string s = "This is a test";
cout << removeSpaces(s) << endl;

s = "geeks for geeks";
cout << removeSpaces(s) << endl;

s = "geeks quiz is awsome!";
cout << removeSpaces(s) << endl;

s = "I love to code";
cout << removeSpaces(s) << endl;

return 0;
}

Output: 输出:
Thisisatest
geeksforgeeks
geeksquizisawsome!
Ilovetocode


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Program 2: Using getline().

程序2: 使用 getline ()。




// C++ program to remove spaces using stringstream
// and getline()
#include <bits/stdc++.h>
using namespace std;

// Function to remove spaces
string removeSpaces(string str)
{
// Storing the whole string
// into string stream
stringstream ss(str);
string temp;

// Making the string empty
str = "";

// Running loop till end of stream
// and getting every word
while (getline(ss, temp, ' ')) {
// Concatenating in the string
// to be returned
str = str + temp;
}
return str;
}
// Driver function
int main()
{
// Sample Inputs
string s = "This is a test";
cout << removeSpaces(s) << endl;

s = "geeks for geeks";
cout << removeSpaces(s) << endl;

s = "geeks quiz is awsome!";
cout << removeSpaces(s) << endl;

s = "I love to code";
cout << removeSpaces(s) << endl;

return 0;
}

// Code contributed by saychakr13
Output: 输出:
Thisisatest
geeksforgeeks
geeksquizisawsome!
Ilovetocode


🍗 参考文献

stringstream::stringstream - C++ Reference (cplusplus.com)

http://www.usidcbbs.com/read-htm-tid-1898.html

c++标准输入输出流关系梳理

C++ stringstream_freeking101的博客

stringstream in C++ and its applications - GeeksforGeeks

高大的树木 · 免费素材图片 (pexels.com)




漠漠水田飞白鹭,阴阴夏木啭黄鹂。

– 王维 《积雨辋川庄作 / 秋归辋川庄作