字符串流
定义与作用
字符串流在内存中模拟 IO——将字符串当作"文件"进行输入输出操作,常用于格式化和解析。
std::ostringstream oss;
oss << "CPU: " << 62.5 << "%"; // 格式化拼接
std::string result = oss.str(); // "CPU: 62.5%"
std::istringstream iss("42 3.14 hello");
int a; double b; std::string c;
iss >> a >> b >> c; // 解析:42, 3.14, "hello"
核心原理
字符串流与 streambuf
完整示例
示例一:飞翔科技日志解析器
场景说明:李眉用 istringstream 解析飞翔科技服务器日志格式。
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iomanip>
struct LogEntry {
std::string timestamp;
std::string level;
std::string source;
std::string message;
double cpuUsage = 0;
};
LogEntry parseLog(const std::string& line) {
LogEntry entry;
std::istringstream iss(line);
// 格式: "2026-06-14|WARN|web-01|CPU 62.5%|high load"
std::getline(iss, entry.timestamp, '|');
std::getline(iss, entry.level, '|');
std::getline(iss, entry.source, '|');
std::getline(iss, entry.message, '|');
// 从 message 中提取数值
std::istringstream msgStream(entry.message);
std::string label;
msgStream >> label >> entry.cpuUsage; // "CPU 62.5%" → label="CPU", cpuUsage=62.5
return entry;
}
int main() {
std::vector<std::string> rawLogs = {
"2026-06-14 09:00|INFO|web-01|CPU 12.5%|正常",
"2026-06-14 09:05|WARN|db-02|CPU 62.5%|负载偏高",
"2026-06-14 09:10|ERROR|cache-03|CPU 95.0%|即将过载",
"2026-06-14 09:15|INFO|web-02|CPU 8.0%|正常",
"2026-06-14 09:20|WARN|mq-01|CPU 78.0%|需关注",
};
std::cout << "=== 飞翔科技日志解析 ===\n\n";
// 格式化表头
std::ostringstream header;
header << std::left
<< std::setw(22) << "时间"
<< std::setw(8) << "级别"
<< std::setw(12) << "来源"
<< std::setw(10) << "CPU"
<< "状态";
std::cout << header.str() << "\n";
std::cout << std::string(60, '-') << "\n";
// 解析并输出
double totalCpu = 0;
int warnCount = 0;
for (const auto& raw : rawLogs) {
auto entry = parseLog(raw);
std::ostringstream row;
row << std::left
<< std::setw(22) << entry.timestamp
<< std::setw(8) << entry.level
<< std::setw(12) << entry.source
<< std::setw(10) << (std::to_string(entry.cpuUsage) + "%")
<< entry.message;
std::cout << row.str() << "\n";
totalCpu += entry.cpuUsage;
if (entry.level == "WARN" || entry.level == "ERROR") ++warnCount;
}
std::cout << std::string(60, '-') << "\n";
// 汇总行
std::ostringstream summary;
summary << "平均 CPU: " << std::fixed << std::setprecision(1)
<< (totalCpu / rawLogs.size()) << "%"
<< " | 告警数: " << warnCount << "/" << rawLogs.size();
std::cout << summary.str() << "\n";
}
预期输出:
=== 飞翔科技日志解析 ===
时间 级别 来源 CPU 状态
------------------------------------------------------------
2026-06-14 09:00 INFO web-01 12.500000% CPU 12.5%
2026-06-14 09:05 WARN db-02 62.500000% CPU 62.5%
2026-06-14 09:10 ERROR cache-03 95.000000% CPU 95.0%
2026-06-14 09:15 INFO web-02 8.000000% CPU 8.0%
2026-06-14 09:20 WARN mq-01 78.000000% CPU 78.0%
------------------------------------------------------------
平均 CPU: 51.2% | 告警数: 3/5
逐段分析:
istringstream用分隔符|解析结构化日志ostringstream配合iomanip(setw、left)实现表格对齐str()提取缓冲区中完整字符串- 嵌套
istringstream提取数值:在已解析字段中再做二次解析
示例二:字符串流实现模板数据填充
场景说明:黄俪用字符串流为飞翔科技通知模板填充动态数据。
#include <iostream>
#include <sstream>
#include <string>
#include <map>
std::string fillTemplate(const std::string& tpl,
const std::map<std::string, std::string>& vars) {
std::istringstream iss(tpl);
std::ostringstream oss;
std::string line;
while (std::getline(iss, line)) {
for (const auto& [key, val] : vars) {
std::string placeholder = "{{" + key + "}}";
size_t pos;
while ((pos = line.find(placeholder)) != std::string::npos)
line.replace(pos, placeholder.length(), val);
}
oss << line << "\n";
}
return oss.str();
}
int main() {
std::string tpl = R"(
========================================
飞翔科技系统通知
========================================
致 {{name}}({{dept}}部):
您的 {{item}} 审核已通过。
有效期至:{{expireDate}}
经办人:{{operator}}
如有疑问,请联系技术部(分机 {{ext}})。
飞翔科技运维中心
2026-06-14
)";
std::map<std::string, std::string> vars = {
{"name", "黄俪"},
{"dept", "技术"},
{"item", "生产环境部署权限"},
{"expireDate", "2026-12-31"},
{"operator", "白歌"},
{"ext", "8080"},
};
std::string result = fillTemplate(tpl, vars);
std::cout << result;
}
预期输出:
========================================
飞翔科技系统通知
========================================
致 黄俪(技术部):
您的 生产环境部署权限 审核已通过。
有效期至:2026-12-31
经办人:白歌
如有疑问,请联系技术部(分机 8080)。
飞翔科技运维中心
2026-06-14
逐段分析:
istringstream逐行读取模板,保留换行结构ostringstream逐行写入替换后的结果std::string::replace原地替换占位符- 字符串流比多次字符串拼接(
+)更高效,避免频繁内存分配
易错场景与面试考点
易错场景
1. 清空字符串流不当
std::ostringstream oss;
oss << "hello";
oss.str(""); // ✅ 清空内容
oss.clear(); // ✅ 清空状态位(通常也需要)
// ❌ 仅 oss.str("") 不清状态位,可能在错误后仍无法写入
2. 重复获取 str()
std::ostringstream oss;
oss << "abc";
auto s1 = oss.str(); // "abc"
// oss.str(""); // 清空后重新使用
oss << "def";
auto s2 = oss.str(); // "abcdef"(不是 "def"!需要先 str("") 清空)
3. istringstream EOF 后重用
std::istringstream iss("1 2 3");
int x;
while (iss >> x) { /* ... */ }
// iss 处于 eofbit 状态
// iss.str("4 5 6"); // 不会自动清除状态位!
iss.clear(); // ✅ 必须
iss.str("4 5 6");
面试考点
| 考点 | 要点 |
|---|---|
| 三个字符串流 | istringstream(读), ostringstream(写), stringstream(读写) |
| str() 方法 | 获取/设置内部缓冲 |
| 格式化拼接 | ostringstream + iomanip 比 std::to_string + 拼接更高效 |
| 数据解析 | istringstream + >> 或 getline 解析结构化字符串 |
| 与 sprintf 对比 | 类型安全、不易缓冲区溢出、可处理 std::string |
| 内部 streambuf | 字符串流使用 stringbuf,与文件流不同 |
| 重用注意 | 改 str 后需 clear 清除 eof/fail 标志 |