std::stringstream 是 C++ 标准库中提供的一个类,定义在头文件 <sstream>
中。它是基于字符串的流(stream),允许像操作输入流(std::cin)或输出流(std::cout)那样,操作字符串内容。
std::stringstream 是 std::iostream 的派生类,支持同时进行字符串解析(输入)和字符串构造(输出)。
核心概念
std::stringstream 用字符串作为存储介质,模拟流的行为。
主要用于:
-
从字符串中提取数据(类似
std::cin
)。 -
将数据写入字符串(类似
std::cout
)。
常见成员函数
-
输入与输出
<<
:将数据写入流中(字符串拼接)。>>
:从流中提取数据(字符串解析)。 -
绑定与清空
-
str()
:获取或设置流内的字符串。 -
clear()
:清除流状态(但不清除内容)。
-
举几个例子
1. 字符串构造
将多个数据拼接成字符串:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::stringstream ss;
ss << "Name: " << "Alice" << ", Age: " << 25; // 写入字符串流
std::string result = ss.str(); // 获取流中的字符串
std::cout << result << std::endl; // 输出: Name: Alice, Age: 25
return 0;
}
输出如下:
2. 字符串解析
从字符串中提取数据:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string data = "123 456 789"; // 要解析的字符串
std::stringstream ss(data);
int a, b, c;
ss >> a >> b >> c; // 逐个提取整数
std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl; // 输出: a: 123, b: 456, c: 789
return 0;
}
输出如下:
3. 字符串重用
修改或清空流中的字符串:
#include <iostream>
#include <sstream>
int main() {
std::stringstream ss;
// 第一次使用
ss << "Hello, World!";
std::cout << ss.str() << std::endl; // 输出: Hello, World!
// 重用流
ss.str(""); // 清空内容
ss.clear(); // 清除状态标志
ss << "New String!";
std::cout << ss.str() << std::endl; // 输出: New String!
return 0;
}
插句题外话
如果写成这样:
#include <iostream>
#include <sstream>
int main() {
std::stringstream ss;
// 第一次使用
ss << "Hello, World!";
std::cout << ss.str() << std::endl; // 输出: Hello, World!
ss << "New String!";
std::cout << ss.str() << std::endl; // 输出: New String!
return 0;
}
输出如下:
应用场景
1. 替代 itoa 或 sprintf
std::stringstream 可以将整数或浮点数格式化为字符串:
#include <iostream>
#include <sstream>
int main() {
int num = 42;
std::stringstream ss;
ss << "Number: " << num;
std::string result = ss.str();
std::cout << result << std::endl; // 输出: Number: 42
return 0;
}
输出如下:
可以看看这篇博客 将数值转换为字符串的函数,涉及到了itoa
和 sprintf
2. 解析复杂字符串
从复杂字符串中提取数据,比如读取配置或处理输入:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string input = "Name=John;Age=30;Country=USA";
std::stringstream ss(input);
std::string item;
while (std::getline(ss, item, ';')) { // 按分号分割字符串
std::cout << item << std::endl;
}
return 0;
}
输出如下:
3. 文件数据处理
用于处理从文件读取的字符串内容:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main() {
std::ifstream file("data.txt");
std::stringstream buffer;
buffer << file.rdbuf(); // 将文件内容读取到字符串流
std::string content = buffer.str();
std::cout << "File Content:\n" << content << std::endl;
return 0;
}
输出如下:
其中data.txt
内容如下:
streamstring类遇到空格或者换行会怎么做
在 C++ 的 std::stringstream 中,空格和换行符的处理取决于使用的输入方式(比如 >>
操作符或 getline
函数):
1. 使用 >> 操作符读取
>>
操作符会将空格和换行符视为分隔符,跳过它们。它会自动提取下一个有效的非空白内容。
比如:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string input = "Hello World\n42";
std::stringstream ss(input);
std::string word;
int number;
ss >> word; // 读取第一个单词
std::cout << "Word: " << word << std::endl; // 输出: Hello
ss >> word; // 读取第二个单词
std::cout << "Word: " << word << std::endl; // 输出: World
ss >> number; // 读取数字
std::cout << "Number: " << number << std::endl; // 输出: 42
return 0;
}
输出如下:
解释:
-
>>
会跳过所有空白字符(包括空格和换行符)。 -
每次调用
>>
都会从上次解析停止的位置继续提取。
2. 使用 getline 函数读取
-
std::getline 会按行读取内容,直到遇到换行符
\n
。 -
换行符会被作为分隔符,不包含在返回的字符串中。
-
空格会被视为普通字符,不会跳过。
比如:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string input = "Hello World\n42";
std::stringstream ss(input);
std::string line;
while (std::getline(ss, line)) { // 按行读取
std::cout << "Line: " << line << std::endl;
}
return 0;
}
输出如下:
解释:
-
getline 会读取整行内容直到遇到换行符,换行符本身被丢弃。
-
每次调用 getline 会从流的当前位置继续读取下一行。
3. 混合读取方式
可以根据需要,使用 >>
和 getline
结合解析内容:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string input = "Name: John Doe\nAge: 30";
std::stringstream ss(input);
std::string label, name;
int age;
// 使用 >> 提取部分数据
ss >> label >> name; // 提取 "Name:" 和 "John"
std::cout << label << " " << name << std::endl;
// 使用 getline 处理整行
std::getline(ss, name); // 提取 " Doe"
std::cout << "Name (continued):" << name << std::endl;
// 提取下一行
ss >> label >> age; // 提取 "Age:" 和 "30"
std::cout << label << " " << age << std::endl;
return 0;
}
输出如下:
4. 空格与换行的处理差异总结
注意事项
-
效率问题:std::stringstream 适合轻量级字符串处理,但对于频繁的字符串拼接操作,性能可能不如 std::string 直接操作高。
-
状态清理:在重用 std::stringstream 时,记得使用
str("")
清空内容,并用clear()
重置流状态。