20

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

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

    }
}
4

5 回答 5

17

C++ 字符串工具包库(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 具有以下元素:

令牌0 = "abc,"
令牌1 = “123”
令牌2 = "xyz"

更多示例可以在这里找到

于 2009-10-17T21:59:15.447 回答
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;
}
于 2009-10-03T15:50:42.323 回答
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

于 2009-10-02T18:38:19.850 回答
2

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

于 2009-10-02T20:17:16.843 回答
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 算法,用一个迭代器作为它的输出,而不是假设它总是推到一个集合上。由于它(暂时)取决于输入是一个字符串,因此它不使用迭代器作为输入。

于 2009-10-02T19:04:06.430 回答