这是花了近一个星期做的c语言课程设计,全部自己独立完成。
做完后感觉收获颇大,有种成就感,鼓励我继续走下去。
这个小型的管理系统比上次做的<银行基本功能的实现>代码量要多一些。
用到了指针,也用到了文件操作,可以保存数据了。
c语言是高效的,涉及到内存的操作。同样只有文本界面,没有图形菜单界面。
菜单界面用MFC或c可以做出来。在实践过程中,编译器的差别是非常让人头
疼的事,我建议大家比较大的程序还是用vc++综合编译环境,turbo c有很
多缺点,比如从不对数组元素的引用是否越界进行检查,如果对内存的安全区
的错误引用甚至会导致应用程序错误。还有些写法也不规范。最后说一句,做
这种应用并不是c的强项,c擅长于做底层的寄存器接口或驱动程序,由于其执
行效率高的优点,UNIX操作系统也是c语言做的。c精通于算法,比如ACM里
大多数都用的c语言。这种应用程序用Delphi或JAVA去实现可能更好。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h> //该头文件用于协调下turbo c与vc不同的库函数
#define LEN sizeof(struct stu)
#define N 30 //宏替换,便于根据需要改变学生数目,节省内存开销
void Getdata(int a);
void Getdatatofree(void); //均是函数声明,告诉编译器这些函数已有定义
void Renewdata(void);
void Deletedata(int i);
void Printdata(int n);
void Printalldata(void);
int Index(void);
static int index;
static int m;
static int sum[N];
static int a[N];
static int empty[N+1];
FILE *fp; //定义了一个文件指针变量
void printstar(int n) //定义了一个简单的打印*号的函数,用于文本界面的美化
{
int i;
for(i=1;i<=n;i++){printf("*");}
printf("/n");
}
static struct stu //定义了一个静态全局结构体,用来存储学生的基本信息
{
int Class;
char StuID[11];
char Name[13];
char Sex[5];
int Age;
int Number;
char Phone[12];
int grade[8]; //学生成绩 用整型数组表示 方便求和排序等计算
}student[N];
static struct stu *p=student;
void InputGrade(int m) //用于输入成绩的函数
{
printf("/n请输入该学生的微积分Ⅱ成绩:/n");scanf("%d",&student[m].grade[0]);
printf("请输入该学生的微积分Ⅲ成绩:/n");scanf("%d",&student[m].grade[1]);
printf("请输入该学生的线性代数成绩:/n");scanf("%d",&student[m].grade[2]);
printf("请输入该学生的大学英语成绩:/n");scanf("%d",&student[m].grade[3]);
printf("请输入该学生的大学物理成绩:/n");scanf("%d",&student[m].grade[4]);
printf("请输入该学生的c语言程序设计成绩:/n");scanf("%d",&student[m].grade[5]);
printf("请输入该学生的信号与信息处理成绩:/n");scanf("%d",&student[m].grade[6]);
printf("请输入该学生的全校性选修课成绩:/n");scanf("%d",&student[m].grade[7]);
}
int SearchByStuID(char stuID[]) //用学号查询的函数
{
int i;
for(i=0;i<N;i++)
{
if(strcmp(stuID,student[i].StuID)==0) return i;
}
return -1;
}
int SearchByName(char name[]) //用姓名查询的函数
{
int i;
for(i=0;i<N;i++)
{
if(strcmp(name,student[i].Name)==0) return i;
}
return -1;
}
void studentgrade(void) //求学生总分的函数 一个函数值实现一个功能
{ //代码健壮 引用方便
int i,j;
for(i=0;i<N;i++) //将全局变量sum数组重新初始化为零
{
sum[i]=0;
}
for(m=0;m<N;m++) //for循环的嵌套用于求每个学生的总分
{
for(j=0;j<8;j++)
{
sum[m]+=student[m].grade[j];
}
}
}
int SearchByGrade(int grade) //用成绩查询的函数
{
int k;
for(k=0;k<N;k++)
{
if(sum[k]==grade)return k;
}
return -1;
}
void sort(void) //将学生的总分从高到低进行排序
{
int i,j,k;
for(i=0;i<N;i++){a[i]=sum[i];}
for(i=0;i<N-1;i++) //所使用的是冒泡排序法
{
for(j=0;j<N-1-i;j++)
{
if(a[j]<a[j+1])
{
k=a[j];a[j]=a[j+1];a[j+1]=k;
}
}
}
}
void SortByGrade(void) //用于输出名次的函数,包含学生的基本信息和总分
{
int flag=0,i,b=1;
studentgrade();
sort();
for(i=0;i<N;i++)
{
if(a[i]!=0)
{
struct stu *p;
m=SearchByGrade(a[i]);
p=&student[m];
printf("第%d名:/n",b);
printf("学号:/t");printf("%s/n",p->StuID);
printf("姓名:/t");printf("%s/n",p->Name);
printf("总成绩:/t");printf("%d/n/n",a[i]);
b++;flag++;
}
else continue;
}
if(flag==0)printf("/n/t/t没有可以显示的排名./n/n");
}
double Variance(void) //用于计算学生总分成绩标准差(波动情况)的函数
{
int i;
double average,total=0.0,Total=0.0;
studentgrade();
for(i=0;i<N;i++)
{
total+=sum[i];
}
average=total/30.0;
for(i=0;i<N;i++)
{
Total+=fabs(average-sum[i])*fabs(average-sum[i]);
}
Total/=30.0;
return sqrt(Total);
}
void Faillist(void) //列出不及格的学生的科目及成绩
{
int j,k,flag=0;
for(j=0;j<N;j++)
{
for(k=0;k<=7;k++)
{
if(student[j].grade[k]!=0&&student[j].grade[k]<60)
{
printf("学号: %-s 姓名: %-s ",student[j].StuID,student[j].Name);
printf("不及格的科目为: ");
switch(k)
{
case 0:printf("微积分Ⅱ");break;
case 1:printf("微积分Ⅲ");break;
case 2:printf("线性代数");break;
case 3:printf("大学英语");break;
case 4:printf("大学物理");break;
case 5:printf("c语言程序设计");break;
case 6:printf("信号与信息处理");break;
case 7:printf("全校性选修课");break;
}
printf("/t分数: %-d/n/n",student[j].grade[k]);
flag++;
}
}
}
if(flag==0)printf("/t/t没有不及格的学生./n/n");
}
void Save(void)
{
char ch;
int i,j;
while(1)
{
fflush(stdin); //清空屏幕缓冲区,防止其它字符的干扰
printf("请问您需要保存数据吗?[Y/N]/n");
ch=getchar();
fflush(stdin);
if(ch=='y'||ch=='Y')
{
fp=fopen("E://STU_DATA.txt","w");
fprintf(fp,"%d /n/n",index);
for(i=0;i<N;i++)
{
fprintf(fp,"%d %s %s %s %d %d %s /n",student[i].Class,
student[i].StuID,student[i].Name,student[i].Sex,
student[i].Age,student[i].Number,student[i].Phone);
for(j=0;j<=7;j++)
fprintf(fp,"%d ",student[i].grade[j]);
fprintf(fp,"/n/n");
}
fclose(fp);printf("/n/t/t保存文件成功!/n/t/t按任意键退出系统./n");break;
}
else if(ch=='n'||ch=='N')
{printf("/n/t/t文件没有保存!/n/t/t按任意键退出系统/n.");break;}
else printf("/n/t/t您的操作有误./n/t/t请重新选择.../n");
}
}
void Menu(void) //主菜单界面
{
printstar(58);
printf(" 中南大学教务信息管理系统 /n");
printstar(58);
printf(" 设计者 彭苑/n");
printf(" 所有权利保留/n/n");
printf("请选择您的操作:/n"); //这是我自己的劳动成果,所以仿照下商业软件
printstar(58); //Copyright,All Rights Reserved
printf(" 1.录入学生数据 2.删除学生数据 3.修改学生数据/n");
printf(" 4.学生数据查询 5.学生成绩统计 6.退出管理系统/n");
printstar(58);
}
void Menu1(void) //对应于主菜单1选项的分菜单
{
int n,i,a;
while(1)
{
printf("/n请选择您的操作:/n");
printstar(58);
printf(" 1.全部顺序录入 2.录入单个数据 3.返回主菜单/n");
printstar(58);
scanf("%d",&n);
switch(n)
{
case 1:a=index;
while(Index()) Getdatatofree();
index=a;
for(i=index;i<N;i++)
{
Getdata(index);
};break;
case 2:if(Index()){a=index;Getdatatofree();index=a;break;}Getdata(index);break;
case 3:return;
default :printf("/t/t您的操作有误./n请重新选择.../n");break;
}
}
}
void Menu2(void) //第二个分菜单
{
int i,n;
char string[11];
while(1)
{
printf("请选择您的操作:/n");
printstar(58);
printf(" 1.删除全部数据 2.删除单个数据 3.返回主菜单/n");
printstar(58);
scanf("%d",&n);
switch(n)
{
case 1:for(i=0;i<N;i++)Deletedata(i);index=0;
printf("/t/t删除全部数据成功!/n/n");getch();break;
case 2:printf("请输入该学生的学号:/n");scanf("%s",string);
m=SearchByStuID(string);
if(m!=-1)
{Deletedata(m);empty[m]=m+1;printf("/n/t/t删除数据成功!/n");}
else printf("数据不存在或已删除!");getch(); break;
case 3:return;
default :printf("/t/t您的操作有误./n请重新选择.../n");break;
}
}
}
void Menu3(void) //第三个分菜单
{
int n;
char string[13];
while(1)
{
printf("请选择您的操作:/n");
printstar(58);
printf(" 1.按学号修改 2.按姓名修改 3.返回主菜单/n");
printstar(58);
scanf("%d",&n);
switch(n)
{
case 1:printf("请输入所查询学生的学号:");scanf("%s",string);
m=SearchByStuID(string);Renewdata();break;
case 2:printf("请输入所查询学生的姓名:");scanf("%s",string);
m=SearchByName(string);Renewdata();break;
case 3:return;
default :printf("/t/t您的操作有误./n请重新选择.../n");break;
}
}
}
void Menu4(void) //第四个分菜单
{
int i,n;
char string[13];
while(1)
{
printf("/n请选择您的操作:/n");
printstar(58);
printf(" 1.显示全部数据 2.按学号查询 3.按姓名查询 4.返回主菜单/n");
printstar(58);
scanf("%d",&n);
switch(n)
{
case 1:if(index==0)
{printf("/t/t数据不存在或已经全部删除!/n");getch();break;}
p=student;
if(p->Class!=0)
{
p=student;
m=0;
for(i=0;i<N;i++)
{
if(i==29)
{
Printalldata();
p++;m++;
printf("/n/t/t全部数据显示完毕./n按任意键返回上一级菜单.../n/n");
getch();
return;
}
Printalldata();
p++;m++;
printf("/n按Esc键退出.按任意键输出下一组数据.../n/n");
if(getch()==27)return;
}
}
else printf("/t/t该项数据不存在或已删除!/n");
case 2:printf("请输入学号:");scanf("%s",string);m=SearchByStuID(string);
printf("/n/t/t正在搜索,请稍后.../n查询的结果如下:/n");
Printdata(m);
getch();break;
case 3:printf("请输入姓名:");scanf("%s",string);m=SearchByName(string);
printf("/n/t/t正在搜索,请稍后.../n查询的结果如下:/n");
Printdata(m);
getch();break;
case 4:return;
default :printf("/t/t您的操作有误./n请重新选择.../n");break;
}
}
}
void Menu5(void) //第五个分菜单
{
int n;
while(1)
{
printf("请选择您的操作:/n");
printstar(58);
printf("1.学生成绩排名 2.学生成绩标准差 3.不及格清单 4.返回主菜单/n");
printstar(58);
scanf("%d",&n);
switch(n)
{
case 1:SortByGrade();break;
case 2:printf("学习成绩的标准差为:/t");printf("%.2f/n/n",Variance());break;
case 3:Faillist();break;
case 4:return; //return语句用来结束该函数的调用,而exit函数用来结束整个程序
default :printf("/t/t您的操作有误./n请您重新选择.../n");break;
}
}
}
void Getdata(int a) //用来录入数据的函数
{
char ch;
printf("请输入第%d个学生的数据:/n",a+1);
printf("班级:/n");scanf("%d",&student[a].Class);
printf("学号:/n");scanf("%s",&student[a].StuID);
printf("姓名:/n");scanf("%s",&student[a].Name);
printf("性别:/n");scanf("%s",&student[a].Sex);
printf("年龄:/n");scanf("%d",&student[a].Age);
printf("宿舍号码:/n");scanf("%d",&student[a].Number);
printf("手机号码:/n");scanf("%s",&student[a].Phone);
printf("继续输入学生成绩?[Y/N]");
ch=getche();
while(1)
{
if(ch=='y'||ch=='Y')
{
InputGrade(a);index++;return;
}
else if(ch=='n'||ch=='N'){index++;printf("/n/n");return;}
else printf("/t/t您的操作有误./n请重新输入:");
}
printf("/n/n");
}
void Deletedata(int i) //用来删除单个学生数据的函数
{
int j;
student[i].Class=0;
for(j=0;j<11;j++)student[i].StuID[j]='/0';
for(j=0;j<13;j++)student[i].Name[j]='/0';
for(j=0;j<5;j++)student[i].Sex[j]='/0';
student[i].Age=0;
student[i].Number=0;
for(j=0;j<12;j++)student[i].Phone[j]='/0';
for(j=0;j<8;j++)student[i].grade[j]=0;
}
int Index(void) //该函数用来判断是否删除过学生数据以及删除过多少数据
{ //方便以后的顺序插入数据
int i,flag=0;
for(i=0;i<N+1;i++)
if(empty[i]!=0)flag++;
return flag;
}
void Getdatatofree(void) //用于插入数据的函数
{
int i;
for(i=0;i<N+1;i++)
if(empty[i]!=0)
{
Getdata(i);empty[i]=0;break;
}
}
void Renewdata(void) //用于修改学生数据的函数
{
int n;
printf("/n/t/t正在搜索,请稍后.../n您所查询的学生现有数据为:/n");Printdata(m);
if((student[m].Class!=0)&&(m!=-1))
{
printf("/n请选择您要修改的项:/n");
printstar(58);
printf("1.班级 2.学号 3.姓名 4.性别 5.年龄/n");
printf("6.宿舍号码 7.手机号码 8.学习成绩 9.返回上级菜单/n");
printstar(58);
}
else
{printf("/t/t您查询的数据不存在./n按任意键返回上一级菜单.../n");getch();return;}
scanf("%d",&n);
switch(n)
{
case 1:printf("请输入新的班级:");scanf("%d",&student[m].Class);break;
case 2:printf("请输入新的学号:/n");scanf("%s",&student[m].StuID);break;
case 3:printf("请输入新的姓名:/n");scanf("%s",&student[m].Name);break;
case 4:printf("请输入新的性别:/n");scanf("%s",&student[m].Sex);break;
case 5:printf("请输入新的年龄:/n");scanf("%d",&student[m].Age);break;
case 6:printf("请输入新的宿舍号码:/n");scanf("%d",&student[m].Number);break;
case 7:printf("请输入新的手机号码:/n");scanf("%s",&student[m].Phone);break;
case 8:InputGrade(m);break;
case 9:return;
default :printf("/t/t您的操作有误./n");break;
}
}
void Printdata(int n) //用于向屏幕输出单个学生数据的函数
{
p=&student[n];
if(n<0||n>N-1||p->Class==0)
printf("/t/t该项数据不存在或已删除!/n/n");
else
{
printf("班级%d/t/t",p->Class);
printf("学号%s/n",p->StuID);
printf("姓名%s/t",p->Name);
printf("性别%s/t",p->Sex);
printf("年龄%d/n",p->Age);
printf("寝室号码%d/t/t/t",p->Number);
printf("电话号码%s/n/n",p->Phone);
printf("微积分Ⅱ%d/t/t",student[m].grade[0]);
printf("微积分Ⅲ%d/t/n",student[m].grade[1]);
printf("线性代数%d/t/t",student[m].grade[2]);
printf("大学英语%d/t/n",student[m].grade[3]);
printf("大学物理%d/t/t",student[m].grade[4]);
printf("c语言程序设计%d/t/n",student[m].grade[5]);
printf("信号与信息处理基础%d/t/t",student[m].grade[6]);
printf("全校性选修课%d/t/n/n",student[m].grade[7]);
}
}
void Printalldata(void) //用于输出所有学生数据的函数,函数体本身不包含循环
{
if(p->Class==0)
printf("/t/t该项数据不存在或已删除!/n/n");
else
{
printf("/t/t基本信息:/n");
printf("班级/t%d/t/t",p->Class);
printf("学号/t%s/n",p->StuID);
printf("姓名/t%s/t/t",p->Name);
printf("性别/t%s/t/t",p->Sex);
printf("年龄/t%d/n",p->Age);
printf("寝室号码/t%d/t/t/t/t",p->Number);
printf("电话号码/t%s/n/n",p->Phone);
printf("/t/t学习成绩:/n");
printf("微积分Ⅱ/t%d/t/t/t/t",student[m].grade[0]);
printf("微积分Ⅲ/t%d/n",student[m].grade[1]);
printf("线性代数/t%d/t/t/t/t",student[m].grade[2]);
printf("大学英语/t%d/n",student[m].grade[3]);
printf("大学物理/t%d/t/t/t/t",student[m].grade[4]);
printf("c语言程序设计/t%d/n",student[m].grade[5]);
printf("信号与信息处理/t%d/t/t/t/t",student[m].grade[6]);
printf("全校性选修课/t%d/n",student[m].grade[7]);
}
}
int main() //主函数
{ //主函数比较简洁 体现了结构化编程的思想
int i,j;
fp=fopen("E://STU_DATA.txt","r"); //在D盘已只读方式打开名为STU_DATA的文件
if((fp=fopen("E://STU_DATA.txt","r"))==NULL) //如果文件打开失败 返回空指针类型
printf("创建文件失败!/n");
else
{
printf("文件打开成功!/n");
fscanf(fp,"%d /n/n",&index); //将学生数据写入文件
for(i=0;i<N;i++)
{
fscanf(fp,"%d %s %s %s %d %d %s /n",&student[i].Class,
student[i].StuID,student[i].Name,student[i].Sex,
&student[i].Age,&student[i].Number,student[i].Phone);
for(j=0;j<=7;j++)
fscanf(fp,"%d ",&student[i].grade[j]);
fprintf(fp,"/n/n");
}
fclose(fp); //关闭文件
}
while(1)
{
int n;
char a[10];
Menu();
scanf("%s",a);
n=atoi(a); //atoi函数用来将字符型数据转化为整型数据
switch(n) //其参数为字符串的首地址,须用到stdlib.h头文件
{ //atoi函数用来防止误输入字符数据而造成的死循环
case 1:Menu1();break;
case 2:Menu2();break;
case 3:Menu3();break;
case 4:Menu4();break;
case 5:Menu5();break;
case 6:Save();getch();return 0; //选项6是退出系统,会提示是否保存文件
default :printf("/t/t 您的操作有误./n/t/t 请重新选择.../n/n");break;
}
}
}