| 网站首页 | JAVA文章 | AppServers | Web开发 | 应用开发 | 资源下载 | 论坛
    想学好编程,学好外语很重要  [enadd  2006年12月25日]        
设为首页 加入收藏 联系站长
您现在的位置: 编程笔记网 >> 应用开发 >> CC++ >> C语言 >> 文章正文
[组图]第三章  三种基本程序结构设计 2            【字体:
第三章  三种基本程序结构设计 2
作者:-    文章来源:-    点击数:    更新时间:2006-12-14

 3.8  选择结构程序设计举例

3.17 求一元二次方程ax2+bx+c=0的解(a≠0)。

1 #include  "math.h"

2 #include <stdio.h>

3 void main()

4 {

5     float a,b,c,disc,x1,x2,p,q;

6     scanf("%f,%f,%f", &a, &b, &c);

7     disc=b*b-4*a*c;

    if(fabs(disc)<=1e-6)  /*fabs():求绝对值库函数*/

9         printf("x1=x2=%7.2f\n", -b/(2*a));/*输出两个相等的实根*/

10    else

11    {

12        if(disc>1e-6)

13        {

14            x1=(-b+sqrt(disc))/(2*a);/*求出两个不相等的实根*/

15            x2=(-b-sqrt(disc))/(2*a);

16            printf("x1=%7.2f,x2=%7.2f\n", x1, x2);

17        }

18        else

19        {

20            p=-b/(2*a);   /*求出两个共轭复根*/

21            q=sqrt(fabs(disc))/(2*a);

22            printf("x1=%7.2f + %7.2f i\n", p, q);/*输出两个共轭复根*/

23            printf("x2=%7.2f - %7.2f i\n", p, q);

24        }

25    }

26 }

说明:由于实数在计算机中存储时,经常会有一些微小误差,所以本案例判断disc是否为0的方法是:判断disc的绝对值是否小于一个很小的数(例如10-6)。

思考题:如果将系数a、b、c定义成整数,能否直接判断disc是否等于0?

 3.18 已知某公司员工的保底薪水为500,某月所接工程的利润profit(整数)与利润提成的关系如下(计量单位:元):

profit≤1000            没有提成;

1000<profit≤2000      提成10%;

2000<profit≤5000      提成15%;

5000<profit≤10000     提成20%;

10000<profit           提成25%。

算法设计要点:

为使用switch语句,必须将利润profit与提成的关系,转换成某些整数与提成的关系。分析本题可知,提成的变化点都是1000的整数倍(1000、2000、5000、……),如果将利润profit整除1000,则当:

profit≤1000            对应0、1

1000<profit≤2000      对应1、2

2000<profit≤5000      对应2、3、4、5

5000<profit≤10000     对应5、6、7、8、9、10

10000<profit           对应10、11、12、……

 为解决相邻两个区间的重叠问题,最简单的方法就是:利润profit先减1(最小增量),然后再整除1000即可:

 profit≤1000            对应0

1000<profit≤2000      对应1

2000<profit≤5000      对应2、3、4

5000<profit≤10000     对应5、6、7、8、9

10000<profit           对应10、11、12、……

1 #include <stdio.h>

2 void main()

3 {

4     long  profit;

5     int  grade;

6     float  salary=500;

7     printf("Input  profit: ");

8     scanf("%ld", &profit);

9     grade= (profit - 1) / 1000;  

10    switch(grade)

11    {

12        case  0:  break;/*profit≤1000 */

13        case  1: salary += profit*0.1; break; /*1000<profit≤2000 */

14        case  2:

15        case  3:

16        case  4: salary += profit*0.15; break; /*2000<profit≤5000 */

17        case  5:

18        case  6:

19        case  7:

20        case  8:

21        case  9: salary += profit*0.2; break;  /*5000<profit≤10000 */

22        default: salary += profit*0.25;   /*10000<profit */

23    }

24    printf("salary=%.2f\n", salary);

25 }

3.9  循环语句概述

我们知道目前计算机是不能进行创造性劳动的,但它却是重复性劳动的高手,而重复性劳动常常可以通过循环来实现。

1~100的累计和。根据已有的知识,可以用“1+2+……+100”来求解,但显然很繁琐。现在换个思路来考虑:

首先设置一个变量sum,其初值为0,用来存放计算之和。利用sum += n来计算(n依次取1、2、……、100),只要解决以下3个问题即可:

1)将n的初值置为1;

2)每执行1次“sum += n”后,n增1;

3)当n增到101时,停止计算。此时,sum的值就是1~100的累计和。

我们可以用if语句+goto语句(无条件转向语句)来实现上述计算。

goto语句的一般格式:

功能为:使系统转向标号所在的语句行执行。

语句标号用标识符表示,它的命名规则与变量名的命名规则相同。例如: 

goto label_1;   /*合法*/

goto 123;       /*不合法*/

goto语句和if语句构成循环。使用goto语句实现求解1~100累计和的程序如下:(流程如图3.10所示)

           

3.10                              3.11

void main()

{

    int  n=1,sum=0;

    loop:  sum+=n;n++;

    if(n<=100)  goto  loop;

    printf(“sum=%d\n”, sum);

}

注意:结构化程序设计方法,主张限制使用goto语句。因为滥用goto语句,将会导致程序结构无规律、可读性差。

由于需要经常使用这种重复计算结构(称为循环结构),C语言提供了3条循环语句来实现,以简化、并规范循环结构程序设计:

1)for语句。(2)while语句。(3)do-while语句。

3.10  for语句、while语句、do-while语句

3.10.1  for语句

3条循环语句中,for语句最为灵活,不仅可用于循环次数已经确定的情况,也可用于循环次数虽不确定,但给出了循环继续条件的情况。

3.19 求1~100的累计和。

1 #include <stdio.h>

2 void main()

3 {

4     int i,sum=0; /*将累加器sum初始化为0*/

5     for(i=1; i<=100; i++)

       sum += i;  /*实现累加*/

7     printf("sum=%d\n",sum);

8 }                    

程序运行结果:sum=5050

3.20 求n的阶乘n!(n!=1*2*……*n)。

1 #include <stdio.h>

2 void main()

3 {

4     int i, n;

5     long  fact=1;     /*将累乘器fact初始化为1*/

6     printf("Input  n: ");

7     scanf("%d", &n);

8     for(i=1; i<=n; i++)

        fact*=i;      /*实现累乘*/

10    printf("%d ! = %ld\n", n, fact);

11 }

 程序运行情况如下:Input  n: 5↙

5 ! = 120

1.    for语句的一般格式

 2.for语句的执行过程

执行过程流程如图3.11所示。

1)求解“循环变量赋初值”表达式。

2)求解“循环继续条件”表达式。如果其值非0,执行(3);否则,执行(4)。

3)执行循环体语句组,并求解“循环变量改变”表达式,然后转向(2)。

4)执行for语句的下一条语句。

3.说明

1)“循环变量赋初值”、“循环继续条件”和“循环变量改变”部分均可缺省,甚至全部缺省,但其间的分号不能省略。(for( ; ; ))

① 循环变量赋初值省略

例: i=1;

     for( ;i<=100;i++)

         sun+=i;

由此可以看出循环变量赋初值并不是真的省略了,而是换了一个地方。

② 循环继续条件省略

例: for(i=1; ;i++)

        sun+=i;

如果循环条件省略,就不判断循环条件,即认为循环条件始终为真,循环无终止的进行,如果没有别的办法退出循环,将成为死循环。

流程如图3.12所示

          

3.12                            3.13 

③ 循环变量改变也可以省略,但程序应另外设法保证循环能正常结束。例:

for(i=1;i<=100;)

{

     sum+=i;

     i++;

  }

从这个意义来看,循环变量改变并没有省,而是换了一个地方。如果不能设法结束循环,循环将成为死循环,死循环一般是没有意义的,应当尽量避免。

④ 可以省略循环变量赋初值和循环变量改变这两个表达式,只留下循环继续条件。这里所说的省略要理解成,在一般情况(不是绝对的)下在适当的位置要给循环变量赋初值,要有改变循环变量值的语句。

例:   i=1; 

       for(;i<=100;)

       {

           sum+=i;

           i++;

       }

2)当循环体语句组仅由一条语句构成时,可以不使用复合语句形式。

3)“循环变量赋初值”表达式,既可以是给循环变量赋初值的赋值表达式,也可以是与此无关的其它表达式(如逗号表达式)。

例如,for(sum=0,i=1;i<=100;i++)

           sum += i;

4)“循环继续条件”部分是一个逻辑量,除一般的关系(或逻辑)表达式外,也允许是数值(或字符)表达式。C语言将非0值看成是逻辑真,将0值看成是逻辑假。

3.10.2  while语句

1.     while语句又叫“当型”循环语句,它的一般格式为:

2. while语句的执行过程

执行过程流程如图3.13所示。

1)求解“循环继续条件”表达式。如果其值为非0,转(2);否则转(3)。

2)执行循环体语句组,然后转(1)。

3)执行while语句的下一条。

显然,while循环是for循环的一种简化形式(缺省“变量赋初值”和“循环变量改变”表达式)。

while循环的特点是,先判断条件后执行循环  

3.21 用while语句求1~100的累计和。

1 #include <stdio.h>

2 void main()

3 {

4      int i=1,sum=0;   /*初始化循环控制变量i和累计器sum*/

5      while( i<=100 )

6      {

7         sum += i; /*实现累加*/

8         i++;      /*循环控制变量i增1*/

9      }

10      printf("sum=%d\n",sum);

11 }

程序运行情况如下:

sum=5050 

 3.10.3  do-while语句

1do-while语句又叫“直到”循环语句,它的一般格式为:

 尾行的分号不能省!!。

当循环体语句组仅由一条语句构成时,可以不使用复合语句形式。

2.执行过程

执行流程如图3.14所示。

1)执行循环体语句组。

3.14

2)计算“循环继续条件”表达式。如果“循环继续条件”表达式的值为非 0(真),则转向(1)继续执行;否则,转向(3)。

3)执行do-while的下一条语句。

do-while循环语句的特点是:先执行循环体语句组,然后再判断循环条件。

3.22 用do-while语句求解1~100的累计和。

1 #include <stdio.h>

2 void main()

3 {

4     int i=1, sum=0; /*定义并初始化循环控制变量,以及累计器*/

5     do

6     {

7         sum += i;     /*累加*/

8         i++;   

9     }while(i<=100);   /*循环继续条件:i<=100*/

10    printf("sum=%d\n",sum);

11 }

程序执行结果为:sum=5050

 do-while语句比较适用于处理:不论条件是否成立,先执行1次循环体语句组的情况。除此之外,do-while语句能实现的,for语句也能实现,而且更简洁。

如果例3.20和例3.21循环条件一开始就为假,它们的运算结果如何,同学们可以试一试。 

3.10.4  循环的嵌套

如果循环体内,又包含另一个完整的循环结构,称为循环的嵌套。循环可以允许多层嵌套。

for语句、while语句、do-while语句都允许进行嵌套,并且可以进行相互嵌套。

1)for循环嵌套 如图3.15~3.17

2)while循环嵌套 如图3.18~3.20

3)do-while循环嵌套 如图3.21~3.23

关于循环的几点注意:

3.15                         图3.16

3.17

3.18                           图3.19

3.20

3)do-while循环嵌套 如图3.18~图3.20

3.21                        图3.22

3.23

1)四种循环都可以处理同一问题,没有孰优孰劣之分。但一般不用goto语句来实现循环。

2)while和do-while循环,只在while后面指定循环条件,因此在循环体中要有使循环趋于结束的语句。

3)一般情况下我们不能忘记“循环三要素”,即“循环变量赋初值”、“循环结束条件(或继续条件)”、“循环变量的改变”(可增可减)。

3.11  break语句与continue语句

为了使循环控制更加灵活,C语言提供了break语句和continue语句。

1.  一般格式:

2.功能

我们在前面已经知道break语句可以跳出switch结构,实际上break语句还可以用于循环语句中。

1)break:强行结束循环,转向执行循环语句的下一条语句。

2)continue:结束本次循环。对于for循环,跳过循环体其余语句,转向循环变量改变表达式的计算;对于while和do-while循环,跳过循环体其余语句,但转向循环继续条件的判定。

3)break和continue语句对循环控制的影响如图3.24和图3.25所示。

3.说明

1)break能用于循环语句和switch语句中,continue只能用于循环语句中。

2)循环嵌套时,break和continue只影响包含它们的最内层循环,与外层循环无关。

3.23 把100~200之间的不能被3整除的数输出,并且每行输出10个。

1 #include <stdio.h>

2 void main()

3 {

    int n,count=0;

5     for(n=100;n<=200;n++)

6     {

7         if(n%3==0)

8             continue;

9         count++;

10        printf("%5d",n);

11        if(count%10==0)

12            printf("\n");

13    }

14 }

        

           

3.24                         图3.25

3.12  循环结构程序举例

3.24 求Fibonacci数列的前40个数。

    该数列的生成方法为:F1=1,F2=1,Fn=Fn-1+Fn-2n>=3),即从第3个数开始,每个数等于前2个数之和。

1 #include <stdio.h>

2 void main()

3 {

4     long f1=1,f2=1;   /*定义并初始化数列的头2个数*/

5     int i=1;      /*定义并初始化循环控制变量i*/

6     for( ; i<=20; i++ ) /*1组2个,20组40个数*/

7    {

8         printf("%15ld%15ld", f1, f2); /*输出当前的2个数*/

9         if(i%2==0)

10            printf("\n");     /*输出2次(4个数),换行*/

11        f1 += f2;          /*计算下2个数*/

12        f2 += f1;        

13    }

14 }               

3.25 输出10~100之间的全部素数。所谓素数n是指,除1和n之外,不能被2~(n-1)之间的任何整数整除。

算法设计要点:

1)显然,只要设计出判断某数n是否是素数的算法,外面再套一个for循环即可。

2)判断某数n是否素数的算法:根据素数的定义,用2~(n-1)之间的每一个数去整除n,如果都不能被整除,则表示该数是一个素数。

判断一个数是否能被另一个数整除,可通过判断它们整除的余数是否为0来实现。

源程序如下:

1 #include <stdio.h>

2 void main()

3 {

4     int i=11, j, counter=0;

5     for(;i<=100;i+=2) /*外循环:为内循环提供一个整数i*/

6     {

        for(j=2;j<=i-1;j++)/*内循环:判断整数i是否是素数*/

            if(i%j==0)      /*i不是素数*/

9                 break;    /*强行结束内循环,执行下面的if语句*/

10        if(j>=i)   /*整数i是素数:输出,计数器加1*/

11        {

12            printf("%6d",i);

13            counter++;

14        }

15        if(counter%10==0)/*每输出10个数换一行*/

16              printf("\n");

17    }

18    printf("\n");

19 }

3.13  良好的源程序书写习惯

 顺序程序段中的所有语句(包括说明语句),一律与本顺序程序段的首行左对齐,并且采用缩进对齐的方式,使程序便于阅读。