1 / 51

第 8 章 综合应用

第 8 章 综合应用. 8.1 穷举法:打开问题的缺口. 8.1.1 穷举法的基本思想. 基本思想:. 将所有可能的状态例举出来,然后逐一检验是否满足条件,从而判断哪些是需要的解,哪些不是。. 问题 1 : 求解 1~1000 之间所有的素数。. 问题 2 : 求解满足在 1~1000 之间的两个数之和等于 1234 的所有解。. 问题 3 : 求解满足在 1~1000 之间的三个数,它们是直角三角形的三条边的所有解。. 第四章 串. 问题 1 的解决方法:. 对从 2 开始一直到 1000 的所有数去判断是否是素数,如果是则输出 。.

halden
Download Presentation

第 8 章 综合应用

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. 第8章 综合应用

  2. 8.1 穷举法:打开问题的缺口 • 8.1.1 穷举法的基本思想 基本思想: 将所有可能的状态例举出来,然后逐一检验是否满足条件,从而判断哪些是需要的解,哪些不是。 问题1:求解1~1000之间所有的素数。 问题2:求解满足在1~1000之间的两个数之和等于1234的所有解。 问题3:求解满足在1~1000之间的三个数,它们是直角三角形的三条边的所有解。

  3. 第四章 串 问题1的解决方法: 对从2开始一直到1000的所有数去判断是否是素数,如果是则输出。 for(i=2;i<1000;i++) if(IsPrime(i)) printf(“%d\t”,i); 问题2的解决方法: 两个数不妨设为a和b。该问题的就是求解满足1≦a ≦1000, 1 ≦b ≦1000 而且a+b=1234的所有的a和b。 for(a=1;a<=1000;a++) for(b=1;b<=1000;b++) if(a+b==1234)printf(“a=%d,b=%d\n”,a,b)

  4. 第四章 串 问题3的解答: 若设这三个数为a,b,c,那么问题的解满足: (1) 1≦a≦1000, 1≦b≦1000, 1≦c≦1000; (2) a2 = b2 + c2 或者 b2 =a2 +c2或者 c2 =a2 + b2 for(a=1;a<=1000;a++) for(b=1;b<=1000;b++) for(c=1;c<=1000;c++) if((a*a=b*b+c*c)||(b*b=a*a+c*c) ||(c*c=a*a+b*b)) printf(“a,b,c分别是%d,%d,%d\n”,a,b,c);

  5. 第四章 串 用穷举法的必备条件: • 可以预先确定每种状态下的元素个数 2.每种状态下元素a1,…ai,…an的可能值是一个连续的值域。称ai为穷举变量,ai∈[amin, amax]。 解决问题的方式一般为: for(a1=a1min; a1<a1max;a1++) for(a2=a2min; a2<a2max;a2++) …… for(an=anmin; an<anmax ; an++) if(状态(a1,a2,…an)满足检验条件) 输出问题的解

  6. 例8-2 百钱买百鸡 鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。凡百钱买百鸡,问鸡翁、母、雏各几何? • 问题分析: 1:确定穷举变量以及穷举范围 • 穷举变量:鸡翁(cock),鸡母(hen),鸡雏(chick) • 穷举范围: • hen∈[0,100/3] • chick∈[0, ] • chick%3==0 • cock∈[0,100/5] • 99 2:满足的条件 • 百钱:5*cock+3*hen+chick/3==100 • 百鸡:cock+hen+chick==100 第四章 串

  7. 程序实现: #include<stdio.h> void main( ) { int cock , hen , chick ; for(cock=0;cock<=20;cock++) for(hen=0;hen<=33;hen++) for(chick=0;chick<=99;chich+=3) if((cock+hen+chick==100)&&(5*cock+3*hen+chich/3==100)) printf(“100钱买公鸡%d只,母鸡%d只,小鸡%d只\n”, cock , hen , chick); } 第四章 串

  8. 上述的程序采用的是三重循环实现穷举,事实上,我们使用二重循环就可以完成任务了。因为这三个循环变量之间不是独立的,而是有关系的,我们可以通过它们之间的关系重新确定穷举变量的范围。上述的程序采用的是三重循环实现穷举,事实上,我们使用二重循环就可以完成任务了。因为这三个循环变量之间不是独立的,而是有关系的,我们可以通过它们之间的关系重新确定穷举变量的范围。 1.穷举变量的穷举范围: cock:0,1,……,20; hen:0,1,……,(100-5*cock)/3; chick:100-cock-hen 2.满足的条件: 小鸡数必须是3的倍数:chick%3==0 百钱:5*cock+3*hen+chick/3==100 第四章 串

  9. 程序实现: #include<stdio.h> void main() { int cock,hen,chick; int maxhen; for(cock=0;cock<=20;cock++) { maxhen=(100-5*cock)/3; for(hen=0;hen<=maxhen;hen++) { chick=100-cock-hen; if((chick%3==0)&&(5*cock+3*hen+chick/3==100)) printf("百钱买公鸡%d只,母鸡%d只,小鸡%d只\n“, cock,hen,chick); } } } 第四章 串

  10. 百钱买百鸡的问题中利用各穷举变量之间的关系提高了效率,由三重循环变为二重循环。这个例子说明,如果在穷举前预先对数据做一下分析,就可以提高穷举的效率。百钱买百鸡的问题中利用各穷举变量之间的关系提高了效率,由三重循环变为二重循环。这个例子说明,如果在穷举前预先对数据做一下分析,就可以提高穷举的效率。 通过这种方法,我们可以将问题2转化为一重循环解决,问题3也可以转化为二重循环来解决了。 问题2求解: for(a=1;a<=1000;a++) { b=1234-a; if(b<=1000) printf (“a=%d,b=%d\n”,a,b) } 第四章 串

  11. 对于某些问题,穷举变量的取值范围并没有确切的给出,此时要能够将问题答案范围内的状态与自然数建立一一对应,从而确定穷举变量的取值范围。对于某些问题,穷举变量的取值范围并没有确切的给出,此时要能够将问题答案范围内的状态与自然数建立一一对应,从而确定穷举变量的取值范围。 例8-3 选人方案。班上要在A,B,C,D,E,F 6名同学中选派若干人去参加比赛,选择条件如下: E和F两人至少去一个; C和D两人去一个; D和E要么都去,要么都不去; A、B、F三人中要去两个; 若C不去,则B也不去; C和F不能一起去。 请仔细分析上述条件,找出参加比赛的人选

  12. 对于该问题,我们很快就可以确定有6个穷举变量,不妨就设为a,b,c,d,e,f,而每个变量的变化范围如何确定呢?对于该问题,我们很快就可以确定有6个穷举变量,不妨就设为a,b,c,d,e,f,而每个变量的变化范围如何确定呢? 6名同学中的每一个同学都只会有“去”或“不去”两种选择,我们分别用自然数“ 1 ”和“ 0 ”来表示“去”和“不去”的状态,这样6个穷举变量的变化范围就确定了。 问题中所说的6个条件(分别用c1,c2,c3,c4,c5,c6表示)表达如下: E和F两人至少去一个:c1=(e+f>=1) C和D两人去一个: c2=(c+d==1) D和E要么都去,要么都不去:c3=(d+e==0||d+e==2) (或者c3=(d+e!=1)) A、B、F三人中要去两个:c4=(a+b+f==2) 若C不去,则B也不去:c5=(c+b==0||c==1) C和F不能一起去:c6=(c+f<=1) 选人时,上述的6个条件都要满足,即满足c1+c2+c3+c4+c5+c6==6的所有的a,b,c,d,e,f都是该问题的解。

  13. 程序实现: #include<stdio.h> void main() { int a,b,c,d,e,f; int c1,c2,c3,c4,c5,c6; for(a=0;a<=1;a++) for(b=0;b<=1;b++) for(c=0;c<=1;c++) for(d=0;d<=1;d++) for(e=0;e<=1;e++) for(f=0;f<=1;f++) { c1=e+f>=1; c2=c+d==1; c3=(d+e==0)||(d+e==2); c4=a+b+f==2; c5=(c+b==0)||(c==1); c6=c+f<=1; if(c1+c2+c3+c4+c5+c6==6) printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",a,b,c,d,e,f); } } 第四章 串

  14. 课堂练习: 问题1:输出从1,2,3,4,5这5个数中选取3个数的所有无复排列。 问题2:输出从1,2,3,4,5这5个数中选取3个数的所有无复组合。 问题3:输出从1,2,3,4,5,6这6个数中选取4个数的所有无复排列,要求最后一位(个位数)是偶数。

  15. 8.1.2 减少穷举量,提高穷举效率 由于穷举法是要将所有的解的状态一一例举,因此,如果解空间较大,穷举量就太大,程序运行的就会太慢。所以要尽可能的减少穷举状态。 如何减少穷举量呢? 问题1:求解1~1000之间所有的素数。 前面我们已经利用穷举法将问题1解决了,实际上,经过分析我们会发现穷举的次数无需1000次,可以减半,因为我们知道除了3,只要是偶数,就一定不会是素数。所以我们可以将所有大于2的偶数排除,在剩余的奇数中寻找素数。 第四章 串

  16. 解决方法如下: for(i=3;i<1000;i+=2) if(IsPrime(i))printf(“%d\t”,i); 而对于素数2,单独处理即可。 ?请大家再想想,看是否还可以减少穷举量? 通过上面的问题,我们可以看到,如果我们在穷举之前对问题先进性分析,挖掘出问题隐含的条件,排除不可能的条件,就可以减少穷举量了。 第四章 串

  17. 例8-4:寻找肇事汽车号码 一辆汽车肇事后逃逸了,目击者向交警描述了这个车号:这是一个4位的十进制完全数,并且这4个数字从左向右一个比一个大。 分析问题: 1.确定穷举变量和穷举范围: 穷举变量只有1个,不妨设为n。而4位十进制的范围从1000到9999,但是由于题目中告知这个数是一个完全数,既是说n=i2。因为1000≤n≤9999,所以32≤i≤99。所以我们把对n的穷举转化为对i的穷举,此时,穷举量大大减少了,有原来的8999个减少到67个。 第四章 串

  18. 分析问题: 2.满足条件:四个数字从左到右一个比一个大。 如果找到n=i2,满足1000≤n≤9999,对组成n的4个数字分别用num[0],num[1],num[2],num[3]表示,那么上述的条件就可表示为: (num[0]<num[1])&&(num[1]<num[2])&&(num[2]<num[3]) 第四章 串

  19. 8.1.3 局部穷举 例8-5:五人合伙夜间捕鱼 问题分析: 设A、B、C、D、E这五个人分得的鱼分别是fish[0]~fish[4]; 从题意中我们不难看出如下的关系式: fish[i+1]=(fish[i]-1)*4/5,i=0,1,2,3. 也就是说,只要我们知道了fish[0],则其它的值我们就可以计算得出了。因此只让fish[0]作为枚举变量就可以了。

  20. 可是从问题中我们知道,fish[0]的枚举范围并不好确定,因为它是最大的一个数。那么我们看一看其余的变量fish[1]~fish[4]中,哪一个作为枚举变量会更合适一些呢?可是从问题中我们知道,fish[0]的枚举范围并不好确定,因为它是最大的一个数。那么我们看一看其余的变量fish[1]~fish[4]中,哪一个作为枚举变量会更合适一些呢? 既然最大的那个数作为枚举变量不好确定枚举范围,我们来看一看让最小的那个数作为枚举变量行不行? 最小的数是fish[4],根据题意,容易知道,fish[4]>=6. 既然如此,我们可以处理各人所得鱼数的关系如下: fish[i]=fish[i+1]*5/4+1 i=3,2,1,0

  21. 因此我们有: int fish[5]={0,0,0,0,6}; do { for(i=3;i>=0;i--) { if(fish[i+1]%4!=0)break; else fish[i]=fish[i+1]*5/4+1; } if(i>=0) fish[4]=fish[4]+5; }while(i>=0);

  22. 局部穷举的例子还可以回顾一下第三张习题3.15.我们可以只对张三做穷举即可。局部穷举的例子还可以回顾一下第三张习题3.15.我们可以只对张三做穷举即可。 类似的,习题3.16、3.17、3.18、3.19、3.20等都是可以用枚举解决的问题。 此外,著名的N皇后问题也可以用枚举的方法求解。

  23. N皇后问题。 将N个皇后分别放置在一张N*N的棋盘上,要求她们之间互不攻击,即任意两个皇后不同行、不同列、不同一对角线。 比如,当N=4时的一种方法如表所示: j=1 j=2 j=3 j=4 i=1 i=2 i=3 i=4

  24. 问题分析: 我们可以使用穷举法解决N皇后问题。(先看N=4的情形。) 1.穷举变量:i,j,k,l; 2.穷举范围:1<=i,j,k,m<=4 3.穷举条件: 我们可以将皇后1放置在二维数组的位置a[1][i],皇后2放置在a[2][j],皇后3放置在a[3][k],皇后4放置在a[4][m].所以不妨假设一种放置的方法为:那么,不同行就已经解决了,接下来要描述的就是不同列和不同对角线: 不同列:(j!=i)&&(k!=i)&&(k!=j)&&(m!=i)&&(m!=j)&&(m!=k) 不同对角线:如果用a[x][i]和a[y][j]分别表示皇后x和皇后y的位置i和j的话,那么她们不同对角线应该为: |x=y|!=|i-j|

  25. void main() { int b[5]; int i,j,k,m; int x,y,t=0; for(i=1;i<=4;i++) for(j=1;j<=4;j++) for(k=1;k<=4;k++) for(m=1;m<=4;m++) if(j!=i&&k!=i&&k!=j&&m!=i&&m!=j&&m!=k) {//如果不同列,就赋给b中个元素 b[1]=i;b[2]=j;b[3]=k;b[4]=m; //如果不同对角线,就输出if(!Isdia(2,j,1,i)&&!Isdia(3,k,1,i)&&!Isdia(3,k,2,j)&& !Isdia(4,m,1,i)&&!Isdia(4,m,2,j)&&!Isdia(4,m,3,k)) for(x=1;x<=4;x++) printf("%d",b[x]); printf("\n"); } }

  26. 8.2 回溯法 N皇后问题: 如果每行放置1个皇后,则行就不会出项冲突的现象。因此解决的主要问题在于如何判断同列、同对角线的问题。 设皇后放置的位置数组为a[N]。则很容易根据a[i]与a[j]的值是否相等来判定皇后i和皇后j是否同列。 而对于对角线的判断,与前面我们曾经讨论的一样,看是否满足等式:j-i=|a[j]-a[i]|.如果满足,则同对角线,否则,就不同对角线。 如果已经放置好了i-1个皇后,在放置第i个皇后的时候要与这前i-1个皇后去判断是否同列和同对角线,如果有位置k,使得皇后i与前i-1个皇后既不同行,也不同对角线,则令a[i]=k即可。但是如果没有位置k满足条件,那么就要回溯了。回到第i-1个皇后,重新放置第i-1个皇后的位置,如果也没有位置放置第i-1个皇后,则继续回溯到前一个皇后。当回溯到第0个皇后的时候,无法回溯,则算法终止。

  27. 非递归实现N皇后问题 void NQueen(int n) { int i,j,k; int g; //安全标志变量 int a[20]; //各皇后存放位置数组 int x; //判定是否同列或对角线的变量 int s; //统计个数的变量 i=1;s=0;a[1]=1; //初始状态 while(1) { g=1; //初始时认为安全 for(k=i-1;k>=1;k--) { x=a[i]-a[k]; if(x<0)x=-x; //确保x非负 if(x==0||x==i-k) //如果同列或者同对角线 g=0; //皇后i位置a[i]不安全 } if(i==n&&g==1) //第n个皇后已经放好,则输出这组解 { s++; printf("第%d个解是:",s); for(j=1;j<=n;j++) printf("%d",a[j]); printf("\n"); } if(i<n&&g==1) //如果第i个皇后不是第n个皇后 { i++; //去放置第i+1个皇后 a[i]=1; //初始的位置仍然是1 continue; } while(a[i]==n&&i>1)i--; //放置皇后i>1的时候,所有位置都不安全,则回溯到第i-1个皇后 if(a[i]==n&&i==1)break; //如果回溯到第1个皇后,说明无解,退出 else a[i]=a[i]+1; //尝试下一个位置 } }

  28. 8.3 综合程序设计 • 综合程序设计的目的:强化C语言结构化设计的知识个进一步锻炼动手能力。 • 综合程序设计的要求: 1)选题。结合实际应用的要求,覆盖知识点,接近工程实际需要。 2)设计。能够根据实际要求,训练自己的实际分析问题的能力、设计能力和编程能力,并养成良好的编程习惯。 3)测试。通过不同类型的验证,测试程序的设计的完备性、全面性。

  29. 在软件开发过程中的各种不同的活动如下 • 定义问题 • 需求分析 • 规划构建 • 软件架构 • 详细设计 • 编码与调试 • 单元测试 • 集成测试 • 集成 • 系统测试 • 保障维护

  30. 综合程序设计的过程: 前期准备: 1 选题(定义问题):对要解决的问题进行清楚地陈述,要从客户的角度来描述问题。 2 需求分析:回答做什么!是对所定义问题的深入调查。是达成解决问题的第一步。这一步常常被忽略,但是这是最重要的工作之一。重视需求有助于减少开始编程开发之后的系统变更情况。 3 软件架构(总体设计):这是软件设计的高层部分,是用于支撑更细节的设计的框架。架构的质量决定了系统的概念完整性,继而影响到系统的最终质量。软件架构主要包括如下几方面的内容: 1)程序组织(模块划分) 2)数据设计 3)用户界面设计 4)输入输出 5)错误处理 ……

  31. 构建实践(详细设计): 1 约定。 1)确定编码之前的设计工作。 2)编码过程中对于名称、注释、代码的编写规则。 3)编码时考虑性能因素,具体的描述。 2 团队合作。 1)是独自编程还是结队编程? 2)如何实现各模块的接口? 3 设计。 1)数据结构设计具体描述 2)菜单设计功能需求描述 3)个模块功能设计描述。 编码、集成和测试。

  32. 实例: 选题:简单通讯录管理。 问题描述:一个简单的通讯录应该包含联系人的姓名、住宅电话、移动电话、分组、E-mail等等信息。实现一个简单的通讯录的管理,能够方便快捷的实现查询、插入、更新、删除、备份等等操作。 需求分析: 1)能够方便地查看联系人的信息。 2)能够更新联系人的信息,包括插入、删除、修改等。 3)能够备份通讯录。 4)系统简单,易操作。

  33. 软件架构(总体设计): (1)功能模块设计 (2)模块接口设计 (3)系统流程设计 (4)数据结构设计

  34. 通信录管理 查看通信录 更新通信录 备份通信录 新增联系人 删除联系人 编辑联系人 系统功能:

  35. 排序索引 通信录 menu.cpp SubMenu2 Menu browse.cpp 菜单代码 菜单代码 List edit.cpp file.cpp 排序索引 通信录 排序索引 通信录 Load New 排序索引 记录数 通信录 通信录 排序索引 记录数 是否成功 通信录 Copy Save Edit Delete tel.cpp 主程序模块与其它模块之间的关系结构图 main

  36. edit.cpp sort.cpp 通信录 通信录 排序索引 联系人 通信录 New SortByAlphabet 原名 姓名 Duplicate Input 菜单代码 是否重名 browse.cpp 排序索引 Edit 通信录 Select List Delete 序号 Print 联系人 edit.cpp模块各函数间的关系结构图

  37. file.cpp 通信录 排序索引 Load Save Copy sort.cpp file.cpp模块各函数间的关系结构图 SortByAlphabet

  38. 开始 从数据文件读入通信录到tel数组 显示主菜单界面 查看通信录 备份通信录 更新通信录 退出 显示更新通讯录菜单界面 新增联系人 编辑联系人 删除联系人 返回主菜单 结束 系统流程图

  39. 构建实践(详细设计): 1.数据结构设计。联系人的结构定义如下: typedef struct Telephone { char name[20]; //姓名 int group; //群组:1.朋友 2.同事 3.家人 4.其他 char home[15]; //住宅电话 char mobile[15]; //手机 char email[20]; //Email char add[20]; //地址 char memo[20]; //备注 }Tel;

  40. sort.cpp模块中利用指针数组对通信录排序,排序用的索引结构的定义如下:sort.cpp模块中利用指针数组对通信录排序,排序用的索引结构的定义如下: typedef struct index { int len; //数组长度 Tel *tel[MaxLen]; //指针数组 }Index;

  41. 总复习 数组和指针变量 C语言的指针概念就是内存地址,是内存的编号。数组的每一个元素都有地址,凡是有地址的地方都可以使用指针。 尤其要注意的是:数组名是常量地址,不能变,可以将数组名赋给一个同种类型的指针,通过指针来间接访问数组元素。

  42. 1 数组。读下面的程序,写出输出结果: #include<stdio.h> void main() { int a[8]={10,3,30,5,67,35,2,49}; int z, y, k; z=0; y=7; k=a[z]; do { while((z<y) && (a[y]>=k)) y --; if(z<y) { a[z]=a[y]; z++; } while((z<y) && (a[z]>=k)) z++; if(z<y) { a[y]=a[z]; y=y+1; } }while(z != y); a[z]=k; for(z=0;z<7; z++) printf("%d ",a[z]); printf("\n"); }

  43. 2.字符串实际上是字符数组,结束标志对字符串很重要。读下面的程序,写出输出结果:2.字符串实际上是字符数组,结束标志对字符串很重要。读下面的程序,写出输出结果: #include<stdio.h> int main() { char s1[30]="Hello,"; char s2[20]="every one !"; int i=0; for(i=0; s2[i] !='\0'; i++) { s1[i]=s2[i]; } s1[i]='\0'; printf("%s",s1); return 0; }

  44. 3 结构数组。读下面的程序,写出输出结果: #include<stdio.h> void main() { struct student { char name[10]; int s[4]; }; struct student stu[4]={ {"John",80,70,60,0},{"Rose",90,70,80,0},{"Tom" ,70,50,60,0},{"Total",0,0,0,0}}; int i, j; for(i=0; i<3; i++) { for(j=0; j<3; j++) stu[i].s[3] += stu[i].s[j]/3; printf("%d,",stu[i].s[3]); } printf("\n"); }

  45. 4 用指针变量访问数组元素:读下面程序,写出输出结果 • #include<stdio.h> • int sum(int *,int); • int main() • { • int x1=0,x2=0,w=0; • int a[ ]={1,2,3,4,5,6,7,8,9,10}; • int *q=NULL; • x1=3; x2=6; • q = a+x1-1; • w = x2-x1+1; • printf("%d\n",sum(q,w)); • return 0; • } • int sum(int *p, int ww) • { • int b=0; • for(int i=0; i<ww; i++) • { b += *p; • p++; • } • return b; • }

  46. 文件 文件是数据集合。这里涉及的文件是保存在计算机外存储器(如磁盘)上以“文件名”存取的数据集合。 按数据格式分,文件可分为文本文件和二进制文件两种。按计算机数据的实质,所有文件都是二进制(字节流)文件。 对文件的操作主要有:打开、关闭、读、写、文件定位等等。

  47. 例1 写一个程序计算文件myfile.txt中的字母、数字和其他字符的个数。 分析:从文件里一个一个字符读出来(就象从键盘上一个一个字符输入一样),每读一个字符就立即统计字母、数字及其它字符的个数。 算法: (1)以“只读”方式打开文件myfile.txt (2)设三个变量分别对字母、数字、其它字符计数,并给初值0 (3)当文件不结束时,反复做: ①读一个字符 ②判断这个字符是字母、数字或其它字符,并计数 (4)关闭文件 (5)输出结果。

  48. #include <stdio.h> void main() { FILE *fp; int letters, numbers, other; char c; if( (fp=fopen("d:\\myfile.txt", "rb")) == NULL) { puts("不能打开文件myfile.txt"); return; } letters=numbers=other=0; while( (c=fgetc(fp)) != EOF ) //读出字符,如果不是文件结束字符则循环做 if( c>='0' && c<='9' ) ++numbers; else if( (c>='A' && c<='Z' ) || (c>='a' && c<='z' )) ++letters; else ++other; fclose(fp); puts("统计结果:"); printf( "字母数:%d\n数字数:%d\n其它字符数:%d\n", letters, numbers, other); }

  49. 例2 写一个程序计算文件 “data.txt”的行数. 分析:什么叫“一行”?其实就是用了一个“回车键”或文件结束。回车键由两个字符组成,一是回车(ASCII为13='\r')二是换行(ASCII为10='\n'),它们成对出现,因此只需判断其中一个即可。文本的行数比回车键的个数多1,只需要给计数器(一个变量)的初值赋1而不是0(换言之,任何一个文件至少有一行). 算法: (1)以“只读”方式打开文件data.txt (2)行数计数器给初值1 (3)当文件不结束时,反复做: ①读一个字符 ②如果是回车则行数增1 (4)关闭文件 (5)输出结果。

More Related