如何用stringstream识别CSV行最后一个字符串键以构建键值对?
解决CSV行解析的键值对映射问题
这个问题的核心在于你原有的解析逻辑没有正确区分键和键对应的整数值——你用;分割所有内容,但实际上键是字符串,每个键后面跟着的是连续的整数值,直到遇到下一个键为止。原代码里判断空word的逻辑不适用,因为最后一个键后面的整数都是用;分隔的,不会出现空字符串的情况。
修改后的完整代码
#include <map> #include <vector> #include <sstream> #include <string> #include <algorithm> #include <cctype> std::map<std::string, std::vector<uint64_t>> CsvReader::readAllKvp() { if (!_ifs->is_open()) { _ifs->open(_fileName); } std::map<std::string, std::vector<uint64_t>> result; std::string line; // 逐行读取CSV内容 while (std::getline(*_ifs, line) >> std::ws) { std::istringstream ss(line); std::string currentKey; uint64_t val; // 循环处理每组键值对 while (true) { // 第一步:读取当前键(以;为分隔符) if (!std::getline(ss, currentKey, ';')) { break; // 没有更多内容,退出循环 } // 清理键前后的空白字符(避免空格干扰键的匹配) currentKey.erase(currentKey.begin(), std::find_if(currentKey.begin(), currentKey.end(), [](unsigned char ch) { return !std::isspace(ch); })); currentKey.erase(std::find_if(currentKey.rbegin(), currentKey.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), currentKey.end()); // 跳过空键(比如行尾多余的;) if (currentKey.empty()) { continue; } // 第二步:读取当前键对应的所有整数,直到遇到下一个非整数(即下一个键) std::vector<uint64_t> values; while (ss.peek() != EOF) { ss >> std::ws; // 跳过;后面的空白 // 尝试读取整数,成功则加入vector if (ss >> val) { values.push_back(val); // 读取整数后,跳过后续的;(如果存在) if (ss.peek() == ';') { ss.ignore(); } } else { // 读取失败,说明下一个是键,恢复流状态后退出当前值读取循环 ss.clear(); break; } } // 将键值对存入map result[currentKey] = std::move(values); } } return result; }
关键修改说明
- 明确的键值分离逻辑:先读取一个完整的键,再读取后续所有能解析为整数的内容,直到遇到无法解析为整数的部分(也就是下一个键),彻底避免了把最后一个键的整数误判为新键的问题。
- 键的空白清理:处理键前后可能存在的空格,确保
" STOPPOSITIONS "这类带空格的键能正确匹配到目标键名。 - 流状态恢复:当读取整数失败时,主动恢复stringstream的状态,保证后续能正常读取下一个键。
- 分隔符处理:读取整数后主动跳过后续的
;,避免分隔符干扰下一次的读取操作。
用你提供的测试行SPIN;5;WIN;10;STOPPOSITIONS;27;1;14测试,这段代码会正确生成:
"SPIN"→{5}"WIN"→{10}"STOPPOSITIONS"→{27, 1, 14}
内容的提问来源于stack exchange,提问作者user7973129
相关产品推荐
相关产品推荐

