1 / 65

C 语言程序设计

C 语言程序设计. 第三讲 算法基础与程序的基本结构 绍兴文理学院 2014 年 2 月. 本章主要内容. 课外阅读材料 程式设计与流程图 ( 请上网下载 ). 程序设计方法简述 算法与流程图 算法的两种表示法 两种流程图 三种基本结构 选择结构程序设计 if …else 语句 switch 语句 循环结构程序设计 四种循环语句 常用算法 枚举法(穷举法) 归纳法(递推法). 一、程序设计方法简述 1 、计算机处理问题的过程. 【 例一 】 让某学生解方程 ax 2 +bx+c=0 求解过程:.

Télécharger la présentation

C 语言程序设计

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. C语言程序设计 第三讲 算法基础与程序的基本结构 绍兴文理学院 2014年2月

  2. 本章主要内容 课外阅读材料 程式设计与流程图 (请上网下载) • 程序设计方法简述 • 算法与流程图 算法的两种表示法 两种流程图 三种基本结构 • 选择结构程序设计 if …else 语句 switch语句 • 循环结构程序设计 四种循环语句 • 常用算法 枚举法(穷举法) 归纳法(递推法)

  3. 一、程序设计方法简述1、计算机处理问题的过程一、程序设计方法简述1、计算机处理问题的过程 • 【例一】让某学生解方程ax2+bx+c=0 求解过程: ①分析问题 这是一个一元二次方程(代数问题,须中学代数知识) ②确定处理方案 用求根公式 ③确定解题步骤 确定a、b、c的值 求出b2 -4ac的值 如果 b2 -4ac>0(双实根) X1=…… X2=…… 如果 b2 -4ac=0(单实根) X1=X2=…… 如果 b2 -4ac<0(双复根) X1=…… X2=…… ④根据上述步骤计算 ⑤写出答案,整理、分析结果

  4. 一、程序设计方法简述1、计算机处理问题的过程一、程序设计方法简述1、计算机处理问题的过程 程序测试与修改 2、编程要诀——自顶向下,逐步求精“先大纲,后文章” 如同写文章:分几部分——每部分几个问题——每个问题几点…… 优点:不易顾此失彼;易于检查;减少后期修改工作量 对于面向过程的程序设计语言: 程序=数据结构+算法(做什么,如何做) 对比:文章=材料+构思

  5. 一、程序设计方法简述3、程序测试 • 目的 发现程序中的错误(Bug) • 程序错误 ◆语法错误(编译系统检查) ◆逻辑错误(编程人员检查) • 方法与技术 测试是以程序通过了编译,没有语法和连接错误为前提。在此基础上运行一组数据,来检测程序的逻辑错误。这一组测试数据应是以“任何程序都是有错误的”为前提精心设计出来的。它不仅应含有被测程序各种情况下的代表性输入数据,还应包括程序执行这些数据后预期的结果。 • 其他 著名计算机软件科学家E.W.Dijkstra曾断言:“程序测试只能证明错误的存在,而不能证明错误的不存在”。可以证明,除了很小的程序外,无论使用任何方法,要想做到彻底的测试,即发现程序中的所有错误,是不现实的。 常见所谓“β版”商业软件,就是软件正式发行前的测试版本。

  6. 二、算法与流程图1、算法(algorithm)P14 • 算法:解题思路(解题步骤等) 算法有表示方式: • 伪码(pseudocode) 用人类语言的形式(通常是英语)表示算法。 伪码不在计算机上执行,仅供程序员缩写程序之前构思时用(*注意伪码程序只包含执行语句,没有声明语句,后者仅仅是给编译器提供的信息) • 流程图(flow chart) 用图示方式表示算法 编程依据(便于检查) 编程时用 使用流程图的优点:不易出错/便于编程/便于别人阅读和检查程序。 • 通常编程的技术路线是: 用伪码和自顶向下、逐步求精的方法来制定算法,然后再编写相应的C语言程序。 复杂程序处理部分宜用流程图表示程序处理的过程。

  7. 二、算法与流程图1、算法(algorithm)示例:根据学生成绩输出评定结果。二、算法与流程图1、算法(algorithm)示例:根据学生成绩输出评定结果。 伪码语句示例之一 if student’s grades greater than or equal to 60 display ” Passed” else display ”Failed” C语言源程序段示例 if (grade>=60) printf(“Passed!”); else printf(“Failed”); 伪码语句示例之二 如果学生成绩大于或等于60 显示”及格” 否则 显示 ”不及格”

  8. 二、算法与流程图2、传统流程图 P20 • 特点: 直观形象; 使用流线。 • 缺点: 占面积大,使用流线任意转移,易出现“乱麻”现象,造成编程与阅读程序困难。

  9. 二、算法与流程图3、N-S结构化流程图 P27 77年美学者I.Nassi和B.Scheiderman提出。 • 特点 ①取消流线 ②不允许流程任意转移,只能从上而下顺序执行 ③规定三种基本结构的流程图单元,由这些基本结构象搭积木似的组成各种算法(结构化设计)。 • 优点 算法清晰,流程不会无规律乱转移。

  10. 二、算法与流程图4、三种基本结构P24- • 通常情况下,程序中的语句是以所编写的顺序一句接一句地执行,这种执行方法称为“顺序执行”。许多C语句能够让程序员指定不按编写顺序执行下一条执行语句,这种执行方法称为“控制转移”。 • Bohm和Jacopini的研究证实,所有的程序都能够只用三种控制结构编写,即 ◆顺序结构 ◆选择结构(selection structure) ◆循环结构(repetition structure) 顺序结构是C语言的基本结构,除非指示转移,否则计算机自动以语句编写的顺序一句一句地执行C语句。 • 任何C语言程序都是由七种控制结构(顺序结构、三种选择结构和三种循环结构)构成的。

  11. 二、算法与流程图4、三种基本结构P24- • 顺序结构 A块、B块顺序执行(每块代表一个或一组操作)

  12. 二、算法与流程图4、三种基本结构P24- • 选择结构 条件p成立时执行a块(否则执行b块) • if 选择结构 条件为真时执行某个指定的操作,条件为假时跳过该操作(单路选择) • if…else选择结构 条件为真时执行某个指定的操作,为假时执行另一个指定的操作(双路选择) • switch选择结构 根据表达式的值执行众多不同操作中的某个指定的操作(多路选择)

  13. 二、算法与流程图4、三种基本结构P24- • 循环结构 分当型和直到型两类。 当型 先判断,只要条件为真就反复执行A块,为假则结束循环。 直到型 先执行A块,再判断条件是否为真,为真则继续执行循环体,为假则结束循环。 • C语言提供了三种循环结构,即while循环结构,do…while循环结构和for循环结构。

  14. 三、选择结构程序设计1、if语句P95 三种形式: • if(表达式)语句; (图5.5a) • if(表达式)语句1; else语句2; (图5.5b) • if(表达式1)语句1; (图5.6) else if(表达式2)语句2; …… else if(表达式n)语句n; else语句n+1; ◆e1?e2:e3是if … else语句在特定情况下的变体。

  15. 三、选择结构程序设计1、if语句示例 【例一】以下程序的作用是什么? main( ) { char c; printf(“Input :”); scanf(“%c”,&c); if (c>=’a’ && c<=’z’) c=c-32; else c=c; printf(“%c”,c); } /*将小写字母转换为大写字母*/

  16. 三、选择结构程序设计1、if语句示例 【例二】以下程序的执行结果是什么? main( ) { int x=2,y=-1,z=2; if (x<y) if (y<0) z=0; else z+=1; printf(“%d\n”,z); } 哦,原来是因为else 总是与靠近它的if配套… /*结果是2*/ 常见错误: if (x>0) ; if (x=2) if (1<=x<=10) y=3x+2; printf(“y>0”); y=x-1;

  17. 三、选择结构程序设计2、switch语句P104 switch 语句的一般形式: switch(e) { case c1:语句组1; casec2:语句组2; …… casecn:语句组n; default:语句组n+1; /*可缺省*/ } /*e – 表达式(整型、字符型或枚举型)*/ c1~cn 常量(整数、字符、常量表达式如3+4,不含变量或函数) default – 不是c1~cn的情况 (位置不一定在最后)。

  18. 三、选择结构程序设计2、switch语句示例 ?! main() { char s; scanf(“%c”,&s); switch(s) { 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(“错误输入\n”); } } 结果: 60~69 <60 错误输入 输入“c”,求输出结果。

  19. 三、选择结构程序设计2、switch语句示例 main() { char s; scanf(“%c”,&s); switch(s) { 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(“错误输入\n”); } } 运行结果: 60~69 <60 错误输入 不好意思,我属于C级! 我的成绩应该是60~69! 什么!“<60”? “错误输入”?怎么会这样?!

  20. 三、选择结构程序设计2、switch语句示例 解决方法——break语句: main() { char s; scanf(“%c”,&s); switch(s) { 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(“错误输入\n”); } } 运行结果: 60~69 break! 这才差不多!

  21. 讨论 switch(s)语句中的s实际上并非真正的条件选择,而只是一种跳转指示(与if语句不同),表示下面应该跳转到什么位置继续执行。而各case实际上只是一个跳转处的标记。当程序跳转到某个case处时,并非只执行此case行的程序组,而是从此处开始一直向下执行各条语句,直到整个switch开关体结束(“}”)。 如果要使每个case处相当于一种if(s)else的效果,必须在其语句组最后加上break语句。 三、选择结构程序设计2、switch语句示例 解决方法——break语句: main() { char s; scanf(“%c”,&s); switch(s) { 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(“错误输入\n”); } }

  22. 说明 1、每个case常量表达式的值必须互不相同,否则会出现互相矛盾的结果。 2、允许多个case共用一个执行语句。 三、选择结构程序设计2、switch语句示例 main() { 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(“a=%d,b=%d\n”,a,b); } 求程序运行结果。 结果:a=2,b=1。 如果x=2? 结果:a=1,b=1 如果x=3? 结果:a=1,b=1

  23. 三、循环结构程序设计 循环是在循环条件为真时计算机反复执行的一组指令(循环体)。 循环控制通常有两种方式: ◆计数控制 事先能够准确知道循环次数时用之 用专门的循环变量来计算循环的次数,循环变量的值在每次执行完循环体各语句后递增,达到预定循环次数时则终止循环,继续执行循环结构后的语句。 ◆标记控制 事先不知道准确的循环次数时用之 由专门的标记变量控制循环是否继续进行。当标记变量的值达到指定的标记值时,循环终止,继续执行循环结构后的语句。

  24. 四、循环结构程序设计 在C语言中可用以下语句构成循环: • if … goto • while • do … while • for 其中if … goto是通过编程技巧(if语句和goto语句组合)构成循环功能。而且goto语句将影响程序流程的模块化,使程序可读性变差,所以结构化程序设计主张限制goto语句的使用。 其他三种语句是C语言提供的循环结构专用语句。

  25. 四、循环结构程序设计 名词解释 无限循环 死循环 循环结构两大要素: • 循环条件p 结束循环的条件表达式 • 循环体 A 循环执行的语句或语句组 设置循环条件要特别注意确定: • 循环变量的初值 • 循环变量的终值 • 循环变量的变化规律 名词解释 空循环

  26. 四、循环结构程序设计1、if … goto语句循环结构P113 当 型 【例一】 main() { int n=0,sum=0; loop: sum+=n; ++n; if (sum<=10000) goto loop; printf(“n = %d\n”,n); } 【例二】 main() { int n=0,sum=0; loop: if (sum>=10000) goto end; sum+=n; ++n; goto loop; end: printf(“n = %d\n”,n); } 直到型

  27. 四、循环结构程序设计2、while语句循环结构P114 当 型 • 一般形式 while (条件表达式)循环体; • 用于构成当型循环:先判断后执行/条件为真继续循环,直到条件为假时结束循环。 • 【注意】条件表达式或循环体内应有改变条件使循环结束的语句,否则可能陷入“死循环”。 【例三】 main() { int n=0,sum=0; while (sum<=10000) { sum+=n; ++n; } printf(“n = %d\n”,n); }

  28. 四、循环结构程序设计3、do…while语句循环结构P108 【例四】 main() { int n=0,sum=0; do { sum+=n; ++n; } while (sum<=10000) ; printf(“n = %d\n”,n); } • 一般形式 do { 循环语句(组) } while (条件表达式); • 用于构成直到型循环:先执行后判断/条件为真继续循环,直到条件为假时结束循环。 • 【注意】条件表达式或循环体内同样应有改变条件使循环结束的语句,否则可能陷入“死循环”。 直到sum超过10000为止 直到型

  29. 四、循环结构程序设计3、do…while语句循环结构示例 【例五】从键盘输入一个整数12456,分析以下程序运行结果。 main() { int num,c; printf(“请输入一个整数:“); scanf(“%d”,&num); do { c=num%10; printf(“%d”,c); } while((num/=10)>0); printf(“\n”); } 结果: 65421 将各位数字反序显示出来 /*取得num的个位数*/ /*输出num的个位数*/ /*直到num/10为0*/

  30. 一般形式 for (表达式1;条件表达式;表达式3) 循环语句(组); 用于构成计数型当型循环:先判断后执行/条件为真继续循环,直到条件为假时结束循环。 表达式1: 整个循环中只执行1次,常用来对循环变量设置初值 条件表达式(表达式2): 其值为真(非0)时继续执行循环语句(组),否则结束循环 表达式3: 常用于循环变量值的更新(循环体的一部分每次循环语句组执行完后执行一次) 四、循环结构程序设计4、for语句循环结构P118 【例六】 求∑i =1+2+3+4…+99+100 (i=1~100) main() { int i , s=0; for (i=1;i<=100;i++) s=s+i; printf(“Sum=%d\n”,s); }

  31. break 结束循环 在switch中退出switch结构; 在循环中结束循环。 continue 结束本次循环 循环“短路” (跳过循环体后面的语句,开始下一轮循环)。 goto 跳转 跳到循环体外指定标号处。 【注意】 goto 语句只能从循环内向外跳转 ,反之不可! main( ) { int a,y; a=10,y=0; do { a+=2;y+=a; if (y>50) break; } while (a=14); printf("a=%d,y=%d\n",a,y); } 四、循环结构程序设计5、其他循环控制结构P122 变量跟踪 分析法 变量跟踪 a y 10 0 12 12 14+2 16+12=28 14+2 16+28=44 14+2 16+44=60 结果:a=16,y=60

  32. break 结束循环 在switch中退出switch结构; 在循环中结束循环。 continue 结束本次循环 循环“短路” (跳过循环体后面的语句,开始下一轮循环)。 goto 跳转 跳到循环体外指定标号处。 【注意】 goto 语句只能从循环内向外跳转 ,反之不可! 求以下程序段执行后x和i的值。 int i,x; for ( i=1,x=1;i<=50;i++) { if (x>=10) break; if (x%2==1) { x+=5; continue; } x-=3; } 四、循环结构程序设计5、其他循环控制结构P122 变量跟踪 i x 1 1→6 2 6→3 3 3→8 4 8→5 5 5→10 6 结果:x的值为10,i的值为6

  33. break 结束循环 在switch中退出switch结构; 在循环中结束循环。 continue 结束本次循环 循环“短路” (跳过循环体后面的语句,开始下一轮循环)。 goto 跳转 跳到循环体外指定标号处。 【注意】 goto 语句只能从循环内向外跳转 ,反之不可! main() { int i=1; while (i<=15) if (++i%3!=2) continue; else printf("%d ",i); printf("\n"); } 四、循环结构程序设计5、其他循环控制结构P122 变量跟踪 i ++i%3 输出i 1→2 2 2 2→3 0 3→4 1 4→5 2 5 5→6 0 …… 结果:2 5 8 11 14

  34. break 结束循环 在switch中退出switch结构; 在循环中结束循环。 continue 结束本次循环 循环“短路” (跳过循环体后面的语句,开始下一轮循环)。 goto 跳转 跳到循环体外指定标号处。 【注意】 goto 语句只能从循环内向外跳转 ,反之不可! main() { int i,k=0; for (i=1; ;i++) { k++; while (k<i*i) { k++; if (k%3==0) gotoloop; } } loop:printf("%d,%d",i,k); } 四、循环结构程序设计5、其他循环控制结构P122 结果:2 ,3

  35. 编程示例※ 题目:编写一个用户密码校验程序。用户根据提示输入密码,如果密码正确,显示“Welcome!”信息;密码不正确,除提示密码输入错误外,允许再输入密码,如果三次输入均错,显示“你是非法用户”,然后结束程序。 • 程序分析(画出传统流程图和N-S流程图) • 密码输入部分分析(画出N-S流程图) • 现场程序编写与调试 • 程序不足处说明(留给学生解决)

  36. 密码校验程序流程图

  37. 密码校验程序N-S流程图

  38. 五、常用算法 1、枚举法(穷举法) “笨人之法”:把所有可能的情况一一测试,筛选出符合条件的各种结果进行输出。 【例一】百元买百鸡:用一百元钱买一百只鸡。已知公鸡5元/只,母鸡3元/只,小鸡1元/3只。 分析: 这是个不定方程——三元一次方程组问题(三个变量,两个方程) x+y+z=100 5x+3y+z/3=100 设公鸡为x只,母鸡为y只,小鸡为z只。

  39. 百元买百鸡问题分析

  40. 百元买百鸡问题分析 main() { int x,y,z; for (x=0;x<=100;x++) for (y=0;y<=100;y++) for (z=0;z<=100;z++) { if (x+y+z==100 && 5*x+3*y+z/3.0==100 ) printf("cocks=%d,hens=%d,chickens=%d\n",x,y,z); } } 结果:x=0,y=25,z=75 x=4,y=18,z=78 x=8,y=11,z=81 x=12,y=4,z=84 【讨论 此为“最笨”之法——要进行101×101×101= 1030301次(100多万次)运算。

  41. 百元买百鸡问题分析 main() { int x,y,z; for (x=0;x<=100;x++) for (y=0;y<=100;y++) { z=100-x-y; if (5*x+3*y+z/3.0==100 ) printf(“cocks=%d,hens=%d,chickens=%d\n",x,y,z); } } 取x<=19,y<=33 只进行20×34= 680 次运算(第1种运算的6.7%) 【讨论】 令z=100-x-y 只进行101×101= 10201 次运算(前者的1%)

  42. 【例二】雨水淋湿了算术书的一道题,8个数字只 能看清3个,第一个数字虽然看不清,但可看出不是1。编程求其余数字是什么?[ □×(□3+□)]2 = 8□□9 • 分析 设分别用A、B、C、D、E五个变量表示自左到右五个未知的数字。其中A的取值范围为2~9,其余取值范围为0~9。条件表达式即为给定算式。

  43. 【例二】雨水淋湿了算术书的一道题,8个数字只 能看清3个,第一个数字虽然看不清,但可看出不是1。编程求其余数字是什么?[ □×(□3+□)]2 = 8□□9 main() { int A,B,C,D,E; for (A=2;A<=9;A++) for (B=0;B<=9;B++) for (C=0;C<=9;C++) for (D=0;D<=9;D++) for (E=0;E<=9;E++) if (A*(B*10+3+C)*A*(B*10+3+C)==8009+D*100+E*10) printf(“%2d%2d%2d%2d%2d\n”,A,B,C,D,E); } 结果:3 2 8 6 4

  44. 【例三】求100~200之间不能被3整除也不能被7整除的数。【例三】求100~200之间不能被3整除也不能被7整除的数。 • 分析:求某区间内符合某一要求的数,可用一个变量“穷举”。所以可用一个独立变量x,取值范围100~200。 for (x=100;x<=200;x++) if (x%3!=0&&x%7!=0) printf(“x=%d\n”,x); 如果是求指定条件的奇数呢? x=101;x<=200;x=x+2 如果是求指定条件的偶数呢? x=100;x<=200;x=x+2

  45. 五、常用算法 2、归纳法(递推法) “智人之法”: 通过分析归纳,找出从变量旧值出发求新值的规律。 【例一】 编程求∑i =1+2+3+4…+99+100 (i=0~100) 分析 i=0 S0= 0 (初值) i=1 S1= 0+1=S0+1 i=2 S2=1+2=S1+2 i=3 S3=1+2+3=S2+3 i=4 S4=1+2+3+4=S3+4 … … … i=n Sn=1+ 2+3+4+…+n=Sn-1+n

  46. 如果是 ∑i =1+1/2+1/3+…+1/n 呢? 【例一】 编程求∑i =1+2+3+4…+n ( n ≤100) 程序: main() { int i ,n, s=0; printf("n="); scanf("%d",&n); for ( i=1;i<=n;i++) s=s+i; printf("Sum=%d\n",s); } 运行结果: n=100 Sum=5050

  47. 算法类型小结:累加型 【累加型】类型诸如 □+□+□+□+……+□+□ 求其前n项之和的编程题。 累加型算法 若设i为循环变量,s为前n项累加之和,则程序的基本结构为: s=0; for( i=1 ;i<=n ;i++ ) s=s+□;

  48. 【例二】编程求1-1/2+1/3-1/4+1/5- … +1/99-1/100 错在哪里? 法1:从变化规律分析…… • 分母为奇数时,相加 • 分母为偶数时,相减 程序: main() { int i; float s=0; for (i=1;i<=100;i++) if (i%2) s=s+1/i; else s=s-1/i; printf("Sum=%f\n",s); } 运行结果:Sum=1.000000

  49. 【例二】编程求1-1/2+1/3-1/4+1/5- … +1/99-1/100 法2:这是个累加型算法的编程题…… 错在哪里? (如何检查程序错误?) 程序: #include <math.h> main(); { int i ; float s=0; for (i=1;i<=100;i++) s=s+pow (-1, i+1) / i ; printf("Sum=%f\n",s); } 累加型算法 程序基本结构为: s=0; for( i=1;i<=n;i++ ) s=s+□; 程序: #include <math.h> main() { int i ,k=1; float s=0; for (i=1;i<=100;i++) { s=s+k / i ; k = -k ; } printf("Sum=%f\n",s); } 运行结果:Sum=0.688172 运行结果:Sum=1.000000

  50. 【例三】 编程求n! (n由键盘输入) 分析 i=0 S0=1=S0 (初值) i=1 S1= 0×1=S0×1 i=2 S2=1×2=S1×2 i=3 S3=1×2×3=S2×3 i=4 S4=1×2×3×4=S3×4 … … … i=n Sn=1× 2×3×4×…×n=Sn-1×n

More Related