分割字符串(C++)
方案1:
利用"IO流"的概念,即C++中的stream,我们都用过C++中std::iostream
中的std::istream
与std::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,会方便许多。
分割字符串(C++)的更多相关文章
- Delphi中stringlist分割字符串的用法
Delphi中stringlist分割字符串的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. 常规的用法大家都知道,现在来讨论它的一些高级的用法. 1.CommaT ...
- C语言分割字符串
最近在做一道C语言题目的时候需要用到分割字符串,本来想自己手写的,也不会很麻烦,但想到其他语言都有分割字符串的库函数,C语言怎么会没有呢?所以,在网上搜了一搜,果然有这样的函数,还是很好用的,在此总结 ...
- Android--split()分割字符串特殊用法
split()分割字符串 1.不同环境下的区分 Java:分割字符串不能写成split("$")//$为要分割的字符Android:分割字符串需要加上中括号split(" ...
- Sql Server分割字符串函数
-- Description: 分割字符串函数 -- SELECT * FROM dbo.Split('a,b,c,d,e,f,g',',') -- ========================= ...
- lua string的自定义分割字符串接口
-------------------------------------------------------------------- -- Create By SunC 2014/7/1 -- ...
- 用C语言来分割字符串
#include <stdio.h> int main() { ] = {}; ] = {}; ] = {}; sscanf("1,2,3#3,4#4,5"," ...
- JAVA 一个或多个空格分割字符串
知识补充 String的split方法支持正则表达式: 正则表达式\s表示匹配任何空白字符,+表示匹配一次或多次. 有了以上补充知识,下面的内容就很好理解了. 一.待分割字符串 待分割字符串为如下: ...
- Swift3.0语言教程分割字符串与截取字符串
Swift3.0语言教程分割字符串与截取字符串 Swift3.0语言教程分割字符串 如果想要快速的创建一个数组,我们可以将字符串进行分割,分割后的内容将会生成一个数组.在NSString中有两个分割字 ...
- LinuxC语言读取文件,分割字符串,存入链表,放入另一个文件
//file_op.c #include <string.h> #include <stdio.h> #include <stdlib.h> struct info ...
- SQLServer实现split分割字符串到列
网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题. 先贴上某大牛写的sp ...
随机推荐
- 记录一次从txt文件导入数据的python下的MySQL实现
环境: python2.7 ComsenzXP自带MySQL 安装python-MySQL模块 数据格式:txt格式的账号信息. 数据一行一条数据. 难点:有的行只有账号,没有密码:有的为空行:有的行 ...
- 修改oracle xe的8080端口
1.用sys管理员身份登录,利用dbms_xdb修改端口设置 SQL> -- Change the HTTP/WEBDAV port from 8080 to 8081 SQL> call ...
- import gevent 协程 import greenlet
- 由浅入深漫谈margin属性
margin 在中文中我们翻译成外边距或者外补白(本文中引用外边距).他是元素盒模型(box model)的基础属性. 一.margin的基本特性 margin 属性包括 margin-top, ma ...
- Android中无标题样式和全屏样式学习
在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...
- WOJ 10 精英选拔
神仙dp,膜Claris 题意:给一个长度为$n$的数列,求出不超过k次交换后的最大连续子区间和. 发现交换后的最优答案一定是这样的(0和2的长度可以为0) 0 ...
- dfs和bfs算法
1. 存储图的方式一般是有两种的:邻接表和邻接矩阵,一般存储链接矩阵的方式是比较简单的,也便于我们去实现这个临接矩阵,他也就是通俗的二维数组,我们平常用到的那种. 2. 这里我们主要记录和讲一下bfs ...
- 开启wifi后不能ping通本机 Cann't ping the local PC while start a wlan
问题如题:今天发现一个问题,测试本机ip时候有时候总是获取失败,后来才发现是wifi共享软件导致的缘故. 本来呢?我买的是小米wifi,但是小米wifi对应的客户端不是很好用,动不动就启动失败,不要问 ...
- Ubuntu学习小结(一) 基础知识,系统安装,软件安装,解压缩
这段时间,抽空研究了一下Ubuntu,虽然也有过到目前为止使用计算机最作死的经历,但目前已经学会了一些最基本的操作.在这里简单的记录一下,算是吸取的教训,供其他人借鉴. 1.装Ubuntu系统.装Ub ...
- Hadoop的安装与配置
一.准备环境: 系统:centos6.5 64位 192.168.1.61 master 192.168.1.5 slave 二.在两台服务器上都要配置ssh免密码登录 在192.168. ...