一、实验题目
学生信息管理系统V5.0
某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入)。定义结构体类型,用结构体数组作函数参数,编程实现如下菜单驱动的学生成绩管理系统:
(1)录入每个学生的学号、姓名和各科考试成绩;
(2)计算每门课程的总分和平均分;
(3)计算每个学生的总分和平均分;
(4)按每个学生的总分由高到低排出名次表;
(5)按每个学生的总分由低到高排出名次表;
(6)按学号由小到大排出成绩表;
(7)按姓名的字典顺序排出成绩表;
(8)按学号查询学生排名及其考试成绩;
(9)按姓名查询学生排名及其考试成绩;
(10)按优秀(90-100)、良好(80-89)、中等(70-79)、及格(60-69)、不及格(0-59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;
(11)输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分
二、工具环境
Window10操作系统,Microsoft Visual C++2010学习版 集成开发环境,C语言
三、实验问题
初始化结构体指针的代码放在自定义函数里无法初始化 (下面代码简写)
问题1:
#include<stdio.h>
#include<malloc.h>
#define STUD_N 30
#define OVERFLOW -2
typedef struct{
int number;
}Student;
int InitList(Student *L){//初始化
L=(Student *)malloc( STUD_N*sizeof(Student) );
if(!L) exit(OVERFLOW);
return 0;
}
int main()
{
Student *L;
InitList(L);
return 0;
}
编译会出
warning: 'L' is used uninitialized in this function
(警告:在此函数中未初始化使用了’L’)
问题2:
#include<stdio.h>
#include<malloc.h>
#define STUD_N 30
#define OVERFLOW -2
typedef struct{
int number;
}Student;
int InitList(Student **L){//初始化
*L=(Student *)malloc( STUD_N*sizeof(Student));
if(!L) exit(OVERFLOW);
return 0;
}
int main()
{
Student *L;
InitList(L);
return 0;
}
编译会出
warning: passing argument 1 of 'InitList’ from incompatible pointer type [enabled by default]
warning: 'L' is used uninitialized in this function
(警告:从不兼容的指针类型传递参数1 InitList[默认启用] 警告:在此函数中未初始化使用了’L’ )
所以最后初始化代码放到了主函数里能运行了QAQ
四、实验代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define STUD_N 30 // 最多学生人数
#define COURSE_N 6 // 考试科目数
#define OVERFLOW -2
typedef struct{
int number;//学号
char name[STUD_N+1];
int grade[COURSE_N+1];
int sum;
float avg;
int order;//序号
}Student;
void input(Student *L,int subject_n,int student_n){//输入学生信息
int i,j;
for(i=0;i<student_n;i++){
printf("\t请输入第%d个学生的学号、姓名和各科成绩\n",i+1);
printf("\t请输入学号:");scanf("%d",&L[i].number);
printf("\t请输入姓名:");scanf("%s",L[i].name);
printf("\t——注意:学科成绩采用百分制——\n");
for(j=0;j<subject_n;j++){
printf("\t请输入第%d个学生的第%d门学科成绩:",i+1,j+1);
scanf("%d",&L[i].grade[j]);
while(L[i].grade[j]>100 || L[i].grade[j]<0){
printf("\t成绩不符合要求,请重新输入第%d门学科成绩:",i+1);
scanf("%d",&L[i].grade[j]);}
}printf("\n\n");
}
}
void output(Student *L,int subject_n,int student_n){//输出学生信息
int i,j;
for(i=0;i<student_n;i++){
printf("\t学号:%d\n",L[i].number);
printf("\t姓名:%s\n",L[i].name);
for(j=0;j<subject_n;j++){
printf("\t第%d门学科成绩:%d\n",j+1,L[i].grade[j]);
}printf("\n\n");
}
}
int Descending(int a,int b)//降序
{
return a<b;
}
int Ascending(int a,int b)//升序
{
return a>b;
}
void Order(int student_n,Student *L,int (*compare)(int a,int b))//总分排序
{ //函数指针
int i,j;
Student A;
for(i=0;i<student_n;i++){//交换序号
for(j=i+1;j<student_n;j++){
if((*compare)(L[i].sum,L[j].sum)){
A=L[i];
L[i]=L[j];
L[j]=A;
}
}
}
for(i=0;i<student_n;i++){
L[i].order=i+1;
}
}
void ouputall_1(int student_n,int subject_n,Student *L)//输出按学号的排名
{
int i;
switch(subject_n)
{
case 1:
printf("学号 姓名 成绩 总分 平均分\n");
printf("-------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%8d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].sum,L[i].avg);
}
break;
case 2:
printf("学号 姓名 第1科成绩 第2科成绩 总分 平均分\n");
printf("-------------------------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%13d%13d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].sum,L[i].avg);
}
break;
case 3:
printf("学号 姓名 第1科成绩 第2科成绩 第3科成绩 总分 平均分\n");
printf("--------------------------------------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%13d%13d%13d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].sum,L[i].avg);
}
break;
case 4:
printf("学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 总分 平均分\n");
printf("---------------------------------------------------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%13d%13d%13d%13d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].sum,L[i].avg);
}
break;
case 5:
printf("学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 总分 平均分\n");
printf("----------------------------------------------------------------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].sum,L[i].avg);
}
break;
case 6:
printf("学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 第6科成绩 总分 平均分\n");
printf("-----------------------------------------------------------------------------------------------------------\n");
for(i=0;i<student_n ;i++){
printf("%4d%8s%13d%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].grade[5],L[i].sum,L[i].avg);
}
break;
}
}
void ouputall_2(int student_n,int subject_n,Student *L,int n)//按学号查询排名和成绩
{
int i;
switch(subject_n)
{
case 1:
printf("名次 学号 姓名 成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%8d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].sum,L[i].avg);
break;
}
}
break;
case 2:
printf("名次 学号 姓名 第1科成绩 第2科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].sum,L[i].avg);
}
}
break;
case 3:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].sum,L[i].avg);
}
}
break;
case 4:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].sum,L[i].avg);
}
}
break;
case 5:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].sum,L[i].avg);
}
}
break;
case 6:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 第6科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(L[i].number==n){
printf("%4d%8d%8s%13d%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].grade[5],L[i].sum,L[i].avg);
}
}
break;
}
}
void ouputall_3(int student_n,int subject_n,Student *L,char s[])//按姓名查询排名和成绩
{
int i;
switch(subject_n)
{
case 1:
printf("名次 学号 姓名 成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%8d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].sum,L[i].avg);
}
}
break;
case 2:
printf("名次 学号 姓名 第1科成绩 第2科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%13d%13d%8d%8.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].sum,L[i].avg);
}
}
break;
case 3:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].sum,L[i].avg);
}
}
break;
case 4:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].sum,L[i].avg);
}
}
break;
case 5:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].sum,L[i].avg);
}
}
break;
case 6:
printf("名次 学号 姓名 第1科成绩 第2科成绩 第3科成绩 第4科成绩 第5科成绩 第6科成绩 总分 平均分\n");
for(i=0;i<student_n;i++){
if(strcmp(L[i].name,s)==0){
printf("%4d%8d%8s%13d%13d%13d%13d%13d%13d%8d%9.2f\n",L[i].order,L[i].number,L[i].name,L[i].grade[0],L[i].grade[1],L[i].grade[2],L[i].grade[3],L[i].grade[4],L[i].grade[5],L[i].sum,L[i].avg);
}
}
break;
}
}
int main()//---------------------------------主函数---------------------------------
{
system("color f1");
int student_n=0;int subject_n=0;int i,j;
Student *L;
L=(Student *)malloc( STUD_N*sizeof(Student) );//初始化
Student A;
int great[6]={0},well[6]={0},middle[6]={0},pass[6]={0},fail[6]={0};//记录学科等级人数以及百分比
float g_percent[6]={0},w_percent[6]={0},m_percent[6]={0},p_percent[6]={0},f_percent[6]={0};
printf("\n");
printf("\t——欢迎使用学生信息管理系统V5.0——\n");
printf("\t首先确定班级人数(不超过30):"); scanf("%d",&student_n);
while(student_n>30 || student_n<1)
{
printf("\t请重新输入班级人数(不超过30):"); scanf("%d",&student_n);
}
printf("\t再确定科目数量(不超过6):"); scanf("%d",&subject_n);
while(subject_n>6 || subject_n<1)
{
printf("\t请重新输入科目数量(不超过6):"); scanf("%d",&subject_n);
}
printf("\t请录入学生的学号、姓名和各科成绩:\n\n");
printf("\t请输入第%d个学生的学号、姓名和各科成绩:\n",i+1);
input(L,subject_n,student_n);
printf("\t 录入完成\n");printf("\n");
int sum_student[STUD_N]={0},sum_subject[STUD_N]={0};//每个学生总成绩和平均分初始化0
float avg_student[STUD_N]={0},avg_subject[STUD_N]={0};//每个学科总成绩和平均分初始化0
//计算学科总分和平均分
for(i=0;i<subject_n;i++){
for(j=0;j<student_n;j++){
sum_subject[i]+=L[j].grade[i];
}
avg_subject[i]=(float)sum_subject[i]/student_n;
}
//计算学生总分和平均分
for(i=0;i<student_n;i++){
for(j=0;j<subject_n;j++){
sum_student[i]+=L[i].grade[j];
}
avg_student[i]=(float)sum_student[i]/subject_n;
L[i].avg=avg_student[i];
L[i].sum=sum_student[i];
}
Order(student_n,L,Descending);//默认总分按降序排名
printf("\t------------------------------------\n");
printf("\t——欢迎使用学生信息管理系统V5.0——\n");
printf("\t0. 退出学生信息管理系统V5.0\n");
printf("\t1. 计算每门课程的总分和平均分\n");
printf("\t2. 计算每个学生的总分和平均分\n");
printf("\t3. 按每个学生的总分由高到低排出名次表\n");
printf("\t4. 按每个学生的总分由低到高排出名次表\n");
printf("\t5. 按学号由小到大排出成绩表\n");
printf("\t6. 按姓名的字典顺序排出成绩表\n");
printf("\t7. 按学号查询学生排名及其考试成绩\n");
printf("\t8. 按姓名查询学生排名及其考试成绩\n");
printf("\t9. 按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类型的人数以及所占的百分比\n");
printf("\t10. 输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分\n\n");
int choose;
while(1)
{
printf("\t请输入你要选择的功能前的序号:");
scanf("%d",&choose);
if(choose==0) break;
switch(choose)
{
case 1://"1. 计算每门课程的总分和平均分\n");
printf("\n");
printf("\t1. 计算每门课程的总分和平均分\n");
for(i=0;i<subject_n;i++){
printf("\t第%d个门学科总分:%d,平均分:%0.2f\n",i+1,sum_subject[i],avg_subject[i]);
}printf("\n");
break;
case 2://"2. 计算每门学生的总分和平均分\n");
printf("\n");
printf("\t2. 计算每个学生的总分和平均分\n");
for(i=0;i<student_n;i++){
printf("\t%s的总分:%d,平均分:%0.2f\n",L[i].name,L[i].sum,L[i].avg);
}printf("\n");
break;
case 3://3. 按每个学生的总分由高到低排出名次表\n");
printf("\n");
printf("\t3. 按每个学生的总分由高到低排出名次表\n");
printf("\t名次 学号 姓名 总分\n");
for(i=0;i<student_n ;i++){
printf("\t%4d%8d%8s%8d\n",i+1,L[i].number,L[i].name,L[i].sum);
}printf("\n");
break;
case 4://4. 按每个学生的总分由低到高排出名次表\n");
printf("\n");
printf("\t4. 按每个学生的总分由低到高排出名次表\n");
Order(student_n,L,Ascending);
printf("\t倒数 学号 姓名 总分\n");
for(i=0;i<student_n ;i++){
printf("\t%4d%8d%8s%8d\n",i+1,L[i].number,L[i].name,L[i].sum);
}printf("\n");
Order(student_n,L,Descending);//默认按总分降序排序
break;
case 5://5. 按学号由小到大排出成绩表\n");
printf("\n");
printf("\t5. 按学号由小到大排出成绩表\n");
for(i=0;i<student_n;i++){//交换学号
for(j=i+1;j<student_n;j++){
if(L[i].number>L[j].number){
A=L[i];
L[i]=L[j];
L[j]=A;
}
}
}
ouputall_1(student_n,subject_n,L);printf("\n");
Order(student_n,L,Descending);//默认按总分降序排序
break;
case 6://6. 按姓名的字典顺序排出成绩表\n");
printf("\n");
printf("\t6. 按姓名的字典顺序排出成绩表\n");
for(i=0;i<student_n ;i++){
for(j=i+1;j<student_n ;j++){
if(strcmp(L[i].name,L[j].name)>0){
A=L[i];
L[i]=L[j];
L[j]=A;
}
}
}
ouputall_1(student_n,subject_n,L);printf("\n");
Order(student_n,L,Descending);//默认按总分降序排序
break;
case 7://7. 按学号查询学生排名及其考试成绩\n");
printf("\n");
printf("\t7. 按学号查询学生排名及其考试成绩\n");
int n;
printf("\t请输入你要查询的学生的学号:");scanf("%d",&n);
ouputall_2(student_n,subject_n,L,n);printf("\n");
break;
case 8://8. 按姓名查询学生排名及其考试成绩\n");
printf("\n");
printf("\t8. 按姓名查询学生排名及其考试成绩\n");
char s[20];
printf("\t请输入你要查询的学生的姓名:");scanf("%s",s);
ouputall_3(student_n,subject_n,L,s); printf("\n");
break;
case 9://9. 按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类型的人数以及所占的百分比\n");
printf("\n");
printf("\t9. 按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类型的人数以及所占的百分比\n");
for(i=0;i<subject_n;i++){
for(j=0;j<student_n;j++){
if(L[j].grade[i]>=90 &&L[j].grade[i]<=100){
great[i]++;}
else if(L[j].grade[i]>=80 &&L[j].grade[i]<90){
well[i]++;}
else if(L[j].grade[i]>=70 &&L[j].grade[i]<80){
middle[i]++;}
else if(L[j].grade[i]>=60 &&L[j].grade[i]<70){
pass[i]++;}
else{
fail[i]++;}
}
}
for(i=0;i<subject_n;i++){
g_percent[i]=(float)great[i]/student_n*100;
w_percent[i]=(float)well[i]/student_n*100;
m_percent[i]=(float)middle[i]/student_n*100;
p_percent[i]=(float)pass[i]/student_n*100;
f_percent[i]=(float)fail[i]/student_n*100;
}
printf(" 优秀人数 良好人数 中等人数 及格人数 不及格人数\n");
for(i=0;i<subject_n;i++){
printf("第%d门成绩%8d%12d%12d%12d%14d\n",i+1,great[i],well[i],middle[i],pass[i],fail[i]);
printf("所占百分比%7.2f%%%12.2f%%%12.2f%%%12.2f%%%12.2f%%\n",g_percent[i],w_percent[i],m_percent[i],p_percent[i],f_percent[i]);
}printf("\n");
break;
case 10://10. 输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分\n");
printf("\n");
printf("\t10. 输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分\n");
ouputall_1(student_n,subject_n,L);
switch(subject_n)
{
case 1:
printf("-------------------------------------\n");
printf(" 课程总分%8d\n",sum_subject[0]);
printf(" 课程平均分%8.2f\n",avg_subject[0]);
break;
case 2:
printf("-------------------------------------------------------\n");
printf(" 课程总分%13d%13d\n",sum_subject[0],sum_subject[1]);
printf(" 课程平均分%13.2f%13.2f\n",avg_subject[0],avg_subject[1]);
break;
case 3:
printf("--------------------------------------------------------------------\n");
printf(" 课程总分%13d%13d%13d\n",sum_subject[0],sum_subject[1],sum_subject[2]);
printf(" 课程平均分%13.2f%13.2f%13.2f\n",avg_subject[0],avg_subject[1],avg_subject[2]);
break;
case 4:
printf("---------------------------------------------------------------------------------\n");
printf(" 课程总分%13d%13d%13d%13d\n",sum_subject[0],sum_subject[1],sum_subject[2],sum_subject[3]);
printf(" 课程平均分%13.2f%13.2f%13.2f%13.2f\n",avg_subject[0],avg_subject[1],avg_subject[2],avg_subject[3]);
break;
case 5:
printf("----------------------------------------------------------------------------------------------\n");
printf(" 课程总分%13d%13d%13d%13d%13d\n",sum_subject[0],sum_subject[1],sum_subject[2],sum_subject[3],sum_subject[4]);
printf(" 课程平均分%13.2f%13.2f%13.2f%13.2f%13.2f\n",avg_subject[0],avg_subject[1],avg_subject[2],avg_subject[3],avg_subject[4]);
break;
case 6:
printf("-----------------------------------------------------------------------------------------------------------\n");
printf(" 课程总分%13d%13d%13d%13d%13d%13d\n",sum_subject[0],sum_subject[1],sum_subject[2],sum_subject[3],sum_subject[4],sum_subject[5]);
printf(" 课程平均分%13.2f%13.2f%13.2f%13.2f%13.2f%13.2f\n",avg_subject[0],avg_subject[1],avg_subject[2],avg_subject[3],avg_subject[4],avg_subject[5]);
break;
}printf("\n");
break;
}
}
return 0;
}//---------------------------------主函数---------------------------------
五、解决方法
方法1:
使用指针函数初始化
#include<stdio.h>
#include<malloc.h>
#define STUD_N 30
#define OVERFLOW -2
typedef struct{
int number;
}Student;
Student* InitList(){//使用指针函数初始化
Student *L=(Student *)malloc( STUD_N*sizeof(Student));
if(!L) exit(OVERFLOW);
return L;
}
int main()
{
Student *L;
L=InitList();
return 0;
}
问题1中函数 int InitList(Student *L) 的参数 Student *L 传的是主函数结构体指针L的形参,在函数内部创建后又随着函数结束而被释放了
方法2:
二级指针做函数参数
#include<stdio.h>
#include<malloc.h>
#define STUD_N 30
#define OVERFLOW -2
typedef struct{
int number;
}Student;
int InitList(Student **L){//二级指针做函数参数进行初始化
*L=(Student *)malloc( STUD_N*sizeof(Student));
if(!L) exit(OVERFLOW);
return 0;
}
int main()
{
Student *L;
InitList(&L);//在问题2中使用错误,缺少&
return 0;
}
问题2中使用二级指针的方式错误