<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';
```

使用 `getline()` 輸入不會被空格截斷,每遇到換行會先接收換行的指令,再跳到下一個輸入
可以參考以下例子
<font color="F5F6B6">**範例 1**</font>
```cpp=
cin >> a;
getline(cin, str);
cout << a << '\n' << str;
```

在這個例子中,我們輸入了 a 以後,還沒輸入字串程式就結束了
這是因為 cin 完最後的位子在 3 的後一格,所以 getline 讀到的是換行,而 getline 遇到換行會停下。
所以要輸入一段字串的話,要使用兩次 `getline()`(或是 `gets()`/`getchar()`)。
第一個吃掉換行,第二格才是輸入你要輸入的字串
```cpp=
cin >> a;
getline();
getline(cin, str);
cout << a << '\n' << str;
```
