题目

编写程序,模拟解析服务端日志或 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
考核状态: 合格