中国地质大学(武汉)
C语言课程设计报告书
姓 名:
专 业:
班级学号:
指导老师:
一﹑题目要求
已知文本文件f1.txt中存放了某校应届大四学生的相关信息(不超过5000人),具体数据及存放格式为:每行存放一个学生的数据,共有7项,依次为:学号、姓名、专业必修课平均成绩、科技活动奖励加分、社会活动奖励加分、是否有专业必修课挂科记录、是否通过大学英语四级。
其中,学号为8位数字字符,其中前2位数字表示学生所在的学院,第3位数字表示学生的专业,第4-5位数字表示学生的年级,统一为09,第6位数字表示学生所在年级同专业内的编号,即所称的班号,第7-8位数字表示学生班级内的序号,如学号07509123表示,机电学院(07)通信工程专业(5)09级(09)1班(1)第23号(23)学生;姓名为长度不超过10个的字符;专业必修课平均成果、科技活动奖励加分、社会活动奖励加分均为0-100以内的整数(含0和100);是否有专业必修课挂科记录、是否通过大学英语四级均为0或1两个整型数字,为1分别表示有专业必修课挂科记录或通过大学英语四级,为0分别表示没有专业必修课挂科记录或没有通过大学英语四级。
该校的保研政策是:必须没有专业必修课挂科记录且通过大学英语四级考试,在此前提下,划分推免研究生指标。外推指标按专业排名,给予2%的指标,小数部分四舍五入。内推指标按班级排名,给予15%的指标,小数部分四舍五入。如果某班有外推指标,外推指标不占内推指标。排名计算方法:专业必修课成绩占60%,科技活动奖励占30%,社会活动奖励占10%。
请编写程序,读出文件f1.txt中的内容,再按保研政策确定每个人的保研状况(0表示没有获得推免资格,1表示获得内推资格,2表示获得外推资格)并存入f2.txt中,并实现以下功能:
(1)能够统计某个班所有获得保研资格的学生信息。
(2)能够统计某个专业所有获得保研资格的学生信息。
(3)能够统计哪个班获得的保研资格的学生人数最多。
(4)能够统计全校所有获得外推资格的学生名单,其结果即可屏幕显示,也可存入文件。
(5)学生可以根据姓名和学号查询自己是否获得保研资格。
说明:
①系统程序要有界面
②存入文件f2.txt中的数据,每行存一个学生的数据,每行之间的不同信息用空格分隔。
二、题目分析
根据题目可以知道,首先要打开f1.txt并读取里面的内容。然后对其中的信息进行分析筛选,根据外推或者内推的条件对学生进行分类排序。除此以外,还要提供选择菜单实现功能选择,再建立一个文件把筛选分析后的学生信息存放进去以便查询。
处理数据时,主要是排序和比较,由于学生的学号里面包含了学生的所在学院、专业、班级以及在班级的序号,所以要把学号的每一位分开处理。在确定外推时要注意,只有专业必修课没有挂科记录而且大学英语通过四级的学生才有划分资格。在确定内推名单时要注意,已经获得外推资格的学生不再参加内推划分。
经过分析,程序的大概流程为:
三、设计思路
1.设计选择菜单
根据题目要求,程序能够统计某个班级、某个专业获得保研资格的学生信息,能够统计哪个班获得保研资格的学生人数最多,能够统计全校所有获得外推资格的学生名单,学生还可以根据自己的姓名和学号查询自己是否获得保研资格。因此,首先要设计一个选择菜单实现功能选择。
2.打开f1.txt,另外再建立一个文件存放处理后的数据
由于学生的原始信息存放于f1.txt中,所以必须先打开并读取这个文件,然后才能对里面的数据进行分析筛选。建立一个f2.txt,把处理后的学生信息写入f2.txt中。
3.将没有参加保研资格的学生找出来
根据题目可以知道,必须没有专业必修课挂科记录而且通过大学英语四级考试的学生才有资格参加划分推免研究生,所以要把有专业必修课挂科记录或者大学英语四级没有通过的学生排除,对没有保研资格的学生标记为0。建立一个文件f3.txt,把剩下的学生信息写入f3.txt中。
4.打开f3.txt,对里面的数据进行处理
该校的保研政策分为外推和内推,分别标记为2和1。
(1).外推指标按专业排名,取前百分之二(小数部分四舍五入),所以要把f3.txt里面的数据按专业进行分类。而专业代号是学号的第三位数字,要注意的是,专业相同的前提是学生所在的学员必须相同,所以同专业的学生学号的前三位必定是一样的。按专业分类好后,再对同专业的学生进行排名编号,排名按综合成绩计算(综合成绩=专业必修课成绩的百分之六十+科技活动奖励分的百分之三十+社会活动奖励分的百分之十)。假设某专业有n个学生,则按综合成绩进行排名编号后,编号小于n*0.02(小数部分四舍五入)的学生有外推资格,标记为2。
(2).内推指标按班级排名,取前百分之十五(小数部分四舍五入)。如果某班有外推指标,外推指标不占内推指标。所以先要把班级相同的学生分类,班级代号为第六位。由于同班级的前提是必须同学院、同专业,所以学号前六位一样的学生在同一个班级。按班级划分后,还要排除已经获得外推资格的学生,排除后再对该班剩下的学生进行排名编号,排名按综合成绩计算(综合成绩=专业必修课成绩的百分之六十+科技活动奖励分的百分之三十+社会活动奖励分的百分之十)。假设某班级排除外推的有n个学生,则按综合成绩进行排名编号后,编号小于n*0.15(小数部分四舍五入)的学生有内推资格,标记为1。
(3).将没有获得保研资格的学生标记为0,有内推资格的学生标记为1,有外推资格的学生标记为2,将标记后的学生数据存入f2.txt中。
5.统计哪个班获得保研资格的人数最多
打开f2.txt,将学生按班级分类之后,把每个班的标号为1或者是2的学生人数统计出来相应的记为k。例如,第n个班级保研人数记为k[n]。比较k的大小从而找出保研人数最多的那个班级n。
6.打开文件f2.txt,建立文件f4.txt,将获得外推资格(即标号为2)的学生信息写入f4.txt中。
四、实现结果
1、主函数
void menu()
{
int n;
printf("******************** Menu *****************\n");
printf("* *\n");
printf("* 1.显示数据 2.班级保研状况 *\n");
printf("* *\n");
printf("* 3. 专业保研状况 4. 保研人数最多的班级*\n");
printf("* *\n");
printf("* 5. 全校外推状况 6. 查询 *\n");
printf("* *\n");
printf("* 7.退出程序 *\n");
printf("*******************************************\n");
printf("\nPlease input your select(1-7):");
scanf("%d",&n);
while(n<1||n>7)
{
printf("Input error. Please input your select again:");
scanf("%d",&n);
}
}
2、生成学生数据
struct student{
char no[9];//学号
char name[11];//姓名
int bs;//专业必修课平均成绩
int ks;//科技活动奖励加分
int ss;//社会活动奖励加分
int gk;//是否挂科
int sj;//英语四级考试是否通过
int grade;//综合成绩
}s[5000];
void generate()
{
FILE *fp;//定义一个指向文件型数据的指针变量
int n,i,j,t;
printf("Please input the total of student:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
s[i].no[0]=rand()%3+'0';
s[i].no[1]=rand()%10+'0';
s[i].no[2]=rand()%6+'0';
s[i].no[3]='0';
s[i].no[4]='9';
s[i].no[5]=rand()%7+'0';
s[i].no[6]=rand()%3+'0';
s[i].no[7]=rand()%10+'0';
s[i].no[8]='\0';
t=rand()%10;
while(!t)
t=rand()%10;
for(j=0;j<t;j++)
s[i].name[j]=rand()%26+'a';
s[i].name[j]='\0';
s[i].bs=rand()%101;
s[i].ks=rand()%101;
s[i].ss=rand()%101;
t=rand()%10;
if(t<=8)
s[i].gk=0;
else
s[i].gk=1;
t=rand()%10;
if(t<=8)
s[i].sj=1;
else
s[i].sj=0;
}
if((fp=fopen("f1.txt","w"))==NULL)
{
printf("File open error.\n");
exit(0);
}
for(i=0;i<n;i++)
fprintf(fp,"%s %s %d %d %d %d %d\n",s[i].no,s[i].name,s[i].bs,s[i].ks,s[i].ss,s[i].gk,s[i].sj);
fclose(fp);
}
3、排除没有保研资格的人并标记
4、确定外推名额
五、课设总结
这次C语言课程设计对我来说是一个极大的挑战。虽然平时的理论知识学得还可以,但运用到实践中就不那么简单了。
刚拿到题目我就有点害怕,一页多的题目,看了第一遍没看懂是什么意思。好在题目理解方面老师允许提问,而且题目本身已经给出许多提示。第一天课程设计,花了一下午的时间终于搞懂题目,有了点思路。虽然有思路,但是不能把想法付诸行动跟失败没什么两样。
我把书上关于结构体、文件以及数组的运用又复习了一遍,还看了老师以前讲过的例题,发现这道题跟最后一节课讲的高考录取划线问题很相似。我把那道题找出来仔细地看了一下,结合这道题的条件开始着手编写程序。开始的生成数据我就花了很长时间,后来老师把这一部分编好了,我们只需要对生成的数据进行处理就行了。在处理数据的过程中,我遇到了一个难题,因为没有想到用字符数组来表示学号,总想着怎么根据学号把相同专业和相同班级的学生分类,所以程序没能做下去。
这次课程设计我要好好检讨自己。因为遇到一点困难就没有战胜它的信心,导致整个程序没能完成。失败的主要原因还是在我自己,没有做够的耐心和信心。编了一段程序执行的时候有时会出现很多错误,改正这些错误也需要很大的耐心。这次课程设计失败了,但是我从中学到了很多书本上没有的知识。我学的专业是通信工程,将来还有很多用到C语言的地方。理论知识的学习是为了能够运用,所以,以后我会更加注重实践。当然,理论知识也有待强化。虽然C语言课结束了,但我会继续努力,将C语言学以致用。
六、源代码
#include <stdio.h>
#include <stdlib.h>
int total;
struct student{
char no[9];//学号
char name[11];//姓名
int bs;//专业必修课平均成绩
int ks;//科技活动奖励加分
int ss;//社会活动奖励加分
int gk;//是否挂科
int sj;//英语四级考试是否通过
int grade;//综合成绩
}s[5000];
void menu();
void generate();
void banjibaoyan();
void zhuanyebaoyan();
void max()
void sort(int n);
void quanxiao();
void chaxun();
void main()
{
menu();
}
void menu()
{
int n;
printf("******************** Menu *****************\n");
printf("* *\n");
printf("* 1.显示数据 2.班级保研状况 *\n");
printf("* *\n");
printf("* 3. 专业保研状况 4. 保研人数最多的班级*\n");
printf("* *\n");
printf("* 5. 全校外推状况 6. 查询 *\n");
printf("* *\n");
printf("* 7.退出程序 *\n");
printf("*******************************************\n");
printf("\nPlease input your select(1-7):");
scanf("%d",&n);
while(n<1||n>7)
{
printf("Input error. Please input your select again:");
scanf("%d",&n);
}
switch(n)
{
case 1:generate();break;
case 2:banji();break;
case 3:zhuanye();break;
case 4:max;break;
case 5:quanxiao();break;
case 6:chaxun();break;
case 7:exit(0);
}
}
/////////////////////////////////////////////////
void generate()
{
FILE *fp;//定义一个指向文件型数据的指针变量
int n,i,j,t;
printf("Please input the total of student:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
s[i].no[0]=rand()%3+'0';
s[i].no[1]=rand()%10+'0';
s[i].no[2]=rand()%6+'0';
s[i].no[3]='0';
s[i].no[4]='9';
s[i].no[5]=rand()%7+'0';
s[i].no[6]=rand()%3+'0';
s[i].no[7]=rand()%10+'0';
s[i].no[8]='\0';
t=rand()%10;
while(!t)
t=rand()%10;
for(j=0;j<t;j++)
s[i].name[j]=rand()%26+'a';
s[i].name[j]='\0';
s[i].bs=rand()%101;
s[i].ks=rand()%101;
s[i].ss=rand()%101;
t=rand()%10;
if(t<=8)
s[i].gk=0;
else
s[i].gk=1;
t=rand()%10;
if(t<=8)
s[i].sj=1;
else
s[i].sj=0;
}
if((fp=fopen("f1.txt","w"))==NULL)
{
printf("File open error.\n");
exit(0);
}
for(i=0;i<n;i++)
fprintf(fp,"%s %s %d %d %d %d %d\n",s[i].no,s[i].name,s[i].bs,s[i].ks,s[i].ss,s[i].gk,s[i].sj);
fclose(fp);
}
/////////////////////////////////////////////////////////////
void baoyan()//能否保研
{
int i,j,grade,n;
FILE *fp;
FILE *fp1;
FILE *fp2;
if((fp2=fopen("f1.txt","r"))==NULL)
{
printf("File open error.\n");
exit(0);
}
fscanf(fp2,"%d",&n);
fclose(fp2);
if((fp=fopen("f1.txt","r"))==NULL)
{
printf("File open error.\n");
exit(0);
}
for(i=0;i<n;i++)
{
fscanf(fp,"%s %s %d %d %d %d %d\n",&s[i].no,&s[i].name,&s[i].bs,&s[i].ks,&s[i].ss,&s[i].gk,&s[i].sj);
}
fclose(fp);
if((fp1=fopen("f2.txt","w"))==NULL)
{
printf("File open error.\n");
exit(0);
}
for(j=0;j<n;j++)
{
grade=s[j].bs*0.6+s[j].ks*0.3+s[j].ss*0.1;
if(s[j].gk==1||s[j].sj==0)
{
fprintf(fp1,"%s %s %d %d %d %d %d %d %d\n",s[j].no,s[j].name,s[j].bs,s[j].ks,s[j].ss,s[j].gk,s[j].sj,0,grade);
}
}
fclose(fp1);
}
///////////////////////////////////////////////////////////////////////////
void waitui()
{
int m,i;
FILE *fp;
if((fp=fopen("f1.txt","r"))==NULL)
{
printf("File open error.\n");
exit(0);
}
i=0;
while( !feof(fp) )
{ if(s[i].gk==0&&s[i].sj==1)
fscanf(fp,"%s %s %d %d %d %d %d\n",s[i].no,s[i].name,&s[i].bs,&s[i].ks,&s[i].ss,&s[i].gk,&s[i].sj);
continue;
i++;
}
total=i;
fclose(fp);
sort(total);
if((fp=fopen("f2.txt","w"))==NULL)
{
printf("File open error.\n");
exit(0);
}
m=(int)(i*0.02+0.5);//确定外推人数(四舍五入)
for(i=0;i<=m;i++)
fprintf(fp,"%s %s %d %d %d %d %d\n",s[i].no,s[i].name,s[i].bs,s[i].ks,s[i].ss,s[i].gk,s[i].sj);//将有外推资格的学生信息输出到fp指向的文件中
fclose(fp);
printf("waitui success!\n");
getchar();
getchar();
system("cls");
}
void sort(int n)
{
int t;
int i;
int j;
for(i=0;i<n;i++)
{
j=i+1;
if(s[i].bs>s[j].bs)
{
t=i;
i=j;
j=t;
continue;
}
}
}