C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt

上传人:小飞机 文档编号:3909468 上传时间:2023-03-27 格式:PPT 页数:42 大小:619KB
返回 下载 相关 举报
C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt_第1页
第1页 / 共42页
C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt_第2页
第2页 / 共42页
C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt_第3页
第3页 / 共42页
C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt_第4页
第4页 / 共42页
C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt_第5页
第5页 / 共42页
点击查看更多>>
资源描述

《C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt》由会员分享,可在线阅读,更多相关《C语言高级语言程序设计(一)教学ppt课件-第四章 程序设计方法-模块化与算法设计.ppt(42页珍藏版)》请在三一办公上搜索。

1、高级语言程序设计(一)(C Programming),第四讲:程序设计方法-模块化与算法设计,本章目标,进一步掌握模块化设计思想掌握常用的数据查找及排序方法了解全局变量了解递归程序设计思想,问题4.1,【问题描述】从文件中查找包含给定字符串的行。【输入形式】从标准输入中分两行分别输入被查找的文件及要查找的字符串(中间不含空格)。【输出形式】在屏幕上输出文件中包含给定字符串的行。【样例输入】在键盘输入如下文件名及字符串:test.txtthe文件test.txt内容如下:Now is the timefor all goodmen to come to the aidof their party

2、【样例输出】屏幕输出为:this is the timemen to come to the aidof their party,问题4.1:算法设计,设 int index(char s,char t)函数用来在字符串s中查找字符串t。若找到则反回t在s中出现的位置,否则返回-1。其主要查找算法如下:,主要算法分析,在字符串s中查找字符串t:for(i=0;si!=0;i+)for(j=i,k=0;tk!=0;j+,k+)sj和tk进行比较,遍历输入字符串中每个字符,依次与给定串中每个字符比较。j为s中每次开始比较的位置。,不同时break;找到的条件是:tk=0,问题4.1:算法设计(续)

3、,主要算法如下:设变量filename,s,line分别用于存储文件名、查找串及文件中一行;从标准输入中读入文件名和要查找的串到filename和s中;以读方式打开文件filename;while 文件中还有内容时读一行到line中如果 index(line,s)=0 输出line;,如何从文件中读入一行?char*fgets(char*s,int n,FILE*fp)从fp上最多读入n-1个字符,放入s 字符数组中。返回s,到达文件尾部返回NULL。,利用fgets从标准输入读取一行字符串放在字符数组s中,s的大小是101:fgets(s,101,stdin);,问题4.1:代码实现,#in

4、clude#define MAXLINE 1000int index(char s,char t);int main()char filename64,s81,lineMAXLINE;FILE*fp;scanf(%s,filename);scanf(%s,s);if(fp=fopen(filename,r)=NULL)printf(Cant open file%s!n,filename);return 1;while(fgets(line,81,fp)!=NULL)if(index(line,s)=0)printf(%s,line);return 0;,int index(char s,cha

5、r t)int i,j,k;for(i=0;si!=0;i+)for(j=i,k=0;tk!=0,使用scanf的缺点是不能输入带空格的字符串。可换成gets(s);来实现查找带空格的字符串。,由于打开一个文件操作可能失败,因此,好的风格应判断fopen函数的返回值,进行错误处理。,注意:由于上述循环当没有相应匹配字符时也退出。因此,要依据t中所有字符都匹配(即tk=0)来判断查找是否成功。,问题4.1:测试,当要查找的文件为“test.txt”,要查找的串为”the”,且文件test.txt中内容为:Now is the timefor all goodmen to come to the

6、aidof their party则屏幕输出:this is the timemen to come to the aidof their party,问题4.1:测试(续),其它考虑点:要查找的串在一行的头、尾要查找的串在文件中不存在,问题4.1:思考1,问题4.1实现了大小写相关的字符串查找,即字符串“the”和“The”是不同字符串。请实现大小写无关的字符串查找。算法分析:在比较字符时,可将比较字符均转换为小写或大写既可实现大小写无关查找。设函数char tolower(char c)用于将字符c转换为相应小写字符,则上面index可改为:,int index(char s,char t

7、)int i,j,k;for(i=0;si!=0;i+)for(j=i,k=0;tk!=0,问题4.1:函数tolower实现,方法一:char tolower(char c)if(c=A 方法二:对于象tolower这样功能简单的函数,可以用宏函数来实现。#define tolower(c)(c=A&c=Z?a-A+c:c),预处理程序:define,定义函数宏定义还可带变元(参数):#define 标识符(标识符,标识符,)单词串如:#definemax(A,B)(A)(B)?(A):(B)于是语句x=max(p+q,r+s);可替换为:x=(p+q)(r+s)?(p+q):(r+s);注

8、意:宏定义名与参数间不能有空格,如max(A,B);参数应用括号括起来,如(A)(B)?(A):(B),#define isupper(c)(c=A&c=Z)?1:0,反例:#define prod(x,y)x*y则:a=prod(b+c,d+e);被替换为:a=b+c*d+e;,问题4.1:思考1(代码实现),#include#define MAXLINE 1000#define tolower(c)(c=A,int index(char s,char t)int i,j,k;for(i=0;si!=0;i+)for(j=i,k=0;tk!=0,问题4.1:思考2,其它实现方法?问题4.1中

9、index只能查找的是子字符串的首次出现。请考虑如何查找子字符串的最后一次出现?如果要查找一个字符串在一个文件中的出现次数,或查找一个字符串在一个文件中的所有出现行列位置,如何实现?(注意,index只能查找子字符串首次出现,如果一行中有多个子字符串怎样办?),问题4.2,【问题描述】某班有不超过200名的学生,从文件中输入某班学生成绩,对输入成绩按由高到低进行排序,并输出到另一个文件中。【输入形式】从文件scorelist.in中读入学生成绩,学生成绩以整数形式按行存放。注意,学生成绩数目不确定。【输出形式】将排序结果按行写到文件sorelist.out中。【样例输入】若文件scorelis

10、t.in中有如下成绩:5875628698【样例输出】程序运行结束后文件scorelist.out中内容为:9886756258,问题4.2:算法分析,问题可分解为如下几个部分:,算法:int socrelistNUM,n=0;while(!feof(in)fscanf(in,“%d”,函数feof用来测试是否已读写到文件尾,若到文件尾,则返回1,否则返回0。函数fscanf用来从文件中读数据。与标准输入scanf不同的是第一个参数为文件指针。,算法:for(i=0;in;i+)fprintf(out,“%d“,scorelisti);函数fprintf用来从文件中读数据。与标准输入print

11、f不同的是第一个参数为文件指针。,算法:设一个函数专门用来对学生成绩进行排序,函数原型为:void sortScore(int list,int len),算法:FILE*in,*out;in=fopen(“scorelist.in”,“r”);out=fopen(“scorelist.out”,”w”);,问题 4.2:算法分析-选择排序(续),有许多经典的算法用来对数据进行排序,如选择排序(selection sort)、插入排序(insertion sort)和快速排序(quick sort)等。有关排序算法及分析主要在数据结构课程中讲授。在问题4.2中将使用选择排序算法对学生成绩进行排

12、序。,问题 4.2:算法分析-选择排序(续),选择排序的核心思想是先通过找到数组中未排序部分的最大元素,然后将其移到未排序部分的最前端来排序一个数组(从大至小排序)。即首先在整个数组中查找最大元素,将其换到第一个位置;然后从数组中第二个元素开始查找最大元素,以此类推。下面以图示来说明:,问题 4.2:算法分析-选择排序(续),最大元素,最大元素,问题 4.2:算法分析-选择排序(续),选择排序包括以下步骤:找到最大元素将最大元素移到未排序部分的第一个位置上,index=0;for(i=1;iN;i+)if(arrayindex arrayi)index=i;,通过交换两个元素即可。如:int

13、tmp;tmp=arrayi;arrayi=arrayindex;arrayindex=tmp;,问题 4.2:代码实现(排序函数),void sortArray(int array,int n)int i,j,tmp,index;for(i=0;in;i+)index=i;for(j=i;jn;j+)if(arrayindex arrayj)index=j;tmp=arrayi;arrayi=arrayindex;arrayindex=tmp;,问题 4.2:代码实现(主函数),#include#define NUM 200void sortArray(int array,int n);in

14、t main()int scorelistNUM,i,n=0;FILE*in,*out;if(in=fopen(scorelist.in,r)=NULL)printf(Cannt open file scorelist.in!n);return 1;if(out=fopen(scorelist.out,w)=NULL)printf(Cannt open file scorelist.out!n);return 1;while(!feof(in)fscanf(in,%d,C程序设计基础,22,问题 4.2:一种模块化更好的实现,#include#define NUM 200int readLis

15、t(int array);void sortArray(int array,int n);void writeList(int array,int n);int main()int scorelistNUM,n;n=readList(scorelist);sortArray(scorelist,n);writeList(scorelist,n);return 0;,int readList(int array)FILE*in;int n=0;if(in=fopen(scorelist.in,r)=NULL)printf(Cannt open file scorelist.in!n);exit(

16、1);while(!feof(in)fscanf(in,%d,问题 4.2:测试及常见问题,若文件scorelist.in文件尾有一个回车,则会发生什么现象?如何调试?,若文件scorelist.in内容为:5875628698,程序运行后文件scorelist.out内容为:9886756258,问题 4.2:修改主函数,#include#define NUM 200void sortArray(int array,int n);int main()int scorelistNUM,i,n=0;FILE*in,*out;if(in=fopen(scorelist.in,r)=NULL)pri

17、ntf(Cannt open file scorelist.in!n);return 1;if(out=fopen(scorelist.out,w)=NULL)printf(Cannt open file scorelist.out!n);return 1;while(fscanf(in,%d,问题 4.2:另一个常用排序方法(冒泡排序)*,void sortArray(int array,int n)int i,j,tmp;for(i=0;in;i+)for(j=i;jn;j+)if(arrayi arrayj)tmp=arrayi;arrayi=arrayj;arrayj=tmp;,问题

18、4.2:另一个常用排序方法(冒泡排序)*,/从后往前,即最先排好的是头部void sortArray(int array,int n)int i,j,tmp;for(i=1;i=i;j-)if(arrayjarrayj-1)tmp=arrayj-1;arrayj-1=arrayj;arrayj=tmp;,/从前往后,即最先排好的是尾部void sortArray(int array,int n)int i,j,tmp;for(i=0;in-1;i+)for(j=0;jn-1-i;j+)if(arrayjarrayj+1)tmp=arrayj+1;arrayj+1=arrayj;arrayj=t

19、mp;,问题 4.2:另一种方法,在上述方法中,学生成绩一次全部读入,然后再排序后输出。还有一种方法为每读入一个数据,就将其加到一个有序数据集中的相应位置上,无需最后排序。其具体算法如下:,问题 4.2:另一种算法,1.设整型数组scorelist存放排序后成绩,n为其中学生成绩个数,初始n为0;2.分别以读和写方式打开文件scorelist.in和scorelist.out;3.while 读文件中还有成绩时,读入一个成绩到score将score插入到有序数组scorelist中相应位置;4.输出数组scorelist到写文件中;5.关闭读写文件;,设函数void insertData(in

20、t array,int data);将一个变量插入到有序(从大到小)数组array中,插入后数组仍有序。,问题 4.2:函数insertData算法,找到数组array中第一个比data小的数组元素,设其下标为i;将下标大于等于i的所有数组元素向后移动一个位置;arrayi=data;数组元素个数n加1;,数组实际元素个数需要在insertData和main函数中都用到,如何在程序中函数间共享数据?1)通过函数参数传递。但函数参数方式为传值,若要通过函数调用改变实参的值,要用到指针。2)通过return语句返回值。注意只能返回一个值。3)使用全局变量。,问题 4.2:另一种代码实现,/c4_2

21、b.c#include#define NUM 200int N=0;void insertData(int array,int data);int main()int scorelistNUM,score,i;FILE*in,*out;if(in=fopen(scorelist.in,r)=NULL)printf(Cannt open file scorelist.in!n);return 1;if(out=fopen(scorelist.out,w)=NULL)printf(Cannt open file scorelist.out!n);return 1;while(fscanf(in,%

22、d,void insertData(int array,int data)int i,j;for(i=0;iarrayi)break;for(j=N;ji;j-)arrayj=arrayj-1;arrayi=data;N+;,查找要插入的位置,从插入位置开始所有元素向后移动一个元素。,N为一个全局变量。,全局变量访问,外部变量*,外部变量(global variable):在函数外面定义的变量。作用域(scope)为整个程序,即可在程序的所有函数中使用。外部变量有隐含初值0。生存期(life cycle):外部变量(存储空间)在程序执行过程中始终存在。,外部变量说明(extern)*,C程序可

23、以分别放在几个文件上,每个文件可作为一个编译单位分别编译。外部变量只需在某个文件上定义一次,其它文件若要引用此变量时,应用extern加以说明。(外部变量定义时不必加extern关键字)。在同一文件中,若前面的函数要引用后面定义的外部(在函数之外)变量时,也应在函数里加以extern说明。,外部变量说明(extern)(续)*,例如,对问题4.2的代码实现中,如果外部变量N不在程序头部定义,则需要用extern加以说明。extern int N;int main()int N=0;void insertData(int array,int data),外部变量定义,外部变量说明,外部变量说明(

24、extern)(续)*,使用外部变量的原因:解决函数单独编译的协调;与变量初始化有关;外部变量的值是永久的;解决数据共享;外部变量的副作用:使用外部变量的函数独立性差,通常不能使用在其他的程序中。而且,如果多个函数都使用到某个外部变量,一旦出现差错,就很难发现问题是由哪个函数引起的。在程序中的某个部分引起外部变量的错误,很容易误以为是由另一部分引起的。,递归(Recursion)*,通过调用自身解决问题的过程称为递归。递归是解决某些复杂问题的有效方法。如:,递归(续)*,例:求n!#include int fact(int n);main()printf(“3!=%d,5!=%dn”,fact

25、(3),fact(5);int fact(int n)int res=0;if(n=1)res=1;else res=n*fact(n-1);return res;,在C语言中,一个函数直接或间接调用自已称为递归。,1,fact(3),3*fact(2),2*fact(1),递归(续)*,递归算法十分简洁,编译后得到的目标代码也很短,但它并不节省(实际上还要增加)运行时所需的时间和空间,因为它必须维持一个要处理的值的栈。此外,递归算法并不是语言必须的,不用它同样可以实现相应功能,如上例中,递归函数fact可用非递归方法 实现:int fact(int n)int f=1;while(n)f*=

26、n;n-;return(f);,例:汉诺塔(hanoi tower)游戏void hanoi(int n,char a,char b,char c)if(n 0)hanoi(n-1,a,c,b);printf(“MOVE%d:%c%cn”,n,a,c);hanoi(n-1,b,a,c);main()int n;printf(“Please input the number of hanoi tower:”);scanf(“%d”,问题4.3:一个经典递归程序示例*,问题4.4:生成全排列数*,【问题描述】输入整数N(1=N=10),生成从1N所有整数的全排列。【输入形式】输入整数N。【输出形式

27、】输出有N!行,每行都是从1N所有整数的一个全排列,各整数之间以空格分隔。各行上的全排列不重复。输出各行遵循“小数优先”原则,在各全排列中,较小的数尽量靠前输出。如果将每行上的输出看成一个数字,则所有输出构成升序数列。具体格式见输出样例。【样例输入1】3【样例输出1】1 2 31 3 22 1 32 3 13 1 23 2 1【样例说明1】输入整数N=3,要求整数1、2、3的所有全排列,共有N!=6行。且先输出1开头的所有排列数,再输出2开头的所有排列数,最后输出3开头的所有排列数。在以1开头的所有全排列中同样遵循此原则。【样例输入2】10【样例输出2】1 2 3 4 5 6 7 8 9 10

28、1 2 3 4 5 6 7 8 10 91 2 3 4 5 6 7 9 8 101 2 3 4 5 6 7 9 10 81 2 3 4 5 6 7 10 8 91 2 3 4 5 6 7 10 9 8【样例说明2】输入整数N=10,要求整数1、2、3、10的所有全排列。上例显示了输出的前10行。,问题4.4:算法分析*,对于N的全排列:MNMN-1MnM1其中Mn的值应为1,2,N数字中不为MNMN-1Mn+1的数字,并且应从小到大取值。因此,可设一个数组int MarkN用来分别标识一个数字是否已被使用。因此,对于生成Mn数字的算法如下:If(n=0)/*当前排列已生成*/输出数字串MNMN

29、-1MnM1;结束;for(i=1;i=N;i+)If(Marki=0)/*表示该数字i未使用*/Marki=1;/*数字i将被使用*/将数字i放到全排列位置n上(即MNMN-1Mn的Mn)生成Mn-1 数字;Marki=0;/*数字i将被释放*/,使用递归方法!,问题4.4:代码实现*,#include#define MAX 10int MarkMAX=0;/*标记数组,用来标记某个数字是否已被使用成为*/char StackMAX+1;/*全排列数字串*/void rank(int m,int n);/*m记录下一个要生成的全排列数字应放在Stack中的位置,n表示还剩几个数字需要生成*/int N;int main()scanf(%d,/*释放该数字*/,递归(续):递归问题总结*,通常包含如下特性的问题适合应用递归方法解决:问题包含一个(或多个)基本实例,如 0!=1问题的解可以简化为包含比当前问题更简单一步的问题的解,并且最终问题解可归结到基本实例,如 n!=n*(n-1)!,0!=1。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号