570 likes | 709 Views
Y. N. 语句 1. 条件. 语句 2. 语句 1. 语句 2. 三种基本结构的表示 ( 1 )顺序结构. 程序控制结构. ( 2 )选择结构. 程序控制结构. N. 条件. 语句. Y. Y. 语句. 条件. N. ( 3 )循环结构. a) 当型循环. b) 直到循环. 赋值语句 数据输入输出 字符数据的输入输出( putchar/getchar ) 格式输入与输出( printf/scanf ). 顺序程序设计. 赋值语句是由赋值表达式加上一个分号构成的。 注意 :
E N D
Y N 语句1 条件 语句2 语句1 语句2 三种基本结构的表示 (1)顺序结构 程序控制结构 (2)选择结构
程序控制结构 N 条件 语句 Y Y 语句 条件 N (3)循环结构 a) 当型循环 b) 直到循环
赋值语句 • 数据输入输出 • 字符数据的输入输出(putchar/getchar) • 格式输入与输出(printf/scanf) 顺序程序设计
赋值语句是由赋值表达式加上一个分号构成的。赋值语句是由赋值表达式加上一个分号构成的。 注意: (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 的条件中不能包含赋值语句。 赋值语句
if 语句用来判定给定的条件是否满足,根据判定的结果来决定执行何种操作。 一、 if 语句的三种形式 1. 第一种形式 格式: if(表达式) 语句 if 语句 假 表达式 真 语句 操作 表达式的值若为非0 (真),执行语句; 若为0(假),不执行条件后的语句,而直接执行下一个语句。 例如: if (x>y) printf("%d", x);
if 语句 • 注意: 在C语言中结果为这4个中的一个才表示0。0 整数0 0.0 实数0 ‘\0’ 字符0 NULL 符号常量0
真 假 表达式 语句1 语句2 if 语句 2.格式: if (表达式) 语句1 else 语句2 操作 当表达式的值为非0(真), 执行语句 1, 否则执行语句 2 例如: if (x>y) printf("%d",x); else printf("%d",y); 注意 不要遗漏else前的分号
假 表达式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;
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 后面的"语句"有多个操作语句,此时必须用" { } "将这些 语句括起来成为一条语句(即复合语句), 但是 { } 之外不需要加";“ • 思考:加了会不会错?
[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
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 的值, 怎么办?
内嵌 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 语句,可以用 { } 来限定其范围。
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;
ì 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中的大者 表示计算
例 有一函数 { -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
if 语句只有两个分支,当遇到多分支选择时,可以用嵌套 if 语句来处理,但是由于需要嵌套的 if 语句层次多,因此程序的可读性降低。C语言中的 switch 语句可直接处理多分支选择,它的一般形式是: 多分支选择语句------switch 语句 其中表达式:可以整型表达式、字符表达式、枚举数据 常量表达式 :应是常数,各常量表达式应互不相等 switch (表达式) { case 常量表达式1 : 语句 1 case 常量表达式2 : 语句 2 ┇ case 常量表达式n : 语句 n default : 语句 n+1 } 执行过程计算表达式的值,将其值按顺序与case的常量表达式的值比较, 若相等, 执行该case后的语句; 若无相等,执行default后的语句
例:根据考试成绩的等级打印出百分制分数段。例:根据考试成绩的等级打印出百分制分数段。 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 语句
多分支选择语句------switch 语句 • 注意 : • 当“表达式”的值与某个 case 后面的常量表达式的值相等时,就执行这个 case 后面的语句,如果 所有的 case 中的常量表达式的值都没有与“表达式”的值相匹配,就执行default 后面的语句。 • 每个 case 的常量表达式的值必须互不相同, 否则会出现相互矛盾的现象(对表达式的同一个值,有两种或多种执行方案)。 • 各个 case 和 default 的出现次序不影响执行的结果。 • 例如,在上面的例子中,可以先出现“case 'D': ……”,然后是 “ case 'A': ……”。 • 4. 执行完一个case 后面的语句后,流程控制转移到下一个case 继续执行。“case 常量表达式”只是起标号作用,并不是在该处进行条件判断。
多分支选择语句------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 后面的语句不需要用复合语句。当然加上花括弧也可以。
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
多分支选择语句------switch 语句 6. 多个 case 可以共用一组语句。 如: ┇ case 'A' : case 'B' : case 'C' : printf(">60"); break ; ┇ 当 switch 后面的表达式的值等于'A' 或'B'或'C'时,都执行 case 'C': 之后的 “printf(">60"); break; ” 语句。
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, 有两个共轭复根
#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) ; } }
例题 以下程序的输出结果是 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
循环结构 • 循环结构是一种重复执行的程序结构。在C语言中,实现循环结构的语句主要有3种: • 当型循环:while • 直到型循环:do…… while • 最灵活的for循环
循环结构 while语句 while语句的一般形式为: while(表达式) 语句; 其中表达式是循环条件,语句为循环体,若是多个语句则必须用{和}组成复合语句。
循环结构 do-while语句 do { 语句; }while (表达式); 其中:语句是循环体, 表达式是循环条件。 执行过程:先执行循环体语句一次, 再判别表达式的值,若为真(非0)则继续循环,否则终止循环。
循环结构 使用while和do-while语句应注意以下几点: 1.在if语句,while语句中, 表达式后面都不能加分号, 而在 do-while语句的表达式后面则必须加分号。 2.当循环体由多个语句组成时,也必须用{}括起来组成一个复合语句。 3.如果循环至少要执行一次,while和do-while语句可以相互替换。
循环结构 for循环 一、使用一般形式为: for(表达式1;表达式2;表达3) 语句; 其中:表达式1通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式。 表达式2通常是循环条件,一般为关系表达式或逻辑表达式。 表达式3通常可用来修改循环变量的值,一般是赋值语句。
循环结构 求解表达式1 0 表达式2 非0 语句 求解表达式3 for语句的执行过程: 1.首先计算表达式1的值。 2.再计算表达式2的值,若值为真(非0)则执行循环体一次, 否则跳出循环。 3.然后再计算表达式3的值,转回第2步重复执行。 在整个for循环过程中,表达式1只计算一次,表达式2和表达式3则可能计算多次。循环体可能多次执行,也可能一次都不执行。 for 语句的执行过程
例:统计从键盘输入一行字符的个数。 #include"stdio.h" void main() { int n=0; printf("input a string:\n"); for(;getchar()!='\n';n++); printf("%d",n); } 说明:本例中,省去了for语句的表达式1,表达式3也不是用来修改循环变量,而是用作输入字符的计数。这样, 就把本应在循环体中完成的计数放在表达式中完成了。因此循环体是空语句。应注意的是,空语句后的分号不可少,如缺少此分号,则把后面的printf 语句当成循环体来执行。反过来说,如循环体不为空语句时, 决不能在表达式的括号后加分号.
break语句和continue语句 break 语句只能用在switch 语句或循环语句中, 其作用是跳出switch语句或跳出本层循环,转去执行后面的程序。 continue 结束本次循环,即不再执行循环体中continue 语句之后的语句,转入下一次循环条件的判断与执行。应注意的是, 本语句只结束本层本次的循环,并不跳出循环。
例题分析 以下程序中,while 循环的循环次数是 int i=0; while(i<10) {if(i<1) continue ; if(i==5) break; i++; } A) 1 B) 10 C) 6 D)死循环,不能确定次数 √
循环的嵌套 for语句也可与while,do-while语句相互嵌套,构成多重循环。以下形式都合法的嵌套。 • do • { • … • do • { • …} while() • … • }while(); (1) while( ) {… while( ) {…} … } (3) for() { ……… for() { …… } …… } (4) while() { … for() {…} … }
循环的嵌套 (5) for( ) {… while( ) {…} … } (6) do{ … for( ) {…} … }while(); while() { … do { … }while(); … } (8) for() { ……… do { …… } while(); …… }
例:打印如下形式的九九乘法表. 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"); } }
常用算法一 例:计算 直到最后一项的绝对值小于1e-7时为止。 一、计数、求和、求阶乘等简单算法 此类问题都要使用循环,要注意根据问题确定循环变量的初值、终值或结束条件,更要注意用来表示计数、和、阶乘的变量的初值。 分析:这道题使用递推方法来做。让多项式的每一项与一个变量n对应,n的值依次为1,3,5,7,...,从多项式的前一项算后一项,只需将前一项乘一个因子: (-x2)/((n-1)*n)
常用算法一 用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); }
分析:(方法-)用辗转相除法 (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
方法二、递减法: (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); }
二、求两自然数的最大公约数和最小公倍数 复习指导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
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); }
三、判断素数 素数:指除了能被1和自身外,不能被其他整数整除的自然数。 算法思路:将m分别除以2,3,…,m-1,若都不能整除,则m为素数。事实上不必除那么多次,因为m=sqrt(m)*sqrt(m),所以,当m能被大于等于sqrt(m)的整数整除时,一定存在一个小于等于sqrt(m)的整数,使m能被它整除,因此只要判断m能否被2,3,…,sqrt(m)整除即可。 判断素数的算法流程图
三、判断素数 程序代码如下: 打印输出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); } }
三、判断素数 复习 : 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); }
四、验证哥德巴赫猜想 一个大于等于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流程图
#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);/*打印输出*/ } }
五、穷举法 穷举法(又称“枚举法”)的基本思想是:一一列举各种可能的情况,并判断哪一种可能是符合要求的解,这是一种“在没有其它办法的情况的方法”,是一种最“笨”的方法,然而对一些无法用解析法求解的问题往往能奏效,常常采用循环来处理穷举问题。 例:将一张面值为100元的人民币等值换成100张5元、1元和0.5元的零钞,要求每种零钞不少于1张,问有哪几种组合? 分析:如果用x,y,z来分别代表5元、1元和0.5元的零钞的张数,根据题意只能得到下面两个方程: x+y+z=100 5x+y+0.5z=100
五、穷举法 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); } 上面程序可以优化: