程序设计报告
( 20## / 20## 学年 第 一 学期)
题 目: 学生信息管理系统
专 业 通信工程
学 生 姓 名 贾玮玮
班 级 学 号 B09010630
指 导 教 师 王 蔚
指 导 单 位 计算机学院计算机软件教学中心
日 期 20##年10月29日
一、课题名称
学生信息管理系统
二、课题内容和要求
1、课题描述:
已知有20个学生记录(包括学号、姓名、成绩)的文件student.dat,所有学生以学号从小到大排序(该文件自行建立)。要求编程序实现查询、排序、插入、删除诸功能。
2、基本要求:
A.要求显示如下界面
****************************************
1--------------查询
2--------------排序
3--------------插入
4--------------删除
****************************************
通过选择1-4来确定要做哪一个操作。
B.若选1,则出现如下界面
****************************************
1.1----------按学号查询
1.2----------按姓名查询
1.3----------按成绩查询
****************************************
通过选择1.1-1.3来确定要做哪一个操作,其中:
按学号查询用二分法实现;
按姓名查询用顺序法实现;
按成绩查询实现查询成绩小于m分的学生;
找到该生将学生记录输出到屏幕,若查无此人,输出相关信息。
C.若选2,则按成绩从大到小排序,姓名,学号顺序也随之调整。
D.若选3,将一个新学生记录按学号顺序插入,并把结果保存到文件student.dat中。
E.若选4,删除指定学生的记录,并把结果保存到文件student.dat中。
F.以上各个功能均编写成子函数,由主函数调用实现。
三、需求分析
1、登录,提供两种登录身份,老师和学生,老师身份登录需要密码验证,这样可以为不同的身份提供不同的使用权限,学生身份登录不可以插入或删除学生信息。
2、信息生成,从student.dat文件中读取学生信息,包括用户学号、姓名、成绩。
3、主菜单,屏幕输出菜单用于提示用户选择功能,根据用户输入的选项,运行不同的函数。功能包括:查询、排序、插入、删除、重新登录、退出系统。
4、查询,屏幕输出子菜单用于提示用户选择功能,根据用户输入的选项,运行不同的函数。功能包括:按学号查询、按姓名查询、按成绩查询通。
5、排序,将学生信息按学号从小到大排序并输出所有学生信息。
6、插入,输入“0000”可以返回上一层,输入要插入的学生信息的学号,验证此学号是否存在,存在则显示提示信息,不存在则继续输入该信息的姓名和成绩,并储存到student.dat文件中,完成后输出提示信息。
7、删除,输入“0000”可以返回上一层,输入要插入的学生信息的学号,验证此学号是否存在,不存在则显示提示信息,存在则删除此条信息,并储存到student.dat文件中,完成后返回提示信息。
8、重新登录,返回登录程序,供用户切换登录身份。
9、退出系统,关闭程序。
10、按学号查询和按姓名查询,输入“0000”可以返回上一层,输入要查询的学生信息的学号或姓名,查找到则输出学生信息,若未查找则输出提示信息。
11、按成绩查询,输入“0000”可以返回上一层,输入一个成绩,查询小于该成绩的所有学生信息,并输出,若未查找到则显示提示信息。
12、返回主菜单,返回主菜单界面。
四、概要设计
1、结构体
struct record
{char xuehao[LEN+1];/*学号*/
char xingming[LEN+1];/*姓名*/
int chengji;/*成绩*/
}stu[N];
2、函数申明
void denglu();/*登录函数*/
void mima();/*密码验证函数*/
void readfile();/*信息生成函数*/
void menu();/*主菜单函数*/
void chaxun();/*查询函数*/
void paixu();/*排序函数*/
void charu();/*插入函数*/
void shanchu();/*删除函数*/
void display();/*显示函数*/
void save();/*保存函数*/
void xuehaopaixu();/*按学号排序函数*/
3、算法流程图
五、详细设计
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#include<ctype.h>
#define LEN 20/*学号、姓名和密码最大字符数*/
#define N 200/*最大学生人数*/
struct record
{char xuehao[LEN+1];/*学号*/
char xingming[LEN+1];/*姓名*/
int chengji;/*成绩*/
}stu[N];
int k=1,x=1,m=0,n;/*定义全局变量,k与退出系统功能有关,x和m用来标示用户身份,n为实际存储的信息数目*/
void denglu();/*函数声明*/
void mima();
void readfile();
void menu();
void chaxun();
void paixu();
void charu();
void shanchu();
void display();
void save();
void xuehaopaixu();
int main()/*主函数*/
{printf("欢迎使用学生信息管理系统!\n");
denglu();
readfile();
while(k)/*用来实现退出系统功能,当k==0时,循环结束*/
menu();
system("pause");
return 0;
}
void denglu()/*登录函数*/
{while(m==0 && x==1)
{ printf("请输入您的登录身份,老师为0,学生为1(老师身份登录需要密码验证):");
scanf("%d",&m);
while(m==0)
{ mima();
if(m==0)
break;
}
}
}
void mima()/*密码验证函数*/
{char password[LEN+1];
int z=0;
printf("请输入密码,最多15位:");
unsigned char c;
while((c=getch())!='\r')/*无显示输出*/
{ if(z<LEN && isprint(c))
{ password[z++]=c;
putchar('*');
}
else
if(z>0 && c=='\b')/*实现退格功能*/
{ --z;
putchar('\b');
putchar('\0');
putchar('\b');/*并删除显示*号*/
}
}
putchar('\n');
password[z]='\0';
if(strcmp(password,"12345678")==0)
{ printf("登录成功!\n");
m=1;/*登录成功,跳出denglu函数的while循环*/
x=0;
}
else printf("密码错误!\n");
}
void readfile()/*建立信息函数*/
{char *p="student.dat";
FILE *fp;
int i=0;
if((fp=fopen("student.dat","r"))==NULL)
{ printf("打开文件%s失败!按任意键推出!",p);
system("pause");
exit(0);
}
while(fscanf(fp,"%s %s %d",stu[i].xuehao,stu[i].xingming,&stu[i].chengji)==3)
i++;
fclose(fp);
n=i;
printf("录入完毕!\n");
}
void menu()/*菜单函数*/
{int num,e=0;/*e为重新登录功能的参数*/
printf("\n 学生信息管理系统\n\n");
printf("**********系统功能菜单**********\n");
printf("********************************\n");
printf("*******1--------------查询******\n");
printf("*******2--------------排序******\n");
printf("*******3--------------插入******\n");
printf("*******4--------------删除******\n");
printf("*******5--------------重新登录**\n");
printf("*******6--------------退出系统**\n");
printf("********************************\n");
while(1)
{ printf("请选择主菜单编号:");
scanf("%d",&num);
switch(num)
{case 1:chaxun();break;
case 2:paixu();break;
case 3:
if(m==1 && x==0)/*权限判定,老师登录为m==1,x==0;学生登录为m==0,x==1*/
charu();
else
printf("您的权限不够!\n");
break;
case 4:
if(m==1 && x==0)
shanchu();
else
printf("您的权限不够!\n");
break;
case 5:e=1;break;
case 6:k=0;break;
default:printf("请在1-6之间选择!\n");break;
}
if(e==1 || k==0)
break;
}
if(e==1)
{ m=0;/*还原登录前的参数值*/
x=1;
denglu();
}
}
void chaxun()/*查询函数*/
{int i,j,item,flag,left,right,mid;
char s1[LEN+1];/*以姓名和学号最长长度+1为准*/
printf("********************************\n");
printf("*****1.1---------按学号查询*****\n");
printf("*****1.2---------按姓名查询*****\n");
printf("*****1.3---------按成绩查询*****\n");
printf("*****1.4---------回到主菜单*****\n");
printf("********************************\n");
while(1)
{ printf("请选择子菜单编号:");
scanf("%d",&item);
flag=0;
switch(item)
{ case 1:
xuehaopaixu();/*首先将学号按从小到大排序,然后运用二分法查找*/
printf("请输入要查询的学生的学号,若要返回上层请输入“0000“:");
scanf("%s",s1);
if(strcmp(s1,"0000")==0)
break;
left=0;
right=n-1;
while(left<=right)
{ mid=(left+right)/2;
if(strcmp(stu[mid].xuehao,s1)==0)
{ printf("该学生的信息为:\n学号 姓名 成绩\n");
printf("%-12s %-12s %d\n",stu[mid].xuehao,stu[mid].xingming,stu[mid].chengji);
flag=1;
left=right+1;/*一旦查询到,就跳出循环*/
}
else
if(strcmp(stu[mid].xuehao,s1)==1)
right=mid-1;
else
left=mid+1;
}
if(flag==0)
printf("该学号不存在!\n");
break;
case 2:
printf("请输入要查询的学生的姓名,若要返回上层请输入“0000“:");
scanf("%s",s1);
if(strcmp(s1,"0000")==0)
break;
for(i=0;i<n;i++)
if(strcmp(stu[i].xingming,s1)==0)
{ flag=1;
printf("该学生的信息为:\n学号 姓名 成绩\n");
printf("%-12s %-12s %d\n",stu[i].xuehao,stu[i].xingming,stu[i].chengji);
i=n;/*一旦查询到,就跳出循环*/
}
if(flag==0)
printf("该姓名不存在!\n");
break;
case 3:
printf("请输入要查询的学生的成绩,若要返回上层请输入“0000“:");
scanf("%d",&j);
if(j==0000)
break;
for(i=0;i<n;i++)
if(stu[i].chengji<j)
{ flag=1;
printf("该学生的信息为:\n学号 姓名 成绩\n");
printf("%-12s %-12s %d\n",stu[i].xuehao,stu[i].xingming,stu[i].chengji);
}
if(flag==0)
printf("小于%d的成绩不存在\n",j);
break;
case 4:return;
default:printf("请在1-4之间选择!\n");break;
}
}
}
void paixu()/*排序函数*/
{int i,j;
struct record temp;
for(i=0;i<n-1;i++)
{ for(j=i+1;j<n;j++)
{ if(stu[i].chengji<stu[j].chengji)
{ temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
display();
}
void charu()/*插入函数*/
{int i,flag=0;
char s1[LEN+1];
printf("请输入新学生记录的学号,若要返回上层请输入“0000“:");
scanf("%s",s1);
if(strcmp(s1,"0000")==0)
return;
for(i=0;i<n;i++)
{ if(strcmp(stu[i].xuehao,s1)==0)
{ flag=1;
printf("该学号已存在!\n");
}
if(flag==1)
break;
}
if(flag==0)
{ for(i=0;i<LEN+1;i++)
stu[n].xuehao[i]=s1[i];
printf("请输入新学生记录姓名、成绩:\n");
scanf("%s %d",stu[n].xingming,&stu[n].chengji);
n++;
xuehaopaixu();
save();
printf("录入成功!\n");
}
}
void shanchu()/*删除函数*/
{int i,j,flag=0;
char s1[LEN+1];
printf("请输入要删除学生的学号,若要返回上层请输入“0000“:");
scanf("%s",s1);
if(strcmp(s1,"0000")==0)
return;
for(i=0;i<n;i++)
{ if(strcmp(stu[i].xuehao,s1)==0)
{ flag=1;
for(j=i;j<n-1;j++)
stu[j]=stu[j+1];
n--;
save();
printf("删除成功!\n");
}
if(flag==1)
break;
}
if(flag==0)
printf("该学号不存在!\n");
}
void display()/*显示函数*/
{int i;
printf("所有学生的信息为:\n学号 姓名 成绩\n");
for(i=0;i<n;i++)
printf("%-12s %-12s %d\n",stu[i].xuehao,stu[i].xingming,stu[i].chengji);
}
void save()/*保存函数*/
{int i;
FILE *fp;
fp=fopen("student.dat","w");
for(i=0;i<n;i++)
fprintf(fp,"%s %s %d\n",stu[i].xuehao,stu[i].xingming,stu[i].chengji);
fclose(fp);
}
void xuehaopaixu()/*按学号排序函数*/
{int i,j,r;
struct record temp;
for(i=0;i<n-1;i++)
{ for(j=i+1;j<n;j++)
{ r=strcmp(stu[i].xuehao,stu[j].xuehao);
if(r==1)
{ temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
}
六、测试数据及其结果分析
1、学生信息:
B09010601 爱因斯坦 100
B09010606 霍金 97
B09010616 麦克斯韦 96
B09010603 莱布尼茨 95
B09010602 牛顿 94
B09010617 普朗克 94
B09010607 蔡定鄂 93
B09010605 李政道 92
B09010604 杨振宁 90
B09010615 伽利略 90
B09010613 笛卡尔 89
B09010608 惠更斯 89
B09010614 卡文迪许 88
B09010610 波尔 87
B09010612 玻尔兹曼 85
B09010609 赫兹 85
B09010620 安培 84
B09010611 多普勒 83
B09010618 汤姆逊 82
B09010619 菲涅耳 80
B09010620 安培 86
2、程序运行
程序运行,首先进入登录界面,进行登录身份选择,老师为0,学生为1,老师身份登录需要密码验证:
首先,选择学生身份登录,输入1,显示主菜单界面,等待输入主菜单编号:
选择查询功能,输入1,显示查询功能子菜单界面:
选择按学号查询功能,输入“0000”返回上一层:
选择按姓名查询功能,输入要查询的姓名,显示学生信息:
选择按成绩查询功能,输入要查询的成绩,输出小于该成绩的所有学生信息:
选择返回主菜单功能:
选择排序功能,将所有学生信息按学号由小到大排序输出:
选择插入功能,由于是以学生身份登录,权限不够:
选择删除功能,由于是以学生身份登录,权限不够:
选择重新登录功能,进入登录界面:
以老师身份登录,进入密码验证:
输入密码,显示星号,可退格,密码验证正确后,进入主菜单界面:
选择插入功能,输入要插入的学生学号,若该学号不存在,则提示继续输入学生的姓名和成绩,保存到student.dat文件中,并显示提示信息:
选择删除功能,输入要删除信息的学生学号,若此学号存在,则删除,并返回提示信息:
七、调试过程中的问题
1、字符串的比较应使用strcmp()函数。
2、用户的菜单选择,为防止死循环,设置标志变量flag。
3、读写文件的时候一定要注意格式的控制,否则很容易出现错误。
4、switch()语句中注意每个case的break。
5、在运用二分法查询时,应先对信息按学号排序。
6、局部变量的命名,尽量避免重复。
7、输入、输出的格式控制符要注意。
8、指针变量的调用要注意格式是否正确。
9、通过引入不同的参数作为某些过程的标记,可以带来许多的方便。
10、灵活的运用循环与break、continue的搭配,可以实现许多小功能。
八、课程设计总结
通过这两周的程序实习,我深刻体会到要完成一项这样具有实际意义的程序设计,它所涉及的问题的多方面性,全面性。同时它更需要我们扎实的功底和足够的耐性。在这个过程中,我们小组成员互帮互助,充分利用各自的资源,在大家的合作与帮助下,我们度过了充实而又有意义的两周。
这次程序设计,我感慨颇多,从理论到实践,在整整两个星期的日子里,我学到了很多书本上所没有学到的内容。通过这次程序设计,我懂得了理论与实际相结合,从理论中得出结论,才是真正的知识,才能提高自己在设计的过程遇到了