<style> html, body, .ui-content { background-color: #333; color: #ddd; } body > .ui-infobar { display: none; } .ui-view-area > .ui-infobar { display: block; } .markdown-body h1{ color: #9CCEF2; } .markdown-body h2, .markdown-body h3{ color: #B1D6CA; } .markdown-body h4, .markdown-body h5, .markdown-body h6 { color: #ddd; } .markdown-body h1, .markdown-body h2 { border-bottom-color: #ffffff69; } .markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: #fff; } .markdown-body img { background-color: transparent; } .ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a { color: white; border-left: 2px solid white; } .expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus { color: white; } .ui-toc-dropdown { background-color: #333; } .ui-toc-label.btn { background-color: #191919; color: white; } .ui-toc-dropdown .nav>li>a:focus, .ui-toc-dropdown .nav>li>a:hover { color: white; border-left: 1px solid white; } .markdown-body blockquote { color: #bcbcbc; } .markdown-body table tr { background-color: #5f5f5f; } .markdown-body table tr:nth-child(2n) { background-color: #4f4f4f; } .markdown-body code, .markdown-body tt { color: #eee; background-color: rgba(230, 230, 230, 0.36); } a, .open-files-container li.selected a { color: #5EB7E0; } </style> ###### tags: `tgirc早修book` # string 字串 ## 宣告與賦值 ```cpp= #include<string> //string標頭檔,內含多種營養函式(? string str1; //宣告一個名為str1的string容器 //僅在c++可用,C語言未提供此型態 char str2[10]; //宣告一個名為str2的char陣列 //如果是使用C語言就只能用char陣列,沒法用string型態 str = "Hello world!"; //把"Hello world!"指定給str ``` 使用 string 型態時,建議引入 <font color="F5F6B6">**\<string>**</font> 標頭檔。 雖然現在不需要此標頭檔,也能宣告 string 及使用一些基本功能,不過一些功能還是要引入此標頭檔才能使用。 (嚴格來說 string 不算是一種型態,而是一種容器,不過現階段就先暫時先把它當成一種形態就好) ## 基本操作 ### <font color="F5F6B6">比較兩字串內容</font> 如果要看內容是否相同,直接用 `==` 就好了,與 `int` 等型態操作方式相同。 至於 `>` 跟 `<` 也能用,不過比較順序是按照字典序來排列。 ### <font color="F5F6B6">存取第n個字元</font> 就像陣列一樣,可以直接以 `str[n]` 的方式處理,但存取超過陣列範圍的字元會出問題。 保險起見可以使用 ``.at(n)``,會有邊界檢查。如果超出範圍的話,雖然編譯時會給過,但執行時它會拋出一個 `out_of_range` 例外並終止程式。 ```cpp= str = "Hello world!"; cout << str[4] << '\n'; cout << str.at(4) << '\n'; cout << str.at(15) << '\n'; //超出str範圍 //拋出exception: throws: out_of_range cout << str[4] << '\n'; cout << str.at(4) << '\n'; ``` 輸出如下: ``` o o ``` 使用 ``.at()`` 的穩定性較高,但一般時候其實用 `str[n]` 就好了,效率會比較好。 ### <font color="F5F6B6">取得字串長度</font> 使用 ``.size()`` 或是 ``.length()`` 兩者,在 string 上不會有明顯差異。 需要注意的是別忘了後面的括號 ()。 ```cpp= str = "Hello world!"; int S,L; S = str.size(); //把str的大小使用.size()指定給S L = str.length(); //把str的大小使用.length()指定給S cout << S << ' ' << L; ``` 輸出如下: ``` 12 12 ``` ### <font color="F5F6B6">串接兩字串</font> 可以使用 `+` 來串接兩字串,或是使用 `.append(str)` 來處理。 建議用 `+` 比較方便。 ```cpp= A = "Hello"; B = "Hello"; A += " world!"; //使用+來進行" world!"串接 B.append(" world!"); //或是使用.append() 把" world!"串接到A與B後 cout << A << '\n' << B; ``` 輸出如下: ``` Hello world! Hello world! ``` ### <font color="F5F6B6">string 轉 int、int 轉 string</font> 使用 `to_string(n)` 則可以將 n 轉為字串型態。 反過來說,`stoi(str)` 可以將 str 字串的內容轉為 int,而因為型態變為 int,開頭的 0 就會消失了 ```cpp= string str1 = "0324",str2; int n1 = 135,n2; n2 = stoi(str1); //將str1轉為int型態指定給n2 str2 = to_string(n1); //將n1轉為string型態指定給str2 cout << str2 << ' ' << n2; ``` 輸出如下: ``` 135 324 //str1原為"0324",轉為int後因為首位不會是0,所以變成324 ``` ### <font color="F5F6B6">取子字串</font> 使用 ``.substr(x,n)`` 來取得 x 開始的 n 個字組成的子字串。 ```cpp= str1 = "Hello world!"; cout << str1.substr(6, 5); //從str1的第6個字開始取5個字元 ``` 輸出如下: ``` world ``` ### <font color="F5F6B6">插入、取代與刪除字串</font> 使用 ``.insert(x,str)`` 在指定位置 x 插入 str。 取代則是用 ``.replace(x,n,str)``,把 x 開始的 n 個字元替換成 str。 刪除某段就用 ``.erase(x,n)``,把從 x 開始的 n 個字元刪掉。 切記,string 跟陣列一樣,第一個字元的位置是 0 而不是 1。 ```cpp= str = "Hello world!"; str.insert(5, " John"); //Hello John world! cout << str << '\n'; str.replace(6, 4, "Maria"); //Hello Maria world! cout << str << '\n'; str.erase(5, 6); //Hello world! cout<<str; ``` 輸出如下: ``` Hello John world! Hello Maria world! Hello world! ``` ### <font color="F5F6B6">尋找字串中指定字串</font> 使用 ``.find(str,n)`` 來尋找指定字串,回傳值為從n開始,找到的第一個str的開頭位置。 如果沒找到的話,則會回傳 string::npos。 ```cpp= str = "Hello world Hello"; if( str.find("Hello",0) != string::npos ){ //find("Hello",0) 不等於 string::npos //找到第一個"Hello"在第0個位置 cout << str.find("Hello",0) << '\n'; } else cout << "Not found!"; if( str.find("PPAP",0) != string::npos ){ cout << str.find("PPAP",0) << '\n'; } else cout << "Not found!"; //find("PPAP",0) 等於 string::npos //也就是找不到"PPAP" ``` 輸出如下: ``` 0 Not found! ``` ### <font color="F5F6B6">反轉字串</font> 這個是搭配 `reverse(a, b)` 函式來使用的,比較特別的是 a 跟 b 要傳入的是<font color="F5F6B6">**位置**</font>。 如果要從 str 的開頭到結尾反轉,那 a 就是 `str.begin()`,代表 str 開頭的位置,而 b 則是 `str.end()`,代表 str 的結尾位置。 而如果是從第二個字元開始,那就把 a 換成 `str.begin() + 1`。 如果只翻轉到倒數第二個,那就把 b 換成 `str.end()-1`,簡而言之,往後一個就 +1,往前一個就 -1。 如果要使用 `reverse()`,記得要引入 <font color="F5F6B6">**\<algorithm\>**</font> 標頭檔。 ```cpp= #include <algorithm> //包含了reverse()在內 . . . str = "Hello world!"; reverse(str.begin(), str.end()); //由str的第一個至最後一個反轉 cout << str << '\n'; ``` 輸出如下: ``` !dlrow olleH ``` ## 使用 getline 進行整行輸入 一般使用 `cin` 輸入字串時,每遇到空格或換行,就會判斷為結束輸入。 但如果需要輸入一個文章,或是一段完整句子, `cin` 就無法完整輸入,因此會需要用到 `getline`。 ```cpp= string s; getline(cin, s); cout << s << '\n'; ``` ![](https://i.imgur.com/3Rvavsj.png) 使用 `getline()` 輸入不會被空格截斷,每遇到換行會先接收換行的指令,再跳到下一個輸入 可以參考以下例子 <font color="F5F6B6">**範例 1**</font> ```cpp= cin >> a; getline(cin, str); cout << a << '\n' << str; ``` ![](https://i.imgur.com/kYlyDi5.png) 在這個例子中,我們輸入了 a 以後,還沒輸入字串程式就結束了 這是因為 cin 完最後的位子在 3 的後一格,所以 getline 讀到的是換行,而 getline 遇到換行會停下。 所以要輸入一段字串的話,要使用兩次 `getline()`(或是 `gets()`/`getchar()`)。 第一個吃掉換行,第二格才是輸入你要輸入的字串 ```cpp= cin >> a; getline(); getline(cin, str); cout << a << '\n' << str; ``` ![](https://i.imgur.com/6zN8KAP.png)