標籤:
在輸入文本時,斷行符號鍵一敲,就開始了新的一行,這個習慣性用法難免誤導 C/C++ 的初學者們對 斷行符號符(CR, Carriage Return)‘\r‘ 和 分行符號(LF, Linefeed)‘\n‘ 的理解,這裡這個問題我們暫且放下,後文再談。先讓我們來看看關於“斷行符號”的有趣曆史來源。
關於“斷行符號鍵”的來曆,要追朔到機械英文打字機的時代。在這種打字機上有個叫“字車”的組件,大概就是下面那個部分,會左右不停地跑的那東西。
當輸滿一行後,使用者就要把“字車”推到起始位置,這時打字機就會有兩個動作,一是“字車”歸位,二是滾筒上卷一行(相當於“字車”下移一行),這樣就可以開始輸入下一行了,這裡推動“字車”的動作就稱為“斷行符號”。
上述打字機的“字元”歸位的動作就相當於我們的 斷行符號 ‘\r‘,只回到行首而仍在當前行,而滾筒上卷的動作就相當於 換行 ‘\n‘,移動到下一行。斷行符號符 ‘\r‘ 對應 ASCII 碼的16進位是 0x0d,10進位是 13,分行符號 ‘\n‘ 對應16進位是 0x0a, 10進位是 10。
而不同的系統對斷行符號的處理是不同的:在我們常用的 Windows 系統中用 "\r\n"兩個字元來表示,,在第一行與第二行之間有兩個字元位,分別是 0D 0A,即 ASCII 碼對應的 ‘\r‘和‘\n‘。這樣的表示方法就和打字機的行為很相似了。
那麼,同樣的方法,在 Linux 上會是什麼情況呢?請繼續看。
在 Linux 上通過 vim 我們看到,在 a, ab, abc 之間只有一個字元位了,對應的是 0a,即 ASCII 碼中的 ‘\n‘,這就說明在 Linux 上只用了一個換行字元來表示,事實上,包括 Mac OS 在內的 Unix 系統也是這樣的。
那麼接下來讓我們回到 C/C++ 中 ‘\r‘ 和 ‘\n‘ 的討論中吧。在 C/C++ 中原風原味地保留了對分行符號的這種理解,斷行符號符 ‘\r‘ 僅表示回到行首,並沒有包含換行的動作,換行是由 ‘\n‘ 來完成的,初學者一定要分清這兩個符號的意義。
這裡再提一個與 ‘\r‘ ‘\n‘ 類似的一個逸出字元:退格(BS, Backspace)‘\b‘,顧名思義,這個字元的意義是往前退一格,這裡需要特別提醒的是:退格 ‘\b‘ 和斷行符號 ‘\r‘ 都只是游標的移動,不會刪除前面的文本!
現在讓我們用一段簡單的代碼來驗證 ‘\r‘ ‘\n‘ ‘\b‘ 的作用效果。
C代碼:
1 #include <stdio.h> 2 3 int main(int argc, char const *argv[]) 4 { 5 printf("abc\r\ncba\rrr\bz\n"); 6 printf("abcd\b\b"); 7 getchar(); 8 9 return 0;10 }
C++代碼:
#include <iostream>int main(int argc, char const *argv[]){ using namespace std; cout << "abc\r\ncba\rrr\bz\n"; cout << "abcd\b\b"; cin.get(); return 0;}
首先我們看下輸出的第一行 "abc\r\ncba\rrr\bz\n":
在輸出 abc 後 \r 使斷行符號符回到當前行即第一行的行首,但不刪除字元,所以第一行最終顯示 abc,然後 \n 使游標移到下一行,接著輸出 cba,\r再次讓游標回到行首,這次不換行,直接接著輸出 rr,這樣達到的效果是行首兩個字元 cb 被替換為 rr,接著 \b 使游標向前一位,輸出 z,這樣第二個 r 就被換成了 z,然後換行,最終第二行顯示結果就是 rza。
接著為了更直觀地證明只有游標移動而不刪除字元,我們看看第二行代碼。"abcd\b\b",在兩個 \b 過後,游標向前移動到 c 的下面(或者是 c 上的方塊游標,亦或是在 c 前的 I 形游標),為了使游標停留以便觀察,我們添加了 getchar() 和 cin.get()。
所以程式運行後的結果將是:
abcrzaabcd
同時可以看到游標停留在上述位置,當然,這時如果你再輸入字元,就會從游標的位置開始向後將 c 甚至 d 覆蓋。
最後,附上一張逸出字元的表格,供大家參考。
| 逸出字元 |
意義 |
ASCII碼值(十進位) |
ASCII碼值(十六進位) |
| \a |
響鈴(BEL) |
007 |
0x07 |
| \b |
退格(BS) ,將當前位置移到前一列 |
008 |
0x08 |
| \f |
換頁(FF),將當前位置移到下頁開頭 |
012 |
0x0C |
| \n |
換行(LF) ,將當前位置移到下一行開頭 |
010 |
0x0A |
| \r |
斷行符號(CR) ,將當前位置移到本行開頭 |
013 |
0x0D |
| \t |
水平製表(HT) (跳到下一個TAB位置) |
009 |
0x09 |
| \v |
垂直製表(VT) |
011 |
0x0B |
| \\ |
代表一個反斜線字元‘‘\‘ |
092 |
0x5C |
| \‘ |
代表一個單引號(撇號)字元 |
039 |
0x27 |
| \" |
代表一個雙引號字元 |
034 |
0x22 |
\?
|
代表一個問號
|
063
|
0x3F |
| \0 |
Null 字元(NULL) |
000 |
0x00 |
| \ddd |
1到3位八位元所代表的任一字元 |
三位八進位 |
| \xhh |
1到2位十六進位所代表的任一字元 |
二位十六進位 |
小提醒:不要把斜杠搞反咯。\轉\義\字\符
關於“斷行符號”的有趣曆史 及 “斷行符號”與“換行”的區別