2.4 输入输出对象
在C语言中,输入与输出功能是通过调用标准库函数中的函数来实现的。在函数库中包含一系列标准输入输出函数,有格式化输入输出函数:“printf”,“scanf”;字符输入输出函数:“putchar”,“getchar”;字符串输入输出函数:“puts”,“gets”。
2.4.1 格式化输入函数
scanf()函数的作用是从输入设备输入若干个任意类型的数据。它的函数原型在头文件<stdio.h>中,C语言是允许在使用scanf()函数之前不包含<stdio.h>文件。scanf()函数最末一个字母f即为“格式”(format)之意。
1.scanf()函数的调用格式
scanf()函数是C语言提供的标准格式输入函数,用来按照指定的格式输入数据并保存到指定变量的存储地址中去。scanf()函数调用的一般形式为:
scanf ("格式控制字符串",地址列表);
例如:
scanf("%d %c", &a,&b);
该函数主要有如下两个参数:
(1)格式控制字符串:用来指定每个输入项的输入格式。格式控制字符串通常由“%”和格式字符组成,如%d、%c、%f等。它的作用是确定输入数据的格式,格式说明都是由“%”字符开头的。
(2)地址列表:地址列表给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的,例如,&a表示变量a在内存中的地址,其中&是取地址运算符,其作用是求变量的地址。
其地址列表的个数必须与格式字符串中规定字符的个数一样多,各地址之间用“,”分开,且顺序必须一一对应,否则将会出现意想不到的错误信息提示,并且各变量前必须加上“&”,用于指向各变量在内存中的地址。
提示
区分变量的值和变量的地址这两个不同的概念。变量的地址是由C编译系统分配的。用户不必深究具体的地址是多少。
在赋值表达式中给变量赋值,例如:
a=1;
则变量的地址与变量值的关系如下所示:a为变量名,1是变量的值,&a是变量a的地址。
在赋值号左边是变量名,不能写地址。而scanf()函数本质上也属于给变量赋值,但要求必须写变量的地址,如:&a。两者在形式上略有不同。“&”是一个取地址运算符,&a是一个表达式,其作用是求变量的地址。
2.scanf()函数的格式控制符
scanf()函数的格式控制符中也可以有多种规定字符,常见格式控制符如表2-1所示。
表2-1 scanf()函数的格式控制符
3.scanf()函数格式控制的注意事项
scanf()函数格式控制可表示为:
%[*][宽度][长度]类型
其中“[]”中为可省略项,其余各项的意义如下:
(1)符号“*”用于表示输入项在录入后被跳过,不赋予相应的变量。
例如,读入整型变量a,b的值,在输入时跳过第二个录入值:
scanf("%d%*d%d",&a,&b);
假设输入2,3,4,则2被赋予变量a,3被跳过,4被赋予变量b。
【例2-2】编写一段程序,读入整型变量a,b的值,在输入时跳过第二个录入值。(源代码\ch02\2-2)
#include<stdio.h> int main() { int a,b,c; printf("请输入三个数:\n"); scanf("%d %*d %d",&a,&b,&c); printf("a=%d b=%d c=%d\n",a,b,c); return 0; }
运行上述程序,结果如图2-2所示。
图2-2 “*”的使用
【代码解析】
本例用于演示格式控制的不同情况。输入三个数据4,5,6。打印出来会发现,4被赋予变量a,5被跳过,6被赋予变量b,c就是一段杂乱的数据,没有任何意义。
(2)用于指定所录入的数据宽度,它的书写形式为“%n类型”,表示录入一个宽度为n的数据,若输入的数据宽度大于n,则保留n位数据,其余舍去。
例如,输入长度为3的整型数据:
scanf("%3d",&a);
假设输入123456,则实际将123赋予变量a,456被舍去。
例如,输入2个长度为3的整型数据:
scanf("%3d%3d",&a, &b);
假设输入123456,则实际将123赋予变量a,将456赋予变量b。
【例2-3】编写一段程序,通过scanf()读入一串数字,查看打印结果。(源代码\ch02\2-3)
#include<stdio.h> int main() { int a,b; printf("请输入一串数字:\n"); scanf("%3d %2d",&a,&b); printf("a=%d b=%d\n",a,b); return 0; }
运行上述程序,结果如图2-3所示。
图2-3 “%n类型”的使用
【代码解析】
本例用于演示通过scanf()输入函数录入数据,并通过格式控制字符串控制输入的数据格式。“%3d”就是将123赋予变量a,“%2d”将45赋予变量b,67则被舍去。
(3)长度
通常使用字母“l”与字母“h”表示长度格式符,其中字母“l”表示输入长整型数据,如“%ld”“%lo”“%lx”“%lu”,以及double型数据,如“%lf”“%le”;字母“h”表示输入短整型数据,如“%hd”“%ho”“%hx”。
注意:
- scanf()函数中的“地址列表”输入的必须是地址,而不能是变量名。这也是C语言与其他高级语言的不同之处。
例如:
scanf ("%d,% d",&a,&b );
不能将上述语句写成:
scanf ("%d,%d",a,b);
- scanf()函数中不支持精度控制。
例如:
scanf("%3.14f",&x);
此语句是非法的,不能使用此语句输入小数。
- 在“格式控制字符串”中除了格式说明符外,也允许非格式字符出现,但输入时在对应位置上也要输入这些非格式字符。
例如:
scanf ("a=%d,b=%d",&a,&b);
则键盘输入时应输入:
a=1,b=2;
看似起提示作用,但由于用户看不见程序中的a=和b=,所以实际起不到提示作用。应尽量不写,若需要加提示,在上一行加上“printf("a=,b=");”更好。
- C源程序在编译时碰到空格键、Tab键、回车键或非法数据时即认为该数据结束。
2.4.2 格式化输出函数
printf()函数的作用是向终端输出若干个任意类型的数据。它的函数原型在头文件<stdio.h>中,与格式输入函数scanf()相同,C语言中允许在使用printf()函数之前不包含<stdio.h>文件。
1.printf()函数的调用格式
格式化输出函数printf()主要是将标准输入流读入的数据向输出设备进行输出,它的语法形式如下:
printf (格式控制字符串,输出列表);
该函数主要有如下两个参数:
(1)格式控制字符串:用来指定每个输出项的输出格式,格式控制字符串通常由格式说明、转义字符和普通字符组成。
① 普通字符:也称为非格式说明符,按原样输出字符。
例如:
printf("a+b=%d\n",x);
其中,“a+b=”是非格式说明符,执行时按原样输出。
② 转义字符:是以“\”开头的字符,例如“\t”“\n”等。
③ 格式说明:由“%”和格式字符组成,例如%d、%c、%f等用来指定数据的输出格式。格式说明都是由“%”开头,以说明输出数据的类型、形式、长度、小数位数等。例如:
"%d" // 按十进制整型输出 "%ld" // 按十进制长整型输出 "%c" // 按字符型输出
(2)输出列表:是要输出的各项数据,这些数据可以是常量、变量、函数或表达式,其具体类型由格式控制符中的格式字符决定。输出列表的个数必须与格式控制字符串中规定的字符个数一样多,各参数之间用“,”分开,且顺序一一对应,否则将会出现意想不到的错误。
【例2-4】编写程序,输出代码中变量的值。(源代码\ch02\2-4)
#include <stdio.h> int main() { int a=3,b=2,c; printf("a=%d,b=%d\n",a,b); printf("a=%d\n",a,b,c); printf("a=%d,b=%d,c=%d\n",a,b); printf("c=%d\n",c=a+b); printf("a=%d\n",a=a+2); return 0; }
运行上述程序,结果如图2-4所示。
图2-4 输出列表
【代码解析】
本例演示了printf()函数的输出列表。在代码中,第一个printf()函数中输出列表的个数与格式控制字符串中规定的字符个数一样多,所以正确地输出了两个变量a和b的值;第二个printf()函数中输出列表有三个变量a、b、c,格式控制字符串中却只有一个字符a,所以也只输出了一个变量a的值;第三个printf()函数由于缺少输出项,最后就会输出一段没有意义的数据;最后两个printf()函数的输出列表允许是表达式。
2.printf()函数的格式控制符
C语言提供的printf()函数中使用的格式控制符如表2-2所示。
表2-2 printf()函数的格式控制符
提示
使用格式字符时,除了X、E等有大写形式的,其余格式字符必须使用小写形式,否则会出现错误。
【例2-5】编写程序,分别定义int型、float型以及char型变量,使用相应的输出格式字符将它们输出。(源代码\ch02\2-5)
#include <stdio.h> int main() { int x=5; // 分别定义int、float以及char型变量 float y=3.14; char c='w'; printf("x=%d\n",x); // 使用相应的格式字符输出 printf("y=%f\n",y); printf("c=%c\n",c); return 0; }
运行上述程序,结果如图2-5所示。
图2-5 格式字符
【代码解析】
本例用于演示通过使用不同的格式字符,将相应类型的变量进行输出的操作。代码中首先定义了不同类型的变量,包括int、float以及char型,然后使用%d来输出int型变量数据;使用%f来输出float型变量数据;使用%c来输出char型变量数据。
3.printf()函数格式控制的注意事项
在输出函数printf()中,格式转换字符一般可以表示为:
%[符号][宽度][.精度]格式字符
其中“[]”中为可省略项,其余各项的意义如下:
(1)通常输出数据都隐含右对齐,如果想实现左对齐,可以在格式控制中的“%”和宽度之间加一个符号“-”。
以输出字符串为例:
printf("%-s","Hello"); // 输出字符串"Hello",并保持左对齐
其中“%-s”表示输出的字符串内容左对齐,若没有“-”符号则右对齐输出。
(2)宽度指的是域宽,也就是对应的输出项输出到设备上时所占的字符数。
以输出字符串为例:
printf("%8s","Hello"); // 输出字符串长度5小于8,则左补3个空格 printf("%2s","Hello"); // 输出字符串长度5大于2,则突破2的限制,全部输出
其中“%ms”表示输出的字符串共占m列,若输出的字符串长度大于m,则突破m限制,将字符串全部输出;若字符串长度小于m,则左补空格。
提示
“%0s”表示输出的字符串若有空位,则用数字“0”进行补位。
例如:
printf("%08s","Hello"); // 表示右对齐输出长度5的"Hello",8为宽度,所以左补3个0
(3)精度用于说明所输出的实型数据的小数位数。它的书写格式为:“%.nf”,表示输出小数位数为n的实型数据。
例如:
float a=5.4321; printf("%.3f\n",a); // 输出float变量a,保留3为小数,则结果为5.432
提示
若将要输出的实数小数点后位数大于所要保留的小数位数,则通过四舍五入后保留;若将要输出的实数小数点后位数小于所要保留的小数位数,则缺位补0。
对于输出精度的情况,还有一种在格式字符前加字母“l”的表示方法:“%ld”,字母“l”的加入表示对于整型,则输出long型;对于实型,则输出double型。
例如:
long a=54321; printf("%ld\n",a); // 输出长整型变量a的值
【例2-6】编写程序,定义float型变量a=5.4321,定义long型变量b=12345678,通过格式控制,输出变量a保留3位小数的形式,输出长整型变量b,输出字符串“program”左端“pro”,并保持左对齐,而左端补空格。(源代码\ch02\2-6)
运行上述程序,结果如图2-6所示。
图2-6 格式控制
【代码解析】
本例用于演示格式控制的不同情况。首先定义float型变量a与long型变量b,使用精度控制输出变量a保留3位小数的形式,结果为5.432,可以发现是经过了四舍五入后的结果;使用“%ld”的形式输出变量b;而“%7.3s”表示右对齐输出内容,“7”表示输出宽度,“.3”表示精度3,在字符串中为截取左端3个字符,所以输出的结果为7个长度,右端为“pro”,左端补4个空格,并使用“|”符号来检验空格。
2.4.3 字符的输入函数
getchar()函数是字符输入函数,作用是从标准输入设备(键盘)上输入一个字符,在同一时间只能读取一个单一的字符。
getchar()函数的使用语法如下:
getchar();
注意:
(1)使用getchar()函数输入时,都是转换为ASCII码值来存储,所以getchar()函数读取一个字符,返回的是一个整数。
(2)getchar()函数无参数,但括号不能省略。输入数字也必须按字符进行处理。当输入多个字符时,只能接收第一个字符。
而在编写C程序时,通常把输入的字符赋予一个字符变量,使其构成一个赋值语句,语法如下:
char x ; //定义字符变量x x = getchar( ); // 从键盘输入一个字符,然后将字符的值赋给变量x
提示
同putchar()函数一样,使用getchar()函数时,首先要添加头文件“#include <stdio.h>”。
【例2-7】编写程序,使用getchar()函数通过输入端输入一个字符,然后通过putchar()函数将此字符输出。(源代码\ch02\2-7)
#include <stdio.h> int main() { char c; // 定义字符变量 printf("请输入一个字符:"); c=getchar(); // 从键盘输入单个字符B给c字符变量 putchar(c); // 输出c字符变量的值 putchar('\n'); return 0; }
运行上述程序,结果如图2-7所示。
图2-7 getchar()函数
【代码解析】
本例用于演示如何使用getchar()函数输入一个字符。首先定义一个char型变量c,用于存放要输入的字符,然后通过printf()函数输出一行提示信息,接着使用getchar()函数,通过输入端输入一个字符并赋予变量c,然后通过putchar()函数输出变量c。
在使用getchar()函数时,如果需要连续地输入两个字符,那么在输入第二个字符前需要清除缓冲区,或者使用getchar()函数获取回车字符。
【例2-8】编写程序,使用getchar输入两个字符,然后再输出它们。(源代码\ch02\2-8)
运行上述程序,结果如图2-8所示。
图2-8 连续输入
【代码解析】
在本例中,如果需要连续输入两个或者更多字符时,需要在输入下一个字符前加上“getchar()”语句。“getchar()”语句是获取回车符,因为一般在输入字符后会按回车键确认,此时回车符就会被输入,而使用“getchar()”语句相当于将输入的回车符存入缓冲区,这样使得下一句的输入函数能够正常获取下一个字符。
2.4.4 字符的输出函数
putchar()函数是字符输出函数,作用是向标准输出设备(显示器)上输出一个字符,同一时间内只能输出一个单一的字符。
其语法格式如下:
putchar(ch);
提示
其中的ch可以是常量、变量、转义字符或表达式等,其数据类型可以是字符型或整型,如果是整型数据,代表的是与一个字符相对应的ASCII码值。
例如:
putchar('A'); // 输出大写字母A putchar('a'); // 输出小写字母a putchar(a); // 输出字符变量a的值 putchar('101'); // 转义字符,输出字符A putchar('\n'); // 转义字符,换行
注意:
(1)putchar函数只能用于单个字符的输出,且一次只能输出一个字符。
(2)在程序中使用putchar函数,务必牢记:在程序(或文件)的开头加上编译预处理命令(也称包含命令),即:#include <stdio.h>。
例如:
【例2-9】编写程序,要求使用putchar()函数输出字符串“New year”。(源代码\ch02\2-9)
运行上述程序,结果如图2-9所示。
图2-9 putchar()函数
【代码解析】
本例用于演示通过使用putchar()函数,将定义的字符变量输出,组成字符串。程序中首先定义字符变量ch1、ch2、ch3。然后分别为它们赋值,再通过使用putchar()函数将字符串补齐后将它们一一输出,使用putchar()函数输出字符时,如果没有特意输出换行转义符的话,每个字符是连续输出的。
2.4.5 字符串的输入函数
gets()函数是字符串输入函数,其作用是从输入流的缓冲区中读取字符到指定的数组,直到遇见换行符或者读到文件尾时停止。
注意:
(1)gets()函数可以直接输入字符串,并且只能输入字符串。scanf()函数是通过格式控制符“%s”输入字符串。
(2)gets()函数在读取字符串时会忽略掉所有前导空白符,而从字符串第一个非空白符读起。并且所读取的字符串将暂时存放于给定的string中。
gets()函数的使用语法如下:
char *gets(char *string);
其中string为字符指针变量,是一个形式参数。gets()函数的返回值为char型,若读取成功返回string的指针,若失败则返回NULL。
【例2-10】编写程序,定义xchar型数组str1[]和str2[]用于存放输入的字符串,使用gets()函数读入一个字符串,然后使用printf()函数将该字符串输出。(源代码\ch02\2-10)
运行上述程序,结果如图2-10所示。
图2-10 get()函数
【代码解析】
本例演示了如何使用gets()函数从输入端读取一个字符串。代码中首先定义两个char型数组str1[]和str2[],注意这两个数组的长度为30,作为了解,数组所定义的长度意为该数组所能存储的数据上限。最后使用printf()函数将输入的字符串输出。
2.4.6 字符串的输出函数
puts()是字符串输出函数,该函数是向输出缓冲区中写入一个字符串,在字符串输出完毕后,紧跟着输出一个换行符“\n”。
提示
puts()函数可以直接输出字符串,并且只能输出字符串。printf()函数通过格式控制符“%s”输出字符串。
puts()函数的使用语法如下:
int puts(char *string);
其中string为将要输出的字符串。输出成功后返回值为非0值,否则返回0。
【例2-11】编写程序,定义一个char型数组str[],并初始化为“My first C program”,使用puts()函数将字符串输出。(源代码\ch02\2-11)
#include <stdio.h> int main() { char str[] = "My first C program"; // 定一个字符串数组 printf("%s\n", str); // 通过变量输出 printf("%s\n", "My first C program"); // 直接输出 puts(str); // 通过变量输出 puts("My first C program"); // 直接输出 return 0; }
运行上述程序,结果如图2-11所示。
图2-11 puts()函数
【代码解析】
本例用于演示一个字符串的4种输出方式。代码中首先定义了一个char型数组str[],然后初始化str[]数组为“My first C program”。先使用printf()函数通过变量和直接输出的方式打印出数组str,再使用puts()函数通过变量和直接输出的方式打印出该数组。
通过对比发现,puts()函数与printf()函数的用法一样。但是puts()函数在输出字符串后会自动输出一个回车符“\n”,而printf()函数需要使用回车符“\n”才能实现换行。
提示
在printf()函数中使用%s输出字符串时,在变量列表中给出数组名即可,不能写为printf("%s",str[]);