C++ STL 字符串分词器






3.27/5 (12投票s)
一个 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()
函数的字符串分词器类是一个静态成员函数。 请注意,CIsSpace
是 Tokenize()
函数的默认谓词。
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
类的源代码和一些测试代码。 我对这个实现的任何意见和新想法都感兴趣。