专栏首页10km的专栏c++11:基于STL实现字符串分割更简单 wstring,string split

c++11:基于STL实现字符串分割更简单 wstring,string split

版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/80193880

关于string的分割,网上有好多好多写得很详细的文章,但基本上都是基于标准C++的。 比如下面这段代码基于strtok函数实现的split(from 《C++之split字符串分割》):

vector<string> split(const string& str, const string& delim) {  
    vector<string> res;  
    if("" == str) return res;  
    //先将要切割的字符串从string类型转换为char*类型  
    char * strs = new char[str.length() + 1] ; //不要忘了  
    strcpy(strs, str.c_str());   

    char * d = new char[delim.length() + 1];  
    strcpy(d, delim.c_str());  

    char *p = strtok(strs, d);  
    while(p) {  
        string s = p; //分割得到的字符串转换为string类型  
        res.push_back(s); //存入结果数组  
        p = strtok(NULL, d);  
    }   
    return res;  
}  

看着还是有点复杂,还要用到内存复制,如果用C++11开发,基于C++11强大的STL库支持,使用std::regex_token_iteratorstd::vector容器的迭代器参数构造函数vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type())这个split功能可以写得更加简单:

#include <iostream>
#include <vector>
#include <iterator>
#include <regex>
/* 
   用delim指定的正则表达式将字符串in分割,返回分割后的字符串数组
   delim 分割字符串的正则表达式 
 */
std::vector<std::string> s_split(const std::string& in, const std::string& delim) {
    std::regex re{ delim };
    // 调用 std::vector::vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type())
    // 构造函数,完成字符串分割
    return std::vector<std::string> {
        std::sregex_token_iterator(in.begin(), in.end(), re, -1),
        std::sregex_token_iterator()
    };
}

如上只要2行代码就可以完成正则表达式的字符串分割。

如果要支持宽字符集和c string,上面的函数还可以衍生出下面的不同版本:

// std::wstring版本
std::vector<std::wstring> ws_split(const std::wstring& in, const std::wstring& delim) {
    std::wregex re{ delim };
    return std::vector<std::wstring> {
        std::wsregex_token_iterator(in.begin(), in.end(), re, -1),
        std::wsregex_token_iterator()
    };
}
// c string版本
std::vector<std::string> c_split(const char* in, const char* delim) {
    std::regex re{ delim };
    return std::vector<std::string> {
        std::cregex_token_iterator(in, in + strlen(in),re, -1),
        std::cregex_token_iterator()
    };
}
// 支持wchar_t宽字符集的版本
std::vector<std::wstring> wc_split(const wchar_t* in, const wchar_t* delim) {
    std::wregex re{ delim };
    return std::vector<std::wstring> {
        std::wcregex_token_iterator(in, in + wcslen(in),re, -1),
        std::wcregex_token_iterator()
    };
}
// 上面的s_split和ws_split可以统一用模板来实现
template<typename E,
    typename TR = std::char_traits<E>,
    typename AL = std::allocator<E>,
    typename _str_type = std::basic_string<E, TR, AL>>
std::vector<_str_type> bs_split(const std::basic_string<E, TR, AL>& in, const std::basic_string<E, TR, AL>& delim) {
    std::basic_regex<E> re{ delim };
    return std::vector<_str_type> {
        std::regex_token_iterator<typename _str_type::const_iterator>(in.begin(), in.end(), re, -1),
            std::regex_token_iterator<typename _str_type::const_iterator>()
    };
}

调用示例:

#include <iostream>
#include <vector>
#include <iterator>
#include <regex>
int main() {    
    auto s_result = s_split("hello,do you ;know the word?", "[\\s,;?]+");
    std::copy(s_result.begin(), s_result.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    auto c_result = c_split("hello,do you ;know the word?", "[\\s,;?]+");
    std::copy(c_result.begin(), c_result.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    // 设置locale使std::wcout支持中文输出
    std::wcout.imbue(std::locale(std::locale(), "", LC_CTYPE));

    auto ws_result = ws_split(L"lao ban 老板,来份 小龙虾,快点啊!?", L"[\\s,;?]+");
    std::copy(ws_result.begin(), ws_result.end(), std::ostream_iterator<std::wstring, std::wstring::value_type>(std::wcout, L"\n"));
}

参考

文章: 《C++ Split string into a vector》 《C++之split字符串分割》 《std::regex_token_iterator》 《constructor of std::vector::vector》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • c++11模板:容器(map,set,list,vector)中元素类型转换

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • C++11:基于STL对string,wstring进行大小写转换

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • C++11:string和wstring之间互转换

    今天打算做string到wstring转换时发现以前早已经写过,已经忘记从哪里找来的了,贴出代码,以防再忘记。C++11后UTF8编码转换还真是方便

    用户1148648
  • 现代C++教程:高速上手(四)-容器

    std::array与std::vector不同的是,array对象的大小是固定的,如果容器大小是固定的,那么可以优先考虑使用std::array容器。

    程序员小涛
  • C++ IO格式控制

    C语言中,我们可以通过函数printf和scanf进行格式化控制,而在C++中仍然包含了前者,但还提供了以下两种格式控制的方法: (1)使用流成员函数进行格式...

    Dabelv
  • [译]C++17,optional, any, 和 variant 的更多细节

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tkokof1/article/details/826...

    用户2615200
  • C++之IO格式控制

    C语言中,我们可以通过函数printf和scanf进行格式化控制,而在C++中仍然包含了前者,但还提供了以下两种格式控制的方法: (1)使用流成员函数进行格...

    Dabelv
  • OpenCV3.3深度学习模块(DNN)应用-图像分类

    DNN模块介绍 在OpenCV3.3版本发布中把DNN模块从扩展模块移到了OpenCV正式发布模块中,当前DNN模块最早来自Tiny-dnn,可以加载预先训练好...

    OpenCV学堂
  • 简单的C++11线程池实现

    线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementati...

    ccf19881030
  • C++11特性

    VS2010版本的C++新增了C++11特性,对原有的C++标准库扩展,融合BOOST库等三方库

    sofu456

扫码关注云+社区

领取腾讯云代金券