C ++字符串基于分隔符的修改和提取

时间:2008-11-28 00:30:14

标签: c++ string

有点基本的问题,但我在思考解决方案时遇到了麻烦,所以我需要朝着正确的方向努力。

我有一个输入文件,我要把它放入一个字符串变量中。问题是我需要将这个字符串分成不同的东西。将有3个字符串和1个int。它们之间用“:”隔开。

我知道我可以通过find()找到第一个“:”的位置,但是我真的不知道如何通过字符串进行处理,对于每个东西并把它放入它自己的字符串/ int。

文件的实际输入如下所示:

A:PEP:909:Inventory Item

A将成为命令我必须执行...所以这将是一个字符串。 PEP是一个关键,需要是一个字符串。 909是一个int。

,最后一个是字符串。

所以我认为我想做的是有3个字符串var,1个int并将所有这些东西放入各自的变量中。

所以我想我最终想要将这个C ++字符串转换为C字符串,这样我就可以使用atoi将一个部分转换为int。

5 个答案:

答案 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)

看看boost::tokenizer

答案 2 :(得分:3)

当您想要使用C ++标准库时,最好使用std::getlinestd::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));
}

这绝对不是最有效的方法 - 主要缺点是修改了主体并为每个令牌创建了一个新的(部分)副本,所以不要在性能关键位置使用它!

但是,对于简单的解析器,我发现这个(以及一些相关的函数)非常有用。