Skip to content

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;
}