页数:66页文件大小:1.19 MB来源: C语言程序设计ppt课件
本课件系统讲解C程序的流程设计,先说明C语句分类与算法、结构化程序设计思想,再用流程图与N-S图展示顺序、选择、循环三种基本结构,随后依次展开if与switch选择结构、while、do-while与for三种循环、break、continue与goto等辅助控制语句,最后以枚举法解题和二分法、梯形法求根等综合示例收尾。
Chapter 4 C程序流程设计:C语句 → C程序的三种基本结构 → 选择型程序设计 → 循环型程序设计 → 辅助控制语句。
C语句:源程序的基本组成部分,编译后产生机器指令,语句分隔符为分号「;」。
流程控制语句共9种:if( )~else~、switch、for( )~、while( )~、do~while( )~、continue、break、goto、return。
算法 Algorithm:解决某一特定问题采取的具体步骤的描述。
Program = Data structure + Algorithm:数据结构是对数据的描述(数据类型和数据组织形式),算法是对操作的描述。
结构化程序设计:
方法:自顶向下、逐步细化、模块化设计、结构化编码。
优点:结构清晰,易读,提高程序设计质量和效率。
C程序由 file1.c…filen.c 多个文件构成,每个文件含 Preprocessor、global variables、main、func1…funcn,函数由 header 与 body 构成,body 内含 local variables 与 statements。
顺序结构编程:从键盘输入五个学生成绩,输出总成绩和平均成绩。
程序结构:文件包含预处理命令 → 符号常量定义 → 主函数(变量定义、输入数据、数据处理、输出数据)。
#include <stdio.h> #define NUM 5 float s1, s2, s3, s4, s5, sum, average; printf("Please input 5 scores:"); scanf("%f,%f,%f,%f,%f", &s1, &s2, &s3, &s4, &s5); sum = s1 + s2 + s3 + s4 + s5; average = sum / NUM; printf("sum=%.1f\naverage=%.1f\n", sum, average);顺序结构:流程图与 N-S 图均表现为 A、B 两个处理框自上而下依次执行,是最简单的程序结构。
顺序结构示例(续):
float s1, s2, s3, s4, s5; int count = 0; printf("Please input 5 scores:"); scanf("%f,%f,%f,%f,%f", &s1, &s2, &s3, &s4, &s5); printf("count=%d\n", count);思考问题:如何统计90分以上人数?——对每个成绩,如果分数>=90,则 count++。如何统计各分数段人数?——如果分数>=90 则 C90++;否则,如果分数>=80 ……
选择结构:
流程图中判断框 P 后有 T(真)与 F(假)两条分支。
数据处理示例:
#include <stdio.h> #define NUM 5 float s1, s2, s3, s4, s5, sum, average; printf("Please input 5 scores:"); scanf("%f,%f,%f,%f,%f", &s1, &s2, &s3, &s4, &s5); sum = s1 + s2 + s3 + s4 + s5; average = sum / NUM;若有200个学生,只需把宏定义改为 #define NUM 200,相应语句执行200遍。
循环结构:
流程图中当型循环条件为真进入循环体,直到型循环条件为真时结束循环。
if 语句(Selection)
if (expression) statement,表达式非0执行语句,为0跳过if (expression) statement1 else statement2说明:if 后面表达式类型任意;语句可以是单一语句或复合语句;if(x) 等价于 if(x!=0)。
例:if (x>y) printf("%d",x);;if (x) y/=x; else y=0;
if 语句形式三:if (expr1) statement1 else if (expr2) statement2 … [else statementn]
if (salary > 1000) index = 0.4; else if (salary > 800) index = 0.3; else if (salary > 600) index = 0.2; else if (salary > 400) index = 0.1; else index = 0; tax = salary * index;if 语句说明:
#include <stdio.h> main() { int x, y; scanf("%d %d", &x, &y); if (x > y) x = y; y = x; else x++; y++; printf("%d,%d\n", x, y); }上例因 if 与 else 之间包含两条语句而未加花括号,导致 Compile Error! 应写为 { x=y; y=x; }。
其他示例:if(a==b&&x==y) printf("a=b,x=y"); if(3) printf("OK"); if('a') printf("%d",'a');
if 语句与条件运算符:if ~ else 可以完成与条件运算符 ( ? : ) 相同的任务,并且可以相互转换。
if (y < 0) x = -y; else x = y; (y < 0) ? (x = -y) : (x = y); x = (y < 0) ? -y : y;三种写法等价,均实现求 y 的绝对值。
例:求 a 和 b 中较大数
#include <stdio.h> main() { int a, b, max; printf("Enter a and b:\n"); scanf("%d%d", &a, &b); max = a; if (max < b) max = b; printf("max=%d\n", max); }Run:Enter integer a and b: 23 12↵ → max=23
例:三个整数降序排序
int a, b, c, t; scanf("%d %d %d", &a, &b, &c); if (a < b) { t = a; a = b; b = t; } if (a < c) { t = a; a = c; c = t; } if (b < c) { t = b; b = c; c = t; } 输入 639 输出 963。交换过程如同两瓶液体互换,需借助第三个空瓶 t。
例:求 a 和 b 中较大数(双分支写法)
int a, b, max; printf("Enter a and b:\n"); scanf("%d%d", &a, &b); if (a > b) max = a; else max = b; printf("max=%d\n", max);Run:Enter integer a and b: 23 12↵ → max=23
例:判断输入字符种类
char c; printf("Enter a character:"); c = getchar(); if (c >= 'A' && c <= 'Z') printf("a capital letter\n"); else if (c >= 'a' && c <= 'z') printf("a lower letter\n"); else if (c >= '0' && c <= '9') printf("a digit\n"); else if (c < 0x20) printf("a control character\n"); else printf("other character\n");嵌套 if:if 结构相当于单一语句,可内嵌于 if 或 else 分支。
if (expr1) if (expr2) statement1 else statement2 if (expr1) statement1 else if (expr2) statement2 else statement3后一种等价于 if (expr1) statement1 else if (expr2) statement2 else statement3。
例:输入两个数并判断大小关系
int x, y; printf("Enter integer x,y:"); scanf("%d %d", &x, &y); if (x != y) if (x > y) printf("X>Y\n"); else printf("X<Y\n"); else printf("X==Y\n");if ~ else 配对原则:缺省 { } 时,else 总是和它上面离它最近的未配对的 if 配对(最近配对)。
if (a == b) if (b == c) printf("a==b==c"); else printf("a!=b"); if (a == b) { if (b == c) printf("a==b==c"); } else printf("a!=b");实现 if ~ else 正确配对的方法就是加 { }。
例:判别学生成绩等级(<60 为 E,60~69 为 D,70~79 为 C,80~89 为 B,90~100 为 A)
int score; char grade; printf("Please input a score:"); scanf("%d", &score); if (score < 60) grade = 'E'; else if (score < 70) grade = 'D'; else if (score < 80) grade = 'C'; else if (score < 90) grade = 'B'; else grade = 'A'; printf("Score is %d: Level %c\n", score, grade);switch 语句(多分支选择)
switch (expression) { case E1: statements 1; break; case E2: statements 2; break; …… case En: statements n; break; [default: statements; break;] }执行流程:计算 expression 的值,与 case 后的常量表达式 E1…En 依次比较,匹配则执行对应语句组,都不匹配则执行 default。
switch 说明:
例:score 为5时输出 Very good! / Good! / Pass! / Fail! / data error! 之一。
例:根据输入字母输出字符串
int c; printf("Enter m or n or h or other:"); c = getchar(); switch (c) { case 'm': printf("\nGood morning!\n"); break; case 'n': printf("\nGood night!\n"); break; case 'h': printf("\nHello!\n"); break; default: printf("\n????????\n"); break; }switch 嵌套示例
int x = 1, y = 0, a = 0, b = 0; switch (x) { case 1: switch (y) { case 0: a++; break; case 1: b++; break; } case 2: a++; b++; break; case 3: a++; b++; } printf("\na=%d,b=%d", a, b);Output:a=2, b=1
内层 switch 的 break 只跳出内层;外层 case 1 没有 break,故继续贯穿执行 case 2。若要在 case 1 后结束,须补写 break;
例:用 switch 判别学生成绩等级
算法:score/10 的值为 0~5 判 E,6 判 D,7 判 C,8 判 B,9 与 10 判 A。
int score, s; char grade; printf("Please input scores:"); scanf("%d", &score); s = score / 10; switch (s) { case 10: case 9: grade = 'A'; break; case 8: grade = 'B'; break; case 7: grade = 'C'; break; case 6: grade = 'D'; break; default: grade = 'E'; }while 循环(Iteration):while(expr) statement;
退出 while 循环的情况:条件表达式不成立(为零);循环体内遇 break、return、goto。
无限循环:while(1) statement;
例:计算 1+2+3+……+100
分析:1、定义 sum,初始值0;2、定义 i,初始值1;3、当 i<=100;4、重复:sum=sum+i,i=i+1;5、若 i>100,输出 sum。
流程图:start → 0→sum,1→i → 判断 i<=100 →(Y)sum=sum+i,i=i+1 → 回到判断 →(N)Output sum → end
#include <stdio.h> main() { int i, sum; i = 1; sum = 0; while (i <= 100) { sum = sum + i; i++; } printf("%d", sum); }循环四要素:循环变量初值 initial、循环条件 condition、循环体 body、循环变量增值 increment。
练习:编程显示 1~10 的平方
#include <stdio.h> main() { int i = 1; while (i <= 10) { printf("%d*%d=%d\n", i, i, i * i); i++; } }Output:1*1=1 / 2*2=4 / 3*3=9 / 4*4=16 / 5*5=25 / 6*6=36 / 7*7=49 / 8*8=64 / 9*9=81 / 10*10=100
例:分析下面程序实现功能
#include <stdio.h> main() { int number, sum = 0; scanf("%d", &number); while (number) { sum += number; scanf("%d", &number); } printf("sum= %d\n", sum); }功能:计算键盘输入数据和,直到输入0为止。
#include <stdio.h> main() { int n = 0; while (n < 3) printf("n is %d\n", n); n++; printf("That's all this program does.\n"); }因 while 后未加花括号,循环体只有 printf 一句,n++ 在循环体外,n 始终为0,程序将不停打印「n is 0」,形成死循环。正确写法应加 { } 把两条语句都括入。
do ~ while 循环:
do statement; while (expr);与 while 的区别:do ~ while 是 until expr is false 才结束,循环体至少执行一次;while 先判断,可能一次也不执行。
#include <stdio.h> main() { int i, sum = 0; i = 1; do { sum += i; i++; } while (i <= 100); printf("%d", sum); }循环要素:i=1 为 initial,i<=100 为 condition,sum+=i 为 body,i++ 为 increment。
while 与 do ~ while 的比较:
int i, sum = 0; scanf("%d", &i); while (i <= 10) { sum += i; i++; } printf("%d", sum); int i, sum = 0; scanf("%d", &i); do { sum += i; i++; } while (i <= 10); printf("%d", sum);若输入20:while 版本条件不成立,循环体一次也不执行,输出0;do ~ while 版本仍先执行一次,输出20。
例:猜数游戏 Guess.c
流程:count=0 → 输入 data → 判断 data>GOAL?Y 输出 Too big;N 再判断 data<GOAL?Y 输出 Too small;N 输出 You get it → count++ → 判断 data!=GOAL?Y 回到输入,N 输出 count。
#include <stdio.h> #define GOAL 39 main() { int data, count = 0; do { printf("Please input a number:"); scanf("%d", &data); if (data > GOAL) printf("Too big! Try again.\n"); else if (data < GOAL) printf("Too small! Try again.\n"); else printf("You get it!\n"); count++; } while (data != GOAL); printf("You guess %d times!\n", count); }例:输入一个正整数,以相反的顺序输出该数(输入12345,输出54321)
基本思路:从个位开始,按位输出整数的每一位。
#include <stdio.h> main() { int number; printf("Input the number:"); scanf("%d", &number); do { printf("%d", number % 10); number /= 10; } while (number != 0); }for 循环:for([expr1]; [expr2]; [expr3]) statement;
即 for(循环变量初值; 循环条件; 循环变量增值) 循环体语句;
#include <stdio.h> main() { int i, sum = 0; for (i = 1; i <= 100; i++) sum += i; printf("%d", sum); }执行流程:先 expr1 → 判断 expr2 → 为真执行循环体 → expr3 → 再判断 expr2。
for 语句说明:
for(;;)expr1; while(expr2){ statement; expr3; }输出 abcdefghij 的四种写法:
for (i = 0; i < 10; i++) putchar('a' + i); for (i = 0; i < 10; ) putchar('a' + (i++)); for (i = 0; i < 10; putchar('a' + i), i++) ; for ( ; ; ) putchar('a' + i);Output:abcdefghij
练习:输出交错字符串 azbycxdwevfugthsirjqkplomn
#include <stdio.h> main() { char i, j; for (i = 'a', j = 'z'; i < j; i++, j--) printf("%c %c", i, j); printf("\n"); }循环变量初值 i='a', j='z',增值 i++, j--,条件 i<j。
循环嵌套:
选用原则:若循环次数在执行循环体之前已确定,一般用 for;若循环次数根据循环体执行情况确定,一般用 while 或 do~while;当循环体至少执行一次,用 do~while;若循环体有可能一次也不执行,用 while。
例:输出下三角形乘法九九表(1<=i<=9,1<=j<=i)
1 2 3 4 5 6 7 8 9 ----------------------------------- 1 1 2 2 4 3 3 6 9 4 4 8 12 16 5 5 10 15 20 25 6 6 12 18 24 30 36 7 7 14 21 28 35 42 49 8 8 16 24 32 40 48 56 64 9 9 18 27 36 45 54 63 72 81外层循环变量 i 从1到9,内层循环变量 j 从1到 i。
#include <stdio.h> main() { int i, j; i = 1; while (i <= 9) printf("%4d", i++); printf("\n--------------------------------\n"); i = 1; while (i <= 9) { j = 1; while (j <= i) { printf("%4d", i * j); j++; } printf("\n"); i++; } }#include <stdio.h> main() { int i, j; for (i = 1; i < 10; i++) printf("%4d", i); printf("\n-----------------------------------\n"); for (i = 1; i < 10; i++) for (j = 1; j <= i; j++) printf((j == i) ? "%4d\n" : "%4d", i * j); }用条件表达式 (j==i) 决定输出后是否换行。
break 语句:功能为跳出循环体或开关体(switch 语句)。
说明:break 只能跳出最近一层的结构。在 while、do~while、for 循环中遇到 break 即终止本层循环,跳到循环之后的语句继续执行。
switch 中的 break:每个 case 分支的语句组后都应写 break,执行完即跳出 switch 结构。
switch (expr) { case const1: statements1; break; case const2: statements2; break; …… case constn: statementsn; break; default: statements; break; }若省略 break,程序将继续执行下一个 case 的语句,形成贯穿。
例:输出半径 1~10 的圆面积,面积大于100时停止
#define PI 3.14159 #include <stdio.h> main() { int r; float area; for (r = 1; r <= 10; r++) { area = PI * r * r; if (area > 100) break; printf("r=%d,area=%.2f\n", r, area); } }例:小写字母转换成大写字母,输入非小写字母结束
#include <stdio.h> main() { char c; while (1) { c = getchar(); if (c >= 'a' && c <= 'z') putchar(c - 'a' + 'A'); else break; } }continue 语句:功能为结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断。
说明:continue 仅用于循环语句中。在 while 与 do~while 中,continue 后直接跳转到条件判断;在 for 中,continue 后先执行 expr3 再判断 expr2。
例:求输入的十个整数中正数的个数及其平均值
#include <stdio.h> main() { int i, num = 0, a; float sum = 0; for (i = 0; i < 10; i++) { scanf("%d", &a); if (a <= 0) continue; num++; sum += a; } printf("%d plus integer's sum :%6.0f\n", num, sum); printf("Mean value:%6.2f\n", sum / num); }本例也可用不含 continue 的 if 语句实现:if(a>0){ num++; sum+=a; }
goto 语句:
goto label; …………. label:statement;说明:不能用整数作标号;标号只能出现在 goto 所在函数内且唯一;只能加在可执行语句前面;应限制使用 goto 语句。
例:求数值积分(梯形法)
#include <stdio.h> #include <math.h> void main() { double a, b, s, h; int n, i; printf("Input integral area a, b:"); scanf("%lf%lf", &a, &b); printf("Input n:"); scanf("%d", &n); h = (b - a) / n; s = 0.5 * h * (sqrt(4 - a * a) + sqrt(4 - b * b)); for (i = 1; i <= n - 1; i++) s = s + h * sqrt(4 - (a + i * h) * (a + i * h)); printf("The integral is %lf\n", s); }把区间 [a,b] n 等分,每个小区间步长 h=(b-a)/n,用多个梯形面积之和近似积分值。
二分法求方程根:基本思想是确定区间 [a,b],使 f(a) 与 f(b) 异号,则 f(x) 在 [a,b] 上至少有一个根。
二分法求方程根算法:
#include <stdio.h> #include <math.h> void main() { double x, fx, a, fa, b, fb; do { printf("Please input the lower and upper boundaries:"); scanf("%lf%lf", &a, &b); fa = 2*a*a*a - 4*a*a + 3*a - 6; fb = 2*b*b*b - 4*b*b + 3*b - 6; } while (fa * fb > 0); while (1) { x = (a + b) / 2; fx = 2*x*x*x - 4*x*x + 3*x - 6; if (fabs(fx) <= 1e-5) { printf("The solution is %.2f\n", x); break; } if (fa * fx < 0) { b = x; fb = fx; } else { a = x; fa = fx; } } }问题:谁做的好事?
有四位同学中的一位做了好事,不留名。校长问这四位是谁做的好事。
已知三个人说的是真话,一个人说的是假话,要根据这些信息找出做了好事的人。
枚举法思路:先假定是 A 同学,让 thisman='A',代入四句话测试:
四个关系表达式值的和为1,显然不是 'A' 做的好事。
再试 B 同学,让 thisman='B',代入四句话:
四个关系表达式值的和为2,也不是 'B' 所为。
再试 C 同学,让 thisman='C',代入四句话:
四个关系表达式值之和为3,显然就是 'C' 做了好事。
这种一个人一个人去试的方法称为枚举法,从编程角度看,实现枚举最好用循环结构。
「谁做的好事」程序框图(N-S 图):
sum = (thisman != 'A') + (thisman == 'C') + (thisman == 'D') + (thisman != 'D');让 thisman 分别为 'A'、'B'、'C'、'D',循环4趟;若 sum==3 则输出该被试者并置有解标志,否则换下一人;循环结束若仍无解则输出无解信息。
#include <stdio.h> main() { char thisman; int sum, found = 0; for (thisman = 'A'; thisman <= 'D'; thisman++) { sum = (thisman != 'A') + (thisman == 'C') + (thisman == 'D') + (thisman != 'D'); if (sum == 3) { printf("%c did it!\n", thisman); found = 1; break; } } if (found == 0) printf("Not found!\n"); }本章小结
交换两个变量的值:如同把 water 与 wine 两杯液体互换,需要借助第三个空杯 t。
t = a; a = b; b = t;a、b 为待交换的两个容器,t 为临时中转变量,三步完成互换。
下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}