【发布时间】:2018-09-02 08:17:43
【问题描述】:
我在 std::string 中获得了一个文本,我想使用 stringstream 进行分析。 文本是 csv 文件中的一行,格式如下:
SPIN;5;WIN;10;STOPPOSITIONS;27;1;14
我必须创建一个键值对(在映射中),键是行中的字符串值(例如:“SPIN”),值是使用行中的下一个整数值填充的向量(例如:5 )。 (KVP:{“SPIN”,{5}})。
问题是我不知道如何确定该行的最后一个字符串值(在本例中为“STOPPOSITIONS”)。
当我在下一次迭代中得到单词“STOPPOSITIONS”时,变量单词更改为“1”,这是错误的,因为我应该创建以下 kvp (KVP: {"STOPPOSITIONS", {27,1,14}} )。
为了找到一行的最后一个字符串值,我应该修复什么?
这是我正在使用的代码:
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;
std::string word;
uint64_t val;
while(getline(*_ifs,line,'\n') >> std::ws)
{
/* do stuff with word */
std::istringstream ss(line);
while(getline(ss, word, ';') >> std::ws)
{
//no more strings found
if(word == "")
{
//read all integers at the end of the line and put them
//in the map at the last key added (in our case: STOPPOSITIONS)
while(ss >> val)
{
result[result.rbegin()->first].push_back(val);
}
break;
}
if (result.find(word) == result.end()) //word not found in map
{
std::vector<uint64_t> newV;
result.insert(
std::pair<std::string, std::vector<uint64_t>>(word, newV));
}
ss >> val;
result[word].push_back(val);
ss.ignore(std::numeric_limits<std::streamsize>::max(),';');
}
}
_ifs->close();
return result;
}
【问题讨论】:
-
您可以尝试使用std::stoi 将令牌转换为数字。如果失败会抛出异常,然后你就知道它是另一个字符串而不是数字。
-
我建议将文本行建模为结构(记录)并在结构中重载
operator>>以读取成员。这允许您处理字段成员,包括忽略不需要的字段。 -
@super 这是一种方法,但我宁愿不捕获和处理异常。正在考虑某种方法来检查 getline 一词是否在当前词和当前词之后得到相同,如果是这样,则该行中没有更多字符串。但是如果我在最后得到一个包含 2 个或多个相同字符串值的行,它就会失败。
-
@ThomasMatthews 这实际上非常简洁。关于在哪里可以找到任何代码示例的任何建议?
-
是的,试试 StackOverflow。在互联网上搜索“StackOverflow C++ 读取文件记录逗号分隔”。尽管您将获得使用逗号分隔的字段的示例,“,”,但您可以轻松地将其更改为“;”。我已经回答了很多。
标签: c++ string file csv stream