做程序的时候遇到一个问题,我想把一个句子按空格拆分成几个关键字,比如说"keyword1 keyword2 keyword3"
拆分成"keyword1"
、"keyword2"
、"keyword3"
,这样便于我组合SQL查询语句。
(图源 :pixabay)
在Python和PHP里,这是很容易的事情,Python中使用split
, PHP中使用explode
就可以胜任,当然了,还有其它按正则表达式等拆分,就不在我们这篇文章讨论的范畴了。
我的实现
在确认string 并没有现成split
或者explode
函数之后,就只能考虑自己去写了。找来找去,一个find()
一个substr()
,似乎可以用这两个完成。
于是乎写了如下函数:
#include
#include
#include
using namespace std;
const vector<string> split(const string& s, const string str)
{
vector<string> v;
size_t pos=0, pos1=0;
string sub;
while (true) {
pos = s.find(str, pos1);
if (pos == string::npos) {
break;
}
sub = s.substr(pos1, pos - pos1);
if (!sub.empty())
v.push_back(sub);
pos1 = pos + 1;
}
sub = s.substr(pos1,-1);
if (!sub.empty())
v.push_back(sub);
return v;
}
这个函数兼顾了首尾多余的分隔符,试了一下貌似挺好用。
int main()
{
string str = " the quick brown fox jumps over the lazy dog ";
vector<string> v = split(str, " ");
for (auto n : v) cout << n << endl;
return 0;
}
然而突然想到,因为我的程序中用到的是空格分隔,所以惯性的把偏移量加一,如果不是用空格作为分隔符,加1已不是就不对了?
比如输入改成:
string str = "::: the quick brown::: fox jumps over::: the lazy dog :::";
用上述函数就全乱套鸟。所以需要把上述代码略作修改比如把pos1 = pos + 1;
改成pos1 = pos + str.size();
就可以了。
运行结果如下:
他人实现
实现一
在这里发现一个有意思的实现:
http://www.cplusplus.com/articles/2wA0RXSz/
vector<string> explode(const string& s, const char& c)
{
string buff{""};
vector<string> v;
for(auto n:s){
if(n != c) buff+=n; else
if(n == c && buff != "") { v.push_back(buff); buff = ""; }
}
if(buff != "") v.push_back(buff);
return v;
}
他的做法相当于按字符直接扫描字符串,但是这个函数遇到多个字节的分隔符,就无能为力了。另外他的函数中没有处理连续分隔符(当然了,可能这也是种需要)。
实现二
另外一种方法使用的stringstream
,这玩意我从来没用过,试了一下很好用,倒是涨姿势了。
vector<string> split(const string &s, char delim) {
stringstream ss(s);
string item;
vector<string> tokens;
while (getline(ss, item, delim)) {
if (!item.empty())
tokens.push_back(item);
}
return tokens;
}
不过实现一里提及的问题,这里依然存在。
实现三(N)
当我快写完这篇文章时,我发现了How to split a string in C++。
链接中的文章里边讲的很详细,并且提供了很多方法,比如使用boost::split
。
感兴趣的去看看吧,我是懒得去读了,毕竟我的需求已经满足了呢。