3.3.2 数据的输出函数
1.putchar函数
该函数是字符输出函数,其功能是在标准输出设备(显示器)上输出单个字符。其一般形式为:
putchar(整型表达式)
其中,“整型表达式”的值为要输出的字符的编码。通常,该表达式直接用字符型表达式代替。
例如:
putchar('A'); 输出大写字母A。
putchar(x); 输出整型(或字符型)变量x的值。
putchar('\n'); 输出换行符,实际就是实现换行操作,并不显示任何字符。
putchar('\101'); 输出大写字母A。
putchar(65); 输出大写字母A。
putchar('a'-32); 输出大写字母A。
使用该函数前必须要用文件包含命令:#include<stdio.h>或#include "stdio.h"。
【例3.1】 putchar函数的使用方法。
源程序如下:
1 #include <stdio.h> 2 void main() 3 { 4 char a='B',b='o',c='k'; 5 putchar(a);putchar(b);putchar(b);putchar(c); 6 putchar('\n'); 7 putchar(b);putchar(c); 8 putchar('\n'); 9 }
程序的运行结果为:
Book ok
在这个程序中,第1行是预编译命令,将头文件“stdio.h”加入进来。第2~9行是主函数main函数的完整定义,第2行的void表示函数的类型为空类型。第4行定义了3个字符型变量a、b、c,并分别进行了初始化。第5行是用putchar函数输出相应变量的值,即运行结果的第1行。第6行输出一个换行符,表示后面的输出将另起一行进行输出。第7行同样是用putchar函数输出相应变量的值,即运行结果的第2行。第8行的作用与第6行一样。
可见,用putchar函数输出一串字符时很不方便,需要写许多putchar。通常,该函数只用于输出单一字符,若要输出一个字符串,可以使用printf函数(见3.3.3节)或puts函数(见第8章)。
2.printf函数
(1)函数的调用方法
printf函数的一般形式为:
printf(格式控制,输出表列);
其中,“格式控制”部分是由双引号括起来的字符串,也称“转换控制字符串”,是不可缺少的部分,其功能是控制“输出表列”中的输出项的格式,即在显示器上输出的具体内容。“格式控制”字符串包括两种信息:格式说明和普通字符,如图3.1所示。“格式说明”(这里为“%d”)由引导符(百分号“%”)和格式字符(字母“d”)组成,而且总是由“%”开始的,其作用是控制待输出的数据按指定的格式输出。“普通字符”(这里指“a=”)是“格式控制”中除了“格式说明”外的那些字符,它们按原样输出。
图3.1 printf函数的一般形式
“输出表列”由0到多个具体参数组成,参数可以是常量、变量、表达式等,参数的个数应该与“格式控制”字符串中“格式说明”的个数一致。
对于图3.1中的输出语句,如果假设整型变量a的值为10(应在执行该语句前给变量a赋值),则其输出为:
a=10
这里的“a=”来自于“格式控制”字符串,是“普通字符”,按原样输出。“10”是输出表列中参数a的值,其输出格式由格式说明“%d”指定。
由于“格式控制”和“输出表列”实际上都是printf函数的参数,因此,printf函数的一般形式还可以表示为:
printf(参数1,参数2,参数3,……,参数n);
其功能是将“参数2”~“参数n”按“参数1”指定的格式输出。“参数2”~“参数n”的输出格式依次由“参数1”中的“格式说明”决定。
例如:
printf("%d%f%c",a,b,c);
的执行结果为:a按%d的格式输出,b按%f的格式输出,c按%c的格式输出。
在printf函数的参数中,只有第一个参数“参数1”是必要的,其他参数可以省略。当只有一个参数时,“参数1”中不能包含“格式说明”字符,只能有“普通字符”。例如,
printf("This is a C program.\n");
是合法的,但
printf("a=%d\n");
是错误的(程序运行时将输出错误的结果,但不是语法错误)。
(2)printf函数的输出格式控制
在“格式说明”中,对于不同类型的数据,要使用不同的格式字符。常见的格式字符如表3.1所示。
表3.1 printf函数的格式字符
在格式说明中,在引导符“%”和格式字符之间还可以插入附加格式说明字符,以便更精确地控制输出格式。常见的附加格式说明字符见表3.2。
表3.2 printf函数的附加格式说明字符
格式控制部分中的格式字符的个数应该与输出表列中要输出的数据个数相等,而且位置也要一一对应。
下面简单介绍各个格式字符的用法。
① d、o、x、u格式符
d、o、x、u格式符都是用来输出整型数据的,其中d控制输出带符号的十进制整数,o输出无符号的八进制整数,x输出无符号的十六进制整数,而u输出无符号的十进制整数。
下面举例说明这4个格式符的用法。
%d、%o、%x、%u:按整型数据的实际长度输出,例如:
unsigned int u=4294967295; printf("%d\n%u\n%o\n%x\n",u,u,u,u); /* 每个数占一行 */
其执行结果为:
-1 4294967295 37777777777 ffffffff
%md、%mo、%mx、%mu(m是一个正整数):m为指定的输出宽度。如果实际数据的位数小于m,则左边补足空格;如果大于m,则按实际位数输出,m将不起作用。例如,
unsigned int u=4294967295; printf("%10d\n%10u\n%10o\n%10x\n",u,u,u,u);
其执行结果为(“_”代表空格):
-1 4294967295 37777777777(实际有11位数字) ffffffff
%-md、%-mo、%-mx、%-mu(m是一个正整数):与%md、%mo、%mx、%mu基本相同,只是输出的数据向左端对齐,右端补空格,例如:
unsigned int u=4294967295; printf("%-10d<\n%-10u<\n%-10o<\n%-10x<\n",u,u,u,u); /* 用<表示边界 */
其执行结果为:
-1 < 4294967295< 37777777777< ffffffff <
%ld、%lo、%lx、%lu:输出长整型数据。
%hd、%ho、%hx、%hu:输出短整型数据。例如:
unsigned short u=65535; printf("%hd,%hu,%o,%hx\n",u,u,u,u);
其执行结果为:
-1,65535,177777,ffff
通常,有符号整数可以用“%d”、“%hd”等格式符输出,无符号整数可用“%u”、“%o”、“%x”等格式符输出;输出长(短)整型数据时应使用带附加格式说明字符“l”(“h”)的格式说明,如“%ld”。
如果将有符号整数用无符号格式符控制输出,或者反过来,将无符号整数用有符号的格式符控制输出,就需要考虑数据的转化规律了。实际上,不论有符号整数还是无符号整数,在计算机内存中都是用补码表示的。假设在计算机内存中一个整数占4个字节(32位长度),“11111111111111111111111111111111”是内存中的一个二进制数。如果把这个数看做是无符号的整数,它就是十进制数4294967295(即232-1);如果看做是有符号整数,它就是十进制数-1。
② f、e、g格式符
f、e、g格式符都是用来输出实型数据的。其中,f以小数形式输出,e以指数形式输出,g则根据输出数据的长度自动选择用小数或指数格式输出。
现举例说明它们的用法。
%f:按带小数点的小数形式输出,整数部分全部输出,并输出6位小数。
例如:
float f=456.123; printf("%f\n",f);
输出结果为:
456.122986
注意,由于内存中的实数存在误差,只有5~6位有效数字,所以达不到6位小数精度。
%e:按标准化指数形式输出(小数部分的小数点前必有且只有1位非0数字),输出宽度共占13列,其中,小数点占1位,小数点前的非0数字占1位,小数点后的小数部分由系统自动指定为6位,指数部分占5位(字母“e”占1位,指数符号占1位,指数占3位)。
例如:
float f=456.123; printf("%e\n",f);
输出结果为:
4.561230e+002
%g:根据输出数据的长度(位数)自动选择按小数或指数格式输出。
例如:
float f1=123.456789, f2=123456789; printf("%f,%e,%g\n",f1,f1,f1); printf("%f,%e,%g\n",f2,f2,f2);
输出结果为:
123.456787,1.234568e+002,123.457 123456792.000000,1.234568e+008,1.23457e+008
%m.nf(m、n为正整数):指定输出的数据共占m列,其中有n位小数。如果数值长度小于m,则左端补空格;如果超过m,则忽略m的限制。
例如:
float f=123.456789; printf("%10.3f,%5.3f\n",f,f);
输出结果为:
_ _ _123.457,123.457(“_”代表空格,下同。)
如果省略了小数位数“.n”(同时省略小数点“.”),则输出6 位小数(即n的默认值为6)。
例如:
float f=123.456789; printf("%10f,%5f\n",f,f);
输出结果为:
123.456787,123.456787
如果只是省略了n,而保留了小数点“.”,如“%5.f”,则不输出小数部分,相当于n为0。
%-m.nf:与%m.nf基本相同,只是输出的数据向左对齐,在右端补空格。
%m.ne:指定输出的数据共占m列,其中数据的小数部分(又称尾数)有n位小数。如果数值长度小于m,则左端补空格。
③ c格式符
c格式符用来输出一个字符,有两种主要用法:%c和%mc。其中,m指定输出宽度(通常m>1),输出的字符输出在指定的最后一列,即第m列,前面补m-1个空格。
例如:
char c='c'; printf("%c%3c\n",c,c);
输出结果为:
c_ _c
在字符型数据的取值范围内,整型数据可以与字符型数据通用。因此,一个整数,只要它的值在字符型数据范围内,就可以用字符形式输出。反之,一个字符型数据也可以用整型形式输出。例如:
char c='A'; int i=65; printf("%c,%d\n",c,c); printf("%c,%d\n",i,i);
输出结果为:
A,65 A,65
④ s格式符
s格式符用来输出一个字符串,主要有以下几种用法。
%s:直接输出全部字符。例如:
printf("%s","china");
输出结果为:
china
%ms(m是一个正整数):输出的字符串占m列。如果字符串本身的长度大于m,则忽略m的限制,将字符串全部输出;如果小于m,则左边补空格。
%m.ns(m、n是正整数):从字符串中截取左边的n个字符(不足则忽略n的限制),输出到m列上。若不足m列,在左边补空格。
%-m.ns(m、n是正整数):基本同%m.ns,只是输出的字符串是左对齐的。
例如:
printf("%3s\n%7.2s\n%.4s\n%-5.3s\n","china","china","china","china");
输出结果为:
china _ _ _ _ _ch chin chi_ _
需要注意,第1行突破了3的限制,第2行前面有5个空格,第3行占4列,最后一行占5列,右边有2个空格。
(3)使用printf函数应注意的问题
① 格式字符要区分大小写。
② 不同的运行环境在实现格式输出时,输出结果可能会有一些小的差别。例如,用%e格式符输出实数时,有些系统输出的指数部分为4位(如e+02)而不是5位(如e+002);前面的数字部分是5位小数而不是6位,等等。
③ 可以在“格式控制”字符串中使用“转义字符”,如“\t”、“\n”、“\b”、“\r”、“\f”、“\345”、“\x1A”等,它们将被看做“普通字符”。
④ 如果想输出字符“%”,则应该在“格式控制”字符串中用连续的两个%表示,例如:
printf("%f%%",1.0/3);
输出结果为:
0.333333%
(4)printf函数应用举例
【例3.2】 用printf函数输出数据。
程序如下:
1 #include <stdio.h> 2 #define PI 3.141592654 3 void main() 4 { 5 printf("不同精度的圆周率\n"); 6 printf("%4s\t%-8s\n","精度","圆周率"); /* 一个汉字占2位 */ 7 printf("%4d\t%-8.0f\n",1,PI); 8 printf("%4d\t%-8.1f\n",2,PI); 9 printf("%4d\t%-8.2f\n",3,PI); 10 printf("%4d\t%-8.3f\n",4,PI); 11 printf("%4d\t%-8.4f\n",5,PI); 12 printf("%4d\t%-8.5f\n",6,PI); 13 printf("%4d\t%-8.6f\n",7,PI); 14 printf("%4d\t%-8.7f\n",8,PI); 15 }
程序的运行结果如下:
不同精度的圆周率 精度 圆周率 1 3 2 3.1 3 3.14 4 3.142 5 3.1416 6 3.14159 7 3.141593 8 3.1415927