65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ STL 字符串分词器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.27/5 (12投票s)

2001年10月14日

Ms-PL

1分钟阅读

viewsIcon

207492

downloadIcon

1001

一个 C++ STL 分词器类,能够根据另一个字符串指定的字符分隔符集来分词。

引言

我在这篇文章中介绍的 CTokenizer 类能够对 STL 字符串进行分词,当分隔符集合由谓词类指定时。 这被设计成一个非常通用的类模板。

template <class Pred>
void CTokenizer { /*...*/ };

分隔(分词)标准在参数谓词类 Pred 中实现。 谓词类通常从 unary_function<char, bool> 派生,并实现 () 运算符。 我只给出三个谓词类的例子:CIsSpace,其中分隔符集合包含空格 0x09-0x0D 和 0x20,CIsComma,其中分隔符是逗号字符 ',',以及 CIsFromString,其中分隔符集合由 STL 字符串中的字符指定。 可以根据需要轻松添加其他谓词类。

实现

首先,我将展示实现的谓词。

对于分隔符是空格 0x09-0x0D 和 0x20 的情况;

class CIsSpace : public unary_function<char, bool>
{
public:
  bool operator()(char c) const;
};

inline bool CIsSpace::operator()(char c) const
{
  // isspace<char> returns true if c is a white-space character 
  // (0x09-0x0D or 0x20)
  return isspace<char>(c);
}

对于分隔符是逗号字符 ',' 的情况

class CIsComma : public unary_function<char, bool>
{
public:
  bool operator()(char c) const;
};

inline bool CIsComma::operator()(char c) const
{
  return (',' == c);
}

对于分隔符是 STL 字符串中给定字符集中的字符的情况

class CIsFromString : public unary_function<char, bool>
{
public:
  //Constructor specifying the separators
  CIsFromString::CIsFromString(string const& rostr) : m_ostr(rostr) {}
  bool operator()(char c) const;

private:
  string m_ostr;
};

inline bool CIsFromString::operator()(char c) const
{
  int iFind = m_ostr.find(c);
  if(iFind != string::npos)
    return true;
  else
    return false;
}

最后,实现 Tokenize() 函数的字符串分词器类是一个静态成员函数。 请注意,CIsSpaceTokenize() 函数的默认谓词。

template <class Pred=CIsSpace>
class CTokenizer
{
public:
  //The predicate should evaluate to true when applied to a separator.
  static void Tokenize(vector<string>& roResult, string const& rostr, 
                       Pred const& roPred=Pred());
};

//The predicate should evaluate to true when applied to a separator.
template <class Pred>
inline void CTokenizer<Pred>::Tokenize(vector<string>& roResult, 
                                            string const& rostr, Pred const& roPred)
{
  //First clear the results vector
  roResult.clear();
  string::const_iterator it = rostr.begin();
  string::const_iterator itTokenEnd = rostr.begin();
  while(it != rostr.end())
  {
    //Eat seperators
    while(roPred(*it))
      it++;
    //Find next token
    itTokenEnd = find_if(it, rostr.end(), roPred);
    //Append token to result
    if(it < itTokenEnd)
      roResult.push_back(string(it, itTokenEnd));
    it = itTokenEnd;
  }
}

如何使用

以下代码片段显示了一些简单的用法示例,每个实现的谓词一个。

//Test CIsSpace() predicate
cout << "Test CIsSpace() predicate:" << endl;
//The Results Vector
vector<string> oResult;
//Call Tokeniker
CTokenizer<>::Tokenize(oResult, " wqd \t hgwh \t sdhw \r\n kwqo \r\n  dk ");
//Display Results
for(int i=0; i<oResult.size(); i++)
  cout << oResult[i] << endl;
//Test CIsComma() predicate
cout << "Test CIsComma() predicate:" << endl;
//The Results Vector
vector<string> oResult;
//Call Tokeniker
CTokenizer<CIsComma>::Tokenize(oResult, "wqd,hgwh,sdhw,kwqo,dk", CIsComma());
//Display Results
for(int i=0; i<oResult.size(); i++)
  cout << oResult[i] << endl;
//Test CIsFromString predicate
cout << "Test CIsFromString() predicate:" << endl;
//The Results Vector
vector<string> oResult;
//Call Tokeniker
CTokenizer<CIsFromString>::Tokenize(oResult, ":wqd,;hgwh,:,sdhw,:;kwqo;dk,", 
                                          CIsFromString(",;:"));
//Display Results
cout << "Display strings:" << endl;
for(int i=0; i<oResult.size(); i++)
  cout << oResult[i] << endl;

结论

附加到本文的工程 StringTok.zip 包含所呈现的 CTokenizer 类的源代码和一些测试代码。 我对这个实现的任何意见和新想法都感兴趣。

© . All rights reserved.