题目
编写程序,模拟解析服务端日志或 CSV 格式的数据行(如:ID,Name,Score,Passed)。使用 std::stringstream 结合 std::getline 提取各逗号分隔的字段,并利用字符流的自动类型推导将数字与布尔标记准确转换入整型、浮点型和布尔变量中。
输入格式:一行 CSV 格式记录,例如:1001,Alice,92.5,1。
输出格式:格式化回显解析出的强类型字段信息;若格式破损给出解析失败提示。
数据范围与约定:字符串流解析与流状态管理。
思路与算法
1. stringstream 双向缓冲std::stringstream 结合了 istream 与 ostream 的所有特性,自带内存缓冲区,是 C++ 中实现多类型转换和按特定分隔符切分字段的瑞士军刀。
2. getline 自定义分隔符
标准 std::getline(ss, token, ',') 能够优雅地将流按照逗号逐段切分成字符串,完美胜任 CSV 与路径切分任务。
3. 流的复用与 clear 陷阱
若需复用同一个 stringstream 对象,必须先调用 ss.str("") 清空底层字符缓冲,紧接着必须调用 ss.clear() 清空 eofbit 错误标志,缺一不可。
完整程序
#include <iostream>
#include <sstream>
#include <string>
struct StudentRecord {
int id;
std::string name;
double score;
bool passed;
};
bool parseCsvRow(const std::string& line, StudentRecord& record) {
std::stringstream ss(line);
std::string token;
// 1. 读取 ID
if (!std::getline(ss, token, ',')) return false;
std::stringstream(token) >> record.id;
// 2. 读取 姓名
if (!std::getline(ss, token, ',')) return false;
record.name = token;
// 3. 读取 分数
if (!std::getline(ss, token, ',')) return false;
std::stringstream(token) >> record.score;
// 4. 读取 是否通过
if (!std::getline(ss, token, ',')) return false;
int passInt = 0;
std::stringstream(token) >> passInt;
record.passed = (passInt != 0);
return true;
}
int main() {
std::string line;
if (!std::getline(std::cin, line)) {
return 0;
}
StudentRecord record{};
if (parseCsvRow(line, record)) {
std::cout << "--- CSV 记录解析成功 ---\n";
std::cout << "学号: " << record.id << "\n";
std::cout << "姓名: " << record.name << "\n";
std::cout << "成绩: " << record.score << "\n";
std::cout << "考核状态: " << (record.passed ? "合格" : "重修") << "\n";
} else {
std::cout << "错误:CSV 行数据字段缺失或损坏。\n";
}
return 0;
}运行示例
输入:
202601,ZhangWei,95.5,1输出:
--- CSV 记录解析成功 ---
学号: 202601
姓名: ZhangWei
成绩: 95.5
考核状态: 合格