2.2 格式化输入/输出函数
格式化输入/输出函数按照指定的格式(数据类型、对齐格式等)输出相应的数据。
2.2.1 printf函数──格式化输出数据
1.函数原型
int printf(const char *format[,argument]…);
2.函数功能
printf函数的功能是在由format指定的格式控制下,将argument输出到屏幕上。
3.函数参数
(1)参数format:由格式说明和普通字符构成。其中,格式说明定义argument的显示格式,它以”%”开头,后面跟格式字符。格式字符前面还可以有其他修饰符,表示输出数据的宽度、精度等。参数format的格式如下。
%[flags][width][.precision][length]格式字符
格式说明的个数必须与参数argument的个数一致。格式字符及说明如表2-1所示。
表2-1 格式字符及说明
普通字符是按照原样输出的字符,如逗号、空格和换行符。
flags控制输出数据的对齐方式。flags及说明如表2-2所示。
表2-2 flags及说明
width控制数据输出的宽度。width及说明如表2-3所示。
表2-3 width及说明
precision表示单精度和双精度浮点数的小数点个数。precision及说明如表2-4所示。
表2-4 precision及说明
length表示整型数据是长整型还是短整型。length及说明如表2-5所示。
表2-5 length及说明
(2)参数argument:表示要格式化输出的数据,分别与格式字符对应。
4.函数的返回值
如果调用成功,则函数返回输出的字符个数;否则返回一个负数。
5.函数范例
/********************************************
*范例编号:02_06
*范例说明:格式化输出数据
*********************************************/
01 #include <stdio.h>
02 #include <stdlib.h>
03 void main()
04 {
05 printf (“整数: %d %ld\n”,2021, 6553500L);
06 printf (“以十、八、十六进制输出:%d %o %x\n”,-1,-1,-1);
07 printf (“以空格填充: %12d,以0填充:%012d\n”,2021,2021);
08 printf (“浮点数: %4.2f %+.0e %E \n”,9.825,9.825,9.825);
09 printf (“输出%: %f%%\n”,1.0/3);
10 printf (“字符: %c %c\n”,’A’,97);
11 printf (“字符串%-30s\n”, “this is a C program!”);
12 printf (“字符串%+30s\n”, “It is beautiful!”);
13 printf (“字符串% 30s\n”, “It is beautiful!”);
14 printf (“字符串:%s\n”, “How are you!”);
15 system (“pause”);
16 }
该函数范例的运行结果如图2-6所示。
图2-6 函数范例的运行结果
6.函数解析
(1)printf函数返回实际输出的字符个数(包括换行符)。例如,printf(“%d\n”,66)返回的是3,而不是2。
(2)printf函数中的格式控制字符包括普通字符和转义字符,如’\n’ ‘\r’ ‘\t’ ‘\f’。
(3)输出指针或地址时,应使用%p输出。
2.2.2 scanf函数──格式化输入数据
1.函数原型
int scanf(const char *format[,argument]);
2.函数功能
scanf函数的功能是接受从键盘输入的数据,并将其转换为相应的格式。
3.函数参数
(1)参数format:由格式说明、空白字符与非空白字符构成。
格式说明:指示了参数 argument 的输入格式,它由%开头,后面跟格式字符,格式字符前也可以有其他修饰符。格式说明的一般格式如下。
%[*][width][modifiers]格式字符
格式字符及说明如表2-6所示。
表2-6 格式字符及说明
格式字符前面的修饰符及说明如表2-7所示。
表2-7 修饰符及说明
空白字符:可以使scanf函数忽略输入的一个或多个空白字符。空白字符可以是空格、制表符或换行符。实际上,scanf函数读入空白字符但是并不存储它们。
非空白字符:scanf函数读入并删除与该字符相同的字符。如果读入的字符与格式控制中的非空白字符不匹配,则停止读入。
(2)参数argument:一个地址列表,表示要格式化的输入数据的地址。
4.函数的返回值
如果调用成功,则函数返回读入数据的个数;如果读入出错,则返回与读入数据匹配的个数。
5.函数范例
/********************************************
*范例编号:02_07
*范例说明:格式化输入数据
*********************************************/
01 #include <stdio.h>
02 #include <stdlib.h>
03 void main()
04 {
05 char name[20];
06 float chinese,math,english,sum,average;
07 printf(“请输入你的姓名:”);
08 scanf(“%s”,name);
09 printf(“请输入你的语文,数学,英语的成绩: “);
10 scanf(“%f,%f,%f”,&chinese,&math,&english);
11 printf(“你的姓名:%s.\n”,name);
12 printf(“语文 数学 英语\n”);
13 printf(“%.2f %.2f %.2f\n”,chinese,math,english);
14 sum=chinese+math+english;
15 average=sum/3.0;
16 printf(“%s的各门课成绩总分:%.2f,平均分:%.2f\n”,name,sum,average);
17 system(“pause”);
18 }
该函数范例的运行结果如图2-7所示。
图2-7 函数范例的运行结果
6.函数解析
(1)scanf函数的参数argument是变量的地址或字符串首地址,而不能是变量。地址列表中的变量名前需要加上&。
(2)一般情况下,回车键被认为是输入的结束。对于非字符型数据的输入,空格符、跳格符、回车键都可以被认为是输入的结束。
7.应用说明
使用*修饰符将忽略地址列表中的分隔符。例如,在下面的代码中,如果输入”20/30”,则忽略输入的”/”,将”20”赋给a,将”30”赋给b。
scanf(“%d%*c%d”,&a,&b);
在格式说明符中,除了格式字符还有其他字符。在输入数据时,应输入与这些格式说明符相同的字符。
scanf(“%d,%d”,&a,&b);
例如,在上面的代码中,应该按照以下形式输入。
30,40
而下面的输入形式则是错误的。这是因为在格式说明中,两个数据以逗号分隔。
30 40
30:40
使用%c输入字符时,空格字符和转义字符都可以作为有效的字符输入。
scanf(“%c%c%c”,&a,&b,&c);
例如,在上面的代码中,如果按照以下形式输入,则字符’x’将赋给a、’y’将赋给b、’z’将赋给c。
x y z
8.注意事项
在输入数据时,不能指定输入数据的精度。例如,下面的输入形式是错误的。
scanf(“%6.3f”,&a);
在使用scanf函数时,不要在格式说明中添加”\n”,这是很常见的错误。例如,下面的输入形式会造成输入错误。
scanf(“%d\n”,&a);
2.2.3 sprintf函数──输出格式化数据到指定的数组中
1.函数原型
int sprintf(char *buffer,const char *format[,argument]);
2.函数功能
sprintf函数的功能是将format指向的格式化数据输出到buffer指向的数组中。
3.函数参数
(1)参数buffer:存放格式化数据。
(2)参数format:格式说明,与printf函数的参数含义相同。
(3)参数argument:参数列表,与printf函数的参数含义相同。
4.函数的返回值
如果调用成功,则返回输出字符的个数(不包括字符串末尾的空字符);否则,返回负数。
5.函数范例
/********************************************
*范例编号:02_08
*范例说明:输出格式化数据到指定的数组中
*********************************************/
01 #include <stdio.h>
02 #include <stdlib.h>
03 void main()
04 {
05 int i,offset=0;
06 char str[40];
07 for(i = 0; i < 10; i++)
08 offset+=sprintf(str+offset,”%d,”,rand()%100);
09 str[offset-1]=’\n’;
10 printf(“产生的随机数分别是:\n%s”,str);
11 system(“pause”);
12 }
该函数范例的运行结果如图2-8所示。
图2-8 函数范例的运行结果
6.函数解析
(1)printf函数与sprintf函数的区别:printf函数输出格式化数据到屏幕上,而sprintf函数输出格式化数据到指定的数组中。
(2)sprintf函数的返回值是输出字符的个数。
7.应用说明
利用sprintf函数的返回值可以将连续多个字符串输出到一个数组中。
2.2.4 sscanf函数──从字符串读取格式化数据
1.函数原型
int sscanf(char *buffer,const char *format[,argument]);
2.函数功能
sscanf函数的功能是从buffer指向的字符串中读取format指定格式的数据,存储到argument中。sscanf函数的功能与scanf函数的类似。
3.函数参数
(1)参数buffer:存放用来读取的源数据。
(2)参数format:格式说明,与scanf函数的参数类似。
(3)参数argument:地址列表,与scanf函数的参数类似。
4.函数的返回值
如果调用成功,则返回输入数据的项数;否则,返回EOF。
5.函数范例
/********************************************
*范例编号:02_09
*范例说明:从字符串读取格式化数据
*********************************************/
01 #include <stdio.h>
02 #include <stdlib.h>
03 void main()
04 {
05 char str[]=”3 plus 5 equals 8!”;
06 int a,b,c;
07 printf(“%s\n”,str);
08 sscanf(str,”%d %*s %d %*s %d”,&a,&b,&c);
09 printf(“%d+%d=%d\n”,a,b,c);
10 system(“pause”);
11 }
该函数范例的运行结果如图2-9所示。
图2-9 函数范例的运行结果
6.函数解析
如果格式字符是%s,则从指定的源字符串中读取字符序列,遇到空格符、跳格符或换行符则停止读取。例如,在下面的代码中,%s读取字符串”Tom live Beijing”,%*s忽略空格符,%d读取”10”到year中。
01 char s[]=”Tom live Beijing 10 years”;
02 char str[20];
03 int year;
04 sscanf (s,”%s %*s %d”,str,&year);
2.2.5 vprintf函数──在屏幕上输出格式化变长参数列表
1.函数原型
int vprintf(const char *format,va_list arg_ptr);
2.函数功能
vprintf函数的功能是在屏幕上输出格式化变长参数列表中的数据。
3.函数参数
(1)参数format:要输出的文本,可以包含格式字符,格式化字符由变长参数指针指示。与printf函数中的参数format含义相同。
(2)参数arg_ptr:变长参数列表对象。其实它是一个指向参数列表的指针。va_list类型在stdarg.h中定义。
4.函数的返回值
如果调用成功,则返回输出的字符个数;否则,返回负数。
5.函数范例
/********************************************
*范例编号:02_10
*范例说明:在屏幕上输出格式化变长参数列表
*********************************************/
01 #include <stdio.h>
02 #include <stdarg.h>
03 #include <stdlib.h>
04 void PrintFormatted(char *format, ...)
05 {
06 va_list args;
07 va_start(args, format);
08 vprintf(format, args);
09 va_end(args);
10 }
11 void main()
12 {
13 PrintFormatted(“Welcome to use %s.\n”,”Visual Studio 2019”);
14 PrintFormatted(“The 120th anniversary of %s will be celebrated
15 in %d.\n”,”Northwest University”,2022);
16 PrintFormatted(“The %dth and %dth anniversary of %s and %s will be celebrated
17 in %d.\n”,120,100,”Nanjing University”,”Southeast University”,2022);
18 system(“pause”);
19 }
该函数范例的运行结果如图2-10所示。
图2-10 函数范例的运行结果
6.函数解析
(1)参数arg_ptr指向要格式化的变长参数。
(2)在调用vprintf函数前,需要先调用va_start函数初始化的va_list类型的指针;在调用结束后,需要使用va_end函数释放的va_list类型的变量。
2.2.6 vscanf函数──读取从键盘输入的格式化数据
1.函数原型
int vscanf(const char *format,va_list arg);
2.函数功能
vscanf函数读取从键盘输入的格式化数据。
3.函数参数
(1)参数format:格式说明符,与scanf函数的参数含义相同。
(2)参数arg:变长参数对象,指向接受数据的变量地址列表。
4.函数的返回值
如果调用成功,则函数返回输入数据的项数;否则,返回EOF。
5.函数范例
/********************************************
*范例编号:02_11
*范例说明:读取从键盘输入的格式化数据
*********************************************/
01 #include <stdio.h>
02 #include <stdarg.h>
03 int InputFormatted(char *fmt, ...)
04 {
05 va_list argptr;
06 va_start(argptr, fmt);
07 vscanf(fmt, argptr);
08 va_end(argptr);
09 }
10 void main()
11 {
12 long int no;
13 int age;
14 float score;
15 printf(“Please Input no,age,score(e.g.1001,23,89.5):\n”);
16 InputFormatted(“%ld,%d,%f”,&no,&age,&score);
17 printf(“%ld %d %f\n”, no, age, score);
18 }
该函数范例的运行结果如图2-11所示。
图2-11 函数范例的运行结果
6.函数解析
vscanf函数的作用与scanf函数的类似,不同之处在于vscanf函数由变长参数列表指针接受输入的数据,而scanf函数则由地址列表接受输入的数据。