# 介紹 string為C++中字串,很像 vector<char> 或 char arr[] 的加強版(之後會介紹vector) 雖然<iostream>函式庫中已經可以宣告string,但完整功能還是要引入<string>,如下: ```cpp= #include <string> ``` ## 宣告 宣告方式如下: ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string a; string b = "abcd123"; string c = "字串"; //需雙引號 } ``` ## 輸入 ### cin ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string s; cin >> s; } ``` 這樣輸入不會截取到空格 例如輸入 ``` 123 456 789 ``` 那麼s只會截取到123 即s=`123` ### getline 如果想截取包含空格的資訊(拿上方的例子即讓s=`123 456 789`) 則要使用getline 用法如下 如果getline前有cin,則需使用**cin.ignore()**(建議擺在cin正下方) ```cpp= #include <iostream> #include <string> using namespace std; int main(){ int n; cin >> n; cin.ignore(); string s; getline(cin, s); } ``` :::info :::spoiler getline是什麼? 看他的字:get line,可以直接理解為抓取(get)一整行(line) 他的原形為 ```cpp getline(輸入流, 目的地, 停止字元) ``` 輸入流基本上只會用到cin,目的地就是你要輸入給誰,停止字元就是他遇到誰會停,不打則為預設'\n' 例如 ```cpp string str; getline(cin, str, 'c'); ``` 輸入`AaBbCcDd`時str=`AaBbC` ::: :::info :::spoiler cin.ignore是什麼? cin.ignore的功能是忽略掉一些輸入 他的原形為 ```cpp cin.ignore(int a, char ch) ``` 其中a代表最多忽略幾個、ch代表遇到哪個字元時停止(停止ignore,即繼續讀取),而這兩個條件只要一個成立就會結束igonre了 例如 ```cpp string str; cin.ignore(3, 's'); cin >> str; ``` 輸入`abcd`時str=`d` 輸入`asdf`時str=`df` 而預設為`cin.ignore(1, EOF)`(EOF為End Of File),即忽略一個字元的輸入 放在cin下面的意義就是把cin完按的那個enter鍵('\n'字元)忽略掉 ::: # 比較/修改 可以使用一整個字串比較、修改 ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string a = "123",b = "123"; if(a == "123") cout << 1; //此行會執行 if(a == b) cout << 1; //此行會執行 } ``` #### 下標運算子[] 跟陣列一樣,是0-based(從0開始) ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string s = "0123456789"; cout << s[9] << '\n'; for(int i = 0; i < 10; i++) cout << s[i] << ' '; } ``` 輸出結果如下 ```cpp= 9 0 1 2 3 4 5 6 7 8 9 ``` 也可以進行比較或修改 ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string s = "0123456789"; s[8] = '0'; //將原本為數字8的位置變成0 cout << s; //輸出0123456709 if(s[9] == '9') cout << 1; //此行會執行 } ``` :::warning 使用 [] 存取的結果為char型態 因此進行操作時必須使用 $單引號$ 否則可能發生不可預期之錯誤(其實應該就是編譯錯誤而已啦) ::: # 加法 可以使用`+`或`+=`將想要的東西加在字串後方(沒有減、乘、除,更沒有取餘數) 例如 ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string s = "asd", a = "jkl"; s += a; cout << s; //輸出asdjkl } ``` # 比較大小 兩個字串如果比較大小,會根據每個字母的ascii碼進行比較(圖:https://zh.wikipedia.org/zh-tw/ASCII) ![](https://hackmd.io/_uploads/H1DBDFjY3.jpg) 使用十進位 例如 ```cpp= char c = 122; cout << c; //輸出z ``` 比較大小由兩字串第一個字開始比較 ```cpp= string f = "abcde"; string g = "abcd"; if(a > b) cout << 1; //此行會執行 ``` 比較從f[0]與g[0]的ascii,因為兩者相等,所以比較f[1]與g[1]; f[1]與g[1]相等 f[2]與g[2]相等 f[3]與g[3]相等 在f[4]與g[4]時,f[4]為e(ascii碼為101),g[4]為'\0'(ascii碼為0)所以a>b回傳1 :::warning :::spoiler **sort** 可以比較,也就可以sort 例如 ```cpp= #include<iostream> #include<string> #include<algorithm> using namespace std; int main() { string arr[3]={"slhfd" , "dhf" , "sidf"}; sort(arr , arr+3); for(int i=0 ; i<3 ; i++) cout<< arr[i] << '\n'; } ``` 輸出: ```cpp! dhf sidf slhfd ``` ::: # 內建函式 - **.length() / .size()** 得字串大小 ```cpp= string a = "jfglk"; cout << a.size() << ' ' << a.length(); //輸出5 5 ``` **.length()** 與 **.size()** 相同 - **to_string()** 將其他型態轉為string型態 ```cpp= int a = 5464; string s = to_string(a) //s="5464" ``` - **stoi() / stod() / stoll() / stoull()** 將`string`轉為`int`/`double`/`long long`/`unsigned long long`型態 stoi=++s++tring ++to++ ++i++nt,以此類推,d=double, ll=long long, ull=unsigned long long ```cpp= string a = "64645" cout << stoi(a) - 645; //輸出64000; ``` :::warning 使用 **stoi() / stod() / stoll() / stoull()** 函式時,如果字串內有非數字之字元,會發生錯誤 如果字串內數字超過欲轉換型態之範圍,也會發生錯誤 ::: - **.find()** 如果找到該字元(串),則回傳最前面的位置(0-based),否則回傳string::npos :::spoiler `string::npos` 呼叫`.find()`時的回傳值實際上不是`int`型態,而是一個叫`size_t`的資料型態,而`string::npos`代表`size_t`的最大值,代表不存在的位置(他是一個常數,由當前的位元系統決定,每台電腦不一定一樣) ::: 用法 str.find(目標字串) str.find(目標字串,起始位置) 目標也可以是char或string變數 ```cpp= string a = "abcdeee"; cout << a.find('a') << '\n'; //輸出0 cout << a.find("cde") << '\n'; //輸出2 cout << a.find("e") << '\n'; //輸出4 cout << a.find("z") << '\n'; //輸出string::npos(一個數) int f = a.find("z"); cout << f << '\n'; //輸出-1,因為string::npos在int會自動溢位成-1 cout << a.find('d', 6) << '\n'; //輸出string::npos(一個數) if(a.find('f') == string::npos) cout << 1 << '\n'; //此行會執行 ``` - **toupper() / tolower()** 將該字元轉為大寫/小寫(若非英文字母則相同) ```cpp= string a = "Aa.Bb.Cc"; for(int i = 0; i < a.length(); i++) a[i] = tolower(a[i]); cout << a << '\n'; //輸出aa.bb.cc; for(int i = 0; i < a.length(); i++) a[i] = toupper(a[i]); cout << a << '\n'; //輸出AA.BB.CC; ``` :::warning **toupper()** 和 **tolower()** 只能改變 **字元** (char型態) ::: - **insert()** **.insert(位置,字串)** 插入字串 ```cpp= string s = "asd"; string i = "56" s.insert(0, i); //或s.insert(0,"56") cout << s << '\n'; //輸出56asd ``` - **erase()** **.erase(位置,數量)** 移除字串 ```cpp= string s = "456789"; s.erase(0, 3); cout << s << '\n'; //從第0個開始往後刪除3個,輸出789 ``` :::warning 注意:第一位都是0 (0-based) ::: # 補充 stringstream 不太會用到 需引入函式庫<sstream>(沒有 `#include <stringstream>` ) ```cpp= #include <sstream> ``` 需要搭配getline擷取空格 未來可搭配vector,直接push_back()即可 直接看範例 ```cpp= #include <iostream> #include <string> #include <sstream> using namespace std; int main() { stringstream ss; string s; getline(cin, s); int arr[1000], value, i = 0; ss << s; //亦可宣告時直接賦值:stringstream ss(s); while(ss >> value) { arr[i] = value; i++; } for(int j = 0; j < i; j++) cout << arr[j] << '\n'; } ``` :::warning :::spoiler **vector版**(暫時不會沒關係) ```cpp= #include <iostream> #include <string> #include <vector> #include <sstream> using namespace std; int main() { string s; getline(cin, s); stringstream ss; ss << s; int value; vector<int> v; while(ss >> value) v.push_back(value); for(int i = 0; i < v.size(); i++) cout << v[i] << '\n'; } ``` ::: 輸入 ```cpp 123 456 789 ``` 輸出 ```cpp 123 456 789 ```
{"title":"字串string","description":"string為C++中字串,很像 vector<char> 或 char arr[] 的加強版(之後會介紹vector)雖然<iostream>函式庫中已經可以宣告string,但完整功能還是要引入<string>,如下:","lang":"zh-TW","contributors":"[{\"id\":\"06153efa-1421-4bf0-8011-540528c47f62\",\"add\":2539,\"del\":692},{\"id\":\"5e98ca27-a10e-43c9-93e9-2c4aa6b38ed6\",\"add\":4881,\"del\":699}]"}
Expand menu