C++课程设计任务书.docx
《C++课程设计任务书.docx》由会员分享,可在线阅读,更多相关《C++课程设计任务书.docx(17页珍藏版)》请在冰豆网上搜索。
C++课程设计任务书
《面向对象程序设计C++》
课程设计指导书
孙静波郭建伟
目录
课程设计的目的与任务…………………………………………………………2
课程设计内容和基本要求………………………………………………………2
课程设计报告要求………………………………………………………………2
成绩考核…………………………………………………………………………3
上机机房与时间按排……………………………………………………………3
题目………………………………………………………………………………4
其它题目…………………………………………………………………………7
附录………………………………………………………………………………13
一、
课程设计的目的与任务
C++是当今最流行的高级程序设计语言之一,应用十分广泛,也是一门复杂的语言,与C语言兼容,既支持结构化的程序设计方法,也支持面向对象的设计方法。
本课程设计是在完成C++程序设计教学后所进行的课程设计,是对学生C++程序设计知识的全面综合训练,把书本上学到的知识用于解决实际问题、培养软件开发工作所需的动手实践能力,包括问题分析、总体结构设计、用户界面的设计、程序设计的基本技能和技巧,以及一整套软件工作规范的训练和团体协作精神的培养。
二、课程设计内容和基本要求
1.问题分析和任务定义
对问题的描述应避开具体的算法和涉及的数据结构,它是对要完成的任务做出明确的回答。
强调的是做什么,而不是怎么做。
2.逻辑设计和数据结构的选择
为操作对象定义相应的数据结构,以面向对象的程序设计的思想方法为原则划分各个模块,定义数据的抽象数据类型。
3.详细设计和编码
算法的具体描述和代码的书写。
4.上机调试
源程序的输入和代码的调试
三、课程设计报告要求【用实验报告纸写】
要求一份完整的设计报告,包括:
需求分析、概要设计、详细设计、调试分析、测试报告等。
具体内容如下:
(1) 需求分析
以无歧义的陈述说明程序设计的任务,强调的是程序要做什么?
明确规定:
•输入的形式和输出、值的范围
•输出的形式
•程序所能达到的功能
•测试的数据:
包括正确的输入和错误的输入及其相应的输出结果
(2) 概要设计
说明程序中用到的所有抽象数据类型的定义,主程序的流程以及各程序模块之间的层次(调用)关系。
(3)详细设计
实现概要设计中定义所有数据类型,对每个操作具体的算法。
(4) 调试分析
内容包括:
•调试过程中遇到的问题并且是如何解决的以及对设计实现的回顾讨论和分析
• 经验和体会等
(5) 用户使用说明
说明用户如何使用你编写的程序,详细列出每一步的操作步骤。
(6) 测试结果
列出测试结果,包括输入的数据和相应的输出数据。
这里的测试数据应该完整和严格,最好多于需求分析中所列。
(7) 附录
应附上带详细注释的源程序(手工书写,不许打印)。
四、成绩考核
(1)课程设计报告书(30分);
(2)程序通过情况(25分)
(3)每天考勤情况(15分);(4)答辩情况(30分)
五、上机机房与时间按排
19周周一至周四上机实践,周五答辩
其余时间,自己写程序与报告书,报告书全部手写不允许复印。
六、题目
下面列出该课程设计的题目,由于学生只学过C++语言,许多专业课程还没有学,所以题目相对较简单。
(1)学生成绩管理系统需求与功能分析
学生成绩的录入、统计、查询、修改、删除、输出。
画出功能结构图。
(2)学生成绩管理系统的数据结构表
序号
成员名(字段名)
数据类型
长度
字段含义
1
class_0
char
20
班级
2
num
int
学号
3
name
char
8
姓名
4
elec
float
电子技术
5
c_prog
float
C++程序设计
6
media
float
多媒体技术
7
eng
float
大学英语
8
math
float
高等数学
9
sport
float
大学体育
10
polity
float
马克思主义政治经济学
11
ave
float
平均成绩
12
order
int
名次
(3)学生成绩管理系统测试数据表
class_0
num
name
elec
c_prog
media
eng
math
sport
polity
ave
order
040401
3033101
马云飞
80
70
60
70
70
60
80
表中其余数据自己编造。
(4)使用结构体数组编写程序
0)定义结构体类型
1)主函数main():
定义学生结构体数组,调用录入、统计等函数对成绩表进行处理;
2)录入函数Input():
输入班级每门功课成绩;
3)统计函数Statistic():
计算平均成绩;
4)查询函数Lookup():
查询指定学号学生成绩记录;
5)修改函数Modify():
修改指定学号学生成绩记录;
6)删除函数Delete():
删除指定学号学生记录;
7)输出函数Output():
输出班级所有学生成绩记录;
8)排序函数Sort():
按平均分对学生成绩记录项进行降序排序;
9)插入函数Insert():
按平均分顺序插入新记录。
10)保存函数Save():
把数据以文件形式保存。
注:
程序要有简单的菜单功能。
如下图:
、
(5)使用链表编写程序
0)定义链表结点
1)主函数main():
定义链表头指针,调用录入、统计等函数对成绩表进行处理;
2)建立链表函数Create():
输入班级的课程成绩信息;
3)统计函数Statistic():
计算平均成绩;
4)查询函数Lookup():
查询指定学号学生成绩记录;
5)修改函数Modify():
修改指定学号学生成绩记录;
6)删除函数Delete():
删除指定学号学生记录;
7)输出函数Output():
输出班级所有学生成绩记录;
8)插入函数Insert():
按平均分顺序插入新结点。
9)保存函数Save():
把数据以文件形式保存。
注:
程序要有简单的菜单功能。
七、其它题目
做完以上题目的同学可以选做以下题目。
1.折半查找。
有15个数按由小到大的顺序放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中的第几个元素的值。
如果该数不在数组中,则打印出“无此数”。
折半查找的思路:
假设一个数组有9个数,a[1]~a[9],其值分别是:
1,3,5,7,9,11,13,15,17。
若输入13,想查找13是否在此数组中,先找出表中居中的数。
即a[5],将13与a[5]比较,发现a[5]<13,显然13应在a[6]~a[9]的范围内。
再找到a[6]~a[9]的范围内的居中数是a[7],把a[7]与13比较,恰好找到。
可以看出,折半查找比顺序查找有更高的效率。
折半查找要求被查找的序列是有序的。
2.打印魔方阵。
所谓魔方阵是指这样的一个方阵,它的每一行、每一列和对角线之和都相等。
例如三阶魔方阵为。
816
357
492
要求打印出由1——n2(n为奇数)的自然数构成的魔方阵。
提示:
魔方阵中各数的排列规律如下:
(1)将第一个数字放在第一行中间
(2)从第二个数开始直到n×n止各数字依次按下列规则存放:
每一个数存放的行比前一个数的行减一,列数加1
(3)如果上一个数的行数为1,下一个数的行数为n(指最下一行)。
列数加1
(4)如果上一个数的列数为n,下一个数的列数为1,行数减1
(5)如果按上面的规则确定的位置上已经有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。
3.输入正整数m,它代表一个人民币钱数(元数)。
求取这样一个方案,使用最少张数的人民币纸币,凑成上述的钱数m,并输出求取结果。
注意,现在共有7种元以上面值的人民币纸币,分别为:
100,50,20,10,5,2,1。
●
●
●
●
●
●
●
●
4.编写程序对八皇后问题进行求解:
在8行8列的棋盘上放置8个皇后,使任一个皇后都不能吃掉其他的7个皇后(注:
皇后可吃掉与她处于同行或同列或同一对角线上的其他棋子),并将结果以某种方式显示出来。
例如,当求出下述的一个解时,可输出如下信息来表示该解(输出了表示摆放皇后的坐标位置以及“棋盘状态”—棋盘中有皇后的位置放一个“Q”字符,其他位置为”+”)。
(1,1)(5,2)(8,3)(6,4)(3,5)(7,6)(2,7)(4,8)
Q+++++++
++++++Q+
++++Q+++
+++++++Q
+Q++++++
+++Q++++
+++++Q++
++Q+++++
提示:
(1)通过“intLineNum[9];boola[9],b[15],c[15];”说明具有全局作用域的4个数组。
其中的:
LineNum[i]表示第i列的皇后要放的行位置(只用其中的列号1到8);
a[i]为true(i=1,2,…,8)表示第i行上尚未放皇后;
b[i]为true(i=0,1,2,…,14)表示第i条斜对角线上尚未放皇后(斜对角线指的是“/”状对角线,该对角线上各点的行列号之和i+j为一个常数);
c[i]为true(i=0,1,2,…,14)表示第i条反斜对角线上尚未放皇后(反斜对角线指的是“\”状对角线,该对角线上各点的行列号之差i-j为一个常数)。
从而当使用语句“if(a[j]&&b[i+j-2]&&c[i-j+7])LineNum[i]=j;”时,可用于判断并实现:
如果在第j行的第i列上放置皇后安全的话,则将一枚皇后放置到那儿。
(2)编制一个具有如下原型的递归函数solve,它负责往第i列开始的连续8-i+1列上均放上皇后,若成功则通过引用参数ok返回true(否则返回false)。
voidsolve(inti,bool&ok);
摆放皇后之后,若i=8即已放满时则递归出口;否则通过solve(i+1,ok);进行递归调用。
(3)编制主函数,首先初始化一个“空棋盘”,即将a、b、c数组的各元素均置为true(表示当前棋盘的8个行、15条斜对角线以及15条反斜对角线上都尚未摆放皇后)。
而后执行调用语句“solve(1,ok);”,它负责往第1列开始的连续8列上均放上皇后,若成功则通过引用参数ok返回true(否则返回false)。
附录:
1.清屏函数
#include
#include
voidClearScreen();
HANDLEhConsoleOut;/*Handletotheconsole*/
CONSOLE_SCREEN_BUFFER_INFOcsbiInfo;/*Consoleinformation*/
intmain(intargc,char*argv[])
{
hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
cout<<"软件学院"<ClearScreen();
return0;
}
voidClearScreen()
{
DWORDdummy;
COORDHome={0,0};
FillConsoleOutputCharacter(hConsoleOut,'',csbiInfo.dwSize.X*csbiInfo.dwSize.Y,Home,&dummy);
SetConsoleCursorPosition(hConsoleOut,Home);
}
2、调用DOS命令
要包含头文件。
#include
例如:
system("cls");//调用cls命令清屏
system("delF:
\\data.doc");//删除文件
system("renameF:
\\file.txtffff.txt");//文件重命名
3、线性表的链式表示和实现
主要内容:
1.线性链表的定义
2.线性链表的存储结构
3.线性表中数据元素的查找、插入和删除,线性链表的创建、合并等算法。
线性表是一种线性结构。
线性结构的特点是数据元素之间是一种线性关系,数据元素“一个接一个的排列”。
在一个线性表中数据元素的类型是相同的,或者说线性表是由同一类型的数据元素构成的线性结构。
在实际问题中线性表的例子是很多的,如学生情况信息表是一个线性表:
表中数据元素的类型为学生类型;一个字符串也是一个线性表:
表中数据元素的类型为字符型,等等。
综上所述,线性表定义如下:
线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列,通常记为:
(a1,a2,…ai-1,ai,ai+1,…an)
其中n为表长,n=0时称为空表。
表中相邻元素之间存在着顺序关系。
将ai-1称为ai的直接前趋,ai+1称为ai的直接后继。
就是说:
对于ai,当i=2,...,n时,有且仅有一个直接前趋ai-1.,当i=1,2,...,n-1时,有且仅有一个直接后继ai+1,而a1是表中第一个元素,它没有前趋,an是最后一个元素无后继。
一.线性链表的基本概念
1.线性表的链式存储结构的特点
用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。
因此,为了表示每个数据元素ai与其直接后继ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的数据信息外,还需要存储其直接后继ai+1的存储位置的信息。
2.概念
●结点(Node):
数据元素除了存储其本身的数据信息外,还需要存储其直接后继元素的存储位置的信息,这两部分信息组成数据元素的存储映象,称为~。
结点包括两个域:
①数据域:
存储数据元素信息的域,称为~。
②指针域:
存储其直接后继存储位置的域,称为~。
●指针(链):
指针域中存储的信息,称为~。
●线性链表(单链表):
n个结点(ai(1≤i≤n)的存储映象)链接成一个链表,即为线性表(a1,a2,…,an)的链式存储结构。
又由于此链表的每个结点中只包含一个指针域,故又称~。
二.线性链表的存储结构
例:
线性表(a,b,c,d,e,f)的链式存储结构。
头指针指示链表中第一个结点的存储位置,整个链表的存取必须从头指针开始进行,同时,由于最后一个数据元素没有直接后继,则线性表最后一个结点的指针域为“空”(NULL)。
【头指针为空,线性链表即为空表。
】
由例中可以看出:
1.线性表由头指针唯一确定。
2.用线性链表表示线性表时,数据元素之间的逻辑关系是由结点中的指针指示的。
换句话说,指针为数据元素之间的逻辑关系映象。
3.在逻辑上相邻的两个数据元素在其存储位置上不要求紧邻,因此,线性表的链式存储结构为非顺序映象(链式映象)。
通常,我们在使用链表时,关心的时线性表中的数据元素的逻辑顺序,而不是每个数据元素在存储器中的实际位置。
因此,我们把链表画成用箭头连接的结点序列。
结点间用箭头表示链域中的指针。
如线性表(a,b,c,d,e,f)可画成如下形式:
H表示头指针。
三.线性链表的描述
在C++语言中,用“结构指针”来描述线性表
在不设“指针”类型的其它高级程序设计语言中,用一维数组来描述线性表。
(一)用“结构指针”描述线性表
1.定义线性链表的存储结构
typedefstructLNode{
ElemTypedata;
structLNode*next;//定义一个指向自身结构的指针
}LNode,*LinkList;
有时,我们在单链表的第一个结点前附设一个结点,称为头结点。
用以代替头指针。
头结点的数据域可以不存储信息,也可以存储诸如线性表长度之类的附加信息。
头结点的指针域存储的是指向线性表第一个结点的指针(即第一个结点的存储位置)。
假设L是LinkList(结构指针)类型变量,并为单链表的头结点,则L的指针域中存储的是指向线性表中第一个结点的指针,若L的指针域为“空”,则表示线性表为“空”表。
如图所示:
2.线性链表的基本操作
在单链表中,任何两个元素的存储位置之间没有固定的联系。
但是,每个元素的存储位置都包含在其直接前驱结点的指针中。
因此,取得第i个数据元素必须从头指针出发开始查找。
假设,p是指向线性表中第i个数据元素ai的指针,则p->next是指向第i+1个数据元素的指针。
即:
p->data=ai;p->next->data=ai+1。
p=p->next的作用是使指针后移。
如图所示:
【有了以上的准备,现在我们讨论对线性表的操作】
(1).查找
【在线性表中查找第i个元素,如果i存在,将其值赋给e,并返回OK,否则返回ERROR。
】
算法:
注:
用status表示函数的返回值。
AERROR和OK可以自己定义。
statusGetElem_L(LinkListL,inti,ElemType&e)
{
p=L->next;//初始化,p指向第一个结点,j为计数器
j=1;
while(p&&j
{//或p为空
p=p->next;
++j;
}//while
if(!
p||j>i)//如果i大于表长或i为负数,则第i个
returnERROR;//元素不存在
e=p->data;
returnOK;
}//GetElem_L
注:
用status表示函数的返回值。
(2).插入
假设我们要在线性表的两个相邻数据元素a和b之间插入数据元素x,已知p为单链表中指向结点a的指针。
为插入数据元素x,首先要生成一个数据域为x的结点,并假设s为指向结点x的指针。
从上图中可以看出,插入操作即为修改指针指向的过程:
令结点a中的指针指向结点x,而结点x的指针指向结点b,从而实现三个元素a,b,x之间的逻辑关系变化。
用语句描述为:
s->next=p->next;p->next=s;
算法:
【在带头结点的单链表L中,第i个位置前插入元素e。
如果成功返回OK,否则,返回ERROR。
】
statusListInsert_L(LinkList&L,inti,ElemTypee)
{
p=L;
j=0;
while(p&&j{
p=p->next;
++j;
}
if(!
p||j>i-1)//未查找到第i-1个节点
returnERROR;
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
returnOK;
}
(3).删除
删除线性表中相邻的三个结点a,b,c中的结点b。
为实现a,b,c之间逻辑关系的变化,仅修改结点a中的指针域即可。
假设p为指向结点a的指针,则修改语句为:
p->next=p->next->next;
可见:
在已知链表中删除元素确切位置的情况下,在单链表中删除一个结点时,仅仅需要修改指针,而不需要移动元素。
算法:
【在带头结点的单链表L中,删除第i个元素,并由e返回其值。
如果成功返回OK,否则,返回ERROR。
】
statusListDelete_L(LinkList&L,inti,ElemType&e)
{
p=L;
j=0;
while(p->next&&j{
p=p->next;
++j;
}
if(!
(p->next)||j>i-1)
returnERROR;
q=p->next;
p->next=q->next;
e=q->data;
free(q);
returnOK;
}
(4).建立单链表
单链表占用的存储空间不需预先分配,可由系统应需要即时生成。
因此,建立线性表链式存储结构的过程是一个动态生成链表的过程。
即从“空表”的初始状态起,依次建立各元素的结点,并逐个插入链表。
a.从表尾到表头逆向建立单链表。
算法:
voidCreateList_L(LinkList&L,intn)
{
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(LNode));
scanf(&p->data);
p->next=L->next;
L->next=p;
}
}
b.从表头到表尾顺序建立单链表。
算法:
voidCreateListSequence_L(LinkList&L,intn)
{
inti;
LinkListp,r;
r=(LinkList)malloc(sizeof(LNode));
r->next=NULL;
L=r;
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(LNode));
scanf(&p->data);
r->next=p;
p->next=NULL;
r=p;
}
}
(5).合并有序表
【假设头指针为La和Lb的单链表分别为线性表LA和LB的存储结构,现在要规并LA和LB得到单链表LC,数据元素按非递减顺序排列。
(已知LA和LB中的数据元素按非递减顺序排列)】
思路:
在归并两个单链表为一个单链表时,不需要另建新的结点空间,只需将原来两个链表中结点之间的关系解除,重新按要求将所有的结点连接成一个链表即可。
设立三个指针pa,pb和pc,其中pa和pb分别指向表LA和LB中当前待比较的结点,而pc指向LC表中当前最后一个结点,若pa->data≤pb->data,则将pa所指结点链接到pc所指结点之后,否则将pb所指结点链接到