1 / 57

程序控制结构

Y. N. 语句 1. 条件. 语句 2. 语句 1. 语句 2. 三种基本结构的表示 ( 1 )顺序结构. 程序控制结构. ( 2 )选择结构. 程序控制结构. N. 条件. 语句. Y. Y. 语句. 条件. N. ( 3 )循环结构. a) 当型循环. b) 直到循环. 赋值语句 数据输入输出 字符数据的输入输出( putchar/getchar ) 格式输入与输出( printf/scanf ). 顺序程序设计. 赋值语句是由赋值表达式加上一个分号构成的。 注意 :

rufus
Download Presentation

程序控制结构

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Y N 语句1 条件 语句2 语句1 语句2 三种基本结构的表示 (1)顺序结构 程序控制结构 (2)选择结构

  2. 程序控制结构 N 条件 语句 Y Y 语句 条件 N (3)循环结构 a) 当型循环 b) 直到循环

  3. 赋值语句 • 数据输入输出 • 字符数据的输入输出(putchar/getchar) • 格式输入与输出(printf/scanf) 顺序程序设计

  4. 赋值语句是由赋值表达式加上一个分号构成的。赋值语句是由赋值表达式加上一个分号构成的。 注意: (1) C语言中的赋值号 “=” 作为赋值运算符,在其它大多数语言中赋值号不是运算符。 (2) C语言中有赋值表达式和赋值语句之分,赋值表达式可以被包括在其它的表达式之中。其它多数高级语言中没有“ 赋值表达式”这一概念。 例如: a=(b=5)是合法的赋值语句,其中 b=5 是一个赋值表达式 a=(b=5;)是非法的,因为 b=5; 已经是一个赋值语句了, 它不能被包括在另一个赋值语句之中。 if((a=b)>0) t=a ; 是合法的。 if((a=b;)>0) t=a ; 是非法的。在 if 的条件中不能包含赋值语句。 赋值语句

  5. if 语句用来判定给定的条件是否满足,根据判定的结果来决定执行何种操作。 一、 if 语句的三种形式 1. 第一种形式 格式: if(表达式)  语句 if 语句 假 表达式 真 语句 操作 表达式的值若为非0 (真), 执行语句; 若为0(假),不执行条件后的语句,而直接执行下一个语句。 例如: if (x>y) printf("%d", x);

  6. 假 表达式 语句1 语句2 if 语句 2.格式: if (表达式) 语句1 else 语句2 操作 当表达式的值为非0(真), 执行语句 1, 否则执行语句 2 例如: if (x>y) printf("%d",x); else printf("%d",y); 注意 不要遗漏else前的分号

  7. 表达式1 真 假 表达式2 真 假 表达式3 真 语句1 语句4 语句2 语句3 if 语句 3. if (表达式1) 语句 1 else if (表达式2) 语句 2 else if (表达式3) 语句 3 . . . else if (表达式n) 语句 n esle 语句 n+1 只执行一个(组)语句 例如: if (x>1) y=1; else if(x>0) y=0.5; else if(x>-1) y=-0.5; else y=-1;

  8. if 语句 • 注意: • if 语句中的"表达式"可以是任何的数值类型(整型、实型、字符型等)只要"表达式"的值 不等于0, 就执行后面的"语句"。例如:if(a==b && x==y) printf("a=b,x=y"); • if(3) printf("O.K"); • if ( ‘a’) printf(“%d”,‘a’); --> a 的ASCII值是 97 • 在带有 else 的 if 语句中,"语句1"、"语句2"仍然以";"结束,不可缺少。else 是 if 语句的一部分, else 部分不能单独使用,必须与 if 配对出现。 • 例如: if (x>0) • printf("x>0\n"); • else • printf("x<=0\n"); • 如果 if 或 else 后面的"语句"有多个操作语句,此时必须用" { } "将这些 语句括起来成为一条语句(即复合语句), 但是 { } 之外不需要加";“ • 思考:加了会不会错?

  9. [5.2] 输入三个数,按小--->大排序 • if 语句 例:输入3个数据,按由小到大打印输出 1. 分析 (1) 输入 a, b, c (2) 数据处理 . 比较 a, b的大小, 小者赋给 a. (把二个数中的小数存入a) . 比较 a, c的大小, 小者赋给 a, 因此 a最小. (把三个数中的最小数存入a) . 比较 b, c的大小, 小者赋给 b, 因此 c最大, b第二. (把第二小数存入b, 最大的数存入c) (3) 输出 a, b, c 注意 此时的a, b, c 已经不是输入时的 a, b, c

  10. if 语句 2. 程序 main() {float a,b,c,t; scanf("%f,%f,%f",&a,&b,&c); if (a>b) {t=a;a=b;b=t;} /* 交换a,b; 结果为:a<b */ if (a>c) {t=a,a=c,c=t;} /* 结果为:a<b且a<c --> a最小 */ if (b>c) {t=b;b=c;c=t;} /* 结果为:b<c */ printf("%5.2f,%5.2f,%5.2f\n",a,b,c); } 3. 运行 输入: 3,7,1 输出: 1.00, 3.00, 7.00 4. 思考 若不改变输入时的 a, b, c 的值, 怎么办?

  11. 内嵌 if 语句 内嵌 if 语句 if ( ... ) if ( ... ) 语句1 else 语句2 ( else 与 哪个 if 相配? ) if ( ... ) { if ( ... ) 语句1 } else 语句2 ( else 与 哪个 if 相配? ) 比较: • if 语句的嵌套 在一个 if 语句中又包含一个或多个 if 语句时称为 if 语句的嵌套。 一般形式: if ( ... ) if ( ... ) 语句 1 else 语句 2 else if ( ... ) 语句 3 else 语句 4 实际上 if 的第三种形式就是 if 嵌套的特例,else后的语句中又包含另一个 if 语句。 注意: else 总是与它上面的最接近的 if 相配对 对于容易混淆的内嵌 if 语句,可以用 { } 来限定其范围。

  12. if 语句的嵌套 1. if 与 else 的配对关系, 从最内层开始 就近原则else 总是与上面最近的 if 配对 如 if(表达式 1) if(表达式 2) 语句 1; else if(表达式 3) 语句 2; else 语句 4; if(表达式 1) { if(表达式 2) 语句 1;} else if(表达式 3) 语句 2; else 语句 4;

  13. ì a a > b n > 0 且 z = í £ b n 0 î • if 语句的嵌套 2. 使用复合语句可以改变 if 与 else 的配对关系 if (n>0) { if(a>b) z=a; } else z=b; 例 if (n>0) if (a>b) z=a; else z=b; 表示 n>0 时, 计算 z=a, b中的大者 表示计算

  14. 例 有一函数 { -1 (x<0) y= 0 (x=0) 1 (x>0) 开始 编一个程序输入 x , 输出 y。 输入 x 假 x<0 ? 假 真 x==0 ? 真 y=1 y=-1 y=0 输出 x 输出 y 程序流程图: 结束 写出算法: 输入x 若x<0 y=-1 若x=0 y=0 若x>0 y=1 输出 y 或: 输入x 若x<0 y=-1 否则 若x=0 y=0 若x>0 y=1 输出 y

  15. main() { int x,y; scanf("%d",&x); if (x<0) y=-1; else if (x==0) y=0; else y=1; printf("x=%d, y=%d\n",x,y); } main() { int x,y; scanf("%d",&x); y=-1; if (x!=0) if (x>0) y=1; else y=0; printf("x=%d, y=%d\n",x,y); } 2 1  √ main() { int x,y; scanf("%d",&x); y=0; if (x>=0) if (x>0) y=1; else y=-1; printf("x=%d, y=%d\n",x,y); } main() { int x,y; scanf("%d",&x); if (x>=0) if (x>0) y=1; else y=0; else y=-1; printf("x=%d, y=%d\n",x,y); } 3 4 √ 

  16. if 语句只有两个分支,当遇到多分支选择时,可以用嵌套 if 语句来处理,但是由于需要嵌套的 if 语句层次多,因此程序的可读性降低。C语言中的 switch 语句可直接处理多分支选择,它的一般形式是: 多分支选择语句------switch 语句 其中表达式:可以整型表达式、字符表达式、枚举数据 常量表达式 :应是常数,各常量表达式应互不相等 switch (表达式) { case 常量表达式1 : 语句 1 case 常量表达式2 : 语句 2 ┇ case 常量表达式n : 语句 n default : 语句 n+1 } 执行过程计算表达式的值,将其值按顺序与case的常量表达式的值比较, 若相等, 执行该case后的语句; 若无相等,执行default后的语句

  17. 例:根据考试成绩的等级打印出百分制分数段。例:根据考试成绩的等级打印出百分制分数段。 scanf(" %c ",&grade); switch(grade) { case 'A' : printf("85~100\n") ; case 'B' : printf("70~84\n") ; case 'C' : printf("60~69\n") ; case 'D' : printf("<60\n") ; default : printf("error\n") ; } 多分支选择语句------switch 语句

  18. 多分支选择语句------switch 语句 • 注意 : • 当“表达式”的值与某个 case 后面的常量表达式的值相等时,就执行这个 case 后面的语句,如果 所有的 case 中的常量表达式的值都没有与“表达式”的值相匹配,就执行default 后面的语句。 • 每个 case 的常量表达式的值必须互不相同, 否则会出现相互矛盾的现象(对表达式的同一个值,有两种或多种执行方案)。 • 各个 case 和 default 的出现次序不影响执行的结果。 • 例如,在上面的例子中,可以先出现“case 'D': ……”,然后是 “ case 'A': ……”。 • 4. 执行完一个case 后面的语句后,流程控制转移到下一个case 继续执行。“case 常量表达式”只是起标号作用,并不是在该处进行条件判断。

  19. 多分支选择语句------switch 语句 因此,应该在执行完一个 case 分支后, 使流程 跳出 switch 结构,即终止 switch 语句的执行。可以在 case 后面的 语句之后再用一个break 语句来达到此目的, 最后一个分支可以不加 break语句,因为后面switch 结构已经结束了。 switch (表达式) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; ┇ case 常量表达式n: 语句n; break; default : 语句n+1; } switch( 表达式 ) { case 常量表达式 1 : 语句 1 ; case 常量表达式 2 : 语句 2 ; ┇ case 常量表达式 n : 语句 n ; default : 语句 n+1 ; } 由于从对应的 case 开始,程序会自动执行后面的语句,直至结束或遇到 break语句后 跳出 switch 结构,因此每个 case 后面的语句不需要用复合语句。当然加上花括弧也可以。

  20. grade 'A' 其它 'B' 'D' 'C' 输出 "85~100" 输出 "70~84" 输出 "60~69" 输出 "<60" 输出 "error" • 多分支选择语句------switch 语句 例如:要求按考试成绩的等级输出百分制分数段。 main( ) { char grade ; scanf("%c", &grade) ; switch(grade) { case 'A' : printf("85~100\n") ; break ; case 'B' : printf("70~84\n") ; break ; case 'C' : printf("60~69\n") ; break ; case 'D' : printf("<60\n") ; break ; default : printf("error\n") ; } } • 如果grade值为'B',则输出"70~84"。 • 如没有break 语句,则将连续输出: • 70~84 • 60~69 • <60 • error

  21. 多分支选择语句------switch 语句 6. 多个 case 可以共用一组语句。 如: ┇ case 'A' : case 'B' : case 'C' : printf(">60"); break ; ┇ 当 switch 后面的表达式的值等于'A' 或'B'或'C'时,都执行 case 'C': 之后的 “printf(">60"); break; ” 语句。

  22. Y N a=0? 输出“非二次方程” Y N b2-4ac=0? 输出两个相等实根 Y N b2-4ac>0? 输出两个 不等实根 输出两个虚根 出口 • 例: 求 ax2+bx+c=0 方程的根。 有以下几种可能: • ⑴ a=0, 不是二次方程 • ⑵ b*b-4*a*c=0, 有两个相等实根 • ⑶ b*b-4*a*c>0, 有两个不等实根 • ⑷ b*b-4*a*c<0, 有两个共轭复根

  23. #include <math.h> main( ) { float a, b, c, disc, x1, x2, realpart, imagpart ; scanf("%f,%f,%f",&a,&b,&c) ; printf("The equation") ; if(fabs(a)<=1e-6) /* 1e-6 是一个很小量 0.000001 */ printf("is not a quadratic") ; else disc=b*b-4*a*c ; if(fabs(disc)<=1e-6) printf("has two equal roots :%8.4\n",-b/(2*a)) ; else if (disc>1e-6) { x1=(-b+sqrt(disc))/(2*a) ; x2=(-b-sqrt(disc))/(2*a) ; printf("has distinct real roots :%8.4f and %8.4f\n",x1,x2) ; } else { realpart=-b/(2*a) ; imagpart=sqrt(-disc)/(2*a) ; printf("has complex roots : \n") ; printf("%8.4f+%8.4f i\n",reatpart,imagpart) ; printf("%8.4f-%8.4f i\n",realpart,imagpart) ; } }

  24. 例题 以下程序的输出结果是 main() { int a=0, i; for(i=1;i<5;i++) { switch(i) { case 0: case 3:a+=2; case 1: case 2:a+=3; default : a+=5; } } printf("%d\n",a); } A) 31 B) 13 C) 10 D) 20

  25. 循环结构 • 循环结构是一种重复执行的程序结构。在C语言中,实现循环结构的语句主要有3种: • 当型循环:while • 直到型循环:do…… while • 最灵活的for循环

  26. 循环结构 while语句 while语句的一般形式为: while(表达式) 语句; 其中表达式是循环条件,语句为循环体,若是多个语句则必须用{和}组成复合语句。

  27. 循环结构 do-while语句 do { 语句; }while (表达式); 其中:语句是循环体, 表达式是循环条件。 执行过程:先执行循环体语句一次, 再判别表达式的值,若为真(非0)则继续循环,否则终止循环。

  28. 循环结构 使用while和do-while语句应注意以下几点: 1.在if语句,while语句中, 表达式后面都不能加分号, 而在 do-while语句的表达式后面则必须加分号。 2.当循环体由多个语句组成时,也必须用{}括起来组成一个复合语句。 3.如果循环至少要执行一次,while和do-while语句可以相互替换。

  29. 循环结构 for循环 一、使用一般形式为: for(表达式1;表达式2;表达3) 语句; 其中:表达式1通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式。 表达式2通常是循环条件,一般为关系表达式或逻辑表达式。 表达式3通常可用来修改循环变量的值,一般是赋值语句。

  30. 循环结构 求解表达式1 0 表达式2 非0 语句 求解表达式3 for语句的执行过程: 1.首先计算表达式1的值。 2.再计算表达式2的值,若值为真(非0)则执行循环体一次, 否则跳出循环。 3.然后再计算表达式3的值,转回第2步重复执行。 在整个for循环过程中,表达式1只计算一次,表达式2和表达式3则可能计算多次。循环体可能多次执行,也可能一次都不执行。 for 语句的执行过程

  31. 例:统计从键盘输入一行字符的个数。 #include"stdio.h" void main() { int n=0; printf("input a string:\n"); for(;getchar()!='\n';n++); printf("%d",n); } 说明:本例中,省去了for语句的表达式1,表达式3也不是用来修改循环变量,而是用作输入字符的计数。这样, 就把本应在循环体中完成的计数放在表达式中完成了。因此循环体是空语句。应注意的是,空语句后的分号不可少,如缺少此分号,则把后面的printf 语句当成循环体来执行。反过来说,如循环体不为空语句时, 决不能在表达式的括号后加分号.

  32. break语句和continue语句 break 语句只能用在switch 语句或循环语句中, 其作用是跳出switch语句或跳出本层循环,转去执行后面的程序。 continue 结束本次循环,即不再执行循环体中continue 语句之后的语句,转入下一次循环条件的判断与执行。应注意的是, 本语句只结束本层本次的循环,并不跳出循环。

  33. 例题分析 以下程序中,while 循环的循环次数是 int i=0; while(i<10) {if(i<1) continue ; if(i==5) break; i++; } A) 1 B) 10 C) 6 D)死循环,不能确定次数 √

  34. 循环的嵌套 for语句也可与while,do-while语句相互嵌套,构成多重循环。以下形式都合法的嵌套。 • do • { • … • do • { • …} while() • … • }while(); (1) while( ) {… while( ) {…} … } (3) for() { ……… for() { …… } …… } (4) while() { … for() {…} … }

  35. 循环的嵌套 (5) for( ) {… while( ) {…} … } (6) do{ … for( ) {…} … }while(); while() { … do { … }while(); … } (8) for() { ……… do { …… } while(); …… }

  36. 例:打印如下形式的九九乘法表. main() { int x,y; for(x=1;x<=9;x++) { for(y=1;y<=9;y++) printf("%d*%d=%2d ",x,y,x*y); printf("\n"); } }

  37. 几种循环语句的比较

  38. 常用算法一 例:计算 直到最后一项的绝对值小于1e-7时为止。 一、计数、求和、求阶乘等简单算法 此类问题都要使用循环,要注意根据问题确定循环变量的初值、终值或结束条件,更要注意用来表示计数、和、阶乘的变量的初值。 分析:这道题使用递推方法来做。让多项式的每一项与一个变量n对应,n的值依次为1,3,5,7,...,从多项式的前一项算后一项,只需将前一项乘一个因子: (-x2)/((n-1)*n)

  39. 常用算法一 用s表示多项式的值,用t表示每一项的值,程序如下: #include <math.h> void main() { double s,t,x; int n; printf("please input x:"); scanf("%lf",&x); t=x; n=1; s=x; do { n=n+2; t=-t*x*x/(n-1)/n; /* 计算通项 */ s=s+t; /* 累加求和 */ }while(fabs(t)>=1e-7); /* 当累加项的值大于1e-7继续循环 */ printf("sin(%f)=%lf",x,s); }

  40. 分析:(方法-)用辗转相除法 (1)对于已知两数m,n,使得m>n; (2) m除以n得余数r; (3)若r=0,则n为最大公约数结束;否则执行(4); (4)m n,n r,再重复执行(2) 二、求两自然数的最大公约数和最小公倍数 void main() { int n,m,nm,r,t; printf("Enter m,n=?"); scanf("%d%d",&m,&n); nm=n*m; if (m<n) {t=m; m=n; n=t;} r=m%n; while (r!= 0) { m=n; n=r; r= m%n; } printf("%d\n", n); printf("%d\n", nm/n); } 例如: 设输入m=28,n=20 循环mn r 赋好初值时:2820 8 第一次结束:20 84 第二次结束:84 0

  41. 方法二、递减法: (1)将2自然数m,n中的较少一个数 赋值给 div, (2)如果m mod div与n mod div 都等于0 则div就是最大公约数,否则转为(3)步。 (3)让div=div-1,重新执行第(2)步。 二、求两自然数的最大公约数和最小公倍数 void main() { int n,m,nm,div; printf("Enter m,n=?"); scanf("%d%d",&m,&n); nm=n*m; div=n; if (m < n) div=m; while (m%div!= 0 || n%div!=0) div=div-1; printf("%d", div); printf("%d\n", nm/div); }

  42. 二、求两自然数的最大公约数和最小公倍数 复习指导P80 3.输入m、n(要求输入数均大于0),输出它们的最大公约数 #include <stdio.h> void main() { int m,n,k; while(scanf("%d%d",&m,&n), _______1____ ); for( ________2_____ ; n%k!=0||m%k!=0; k--); printf("%d\n",k); } n<0 || m<0 k=m<n?m:n

  43. n<0 || m<0 || m<n k=k*n; 二、求两自然数的最大公约数和最小公倍数 复习指导:p84 13.输入m、n(要求输入数均大于0),输出它们的最小公倍数。 #include <stdio.h> void main() { int m,n,k; /******** 1 *********/ while(scanf("%d%d",&m,&n), m<0 && n<0 ); for(k=m; k%n!=0;) /******** 2 ********/ k=k+n; printf("%d\n",k); }

  44. 三、判断素数 素数:指除了能被1和自身外,不能被其他整数整除的自然数。 算法思路:将m分别除以2,3,…,m-1,若都不能整除,则m为素数。事实上不必除那么多次,因为m=sqrt(m)*sqrt(m),所以,当m能被大于等于sqrt(m)的整数整除时,一定存在一个小于等于sqrt(m)的整数,使m能被它整除,因此只要判断m能否被2,3,…,sqrt(m)整除即可。 判断素数的算法流程图

  45. 三、判断素数 程序代码如下: 打印输出100---200之间的素数 #include "math.h" void main() { int m,i,k; printf("Enter m=\n"); scanf("%d",&m); k=sqrt(m); for(i=2;i<k;i++) if(m%i==0) break; if(i>=k) printf("Yes\n"); else printf("No\n"); } #include "math.h" void main() { int m,i,k; for(m=101;m<=199;m++) { k=sqrt(m); for(i=2;i<k;i++) if(m%i==0) break; if(i>=k) printf(“%d\n“,m); } }

  46. 三、判断素数 复习 P67: 2003年等级考试编程题 输入两个正整数m和n(m<n),求从m到n之间(包括m和n)所有素数的和,要求定义并调用函数isprime(x)来判断x是否为素数(素数年是除1以外只能被自身整除的自然数)。 #include "math.h" intisprime(int m) { int m,i,k; k=sqrt(m); for(i=2;i<k;i++) if(m%i==0) return 0; return 1; } void main() { int m,n,i,k=0; do { scanf(“%d%d”,&m,&n); }while (m<0 || n<0 || m>n); for(i=m;i<=n;i++) if(isprime(i)==1) k+=i; printf(“%d\n“,k); }

  47. 四、验证哥德巴赫猜想 一个大于等于6的偶数可以表示为两个素数之和。 如:6=3+3 8=3+5 10= 3+7 设n为大于等于6的任一偶数,将其分解为n1和n2两个数,使用n1+n2=n,分别判断n1和n2是否为素数,若都是,则为一组解。若n1不是素数,就不必再检查n2是否素数。先从n1=3开始,直到n1=n/2为止。 图3-21 验证哥德巴赫猜想的N-S流程图

  48. #include "math.h" void main() { int n,n1,n2,j,k; printf("Enter a number n=?\n"); scanf("%d" ,&n); for(n1=3;n1<=n/2;n1++) { k=sqrt(n1); for (j=2;j<=k;j++) /*判断n1是否是素数*/ if(n1%j==0) break; if(j<k) continue; /*n1不是素数*/ n2=n-n1; k=sqrt(n2); for (j=2;j<=k;j++) /*判断n2是否是素数*/ if(n2%j==0) break; if(j>k) /*n2是素数*/ printf(“%d=%d+%d\n”,n,n1,n2);/*打印输出*/ } }

  49. 五、穷举法 穷举法(又称“枚举法”)的基本思想是:一一列举各种可能的情况,并判断哪一种可能是符合要求的解,这是一种“在没有其它办法的情况的方法”,是一种最“笨”的方法,然而对一些无法用解析法求解的问题往往能奏效,常常采用循环来处理穷举问题。 例:将一张面值为100元的人民币等值换成100张5元、1元和0.5元的零钞,要求每种零钞不少于1张,问有哪几种组合? 分析:如果用x,y,z来分别代表5元、1元和0.5元的零钞的张数,根据题意只能得到下面两个方程: x+y+z=100 5x+y+0.5z=100

  50. 五、穷举法 void main() {int x, y, z,n; printf( " 5yun 1yun 0.5yun\n"); n=0; for(x=1; x<=100;x++) for(y=1;y<=100;y++) for(z=1;z<=100;z++) if(x+y+z==100 && 5*x+y+0.5*z==100) { printf(" %d %d %d\n",x,y,z); n++; } printf(" Total %d",n); } void main() {int x, y, z,n; printf( " 5yun 1yun 0.5yun\n"); n=0; for(x=1; x<=100;x++) for(y=1;y<=100-x;y++) {z=100-x-y; if(5*x+y+0.5*z==100) { printf(" %d %d %d\n",x,y,z); n++; } } printf(" Total %d",n); } 上面程序可以优化:

More Related