<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{
color: #B1D6CA;
}
.markdown-body h3{
color: #F5F6B6;
}
.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: `雜~~瓦魯多~~筆記`
# 跳脫字元是啥,會跳脫嗎?
跳脫字元是一種「特別」的字元,至於特別在哪呢?這就帶你來看看它的特別之處。
[TOC]
## 首先試試這題
在閱讀後段之前,各位可以先試試這個小任務,也許會對後面的內容更有感覺。
那麼,請輸出以下的字串試試看:
* `\\>w<\\`
* `"o"`
* `\n\t\n\t`
如果直接把這些字串放在 `cout` 輸出,那結果會如下,沒一個是正常的:
* `\\\>w<\\\`
```cpp=
cout<<"\\>w<\\";
```
```
\>w<\
```
* `"o"`
```cpp=
cout<<""o"";
```
```
Line 5: [Error] unable to find string literal operator ‘operator""o’ with ‘const char [1]’, ‘long unsigned int’ arguments
```
* `\n\t\n\t`
```cpp=
cout<<"\n\t\n\t";
```
```
```
## 特殊的字元 - 跳脫字元
剛剛的幾個字串,第一個例子左右各少了一個 `\` ,第二個直接編譯錯誤,最後一個則是看來啥都沒輸出。
這是因為,第一個例子中的 `\\` 被看作是一個字元,第三個的 `\n` 與 `\t` 則各自被看作是換行與 tab 。
第二個中的 `"` 則被看作是程式執行中,字串的開頭結尾符號。
*輸出特殊符號* ,這就是跳脫字元的功能。
以下列出一些常見的跳脫字元:
* `\n` :換行
* `\t` :tab(大約是4個空白鍵)
* `\\` :反斜線 `\`
* `\"` :雙引號 `"`
* `\'` :單引號 `'`
* `\0` :null 空字元(不等於空白,它就是一個空的字元)
* `\b` :backspace(後退一個字元,需再補上其他字元填補原本字元的位置)
* `\r` :回到該行開頭(後續輸出內容會覆蓋原本該行內容)
所以像剛剛的第一個例子,要輸出 `\` 時,應該如下:
```cpp=
cout<<"\\\\>w<\\\\"; // 將 \ 換成 \\
```
而第二個例子,要輸出 `"` 則是如下:
```cpp=
cout<<"\"o\""; // 將 " 換成 \"
```
第三個例子也是像第一個例子,在每個 `\` 前頭再加上一個反斜線,變成 `\\`。
這樣原本該被輸出的 `\` ,才不會被跟後方的 `n` 及 `t` 看做是 `\n` 與 `\t` 。
## \n 與 \<\<endl
上面提到, `\n` 代表的字元是換行字元。
不知道各位還記不記得,在一開始學到 `cout` 時,有講過 `<<endl` 這個東西,功能也是換行。
乍看之下,兩者的功能沒啥太大的差別,但如果輸出的資料量很大時,`<<endl` 的速度會比 `\n` 慢上許多!
這是因為 `<<endl` 在輸出一個換行後,會再執行一個「清空緩衝區」的動作。
至於 `\n` 需要額外加上 `<<flush` 才會清空緩衝區。
所以,以下兩行功能會是相同的,:
```cpp=
cout << "\n" << flush;
cout << endl;
```
這裡就不多解釋緩衝區是什麼意思了,有興趣再自行搜尋就好。
各位只需要記得 `<<endl` 會比 `\n` 多一步手續,執行速度也會比 `\n` 來的慢。
所以解題時也建議使用 `\n` 來取代 `<<endl` ,避免造成 `TLE` (Time Limit Exceed)。
## 小結
如果以上的有看懂,那相信 [e926: 跳脫字元](https://zerojudge.tw/ShowProblem?problemid=e926) 以及 [d559: 班號](https://zerojudge.tw/ShowProblem?problemid=d559) 這兩題,對各位應該不是難事。
在輸出字串時,記得檢查一下有沒有特殊字元會被判定為跳脫字元,或是該做為跳脫字元卻未加上 `\` 的。
另外在解題時,建議使用 `\n` ,比起使用 `<<endl` ,可以加快執行的速度。
保持良好檢查習慣,這樣才能避免輸出錯誤造成 `WA` (Wrong Answer)或是 `TLE` (Time Limit Exceed),或是更慘的直接吃個 `CE` (Compile Error)。