有点基本的问题,但我在思考解决方案时遇到了麻烦,所以我需要朝着正确的方向努力。
我有一个输入文件,我要把它放入一个字符串变量中。问题是我需要将这个字符串分成不同的东西。将有3个字符串和1个int。它们之间用“:”隔开。
我知道我可以通过find()找到第一个“:”的位置,但是我真的不知道如何通过字符串进行处理,对于每个东西并把它放入它自己的字符串/ int。
文件的实际输入如下所示:
A:PEP:909:Inventory Item
A将成为命令我必须执行...所以这将是一个字符串。 PEP是一个关键,需要是一个字符串。 909是一个int。
,最后一个是字符串。
所以我认为我想做的是有3个字符串var,1个int并将所有这些东西放入各自的变量中。
所以我想我最终想要将这个C ++字符串转换为C字符串,这样我就可以使用atoi将一个部分转换为int。
答案 0 :(得分:6)
我通常使用这样的东西:
void split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
}
你可以像这样使用它:
std::vector<std::string> tokens;
split("this:is:a:test", ':', tokens);
令牌现在将包含“this”,“is”,“a”和“test”
答案 1 :(得分:3)
答案 2 :(得分:3)
当您想要使用C ++标准库时,最好使用std::getline
和std::istringstream
:
std::string command;
std::string key;
int id;
std::string item;
std::string line = "A:PEP:909:Inventory Item";
// for each line:
std::istringstream stream(line);
std::getline(stream, command, ':');
std::getline(stream, key, ':');
stream >> id;
std::getline(stream, item);
// now, process them
考虑将它放入自己的结构中:
struct record {
std::string command;
std::string key;
int id;
std::string item;
record(std::string const& line) {
std::istringstream stream(line);
stream >> *this;
}
friend std::istream& operator>>(std::istream& is, record & r){
std::getline(is, r.command, ':');
std::getline(is, r.key, ':');
stream >> r.id;
std::getline(is, r.item);
return is;
}
};
答案 3 :(得分:1)
使用C风格的字符串,您可以使用strtok()执行此操作。您也可以使用sscanf()
但是既然你正在处理C ++,你可能想要坚持使用内置的std :: string函数。因此,您可以使用find()。 Find有一个表单,它接受第二个参数,它是开始搜索的偏移量。所以你可以找到(':')找到第一个实例,然后使用find(':',firstIndex + 1)来查找下一个实例,其中firstIndex是第一次调用find()返回的值。
答案 4 :(得分:1)
我发现的一个舒适的解决方案并不罕见,是以下原型:
string SplitToken(string & body, char separator)
返回分隔符第一次出现的所有内容,并删除包含分隔符的部分。
“我的”MFC - 基于CString的实现如下:
CString SplitStringAt(CString & s, int idx)
{
CString ret;
if (idx < 0)
{
ret = s;
s.Empty();
}
else
{
ret = s.Left(idx);
s = s.Mid(idx+1);
}
return ret;
}
CString SplitToken(CString & s,TCHAR separator)
{
return SplitStringAt(s, s.Find(separator));
}
这绝对不是最有效的方法 - 主要缺点是修改了主体并为每个令牌创建了一个新的(部分)副本,所以不要在性能关键位置使用它!
但是,对于简单的解析器,我发现这个(以及一些相关的函数)非常有用。