对字符串进行标记并在C ++中包含分隔符

时间:2009-10-02 18:07:57

标签: c++ tokenize

我正在使用以下内容,但不确定如何在其中包含分隔符。

void Tokenize(const string str, vector<string>& tokens, const string& delimiters)
{

    int startpos = 0;
    int pos = str.find_first_of(delimiters, startpos);
    string strTemp;


    while (string::npos != pos || string::npos != startpos)
    {

        strTemp = str.substr(startpos, pos - startpos);
        tokens.push_back(strTemp.substr(0, strTemp.length()));

        startpos = str.find_first_not_of(delimiters, pos);
        pos = str.find_first_of(delimiters, startpos);

    }
}

5 个答案:

答案 0 :(得分:17)

C++ String Toolkit Library (StrTk)有以下解决方案:

std::string str = "abc,123 xyz";
std::vector<std::string> token_list;
strtk::split(";., ",
             str,
             strtk::range_to_type_back_inserter(token_list),
             strtk::include_delimiters);

它应该导致token_list具有以下元素:

Token0 = "abc,"
Token1 = "123 "
Token2 = "xyz"

可以找到更多示例Here

答案 1 :(得分:4)

我现在这有点草率,但这就是我最终的结果。我不想使用boost,因为这是一项学校作业,我的导师希望我使用find_first_of来实现这一目标。

感谢大家的帮助。

vector<string> Tokenize(const string& strInput, const string& strDelims)
{
 vector<string> vS;

 string strOne = strInput;
 string delimiters = strDelims;

 int startpos = 0;
 int pos = strOne.find_first_of(delimiters, startpos);

 while (string::npos != pos || string::npos != startpos)
 {
  if(strOne.substr(startpos, pos - startpos) != "")
   vS.push_back(strOne.substr(startpos, pos - startpos));

  // if delimiter is a new line (\n) then addt new line
  if(strOne.substr(pos, 1) == "\n")
   vS.push_back("\\n");
  // else if the delimiter is not a space
  else if (strOne.substr(pos, 1) != " ")
   vS.push_back(strOne.substr(pos, 1));

  if( string::npos == strOne.find_first_not_of(delimiters, pos) )
   startpos = strOne.find_first_not_of(delimiters, pos);
  else
   startpos = pos + 1;

        pos = strOne.find_first_of(delimiters, startpos);

 }

 return vS;
}

答案 2 :(得分:2)

我无法真正遵循您的代码,您是否可以发布有效的程序?

无论如何,这是一个简单的标记化器,没有测试边缘情况:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void tokenize(vector<string>& tokens, const string& text, const string& del)
{
    string::size_type startpos = 0,
        currentpos = text.find(del, startpos);

    do
    {
        tokens.push_back(text.substr(startpos, currentpos-startpos+del.size()));

        startpos = currentpos + del.size();
        currentpos = text.find(del, startpos);
    } while(currentpos != string::npos);

    tokens.push_back(text.substr(startpos, currentpos-startpos+del.size()));
}

示例输入,分隔符= $$

Hello$$Stack$$Over$$$Flow$$$$!

令牌:

Hello$$
Stack$$
Over$$
$Flow$$
$$
!

注意:我绝不会使用我在没有测试的情况下编写的标记器!请使用boost::tokenizer

答案 3 :(得分:2)

如果分隔符是字符而不是字符串,则可以使用strtok

答案 4 :(得分:0)

这取决于您是否需要前面的分隔符,以下分隔符或两者,以及您希望在字符串的开头和结尾处使用字符串,这些字符串可能在它们之前/之后没有分隔符。

我假设你想要每个单词,前面和后面的分隔符,但不是任何分隔符串(例如,如果在最后一个字符串后面有分隔符)。

template <class iter>
void tokenize(std::string const &str, std::string const &delims, iter out) { 
    int pos = 0;
    do { 
        int beg_word = str.find_first_not_of(delims, pos);
        if (beg_word == std::string::npos) 
            break;
        int end_word = str.find_first_of(delims, beg_word);
        int beg_next_word = str.find_first_not_of(delims, end_word);
        *out++ = std::string(str, pos, beg_next_word-pos);
        pos = end_word;
    } while (pos != std::string::npos);
}

目前,我把它写成更像STL算法,为其输出采用迭代器,而不是假设它总是推送到集合上。由于它在输入中依赖(暂时)是一个字符串,因此它不会使用迭代器作为输入。