综合实训
1 综合实训的目的
综合实训是C语言程序设计教学过程中一个重要的实践性环节,是在学生学习完C语言程序设计课程后进行的一次全面的综合练习。在C语言程序设计的教学中,除了要求学生熟练掌握程序设计语言的语法,更重要的是培养学生提高程序设计分析能力、动手编程能力、自学和创新能力等。一般来讲,综合实训应该比课程教学实验复杂一些,要求所涉及的内容应该有一定的深度和广度,并更加接近现实应用。通过综合实训练习,帮助学生系统掌握该门课程的主要内容,培养学生实际分析问题、编程和动手能力。
综合实训围绕课程的整体教学目标进行,设计题目具有一定的综合性和应用性。综合实训强调理论与实际相结合,将理论如何应用于实际是核心问题。要完成好综合实训,就要将理论教学中涉及到的知识点贯穿起来,对不同的数据类型、程序控制结构、数据结构进行比较和总结,结合设计题目进行综合性应用,达到在实践中学习知识、掌握知识、应用知识和培养能力的目的。
通过综合实训,学生在下述各方面的能力应该得到锻炼:
? ? ? ?
综合使用所学过的C语言程序设计知识,掌握结构化程序设计的基本思路和方法,加深对C语言基本要素和控制结构的理解。
通过查阅手册和文献资料,培养系统理解、综合运用C语言知识分析问题和利用计算机求解问题的能力。
利用所学的基本知识和技能,开发小型应用程序,培养数据处理的综合能力。 结合课程的教学内容循序渐进地进行设计方面的实践训练,以获得软件开发的经验,并加强与其它相关课程的横向联系及其应用,为后续课程的学习和毕业设计奠? ?
定基础。
及时巩固已学知识,对于给定的设计题目,考虑如何进行系统分析,建立相应的数学模型,从而提高自身的专业综合素质。 熟练应用自顶而下的计算思维方法,将大问题模块化,领会结构化程序设计的精髓;培养独立思考、阅读和编写程序的能力,积累编程经验,打下良好的计算机应用基础。 ? ? ? ?
学习设计软件的思维方法。培养从全局考虑问题的模块化思维方法,培养设计单个模块算法的逻辑化思维方法,培养产生多种设计方案的发散性思维方法。 掌握程序的局部测试与系统测试的方法,掌握在集成环境下如何设置断点进行单步调试或分块调试的方法。
获得相关项目管理和团队合作等众多方面的具体经验,培养学生在项目开发中的团队合作精神、创新意识及能力。
培养学生良好的程序设计风格及书写程序设计开发文档的能力。
2 综合实训的要求
综合实训步骤的规范不但可以培养学生科学的工作方法和作风,而且还能有效地减少错误,提高工作效率。因此必须严格执行良好的实验步骤规范。综合实训的要求是:
?
对系统进行功能模块、控制模块分析,可以加其他功能修饰,使程序更加完善、合
理,画出功能模块图。 ? ? ? ? ? ? ?
采用模块化程序设计方法,程序尽量局部化和模块化。
利用C语言面向过程的编程思想来完成系统的设计,突出C语言的函数特征,采用多个函数实现各个子功能。
程序流程图要清晰,数据类型和数据结构要详细定义,要注意浮点运算的误差。 算法要简洁明了、少使用技巧,尽量避免使用多重循环嵌套或条件嵌套结构。 充分利用库函数,系统设计要实用,编程简练,输入输出操作能给用户必要的提示,功能全面可用,能够实现友好的交互。
说明书、流程图要清楚,记录设计情况为编写设计说明书作好准备。
源程序采用锯齿型书写格式,要求注释细致,采用较好的缩进格式,要求上机调试通过,设计报告按规定格式书写。
3 综合实训的过程
C语言综合实训的过程主要包括5个步骤,即程序的功能分析、数据结构设计、算法分析与设计、函数设计、编码及调试等,各个步骤都有其特定的任务。
3.1 功能分析
C语言程序设计属于结构化程序设计,采用的是自顶向下逐步细化的设计方法。功能分析就是为实现系统目标而设置的,它的任务是根据综合实训题目的描述和要求,确定程序要实现的功能,然后将这些功能分解和细化,划分成不同的层次并确定各层功能的上下级关系。
3.2 数据设计
程序的数据设计主要包括:
(1)确定程序中所用数据的数据类型。
(2)确定程序中数据元素之间的关系,选择所用的数据结构,如:数组、链表等。 (3)对程序中用到的结构体数据定义其结构体类型。 (4)定义程序中使用的全局变量、外部变量等。 (5)定义程序中通用的符号常量。 3.3 算法设计与分析
算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令。算法的设计取决于数据(逻辑)结构,算法的实现依赖于采用的存储结构。算法设计与分析的方法很多,如递推法、递归法、穷举法、迭代法等。同一个问题可选用不同的算法解决,但不同的算法对程序的执行效率影响却很大。
3.4 函数设计
综合性的程序一般应分为若干个程序模块,每一个模块用函数来完成一个特定的功能。为了使总体设计协调有序地进行,需要在程序编码之前,对主要的函数做出预先设计,即函数设计。
首先根据功能分析,确定各项功能要使用的主要函数;然后进行函数定义,包括:函数名称、函数功能、函数参数、函数返回值类型等。有些函数之间存在调用和被调用关系,在进行函数定义时需要注意顺序问题,有的函数先定义,有的函数后定义。函数间的调用关系要明确,选择合适的函数调用方式实现调用。
3.5 编程及调试
程序编程及调试是实现程序功能的核心阶段,需要注意以下问题:
(1)综合实训具有一定的综合性,其程序通常由多个函数构成,每个函数都有独立的功能,实现特定的操作。但程序中的所有函数都是围绕实现程序的功能进行设计的。
(2)在程序设计中往往根据需要确定若干模块,分别由一些函数来实现。有的函数在程序设计前的函数设计阶段就被考虑到了,而有的函数是在程序设计过程中因需要才产生的。但无论哪一个函数,都会经历由简单,到功能完善定型的过程。
(3)程序设计一般以功能实现为主线,每一个函数完成相应功能之后,都要立即进行函数功能测试,直到确认函数的功能无误为止。
(4)整体调试是在前期程序设计调试基础上进行的,它是程序设计的必要阶段。整体调试时需要准备一个较大规模的数据集,按照综合实训题目的功能要求,对组装完成的程序逐项进行功能测试和调试,直到满足要求。
4 综合实训的内容
综合实训的内容共有十五组题目,每组有三道大题。每组题中的第一、二题多为应用类题目,第三题为综合类题目,涉及循环、数组、函数、链表等主要知识点。
教学中可将学生每3~5人分为一小组,每小组选择其中一组题目(不同组尽量选不同题目)。每组选题后应根据题目进行进一步的任务分解,形成设计模块后再进行组内分工,建议每组设组长、副组长各一名,共同领导小组内其他成员,并向指导教师反馈实施进度。组长主要负责本组工作的组织、计划的制定、分配、实施以及进程监控与协调工作;副组长主要负责质量保证工作,包括及时发现分析、设计、编码、测试、文档建设等实施阶段的问题并及时提供协调、审查以及提交相应的解决方案、保管各类资料等。
每组学生选题后针对课题依据综合实训的过程完成以下工作: (1)写出每个模块的设计思想
(2)画出每个函数的流程图或N-S图 (3)编写源程序
(4)静态检查程序和上机调试程序,写出调试报告
(5)综合程序。在完成(1)~(4)点的基础上,将每组中的三道题目,组合成一个程序(以命令菜单的方式,供用户选择每题实现的功能),并进行调试。
综合实训以课题组形式组织,每名学生应有计划、有步骤地进行,设计过程中不得从事其他活动,组员应严格服从分派、协作管理。
第一组
1. 用牛顿迭代法解方程
求解任意的三次方程:
ax3+bx2+cx+d=0
要求a,b,c,d从键盘输入,使用循环方法编程。
【编程提示】
令f(x)= ax3+bx2+cx+d=((a*x+b)*x+c)*x+d。求出方程的表达式f(x)的导数f1(x)=(3*a*x+2*b)*x+c。计算曲线上的点(x0,f(x0))的切线与x轴的交点x:
x=x0-f(x0)/f1(x0)
任取初始点x,在循环中进行迭代:
x0=x
x=x0-f(x0)/f1(x0)
依次继续,直至x与x0的差满足指定精度要求为止。 2. 万年历
使用函数方法编写程序。要求当用户输入年份时能输出该年的日历,在日历上能够看出某天是星期几,可以显示任意一年任意一天,并能够知道是否是闰年等。
【编程提示】
用数组表示各个月份的天数;接收用户输入的年份,调用函数进行计算,算出该年之前的天数;依据输入的年份判断是否是闰年,计算该年各月的天数,并按照每排输出两个月的格式将日历存入数组。 3. 学生成绩管理
有n个学生,每个学生有m门成绩。每个学生的m门成绩用一单链表实现,n个学生所对应n个单链表的头指针用一指针数组统一存放。要求:
(1)建立该存贮结构;
(2)查找第i个学生的某门课成绩; (3)删除第i个学生的某门课成绩。 【编程提示】
将学生当作一个结点,类型为结构体,结构体中包含学生的属性和结点指针。定义链表中学生结点的结构为:
struct node
{ char course[40];/*课程名*/ float sco;/*该门课程的成绩*/
struct node *link;/*指向下一课程结点的指针*/
}
查找某个学生的某门课的成绩,应先在指针数组中查找头指针,然后从头结点开始按课程名查找,比较课程名可用字符串比较函数strcmp()来实现。删除某个结点时,首先按课程名查找该门课对应的结点,如果没找到则输出没找到信息。如果找到则分三种情况讨论:该结点为头结点时,修改原头结点所指向的结点为新的头结点,同时更新头指针数组;该结点为中间结点时,修改该结点的前一结点的指针使其指向该结点的后一结点;该结点为尾结点时,修改原尾结点的前一结点为新的尾结点;最后释放该结点。
第二组
1. 层叠方阵
起始数放在方阵的左上角,然后从起始数开始先在同行后在同列递增,层层折叠地排列为层叠方阵。如下图为起始数是1,行数是5的层叠方阵。
使用数组方法设计程序,打印输出起始数为a,行数为m(a,m从键盘输入确定)的层叠方阵。
1 2
4 3
9 8
5 6 7
10 17 11 18 12 19
16 15 14 13 20 25 24 23 22 21
【编程提示】
设置变量n从a开始,依次增1。然后根据层叠方阵的特点给二维数组z[x][y]赋值。第i层(i=2,3,…,m)的起始位置为(1,i),随后列号y不变行号x递增,至x==i时转折,行号x不变列号y递减,至y==1时该层结束,每一位置递增的n赋值给z[x] [y]。 2. 出售金鱼
买买提将养的一缸金鱼分五次出售:第一次卖出全部的一半加二分之一条;第二次卖出余下的三分之一加三分之一条;第三次卖出余下的四分之一加四分之一条;第四次卖出余下的五分之一加五分之一条;最后卖出余下的11条。问原来的鱼缸有几条金鱼?使用循环方
法求解。
【编程提示】
题目中所有的鱼是分五次出售的,每次卖出的策略相同:第j次卖剩下的(j+1)分之一再加1/(j+1)条。第五次将第四次余下的11条全卖了。假定第j次鱼的总数为x,则第j次留下:x-(x+1)/(j+1)。当第四次出售完毕时,应该剩下11条。若x满足上述要求,则x就是题目的解。注意:(x+1)/(j+1)应满足整除条件。 3. 简易通讯录
使用单链表建立一个简易通讯录,要求:
(1)每条记录包含姓名、电话,建立该存贮结构; (2)查找指定姓名的结点,若找到,返回该姓名的电话;
(3)在指定姓名的结点之前插入一个新的结点,若表中没有该结点,则将要插入的结点插入表尾。
【编程提示】
将每条记录当作一个结点,类型为结构体,定义链表中记录结点的结构为:
struct node
{ char name[40];/*姓名*/
char tele[20];/*电话*/
struct node *link;/*指向下一结点的指针*/
}
按照姓名查找电话,可从头结点开始循序查找,比较姓名可用字符串比较函数strcmp()来实现。插入新结点时,如果表中没有指定结点,则将尾结点的指针指向新结点。如果表中有指定结点,则分两种情况讨论:该指定结点为头结点时,则修改新的结点的指针使其指向头结点;该结点为其他结点时,则修改新结点的指针使其指向指定结点,修改指定结点的前一结点的指针使其指向新结点。
第三组
1. 梅森素数
形如2n-1的素数称为梅森素数,这里指数n是一个素数。例如22-1=3,23-1=7都是梅森素数。
使用循环设计程序,求出指数n<30的所有梅森素数。
【编程提示】
设置指数(2≤n<30),t=2;通过t*2求t=2n;然后用试商法判断素数。
2. 大赛现场统分
某大奖赛有n个选手参赛,m(m>2)个评委为依次参赛的选手评判打分:最高10分,最低0分。统分规则为:每个选手所得的m个评分中,去掉一个最高分,去掉一个最低分,然后平均为该选手的最后得分。根据n个选手的最后得分从高到低排出名次表,以便确定获奖名单。使用数组方法实现程序设计。
【编程提示】
定义3个数组:sh[i]为第i个选手编号,f[i][j]为第j个评委给第i个选手的评分,sf[i]为第i个选手的最后得分。对第i个选手,将每个f[i][j]累加到sf[i]中,然后求最后得分sf[i]=(sf[i]-max-min)/(m-2),将n个选手的最后得分sf[i]根据冒泡法从高到低排序后输出。 3. 工资管理
使用单链表建立一个简易工资表,要求:
(1)每个结点包含职工工号、姓名、应发工资等,建立n个结点(结点数据域的值由