【C++實現python字符串函數庫】split()與rsplit()方法
前言
本系列文章將介紹python提供的字符串函數,並嘗試使用C++來實現這些函數。這些C++函數在這里做單獨的分析,最后我們將把這些函數放在命名空間中,真正作為一個函數庫來使用。
本節內容
在本節,我們將實現兩個python字符串分割函數。這兩個函數的函數原型為:
split(spe = None,maxsplit= -1)
rsplit(spe= None ,maxsplit = -1)
這兩個方法使用參數spe作為分隔符,將字符串切割成指定的maxsplit段,並以列表的形式返回切割后的字符串。默認的分隔符是空格,默認情況下對所有的分隔符進行分割:
>>>
>>> s = "I'm not to see you"
>>> s.split()
["I'm", 'not', 'to', 'see', 'you']
>>>
>>> s.rsplit()
["I'm", 'not', 'to', 'see', 'you']
>>>
可以看到字符串根據空格進行分割,分割成的各段作為列表的元素組成了列表並返回。
我們再來看更多的例子:
分隔成指定段數
>>>
>>> s = 'aaaaaaaaaaa'
>>> s.split('a',2) #依據'a'進行分割,最大分割數為2(分割兩次)
['', '', 'aaaaaaaaa']
>>>
>>>
>>> s.split('a',1000)#分隔數偏多
['', '', '', '', '', '', '', '', '', '', '', '']
>>>
>>>
>>> s.split('a',-19)#分割數為負數
['', '', '', '', '', '', '', '', '', '', '', '']
>>>
split方法從左至右處理字符串,而rsplit方法從右至左處理字符串:
>>> ##兩個方法的區別
>>> s
'aaaaaaaaaaa'
>>> s.split('a',2)
['', '', 'aaaaaaaaa']
>>> s.rsplit('a',2)
['aaaaaaaaa', '', '']
>>>
C++實現
我們使用容器vector來保存字符串分割后的元素。盡管我們的目標是實現split與rsplit這兩個函數,但是模塊化的思想促使我們定義出以下這5個函數:
- reverse_strings :用於rsplit_whitepace與rsplit函數。
- split_whitespace :用於split調用,以空格作為分隔符對整個字符串做分隔處理(默認)
- rsplit_whitespace :用於 rsplit調用,以空格作為分隔符對整個字符串做分隔處理(默認)
- split 我們所期待的函數
- rsplit 我們所期待的函數
在函數的實現中,我們會調用到C++容器提供的一些接口:vector容器的push_back,substr等。
頭文件與宏定義
在這兩個函數的實現中,我們需要如下頭文件與宏定義:
#include<vector>
#include<string>
#define MAX_32BIT_INT 2147483467
倒序函數reverse_strings
這個函數提供給rsplit函數使用。具體使用繼續向下看。
//采用std的swap函數
void reverse_strings(std::vector< std::string > & result)
{
for (std::vector< std::string >::size_type i = 0; i < result.size() / 2; i++)
{
std::swap(result[i], result[result.size() - 1 - i]);
}
}
spilt()方法默認情況下處理函數:split_whitespace
void split_whitespace(const std::string &str, std::vector<std::string> &result, int maxsplit)
{
std::string::size_type i, j, len = str.size();
for (i = j = 0; i < len;)
{
while (i < len&&::isspace(str[i]))
i++;
j = i;
while (i < len&&!::isspace(str[i]))
i++;
if (j < i)
{
if (maxsplit-- <= 0)
break;
result.push_back(str.substr(j, i - j));
while (i < len&&::isspace(str[i]))
i++;
j = i;
}
}
if (j < len)
{
result.push_back(str.substr(j, len - j));
}
}
split()函數
void split(const std::string &str, std::vector<std::string>&result, const std::string &sep, int maxslit)
{
result.clear();
if (maxslit < 0)
maxslit = MAX_32BIT_INT; //MAX_32BIT_INT是自己定義的一個整數,當maxslit為負數時,對整個字符串做切割處理
//split函數默認為空格為分隔符
if (sep.size() == 0)
{
//調用函數進行空格切割
split_whitespace(str, result, maxslit);
return;
}
std::string::size_type i, j, len = str.size(), n = sep.size();
i = j = 0;
while (i + n <= len)
{
if (str[i] == sep[0] && str.substr(i, n)== sep)
{
if (maxslit-- <= 0)
break;
result.push_back(str.substr(j, i - j));
i = j = i + n;
}
else
i++;
}
//剩下部分
result.push_back(str.substr(j, len - j));
}
rsplit()方法默認情況處理函數
void rsplit_whitespace(const std::string &str, std::vector<std::string>&result, int maxsplit)
{
std::string::size_type i,j,len = str.size();
for (i = j = len; i > 0;)
{
while (i > 0 && ::isspace(str[i - 1]))
i--;
j = i;
while (i > 0 && !::isspace(str[i - 1]))
i--;
if (j > i)
{
if (maxsplit-- <= 0)
break;
result.push_back(str.substr(i, j - i));
while (i > 0 && ::isspace(str[i - 1]))
i--;
j = i;
}
}
if (j > 0)
{
result.push_back(str.substr(0, j));
}
reverse_strings(result);
}
rsplit()函數
void rsplit(const std::string &str, std::vector<std::string>&result, const std::string &sep, int maxsplit)
{
if (maxsplit < 0)
{
split(str, result, sep, maxsplit);
return;
}
result.clear();
if (sep.size() == 0)
{
rsplit_whitespace(str, result, maxsplit);
return;
}
std::string::size_type i, j;
std::string::size_type len = str.size();
std::string::size_type n = sep.size();
i = j = len;
while (i >= n)
{
if (str[i - 1] == sep[n - 1] && str.substr(i - 1, n) == sep)
{
if (maxsplit-- <= 0)
break;
result.push_back(str.substr(i, n));
i = j = i - n;
}
else
{
i--;
}
}
result.push_back(str.substr(0, j));
reverse_strings(result);
}
測試
string s = "I'm not to see you";
vector<string> result;
string sep = " ";
split(s,result,sep,10);
結果:
string b = "abc abc abc abc";
vector<string>result;
string sep = "a";
split(b, result, sep, 2);
for (int i = 0; i < result.size(); i++)
cout << result[i] << endl;
結果:
string b = "abc abc abc abc";
vector<string>result;
string sep = "a";
rsplit(b, result, sep, 2);
for (int i = 0; i < result.size(); i++)
cout << result[i] << endl;
結果: