310 likes | 473 Views
第 5 章 循环控制. 四、 break 语句与 continue 语句 五、 goto 语句 六、多重循环 七、梯形法求积分算例. 四、 break 语句与 continue 语句 前面三种循环结构都以某个表达式的判断结果作为循环 条件,当表达式的值为零时,就立即结束循环。 这是一种遇零就结束循环的简短直接的判断。 C/C++ 另外提供了 break 语句、 continue 语句与 goto 语 句来改变循环的转向。 break 与 continue 语句用在 while 、 do~while 和 for 循环
E N D
第5章 循环控制 • 四、break语句与continue语句 • 五、goto 语句 • 六、多重循环 • 七、梯形法求积分算例
四、break语句与continue语句 • 前面三种循环结构都以某个表达式的判断结果作为循环 • 条件,当表达式的值为零时,就立即结束循环。 • 这是一种遇零就结束循环的简短直接的判断。 • C/C++另外提供了break语句、continue语句与goto 语 • 句来改变循环的转向。 • break与continue语句用在while、do~while和for循环 • 中,break尚可用于switch 语句。 • break语句与continue语句的语法格式非常简单,各在其 • 关键字后跟随一个分号 : • break; • 或 continue;
后续语句 for while do 初始表达式 循环体 ... [ break;] ... [continue;] .... 表达式 表达式 非零 零 零 非零 非 零 循环体 [ break;] ... [continue;] .... 循环体 [ break;] ... [continue;] .... while 表达式 零 后续语句 增量表达式 后续语句 • (1)while语句 (2)for语句 (3) do~ while语句
1.break语句 • 用于退出循环体或switch语句,在多重循环或switch语 • 句的嵌套中break语句仅只终止最紧密包含它的循环体或 • switch语句,控制跳转到当前层的循环体或switch语句的后 • 续语句; • 2.continue语句 • 仅位于循环语句的循环体中,忽略跟随其后的剩余语 • 句,然后判断是否继续下一轮的循环,它的作用不是结束循 • 环迭代,而是退出本次循环,继续下一轮的循环; • 对于while和do~while循环continue语句跳到循环的底 • 部或立即执行条件测试,对于常规的for循环,执行增量表 • 式之后再继续下一个回合的条件判断。
for循环和while循环具有下面的相当的关系: • for(初始化表达式;条件表达式;增量表达式) • {循环体语句;} • for (initialexpre; conditionexpre; stepexpre) • { statement; } • 相当于下面while循环: • initialexpre; while (conditionexpre) • { statement; stepexpre; } • 初始化表达式; while (条件表达式) • { 循环体语句; 增量表达式; } • 但continue语句隐含地执行for循环的增量表达式。如 • 果while循环中的增量表达式位于continue语句之后,此时 • 这个增量表达式stepexpre可以不执行。这是两者不同之 • 处。
常规形式: • for (initexpre;conditionexpre;stepexpre) • { statement;} • # include<iostream.h> //求自然数的和 • void main (void) • { int sum=0; • for (int k=0; k<=100; sum+=k++) • ; // 循环体的语句为空语句 • cout<<sum <<endl; • } //输出 5050
初始化表达式前置: • initexpre;for ( ; conditionexpre; stepexpre) • { statement; } • # include<iostream.h> • int sum ( int k ) • //此种形式用于函数体中,初始值直接从形参中获得 • { int s=0; • for ( ; k<=100;s+=k++) ; //循环体的语句为空语句 • return s; } • void main (void) { cout<<sum (10) <<endl; } • //输出 5005
条件表达式内置(目的是灵活控制循环的跳出件):条件表达式内置(目的是灵活控制循环的跳出件): • for (initexpre ; ; stepexpr) • { if(condition1==0) break; • //条件1为0跳出循环 • statement; //条件1非0继续循环 • if(condition2) break; • //条件2为非0跳出循环 • } //for ( initexpre ; ; stepexpr )等价于 • for(initexpre ; 1 ; stepexpr) • 此时如果for循环中没有相应的跳出条件,则 • 构成无穷循环。
[例]输出奇数 [例2]输出偶数 • # include<iostream.h> # include<iostream.h> • void main (void) void main(void) • { for(int k=1;k<10;k++) { for (int k=1;;k++){ • { if (k%2==0) continue; if (k%2==0) {cout<<k<<","; continue; } • cout<<k<<","; if (k>10) break; • } } • } } • /*输出:1,3,5,7,9,*/ //输出:2,4,6,8,10,
条件表达式内置与增量表达式内置 • [例]输出奇数 [例]输出偶数 • # include<iostream.h> # include<iostream.h> • void main (void) void main (void) • { for (int k=0;;) { for (int k=0;;) • { k++; { k++; • if (k<10) if (k%2==0) • {if(k%2){cout<<k; continue;}} {cout<<k; continue;} • else break; if (k>10) break; • } } • }//输出:246810 }//输出:13579
无穷循环for (;;) • # include<iostream.h> • void main(void) • { int k=0,sum=0; // initexpre; • for(; ;) //for (;;) • { if( k>100) break; • //{ if(condition) break;条件判断为真退出循环 • sum+=k; • // statement; 条件判断为0执行循环体 • k++; // stepexpre; 循环步长增量变动 • } • cout<<sum <<endl; /*输出 5050*/ • }
五、goto 语句 • 要求和标号配合及使用的格式如下: • goto 标号; goto label; • 标号:语句; label :statement; goto语句 • goto语句要求和标号配合;其中标号的命名遵循标识 • 符的规定。 • goto语句的功能是把程序控制转移到标号指定的语 • 句,即执行goto语句之后,程序从指定标号处的语句继续执 • 行标号表明程序中代码段的某个位置。 • 标号加在某个执行语句的前面,其后面使用冒号“:”作 • 为分隔符。
[例] for循环与if~goto label 循环比较 • 1.if~goto label 循环求和 2.goto 语句循环求和 • # include<iostream.h> int sum (int n=100) • void main (void) { int k=1,s=0; • { int k=0,sum=0; loop: • loop: if (k<=n) • if(k>100) goto end; { s+=k++; • sum+=k++; goto loop; • goto loop; } • end: cout <<sum <<endl; return s; • } /*输出 5050*/ }
3. if~goto label 循环求和 • # include<iostream.h> • void main (void) • { int k=0,sum=0; • loop: • if (k>100) goto end; • sum+=k++; • goto loop; • end:cout << sum << endl; • } /*输出 5050*/
六、多重循环 • 多重循环结构指在循环体中的复合语句是另外一个循环 • 控制结构,形成循环的多层次的嵌套。 • C/C++中三种循环可以互相渗透互相包含,也可以自身嵌套 • 如: • while(e4) statement ; • while(e) while(e4) statement ; • for (e1;e2;e3) while(e4) statement; • while(e) for (e1;e2;e3) while(e4) statement; • do { do { statement;} while(e1);} while(e2); • while(e) do do statement; while(e1); while(e2);
每一个循环控制结构本身应是一个完整的循环语句,同每一个循环控制结构本身应是一个完整的循环语句,同 • 时完整的循环语句可以视为一条简单的语句。单一语句可以 • 出现的场所,完整的循环语句也可以恰当地嵌入。 • 循环嵌套时外层的循环控制变量常作为内层的循环控制 • 体相关变量的初值。 • 不要在内层轻易改变外层循环的增量控制条件。 • for循环语句 [ for (e1; e2; e3) s; ]中的语句是另外一个 • for循环语句这样就得到双重for循环: • for ( e1;e2;e3 ) for ( e4;e5;e6 ) statement;
[例]求的 和,误差小于指定精度eps • #include<stdio.h> • #include<math.h> • const double e=exp(1); • double expf () • { double const eps=1.0e-19; • double sum=1; int n=1; • while (e - sum> eps)
{ double facn=1; • for (int i=1; i<=n; i++) facn *=i; • sum+=1.0/facn; n++; } • return sum; • } • void main( ) • { printf ("e=%lf, es=%lf\t", e, expf ()); } • 上面while(e-sum>eps) 条件判断中的e=exp(1),如果写 • 为while (exp(1)- sum > eps)则每次判断时都需执行函数 • exp(1)求值计算。 • 对于与循环无关的函数调用应先计算出其值,以减少不 • 必要的重复计算。
七、梯形法求积分算例 • 将一个区间[a,b]分成n个子区间: • 其中 • 下面是积分的定义: • 积分 • 如果右边的极限存在,其极限值就是定积分的结果。 • 理论上区间分得越细越逼近理论的解,但计算机求和次数过 • 多导致的计算误差不容小视。
在计算机进行离散处理时应考虑两方面因素: • 一是区间适当细分; • 二是收敛性的精度限制。 • 区间的划分存在两种途径: • 一是静态地将区间分为n等分,n是预先定好的 • 整数; • 另一种是动态地确定区间划分数,将区间根据 • 某种细分机制,逐步细分,最终的区间划分数根据 • 收敛指标动态确定。
y x a b • 下面介绍的梯形算法属于区间一分为二的动态等分,包 • 含复杂求积算法的基本要素。梯形法的求解步骤为: • (1)首先分成一个区间时积分值为: • h=b-a ,T2=0 • 上面的关系作为迭代的初始值。
y a x1 b x • (2)分成两个相等的子区间时积分值为:
y xk xk1 x • (3)当分成相等的子区间时积分值为:
(4)进一步将上面个相等的每一个子区间一分为二,对于(4)进一步将上面个相等的每一个子区间一分为二,对于 • 每一新的子区间采用梯形计算公式,其结果用前一个回合的 • 区间边界值予以表示得到: • 这样就得到迭代关系式: y x
(5)迭代的收敛准则。迭代根据一个精度指标限定,满(5)迭代的收敛准则。迭代根据一个精度指标限定,满 • 足这个指标认为计算收敛,这个指标为: • 即相邻两次迭代求得的积分值之差小于一个非常小的 • eps,则认为此时求得的就是所求的结果。 • 如果不满足收敛指标则继续迭代,即将区间的分点加密 • 一倍。 • 迭代不一定收敛,因此通常内置一个最大迭代次数。如 • 果超过最个迭代次数依然未得到正常的收敛结果,应考虑采 • 取相关的手段。 • 如调整精度指标eps,过小的eps非但得不到合理的计 • 算结果反而因为计算的累计误差而发散。
[例]梯形求积算法 • #include <math.h> • # include<stdio.h> • extern double f(double); //函数原型说明 • double Trapzoidal (double a,double b, • const double eps=1.0e-8) • { double h=b - a; • double T1=0.5*h*(f(a)+f(b)); • double T2=0; • const int MaxIteration=0x7000;
for (int n=1;n<MaxIteration;n*=2) • { double sum=0; • double x=a+0.5*h; • for ( int k=0; k<n; k++,x+=h) sum+=f(x); • T2=0.5*(T1+h*sum); • if(fabs(T2-T1)<eps) return T2; • T1=T2; • h/=2; • } • printf ("Epsilon is too small\n"); • return MaxIteration; • }
Trapzoidal函数第三个形参eps声明为 • const double eps=1.0e-8,这是程序员对于函数使用者的 • 一个缺省建议,收敛指标eps取值于1.0e-8附近,函数容易 • 收敛。带缺省值的参数是C++新引进的语法现象。 • 上面的Trapzoidal函数通过两个被积函数进行具体算题 • 考核,它们分别是: • f(x)=1+x • 精度指标eps影响函数 的积分收 • 敛性,对于线性函数无影响。
[例]被积函数为 • double f(double x) • { return exp(x)/(2.5+x*x); } • void main (void) • { • printf("%f\n",Trapzoidal(1,2,1.0e-7)); • printf("%f\n",Trapzoidal(1,2,1.0e-13)); • } • 被积函数为输出结果为 • 0.947938 • Epsilon is too small • 28672.000000
[例] 被积函数为1+x • double f(double x) • {return (1+x); } • void main (void) • { printf("%f\n",Trapzoidal(1,2,1.0e-1)); • printf("%f\n",Trapzoidal(1,2,1.0e-23)); • printf("%f\n",Trapzoidal(1,2,1.0e-123)); • } • 被积函数为1+x输出结果为: • 2.500000 • 2.500000 • 2.500000