使用流拆分CSV键值对至map<string,vector<uint64>>的最优方法
解析CSV键值对到
map<string, vector<uint64_t>>的正确方法 我来帮你搞定这个解析问题!你要把这种逗号+空格混合分隔的键值对数据,解析到std::map<std::string, std::vector<uint64_t>>里,之前用std::istringstream没成功,大概率是没处理好「逗号拆分键值」这个核心步骤。下面给你两种可行的实现方案:
方案一:简洁版(适配你的输入场景)
你的输入里键都是纯字母、值都是纯数字,且没有包含空格的情况,我们可以先把所有逗号替换成空格,再用istringstream的默认空白拆分功能,直接读取键和值:
#include <sstream> #include <map> #include <vector> #include <string> #include <cstdint> #include <algorithm> #include <stdexcept> std::map<std::string, std::vector<uint64_t>> parseToMap(const std::string& input) { std::map<std::string, std::vector<uint64_t>> result; std::string processedInput = input; // 把所有逗号替换成空格,让istringstream可以按空白拆分键和值 std::replace(processedInput.begin(), processedInput.end(), ',', ' '); std::istringstream iss(processedInput); std::string key; std::string valueStr; // 每次读取一个键+一个值,配对处理 while (iss >> key >> valueStr) { try { // 把字符串转成uint64_t uint64_t value = std::stoull(valueStr); // 将值添加到对应键的vector中 result[key].push_back(value); } catch (const std::invalid_argument&) { throw std::runtime_error("Invalid numeric value for key '" + key + "': " + valueStr); } catch (const std::out_of_range&) { throw std::runtime_error("Value out of uint64_t range for key '" + key + "': " + valueStr); } } return result; }
怎么用?
比如把你的输入字符串传进去:
std::string input = R"(STARTX,20000000,WIDTH,20,COUNT,1000000 ROW,4,COL,55 ROW,5,COL,20 ROW,9,COL,20 ROW,12,COL,85 ROW,14,COL,8)"; auto myMap = parseToMap(input); // 测试输出 for (const auto& entry : myMap) { std::cout << entry.first << ": "; for (uint64_t val : entry.second) { std::cout << val << " "; } std::cout << "\n"; }
输出结果会是:
COL: 55 20 20 85 8 COUNT: 1000000 ROW: 4 5 9 12 14 STARTX: 20000000 WIDTH: 20
方案二:通用版(支持键/值含空格的情况)
如果未来你的键或值可能包含空格(只要不包含逗号),可以用std::getline按逗号拆分每个token,再手动处理空白:
#include <sstream> #include <map> #include <vector> #include <string> #include <cstdint> #include <stdexcept> #include <algorithm> #include <cctype> // 辅助函数:去除字符串前后的空白字符 std::string trim(const std::string& s) { auto start = s.begin(); while (start != s.end() && std::isspace(static_cast<unsigned char>(*start))) { start++; } auto end = s.rbegin(); while (end != s.rend() && std::isspace(static_cast<unsigned char>(*end))) { end++; } return std::string(start, end.base()); } std::map<std::string, std::vector<uint64_t>> parseToMapGeneral(const std::string& input) { std::map<std::string, std::vector<uint64_t>> result; std::istringstream iss(input); std::string token; std::string currentKey; bool expectingKey = true; // 标记下一个token是键还是值 while (std::getline(iss, token, ',')) { std::string trimmedToken = trim(token); if (trimmedToken.empty()) { continue; // 跳过空的token(比如连续逗号或换行导致的) } if (expectingKey) { currentKey = trimmedToken; expectingKey = false; } else { try { uint64_t value = std::stoull(trimmedToken); result[currentKey].push_back(value); } catch (const std::exception& e) { throw std::runtime_error("Failed to parse value for key '" + currentKey + "': " + trimmedToken); } expectingKey = true; } } // 检查是否有未配对的键(输入元素个数为奇数的情况) if (!expectingKey) { throw std::runtime_error("Unexpected end of input: missing value for key '" + currentKey + "'"); } return result; }
你之前代码可能出错的原因
- 直接用
iss >> key >> value的话,会把逗号当作键的一部分(比如第一个键会变成STARTX,20000000,WIDTH,20,COUNT,1000000),根本没拆分出单独的键和值。 - 没有处理换行和空格混合的情况,导致token里包含换行符,转换数值时失败。
注意事项
- 一定要处理数值转换的异常:如果输入里有非数字的“值”,或者数值超出
uint64_t的范围,std::stoull会抛出异常,直接崩溃,所以要捕获并处理。 - 如果是从文件读取,只需要把
std::istringstream换成std::ifstream,或者把文件内容读到std::string里再调用上面的函数。
内容的提问来源于stack exchange,提问作者user7973129
相关产品推荐
相关产品推荐

