《C语言入门1.2.3—一个老鸟的C语言学习心得》—清华大学出版社炮制的又一本劣书及伪书
【薛非评】
区区15页,有80多个错误。
最严重的有:
通篇完全是C++代码,根本不是C语言代码。其中的很多代码根本不可能通过编译。仅此足矣说明该书不仅是一本劣书,而是一本挂羊头卖狗肉的伪书。
通篇的void main()。C语言从来没说过可以这样写main()。
很多地方完全是一个外行荒唐的臆想和信口开河,如: “scanf("%d,%d\n",&a,&b);
该格式字符串在之前的字符串基础上,增加了一个\n 换行符。但是输入函数并不认为格式字符串中的\n 是一个换行符,而是将其视做一个反斜杠\和一个字母n。因此在输入的时候,还应当输入这两个字符。正确的输入应当为:
18,33\n”
================================================================
第3 章 输入与输出
任何一个完整的程序应当包括输入【错:程序可以没有输入】和输出(Input/Output)功能。通过输入功能程序使用者能根据需要使用程序,通过输出功能使用者能得到程序运行的反馈。前面章节已经对C 语言的输出方法有所了解,本章将详细介绍C 语言的输入输出方法,主要学习C 语言在标准输入输出设备上(屏幕和键盘)的输入输出。关于磁盘文件的输入输出方法,将在第9 章进行讲解。本章涉及的知识点有:
q 格式化输出和输入函数的使用。
q 常用的字符输入输出函数。
3.1 输入输出——让人与机器交流的窗口
输入输出(Input/Output,也称做I/O),是计算机的重要组成部分。输入是指计算机程序在计算机中运行,需要的数据通过输入操作从外部设备中输入到计算机内部。输出是指计算机程序运行过程中或结束时,将程序运算的结果在外部设备上显示或打印到外部设备上。
输入输出需要通过必要的设备才能完成,输入设备通常是鼠标和键盘,输出设备通常是显示器。程序真正处理的地方,仅在主机的内存和CPU 上。在计算机运行某个程序时,其运算过程的相关的指令和数据都将被转换成二进制形式的电信号。程序的用户想要知道程序的运行状况和结果,就必须使用输出设备将程序数据转换成为人能识别的文字或图像信息。若用户想控制正在执行的程序,也必须通过输入设备,将指令输入到主机中去。人与计算机交流的过程如图3-1 所示。
输入输出是人与机器进行交流的窗口。大多数的程序在编写过程中,都需要有输入和输出功能。对于编程语言而言,输入输出功能体现在它能够提供某些方法来打开计算机的输入输出设备供给程序用户使用。程序的用户通常不是程序的设计者,他们并不知道程序内部实现的步骤,只能通过必要的输入和相应的输出结果来判断程序功能是否有用。在设计程序的时候,就需要考虑到使用者并不知道何时输入、输入什么样的数据等问题。因此,编写程序时必要的提示信息和非法输入数据的检测也很重要。例如当需要用户输入一个数据时,应该有相应的提示;当需要输入整数时,用户可能会输入浮点数等情况出现。程序员需要对全部的程序功能负责,并且需要控制好输入输出。这才能保证程序的最终用户与计算机之间的交流畅通无阻。
在C 语言中,没有直接提供输入和输出的语句,只能从标准函数库中调用相应的输入和输出函数来实现。在调用这些函数时,需要在代码文件的开始加入编译预处理语句【错:语句是程序执行的动作,预处理和程序执行无关】#include<stdio.h>,使头文件stdio.h 包含到用户的源程序中。stdio.h 文件包括所有标准输入输出的库函数【错:stdio.h 文件中有的只是一些声明和宏而已】。
图3-1 人与计算机交流的过程
3.2 格式化的输入输出
C 语言中使用格式化的输入输出方法,本节将讲解格式化输出函数printf()和格式化输入函数scanf()。
3.2.1 格式化输出函数printf()
printf()函数的功能是让计算机系统默认的输出设备(一般是显示器)输出一个或多个任意数据类型的数据【错:printf()函数不可能输出任意数据类型的数据】。其基本格式为:
printf("格式控制参数",输出项1,输出项2,…,输出项n);
其中格式控制参数是以字符串的形式描述的,也成【错别字】为格式控制字符串。格式控制参数包括普通字符和格式说明项。
1.普通字符
普通字符包括可打印字符和转义字符【错:这并非是两个互斥的概念,转义字符也可以是可打印字符】。可打印字符主要起说明作用,可以按字符的原样显示在屏幕上。转义字符是不可打印的字符【错:胡扯】,输出转义字符可以实现控制字符显示等特殊效果【错:不知所云】。printf()函数除了支持ASCII 中的字符【错:支持ASCII不是必须的】,还可以输出汉字。
2.格式说明项
在前面一章的学习中,已经接触到了关于整数、浮点数和字符输出的格式说明项。格式说明项是由%与格式字符组成,其作用是将数据转换为指定的格式进行输出,不同的数据类型有不同的格式字符。
q d 格式字符,用于输出十进制整数。%d、%hd、%ld 分别用于输出整型、短整型【错:片面的描述】和长整型。【错:前面讲“用于输出十进制整数”,后面“用于输出整型…”,言外之意是“整型…”是“十进制”的,误导。】
q o 格式字符,用于输出八进制整数。
q x 格式字符,用于输出十六进制整数。
q u 格式字符,用于输出unsigned 的整数。【错:“unsigned 的整数”与前面的“十进制整数”、“八进制整数”及“十六进制整数”并列,逻辑错乱】
q c 格式字符,用于输出一个字符【错:输出几个字符与很多因素有关。如果这里的字符指的是转换对象为char类型,同样是错的。】。
q s 格式字符,用于输出一个字符串。
q f 格式字符,用于输出一个浮点数。%f 和%lf 分别控制输出单精度和双精度浮点数【错:%lf与%f完全等价】。小数部分保留6 位。
q e 格式字符,用于以指数形式输出浮点数。
q g 格式字符,用于输出浮点数,系统根据输出数据的宽度自动选择使用f 格式或e格式【错:根据的不是数据的宽度】。
如代码3-1 所示,实现各种数据类型的输出。
代码3-1 各种数据类型的输出(3-1.cpp)【大错特错:这个根本就不是C语言的代码,而是C++代码。参见《品悟C》<问题1 C啊,多少C++假汝之名而行——C、C++不分>】
01 #include <stdio.h>
02 void main()【错:参见《品悟C》<五花八门的main()> http://www.cnblogs.com/pmer/archive/2011/09/08/2171823.html 】
03 {
04 short snum = 100; //短整型变量
05 int num = 200; //整型变量
06 long lnum = 300; //长整型变量
07 printf("%hd\t%d\t%ld\n",snum,num,lnum);
//使用%hd、%d、%ld 输出这个3 个变量
08
09 float fnum = 1.23f; //单精度浮点数【大错特错:对于基于C90的VC++6.0来说,这根本无法通过编译】
10 double dnum = 1.234; //双精度浮点数
11 printf("%f\t%lf\n",fnum,dnum); //使用%f、%lf 输出这两个变量【错:画蛇添足。使用任一种皆可】
12 printf("%e\t%g\n",fnum,dnum); //使用%e、%g 输出这两个变量
13
14 char ch = 'C'; //字符变量
15 printf("%s%c\n","the character is :",ch);
//使用%s 输出字符串常量
16 } //使用%c 输出字符变量【错:这里输出的其实是 (int)ch 】
这段代码的执行结果为:
100 200 300
1.230000 1.234000
1.230000e+000 1.234
the character is :C
代码第04~06 行分别定义了短整型变量snum、整型变量num 和长整型变量lnum。
这3 种数据类型分别使用%hd、%d 和%ld 格式说明项。【错:其实输出的还是int类型的值】
%注意:在本段代码中,这些变量不采用其对应的数据类型的说明项,输出也不会有任何问题【错:fnum就不能用%d】。但如果变量中保存的值,与说明项对应数据类型的取值范围不一致,将会导致问题【错:这个问题根本扯不到范围问题上】。例如将lnum 的值改为30000000【错:这是根本不可能的】,而输出的时候按短整型输出(使用%hd),则输出的结果将会发生溢出【错:根本就不存在输出结果溢出这回事】,结果将不再是30000000【错:结果从来就不是30000000,哪来的什么“不再”?】,而是-15488。
代码第09 和第10 行定义了一个单精度浮点数fnum 和一个双精度浮点数dnum。【错:这种定义对于VC++6.0是非法的】分别使用格式说明符%f 和%lf 输出,此时输出数据的形式是小数形式。同时,如果要使其输出的形式为指数形式,就要使用%e。代码第12 行使用%e 将fnum 输出为指数形式,而使用%g 输出dnum,通过判断dnum 的宽度【错:不是通过判断宽度】,最终仍然输出小数形式。
代码第15 行,输出了一个字符串常量和一个字符变量。字符串常量除了以格式字符串的形式输出外,还可以像变量一样使用格式控制项%s 将其输出。
3.输出宽度
在通过%d、%hd 和%ld 输出整型变量时,可以通过在百分号%与格式字符之间增加一个字段宽度m,来控制输出数据的宽度。格式说明项相应改变为%md、%mhd 和%mld,其中m 是1~9 之间的数字【错:没这回事】。如果整数的位数小于m,则输出结果在最左端用空格补齐;如果整数的位数大于m,则输出结果按实际的长度输出。数据宽度是指一个数值的位数。例如,整数123 有3 位有效数字,如果指定数据宽度m 为5,输出的123 前面将有两个空格;如果指定m 为1,则仍然输出123。
如代码3-2 所示,展示了通过%md 控制整数输出的宽度。
代码3-2 指定整数输出的进制和宽度(3-2.cpp)
01 #include <stdio.h>
02 void main()
03 {
04 int num = 200;
05 printf("%d\t%o\t%x\n",num,num,num); //指定整数输出为十、八、十六进制
06 printf("%5d\t%3d\t%2d\n",num,num,num); //指定输出宽度为5、3、2
07
08 }
代码的输出结果为:
200 310 c8
200 200 200
从输出结果可以看出,代码第05 行分别使用%d、%o 和%x 对同一个变量num 进行输出控制。输出结果为这个数的十进制、八进制和十六进制形式。同时从结果第2 行可以看出,第1 个200 前多了两个空格,这是由于代码第06 行输出第1 个整型变量时,指定其宽度为5 位,如果指定宽度大于数据宽度,则使用空格进行填充。当指定宽度小于或等于数据宽度时,则仍然按照该数据实际宽度输出。
%注意:使用转义字符\t 之后,输出数据应该按照列进行左对齐。【错:对\t的误解】
同样,在使用%f 和%lf 输出浮点数时,也可以使用%m.nf 和%m.nlf 来控制输出数据的宽度。其中m 表示数据的宽度(小数点同样占用1 位),n 表示小数的位数。如果数据的位数小于m,则左端补齐;如果数据的数位大于m,则按实际长度输出。例如,输出浮点数1.36,指定m 为5,n 为1,则输出为“ 1.4”。小数位后只保留1 位,其余位四舍五入【无依据的说法】,整数位不足按空格补齐。
如代码3-3 所示,实现的是控制浮点数输出的宽度。
代码3-3 指定输出浮点数的宽度(3-3.cpp)
01 #include <stdio.h>
02 void main()
03 {
04 double dnum = 123.321;
05 printf("%10.5lf\n",dnum); //输出数据宽度为10【错:应为宽度至少为10】,小数占5 位
06 printf("%6.2lf\n",dnum); //输出数据宽度为6,小数占2 位
07 printf("%3.0lf\t%3lf\n",dnum,dnum); //小数占0 位与省略小数宽度
08 printf("%0.5lf\t%.5lf\n",dnum,dnum); //数据宽度为0【错:这个0说的根本就不是宽度】 位与省略数据宽度
09 }
代码的输出结果为:
123.32100
123.32
123 123.321000
123.32100 123.32100
printf()函数输出双精度浮点数时,使用%m.nlf 控制输出数据的宽度。代码第05 行,当输出宽度10 大于数据宽度7,输出小数位5 大于实际小数占的位数3,则首先小数部分以0 补齐,整数部分以空格补齐,因此输出 123.32100。而代码第06 行则刚好相反,整数部分和小数部分的输出宽度都小于实际数据的宽度【错:“整数部分”“输出宽度”是子虚乌有的说法】,则小数部分保留指定位数(多余位四舍五入【无依据的说法】),整数部分按123 原样输出,输出结果为123.32。
在使用%m.nlf 控制输出数据宽度时,可以省略m 或n,但两者不可同时省略。在使用省略宽度数值时,尤其要注意省略数值与指定数值为0 的区别。代码第07 行,指定了输出小数部分占用0 位和不指定输出的小数位数n。从输出结果可以看出,指定小数部分占用0位输出时将不再带有小数,并且小数点也没有了。而没有指定小数位的输出,则按照正常%lf 的输出,保留了小数的6 位数字。代码第08 行,则是指定输出数据宽度为0 【错:这个0说的不是宽度】和省略数据宽度。从结果可以看出,它们的小数部分都按指定宽度输出,但整数部分仍然按原样输出。
%注意:从这里可以看出,printf()函数输出一个浮点数时,默认采用的是%.6lf。【错:浮点数其实至少有3种类型;这个l毫无意义】
以指数形式输出浮点数时,同样可以使用%m.ne 的形式控制输出数据的宽度。m 和n的含义与%m.nf 的含义相同,这里不再介绍。
另外,使用printf()函数输出数据时,还可以在百分号%与格式字符之间增加减号-,来实现数据按左对齐输出。在百分号%与格式字符之间增加0 可以在数据前使用0 补齐【这与前面“宽度为0”的说法自相矛盾,两者必有一错】(默认为空格)。
如代码3-4 所示,指定用0 补齐数据
代码3-4 用数字0 补齐输出数据(3-4.cpp)
01 #include<stdio.h>
02 void main()
03 {
04 int num = 100;
05 printf("%05d\n",num); //指定输出宽度为5,不足部分以0 补齐
06
07 double dnum = 123.321;
08 printf("%010.5lf\n",dnum); //指定输出宽度为10,不足部分以0 补齐
09 }
输出结果为:
00100
0123.32100
代码第05 行使用%05d 输出整数变量num,该变量的值为100,只有3 位数字,因此
需要在数字前面使用00 补齐。代码第08 行使用%010.lf 输出浮点数变量,会在最高位用0
补齐,其结果为0123.32100。
4.其他注意事项
(1)printf()除了输出变量,同样可以输出常量和表达式。【废话。输出的本来就是表达式的值,常量、变量都是表达式】输出常量时也要使用格式说明符,且必须按从左到右的顺序与输出项中的数据一一对应【严格地说,一一对应的说法并不成立】。
例如,可以使用下列语句输出一个整数和一个结果为浮点数的算术表达式【两者都是表达式】。
printf("%d\n%f",5,1.2*5);
换句话来说,printf()输出项不仅可以是变量,也可以是常量和表达式。
(2)字符串常量可以直接使用printf 输出,也可以使用格式字符s 输出。例如:
printf("I LOVE CHINA\n");
prinf("%s\n","I LOVE CHINA");
字符串常量中可以是打印字符和控制字符。第2 句还可以将换行符'\n'放在字符串常量中,相应改写为:
prinf("%s","I LOVE CHINA\n");
(3)格式字符x、e、g 可以使用小写字母,也可以使用大写字母。使用大写字母时,输出数据中如果带有字母,也会相应输出为大写。除了x、e、f 【前面说x、e、g,这里又成了x、e、f】格式字符外,其他格式字
符必须使用小写,否则会出错。例如,%d 不能写做%D,%f 不能写做%F【错:C语言有%F】。
(4)格式字符紧跟在百分号%后面才表示为格式字符,其输出控制作用。否则将视做字符串的普通字符输出。例如:
char c = 'C';
float f = 1.2;
printf("c=%c,f=%f",c,f);
输出结果为:
c=C,f=1.2
上述printf()函数中,多次出现字符c 和字符f,但每一个c 和f 的含义都不相同。c=%c的第1 个字符c 是普通字符c,会按照原样输出;第2 个字符c 前面有百分号%,因此会被编译器认为是格式字符,该处会按输出项中的字符变量c 的内容输出。同样,f=%f 的第1个字符f 是普通字符,按照原样输出;第2 个字符f 为格式字符,按照输出项中变量f 的内容输出。
3.2.2 格式化输入函数scanf()
格式化输入函数scanf()的功能是从键盘上输入数据【未必】,该输入数据按指定的输入格式被赋值给相应的输入项。其基本输入格式为:
scanf("格式字符串",输出项1,输入项2,…,输入n);
其中格式字符串用于规定数据的输入格式,必须用双引号括起来【没这回事】。其内容由格式说明项、普通字符和输入分隔符3 部分组成。输入项是一个或多个变量的地址,当有多个输入项时,每个输入项使用逗号隔开。输入项变量的地址,就是在每个变量前加取地址符&。输入与输出都需要保持格式字符和输入项数据一致。输入多项数据时,输入数据使用空格或回车符隔开【错:有时不可以,有时还可以用其他字符隔开】。
scanf()函数的格式说明项与printf()的格式说明项基本相同,使用%d、%lf 等控制输入数据类型。但在输入浮点数时,不能使用m.n 中的n,因为输入数据不能规定其精度。同时scanf()也没有%u 的格式说明符【错:scanf()有%u 】,需要输入无符号数时,通常以%d、%o 或%x 格式输入。【错:误导】如果百分号%后加*表示跳过相应的数据,即“虚读”。
如代码3-5 所示,展示了整数、浮点数和字符的输入。
代码3-5 整数、浮点数和字符的输入(3-5.cpp)
01 #include <stdio.h>
02 void main()
03 {
04 int num;
05 double dnum;
06 char ch;
07 printf("please input <char> <int>and <double> type data:\n");
08 scanf("%c",&ch); //输入一个字符,保存在ch 中
09 scanf("%d%lf",&num,&dnum); //输入一个整数和小数,保存在num 和dnum
10 printf("you have input:\n");
11 printf("%d\t%lf\t%c\n",num,dnum,ch);
12 }
程序运行过程中,CMD 窗口的输入输出内容为:
please input <int> <double> and <char> type data:
A↙ //该行是输入内容
12﹍1.2↙ //输入
you have input:
12 1.20 A
程序首先提示输入char、int 和double 类型的数据,依次输入字符'A',数字12 和1.2
之后,输出这几个输入的值。
尤其需要注意的是使用%c 输入一个字符。从前面章节已经知道,ASCII 不仅定义了大小写字母、常用符号和数字等键盘上的可打印字符,还定义了转义字符【错:驴唇不对马嘴的说法。转义字符是C代码层面上的概念,跟ASCII八竿子打不着】。使用scanf()函数不仅可以输入可打印字符,还可以输入转义字符【荒唐】。这样的特性有时候会有一些麻烦。比如上面的程序,在第一次输入字符A 的时候,不输入任何字符直接按回车键,然后输入12﹍1.2↙,则程序仍然正常执行。输出的时候,输出结果将会多一个空行。这是因为按回车键这个确认输入的操作,被scanf()函数读入,并认为是一个转移字符 '\n' 保存在字符变量ch 中。
scanf()函数这样的特性有时候会导致一些错误的产生。例如,同时读取字符与整数、浮点数等类型数据时,代码如下:
scanf("%d%lf%c",&num,&dnum,&ch);
如果输入内容为12﹍1.2﹍A↙,将会发生错误。输出结果为:
12 1.20
这是因为在输入数据时习惯性使用空格间隔不同的数据,导致1.2 后面的空格被认为是需要输入的字符将其读取,而真正需要读取的字符A 却被忽略掉了。如果一定要同时输入字符数据和其他类型数据,则字符数据不要使用空格间隔,上面的输入修改为12﹍1.2A↙就没有问题了。【拙劣的方案,不能从根本上解决问题】
%注意:为了读者能看清楚输入的内容,在输入时本书使用﹍表示空格,使用↙表示回车。
输入数据时,需要注意以下几点。
(1)scanf()函数同时输入两个或多个数据时,在两个输入的数据之间可以使用一个或
多个空格间隔,也可以使用回车或制表符(键盘Tab 键)间隔。例如:
scanf("%d%d",&a,&b);
假设输入18 保存在变量a 中,输入33 保存在b 中,其输入内容应当为:
18﹍33↙
或者
18↙
33↙
(2)格式字符串中出现的普通字符必须原样输入。例如:【这种设计本身很拙劣】
scanf("%d,%d",&a,&b);
该scanf()语句的格式字符串为"%d,%d",在两个格式字符之间有一个逗号,因此在输入时必须在两个数据之间带有一个逗号。正确的输入应当为:
18,33↙
此外,对于scanf()函数中的带有转义字符的格式字符串,C 语言编译并不将其视做转移字符,而是当做普通的字符,所以输入时同样需要原样输入该字符。例如:
scanf("%d,%d\n",&a,&b);
该格式字符串在之前的字符串基础上,增加了一个\n 换行符。但是输入函数并不认为格式字符串中的\n 是一个换行符,而是将其视做一个反斜杠\和一个字母n。因此在输入的时候,还应当输入这两个字符。正确的输入应当为:
18,33\n↙【完全是胡扯】
(3)scanf()函数会依次在输入的内容中读取数据。读取数据时遇到以下情况,程序会
认为输入结束:
q 遇到空格、回车键或Tab 键【错:只在个别情况下成立而已】
q 输入域宽度结束。例如输入%3d,读取时只会读入3 位数字。
q 非法输入。非法输入是指在输入数据时使用与数据类型不相关的字符。例如,输入整数时遇到字母【错:十六进制就不排斥字母】,或者其他非数值符号(数值符号仅由数字字符0~9、小数点和正负号组成【错:十六进制就不排斥字母】)。
(4)使用格式说明符%c 控制单个字符的输入时,空格和转义字符【概念错误,转义字符是C代码语境下的概念】均作为有效字符被输入。例如,输入函数【?】:
scanf("%c%c",&ch1,&ch2);
当输入的字符带有空格和反斜杠\时,【错:空格和反斜杠\本来就是字符】
﹍\
则ch1 保存空格字符,ch2 保存反斜杠字符。
(5)在格式说明符的%与格式字符之间可以增加一个整数m,来控制读入数据的最大位数【拜托,那叫宽度好不好】,如%mlf、%md。这和控制输出宽度时使用的方法类似。使用这种方法控制读入数据的宽度,则系统会自动截取所需要的数据,因而在输入多个数据的时候不需要任何分隔符进行分隔。
如代码3-6 所示,展示了设置宽度的输入。
代码3-6 设置输入数据的宽度(3-6.cpp)
01 #include<stdio.h>
02 void main()
03 {
04 int num;
05 double dnum;
06 printf("please input <int> and <double> type data:\n");
07 printf("please keep input data with 5 bit!\n");【chinglish?】
08 scanf("%5d%5lf",&num,&dnum); //输入一个小数
09 printf("you have input:\n");
10 printf("%d %.2lf\n",num,dnum); //输出小数,保留小数点后2 位
11 }
代码执行时,CMD 窗口的显示内容为:
please input <int> and <double> type data:
please keep input data with 5 bit!
12345123.4↙ //输入
you have input:
12345 123.40
代码第08 行,要求执行程序的人输入两个5 位数据、1 个整数和1 个浮点数。但是在实际输入过程中,输入行输入的是12345123.4。但从输出可以看出,程序仍然识别其为两个数:12345 和123.4。说明使用%md 或%mlf 时,程序最多读取m 位就截断数据,不论后面是否有空格进行分隔,都认为该数值的读取完毕。
当然在输入的时候,往往并不能保证输入的数据宽度正好等于需要的数据宽度。此时,如果数据之间没有使用空格等进行分隔,则程序会依次读取每个数,每个数都读入相应m位,最后不足m 位的那个数作为最后1 个数。
(6)格式说明中使用符号*可以过滤掉当前的输入数据,而将下一个数据读入后继变量中。例如输入代码:
scanf("%c%*c%c%c",&a,&b,&c);
当输入内容为ABCDEF↙时,a 的值为A,b 的值为C,c 的值为D。可以看出当读入字符A 并将其赋值给变量a 后,下一个读取的字符数据B 成为当前输入的数据,但它读入之后并不赋值给后继变量b,变量b 得到的值是C。
(7)输入数据时,再按回车键之后才会将数据传送给各个变量。输入的这行字符先放到缓存区中,当按回车键之后,这些数据会按照格式控制参数规定的要求,将数据转换为相应格式再赋值给指定变量。如果输入数据多于变量个数,则数据被保留在缓存区,当下一次输入时这些数据会再被使用。
3.3 常用字符输入输出函数
字符数据的输入输出,除了使用printf()和scanf()函数之外,C 语言还提供了单个字符读取和输出的函数putchar()和getchar()。本节将学习这两个函数的使用方法。
3.3.1 putchar()函数
putchar()函数的完整形式如下:
putchar(char ch);【错:putchar()的函数原型为int putchar( int );】
该函数的功能是将字符变量ch 保存的字符【字符变量不保存字符】输出到标准输出设备。putchar()函数的功能与printf()函数使用%c 相同【错:只有部分功能相同】。putchar()函数必须带有输出项,输出项可以是字符常量、变量或者表达式,甚至是转义字符【错,没什么“甚至”,都是int类型的表达式】。putchar()函数只能输出一个字符,不能输出字符串。例如代码:
putchar('A');
可以输出字符'A'。
%注意:这里使用的是单引号' ',与printf()函数的格式控制字符串不同。
3.3.2 getchar()函数
getchar()函数的功能是从标准输入设备上读取一个字符。字符在按下回车键之后被送到缓冲区,然后getchar()函数从缓冲区取出并返回。getchar()不带任何参数,其通常的格式如下:
ch = getchar();
其中ch 是一个字符变量【错:C语言并没有对ch的类型做出限制,通常应该是int类型】,getchar()函数执行的结果通过赋值符号=赋值给ch 保存。
例如代码3-7,实现了使用getchar()函数读入一个小写字符,并且通过putchar()函数输出该字符的大写形式。
代码3-7 小写字母转化为大写字母(3-7.cpp)
01 #include<stdio.h>
02 void main()
03 {
04 char ch;
05 ch = getchar(); //读入字符
06 ch -= 32【MAGIC NUMBER,风格拙劣,且代码缺乏一般性】 //将小写变为大写
07 putchar(ch); //输出字符
08 }
代码通过getchar()函数读入字符,使用putchar()函数输出字符。在ASCII 码中,大写字母比小写字母的数值小32,例如字母A 的编码为65,字母a 的编码为97,两者的差值为32。因此任何一个小写字母的字符,减去32 就是该字母的大写字母。代码第06 行,通过复合算术运算【臆造概念】减去32,将其值修改为相应的大写字母的值。
3.4 本 章 小 结
本章内容较少,但非常重要。学好本章的标准输入输出函数,对今后的学习都会有莫大的帮助。通过输入输出,读者可以很方便地与计算机进行交互,可以直观地看到计算机运行的结果。灵活的运用sacnf()函数和printf()函数,是一个C 语言程序员应该具备的最基本素质。【错谬百出,这段话简直是一种自我讽刺】
3.5 本 章 习 题
1.编程实现:输入字符串,在显示器输出该字符串3 次。
2.编程实现:输入两个整数变量,计算它们的加、减、乘、除后输出结果。
3.编程实现:输入一个字符,输出该字符的ASCII 值。
4.编程实现:输入3 个数,求其平均值并输出。