[C++]从C++的字符串分割展开讨论
没有内置函数,可以自己来写。下面是我在别人代码上修改之后的一个版本。
vector<string> split(const string& src, const string& separator){
string str = src;
string substring;
string::size_type start = 0, index;
vector<string> dest;
while(index != string::npos){
index = str.find_first_of(separator,start);
if (index != string::npos){
substring = str.substr(start,index-start);
dest.push_back(substring);
start = str.find_first_not_of(separator,index);
if (start == string::npos) break;
}
}
substring = str.substr(start);
dest.push_back(substring);
return dest;
}
其中,string::size_type是一种数据类型,而string::npos的解释可以直接读官网解释:
static const size_t npos = -1;
Maximum value for size_t
npos is a static member constant value with the greatest possible value for an element of type size_t.
This value, when used as the value for a len (or sublen) parameter in string's member functions, means "until the end of the string".
As a return value, it is usually used to indicate no matches.
his constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type.
从上述表达可知,string::npos常常用于字符串中子串查找不到的返回值。幸好,C++提供了find函数的内置实现,也就是说,string::npos和find结合实现子串查找逻辑。此处据说有大坑,先留坑,后讨论。
index = str.find_first_of(separator,start);
返回separator在str[start:](Python党一定知道我在说什么)中首次出现的位置。
start = str.find_first_not_of(separator,index);
返回separator在str[index:]中首次不匹配的位置。注意,在while结构中,返回值start又作为find_first_of的参数进行下一轮循环。
if (start == string::npos) break;
查找结束,退出。上文提到的大坑与这行代码相关。
substring = str.substr(start);
dest.push_back(substring);
不要忘记最后分割出的子串,分割结束。
关于上述大坑的描述,在这篇博客中有介绍。在此简单描述:
int idx = str.find(substr);
if(idx == string::npos){
cout << "No found!";
}else{
cout << "Found!";
}
作者说道,idx == string::npos会由于类型不一致导致错误!正确的做法应该是:
string::size_type idx = str.find(substr);
或者
if(str.find(substr) == string::npos){//TODO}
第一种解决方法声明正确的类型,第二种解决方法避免判断返回值类型。
实际上,打印出的string::npos的值是一个非常大的数,而且代码在C++11下使用int类型声明idx验证通过。坑在哪里?(难道验证姿势不对?)
在LeetCode中,C++的字符串操作是一种常见类型。涉及函数substr, replace, find, rfind,
find_first_of, find_last_of, find_first_not_of, find_last_not_of。
补充:
erase指针失效问题,这篇博客相对较早,给出了两种方案,代码如下:
for(vector<int>::iterator iter = numbers.begin();iter != numbers.end();){
if(*iter == 10){
iter = numbers.erase(iter);
//Not work!
//numbers.erase(iter++);
}else{
iter++;
}
}
iter = numbers.erase(iter);
erase返回被删除元素下一个元素的地址,所以可以使用返回值(iter)来存储下一个元素的指针(地址)。
虽然,
numbers.erase(iter++)
表示在指针时效前完成计算,但是实验中不OK!个人感觉这种方式仍然没有解决野指针问题。