程序2-1的运行结果并不令人满意,因为华氏温度100对应的摄氏温度应该为37.777…而不应该是37。int类型不适用于所有应用,这里需要用浮点型变量来存储带小数点的数,需要将celsius和fahr声明为浮点类型。
试试看:从键盘上输入任意一个浮点数作为华氏温度,编程输出相对应的摄氏温度。
/*程序2-4:对任意浮点数进行温度转换*/
程序2-4的语句
double celsius,fahr;
是将celsius和fahr声明为双精度浮点变量,而在语句
printf("fahr=%f,celsius=%f\n",fahr,celsius);
中printf的格式转换符%f用来输出浮点数据。语句
scanf("%lf",&fahr);
中scanf的格式转换符%lf用来读入双精度浮点数据。
浮点型变量用来存储浮点数,浮点数既可表示小数,也可表示分数和整数。浮点数在计算机中的表示是基于指数表示法,分为指数和尾数来存储。根据数据表示范围和精确度不同,C语言提供了3种不同的浮点格式float、double和long double。IEEE标准中浮点类型的一些特征如表2-3所示。
表2-3 浮点类型(IEEE标准)
long double类型没有显示在此表中,因为它的长度随着机器的不同而变化,最常见的是80位和128位,而VC++6.0中,long double和double类型的长度相同,都是64位。
1.转换字符串%f
格式转换符f用于浮点数据的输出格式限定,在程序2-3中,语句
printf("fahr=%f,celsius=%f\n",fahr,celsius);
是将浮点型变量fahr和celsius以小数形式输出到屏幕上,输出结果为:fahr=100.000000,celsius=37.777778。两个浮点型变量以小数形式输出时,小数部分精确到6位。
2.转换字符串%m.nf
m表示输出宽度,而n表示精度,指定小数点后显示的数字个数。例如:
double mercuryLevel=168.2251074;
printf("%7.2f",mercuryLevel);
输出结果为:168.23。
此输出函数是将mercuryLevel变量以单精度小数形式输出,要求输出时宽度(所有数字和小数点所占的位数)为7位,右对齐,小数点后精确到2位。
当指定的输出宽度大于数据的实际宽度,则默认在宽度内为右对齐,左补空格或补0,直到满足指定宽度。当指定的输出宽度小于数据的实际宽度时,则按实际数据的位数输出(宽度自动增加)。对于整数而言,按该数的实际宽度输出,对浮点数而言,按实际位数输出,但如果指定浮点数的精度,则相应的小数位按精度的位数四舍五入。
如果没有为要输出的数据提供足够大宽度,可能造成其他输出数据发生位置偏移,从而产生不可预料的输出结果。
在输入浮点数时,输入单精度可以使用格式符f、g、e,输入双精度浮点数需要加前缀l。可以指定读入数据的宽度,但不能指定精度。如:
如下程序段定义一个double类型的变量a,然后为其读入数据,在读入数据时指定读入宽度,最后输出a的值。
double a;
scanf("%5lf",&a);
printf("%f\n",a);
若输入:12.34567,则输出:12.340000。若输入:1.2e12,则输出:12.0000000。因为指定了输入宽度为5,在输入12.34567时,只读取前5个字符12.34,转换为双精度浮点型存入变量a;在输入1.2e12时,只读取前5个字符1.2e1,转换为双精度浮点型存入变量a。
在scanf()函数的格式控制字符串中若有普通字符,则输入时在对应位置也必须输入该普通字符,否则会因读入格式错误而终止程序。
例如:scanf("%d,%d",&a,&b);
格式控制字符串中有普通字符逗号,所以输入时两个数据之间必须输入一个逗号,即输入:3,5。
例如:scanf("a=%d,b=%b",&a,&b);
此时输入数据的格式应该是:a=3,b=5。
scanf的格式控制字符串中最好不加任何普通字符,只写%开头的格式转换符。如scanf("%d%d",&a,&b);
不要给用户制造输入格式限制,以免增加输入操作错误的几率。
和变量一样,常量也是程序使用的一个数据存储位置。和变量不同的是,在程序运行期间,存储在常量中的值是不能修改的。C语言中的常量分为字面常量、宏常量、const常量。
1.字面常量
字面常量是指在源代码中直接输入的值,分为以下4种:
·整型常量,如:32、100、071、0x3A;
·浮点常量,如:1.23、123.567E5;
·字符常量,如:'a'、'2'、'\n';
·字符串常量:如:"c program"。
C语言支持的整型字面量有十进制、八进制和十六进制。八进制常量以前缀“0”开头,如071,为八进制数,对应的十进制数为57。十六进制常量以“0x”开头,如0x3A,为十六进制数,对应十进制数为58。
2.宏常量
宏常量是指为使程序易于阅读和便于修改,给程序中经常使用的常量定义一个有一定含义的名字,常量用于定义具有以下特点的数据:
·在程序中保持不变;
·在程序内部频繁使用;
·需要用比较简单的方式替代某些值;
·防止意外的修改,增强程序的健壮性。
定义宏常量格式:
#define 标识符常量 替换文本
#define编译指令的准确含义是,命令编译器将源代码中所有标识符常量替换为替换文本。其效果与使用编辑器手工进行查找并替换相同。
例如:#define PI 3.1415926
编译预处理指令#define将PI定义成一个要被3.1415926取代的符号,此时PI不是一个变量,而是3.1415926的别名。在编译开始之前,只要在程序的表达式中引用PI,预处理器就会用#define指令中的值3.1415926来取代它。
根据约定,符号常量名中的字母为大写,这易于将其同变量名区分开来。
#define语句不以分号结尾,可以位于源代码的任何位置,它定义的常量只在后面的源代码中有效。
一般情况下,程序员将所有的#define放在一起,并将它们放在程序的开头。
宏常量也有其自身的缺点,就是宏常量被替换成替换文本之后,内存中有同一个替换文本的多份副本。
3.const常量
const常量与变量定义形式类似,加上const修饰,告诉编译器,它的值是固定的,不能被改变,编译器会帮你检查、监督。
定义const常量,用到关键字const。例如:
const double PI=3.1415926;
const推出的初始目的,正是为了取代宏常量,消除其缺点,同时继承其优点。
在编译的时候,由于const定义常量只是给出了对应的内存地址,而不是像#define给出的是替换文本,所以const定义的常量在程序运行过程中只有一份副本,而#define定义的常量在内存中有若干份副本。
下面通过程序2-5来学习如何使用常量。
试试看:定义常量。
已知一个圆柱体的底面半径和高,求圆柱体的体积,圆周率用宏常量来表示。
/*程序2-5:求圆柱体体积*/
也可以使用const声明常量PI将程序2-5中第2行改成const double PI=3.1415926。