1.2变量和算术表达式

来源:互联网 发布:手机屏幕锁屏软件 编辑:程序博客网 时间:2024/04/30 18:34

下一个程序使用公式 来打印下面的华氏和它对应的摄氏温度的一个表:

1    -17

   20   -6

   40   4

   60   15

   80   26

   100  37

   120  48

   140  60

   160  71

   180  82

   200  93

   220  104

   240  115

   260  126

   280  137

   300  148

 

这个程序仍然由定义的一个main函数组成。比打印“hello,world”的程序要长些,但不复杂。这个程序要介绍几个新的概念,包括注释,声明,变量,算法表达式,循环,以及格式化输出。

 

#include <stdio.h>

 

   /* print Fahrenheit-Celsius table

       for fahr = 0, 20, ..., 300 */

   main()

   {

     int fahr, celsius;

     int lower, upper, step;

 

     lower = 0;      /* lower limit of temperature scale */

     upper = 300;    /* upper limit */

     step = 20;      /* step size */

 

     fahr = lower;

     while (fahr <= upper) {

         celsius = 5 * (fahr-32) / 9;

         printf("%d/t%d/n", fahr, celsius);

         fahr = fahr + step;

     }

   }

 

这两行:

 /* print Fahrenheit-Celsius table

      for fahr = 0, 20, ..., 300 */

就是注释,这里是来简单解释程序的用途。介于/**/之间的任何字符都会被编译器忽略。它们可以自由地使用来使程序更容易理解。注释可以在任何地方使用,空格,制表列或者一个新行。

 

C中,所有变量在使用前都必须先声明,通常在函数的任何可执行语句之前声明。一个声明宣告一个变量的特性,它由一个类型名和一列变量组成,比如:

 

    int fahr, celsius;

int lower, upper, step;

类型int表示列出的那些变量是整数类型,对应的有float即浮点型,也是数字可以带有小数部分。Intfloat的数值数范围取决于你使用的机器。16位的int可以表示-3276832767之间的数。通常来说是32int。一个float数典型的是一个32位数。至少有6位有效数字,数量级通常介于 之间。

C语言除了int float 外还包括其它几种数据类型,有:

 char 

 character - a single byte

 short 

 short integer

 long 

 long integer

 double 

 double-precision floating point 

这些类型的大小仍然依赖于机器。类型还有数组,结构和枚举,在这些基本类型中,指针能够指向它们,函数可以返回这些类型值。所有的这些我们都会在以后的课程中学到。

 

在这个温度转换程序中,计算从赋值语句开始

 

lower = 0;

    upper = 300;

step = 20;

 

这些语句设定了变量的初始值。每个语句都由一个分号;结束。

表中每行的处理方式一样,所以我们使用循环来重复每行的输出,这也是使用while循环的目的。

 

while (fahr <= upper) {

       ...

}

 

while循环过程如下:检测括号中的条件,如果是true,就执行循环体的语句,然后再检测条件。当条件娈为false时,循环结束。程序继续执行跟在循环后面的语句。在这个程序中没有更多的语句,所以程序结束。

 

while的循环体可以有一个或多个由大括号包围的语句。在这个温度转换程序中或者只有一条语句的情况下,可以不使用大括号,即以下形式:

while (i < j)

       i = 2 * i;

在任何情况下,我们总是使用一个tab键来缩进while控制的那些语句,因此你可以一眼看出循环体中的语句。缩进强调程序的逻辑结构。尽管编译器不会在意一个程序的形式,但适当的缩进和空格会使程序容易阅读。我们建议一行写一个语句,运算符两边使用空格来分组。大括号的位置相对不怎么重要,尽管有人热衷于此。我们选取了一些受欢迎的风格。选择你喜欢的一种方式并始终如一的使用。

大多数的工作由循环体完成。经过计算后的摄氏温度赋给变量celsius

 

celsius = 5 * (fahr-32) / 9;

 

先乘5再除9而不直接乘5/9的原因是在C语言中,如和许多其它语言一样,整数相除会产生:任何小数部分被丢弃。因为59都是整数,5/9会被截断变成0,这样摄氏温度就将是0了。

这个程序也显示了一些更多的printf功能,printf是一个多用途的格式控制输出函数。我们将在第7章详细描述。它的第一个参数是将要打印的字符串,其中的%指出还有其它参数要打印(第2,3个参数……)以及要打印的参数的形式。比如,%d代表一个整型参数,因此语句

 

printf("%d/t%d/n", fahr, celsius);

 

导致两个整数 fahrcelsius 的值被打印出来,中间隔有一个制表列。

printf第一个参数中的每个%结构都和相应的第二个,第三个参数等等相对应,它们必须在数量和类型上相匹配,否则你可能会得到错误的答案。
顺便说下,printf不是C语言的一部分了,C语言本身没有定义输入输出语句。Printf只是来自标准库的一个有用的函数,通常的C程序都可以使用。printf函数的行为特性定义在ANSI标准中。然而,和标准一致的任何编译器和库,printf的特性都应该是一样的。

为了集中在C本身,我们在第7章之前不过多讨论输入和输出函数。特别是我们把格式化输入也推迟到那个时候再说。如果你必须要输入数,可以读7.4部分的scanf的相关讨论。scanfprintf类似,只不过它是读入数而不是输出数。

对于这个温度转换程序还有一些问题。简单一点的就是这个输出不够优美,因为数字对齐不对。这个很容易解决,如果我们给printf中的每个%d参数一个宽度,那么数字就会相应对齐了。例如,我们可以这样:

 

printf("%3d %6d/n", fahr, celsius);

 

每行的第一个数用3位数字宽度,第二个用6个数字宽度来打印。

稍微严重一点的问题是,因为我们用的是整数运算,摄氏温度不够精确。比如0 实际上是 而不是-17。要得到更精确的答案,我们应该使用浮点运算来代替整数运算。这就需要对程序进行一些改变。下面的是第二版:

 

#include <stdio.h>

 

   /* print Fahrenheit-Celsius table

       for fahr = 0, 20, ..., 300; floating-point version */

   main()

   {

     float fahr, celsius;

     float lower, upper, step;

 

     lower = 0;      /* lower limit of temperatuire scale */

     upper = 300;    /* upper limit */

     step = 20;      /* step size */

 

     fahr = lower;

     while (fahr <= upper) {

         celsius = (5.0/9.0) * (fahr-32.0);

         printf("%3.0f %6.1f/n", fahr, celsius);

         fahr = fahr + step;

     }

   }

 

除了fahrcelsius声明为float型变量,相应的转换公式写成更自然的方式外,这个程序和前面的差不多。我们在前面不能直接乘5/9是因为整数相除会产生截断,5/9就会变为0。常数中的小数点表示它是一个浮点数。因此5.0/9.0不会被截断是因为它是两个浮点数的比。

 

如果一个算术运算有整数操作数的话,就会进行整数运算。如果是浮点运算而有整数参与的话,在进行浮点运算之前,整数将会转换成浮点数。如果我们写的是(fahr32),则数32将自动转换成浮点数。尽管如此,即使有整数时,也用清楚的小数点书写浮点常数能突出浮点运算的性质。

整数转换成浮点数的详细规则放在第二章。现在,注意这个赋值语句:

 

fahr = lower;

 

还有这个条件测试

 

while (fahr <= upper)

 

也工作在自然而然的方式下――在运算之前,int型被转换成float

pritnf的变换格式%3.0f表示一个浮点数至少打印成3个字符宽,不带有小数点,没有小数部分。%6.1f表示另一个数至少打印成6个字符宽,并且小数点后带有一位小数。输出看上去如下:

0  -17.8

    20    -6.7

    40     4.4

   ...

宽度和精度可以以一种格式忽略:%6f说明数字打印至少6个字符宽,%.2f说明小数点后有两位,但是宽度没有限制。%f只是说明要按浮点数打印。

 %d

 print as decimal integer

 %6d

 print as decimal integer, at least 6 characters wide

 %f

 print as floating point

 %6f

 print as floating point, at least 6 characters wide

 %.2f

 print as floating point, 2 characters after decimal point

 %6.2f  

 print as floating point, at least 6 wide and 2 after decimal point 

printf支持的其它的一些输出格式有:%o用于输出八进制数,%x用于输出十六进制数,%c用于输出字符,%s用于输出字符串,%%用于输出%本身。

 

Exercise 1-3. Modify the temperature conversion program to print a heading above the table.

 

解:

#include <stdio.h>

/*print Fahrenheit-Celsius table for fahr=0,20,...,300*/

 

main()

{

float fahr,celsius;

float lower,upper,step;

 

lower=0;

upper=300;

step=20;

 

fahr=lower;

printf("--------------------------Fahrenheit-Celsius table------------------------/n");

while(fahr<=upper)

{

       celsius=(5.0/9.0)*(fahr-32);

       printf("%3.0f/t%6.1f/n",fahr,celsius);

       fahr=fahr+step;

}

printf("--------------------------------------------------------------------------------/n");

}

 

Exercise 1-4. Write a program to print the corresponding Celsius to Fahrenheit table.

解:

#include <stdio.h>

/*print Celsius-Fahrenheit table */

 

main()

{

float fahr,celsius;

float lower,upper,step;

 

lower=0;

upper=300;

step=15.5;

 

fahr=lower;

printf("--------------------------Celsius-Fahrenheit table------------------------/n");

while(celsius<=upper)

{

       fahr=(9.0/5.0)*celsius+32;

       printf("%3.0f/t%6.1f/n",celsius,fahr);

       celsius=celsius+step;

}

printf("--------------------------------------------------------------------------/n");

}