学生成绩管理系统-C语言程序设计

C语言课程设计(实训)报告

信息科技学院

学    院   _电子信息学院_   专   业   电子信息工程

班   级 _        _        学   号                  

姓    名                  课    题 _C语言课程设计_

指导教师 __      __       报告成绩______________

    期:20## 77

学生成绩管理系统

本题目设计目的是训练学生的基本编程能力,了解管理信息系统的开发流程,熟悉C语言的文件和单链表的各种基本操作。本程序中涉及结构体、单链表、文件等方面的知识。通过本程序的训练,使学生能对C语言的文件操作有一个更深刻的了解,掌握利用单链表存储结构实现对学生成绩管理的原理,为进一步开发出高质量的管理信息系统打下坚实的基础。

1、问题定义

创建一个学生成绩管理系统。假设系统中每个学生记录只包括学号、姓名、数学成绩、英语成绩、C语言成绩、总分、平均分、等信息。程序的运行效果如下图所示,选择任意菜单后,实现相应功能。

 =================主菜单====================

 ==      1    输入学生信息                     ==

==      2    删除学生信息                     ==

==      3    查询学生信息                     ==

 ==      4    修改学生信息                     ==

 ==      5    显示学生信息                     ==

 ==      6    统计学生信息                     ==

 ==      7    排序学生信息                     ==

==      8    保存学生信息                     ==

 ==      0    退出系统                         ==

============================================

图1.1  学生成绩管理系统功能需求

在问题定义阶段要考虑题目的可行性和需求分析,接下来进入开发阶段,完成系统设计和系统实现的任务。

2、系统设计

2.1 总体设计

采用模块化的程序设计方法,即将较大的任务按照一定的原则分为一个个较小的任务,然后分别设计各个小任务。需要注意的是划分出来的模块应该相对独立但又相关,且容易理解。可以用模块化层次结构图(即模块图)来分析其任务的划分,一般从上到下进行,最上面一层是主模块,下面各层是其上一层模块的逐步细化描述。

 


本成绩管理系统要求采用单链表实现,如图2.1所示,它由如下五大功能模块组成:

l  输入记录模块。完成将数据存入单链表的工作。记录可以从以二进制形式存储的数据文件中读入,也可从键盘逐个输入学生记录。学生记录由学生的基本信息和成绩信息字段构成。当从数据文件中读入记录时,也就是把在以记录为单位存储的数据文件中,将记录逐条复制到单链表中。

l  查询记录模块。完成在单链表中查找满足相关条件的学生记录。在此成绩管理系统中,用户可以按照学生的学号或姓名在单链表中进行查找。若找到该学生的记录,则返回指向该学生的记录的指针。否则返回一个值为NULL的空指针,并打印出未找到该学生记录的提示信息。

l  更新记录模块。完成对学生记录的维护。在此成绩管理系统中,它实现了对学生记录的修改、删除、插入和排序操作,并将修改后的数据存入源数据文件。

l  统计记录模块。完成对各门功课最高分和不及格人数的统计。

l  输出记录模块。一是实现对学生记录的存盘,即将记录写入数据文件中;二是实现将记录信息以表格的形式在屏幕上打印出来。

2.2 详细设计

2.2.1数据结构设计

l  学生成绩信息结构体

struct student

{

char num[10];   /*学号*/

char name[15];  /*姓名*/

int cgrade;     /*C语言成绩*/

int mgrade;     /*数学成绩*/

int egrade;     /*英语成绩*/

int total;      /*总分*/

float ave;      /*平均分*/

};

结构体struct student将用于存储学生的基本信息,它将作为单链表的数据域。为了简化程序,只取了3门成绩。

l  单链表node结构体

typedef struct node

{

struct student data;  /*数据域*/

struct node *next;    /*指针域*/

}Node,*Link;  

这样就定义了一个单链表的结构,data为struct student结构类型的数据,作为单链表结构中的数据域,next为单链表中的指针域,用来存储其直接节点的地址。

2.2.2 主控main()函数执行流程

 


                          

本成绩管理系统执行主流程如图2.2所示。它先以可读写的方式打开数据文件,此文件默认为“D:\student”,若该文件不存在,则新建此文件。当打开文件操作成功后,从文件中一次读出一条记录,添加到新建的单薄链表中,然后执行显示主菜单和进入主循环操作,进行按键判断。

在判断键值时,有效的输入为本0至9之间的任意数值,其他输入都被视为错误按键。若输入为0(即变量select=0),它会继续判断,如果对记录进行过更新操作,那么是否已经保存过新的数据,若没有,则全局变量saveflage=1,系统会提示用户是否需要进行数据存盘操作,用户输入Y或y,系统会自动进行存盘操作后再执行退出成绩管理系统的操作。

若选择1,则调用Add()函数,执行增加学生记录操作;若选择2,则调用Del()函数,执行删除学生记录操作;若选择3,则调用Qur()函数,执行查询学生记录操作;若选择4,则调用Modify()函数,执行修改学生记录操作;若选择5,则调用Insert()函数,执行插入学生记录操作;若选择6,则调用Tongji()函数,执行统计学生记录操作;若选择7,则调用Sort()函数,执行按降序排序学生记录操作;若选择8,则调用Save()函数,执行将学生记录存入数据文件的操作;若输入为0~8之外的值,则调用Wrong()函数,给出按键错误的提示。

2.2.3        输入记录模块

输入记录模块主要实现将数据存入单链表中。当从数据文件中读出记录时,调用fread(p,sizeof(Node),1,fp)文件读取函数,执行一次从文件中读取一条学生成绩记录信息存入指针变量p所指的节点中的操作,并且该操作在main()函数中执行,即当成绩管理系统进入显示菜单界面时,该操作已经执行了。若该文件中没有数据,系统会提示单链表为空,没有任何学生记录可操作,此时,用户应选择1,调用Add()函数,进行学生记录的输入,即完成在单链表l中添加记录的操作。值得一提的是,这里的字符串和数值的输入分别采用了函数来实现,在函数中完成输入数据任务,并对数据进行条件判断,直到满足条件为止,这样一来,大大减少了代码的重复和冗余,符合模块化程序设计的特点。

2.2.4        查询记录模块

查询记录模块主要实现了在单链表中按学号或姓名查找满足相关条件的学生记录。在查询函数Qur(l)中,l为指向保存了学生成绩信息的单链表的首地址的指针变量。为了遵循模块化编程的原则,我们将在单链表中进行的指针定位操作,设计成了一个单独的函数
Node *Locate(Link l,char findmess[],char nameornum[]),参数findmess[]保存要查找的具体内容,nameornum[]保存要查找的字段(值为字符串类型的name或者num),若找到该记录,则返回指向该节点的指针;否则,返回一个空指针。

2.2.5        更新记录模块

此模块主要实现了对学生记录的修改、删除、插入和排序操作。因为学生记录是以单链表的结构形式存储的,所以这些操作都在单链表中完成。下面分别介绍着4个功能模块。

①       修改记录。该操作需要对单链表中目标节点的数据域中的值进行修改,它分两步完成。

第一步,输入要修改的学号,输入后调用定位函数Locate(),在单链表中逐个对节点数据域中学号字段的值进行比较,直到找到该学号的学生记录;

第二步,若找到该学生记录,修改除学号字段之外的各字段值,并将存盘标记变量saveflag置1,表示已经对记录进行了修改,但还未执行存盘操作。

②       删除记录。该操作完成删除指定学号或姓名的学生记录,它也分两步完成。

第一步,输入要删除的学号或姓名,输入后调用定位函数Locate(),在单链表中逐个对节点数据域中学号或姓名字段的值进行比较,直到找到该学号或姓名的学生记录,则返回指向该学生记录的节点指针;

第二步,若找到该学生记录,将该学生记录所在节点的前驱节点的指针域,指向目标节点的后继节点。

③ 插入记录。该操作完成在指定学号的随后位置插入新的学生记录。首先,要求用户输入某个学生的学号,新的记录将插入在该学生记录之后;然后,提示用户输入一条新的学生记录的信息,这些信息保存在新节点的数据域中;最后,将该节点插入在指定位置学号之后。它的具体插入执行过程如图2.3所示,图中q为位置学号所在节点的指针变量,p为q所指节点的后继节点的指针变量,q->next=p,指针变量i指向新记录所在的节点,即为插入节点i,依次执行的操作为:① i->next= q->next;② q->next=i。

 


   

④ 排序记录。有关排序的算法很多,如冒泡排序、插入排序等。针对单链表结构的特点,我们采用插入排序算法实现按总分的从高到低对学生记录进行排序,排序完成之后,即可按顺序给名次字段赋值。在单链表中,实现插入排序的基本步骤如下:

1)  新建一个单链表l,用来保存排序结果,其初始值为待排序单链表中的头节点。

2)  从待排序单链表中取出下一个节点,将其总分字段值与单链表l中的各节点中总分字段的值进行比较,直到在链表l中找到总分小于它的节点。若找到此节点,系统将待排序链表中取出的节点插入此节点前,作为其前驱。否则,将取出的节点放在单链表l的尾部。

3)  重复第二步,直到从待排序链表中取出的节点的指针域为NULL,即此节点为链表的尾部节点,排序完成。

2.2.6        统计记录模块

主要通过循环读取指针变量p所指的当前节点的数据域中各字段的值,并对各个成绩字段进行逐个判断的形式,完成单科最高分学生的查找和各科不及格人数的统计。

2.2.7        输出记录模块

当把记录输出至文件时,调用fwrite(p,sizeof(Node),1,fp)函数,将p指针所指节点中的各字段值,写入文件指针fp所指的文件。当把记录输出至屏幕时,调用void Disp (Link l)函数,将单链表l中 的学生记录信息以表格的形式在屏幕上打印出来。

2.2.8        函数功能描述

l  printheader()

函数原型:void printheader()

printheader()函数用于在以表格形式显示学生记录时,打印输出表头信息。

l  printdata()

函数原型:void printdata(Node *pp)

printdata()函数用于在以表格形式显示学生记录时,打印输出单链表pp中的学生信息。

l  stringinput ()

函数原型:void stringinput (char *t,int lens,char *notice)

stringinput ()函数用于输入字符串,并进行字符串长度验证(长度<lens)。t用于保存输入的字符串,因为是以指针形式传递的,所以t相当于该函数的返回值。notice用于保存printf()中输出的提示信息。

l  numberinput()

函数原型:int numberinput (char *notice)

numberinput()函数用于输入数值型数据,notice用于保存printf()中输出的提示信息,该函数返回用户输入的整型数据。

l  Disp()

函数原型:void printdata Disp(Link l)

Disp()函数用于显示单链表l中存储的学生记录,内容为struct student结构中定义的内容。

l  Locate()

函数原型:Node * Locate(Link l,char findmess[],char nameornum[])

Locate()函数用于定位链表中符合要求的节点,并返回指向该节点的指针。参数findmess[]保存要查找的具体内容,nameornum[]保存按什么字段在单链表l中查找。

l  Add()

函数原型:void Add(Link l)

Add()函数用于在单链表l中增加学生记录的节点。

l  Qur()

函数原型:void Qur(Link l)

Qur()函数用于在单链表l中按学号或姓名查找满足条件的学生记录,并显示出来。

l  Del()

函数原型:void Del(Link l)

Del()函数用于先在单链表l中找到满足条件的学生记录的节点,然后删除该节点。

l  Modify()

函数原型:void Modify (Link l)

Modify ()函数用于在单链表l中修改学生记录。

l  Insert()

函数原型:void Insert (Link l)

Insert ()函数用于在单链表l中插入学生记录。

l  Tongji()

函数原型:void Tongji(Link l)

Tongji()函数用于在单链表l中完成学生记录的统计工作,统计该班的总分第一名、单科第一名和各科不及格人数。

l  Sort()

函数原型:void Sort(Link l)

Sort()函数用于在单链表l中完成利用插入排序算法实现单链表的按总分字段的降序排序。

l  Save()

函数原型:void Save(Link l)

Save()函数用于将单链表l中的数据写入磁盘中的数据文件。

l  主函数main()

整个成绩管理系统控制部分,其详细说明可参考图二。

完成在上述系统设计后,即可着手进行系统实现的工作,开始程序代码的编写。

3、系统实现

3.1 编码

3.1.1 程序预处理

包括加载头文件,定义结构体、常量和变量,并对它们进行初始化工作。

#include "stdio.h"   /*标准输入输出函数库*/

#include "stdlib.h"  /*标准函数库*/

#include "string.h"  /*字符串函数库*/

#include "Conio.h"   /*屏幕操作函数库*/

#include "graphics.h"

#define closegr closegraph

void initgr(void) /* BGI初始化 */

{

  int gd = DETECT, gm = 0; /* 和gd=VGA,gm=VGAHI是同样效果 */

  registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行 */

  initgraph(&gd, &gm, "");

}

void drawmat(char *mat,int matsize,int x,int y,int color)

/*依次:字模指针、点阵大小、起始坐标(x,y)、颜色*/

{

  int i, j, k, n;

  n = (matsize - 1) / 8 + 1;

  for(j = 0; j < matsize; j++)

    for(i = 0; i < n; i++)

      for(k = 0;k < 8; k++)

        if(mat[j * n + i] & (0x80 >> k))  /*测试为1的位则显示*/

          putpixel(x + i * 8 + k, y + j, color);

}

char huan24[]={

/* 以下是 '欢' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,

  0x00,0x00,0x06,0x00,0x00,0x46,0x00,0x3F,

  0xC4,0x00,0x00,0xC4,0x04,0x00,0x8F,0xFE,

  0x20,0x88,0x08,0x11,0x89,0x90,0x09,0x11,

  0x80,0x05,0x21,0x80,0x02,0x21,0x80,0x03,

  0x03,0x80,0x05,0x82,0x80,0x05,0x82,0x40,

  0x08,0xC2,0x40,0x08,0xC4,0x60,0x10,0x4C,

  0x20,0x20,0x08,0x30,0x40,0x10,0x18,0x00,

  0x60,0x0E,0x00,0x80,0x00,0x00,0x00,0x00,

};

char ying24[]={

/* 以下是 '迎' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x02,

  0x00,0x0C,0x0E,0x00,0x06,0x72,0x08,0x04,

  0x41,0xFC,0x00,0x41,0x08,0x00,0x41,0x08,

  0x04,0x41,0x08,0x7E,0x41,0x08,0x04,0x41,

  0x08,0x04,0x41,0x08,0x04,0x41,0x08,0x04,

  0x45,0x08,0x04,0x59,0x08,0x04,0x61,0x78,

  0x04,0x41,0x18,0x04,0x01,0x00,0x1A,0x01,

  0x00,0x71,0x00,0x00,0x60,0xE0,0x02,0x00,

  0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,

};

char shi24[]={

/* 以下是 '使' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,

  0x00,0x03,0x01,0x00,0x03,0x01,0x04,0x02,

  0xFF,0xFE,0x06,0x01,0x00,0x04,0x01,0x00,

  0x0E,0x21,0x18,0x0E,0x3F,0xE8,0x16,0x21,

  0x08,0x26,0x21,0x08,0x26,0x21,0x08,0x46,

  0x3F,0xF8,0x06,0x21,0x00,0x06,0x13,0x00,

  0x06,0x12,0x00,0x06,0x0A,0x00,0x06,0x06,

  0x00,0x06,0x06,0x00,0x06,0x0F,0x00,0x06,

  0x10,0xE0,0x06,0x60,0x3C,0x01,0x80,0x00,

};

char yong24[]={

/* 以下是 '用' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,

  0x10,0x0F,0xFF,0xF8,0x0C,0x08,0x10,0x0C,

  0x08,0x10,0x0C,0x08,0x10,0x0C,0x08,0x10,

  0x0C,0x08,0x10,0x0F,0xFF,0xF0,0x08,0x08,

  0x10,0x08,0x08,0x10,0x08,0x08,0x10,0x08,

  0x08,0x10,0x0F,0xFF,0xF0,0x08,0x08,0x10,

  0x08,0x08,0x10,0x08,0x08,0x10,0x10,0x18,

  0x10,0x10,0x18,0x10,0x20,0x18,0x10,0x20,

  0x18,0xF0,0x40,0x00,0x30,0x00,0x00,0x00,

};

char xue24[]={

/* 以下是 '学' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,

  0x60,0x02,0x10,0x40,0x03,0x18,0xC0,0x01,

  0x18,0x80,0x01,0x11,0x00,0x10,0x02,0x0C,

  0x1F,0xFD,0xFE,0x10,0x00,0x18,0x30,0x00,

  0xA0,0x27,0xFF,0xC0,0x00,0x03,0x00,0x00,

  0x04,0x00,0x00,0x18,0x00,0x00,0x18,0x18,

  0x3F,0xFF,0xE0,0x00,0x18,0x00,0x00,0x18,

  0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,

  0xF8,0x00,0x00,0x30,0x00,0x00,0x00,0x00,

};

char sheng24[]={

/* 以下是 '生' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x1C,

  0x00,0x02,0x08,0x00,0x03,0x08,0x00,0x06,

  0x08,0x00,0x06,0x08,0x10,0x04,0x08,0x18,

  0x0F,0xFF,0xE0,0x08,0x08,0x00,0x18,0x08,

  0x00,0x10,0x08,0x00,0x20,0x08,0x00,0x00,

  0x08,0x20,0x07,0xFF,0xF0,0x00,0x08,0x00,

  0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,

  0x00,0x00,0x08,0x00,0x00,0x08,0x04,0x3F,

  0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,

};

char cheng24[]={

/* 以下是 '成' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,

  0x80,0x00,0x0C,0x40,0x00,0x0C,0x60,0x00,

  0x04,0x20,0x08,0x04,0x0C,0x0F,0xFF,0xF0,

  0x08,0x04,0x00,0x08,0x04,0x10,0x08,0x06,

  0x18,0x08,0x26,0x30,0x0F,0xE6,0x30,0x08,

  0x22,0x20,0x08,0x22,0x60,0x08,0x23,0x40,

  0x08,0x61,0xC0,0x18,0x61,0x82,0x12,0x43,

  0xC4,0x11,0xC6,0x64,0x10,0x8C,0x3C,0x20,

  0x10,0x1C,0x40,0x20,0x06,0x00,0x00,0x00,

};

char ji24[]={

/* 以下是 '绩' 的 24点阵宋体 字模,72 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x01,

  0x80,0x06,0x01,0x08,0x04,0x3F,0xFC,0x08,

  0x01,0x00,0x08,0x81,0x10,0x10,0xDF,0xE0,

  0x21,0x81,0x00,0x3F,0x01,0x0C,0x22,0x3E,

  0xF0,0x04,0x10,0x08,0x08,0x1F,0xF8,0x08,

  0x10,0x18,0x13,0xD1,0x98,0x3C,0x11,0x18,

  0x00,0x11,0x18,0x00,0x11,0x18,0x03,0x13,

  0x10,0x1C,0x02,0xC0,0x30,0x04,0x30,0x00,

  0x08,0x0C,0x00,0x70,0x0C,0x00,0x80,0x00,

};

char guan48[]={

/* 以下是 '管' 的 48点阵宋体 字模,288 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x18,0x00,0x06,0x00,0x00,

  0x00,0x38,0x00,0x06,0x00,0x00,0x00,0x30,

  0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x08,

  0x00,0x40,0x00,0x60,0x06,0x18,0x00,0xE0,

  0x00,0xC0,0x00,0x10,0x80,0x00,0x00,0x80,

  0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x00,

  0x20,0x00,0x00,0x01,0x00,0x00,0x30,0x00,

  0x00,0x01,0x82,0x00,0x30,0x00,0x00,0x01,

  0x81,0x00,0x10,0x00,0x00,0x00,0x01,0x80,

  0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x60,0x01,0xFF,

  0xFF,0xFF,0xFF,0xF0,0x02,0x00,0x00,0x00,

  0x00,0x70,0x02,0x00,0x00,0x00,0x00,0xC0,

  0x06,0x00,0x00,0x00,0x00,0x80,0x0E,0x08,

  0x00,0x00,0x41,0x00,0x0C,0x0F,0xFF,0xFF,

  0xE0,0x00,0x00,0x04,0x00,0x00,0xC0,0x00,

  0x00,0x04,0x00,0x00,0xC0,0x00,0x00,0x04,

  0x00,0x00,0xC0,0x00,0x00,0x04,0x00,0x00,

  0xC0,0x00,0x00,0x04,0x00,0x00,0xC0,0x00,

  0x00,0x04,0x00,0x00,0xC0,0x00,0x00,0x04,

  0x00,0x00,0xC0,0x00,0x00,0x04,0x00,0x00,

  0x80,0x00,0x00,0x04,0x00,0x00,0x00,0x00,

  0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x04,

  0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,

  0x30,0x00,0x00,0x04,0x00,0x00,0x30,0x00,

  0x00,0x04,0x00,0x00,0x20,0x00,0x00,0x04,

  0x00,0x00,0x20,0x00,0x00,0x04,0x00,0x00,

  0x20,0x00,0x00,0x04,0x00,0x00,0x20,0x00,

  0x00,0x04,0x00,0x00,0x20,0x00,0x00,0x0C,

  0x00,0x00,0x20,0x00,0x00,0x0C,0x00,0x00,

  0x20,0x00,0x00,0x0C,0x00,0x00,0x30,0x00,

  0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};

char li48[]={

/* 以下是 '理' 的 48点阵宋体 字模,288 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x04,0x00,0x00,0x80,0x00,0x00,0x06,0x00,

  0x01,0xC0,0x00,0x00,0x86,0x01,0x00,0xC0,

  0x00,0x01,0xC6,0x01,0x00,0x80,0x00,0x10,

  0x02,0x01,0x00,0x80,0x00,0x10,0x02,0x01,

  0x00,0x80,0x00,0x10,0x02,0x01,0x00,0x80,

  0x00,0x10,0x02,0x01,0x00,0x80,0x00,0x10,

  0x02,0x01,0x00,0x80,0x00,0x10,0x02,0x01,

  0x00,0x80,0x00,0x10,0x02,0x01,0x00,0x80,

  0x00,0x10,0x02,0x01,0x00,0x80,0x00,0x10,

  0x02,0x01,0x00,0x80,0x00,0x10,0x02,0x01,

  0x00,0x80,0x00,0x10,0x02,0x01,0x00,0x80,

  0x00,0x10,0xC2,0x01,0x00,0x80,0x04,0x10,

  0x02,0x01,0x00,0x80,0x00,0x10,0x02,0x01,

  0x00,0x80,0x00,0x10,0x06,0x01,0x00,0x80,

  0x00,0x10,0x06,0x01,0x00,0x80,0x00,0x10,

  0x06,0x01,0x00,0x80,0x00,0x10,0x06,0x01,

  0x00,0x00,0x00,0x10,0x00,0x01,0x00,0x00,

  0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x10,

  0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x01,

  0x00,0x00,0x00,0x10,0x00,0x01,0x00,0x00,

  0x00,0x10,0x00,0x01,0x01,0x80,0x00,0x11,

  0x06,0x01,0x00,0x00,0x00,0x1C,0x00,0x01,

  0x00,0x00,0x00,0x70,0x00,0x01,0x00,0x00,

  0x03,0xC0,0x00,0x01,0x00,0x00,0x0F,0x00,

  0x00,0x01,0x00,0x00,0x0C,0x00,0x00,0x01,

  0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,

  0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,

  0x00,0x01,0x00,0x30,0x00,0x00,0x80,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};

char xi48[]={

/* 以下是 '系' 的 48点阵宋体 字模,288 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x01,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,

  0x00,0x00,0x00,0x01,0xFF,0x80,0x00,0x00,

  0x00,0x7F,0x00,0x00,0x00,0x00,0x3E,0x00,

  0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,

  0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,

  0x03,0x00,0x00,0x00,0x00,0x00,0x04,0x00,

  0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,

  0x00,0x00,0x20,0x00,0x30,0x00,0x00,0x00,

  0x40,0x00,0x70,0x00,0x00,0x01,0x00,0x01,

  0xC0,0x00,0x00,0x02,0x00,0x03,0x00,0x00,

  0x00,0x1C,0x7F,0xDC,0x00,0x00,0x00,0x1F,

  0x80,0x10,0x00,0x00,0x00,0x08,0x00,0x20,

  0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,

  0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,

  0x04,0x00,0x00,0x00,0x00,0x00,0x10,0x00,

  0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,

  0x00,0x01,0x00,0x00,0x06,0x00,0x00,0x04,

  0x00,0x00,0xFF,0x00,0x00,0x3D,0xFF,0xE0,

  0x03,0x80,0x00,0x1F,0x00,0x40,0x01,0x80,

  0x00,0x10,0x00,0x40,0x01,0x80,0x00,0x00,

  0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x40,

  0x00,0x00,0x00,0x00,0xC0,0x40,0x00,0x00,

  0x00,0x00,0xE0,0x40,0x00,0x00,0x00,0x01,

  0x80,0x40,0x30,0x00,0x00,0x03,0x00,0x40,

  0x1C,0x00,0x00,0x06,0x00,0x40,0x0E,0x00,

  0x00,0x08,0x00,0x40,0x07,0x80,0x00,0x10,

  0x00,0x40,0x03,0xC0,0x00,0x00,0x00,0x40,

  0x01,0xE0,0x00,0x80,0x00,0x40,0x00,0xE0,

  0x00,0x00,0x00,0x40,0x00,0xE0,0x00,0x00,

  0x00,0xC0,0x00,0x60,0x00,0x00,0x0F,0xC0,

  0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,

  0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};

char tong48[]={

/* 以下是 '统' 的 48点阵宋体 字模,288 byte */

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,

  0x00,0x0E,0x00,0x04,0x00,0x00,0x00,0x0C,

  0x00,0x06,0x00,0x00,0x00,0x18,0x00,0x03,

  0x00,0x00,0x00,0x18,0x00,0x03,0x00,0x00,

  0x00,0x30,0x00,0x02,0x00,0x40,0x00,0x20,

  0x00,0x00,0x00,0xE0,0x00,0x40,0x04,0x00,

  0x00,0x00,0x00,0x40,0x00,0x04,0x00,0x00,

  0x00,0x80,0x60,0x07,0x00,0x00,0x01,0x00,

  0x60,0x0E,0x00,0x00,0x00,0x00,0xC0,0x0C,

  0x00,0x00,0x02,0x01,0x80,0x18,0x00,0x00,

  0x04,0x01,0x00,0x30,0x00,0x00,0x0F,0xE2,

  0x00,0x60,0x04,0x00,0x0E,0x06,0x00,0x40,

  0x02,0x00,0x00,0x04,0x01,0x00,0x01,0x80,

  0x00,0x08,0x02,0x00,0x01,0xC0,0x00,0x10,

  0x0E,0x03,0xE0,0xE0,0x00,0x20,0x07,0xC0,

  0x00,0x60,0x00,0x40,0x04,0x00,0x00,0x60,

  0x00,0x00,0x00,0x20,0x40,0x00,0x00,0x00,

  0x00,0x38,0x60,0x00,0x02,0x00,0x40,0x30,

  0x60,0x00,0x06,0x38,0x00,0x30,0x60,0x00,

  0x07,0xC0,0x00,0x30,0x60,0x00,0x02,0x00,

  0x00,0x30,0x60,0x00,0x00,0x00,0x00,0x30,

  0x60,0x00,0x00,0x00,0x00,0x20,0x60,0x00,

  0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,

  0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x60,

  0x60,0x00,0x00,0x02,0x00,0x40,0x60,0x00,

  0x00,0x30,0x00,0xC0,0x60,0x00,0x03,0x80,

  0x00,0x80,0x60,0x00,0x0E,0x00,0x01,0x80,

  0x60,0x10,0x08,0x00,0x03,0x00,0x60,0x10,

  0x00,0x00,0x06,0x00,0x60,0x10,0x00,0x00,

  0x08,0x00,0x60,0x18,0x00,0x00,0x00,0x00,

  0x3F,0xF8,0x00,0x00,0x00,0x00,0x1F,0xE0,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};

 int shoudsave=0;

struct student

{

char num[10];   /*学号*/

char name[15];  /*姓名*/

int cgrade;     /*C语言成绩*/

int mgrade;     /*数学成绩*/

int egrade;     /*英语成绩*/

int total;      /*总分*/

float ave;      /*平均分*/

}

char neartime[10];/*最近更新时间 */

};

 void printstart()

 {

 printf("-----------------------------------------------------------------------\n");

 }

 void Wrong()

 {

 printf("\n=====>提示:输入错误!\n");

 }

 void Nofind()

 {

 printf("\n=====>提示:没有找到该学生!\n");

 }

 void printc() /*本函数用于输出中文 */

 {

 printf(" 学号       姓名      性别  英语成绩  数学成绩  C语言成绩  总分 平均分\n");

 }

 void printe(Node *p)/*本函数用于输出英文*/

 {

 printf("%-12s%s\t\t%s\t%d\t%d\t%d\t%d\t %d\n",p->data.num,p->data.name,p->data.sex,p->data.egrade,  p->data.mgrade,  p->data.cgrade,  p->data.totle,     p->data.ave);

 }

 Node* Locate(Link l,char findmess[],char nameornum[]) /*该函数用于定位连表中符合要求的接点,并返回该指针*/

3.1.2 主函数main()

main()函数主要实现了对整个程序的运行控制,以及相关功能模块的调用。详细分析可参考图2。

void main()

{

   Link l;      /*定义链表*/

   FILE *fp;    /*文件指针*/

   int select;     /*保存选择结果变量*/

   char ch;     /*保存(y,Y,n,N)*/

   int count=0; /*保存文件中的记录条数(或结点个数)*/

   Node *p,*r;   /*定义记录指针变量*/

  l=(Node*)malloc(sizeof(Node));

 l->next=NULL;

 r=l;

 fp=fopen("C:\\student","rb");

 if(fp==NULL)

 {

  printf("\n=====>提示:文件还不存在,是否创建?(y/n)\n");

  scanf("%c",&jian);

  if(jian=='y'||jian=='Y')

  fp=fopen("C:\\student","wb");

  else

  exit(0);

 }

 printf("\n=====>提示:文件已经打开,正在导入记录......\n");

 while(!feof(fp))

 {

  p=(Node*)malloc(sizeof(Node));

  if(fread(p,sizeof(Node),1,fp)) /*将文件的内容放入接点中*/

  {

   p->next=NULL;

   r->next=p;

   r=p; /*将该接点挂入连中*/

   count++;

  }

 }

 fclose(fp); /*关闭文件*/

 printf("\n=====>提示:记录导入完毕,共导入%d条记录.\n",count);

 while(1)

 {

  menu();

  printf("请你选择操作:");

  scanf("%d",&sel);

  if(sel==0)

  {

   if(shoudsave==1)

   { getchar();

   printf("\n=====>提示:资料已经改动,是否将改动保存到文件中(y/n)?\n");

   scanf("%c",&ch);

   if(ch=='y'||ch=='Y')

    Save(l);

   }

   printf("\n=====>谢谢使用!\n");

   break;

  }

  switch(sel)

  {

  case 1:Add(l);break; /*增加学生*/

  case 2:Del(l);break;/*删除学生*/

  case 3:Qur(l);break;/*查询学生*/

  case 4:Modify(l);break;/*修改学生*/

  case 5:Disp(l);break;/*显示学生*/

  case 6:Tongji(l);break;/*统计学生*/

  case 7:Sort(l);break;/*排序学生*/

  case 8:Save(l);break;/*保存学生*/

  default: Wrong();

  printf("\n=====>提示:输入错误!\n"); getchar();

  getchar();break;

  }

 }

 }

3.1.3 主菜单界面

用户进入成绩管理系统时,需要显示主菜单,提示用户进行选择,完成相应任务。此代码被main()函数调用。

char menu( void )  /*以下是调用菜单函数*/

{

    char choice;

    clrscr();

    gotoxy( 17 , 5 );

    printf(" =================主菜单===================");

    gotoxy(17 , 6);

    printf(" ==      1    输入学生信息               ==");/*输入信息*/

    gotoxy(17 , 7);

    printf(" ==      2    删除学生信息               ==");/*删除所有信息*/

    gotoxy(17 , 8);

    printf(" ==      3    查询学生信息               ==");

    gotoxy(17 , 9);

    printf(" ==      4    修改学生信息               ==");      /*修改信息*/

    gotoxy(17 , 10);

    printf(" ==      5    显示学生信息               ==");      /*显示新信息*/

    gotoxy(17 , 11);

    printf(" ==      6    统计学生信息               ==");      /*统计信息*/

    gotoxy(17 , 12);

    printf(" ==      7    排序学生信息               ==");      /*排序信息*/

    gotoxy(17 , 13);

    printf(" ==      8    保存学生信息               ==");

    gotoxy(17 , 14);

    printf(" ==      0    退出系统                   ==");    /*退出*/

    gotoxy(17 , 15);

    printf(" ==========================================");

}

}

3.1.4 记录查找定位

用户进入成绩管理系统时,对某个学生的记录进行处理前,需要按照条件找到这条记录。此函数完成了节点定位的功能。

/*************************************************************

作用:用于定位链表中符合要求的节点,并返回指向该节点的指针

参数:findmess[]保存要查找的具体内容; nameornum[]保存按什么

      在单链表l中查找;

**************************************************************/

Node* Locate(Link l,char findmess[],char nameornum[]) /*该函数用于定位连表中符合要求的接点,并返回该指针*/

 {

 Node *r;

 if(strcmp(nameornum,"num")==0) /*按学号查询*/

 {

  r=l->next;

  while(r!=NULL)

  {

   if(strcmp(r->data.num,findmess)==0)

   return r;

   r=r->next;

  }

 }

 else if(strcmp(nameornum,"name")==0) /*按姓名查询*/

 {

  r=l->next;

  while(r!=NULL)

  {

   if(strcmp(r->data.name,findmess)==0)

   return r;

   r=r->next;

  }

 }

 return 0;

 }   return 0; /*若未找到,返回一个空指针*/

}

3.1.5 增加学生记录

在此成绩管理系统中,若数据文件为空,则从单链表的头部开始增加学生记录节点;否则,将此生记录节点添加在单链表的尾部。

void Add(Link l) /*增加学生*/

 {

 Node *p,*r,*s; /*实现添加操作的临时的结构体指针变量*/

 char num[15];

 r=l;

 s=l->next;

 while(r->next!=NULL)

  r=r->next; /*将指针置于最末尾*/

 while(1)

 {

  printf("请你输入学号(以'0'返回上一级菜单:)");

  scanf("%s",num);

  if(strcmp(num,"0")==0)

   break;

  while(s)

  {

   if(strcmp(s->data.num,num)==0)

   {

   printf("=====>提示:学号为'%s'的学生已经存在,若要修改请你选择'4 修改'!\n",num);

   printstart();

   printc();

   printe(s);

   printstart();

   printf("\n");

   return;

   }

   s=s->next;

  }

  

  p=(Node *)malloc(sizeof(Node));

  

  strcpy(p->data.num,num);

  printf("请你输入姓名:");

  scanf("%s",p->data.name);

  getchar();

  printf("请你输入性别:");

  scanf("%s",p->data.sex);

  getchar();

  printf("请你输入c语言成绩:");

  scanf("%d",&p->data.cgrade);

  getchar();

  printf("请你输入数学成绩:");

  scanf("%d",&p->data.mgrade);

  getchar();

  printf("请你输入英语成绩:");

  scanf("%d",&p->data.egrade);

  getchar();

  p->data.totle=p->data.egrade+p->data.cgrade+p->data.mgrade;

  p->data.ave=p->data.totle / 3;

  /*信息输入已经完成*/

  p->next=NULL;

  r->next=p;

  r=p;

  shoudsave=1;

  

 }

 } }

3.1.6 删除学生记录

在删除操作中,系统会按用户要求先找到该学生记录,然后从单链表中删除该节点。

void Del(Link l) /*删除*/

 {

 int sel;

 Node *p,*r;

 char findmess[20];

 if(!l->next)

 {

  printf("\n=====>提示:没有资料可以删除!\n");

  return;

 }

 printf("\n=====>1按学号删除\n=====>2按姓名删除\n");

 scanf("%d",&sel);

 if(sel==1)

 {

  printf("请你输入要删除的学号:");

  scanf("%s",findmess);

  p=Locate(l,findmess,"num");

  if(p)

  {

   r=l;

   while(r->next!=p)

   r=r->next;

   r->next=p->next;

   free(p);

   printf("\n=====>提示:该学生已经成功删除!\n");

   shoudsave=1;

  }

  else

   Nofind();

 }

 else if(sel==2)

 {

  printf("请你输入要删除的姓名:");

  scanf("%s",findmess);

  p=Locate(l,findmess,"name");

  if(p)

  {

   r=l;

   while(r->next!=p)

   r=r->next;

   r->next=p->next;

   free(p);

   printf("\n=====>提示:该学生已经成功删除!\n");

   shoudsave=1;

  }

  else

   Nofind();

 }

 else

  Wrong();

 }

3.1.7 查询学生记录

当用户执行此查询任务时,系统会提示用户进行查询字段的选择,即按学号或姓名进行查询。若此学生记录存在,则会打印输出此学生记录的信息。

void Qur(Link l) /*查询学生*/

 {

 int sel;

 char findmess[20];

 Node *p;

   if(!l->next)

 {

  printf("\n=====>提示:没有资料可以查询!\n");

  return;

  }

 printf("\n=====>1按学号查找\n=====>2按姓名查找\n");

 scanf("%d",&sel);

 if(sel==1)/*学号*/

 {

  printf("请你输入要查找的学号:");

  scanf("%s",findmess);

  p=Locate(l,findmess,"num");

  if(p)

  {

   printf("\t\t\t\t查找结果\n");

   printstart();

   printc();

   printe(p);

   printstart();

  }

  else

   Nofind();

 }

 else if(sel==2) /*姓名*/

 {

  printf("请你输入要查找的姓名:");

  scanf("%s",findmess);

  p=Locate(l,findmess,"name");

  if(p)

  {

   printf("\t\t\t\t查找结果\n");

   printstart();

   printc();

   printe(p);

   printstart();

  }

  else

   Nofind();

 }

 else

  Wrong(); 

 }

3.1.8 修改学生记录

在修改学生记录操作中,系统会先按输入的学号查询到该记录,然后提示用户修改学号之外的值,但学号不能修改。

void Modify(Link l)

 {

 Node *p;

 char findmess[20];

 if(!l->next)

 {

  printf("\n=====>提示:没有资料可以修改!\n");

  return;

 }

 printf("请你输入要修改的学生学号:");

 scanf("%s",findmess);

 p=Locate(l,findmess,"num");

 if(p)

 {

 printf("请你输入新学号(原来是%s):",p->data.num);

  scanf("%s",p->data.num);

 printf("请你输入新姓名(原来是%s):",p->data.name);

  scanf("%s",p->data.name);

  getchar();

  printf("请你输入新性别(原来是%s):",p->data.sex);

  scanf("%s",p->data.sex);

  printf("请你输入新的C语言成绩(原来是%d分):",p->data.cgrade);

  scanf("%d",&p->data.cgrade);

  getchar();

  printf("请你输入新的数学成绩(原来是%d分):",p->data.mgrade);

  scanf("%d",&p->data.mgrade);

  getchar();

  printf("请你输入新的英语成绩(原来是%d分):",p->data.egrade);

  scanf("%d",&p->data.egrade);

  p->data.totle=p->data.egrade+p->data.cgrade+p->data.mgrade;

  p->data.ave=p->data.totle/3;

  printf("\n=====>提示:资料修改成功!\n");

  shoudsave=1;

 }

 else

  Nofind();

 }

 3.1.9显示记录

由于记录显示操作经常进行,所以将这部分由独立的函数来完成,减少代码的重复。它将显示单链表L中存储的学生记录,内容为student结构中定义的内容。

void Disp(Link l) 

{

   Node *p;

   p=l->next; /*l存储的是单链表中头结点的指针*/

   if(!p)  /*p==NULL,NULL在stdlib中定义为0*/

   {

      printf("\n=====>Not student record!\n");

      getchar();

      return;

   }

   printf("\n\n");

   printheader(); /*输出表格头部*/

   while(p)    /*逐条输出链表中存储的学生信息*/

   {

      printdata(p);

      p=p->next;  /*移动直下一个结点*/

      printf(HEADER3);

   }

   getchar();

}

3.1.10 统计学生记录

在统计学生记录操作中,系统会统计该班的总分第一名、单科第一名,并打印输出统计结果。

void Tongji(Link l)

 {

 Node *pm,*pe,*pc,*pt,*pa; /*用于指向分数最高的接点*/

 Node *r=l->next;

 if(!r)

 {

  printf("\n=====>提示:没有资料可以统计!\n");

  return ;

 }

 pm=pe=pc=pt=pa=r;

 while(r!=NULL)

 {

  if(r->data.cgrade>=pc->data.cgrade)

   pc=r;

  if(r->data.mgrade>=pm->data.mgrade)

   pm=r;

  if(r->data.egrade>=pe->data.egrade)

   pe=r;

  if(r->data.totle>=pt->data.totle)

   pt=r;

  if(r->data.ave>=pa->data.ave)

  pa=r;

  r=r->next;

 }

 printf("------------------------------统计结果--------------------------------\n");

 printf("总分最高者:\t%s %d分\n",pt->data.name,pt->data.totle);

 printf("平均分最高者:\t%s %d分\n",pa->data.name,pa->data.ave);

 printf("英语分最高者:\t%s %d分\n",pe->data.name,pe->data.egrade);

 printf("数学分最高者:\t%s %d分\n",pm->data.name,pm->data.mgrade);

 printf("C语言分最高者:\t%s %d分\n",pc->data.name,pc->data.cgrade);

   printstart();

 } 3.1.11 排序学生记录

在排序学生记录操作中,系统会利用插入排序法实现单链表的按总分字段的降序排序,并打印出排序前和排序后的结果。

void Sort(Link l)

 {

 Link ll;

 Node *p,*rr,*s;

 ll=(Link)malloc(sizeof(Node)); /*用于做新的连表*/

 ll->next=NULL;

 if(l->next==NULL)

 {

  printf("\n=====>提示:没有资料可以排序!\n");

  return ;

 }

 p=l->next;

 while(p)

 {

  s=(Node*)malloc(sizeof(Node)); /*新建接点用于保存信息*/

  s->data=p->data;

  s->next=NULL;

  rr=ll;

  while(rr->next!=NULL && rr->next->data.totle>=p->data.totle)

   rr=rr->next;

  if(rr->next==NULL)

   rr->next=s;

  else

  {

   s->next=rr->next;

   rr->next=s;

  }

  p=p->next;

 }

 free(l);

 l->next=ll->next;

 printf("\n=====>提示:排序已经完成!\n");

}

3.1.12 存储学生记录

在存储学生记录操作中,系统会将单链表中的数据写入磁盘数据文件中,若用户对数据已修改过但没有专门进行存盘操作,那么在退出系统时,系统会提示用户是否存盘。

void Save(Link l)

 {

 FILE* fp;

 Node *p;

 int flag=1,count=0;

 fp=fopen("c:\\student","wb");

 if(fp==NULL)

 {

  printf("\n=====>提示:重新打开文件时发生错误!\n");

  exit(1);

 }

 p=l->next;

 while(p)

 {

  if(fwrite(p,sizeof(Node),1,fp)==1)

  { 

   p=p->next;

   count++;

  }

  else

  {

   flag=0;

   break;

  }

 }

 if(flag)

 {

  printf("\n=====>提示:文件保存成功.(有%d条记录已经保存.)\n",count);

  shoudsave=0;

 }

 fclose(fp);

 }

3.2 测试与调试

3.2.1 概述

一般情况下,为解决一个问题所编写的程序代码较长,可能包括几百条甚至成千上万条语句。在检查并排除所有语法错误后,还会有不易发现的逻辑错误,因此要对程序进行认真仔细的测试与调试。

测试是通过运行程序发现错误的过程,常见的错误有数据溢出、数组越界、进入死循环、语句顺序颠倒、多加“;”或少加“{}”等等。调试则是确定测试中找到的错误性质并改正错误的过程。测试与调试通常交替进行,即测试——调试——再测试——再调试。

能检查出尚未发现的、各种不同类型错误的测试才是成功的测试。测试程序需要测试用例,测试用例可用如下公式表示:测试用例=测试数据+预期结果。

好的测试用例应该是用尽可能少的测试数据发现尽可能多的错误,即发现错误的概率要大。要选择合适的测试数据,使系统在运行时尽量能执行到每条语句,以测试各指令是否正确。还应分别测试输入合法数据与非法数据时,程序的运行情况,。对于合法数据,还要考虑数据的一般性与特殊性,如求最大值的问题,应测试最大值在最前面、最后面、中间某一位置的情况。

测试可按模块测试、组装测试和确认测试的步骤进行。

(1)模块测试就是分别对各模块进行测试的过程。在编写一个模块后应立即对其进行测试,因为这时对模块记忆深刻,而且单个模块相对较小,所以容易构造测试数据,能方便地检查和改正错误。

(2)组装测试就是把所有模块(应该是通过模块测试的模块)按预先制定的计划逐步组装和测试的过程。一般情况下,各模块之间要相互传递数据和控制信息,因此组装测试的主要任务是发现模块接口中的错误。

(3)确认测试是最后一个步骤,一般在将软件交付用户之前,应确认软件是否确实满足用户的要求,通常使用接近实际的用例进行测试。

Turbo C环境下测试程序可以用以下的方法。

● 临时加打印语句,将所要观察的数据显示在屏幕上。

● 用F8或F7热键单步执行程序。

● 用Ctrl+F8组合键设置断点。

● 综合使用以上方法。

测试程序时,用监视窗口可以随时查看变量或表达式的值,有时还可以将部分程序代码用注释符暂时括起来,缩短程序,以便压缩出错代码的范围。

3.2.2 程序测试

l  在主菜单中选择1

当用户输入1并按回车键后,即可进入数据输入界面。若是第一次运行该程序,应能实现从键盘输入学生信息到链表中,当输入的学号重复时,应能提示不予接收,当输入为0的学号时,能结束输入过程,返回主菜单界面。若非第一次运行该程序,应能实现从文件中读入学生信息到链表中,并进入增加学生记录画面。

l  在主菜单中选择2

当用户输入2并按回车键后,即可进入记录删除界面。在进入删除界面中,一,可以按学号删除;二,可以按姓名删除。

l  在主菜单中选择3

当用户输入3并按回车键后,即可进入记录查找界面。其查找记录过程,可按学号或姓名进行查找。

l  在主菜单中选择4

当用户输入4并按回车键后,即可进入记录修改界面。其修改记录过程中,按学号修改,他会显示原来的信息,只要输入要修改的信息,按回车就可以实现。

l  在主菜单中选择5

当用户输入5并按回车键后,即可进入信息记录显示界面。其显示记录过程中,是将之前的保存的信息全部显示。

l  在主菜单中选择6

当用户输入6并按回车键后,即可进入信息记录统计界面。其统计结果显示出了最高分人数。

l  在主菜单中选择7

当用户输入7并按回车键后,即可进入记录排序界面。其排序结果,有排序前和排序后的学生信息记录输出结果。

l  在主菜单中选择8

当用户输入8并按回车键后,即可进入记录保存界面。,将信息记录已经存储到磁盘文件中。

l  在主菜单中选择0

当用户输入0并按回车键后,即可执行退出管理程序的操作。

4、系统维护

经测试与调试确认软件无错时,开发就告一段落,这时可以交付软件供用户使用,但是在软件的使用过程中还会面临更加漫长的工作,即软件维护。一般维护的工作有:更改使用中发现的错误;为适应实际环境而对程序进行修改;为满足新的需求而对程序作必要的改进等等。

5、归纳总结

5.1 开发经验

通过对本题目的开发,体会到要掌握以下几点内容。

l  大程序的设计风格。按“自顶向下,逐步细化,模块化”的方法进行程序设计。

l  编写主函数,并进行测试与调试。当被调函数又需要调用其他函数时,也要遵循逐步细化的原则。C语言提供丰富的库函数,编程序时要善于使用库函数,避免不必要的劳动。

l  定义函数时,应选好参数的个数和数据类型。

l  文件使用方法。文件使用完毕后应及时关闭。

5.2 实训中遇到的问题及解决方法

在这次的实训中,主要遇到的问题是编译环境的不同对程序也不同。本来我们的程序是不支持在VC++里面编译的,因此一直都处在编译失败,该函数未定义的错误中。后来经过老师的指导,终于找到了根源,就是把“clrscr()”改为“system("cls")”就可以了。

5.3 设计中尚存的不足之处

关于这次的程序,也有挺多不足的地方。首先,我觉得程序还不够完善,有些地方甚至有点乱;其次,有些地方好像功能有点重复了;最后,就是该程序界面不够美观大方。

5.4 感想和心得体会

通过这次实训,我感触甚深,要把所学的理论知识运用于解决实际问题不仅要付出艰辛的劳动,还得要有科学的方法和坚持不懈的努力。这次实训让我进一步理解了“编程是什么”,“如何去编程”,“编程的目的又是什么”,……发现自己的知识竟是如此贫乏,顿时感到了压力的存在,从而也激发了我的学习热情。它会成为我今后不断进取、永不懈怠的动力。

在整个实训过程中,我能够坚持虚心的向老师以及同学请教问题,它使我明白了虚心好学的重要性,更让我懂得了如何跟老师同学去相处、去沟通。没有老师和同学们的无私帮助,我不可能圆满完成这次实训任务。感谢帮助过我的所有老师和同学们,要列出所有帮助过我的人的名字是不现实的,因为有些困难是通过因特网解决的,我甚至不知道他们的名字,在此,谨向他们一并表示感谢!

6、参考资料

[1] 谭浩强.   C程序设计(第三版).      清华大学出版社,     2005 

[2] 李凤霞.   C语言程序设计教程.        北京理工大学出版社, 2003

[3] 郭翠英.   C语言课程设计案例精编.    北京.中国水利出版社,2004

[4] 刘振安等. C程序设计课程设计.        北京.机械工业出版社,2004

[5] 朱承学等. C语言程序设计实践训练教程.北京.中国水利出版社,2004

[6] 马尚风等. C语言程序设计实训教程.    北京.科学出版社,    2003

[7] 张高煌.   C语言程序设计实训.        北京.中国水利出版社,2001

相关推荐