網站首頁 編程語言 正文
如:
string str1 = "This is a test";
string str2 = "This-is-a-test";
string str2 = "This+is+a+test";
我們如何將以上字符串按照某種分隔符( ,-,+),將其分割成四個子串,其值分別為 “This” “is” “a” “test” 。
一、使用stringstream流
這里我們只需要用到 istringstream(字符串輸入流) 構造字符串流,然后從字符串流中按照一定的格式讀取數據即可。
通常我們使用 cin 從流中讀取數據,而我們也可以使用 getline 讀取,而后者在讀取時可以選擇接受的數據格式,其函數原型如下:
// istream & getline(char* buf, int bufSize); // 讀到 \n 為止
istream & getline(char* buf, int bufSize, char delim); //讀到 delim 字符為止
// \n 或 delim 都不會被讀入 buf,但會被從文件輸入流緩沖區中取走
?因此,我們可以按照此方式設計一個C++中的string split函數。
void Stringsplit(string str,const const char split)
{
istringstream iss(str); // 輸入流
string token; // 接收緩沖區
while (getline(iss, token, split)) // 以split為分隔符
{
cout << token << endl; // 輸出
}
}
如此,我們就設計出了我們的Stringsplit() 函數。該函數有以下 2 種語法格式
void Stringsplit(string str,const const char split);
// 默認將傳入的字符串str以split為分隔符進行分割,并將得到的子串打印在屏幕上,無返回值
void Stringsplit(string str, const const char split,vector<string>& rst);
// 默認將傳入的字符串str以split為分隔符進行分割, 不會將子串打印在屏幕上,無返回值
// 分割的子串將會保存在rst數組中被帶出函數。
?以上,我們簡單的設計了一種C++中的分割字符串的函數,下面來看一個測試用例:
int main() {
string str("This is a test");
Stringsplit(str, ' '); // 打印子串
vector<string> strList;
string str2("This-is-a-test");
Stringsplit(str2, '-', strList); // 將子串存放到strList中
for (auto s : strList)
cout << s << " ";
cout << endl;
return 0;
}
# 輸出
This
is
a
test
This is a test
二、使用string類提供的find方法與substr方法
find函數原型:?
size_type find( const basic_string& str, size_type pos = 0 ) const;
參數:
str - 要搜索的 string , pos - 開始搜索的位置
返回值
找到的子串的首字符位置,或若找不到這種子串則為 npos 。
substr函數原型:?
basic_string substr( size_type pos = 0, size_type count = npos ) const;
參數:
pos - 要包含的首個字符的位置 ,count - 子串的長度
返回值
含子串 [pos, pos+count) 的 string 。
由以上兩個函數我們便可以設計出我們的Stringsplit()來。同時,因為find()函數查找的可以是字符串,因此我們的分隔符可以是單個的字符,也可以是一個字符串。?
// 使用字符分割
void Stringsplit(const string& str, const char split, vector<string>& res)
{
if (str == "") return;
//在字符串末尾也加入分隔符,方便截取最后一段
string strs = str + split;
size_t pos = strs.find(split);
// 若找不到內容則字符串搜索函數返回 npos
while (pos != strs.npos)
{
string temp = strs.substr(0, pos);
res.push_back(temp);
//去掉已分割的字符串,在剩下的字符串中進行分割
strs = strs.substr(pos + 1, strs.size());
pos = strs.find(split);
}
}
// 使用字符串分割
void Stringsplit(const string& str, const string& splits, vector<string>& res)
{
if (str == "") return;
//在字符串末尾也加入分隔符,方便截取最后一段
string strs = str + splits;
size_t pos = strs.find(splits);
int step = splits.size();
// 若找不到內容則字符串搜索函數返回 npos
while (pos != strs.npos)
{
string temp = strs.substr(0, pos);
res.push_back(temp);
//去掉已分割的字符串,在剩下的字符串中進行分割
strs = strs.substr(pos + step, strs.size());
pos = strs.find(splits);
}
}
下面是一個測試用例:
int main()
{
vector<string> strList;
string str("This-is-a-test");
Stringsplit(str, '-', strList);
for (auto s : strList)
cout << s << " ";
cout << endl;
vector<string> strList2;
string str2("This%20is%20a%20test");
Stringsplit(str2, "%20", strList2);
for (auto s : strList2)
cout << s << " ";
cout << endl;
return 0;
}
# 輸出
This is a test
This is a test
三、使用C庫函數strtok
char* strtok( char* str, const char* delim );
參數:
- str - 指向要記號化的空終止字節字符串的指針
- delim - 指向標識分隔符的空終止字節字符串的指針
返回值:
指向下個記號起始的指針,或若無更多記號則為空指針。
需要注意的是,該函數使用一個全局的靜態變量來保存每次分割后的位置,因此在多線程中是不安全的,這里我們也可以選擇使用它的線程安全版本
char *strtok_r(char *str, const char *delim, char **saveptr); 。
void Stringsplit(const string& str, const string& split, vector<string>& res)
{
char* strc = new char[str.size() + 1];
strcpy(strc, str.c_str()); // 將str拷貝到 char類型的strc中
char* temp = strtok(strc, split.c_str());
while (temp != NULL)
{
res.push_back(string(temp));
temp = strtok(NULL, split.c_str()); // 下一個被分割的串
}
delete[] strc;
}
如此,我們的使用 strtok 版本的Stringsplit() 就完成了。不過,我們使用這種方法實現的字符串分割函數只能根據字符來分割,而我們傳入的參數是字符串類型,這樣可能會對函數的使用這造成誤導(注:參數傳入字符串用的雙引號,傳入字符用的單引號),因此我們也可以使用下面的方法封裝一個參數是字符類型的函數。
void Stringsplit(const string& str, const char split, vector<string>& res)
{
Stringsplit(str, string(1,split), res); // 調用上一個版本的Stringsplit()
}
下面給出一個測試用例,我們分別使用單/雙引號傳入分割的限定字符。
int main()
{
vector<string> strList;
string str("This+is+a+test");
Stringsplit(str, '+', strList);
for (auto s : strList)
cout << s << " ";
cout << endl;
vector<string> strList2;
string str2("This-is-a-test");
Stringsplit(str2, "-", strList2);
for (auto s : strList2)
cout << s << " ";
cout << endl;
return 0;
}
四、使用regex_token_iterator(正則表達式)
正則表達式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等。?
而在C++的正則中,把這種操作稱為Tokenize分詞(或者叫切割)。這種操作剛好可以滿足我們的需求,用模板類regex_token_iterator<>提供分詞迭代器,可以完成字符串的分割。
void Stringsplit(const string& str, const string& split, vector<string>& res)
{
//std::regex ws_re("\\s+"); // 正則表達式,匹配空格
std::regex reg(split); // 匹配split
std::sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
decltype(pos) end; // 自動推導類型
for (; pos != end; ++pos)
{
res.push_back(pos->str());
}
}
測試用例:
int main()
{
// 單個字符分詞
vector<string> strList;
string str("This is a test");
Stringsplit(str," ", strList);
for (auto s : strList)
cout << s << " ";
cout << endl;
// 使用字符串分詞
vector<string> strList2;
string str2("ThisABCisABCaABCtest");
Stringsplit(str2, "ABC", strList2);
for (auto s : strList2)
cout << s << " ";
cout << endl;
}
# 輸出
This is a test
This is a test
總結
原文鏈接:https://blog.csdn.net/m0_58086930/article/details/122759927
相關推薦
- 2022-11-14 Python實現簡易超市管理系統_python
- 2022-05-04 R語言數據類型與相應運算的實現_R語言
- 2022-11-13 如何修改npm默認源為淘寶源
- 2024-01-15 mybatis中@Results,@ResultMap注解使用
- 2022-05-31 postman批量執行接口測試的圖文步驟_其它綜合
- 2022-02-22 Android對話框AlertDialog詳解_Android
- 2022-12-12 flutter?Bloc?更新后事件同步與異步詳解_Android
- 2022-04-07 你知道怎么在?HTML?頁面中使用?React嗎_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支