split函数的实现

JeffChen

split函数的实现

2013年1月17日 jeffchen 2 条评论

前几天朋友问我要几道C++面试题,我说你让他先写一个string的split函数吧,类似C语言里的strtok. 现在想想自己的代码里,split函数的实现真是兴之所至,想到用什么方法就用什么方法:

一种方法是用stringstream,然后用getline:

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);
    }
}

也可以用regex实现:

void split(const string &s,const string &delim,vector<string>&elems){
	regex reg(delim);
	sregex_token_iterator it(s.begin(),s.end(),reg,-1);
	sregex_token_iterator end;
	while (it!=end)
	{
		elems.push_back(*it++);
	}
}

然后去stackoverflow上search了一把,这个问题竟然在上面C++ tag问题中名列前茅!
支持各种定制的template实现:

template < class ContainerT >
void tokenize(const std::string& str, ContainerT& tokens,
              const std::string& delimiters = " ", const bool trimEmpty = false)
{
   std::string::size_type pos, lastPos = 0;
   while(true)
   {
      pos = str.find_first_of(delimiters, lastPos);
      if(pos == std::string::npos)
      {
         pos = str.length();
 
         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));
         break;
      }
      else
      {
         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));
      }
      lastPos = pos + 1;
   }
};

使用string提供的find of函数实现:

void Tokenize(const string& str,
                      vector<string>& tokens,
                      const string& delimiters = " ")
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);
 
    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

如果是用空格分离,还有更简洁的方法:

void split(const string &s,const string &delim,vector<string>&elems){
    string buf;
    stringstream ss(s); 
    while (ss >> buf)
        elems.push_back(buf);
}

JeffChen » split函数的实现

split函数的实现

前几天朋友问我要几道C++面试题,我说你让他先写一个string的split函数吧,类似C语言里的strtok. 现在想想自己的代码里,split函数的实现真是兴之所至,想到用什么方法就用什么方法:

一种方法是用stringstream,然后用getline:

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);
    }
}

也可以用regex实现:

void split(const string &s,const string &delim,vector<string>&elems){
	regex reg(delim);
	sregex_token_iterator it(s.begin(),s.end(),reg,-1);
	sregex_token_iterator end;
	while (it!=end)
	{
		elems.push_back(*it++);
	}
}

然后去stackoverflow上search了一把,这个问题竟然在上面C++ tag问题中名列前茅!
支持各种定制的template实现:

template < class ContainerT >
void tokenize(const std::string& str, ContainerT& tokens,
              const std::string& delimiters = " ", const bool trimEmpty = false)
{
   std::string::size_type pos, lastPos = 0;
   while(true)
   {
      pos = str.find_first_of(delimiters, lastPos);
      if(pos == std::string::npos)
      {
         pos = str.length();
 
         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));
         break;
      }
      else
      {
         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));
      }
      lastPos = pos + 1;
   }
};

使用string提供的find of函数实现:

void Tokenize(const string& str,
                      vector<string>& tokens,
                      const string& delimiters = " ")
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);
 
    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

如果是用空格分离,还有更简洁的方法:

void split(const string &s,const string &delim,vector<string>&elems){
    string buf;
    stringstream ss(s); 
    while (ss >> buf)
        elems.push_back(buf);
}
原文地址:https://www.cnblogs.com/lexus/p/2874899.html