【程序设计与实践】实验六:学生成绩管理

【程序设计与实践】实验六:学生成绩管理

设计一个菜单驱动的学生成绩管理程序,管理n个学生的m门考试科目成绩,实现以下基本功能。

(1)能够新增学生信息,并计算总分和平均分。
(2)能够根据学号修改和删除某学生信息。
(3)能够显示所有学生的成绩信息。
(4)能够分别按总分和学号进行排序。
(5)能够根据学号查询该学生的基本信息。
(6)学生成绩数据最终保存在文件中,能够对文件读、写学生数据。
程序运行时,菜单形式如下。
Management for Students's scores
1.AppenD、record
2.List record
3.Delete record
4.Modify record
5.Search record
6.Sort in descending order by sum
7.Sort in ascending order by sum
8.Sort in descending order by num
9.Sort in ascending order by num
W.Write to A、File
R.ReaD、from A、File
0.Exit
Please input your choice:

要求用模块化方式组织程序结构,合理设计各个自定义函数。同时,程序能够进行异常处理,检查用户输入数据的有效性,在用户输入数据有错误(如类型错误)或无效时,不会中断程序的执行,程序具有一定的健壮性。
在这里插入图片描述

代码:

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <string.h>
#include <string.h>
#include <conio.h>
#include <bits/stdc++.h>
using namespace std;

long size;    

/*当前最近一次的流水号*/
                
struct LogData{                    /*记录的结构*/
    long logid;             
    long id;
    char name[50];      
    double sum;   
	double ave;           
    double s[20];   
	int cnt;           
};


int inputchoice()/*选择操作参数*/
{
	system("cls");
	int mychoice;
	cout<<endl;
	cout<<"              程序设计与实践     实验(六) 学生成绩管理"<<endl<<endl;
	cout<<"                                               "<<endl<<endl<<endl<<endl;
	cout<<"	   --------------------------学生成绩管理---------------------------"<<endl<<endl;
	cout<<"		   1.新增学生信息 			2.删除学生信息"<<endl<<endl;
	cout<<"		   3.显示所有学生信息			4.学生信息排序"<<endl<<endl;
	cout<<"		   5.查询学生信息			6.修改学生信息"<<endl<<endl;
	cout<<"		   0.退出"<<endl;
	cout<<"	   -----------------------------------------------------------------"<<endl<<endl;
	cout<<"	   请选择:";
	cin>>mychoice;
	return mychoice; 
}

bool cmp1(struct LogData log1,struct LogData log2){
	return log1.sum>log2.sum;
}

bool cmp2(struct LogData log1,struct LogData log2){
	return log1.id<log2.id;
}

long getLogcount(FILE *cfp)     /*获取文件记录总数*/
{  
    long begin,end,logcount;
    fseek(cfp,0L,SEEK_SET);       //SEEK_SET文件头
    begin=ftell(cfp);            //ftell用于得到文件位置指针当前位置相对于文件首的偏移字节数
    fseek(cfp,size,SEEK_END);    //SEEK_END文件尾
    end=ftell(cfp);
    logcount=(end-begin)/size-1;
    return logcount;
}

void AddNewLog(FILE *cfp)             /*添加新记录*/
{
    struct LogData log,lastlog;
    log.sum=0;
    long logcount;
    int i=0;
    double score=0;
    printf("Input name:");
    scanf("%s",log.name);
    printf("Input id:");
    cin>>log.id;
    printf("Input score(-1):");
    while(1){
    	cin>>score;
    	if(score!=-1){
    		log.s[i]=score;
    		i++;
    		log.sum+=score;
		}
		else if(score==-1)	break;
	}
	log.cnt=i;
	log.ave=log.sum/log.cnt;
	
    logcount=getLogcount(cfp);                    /*获取记录数*/
	if(logcount>0){
        fseek(cfp,size*(logcount-1),SEEK_SET);    /*fseek函数设置文件指针cfp的位置(从SEEK_SET开始移动size*(logcount-1))*/
        fread(&lastlog,size,1,cfp);              /*读入最后记录*/
		log.logid=lastlog.logid+1;                    /*记录号按顺序是上次的号+1*/
    }
    else{                                        /*如果文件是初始,记录数为0*/
        log.logid=1;
    }
    rewind(cfp);//重设文件指针
    getch();    //等待按下任意键,再继续执行下面的语句
    fwrite(&log,sizeof(struct LogData),1,cfp);    /*写入记录*/
    fclose(cfp);
}

void ListAllLog(FILE *cfp)                /*列出所有收支流水帐*/
{
    struct LogData log;
    long logcount;
    logcount=getLogcount(cfp);
    if(logcount>0){                        /*表示有记录存在*/    
        fseek(cfp,0L,SEEK_SET);            /*定位指针到文件开始位置,0L—不移动*/
        fread(&log,size,1,cfp);            /*1.读取到的位置指针 2.一个对象的字节大小 3.对象个数 4.要读的目标指针*/
        printf("LogID    Name       ID      Sum       Ave    \n");
        while(!feof(cfp)){                //检测文件结束符,如果文件结束,则返回非0值,否则返回0
            printf("%5ld  %-12s %6ld %6.2lf %6.2lf     ",
log.logid,log.name,log.id,log.sum,log.ave);
for(int j=0;j<log.cnt;j++)	cout<<setw(5)<<log.s[j];
cout<<endl;
            fread(&log,size,1,cfp);
        }
    }
    else    printf("no logs in file!\n");
    
    printf("\n");
    printf("Press any key to continue...");
    
    system("pause");
}

void QueryLog(FILE *cfp)              
{
	struct LogData log[1000],*plog=log;    /*假定文件不超过1000记录*/

    long logcount,id,i,index=-1;

     printf("Input id:");
     scanf("%ld",&id);                      

/*查找帐户号是否存在,若存在则更新*/
    logcount=getLogcount(cfp);                /*获取记录数*/
    rewind(cfp);
    fread(plog,size,logcount,cfp);            //相当于copy?从文件中读到数组中
    for(i=0;i<logcount;i++){
        if(id==log[i].id){            /*已经找到*/
            printf("LogID    Name       ID      Sum       Ave    \n");
            printf("%5ld  %-12s %6ld %6.2lf %6.2lf     ",
log[i].logid,log[i].name,log[i].id,log[i].sum,log[i].ave);
for(int j=0;j<log[i].cnt;j++)	cout<<setw(5)<<log[i].s[j];
cout<<endl;
            break;
           }
    }
    
	if(i>=logcount)	printf("no logs in file!\n");
    
    printf("\n");
    printf("Press any key to continue...");
    getch();

}

void Sortlog(FILE *cfp){
	FILE *fp1;
	
	struct LogData log[1000],*plog=log;    /*假定文件不超过1000记录*/
    long logcount;
    logcount=getLogcount(cfp);                /*获取记录数*/
    rewind(cfp);
    fread(plog,size,logcount,cfp);            //相当于copy?从文件中读到数组中
    
	int c;
	cout<<"按照 1.总分 或者 2.学号 排序:"<<endl;
	cin>>c;
	if(c==1){
		stable_sort(log,log+logcount,cmp1);
		fp1=fopen("cashbox.dat","wb+");  
  		fwrite(plog,size,logcount,fp1);
  		fclose(fp1);
		ListAllLog(cfp);
	}
	else if(c==2){
			stable_sort(log,log+logcount,cmp2);
		fp1=fopen("cashbox.dat","wb+");  
  		fwrite(plog,size,logcount,fp1);
  		fclose(fp1);
		ListAllLog(cfp);
	}
	else	cout<<"Error!"<<endl;
}

/*函数功能:查询记录 ID 并更新账户记录*/
void Updatelog(FILE *cfp){
    struct LogData log[1000],*plog=log;    /*假定文件不超过1000记录*/
//plog=log数组首地址?

    long logcount,id,i,index=-1;

     printf("InputID:");
     scanf("%ld",&id);                        /*输入要修改的记录 ID*/

/*查找帐户号是否存在,若存在则更新*/
    logcount=getLogcount(cfp);                /*获取记录数*/
    rewind(cfp);
    fread(plog,size,logcount,cfp);            //相当于copy?从文件中读到数组中
    for(i=0;i<logcount;i++){
        if(id==log[i].id){            /*已经找到*/
            printf("LogID    Name       ID      Sum       Ave    \n");
            printf("%5ld  %-12s %6ld %6.2lf %6.2lf     ",
log[i].logid,log[i].name,log[i].id,log[i].sum,log[i].ave);
for(int j=0;j<log[i].cnt;j++)	cout<<setw(5)<<log[i].s[j];
cout<<endl;
            index=i;
            break;
           }
    }
    
    if(index>=0){
    	int j=0;
    	double score=0;
    	printf("Input name:");
    	scanf("%s",log[index].name);
    	printf("Input id:");
    	scanf("%ld",&log[index].id);
    	printf("Input score(-1):");
    while(1){
    	cin>>score;
    	if(score!=-1){
    		log[index].s[j]=score;
    		j++;
    		log[index].sum+=score;
		}
		else if(score==-1)	break;
	}
	log[index].cnt=j;
	log[index].ave=log[index].sum/log[index].cnt;
			
       rewind(cfp);
        fwrite(plog,size,logcount,cfp);        /*更新回文件*/
 
    }
    else{  
        printf("Error logid and try another!\n");
        printf("Press any key to continue...");
        getch();
    }
     fclose(cfp);
}


/*函数功能:查询记录 ID 并删除该账户记录*/
void Deletelog(FILE *cfp){
    FILE *fp1;
    struct LogData log[1000],*plog=log;/*假定文件不超过 1000 记录*/
    long logcount,id,i,index=-1;

    printf("Input ID:");
    scanf("%ld",&id);                /*输入要删除的记录 ID*/

/*查找帐户号是否存在,若存在则更新*/
    logcount=getLogcount(cfp);            /*获取记录数*/
    rewind(cfp);
    fread(plog,size,logcount,cfp);         //从文件中读到数组中
    for(i=0;i<logcount;i++){
        if(id==log[i].id){         /*已经找到,显示当前记录*/
            printf("LogID    Name       ID      Sum       Ave    \n");
            printf("%5ld  %-12s %6ld %6.2lf %6.2lf     ",
log[i].logid,log[i].name,log[i].id,log[i].sum,log[i].ave);
for(int j=0;j<log[i].cnt;j++)	cout<<setw(5)<<log[i].s[j];
cout<<endl;
            index=i;
               getch();
               break;
        }
    }
    printf("\n");
    
    rewind(cfp);
    if(index>=0){
        for(i=index;i<=logcount-1;i++){    //将index之后的数据整体前移
              log[i].logid=i+1;
              strcpy(log[i].name,log[i+1].name);
              log[i].id=log[i+1].id;
              log[i].sum=log[i+1].sum;
              log[i].ave=log[i+1].ave;
              log[i].cnt=log[i+1].cnt;
              memcpy(log[i].s,log[i+1].s,log[i+1].cnt);
              
        }
    getch();
    fp1=fopen("cashbox.dat","wb+");  
    fwrite(plog,size,logcount-1,fp1);/*写回去更新*/
    fclose(fp1);
     }

    else{
        printf("Error logid and try another!\n");
          printf("Press any key to continue...");
          getch();
    }
}


int main(void)
{
    FILE *fp;
    int choice;
    if((fp=fopen("cashbox.dat","ab+"))==NULL){ 
        printf("can not open file cashbox.dat!\n");
        exit(0);//退出程序
    }
    size=sizeof(struct LogData);
    while((choice=inputchoice())!=0){
        switch(choice){
            case 1:
                fp=fopen("cashbox.dat", "ab+");
                AddNewLog(fp);break;/*添加新记录*/

            case 2:
                fp=fopen("cashbox.dat", "rb+");
                Deletelog(fp);break;
                
            case 3:
                 fp=fopen("cashbox.dat", "ab+");
                ListAllLog(fp);break;
                
            case 4:
                fp=fopen("cashbox.dat", "ab+");
                Sortlog(fp);break;
                
            case 5:
                fp=fopen("cashbox.dat", "ab+");
                QueryLog(fp);break;
                
            case 6:
                fp=fopen("cashbox.dat", "rb+");
                Updatelog(fp);break;
                
            default:
                printf("Input Error.");break;
        }
    }
    
    if(fclose(fp)){//如果关闭成功返回 0,否则返回EOF(-1)
        printf( "Can not close the file!\n" );
        exit(0);//退出程序
    }
    
}

  • 12
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值