程序设计报告
(2012 / 2013 学年第一学期)
题目:学分和绩点计算器
专业教育技术学
(网络教育和知识工程)
学生姓名吴鹏
班级学号 B11140220
指导教师李鹏
指导单位计算机学院
计算机系统与网络教学中心日期 2012.12.10-2012.12.18
学分和绩点计算器
一、课题内容和要求
所选题目0:学分和绩点计算器
1.课题内容
@设计目的:
用C或C++语言开发一个能够自动计算适合于南京邮电大学学生使用的所获学分和绩点的计算器。并且该绩点计算器能够保证良好的扩展性能。
(1)基本掌握面向过程程序设计的基本思路和方法;
(2)达到熟练掌握C语言的基本知识和技能;
(3)能够利用所学的基本知识和技能,解决简单的程序设计问题
@程序功能:
(1)学生基本信息及成绩所选科目成绩的录入。
(2)基本信息的查询与修改。
(二)课题要求
1. 基本要求。
(1) 输入课程名、学分和成绩,通过绩点计算公式计算相应的绩点,满足如下要求:
根据南京邮电大学的本科生《南京邮电大学学生学籍管理办法》规定:为反映学生学习的质量,采用学分绩点制的学习质量评定方法。学生学分绩点以平均学分绩点(GPA) 表示,其计算方法如下:
(课程名,学分,成绩,等级,绩点)
低于60分折合为0绩点,不及格折合为0绩点
60—69 分折合为1.0—1.9绩点,及格折合为1.5绩点;
70—79 分折合为2.0—2.9绩点,中等折合为2.5绩点;
80—89 分折合为3.0—3.9绩点,良好折合为3.5绩点;
90—100分折合为4.0—5.0绩点,优秀折合为4.5绩点。
平均学分绩点(GPA) = ∑(课程学分数×绩点数×K
(课程数))
∑课程学分数
平均学分绩点分为学年平均学分绩点和累积平均学分绩点:即按学年结算的平均学分绩点称为学年平均学分绩点;从入学后累积结算的平均学分绩点积为累积平均学分绩点。
(2) 判断所获得的绩点是否合格,能给出相应的结果提示;
(3) 程序操作友好、界面美观。
2. 扩展要求。
(1) 从文件中读取课程的学分与成绩,并保存绩点计算的结果;并根据排序算法排序,给出每门课程所获得的绩点。
(2) 实现绩点的预警功能。如按照班级(或者专业)的学分统计查询功能,从文件读入多个学生的学分绩点,按照总的绩点排序。
二、需求分析
管理系统工作原理图(简图):
(1)界面美观的友好操作系统:简洁、明了、直观的友好操作系统,将文件中已经写好的菜单打印在显示屏幕上,指导操作者进行下一步操作。同时根据操作者的选择,进行相关信息的调用或存储。
(2)信息的载入与修改:以文本形式打开,并修改相关信息。在事先文本不存在的情况下,提示用户文本不存在,并重新创建一个新的文本文档student.doc。(3)查找:根据用户对菜单项的选择,调用已经存储的用户信息,按照选项指令(学号,姓名,绩点)进行相关大类或更为详细的查找,调用所需学生信息进行查看或进一步编辑。
(4)插入:创建新的学生信息,并写入已经存在的文本中。同时建立新的链表结点,方便以后对该创建信息的管理。
(5)删除:调用已经存在的文本中的信息后,若该信息不再需要,用户希望删除该信息,则用户可以下达指令,通过链表对该信息进行删除。
(6)修改:调用已经存在的文本中的信息后,若该信息有新的变动,用户希望修改该信息,则用户可以下达指令,通过链表对该信息进行修改。
(7)保存:所有信息在用户进行编辑以后,将自动以文本形式进行保存,以免数据的丢失造成不必要的损失。
(8)备份:通过文件格式读写函数,将源文件信息写到客户提供的目标文件中。(9)排序:根据需要,在用后输入学生信息后,系统将通过冒泡排序法自动按照绩点的高低对所有信息进行排序。
(10)制表打印:所有信息采编完毕后,当客户通过菜单选项在屏幕上输出所有信息时,程序将自动进行排版,并以表格的形式在屏幕上输出,方便客户的阅览。
三、概要设计
主要结构体:
(1)学生信息结构
struct Student //定义学生信息结构
{
long num; //学生学号
char name[20]; //学生名字
char sex[10]; //学生性别
float GPA; //学生绩点
};
typedef struct Student Type; //将学生信息结构重新定义为Type
(2)学生绩点计算结构
{省略
{省略
sum_score+=score; //计算总成绩
sum_GPA+=score*level; //计算总绩点
}
GPA=sum_GPA/sum_score; //计算平均绩点
}
(3)系统的操作函数
1、输入函数:其中包括学生的姓名、学号以及学生的考试科目、成绩、绩点等相关信息;可用GPA计算器源程序代码来实现此操作。
2、查询函数:可用struct node *searchManage(struct node *head)来实现。找到就输出此学生全部信息包括学生的学号、姓名、性别以及GPA。
3、编辑函数:可用insert( )函数来实现。其中通过学号的大小来比较的,并且以此来排序。
4、输出函数:GPA=sum_GPA/sum_score函数进行学生GPA的计算,head=readFile(head)调用学生个人信息及GPA信息
5、退出函数:可用一个函数exit()来实现,首先将信息保存到文件中,释放动态创建的内存空间,再退出此程序
(4)输入与写入文件
1、函数原型:scanf(“%d”,&) fprintf(fp,“%ld%s%s”, stu[i].studentID,stu[i].studentName,stu[i].studentSex),
2、功能:scanf()函数利用取地址符号&完成对程序中某个变量的赋值进而程序中判断循环的功能。 Fprintf()函数利用write将数据写入文件中
3、变量及类型:int n,m: 整型形参变量,接收函数传过来的数字。
int i,j,k:循环控制变量。
4、说明:输入字符后需要按回车键 待系统做出判断后往下执行。
四、详细设计
GPA计算器源程序代码
#include
#include
#include
void main()
{
system("color 75");
float sum_GPA=0.0,GPA=0.0,level=0.0,sum_score=0.0,score=1.0;
int grade=0,n=0,i=0,k;
char a[20],d;
char Wupeng;
char name[20];
char ID[20];
printf("************************************************************\n");
printf("**** 欢迎您使用 ****\n");
printf("**** ****\n");
printf("**** 南京邮电大学学生GPA管理系统 ****\n");
printf("**** ****\n");
printf("**** 本系统由B11140220 吴鹏制作 ****\n");
printf("************************************************************\n");
printf("输入科目数:\n");
scanf( "%d", &n );
getchar(); //这个GETCHAR把前一个输入的回车滤掉。不明白可以删掉试一试
printf( "添加一个学生?[Y/N] " );
Wupeng= getchar();
while( Wupeng != 'N' && Wupeng != 'n' ){ //如果输入的不是'N'或'n‘就继续添加
printf("请输入学生姓名:\n");
scanf("%s",&name);
printf("请输入学生学号:\n");
scanf("%s",&ID);
if(n<11&&n>0)
{
for(i=0;i { printf("请输入第%d课课程名:\n",i+1); scanf("%s",a); printf("若学科为分数制,请按 scanf("%s",&d); if(d=='F') { printf("请输入%s学科学分(1-6):\n",a); scanf("%f",&score); if(score>=0&&score<=6) { printf("请输入您的分数:\n"); scanf("%d",&grade); if(grade>=60&&grade<=100) { grade-=50; level=(float)grade/10; printf("%s绩点为%.2f\n",a,level); }else if(grade>=0&&grade<60) { printf("不及格,绩点为0\n"); level=0; } else { printf("score输入错误!\n");} } }else { if(d=='D') { printf("请输入%s学科学分(1-6):\n",a); scanf("%f",&score); printf("若为优秀,则按<1>,若为良好,则按<2>,若为中等,则按<3>,若为及格,则按<4>, 若为不及格,则按<5>\n"); scanf("%d",&k); if(k==1) { printf("%s成绩为优秀,绩点为4.5\n",a); level=4.5; } if(k==2) { printf("%s成绩为良好,绩点为3.5\n",a); level=3.5; } if(k==3) { printf("%s成绩为中等,绩点为2.5\n",a); level=2.5; } if(k==4) { printf("%s成绩为及格,绩点为1.5\n",a); level=1.5; } if(k==5) { printf("%s成绩为不及格,绩点为0\n",a); level=0; } }else { getchar(); printf("error\n"); i=i-1; continue; } } sum_score+=score; sum_GPA+=score*level; } GPA=sum_GPA/sum_score; printf("您的平均GPA分数为%.2f:\n",GPA); } printf("\n"); printf("*****************************您的结果*********************************\n"); printf("\n"); printf("姓名: %s\n",name); printf("学号: %s\n",ID); printf("平均GPA:%.2f:\n",GPA); if(GPA<1.8) printf("您的成绩低于南京邮电大学合格绩点,请注意1\n"); else printf("您的成绩已达南京邮电大学合格绩点,请继续保持!\n"); printf( "添加一个学生?[Y/N] " ); getchar(); Wupeng = getchar(); } } GPA管理系统源程序代码 /*node.h*/ #ifndef _NODE #define _NODE struct Student { long num; char name[20]; char sex[10]; float GPA; int total; int rank; }; typedef struct Student Type; const int sizeStu=sizeof(Type); struct node { Type data; struct node*next; }; const int size=sizeof(struct node); #endif /*prepare.h*/ #ifndef _PREP #define _PREP #include"node.h" #include void printNode(Type data) { printf("%8ld",data.num); printf("%8s",https://www.doczj.com/doc/7e2065096.html,); printf("%8s",data.sex); printf("%10.2f",data.GPA); printf("\n"); void readNode(Type *pdata) { printf("输入一个学生的信息\n"); printf("学号:\n"); scanf("%ld",&pdata->num); printf("姓名:\n"); scanf("%s",pdata->name); printf("性别:\n"); scanf("%s",pdata->sex); printf("请输入该学生的绩点:\n"); scanf("%f",&pdata->GPA); } int endWith(Type data) { return data.num==0; } int equal(Type data1,Type data2,int condition) { if(condition==1) return data1.num==data2.num; else if(condition==2) if(strcmp(https://www.doczj.com/doc/7e2065096.html,,https://www.doczj.com/doc/7e2065096.html,)==0) return 1; else return 0; else if(condition==3) return data1.rank==data2.rank; else return 1; } int larger(Type data1,Type data2,int condition) { if(condition==1) return data1.num>data2.num; if(condition==2) return data1.total>data2.total; return 1; } #endif /*file.h*/ #include #include #include"list.h" void createFile() { Type data; FILE *fp; if((fp=fopen("D:\\student.dat","wb"))==NULL) { printf("打开学生信息失败!\n"); exit(0); } printf("读取学生信息直到学号为0结束\n"); readNode(&data); while(!endWith(data)) { fwrite(&data,sizeStu,1,fp); readNode(&data); } fclose(fp); } struct node *readFile(struct node *head) { Type data; FILE *fp; head=NULL; if((fp=fopen("D:\\student.dat","rb"))==NULL) { printf("文件打开失败,请先创建文件!\n"); return(0); } fread(&data,sizeStu,1,fp); while(!feof(fp)) { head=InsertOrder(head,data,1); fread(&data,sizeStu,1,fp); } fclose(fp); return head; } void saveFile(struct node*head) { struct node *p=head; FILE *fp; if((fp=fopen("D:\\student.dat","wb"))==NULL) { printf("打开失败!\n"); exit(0); } if(head==NULL) { printf("\n无记录!\n"); return; } while(p) { fwrite(&p->data,sizeStu,1,fp); p=p->next; } fclose(fp); } /*list.h*/ //链表操作的完整程序 #ifndef _LIST #define _LIST #include"prepare.h" //文本包含,对节点数据域为Type类型 struct node *CreateBackward(); //后插法新建链表 struct node *CreateForward(); //前插法新建列表 struct node *CreateInsert(); //按序插入法新建列表 struct node *printList(struct node *head); //列表的遍历 struct node *SearchNode(struct node *head,Type data,int condition); //单链表的查找 struct node *InsertAfter(struct node *head,Type data); //尾部插入 struct node *InsertOrder(struct node *head,Type data,int condition); //有序插入 struct node *Delete(struct node *head,Type data); //删除节点 struct node *Reverse(struct node *head); //单链表逆置 struct node *printList(struct node *head) { struct node *p; if(head==NULL) { printf("\n无信息!\n"); return NULL; }for(p=head;p;p=p->next) //p从头指针开始,每循环一次后移动1节点printNode(p->data); //p非空时执行循环体,调用printNode函数 printf("\n"); //节点的元素值,最后换行 return head; } struct node *CreatBackward() //后插法新建列表 { struct node *head,*p,*tail; //tail定位当前列表最后一个节点位置 Type data; head=NULL;tail=NULL; //链表未建立时对头指针和尾指针进行清零处理 printf("Input data end with 0:"); readNode(&data); //调用readNode输入一个节点的数域的值 while(!endWith(data)) //endWith(data)函数值为真时结束链表节点的生成 { p=(struct node *)malloc(size); //利用指针p申请新节点的动态空间 p->data=data; //数据域赋值 p->next=NULL; //新节点的指针域赋值 if(head==NULL) //初始链为空,需要修改头指针 head=p; else //链非空时,将p置于tail所指节点之后 tail->next=p; tail=p; //使tail指向新的链尾,便于下次插入 readNode(&data); } return head; } struct node *CreatForward() //前插法新建列表 { struct node *head,*p; Type data; head=NULL; //链表未建立时对头指针进行清零处理 printf("Input data end with 0:\n"); readNode(&data); //调用readNode输入一个节点的数据域的值while(!endWith(data)) //endWith(data)函数值为真时结束链表节点的生成 { p=(struct node *)malloc(size); //利用指针p申请新节点的动态空间 p->data=data; // p->next=head; head=p; readNode(&data); } return head; } struct node *SearchNode(struct node *head,Type data,int condition) { struct node *p=head; if(head==NULL) { printf("\n无记录!\n"); return 0; } while(p&&!equal(p->data,data,condition)) { p=p->next; } if(p) return p; return 0; } struct node *InsertAfter(struct node *head,Type data) { struct node *p,*p1; p=(struct node *)malloc(size); p->data=data; p->next=NULL; if(head==NULL) { head=p; return head; } p1=head; while(p1->next) { p1=p1->next; } p1->next=p; return head; } struct node *InsertOrder(struct node *head,Type data,int condition) { struct node *p,*p1,*p2; p2=head; p=(struct node *)malloc(size); p->data=data; p->next=NULL; if(head==NULL) { head=p; return head; } while(p2&&larger(p->data,p2->data,condition)) { p1=p2; p2=p2->next; } if(head==p2) head=p; else p1->next=p; p->next=p2; return head; } struct node *CreateInsert() { struct node *head; Type data; head=NULL; printf("Input data end with 0:\n"); readNode(&data); while(!endWith(data)) { head=InsertOrder(head,data,1); readNode(&data); } return head; } struct node *Delete(struct node *head,Type data) { struct node *p=head,*q=NULL; if(head==NULL) { printf("\n无记录!\n"); return head; } while(p&&!equal(p->data,data,1)) { q=p; p=p->next; } if(p) { if(q) q->next=p->next; else head=head->next; free(p); } else printf("无此信息!\n"); return head; } struct node *Reverse(struct node *head) { struct node *p=head,*q; head=NULL; while(p) { q=p->next; p->next=head; head=p; p=q; } return head; } #endif /*wupeng.c*/ //主程序 #include #include #include"file.h" void printHead() //打印表头函数 { printf("%8s%10s%8s%8.2f \n","学号","姓名","性别","绩点\n"); } void menu() //一级菜单函数 { printf("************************************************************\n"); printf("**** 欢迎您使用 ****\n"); printf("**** ****\n"); printf("**** 南京邮电大学学生GPA管理系统 ****\n"); printf("**** ****\n"); printf("**** 本系统由B11140220 吴鹏制作 ****\n"); printf("************************************************************\n"); printf(" ********1.显示基本信息********\n"); printf(" ********2.基本信息管理********\n"); printf(" ********3.考试成绩统计********\n"); printf(" ********0.退出********\n"); } void menuBase() //基本信息管理的二级菜单 { printf(" ********1.插入学生记录********\n"); printf(" ********2.删除学生记录********\n"); printf(" ********3.修改学生记录********\n"); printf(" ********0.返回上层菜单********\n"); } void menuSearch() //根据条件查询的二级菜单 { printf(" ********1.按学号查询********\n"); printf(" ********2.按姓名查询********\n"); printf(" ********0.返回上层菜单******\n"); } struct node *baseManage(struct node *head) //基本信息管理模块的实现 { int choice; Type data; struct node *p; do //实现多次选择二级菜单 { menuBase(); //调用二级菜单显示函数 printf("请选择你想进行的操作:\n"); scanf("%d",&choice); switch(choice) { case 1: readNode(&data); //读入待插入学生记录 head=InsertOrder(head,data,1); break; case 2: printf("请输入需要删除的学号:\n"); scanf("%d",&data.num); //读入学号后进行删除 head=Delete(head,data); break; case 3: readNode(&data); p=SearchNode(head,data,1); //查找是否存在 if(p) p->data=data; //存在则修改 else printf("此人不存在!\n"); break; case 0: break; } }while(choice); //回到二级菜单 return head; } struct node *searchManage(struct node *head) //条件查询模块的实现{ int choice; Type data; struct node *p; do { menuSearch(); printf("请选择您想进行的操作:\n"); scanf("%d",&choice); switch(choice) { case 1: printf("根据学号查询:\n"); scanf("%ld",&data.num); break; case 2: printf("根据姓名查询:\n"); scanf("%s",&https://www.doczj.com/doc/7e2065096.html,); break; case 0: break; } if(choice>=1&&choice<=3) if(p=SearchNode(head,data,choice)) //若找到匹配记录 { printHead(); printNode(p->data); //输出记录 } else printf("该查询不存在!\n"); }while(choice); return head; } struct node *runMain(struct node *head,int choice) //根据选项受main函数调用{ switch(choice) { case 1: printHead(); head=printList(head); //调用显示基本信息 break; case 2: head=baseManage(head); //调用基本信息管理 break; case 3: head=searchManage(head); //调用根据条件查询 break; case 0: break; }return head; } int main() { struct node *head=NULL; //定义头指针 int choice; //输入一级菜单 head=readFile(head); //执行文件打开 if(!head) { createFile(); //创建 head=readFile(head); //读入链表 } do { menu(); printf("请输入你的选择:\n"); scanf("%d",&choice); if(choice>=0&&choice<=5) head=runMain(head,choice); //调用该函数完成系统功能 else