本节书摘来自华章社区《C语言程序设计:问题与求解方法》一书中的第2章,第2.12节数据输入—格式化输入库函数scanf()的用法,作者:何 勤,更多章节内容可以访问云栖社区“华章社区”公众号查看
2.12 数据输入—格式化输入库函数scanf()的用法
在程序运行过程中,我们想要在某语句处暂时中断程序的运行,通过键盘输入数据到变量所对应的内存单元中,就要在程序中事先写好输入库函数调用语句。scanf()是格式化输入库函数,这是一种经常用到的输入库函数。
格式化输入库函数scanf()的调用,可以使得程序运行暂停下来,等待用户从键盘输入数据。程序用户可以通过键盘输入一个(或多个)数值;输完数据后,还要按下回车键,scanf()函数就会将这个(或多个)输入值(经过转换)存放到变量所对应的内存单元中。从scanf()函数返回后,接着运行程序后面的语句。
不过在调用scanf()函数时,第一个参数是相应的格式符%d、%f或%c,它们与要输入的变量类型的简单对应关系如表2-4所示。
调用库函数scanf(),通过键盘输入一个变量值的最简单形式是:
scanf( "格式符",&变量);
例如:
scanf("%f" , & tenement_area ) ; // 假设tenement_area是float型变量
scanf("%d" , & age ) ; // 假设age是int型变量
scanf(" %c" , & ch ) ; //假设ch是char型变量,在 %c 之前,加了一个空格字符
请看以下程序:
#include<stdio.h>
int main(void)
{
int num ;
float x ;
char ch;
printf("请输入总人数\n");
scanf("%d" , & num ) ;
printf("请输入现在的气温\n");
scanf ("%f" ,&x ) ;
printf("请输入等级(A、B、C)\n");
scanf(" %c" ,& ch ) ; //注意:此处在 %c左边加了一个空格,原因请参见书末参考文献
printf("总人数是:%d\n气温是:%.2f\n 等级是:%c\n" , num, x,ch); //输出变量值
return 0;
}
程序运行后,人机之间的交互过程如下:
请输入总人数 //计算机显示的输入提示
18 //程序用户在键盘上输入的数据。“” 表示按下回车键
请输入现在气温 //计算机显示的输入提示
23.6 //用户在键盘上输入的数据
请输入等级(A、B、C) //计算机显示的输入提示
B //用户在键盘上输入的数据
总人数是:18 //计算机显示的输出结果
气温是:23.60 //计算机显示的输出结果
等级是:B //计算机显示的输出结果
在本例程序中,交替使用了库函数printf()和scanf(),这使得程序可以在运行时与用户进行实时交互,实现“人机对话”(更准确地说,是计算机用户与运行着程序的计算机对话)。这样编写的程序用户比较喜欢。
常见编程错误:漏写输入项中变量左边的取地址运算符 “&”是调用scanf()函数时最为常见的编程错误。这个错误很可能使得程序在运行时崩溃。例如:
scanf(" %f", tenement_area ) ; //错误!
scanf("%f" , &tenement_area ) ; //正确!
多个变量值的输入
用于多个变量值的输入scanf()函数的调用方式如下:
scanf("格式符1格式符2格式符3",&变量1,&变量2, &变量3) ;
对于scanf()函数调用,格式串中格式符的个数要与输入项一样多,类型也要一一匹配。即格式符1要与变量1的类型匹配,格式符2要与变量2的类型匹配等。
注意:用一次scanf()函数调用,输入多个非字符类型的变量,程序运行时几个输入数据之间要用空格隔开,输完最后一个数据之后,再按下回车键。
但字符变量是例外,几个字符变量的值要连着用键盘输入,输入的字符之间不要用空格隔开,因为空格本身也是一个字符。
字符变量与其他类型数值变量最好不要用同一个scanf()函数调用输入,这样容易在输入时出错。
与printf()类似,在scanf()函数调用时,整型量也不能用格式符%f匹配,实型量也不能用格式符%d匹配。这也是初学者经常犯的严重编程错误。
有了上述这些知识,我们现在可以来完善例题2.5了。请读者先不看答案,自己独立做出来,然后与本书所给的答案比较一下。
经过修改完善的例题2.5如下所示:
1 #include <stdio.h>
2 #define UNIT_PRICE 1.3 /*单价定义为符号常量*/
3 int main(void)
4 {
5 float tenement_area ; /*定义变量:住宅面积*/
6 float management_cost ; /*定义变量:每月物管费用*/
7 printf("请输入住宅面积,单位是平方米\n");
8 scanf("%f" , & tenement_area );
9 management_cost= UNIT_PRICE * tenement_area ; /* 求出每月物管费用*/
10 printf("住宅面积% 6.2f平方米 ,物管费% .2f元\n ",tenement_area , management_cost);
11 return 0;
12 }
编译通过后,请重复两次运行此程序,每次输入的面积不同,看看程序是否输出了相应不同的物管费用。
通过在编程时调用输入库函数,才使程序能够及时从输入设备(人操作的键盘)得到变量的当前值。
【问题1】第8行的语句能否写成:
1) scanf("%f" , tenement_area );
2) scanf("%d" , & tenement_area );
3) scanf("%f , & tenement_area " );
为什么?
【问题2】如果漏写了上例中第8行的scanf()调用语句,结果将如何?
【问题3】能否将变量 tenement_area 定义为int型? 为什么?
延伸与拓展:printf()函数与scanf()函数调用时的一些重要区别
虽然格式化输入库函数scanf()在用法上与printf()有不少类似之处,但是,两者之间在使用上,也有以下所列的重要不同之处:
1)在printf()的格式串中可以使用转义字符 n来换行,但在scanf()的格式串中却不能使用转义字符 n(也不能使用其他一些转义字符)。
2)scanf()的格式串后面的参数是输入数据的存放地址,所以在通常情况下,变量名左边的取地址符号“&”是绝不能漏写的。例如,如果age是int型变量,那么
scanf("%d" , &age);
不能写成
scanf("%d" , age);
然而,对于printf()函数来说,以下语句却常常是一种误写:
printf("%d" , &age);
在VC++ 6.0编译环境下,这只是输出了变量age的内存地址。正确形式是:
printf("%d" , age);
这样才是输出变量age的值。
3)对于printf()函数来说,
printf("%d%d%d", n1,n2,n3) ;
不是好的形式,三个变量的值在输出时根本区分不开;而
printf("n1=%d,n2=%d,n3=%d", n1 , n2 , n3 ) ;
却是比较好的形式。
但是对于scanf()来说:
scanf("%d%d%d", &n1 , &n2 , &n3 ) ;
通常比较好,在输入三个数据之间只需输入一个空格将其分开;而
scanf("n1=%d,n2=%d,n3=%d",& n1 , &n2 , &n3 ) ;
却非常不好。你必须先从键盘键入“n1=”这些字符之后,才能输入变量n1的值,整个输入过程非常麻烦,完全是自讨苦吃。不信你可以亲自试一试。
4)printf()的输出项既可以是表达式和变量,也可以是常量和函数调用(注意:其实它们本质上都是表达式);而scanf ()的输入项通常只能是变量的地址,不能是通常的表达式。