std::stringstream
是C++标准库中的一个类,用于在内存中操作字符串流。它提供了一种方便的方式来格式化和解析字符串数据,类似于文件流(如 std::ifstream
和 std::ofstream
)但针对字符串。std::stringstream
属于 <sstream>
头文件,结合了输入(std::istringstream
)和输出(std::ostringstream
)的功能。
1.基本功能
- 格式化输出:可以像使用
std::cout
一样向std::stringstream
写入数据,然后将其作为字符串读取。 - 字符串解析:可以将一个字符串传递给
std::stringstream
,并从中解析不同的数据类型。 - 内存中的流操作:不涉及文件操作,完全在内存中进行数据的格式化和解析。
2.常见用法
构造和赋值
#include <sstream>
#include <string>
int main() {
// 创建一个空的 stringstream
std::stringstream ss;
// 用字符串初始化 stringstream
std::string initialData = "123 456";
std::stringstream ss2(initialData);
}
写入数据
#include <sstream>
#include <iostream>
int main() {
std::stringstream ss;
int num = 42;
std::string text = "Hello, World!";
// 向 stringstream 写入数据
ss << num << " " << text;
// 获取生成的字符串
std::string result = ss.str();
std::cout << "Generated string: " << result << std::endl;
return 0;
}
读取数据
#include <sstream>
#include <iostream>
int main() {
std::string data = "123 456.789 Hello";
std::stringstream ss(data);
int i;
float f;
std::string s;
// 从 stringstream 读取数据
ss >> i >> f >> s;
std::cout << "Integer: " << i << std::endl;
std::cout << "Float: " << f << std::endl;
std::cout << "String: " << s << std::endl;
return 0;
}
清空和重用
#include <sstream>
#include <iostream>
int main() {
std::stringstream ss;
ss << "Initial text";
std::cout << "Before clearing: " << ss.str() << std::endl;
// 清空内容并重用
ss.str("");
ss.clear();
ss << "New text";
std::cout << "After clearing: " << ss.str() << std::endl;
return 0;
}
3.常见的操作
str()
:获取或设置stringstream
中的字符串。clear()
:重置流的状态标志。seekg()
和seekp()
:调整流中读写指针的位置。
#include <sstream>
#include <iostream>
int main() {
std::stringstream ss("1234");
// 读取第一个字符
char c;
ss >> c;
std::cout << "First char: " << c << std::endl; // 1
// 移动读指针到起始位置
ss.seekg(3);
// 读取第一个字符
ss >> c;
std::cout << "First char after seekg: " << c << std::endl; // 4
return 0;
}
4.适用场景
- 字符串拼接和格式化:代替
sprintf
或手动字符串拼接操作,更加类型安全。 - 解析复杂字符串:从一个字符串中提取并解析多个数据字段。
- 内存中的流处理:无需文件I/O操作,适合处理小型数据或临时数据。
5.示例:解析复杂字符串
#include <sstream>
#include <iostream>
int main() {
std::string data = "42 3.14 Hello World";
std::stringstream ss(data);
int integer;
float real;
std::string firstWord, secondWord;
ss >> integer >> real >> firstWord >> secondWord;
std::cout << "Integer: " << integer << std::endl;
std::cout << "Float: " << real << std::endl;
std::cout << "First word: " << firstWord << std::endl;
std::cout << "Second word: " << secondWord << std::endl;
return 0;
}
7. 线程安全
std::stringstream
不是线程安全的。如果多个线程同时访问同一个 std::stringstream
对象,必须使用适当的同步机制(如互斥锁)来防止数据竞争和不一致。
8. 相关类
std::istringstream
:只支持输入操作的字符串流。std::ostringstream
:只支持输出操作的字符串流。std::fstream
、std::ifstream
、std::ofstream
:文件流,用于处理文件的I/O操作。
总结
std::stringstream
是一个强大的工具,用于在内存中处理字符串数据。它提供了灵活的格式化和解析功能,适合在需要频繁进行字符串操作的应用场景中使用。相比传统的C风格字符串操作,std::stringstream
提供了更安全和更便捷的接口,有助于提高代码的可读性和维护性。
具体例题例子
string discountPrices(string sentence, int discount) {
double d = 1 - discount / 100.0;
stringstream ss(sentence);
string ans, w;
while (ss >> w) { // 一边分割,一边加到答案中
if (!ans.empty()) {
ans += ' ';
}
if (w.length() > 1 && w[0] == '$' && all_of(w.begin() + 1, w.end(), ::isdigit)) {
stringstream s;
s << fixed << setprecision(2) << '$' << stoll(w.substr(1)) * d;
ans += s.str();
} else {
ans += w;
}
}
return ans;
}
解释:
std::fixed
:
- 操作流,使其以定点表示法输出浮点数。
- 输出的浮点数总是保留固定的小数位数(由
std::setprecision
指定)。 - 如果
std::setprecision
设置了整数部分小数点后的位数,将用0填充不足的位数。
std::setprecision
:
- 用于设置浮点数输出时的小数精度。
- 其效果取决于当前流的浮点格式模式(例如,
std::fixed
或std::scientific
)。 - 在
std::fixed
模式下,std::setprecision
控制小数点后的位数。
举例
显示两位小数
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589793;
std::cout << std::fixed << std::setprecision(2) << pi << std::endl; // Output: 3.14
return 0;
}
与其他格式操纵符对比
std::scientific
:- 将浮点数以科学计数法输出。
- 通常用于处理非常大或非常小的数值。
#include <iostream>
#include <iomanip>
int main() {
double value = 12345.6789;
std::cout << std::scientific << std::setprecision(2) << value << std::endl; // Output: 1.23e+04
return 0;
}