在输入文本时,回车键一敲,就开始了新的一行,这个习惯性用法难免误导 C/C++ 的初学者们对 回车符(CR, Carriage Return)'r' 和 换行符(LF, Linefeed)'n' 的理解,这里这个问题我们暂且放下,后文再谈。先让我们来看看关于“回车”的有趣历史来源。
关于“回车键”的来历,要追朔到机械英文打字机的时代。在这种打字机上有个叫“字车”的部件,大概就是下面那个部分,会左右不停地跑的那东西。
当输满一行后,使用者就要把“字车”推到起始位置,这时打字机就会有两个动作,一是“字车”归位,二是滚筒上卷一行(相当于“字车”下移一行),这样就可以开始输入下一行了,这里推动“字车”的动作就称为“回车”。
上述打字机的“字符”归位的动作就相当于我们的 回车 'r',只回到行首而仍在当前行,而滚筒上卷的动作就相当于 换行 'n',移动到下一行。回车符 'r' 对应 ASCII 码的16进制是 0x0d,10进制是 13,换行符 'n' 对应16进制是 0x0a, 10进制是 10。
而不同的系统对回车的处理是不同的:在我们常用的 Windows 系统中用 "rn"两个字符来表示,如图,在第一行与第二行之间有两个字符位,分别是 0D 0A,即 ASCII 码对应的 'r'和'n'。这样的表示方法就和打字机的行为很相似了。
那么,同样的方法,在 Linux 上会是什么情况呢?请继续看。
在 Linux 上通过 vim 我们看到,在 a, ab, abc 之间只有一个字符位了,对应的是 0a,即 ASCII 码中的 'n',这就说明在 Linux 上只用了一个换行字符来表示。
那么接下来让我们回到 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("abcrncbarrrbzn");
6 printf("abcdbb");
7 getchar();
8
9 return 0;
10 }
C++代码:
#include <iostream>
int main(int argc, char const *argv[])
{
using namespace std;
cout << "abcrncbarrrbzn";
cout << "abcdbb";
cin.get();
return 0;
}
首先我们看下输出的第一行"abcrncbarrrbzn":
在输出 abc 后 r 使回车符回到当前行即第一行的行首,但不删除字符,所以第一行最终显示 abc,然后 n 使光标移到下一行,接着输出 cba,r再次让光标回到行首,这次不换行,直接接着输出 rr,这样达到的效果是行首两个字符 cb 被替换为 rr,接着 b 使光标向前一位,输出 z,这样第二个 r 就被换成了 z,然后换行,最终第二行显示结果就是 rza。
接着为了更直观地证明只有光标移动而不删除字符,我们看看第二行代码。"abcdbb",在两个 b 过后,光标向前移动到 c 的下面(或者是 c 上的方块光标,亦或是在 c 前的 I 形光标),为了使光标停留以便观察,我们添加了 getchar() 和 cin.get()。
所以程序运行后的结果将是:
abc
rza
abcd
同时可以看到光标停留在上述位置,当然,这时如果你再输入字符,就会从光标的位置开始向后将 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** |
** |