使用 stringstream 标记字符串,其中最后一个字符是定界符
Tokenize a string with stringstream where the last char is the delimiter
我正在从文件中读取数据并将其放入字符串标记中,如下所示:
std::vector<Mytype> mytypes;
std::ifstream file("file.csv");
std::string line;
while (std::getline(file, line)){
std::stringstream lineSs(line);
std::vector<std::string> tokens;
std::string token;
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
Mytype mytype(tokens[0], tokens[1], tokens[2], tokens[3]);
mytypes.push_back(mytype);
}
显然这是一种非常标准的方法。然而,数据没有 NULL 值,而是在那时它只是空的。我的意思是数据可能看起来像这样:
id0,1,2,3
id1,,2,
id2,,,3
中间行的情况给我带来了问题,因为在“2”之后没有任何东西被推回到我的标记向量中,尽管应该有一个空字符串。然后当我尝试创建 Mytype 的实例时遇到一些 out_of_range 问题。
直到现在我一直在检查每行的最后一个字符是否是逗号,如果是,则在行尾附加一个 space。但是我想知道是否有更好的方法来做到这一点。
谢谢。
如果行以逗号结尾,将空字符串添加到向量的一种简单方法是在创建 mytype
之前检查它。如果你加上
if (line.back() == ',')
tokens.push_back("");
在你的内部 while 循环之后,这将向 tokens
添加一个空字符串,如果你以空列结束。
所以
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
变成
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
if (line.back() == ',')
tokens.push_back("");
区别在于第 2 行在最后一次调用 getline() 之前有 !lineSs.eof()。所以如果 getline() returns false (note: 这不是真的 getline()
返回 false,但流在转换时为 false,所以你应该停止循环布尔);相反,停止一次 lineSs.eof() returns true.
这里是对你的程序的修改,展示了这个想法:
int main() {
std::string line;
while (std::getline(std::cin, line)){
std::stringstream lineSs(line);
std::vector<std::string> tokens;
do {
std::string token;
std::getline(lineSs, token, ',');
tokens.push_back(token);
std::cout << "'" << token << "' " << lineSs.eof() << ' ' << lineSs.fail() << std::endl;
} while(!lineSs.eof());
std::cout << tokens.size() << std::endl;
}
}
“1,2,3”会在最后一行显示“3”,“1,2,3”会在最后一行显示“4”。
我正在从文件中读取数据并将其放入字符串标记中,如下所示:
std::vector<Mytype> mytypes;
std::ifstream file("file.csv");
std::string line;
while (std::getline(file, line)){
std::stringstream lineSs(line);
std::vector<std::string> tokens;
std::string token;
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
Mytype mytype(tokens[0], tokens[1], tokens[2], tokens[3]);
mytypes.push_back(mytype);
}
显然这是一种非常标准的方法。然而,数据没有 NULL 值,而是在那时它只是空的。我的意思是数据可能看起来像这样:
id0,1,2,3
id1,,2,
id2,,,3
中间行的情况给我带来了问题,因为在“2”之后没有任何东西被推回到我的标记向量中,尽管应该有一个空字符串。然后当我尝试创建 Mytype 的实例时遇到一些 out_of_range 问题。
直到现在我一直在检查每行的最后一个字符是否是逗号,如果是,则在行尾附加一个 space。但是我想知道是否有更好的方法来做到这一点。
谢谢。
如果行以逗号结尾,将空字符串添加到向量的一种简单方法是在创建 mytype
之前检查它。如果你加上
if (line.back() == ',')
tokens.push_back("");
在你的内部 while 循环之后,这将向 tokens
添加一个空字符串,如果你以空列结束。
所以
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
变成
while (std::getline(lineSs, token, ',')){
tokens.push_back(token);
}
if (line.back() == ',')
tokens.push_back("");
区别在于第 2 行在最后一次调用 getline() 之前有 !lineSs.eof()。所以如果 getline() returns false (note: 这不是真的 getline()
返回 false,但流在转换时为 false,所以你应该停止循环布尔);相反,停止一次 lineSs.eof() returns true.
这里是对你的程序的修改,展示了这个想法:
int main() {
std::string line;
while (std::getline(std::cin, line)){
std::stringstream lineSs(line);
std::vector<std::string> tokens;
do {
std::string token;
std::getline(lineSs, token, ',');
tokens.push_back(token);
std::cout << "'" << token << "' " << lineSs.eof() << ' ' << lineSs.fail() << std::endl;
} while(!lineSs.eof());
std::cout << tokens.size() << std::endl;
}
}
“1,2,3”会在最后一行显示“3”,“1,2,3”会在最后一行显示“4”。