吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2920|回复: 1
收起左侧

[C&C++ 原创] 【C++】 字符串分割 (split)

[复制链接]
lovingxiaobing 发表于 2019-12-8 02:10
昨天,有人问我,C++标准库有没有字符串分割的函数。
emmmm,我特意去翻了翻,好像没有。

于是我们可以可以简单封装一个。

在设计这个字符串分割函数以前,我们思考一下这个函数都有哪些规则。

我们给这个函数起名为"split"
这个函数有两个参数,用来接收待分割的字符串(str)和分隔符(delim),这个分隔符是一个字符串。
这个函数将分割得到的子串存入一个容器中,这里可以选择 std:vector。

定义几个规则:
  • 不对空字符串进行分割
  • 空分隔符不存在,即不对字符串进行分割,原封不动的加入到容器中
  • 根据分隔符对字符串进行分割
  • 字符串中没有找到分隔符不添加到容器


为了最小依赖,我们可以完全使用C++标准库中提供的方法。我们会用到两个C++标准库字符串类提供的方法。
  • std::basic_string<CharType>::find  :搜索子串在字符串中出现的位置
  • std::basic_string<CharType>::substr :返回某个范围内的子串

(std::string是std::basic_string<char>的类型别名)

如果没有find到子串,会返回std::basic_string<CharType>::npos;

这个字符串分割就是在字符串中搜索子串分隔符出现的位置,然后提取出当前上一个位置+分隔符长度到下一个分隔符的位置之间的子串。

算法很简单吧!

为了同时兼容char和wchar_t,我对split进行了泛化。可以同时适应char和wchar_t以及其他宽度的字符序列,但都是以std::basic_string为模板。

下面就是具体代码,主要函数就split,其他的都是用来测试split函数的。

[C++] 纯文本查看 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <locale>

inline namespace {
  ////////
  // split: 字符串分割
  // str : 被分割的字符
  // delim : 分隔符
  // 返回一个std::vector容器里面容纳被分割后的字符串
  template <typename CharT>
  auto split(const std::basic_string<CharT>& str,
             const std::basic_string<CharT>& delim)
               -> std::vector<std::basic_string<CharT>> {
    std::vector<std::basic_string<CharT>> strVec;
    
    // 空字符串不分割
    if (!str.length())
      return strVec;
    
    // 空分隔符不分割
    if (!delim.length()) {
      strVec.push_back(str);
      return strVec;
    }
    
    typename std::basic_string<CharT>::size_type start{};
    typename std::basic_string<CharT>::size_type end{};
    
    // 找不到分隔符不添加
    end = str.find(delim, start);
    if (end == std::basic_string<CharT>::npos) {
      return strVec;
    } else {
      strVec.push_back(std::move(str.substr(start, (end-start))));
      start = end + delim.length();
    }
    
    // 不断分割添加子串到容器
    while (end != std::basic_string<CharT>::npos) {
      end = str.find(delim, start);
      strVec.push_back(std::move(str.substr(start, (end-start))));
      start = end + delim.length();
    }
    
    return strVec;
  }
  
  
  
  ////////////////////////////////////////
  // 测试用例
  
  
  void Print(const std::string& str, std::string end = "") {
    std::cout << str << end;
  }
  void Print(const std::wstring& wstr, std::wstring end = L"") {
    std::wcout << wstr << end;
  }

  template <typename T>
  void PrintVector(const std::vector<T>& vec) {
    size_t idx{};
    Print(L"[");
    for (const auto& e : vec) {
      Print(L"\"");
      Print(e);
      Print(L"\"");
      if (++idx < vec.size()) {
        Print(L", ");
      }
    }
    Print(L"]", L"\n");
  }
  
  void DemoMultibytes() {
    Print("多字节测试:", "\n");
    std::string str{"&&Hello&,&&I'm 小冰哟&&&#128514;&xx"};
    std::string delim{"&&"};
    
    Print("字符串: \"", str + "\"");
    Print("\n分隔符: \"", delim + "\"");
    Print("\n");
    
    /////////////////////////////////////
    // vec = split(...)
    std::vector<std::string> vec{split(str, delim)};
    /////////////////////////////////////
    
    PrintVector(vec);
  }
  
  void DemoWideChar() {
    // ...
    {
      std::ios::sync_with_stdio(false);
      std::wcout.imbue(std::locale(""));
    }
    
    Print(L"宽字符测试:", L"\n");
    
    std::wstring wstr{L"&&Hello&,&&I'm 小冰哟&&&#128514;&xx"};
    std::wstring wdelim{L"&&"};
    
    Print(L"宽字符串: \"", wstr + L"\"");
    Print(L"\n分隔符: \"", wdelim + L"\"");
    Print(L"\n");
    
    //////////////////////////////////////
    // wvec = split(...)
    std::vector<std::wstring> wvec{split(wstr, wdelim)};
    //////////////////////////////////////
    
    PrintVector(wvec);
  }
  
  
  void test() {
    DemoMultibytes();
    Print("***************", "\n");
    DemoWideChar();
  }
}

int main() {
  test();
  return 0;
}


我的C++代码中用了一些C++新标准的东西,保证自己的编译器支持C++11/14以上。

运行结果:
Screenshot_2019-12-08-02-06-59-93.png


下面是相关资料的链接

https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/basic_string/find
https://en.cppreference.com/w/cpp/string/basic_string/substr

免费评分

参与人数 1热心值 +1 收起 理由
xinxirong + 1 楼主用的是什么安卓版C++编译器?

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

silencereader 发表于 2019-12-18 10:10
刚好上次遇到了这个问题,把我折磨了一个星期,现在学习一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 19:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表