方案1:

利用"IO流"的概念,即C++中的stream,我们都用过C++中std::iostream中的std::istreamstd::ostream

如果你接触过网络编程(Socket编程),可能会对这个流的概念更加清楚。在C++中,我们常用的cin其实是一个istream对象,从标准输入读取数据,cout是一个ostream对象,用于向标准输出写入数据。IO对象无拷贝或赋值

相应的,我们可以使用std::istream_iterator来作为关联输入流的迭代器:

std::string text = "Let me split this into words";
std::istringstream iss(text);
std::vector<std::string> results(std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>());

利用stream_iterator的方法,由于是stream,我们甚至可以利用fstream对除了字符串之外的输入进行分割,虽然可以分割,但是他只能识别出空格。

针对这个,我们希望可以重载>>,使得满足原有功能的基础上还能满足我们需要的一些操作:

std::istream& operator>>(std::istream& is, std::string& output)
{
// ...do operations we need...
}

最后的形式需要变为:

std::istream& operator>>(std::istream& is, SELF_STRING(public std:string)& output)

其中的SELF_STRING是我们可以把除了空格之外的字符引入,从而可以分割的类型。在这里提出一个可能受争议的解决方式:

构造一个新的类wordDelimitedBy去继承std:string,然后对于这个新的类我们可以模板化使其适应于多种分隔符:

template<char delimiter>
class WordDelimitedBy : public std::string
{}; template<char delimiter>
std::istream& operator>>(std::istream& is, WordDelimitedBy<delimiter>& output)
{
std::getline(is, output, delimiter);
return is;
} int main()
{
std::string text = "Let,me,split,this,into,words"; std::istringstream iss(text);
std::vector<std::string> results(std::istream_iterator<WordDelimitedBy<','>>{iss},
std::istream_iterator<WordDelimitedBy<','>>()); for (int i = 0; i < results.size(); ++i)
std::cout << results[i] << std::endl; system("pause");
}

然后为什么说会受争议的方式,因为std::string并没有virtual destructor,即出现了:当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的。运行时比较有代表性的后果是对象的派生 部分不会被销毁。然而,基类部分很可能已被销毁,这就导致了一个古怪的“部分析构”对象,这是一个泄漏资源。在C++中并没有Java的GC机制。但是铜鼓哦代码我们也会发现,我们并没有实例化WordDelimitedBy,而是一直使用着他的类型和模板化,但是我们也并没有足够的手段去阻止这种实例化的发生;所以严格来说,这种方式虽然比stream的iterator方式快并支持多种分隔符,但是存在漏洞的。

此外,我们还以可以利用std::getline的一个特性:

std::vector<std::string> split(const std::string& s, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
} int main()
{
std::string text = "Let,me,split,this,into,words"; std::vector<std::string> results=split(text, ','); for (int i = 0; i < results.size(); ++i)
std::cout << results[i] << std::endl; system("pause");
}

方案2:

我们可以利用boost库中的split函数,安装boost库可以参照这一篇教程.

#include <boost/algorithm/string.hpp>

std::string text = "Let me split this into words";
std::vector<std::string> results; boost::split(results, text, [](char c){return c == ' ';});

注意到这里的split函数第三个参数实际上是一个lambda表达式,用来判断分隔符是不是一个空格。原理实际上也非常简单,就是执行多次find_if直到到string的结尾。

方案3:

第三种方案实际上涉及到Ranges,这是作者Eric Niebler 的库地址,这个应该会在C++20的标准中被纳入。

用法是这样的:

std::string text = "Let me split this into words";
auto splitText = text | view::split(' ');

同样我们在库的test中可以看见相应的代码 rangeV3

其中我们方案1是最中规中矩的,当然如果ranges被纳入了C++20,会方便许多。

最新文章

  1. STM32之SRAM调试
  2. php composer使用经验
  3. 【leetcode】Multiply Strings
  4. 位运算 ZOJ 3870 Team Formation
  5. linux/lib/string.c
  6. 六:分布式事务一致性协议paxos的分析
  7. 深度分析 Java 的 ClassLoader 机制(源码级别)
  8. .net entity framework 泛型 更新与增加记录
  9. hibernate通过判断参数动态组合Hql语句,生成基本通用查询
  10. ASP.NET上传文件的三种基本方法
  11. android之intent显式,显式学习
  12. switch 在什么时候可以不写default
  13. poj2253 Frogger Dijkstra变形
  14. webView 不能复制解决方案
  15. 【转】详解JavaScript中的异常处理方法
  16. Java并发编程-再谈 AbstractQueuedSynchronizer 1 :独占模式
  17. SSH框架的搭建和测试(Spring + Struts2 + Hibernate)
  18. Spring事务管理机制的实现原理-动态代理
  19. fastDFS教程Ⅱ-文件服务器迁移
  20. Angular中ui-grid的使用详解

热门文章

  1. java中常用的时间操作
  2. 【转载】C语言综合实验1—学生信息管理系统
  3. 错误信息:&quot;OraOLEDB.Oracle&quot; 返回了消息 &quot;ORA-12154: TNS: 无法解析指定的连接标识符
  4. Swing界面组件的通用属性
  5. PHP trim() 函数
  6. 2018 - Start Up
  7. vray学习笔记(3)-多维子材质是个什么东西
  8. CF570E Pig and Palindromes
  9. rest-framework组件 之 视图三部曲
  10. Win提权思路,方法,工具(小总结)[转]