Split the String 字串分割
什麼是字串分割呢?如果你有學過python會知道有一個函數是str.split(),舉例來說,你的輸入是一行以空白(或是其他字元)隔開的字:This is C++,那你要怎麼把它拆開成三個單獨的字呢?
在python中,我們只要先用一個變數把整句話存起來,接著用.split(' ')就可以了,而在C++裡面比較麻煩,接著我們來介紹怎麼做。
TIP
您也可以直接按建議看我最終的化簡版。
stringstream 字符串流
程式碼
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
string str = "Hello this is C++";
stringstream ss(str); // 將字串輸入到字符串流中
string token;
vector<string> result;
// 分割符號為空格
while (getline(ss, token, ' ')) {
result.push_back(token);
}
for(auto &s: result) cout << s << endl;
}執行結果
text
Hello
this
is
C++更簡單版本
程式碼
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
stringstream ss("Hello this is C++");
string str("");
vector<string> result;
while(ss >> str) result.push_back(str);
cout << result[3];
}執行結果
text
C++使用者輸入
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
string myInput;
getline(cin, myInput);
stringstream ss(myInput);
string str("");
vector<string> result;
while(ss >> str) result.push_back(str);
cout << result[3];
}strtok
strtok可以當作string tokenization的縮寫,簡單來說就是將字串分割成子字串。
我們在使用這個函數的時候,會需要提供兩個參數,一個是要被你分割的字串,另一個則是用什麼字元當做分割符號。
程式碼
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
// 要被我們分割的字串
char str[] = "Hello this is C++";
// 宣告一個向量來儲存結果
vector<string> result;
// 宣告一個 char 指標
char *p;
// 使用 strtok 這邊使用空格當作分割
p = strtok(str, " ");
// 持續分割直到結尾
while( p != NULL) {
result.push_back(p);
// 參數要放NULL
p = strtok(NULL, " ");
}
// 將結果顯示
for(auto& s: result){
cout << s << endl;
}
// 顯示長度
cout << result.size();
}執行結果
text
Hello
this
is
C++
4每次strtok被呼叫時,會將原始的字串遇到分割符號的地方改為\0,也就是字串結尾的意思。而在第16行放NULL是因為,第一次呼叫時他會回傳第一個子字串的指標,然後,我們再從剩餘的繼續分割。如果我們放了原本的字串,那會變成無限循環。
程式碼
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
char str[] = "11 12 13";
vector<string> result;
char *p;
p = strtok(str, " ");
while( p != NULL) {
result.push_back(p);
p = strtok(NULL, " ");
}
cout << stoi(result[0]) + 3;
}執行結果
text
14此例的差異在於第13行,我們用stoi將得到的值轉換為整數。
程式碼
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
char str[] = "Hello, this? is !C++ ,aaaaaaaaaaaa b";
vector<string> result;
char *p;
p = strtok(str, "?!, ");
while( p != NULL) {
result.push_back(p);
p = strtok(NULL, "?!, ");
}
for(auto &s: result) cout << s << endl;
cout << result.size();
}執行結果
text
Hello
this
is
C++
aaaaaaaaaaaa
b
6此例我們把分割符號擴展為問號、驚嘆號、空格、逗號都算,因此遇到這幾種都會被分割。
建議
建議一般想解題的初學者必備最簡單的方法以及稍微有彈性的作法,並且可以因應使用者輸入,以下範例由簡而難。
stringstream + 使用者輸入 + 空格分隔
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
string myInput;
getline(cin, myInput);
stringstream ss(myInput);
string str("");
vector<string> result;
while(ss >> str) result.push_back(str);
cout << result[3];
}stringstream + 使用者輸入 + 其他分隔
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
string myInput;
getline(cin, myInput);
stringstream ss(myInput);
string str;
vector<string> result;
while(getline(ss, str, ',')) result.push_back(str);
cout << result[3];
}stringstream + 使用者輸入 + 清理 + 其他分隔
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
string myInput;
getline(cin, myInput);
stringstream ss;
// 清除 ,!. 三種符號
for(auto c : myInput) {
if (c != '.' && c != '!' && c != ',') {
ss << c;
}
}
string str;
vector<string> result;
while(getline(ss, str, ' ')) result.push_back(str);
for(auto &s: result) cout << s << endl;
}