字符串分割函数是程序开发中常用的函数。实现比较简单,这儿是我的实现:using namespace std; template<class Functor> void __SpliteString(TCHAR* p, const TCHAR cTok, Functor func) { TCHAR* e = p; do { e = _tcschr(p, cTok); if (e != NULL) *e++ =_T('/0'); func(p); p = e; }while(p != NULL); } template<class Functor> void SpliteString(const TCHAR* psz, const TCHAR cTok, Functor func) { string str = psz; __SpliteString((TCHAR*)str.c_str(), cTok, func); } template<class Functor> void __SpliteString(TCHAR* p, const TCHAR* szTok, Functor func) { int len = _tcslen(p); TCHAR* e = p; do { e = _tcsstr(p, szTok); if (e != NULL) { *e =_T('/0'); e += len; } func(p); p = e; }while(p != NULL); } template<class Functor> void SpliteString(const TCHAR* psz, const TCHAR* szTok, Functor func) { string str = psz; __SpliteString((TCHAR*)str.c_str(), szTok, func); }
代码非常简单就不多做解释了。下面给出应用实例:typedef vector<string> string_vector; typedef string_vector::iterator string_iterator; struct IntoVector { IntoVector(string_vector& str_vec) : _str_vec(str_vec){} void operator()(const TCHAR* str) { _str_vec.push_back(str); } string_vector& _str_vec; }; void println(const string& str) { cout<<str<<endl; } void main() { TCHAR szSource[] = "hello|this|is|a|test|string"; string_vector splited; SpliteString(szSource, '|', IntoVector(splited)); for_each(splited.begin(), splited.end(), println); }
以上代码把字符串按照竖线分割符分割后,放入一个vector容器中,并分行打印。如果又想返回切割后字符串个数呢?改动一下:typedef vector<string> string_vector; typedef string_vector::iterator string_iterator; struct IntoVector { IntoVector(string_vector& str_vec) : _str_vec(str_vec),_count(0){} void operator()(const TCHAR* str) { _str_vec.push_back(str); ++ _count; } string_vector& _str_vec; int _count; }; void println(const string& str) { cout<<str<<endl; } void main() { TCHAR szSource[] = "hello|this|is|a|test|string"; string_vector splited; IntoVector intovector(splited); SpliteString(szSource, '|', (IntoVector&)intovector); for_each(splited.begin(), splited.end(), println); cout<<intovector._count<<endl; }
看起来很完美:为了防止拷贝重新构造IntoVector对象,特地强制类型转换为 IntoVector的引用。事实总是让人意外又恼火的,打印结果还是0。跟踪结果就可以发现SpliteString传递的还是IntoVector拷贝构造后的对象,而并不是引用。原因不是这儿探讨的范围,让我表达我也表达不清楚。不过解决办法还是有的。方法1. 把count作为外部对象引用传入:struct IntoVector { IntoVector(string_vector& str_vec,int count) : _str_vec(str_vec),_count(count){} void operator()(const TCHAR* str) { _str_vec.push_back(str); ++ _count; } string_vector& _str_vec; int& _count; }; void main() { TCHAR szSource[] = "hello|this|is|a|test|string"; string_vector splited; int count; IntoVector intovector(splited, count); SpliteString(szSource, '|', intovector); for_each(splited.begin(), splited.end(), println); cout<<count<<endl; }
方法2. 当然还有更好的解决方式。boost是个好东西只需要修改一行就OKSpliteString(szSource, '|', boost::bind<void>(boost::ref(intovector), _1));
为什么这么写?不是这儿的讨论范围了。查看一下boost源代码会很有帮助。方法3. 这个是个ugly的办法——修改SpliteString的函数,将传递的Functor改成引用:void SpliteString(const TCHAR* psz, const TCHAR* szTok, Functor& func); void __SpliteString(const TCHAR* psz, const TCHAR* szTok, Functor& func);
结果就是你只能使用仿函数而不能直接传递函数指针了,so ugly,所以不要考虑这种方式。
字符串分割函数SpliteString
最新推荐文章于 2024-02-02 23:11:09 发布