目录
章节内容导读:
键盘输入和屏幕输出是编写简单的顺序结构程序时最常用到的操作。C 程序中的键盘输入和屏幕输出都是通过调用输入 / 输出函数实现的。本章介绍常用的输入 / 输出函数,建议这部分内容当作手册内容即用即学,或者自学 “C 语言程序设计精髓” MOOC 课程中的第 3 周视频,主要内容如下:
- 字符常量与转义字符
- 字符输入函数 getchar() 与字符输出函数 putchar()
- 数据的格式化输出函数 printf() 与数据的格式化输入函数 scanf()
4.1.1 字符常量
C 语言中的字符常量是用单引号(')括起来的一个字符。例如,'a' 是字符常量,而 a 则是一个标识符。再如,'3' 表示一个字符常量,而 3 则表示一个整数。
注意,单引号里面至少要有一个字符,不能为空。如果尝试创建一个空的字符常量(即两个相邻的单引号而没有字符,如 ''),编译器会报错,因为这不是一个有效的字符常量。
转义字符
把字符放在一对单引号里的做法,适用于多数可打印字符,但不适用于某些控制字符(如回车符、换行符等)。
C 语言中用转义字符(Escape Character)即以反斜线(\)开头的字符序列来描述特定的控制字符。常用的转义字符如表 4-1 所示。
- 例如,前几章的程序实例中涉及的字符 '\n',就是一种转义字符,它用于控制输出时的换行处理,即将光标移到下一行的起始位置。
- 与 '\n' 不同的是,'\r' 则表示回车,但不换行,即将光标移到当前行的起始位置。
- 再如,'\0' 代表 ASCII 码值为 0 的字符,它代表一个字符,而不是两个字符,通常用作字符串的结束标志。
- 而 '\t' 为水平制表符,相当于按下 Tab 键。屏幕上的一行通常被划分成若干个域,相邻域之间的交界点称为 “制表位”,每个域的宽度就是一个 Tab 宽度,有些开发环境对 Tab 宽度的默认设置为 4,而有些则为 8,多数人习惯上将其设置为 4。
- 注意,每次按下 Tab 键,并不是从当前光标位置向后移动一个 Tab 宽度,而是移到下一个制表位,实际移动的宽度视当前光标位置距相邻的下一个制表位的距离而定。
另外值得注意的是:当转义序列出现在字符串中时,是按单个字符计数的。例如,字符串 "abc\n" 的长度是 4,而非 5。因为字符 '\n' 代表 1 个字符。
ASCII 码
由于字符型(char)变量仅占 1 个字节的内存空间,因此它只能存放 1 个字符。
字符型变量的取值范围取决于计算机系统所使用的字符集。目前计算机上广泛使用的字符集是 ASCII 码(美国标准信息交换码)字符集(详见附录 D)。该字符集规定了每个字符所对应的编码,即在字符序列中的 “序号”。也就是说,每个字符都有一个等价的整型值与其相对应,这个整型值就是该字符的 ASCII 码。从这个意义上而言,可将 char 型看成是一种特殊的 int 型。
一个整型数在内存中是以二进制形式存储的,而一个字符在内存中也是以其对应的 ASCII 码的二进制形式存储的。例如,字符 'A' 在内存中存储的是其 ASCII 码 65 的二进制值,存储形式与整型数 65 类似,只是在内存中所占的字节数不同而已。char 型数据占 1 个字节,而 int 型数据在 16 位系统中占 2 个字节,在 32 位系统中占 4 个字节。
在 ASCII 码取值范围内,对 char 型数据和 int 型数据进行相互转换不会丢失信息,二者可以进行混合运算。同时,一个 char 型数据既能以字符型格式输出(%c),也能以整型格式输出(%d),以整型格式输出时就是直接输出其 ASCII 码的十进制值。
Unicode 字符集
由于不同国家和地区制定的编码标准互不兼容,无法将不同语言的文字存储在同一段编码的文本中,不便于国际的信息交流,不能跨语言、跨平台文本转换和处理,为了解决这个问题,国际标准化组织(ISO)制定了更强大的编码标准——Unicode 字符集,为各种语言中的每个字符设定统一且唯一的数字编号,所有字符统一用 2 个字节保存,也称为宽字节字符。
4.1.2 字符的输入输出
getchar() 和 putchar()
getchar() 和 putchar() 是 C 标准函数库中专门用于字符输入 / 输出的函数。
int getchar(void);
- 功能描述:从标准输入(通常是键盘)读取一个字符,并返回该字符的 ASCII 值。
- 返回值:成功时返回读取的字符(作为一个 int 值,即 ASCII 码值),遇到文件结束(End-Of-File)或读取错误时返回 EOF(通常定义为 -1)。
int putchar(int c);
- 功能描述:将一个字符写入标准输出(通常是屏幕)。
- 参数:c 是要输出的字符,类型为 int,但实际传递的是字符的 ASCII 值。
- 返回值:成功时返回写入的字符(作为一个 int 值,即 ASCII 码值),遇到写入错误时返回 EOF(通常定义为 -1)。
输入缓冲区
当程序调用 getchar() 时,程序会等待用户按键。用户从键盘输入的字符首先会被放入输入缓冲区中,直到用户按下回车键为止(回车符也会被放入输入缓冲区中)。当用户按下回车后,getchar() 开始从标准输入流中读取字符,每次调用只读取一个字符,其返回值是用户输入字符的 ASCII 码。
- 文件结尾:如果遇到文件结尾(通常是 EOF,可以通过 Ctrl+D 在 Unix/Linux 系统或 Ctrl+Z 在 Windows 系统中输入),getchar() 将返回 -1。
- 字符回显:用户输入的字符会回显到屏幕上。
- 缓冲区处理:如果用户在按回车之前输入了多个字符,这些字符会继续留在输入缓冲区中,等待后续的 getchar() 调用来读取。即,后续的 getchar() 调用会直接从缓冲区中读取字符,直到缓冲区中的字符(包括回车)全部读完后,才会再次等待用户按键。只要缓冲区中有字符,getchar() 就不会等待用户的按键操作。
示例:字母大小写转换
【例 4.1】从键盘输入一个大写英文字母,将其转换为小写字母后,再显示到屏幕上。
【问题求解方法分析】观察附录 D 中的常用 ASCII 字符表,可以发现这样一个规律,即小写英文字母的 ASCII 码值比相应的大写英文字母的 ASCII 码值大 32,即 'a' 与 'A','b' 与 'B','c' 与 'C'……的 ASCII 码值均相差 32。根据这一规律,可轻松实现大小写英文字母之间的转换。程序如下:
#include <stdio.h>
int main(void)
{
char ch;
printf("Press a key and then press Enter: ");
ch = getchar(); // 从键盘输入一个字符,按回车键结束输入,该字符被存入变量 ch
ch = ch + 32; // 将大写英文字母转换为小写英文字母
putchar(ch); // 在屏幕上显示变量 ch 中的字符
putchar('\n'); // 输出一个回车换行控制符
return 0;
}
程序的运行结果如下:
程序第 7 行语句首先调用函数 getchar() 从键盘输入一个字符,然后将读入的字符即函数 getchar() 的返回值赋值给字符型变量 ch(涉及 int 到 char 的自动类型转换)。注意,函数 getchar() 没有参数,函数的返回值就是从终端键盘读入的字符。因此,不要把该语句写成如下形式:
getchar(ch); /* 错误的使用方法 */
第 8 行语句将变量 ch 中的大写英文字母的 ASCII 码值加上 32,即可得到相应的小写英文字母的 ASCII 码值,从而实现大写英文字母到小写英文字母的转换。由于字符 'a' 与字符 'A' 相减,相当于字符 'a' 与字符 'A' 的 ASCII 码值相减,也相当于字符 'b' 与字符 'B' 的 ASCII 码值相减……而二者相减的差值就是 32,因此第 8 行语句与下面的语句是等价的:
ch = ch + ('a' - 'A');
第 9 行语句调用函数 putchar() 向终端显示器屏幕的当前光标位置输出 ch 中的字符,函数 putchar() 的参数就是待输出的字符,这个字符既可以是可打印字符,也可以是转义字符。例如,第 10 行调用函数 putchar() 输出的就是转义字符 \n,作用是将光标换到下一行的起始位置。