《C程序设计语言(第2版新版)典藏版》 —1.2 变量与算术表达式
1.2 变量与算术表达式
我们来看下一个程序,使用公式鸆=(5/9)(鸉-32)打印下列华氏温度与摄氏温度对照表:
此程序中仍然只包括一个名为main的函数定义。它比前面打印“hello,world”的程序长一些,但并不复杂。这个程序中引入了一些新的概念,包括注释、声明、变量、算术表达式、循环以及格式化输出。该程序如下所示:
其中的两行
称为注释,此处,它简单地解释了该程序是做什么用的。包含在/*与*/之间的字符序列将被编译器忽略。注释可以自由地运用在程序中,使得程序更易于理解。程序中允许出现空格、制表符或换行符之处,都可以使用注释。
在C语言中,所有变量都必须先声明后使用。声明通常放在函数起始处,在任何可执行语句之前。声明用于说明变量的属性,它由一个类型名和一个变量表组成,例如:
其中,类型int表示其后所列变量为整数,与之相对应,float表示所列变量为浮点数(即可以带有小数部分的数)。int与float类型的取值范围取决于具体的机器。对于int类型,通常为16位,其取值范围为-32 768~+32 767,也有用32位表示的int类型。float类型通常是32位,它至少有6位有效数字,取值范围一般为10-38~10+38。
除int与float类型之外,C语言还提供了其他一些基本数据类型,例如:
char 字符—一个字节
short 短整型
long 长整型
double 双精度浮点型
这些数据类型对象的大小也取决于具体的机器。另外,还存在这些基本数据类型的数组、结构、联合,指向这些类型的指针以及返回这些类型值的函数。我们将在后续相应的章节中分别介绍。
在上面的温度转换程序中,最开始执行的计算是下列4个赋值语句:
它们为变量设置初值。各条语句均以分号结束。
温度转换表中的各行计算方式相同,因此可以用循环语句重复输出各行。这是while循环语句的用途:
while循环语句的执行方式是这样的:首先测试圆括号中的条件,如果条件为真(fahr<=upper),则执行循环体(括在花括号中的3条语句);然后再重新测试圆括号中的条件,如果为真,则再次执行循环体;当圆括号中的条件测试结果为假(fahr>upper)时,循环结束,并继续执行跟在while循环语句之后的下一条语句。在本程序中,循环语句后没有其他语句,因此整个程序的执行终止。
while语句的循环体可以是用花括号括起来的一条或多条语句(如上面的温度转换程序),也可以是不用花括号括起来的单条语句,例如:
在这两种情况下,我们总是把由while控制的语句缩进一个制表位,这样就可以很容易地看出循环语句中包含哪些语句。这种缩进方式突出了程序的逻辑结构。尽管C编译器并不关心程序的外观形式,但正确的缩进以及保留适当空格的程序设计风格对程序的易读性非常重要。我们建议每行只书写一条语句,并在运算符两边各加上一个空格字符,这样可以使得运算的结合关系更清楚明了。相比而言,花括号的位置就不那么重要了。我们从比较流行的一些风格中选择了一种。读者可以选择适合自己的一种风格,并养成一直使用这种风格的好习惯。
在该程序中,绝大部分工作都是在循环体中完成的。循环体中的赋值语句
用于计算与指定华氏温度相对应的摄氏温度值,并将结果赋值给变量celsius。在该语句中,之所以把表达式写成先乘5然后再除以9而不是直接写成5/9,其原因是在C语言及许多其他语言中,整数除法操作将执行舍位,结果中的任何小数部分都会被舍弃。由于5和9都是整数,5/9后经截取所得的结果为0,因此这样求得的所有摄氏温度都将为0。
从该例子中也可以看出printf函数的一些功能。printf是一个通用输出格式化函数,第7章将对此做详细介绍。该函数的第一个参数是待打印的字符串,其中的每个百分号(%)表示其他的参数(第二个参数,第三个参数,……)之一进行替换的位置,并指定打印格式。例如,%d指定一个整型参数,因此语句
用于打印两个整数fahr与celsius的值,并在两者之间留一个制表符的空间(\t)。
printf函数的第一个参数中的各个%分别对应于第二个参数,第三个参数,……它们在数目和类型上都必须匹配,否则将出现错误的结果。
顺便指出,printf函数不是C语言本身的一部分,C语言本身并没有定义输入/输出功能。printf仅仅是标准库函数中一个有用的函数,这些标准库函数在C语言程序中通常都可以使用。但是,ANSI标准定义了printf函数的行为,因此,对每个符合该标准的编译器和库来说,该函数的属性都是相同的。
为了将重点放到讲述C语言本身上,我们在第7章之前的各章中将不再对输入/输出做更多的介绍,并且,特别将格式化输入推后到第7章讲解。如果读者想了解数据输入,可以先阅读7.4节中对scanf函数的讨论部分。scanf函数类似于printf函数,但它用于读输入数据而不是写输出数据。
上述的温度转换程序存在两个问题。比较简单的问题是,由于输出的数不是右对齐的,所以输出的结果不是很美观。这个问题比较容易解决:如果在printf语句的第一个参数的%d中指明打印宽度,则打印的数字会在打印区域内右对齐。例如,可以用语句
打印fahr与celsius的值,这样,fahr的值占3个数字宽,celsius的值占6个数字宽,输出的结果如下所示:
另一个较为严重的问题是,由于我们使用的是整型算术运算,因此经计算得到的摄氏温度值不太精确,例如,与0鸉对应的精确的摄氏温度应该为-17.8℃,而不是-17℃。为了得到更精确的结果,应该用浮点算术运算代替上面的整型算术运算。这就需要对程序做适当修改。下面是该程序的又一种版本:
这个程序与前一个程序基本相同,不同的是,它把fahr与celsius声明为float类型,转换公式的表述方式也更自然一些。在前一个程序中,之所以不能使用5/9的形式,是因为按整型除法的计算规则,它们相除并舍位后得到的结果为0。但是,常数中的小数点表明该常数是一个浮点数,因此,5.0/9.0是两个浮点数相除,结果将不被舍位。
如果某个算术运算符的所有操作数均为整型,则执行整型运算。但是,如果某个算术运算符有一个浮点型操作数和一个整型操作数,则在开始运算之前整型操作数将会被转换为浮点型。例如,在表达式fahr-32中,32在运算过程中将被自动转换为浮点数再参与运算。不过,即使浮点常量取的是整型值,在书写时也最好为它加上一个显式的小数点,这样可以强调其浮点性质,便于阅读。
第2章将详细介绍把整型数转换为浮点型数的规则。在这里需要注意,赋值语句
与条件测试语句
也都是按照这种方式执行的,即在运算之前先把int类型的操作数转换为float类型的操作数。
printf中的格式说明%3.0f表明待打印的浮点数(即fahr)至少占3个字符宽,且不带小数点和小数部分;%6.1f表明另一个待打印的数(celsius)至少占6个字符宽,且小数点后面有1位数字。其输出如下所示:
格式说明可以省略宽度与精度。例如,%6f表示待打印的浮点数至少有6个字符宽;%.2f指定待打印的浮点数的小数点后有两位小数,但宽度没有限制;%f则仅仅要求按照浮点数打印该数。
%d 按照十进制整型数打印
%6d 按照十进制整型数打印,至少6个字符宽
%f 按照浮点数打印
%6f 按照浮点数打印,至少6个字符宽
%.2f 按照浮点数打印,小数点后有两位小数
%6.2f 按照浮点数打印,至少6个字符宽,小数点后有两位小数
此外,printf函数还支持下列格式说明:%o表示八进制数;%x表示十六进制数;%c表示字符;%s表示字符串;%%表示百分号(%)本身。
练习1-3 修改温度转换程序,使之能在转换表的顶部打印一个标题。
练习1-4 编写一个程序打印摄氏温度转换为相应华氏温度的转换表。
- 点赞
- 收藏
- 关注作者
评论(0)