<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)。