【CS34913】LAB-4 基于文件的信息管理系统

目  录

第1章 实验基本信息... - 2 -

1.1 实验目的... - 2 -

1.2 实验环境与工具... - 2 -

1.2.1 硬件环境... - 2 -

1.2.2 软件环境... - 2 -

1.2.3 开发工具... - 2 -

第2章 小型成绩管理系统... - 3 -

2.1 小型成绩管理系统总体设计(4分)... - 3 -

2.2 主要功能模块设计(25分)... - 3 -

2.2.1成绩录入(3分)... - 3 -

2.2.2成绩查询(3分)... - 3 -

2.2.3成绩修改(3分)... - 3 -

2.2.4成绩删除(4分)... - 4 -

2.2.5成绩计算(4分)... - 4 -

2.2.6成绩排序(4分)... - 4 -

2.2.7成绩统计分析(4分)... - 5 -

第1章 实验基本信息

(本章满分1)

1.1 实验目的

    • 掌握结构化数据排序方法及文件相关操作
    • 掌握共享库的建立与使用
    • 掌握模块化程序设计和增量测试方法
    • (选)掌握跨平台程序编写、调试方法

  

1.2 实验环境与工具

1.2.1 硬件环境

1.2.2 软件环境

1.2.3 开发工具

    • gcc、g++;vi/vim/gedit

第2章 小型成绩管理系统

(本章满分29)

2.1 小型成绩管理系统总体设计(4分)

(1)班级人数最多45人(具体人数由键盘输入确定)

(2)成绩科目包括计算机系统(iCS)、程序设计实践(PDP)、数据结构(DS)、数字逻辑(DL)4门课程

  • 程序功能要求

(1)通过键盘录入每个学生的学号、姓名和各科成绩;

(2)按姓名查询学生成绩,并显示;

(3)按学号查询学生成绩,并显示;

(4)修改某个学生成绩;

(5)删除某个学生成绩;

(6)计算每个学生总成绩和平均成绩,并显示;

(7)计算班级各科平均成绩,并显示;

(8)按某一科成绩由高到低排序,并显示(包括其他科目成绩);

(9)按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)五个类别,对每科成绩分别统计每个类别的人数及所占的百分比,并显示结果;

(10)导出,以文本或二进制文件形式输出1、4、5的结果,文本文件每行一个记录;

(11)导入,从文本或二进制文件读入所有学生成绩信息;

(12)退出。

2.2 主要功能模块设计(25分)

2.2.1成绩录入(3分)

从键盘输入至少5名学生的成绩,必须包括本人的信息。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
//input:学生数量n
//output:指向学生结构体数组的指针
//function:通过键盘录入每个学生的学号、姓名和各科成绩
STUDENT* append_record(int n)
{
  STUDENT *stu;
  stu = (STUDENT*)malloc(sizeof(STUDENT) * n);
  if (stu == NULL)
  {
    printf("内存分配失败\n");
    return NULL;
  }
  for (int i = 0; i < n; i++)
  {
    printf("请输入第%d个学生的学号、姓名和各科成绩\n", i + 1);
    if (scanf("%ld %255s %f %f %f %f", &stu[i].id, stu[i].name, &stu[i].score.ics, &stu[i].score.pdp, &stu[i].score.ds, &stu[i].score.dl) != 6)
    {
      printf("输入格式错误\n");
      free(stu); 
      return NULL;
    }
    printf("第%d个学生的学号、姓名和各科成绩输入成功!\n", i + 1);
  }
  return stu;
}

2.2.2成绩查询(3分)

以姓名查询本人的成绩。

相关函数代码与说明:

输入:结构体数组指针stu,学生人数n,学生姓名name

输出:指向查询的学生的结构体指针

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
#include <string.h>
//
//
//
STUDENT* search_by_name(STUDENT * stu,int n,char * name)
{
  for(int i=0;i<=n-1;i++)
  {
    if(!strcmp(stu[i].name,name))
    {
      return stu+i;
    }
  }
  return NULL;
}

2.2.3成绩修改(3分)

以学号找到自己成绩并修改。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
//
//
//
STUDENT* search_by_id(STUDENT * stu,int n,unsigned long iid)
{
  for(int i=0;i<=n-1;i++)
  {
    if(stu[i].id==iid)
    {
      return &stu[i];
    }
  }
  return NULL;
}
#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
//
//
//
int modify(STUDENT *stu,int n,STUDENT *stu1)
{
  for(int i=0;i<=n-1;i++)
  {
    if(stu1->id==stu[i].id)
    {
      stu[i].score.ics=stu1->score.ics;
      stu[i].score.pdp=stu1->score.pdp;
      stu[i].score.ds=stu1->score.ds;
      stu[i].score.dl=stu1->score.dl;
      return 1;
    }
  }
  return 0;
}


输入:结构体数组指针stu,学生数量n,要查询的学生的结构体指针stu1

输出:1代表修改成功

功能:按学号修改学生成绩

2.2.4成绩删除(4分)

以学号为索引删掉本人成绩记录。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
//
//
//
int delect(STUDENT *stu,int n,STUDENT *stu1)
{
  for(int i=0;i<=n-1;i++)
  {
   if (stu1->id == stu[i].id)
   {
      for (int j = i; j < n - 1; j++) 
      {
         stu[j] = stu[j + 1];
      }
            return 1;
    }
  }
  return 0;
}


输入:结构体数组指针stu,学生数量n,要查询的学生的结构体指针stu1

输出:1代表删除成功

功能:按学号删除学生成绩

2.2.5成绩计算(4分)
计算各科平均成绩并显示。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
//
//
//
/*typedef struct course
{
	float ics;
	float pdp;
	float ds;
	float dl;
}COURSE;*/
void caculate_aver(STUDENT *stu,int n)
{
  double ics_total=0;
  double pdp_total=0;
  double ds_total=0;
  double dl_total=0;
  for(int i=0;i<=n-1;i++)
  {
    ics_total+=stu[i].score.ics;
    pdp_total+=stu[i].score.pdp;
    ds_total+=stu[i].score.ds;
    dl_total+=stu[i].score.dl;
  }
  double ics_aver=ics_total/n;
  double pdp_aver=pdp_total/n;
  double ds_aver=ds_total/n;
  double dl_aver=dl_total/n;
printf("该班级ics课程平均成绩为:%.2lf,\npdp课程平均成绩为:%.2lf,\nds课程平均成绩为:%.2lf,\ndl课程平均成绩为:%.2lf,\n",ics_aver,pdp_aver,ds_aver,dl_aver);
}

输入:结构体数组指针stu,学生数量n

输出:null
功能:计算各科平均成绩

2.2.6成绩排序(4分)

任意一科成绩为准进行降序排序。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"


void sort_dl(STUDENT *stu, int n)
{
    for (int i = 1; i < n; i++)
    {
        STUDENT temp = stu[i];
        int k = i - 1;
        while (k >= 0 && stu[k].score.dl < temp.score.dl)
        {
            stu[k + 1] = stu[k];
            k--;
        }
        stu[k + 1] = temp;
    }
}


#include <stdio.h>
#include <stdlib.h>
#include "manage.h"


void sort_ds(STUDENT *stu, int n)
{
    for (int i = 1; i < n; i++)
    {
        STUDENT temp = stu[i];
        int k = i - 1;
        while (k >= 0 && stu[k].score.ds < temp.score.ds)
        {
            stu[k + 1] = stu[k];
            k--;
        }
        stu[k + 1] = temp;
    }
}


#include <stdio.h>
#include <stdlib.h>
#include "manage.h"


void sort_ics(STUDENT *stu, int n)
{
    for (int i = 1; i < n; i++)
    {
        STUDENT temp = stu[i];
        int k = i - 1;
        while (k >= 0 && stu[k].score.ics < temp.score.ics)
        {
            stu[k + 1] = stu[k];
            k--;
        }
        stu[k + 1] = temp;
    }
}


 

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"


void sort_pdp(STUDENT *stu, int n)
{
    for (int i = 1; i < n; i++)
    {
        STUDENT temp = stu[i];
        int k = i - 1;
        while (k >= 0 && stu[k].score.pdp < temp.score.pdp)
        {
            stu[k + 1] = stu[k];
            k--;
        }
        stu[k + 1] = temp;
    }
}


输入:结构体数组指针stu,学生数量n

输出:null

功能:插入排序实现成绩降序。这里我一时没有想到更好的办法,于是干脆对四门课程各自封装了排序函数,从main函数中实现判断并调用。

2.2.7成绩统计分析(4分)

按五个类别,对每科成绩分别统计每个类别的人数及所占的百分比。

相关函数代码与说明:

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
#include <string.h> // 包含字符串操作的头文件

void analysis(STUDENT *stu, int n) {
    float *s[4];
    s[0] = &(stu->score.ics);
    s[1] = &(stu->score.pdp);
    s[2] = &(stu->score.ds);
    s[3] = &(stu->score.dl);

    char str[4][5];
    strcpy(str[0], "ics");
    strcpy(str[1], "pdp");
    strcpy(str[2], "ds");
    strcpy(str[3], "dl");

    for (int j = 0; j <= 3; j++) {
        int exe = 0;
        int good = 0;
        int mid = 0;
        int pass = 0;
        int bad = 0;
        for (int i = 0; i <= n - 1; i++) {
            float ans = *(s[j] + i); // 获取分数
            if (ans >= 90 && ans <= 100)
                exe++;
            else if (ans >= 80 && ans <= 89)
                good++;
            else if (ans >= 70 && ans <= 79)
                mid++;
            else if (ans >= 60 && ans <= 69)
                pass++;
            else
                bad++;
        }
        printf("科目:%s\n", str[j]);
        printf("优秀成绩人数:%d, 优秀成绩百分比:%.2f%%\n", exe, ((float)exe / n) * 100);
        printf("良好成绩人数:%d, 良好成绩百分比:%.2f%%\n", good, ((float)good / n) * 100);
        printf("中等成绩人数:%d, 中等成绩百分比:%.2f%%\n", mid, ((float)mid / n) * 100);
        printf("及格成绩人数:%d, 及格成绩百分比:%.2f%%\n", pass, ((float)pass / n) * 100);
        printf("不及格成绩人数:%d, 不及格成绩百分比:%.2f%%\n", bad, ((float)bad / n) * 100);
        printf("****************************************\n");
    }
}

输入:结构体数组指针stu,学生数量n

输出:null

功能:分析成绩

注意有关字符串操作在头文件<string.h>中包含。

strcpy()是一个C语言标准库函数,用于将源字符串复制到目标字符串。它的函数原型如下:

char *strcpy(char *dest, const char *src);

参数说明:

dest:目标字符串的指针。
src:源字符串的指针。
strcpy()函数会将源字符串的内容复制到目标字符串中,包括终止字符'\0'。函数返回目标字符串的指针。

2.2.8成绩保存到本地文件

#include <stdio.h>
#include <stdlib.h>
#include "manage.h"
/*typedef struct course
{
	float ics;
	float pdp;
	float ds;
	float dl;
}COURSE;
typedf struct student
{
	unsigned long   id;
	char name[256];
	COURSE  score;
}STUDENT;*/
void save(STUDENT *stu, int n, char *fn) 
{
    FILE *file = fopen(fn, "w");
    if (file == NULL) {
        printf("无法打开文件!\n");
        return;
    }
    
    for (int i = 0; i < n; i++) 
    {
      fprintf(file, "%ld %s %f %f %f %f\n", stu[i].id, stu[i].name, stu[i].score.ics, stu[i].score.pdp, stu[i].score.ds, stu[i].score.dl);
    }
     printf("success to save!\n");
    fclose(file);
}

附:manage.h代码



typedef struct course
{
	float ics;
	float pdp;
	float ds;
	float dl;
}COURSE;
typedef struct student
{
	unsigned long   id;
	char name[256];
	COURSE  score;
}STUDENT;
typedef struct answer
{
  STUDENT *stun;
  int num;
}ans;
STUDENT* append_record(int n);
STUDENT* search_by_name(STUDENT * stu,int n,char * name);
STUDENT* search_by_id(STUDENT * stu,int n,unsigned long iid);
int modify(STUDENT *stu,int n,STUDENT *stu1);
int delect(STUDENT *stu,int n,STUDENT *stu1);
void caculate_total(STUDENT *stu,int n);
void caculate_aver(STUDENT *stu,int n);
void sort_ics(STUDENT *stu, int n);
void sort_pdp(STUDENT *stu, int n);
void sort_ds(STUDENT *stu, int n);
void sort_dl(STUDENT *stu, int n);
void print(STUDENT *stu,int n);
void analysis(STUDENT *stu,int n);
void save(STUDENT *stu, int n, char *fn) ;
ans load(char *fn);

makefile

CC      = gcc -m64 -w


#.. What optimization level for the compilers?
#COPT   = -O2
COPT    = -g


GRARC    = main.a
GRSRCS   = append_record.c load.c modify.c delect.c caculate_total.c caculate_aver.c sort_ics.c sort_pdp.c sort_ds.c sort_dl.c print.c analysis.c save.c search_by_name.c search_by_id.c main.c
GROBJS   = append_record.o load.o modify.o delect.o caculate_total.o caculate_aver.o sort_ics.o sort_pdp.o sort_ds.o sort_dl.o print.o analysis.o save.o search_by_name.o search_by_id.o main.o
HEADER   = manage.h

runfile: $(GROBJS)
	$(CC) $(COPT) -o runfile $(GROBJS) 
main.o: main.c manage.h
	$(CC) $(COPT) -c main.c -o main.o
append_record.o: append_record.c manage.h
	$(CC) $(COPT) -c append_record.c -o append_record.o
load.o: load.c manage.h
	$(CC) $(COPT) -c load.c -o load.o
modify.o: modify.c manage.h
	$(CC) $(COPT) -c modify.c -o modify.o        
delect.o: delect.c manage.h
	$(CC) $(COPT) -c delect.c -o delect.o       
caculate_total.o: caculate_total.c manage.h
	$(CC) $(COPT) -c caculate_total.c -o caculate_total.o   
caculate_aver.o: caculate_aver.c manage.h
	$(CC) $(COPT) -c caculate_aver.c -o caculate_aver.o  
sort_ics.o: sort_ics.c manage.h
	$(CC) $(COPT) -c sort_ics.c -o sort_ics.o
sort_pdp.o: sort_pdp.c manage.h
	$(CC) $(COPT) -c sort_pdp.c -o sort_pdp.o
sort_ds.o: sort_ds.c manage.h
	$(CC) $(COPT) -c sort_ds.c -o sort_ds.o
sort_dl.o: sort_dl.c manage.h
	$(CC) $(COPT) -c sort_dl.c -o sort_dl.o     	
print.o: print.c manage.h
	$(CC) $(COPT) -c print.c -o print.o 
analysis.o: analysis.c manage.h
	$(CC) $(COPT) -c analysis.c -o analysis.o   
save.o: save.c manage.h
	$(CC) $(COPT) -c save.c -o save.o 
search_by_name.o: search_by_name.c manage.h
	$(CC) $(COPT) -c search_by_name.c -o search_by_name.o 
search_by_id.o: search_by_id.c manage.h
	$(CC) $(COPT) -c search_by_id.c -o search_by_id.o  
clean   :
                 

print函数

#include <stdio.h>
#include <stdlib.h>
#include "manage.h" 
void print(STUDENT *stu,int n)
{
  for(int i=0;i<=n-1;i++)
  {
    printf("该学生的学号为%ld,姓名为:%s,ics课程成绩为%.2f,pdp课程成绩为%.2f,ds课程成绩为%.2f,dl课程成绩为%.2f\n",stu[i].id,stu[i].name,stu[i].score.ics,stu[i].score.pdp,stu[i].score.ds,stu[i].score.dl);
  }
}

很简单,但建议单独封装出来,不然会在各种奇奇怪怪的地方报错。

main函数

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "manage.h"
/*头函数部分*/





/*typedef struct course
{
	float ics;
	float pdp;
	float ds;
	float dl;
}COURSE;
typedef struct student
{
	unsigned long   id;
	char name[256];
	COURSE  score;
}STUDENT;
typedef struct answer
{
  STUDENT *stun;
  int num;
}ans;*/
STUDENT* append_record(int n);
STUDENT* search_by_name(STUDENT * stu,int n,char * name);
STUDENT* search_by_id(STUDENT * stu,int n,unsigned long iid);
int modify(STUDENT *stu,int n,STUDENT *stu1);
int delect(STUDENT *stu,int n,STUDENT *stu1);
void caculate_total(STUDENT *stu,int n);
void caculate_aver(STUDENT *stu,int n);
void sort_ics(STUDENT *stu, int n);
void sort_pdp(STUDENT *stu, int n);
void sort_ds(STUDENT *stu, int n);
void sort_dl(STUDENT *stu, int n);
void print(STUDENT *stu,int n);
void analysis(STUDENT *stu,int n);
void save(STUDENT *stu, int n, char *fn) ;
ans load(char *fn);
/*函数声明和结构体定义*/





int main()
{
  
  int card=0;  
  STUDENT *stu;
  int n=0;
START:  
  while(1)
  {
    printf("1. Append record\n");
    printf("2. Search by name\n");
    printf("3. Search by ID\n");
    printf("4. Modify by ID\n");
    printf("5. Delete by ID\n");
    printf("6. Caculate total and average score of every student\n");
    printf("7. Caculate average score of every course\n");
    printf("8. Sort in descending order by course score\n");
    printf("9. Statistic analysis for every course\n");
    printf("10.Save record\n");
    printf("11.Load record\n");
    printf("0. Exit\n");
    printf("Please enter your choice:\n");
    scanf("%d",&card);
    switch(card)
    {
      case 1:
        printf("请输入学生数量\n");
        scanf("%d",&n);
        stu=append_record(n);
        if(stu!=NULL)
        {printf("学生信息录入成功!\n");
        goto START;}
        else
        {printf("录入失败!");
        break;}
      case 2:
        printf("请输入学生的姓名:\n");
        char name[256];
        scanf("%s",name);
        //STUDENT *stu2;
         STUDENT *stu2=(STUDENT *)malloc(sizeof(STUDENT));
        stu2=search_by_name(stu,n,name);
        if (stu2==NULL)
        {
          printf("没有找到这个学生\n");
        }
        else
        {
          printf("该学生的学号为%ld,ics课程成绩为%.2f,pdp课程成绩为%.2f,ds课程成绩为%.2f,dl课程成绩为%.2f\n",stu2->id,stu2->score.ics,stu2->score.pdp,stu2->score.ds,stu2->score.dl);
          // free(stu2);
        }
       
        break;
      case 3:
        printf("请输入学生的学号:\n");
        unsigned long iid=0;
        scanf("%ld",&iid);
        STUDENT *stu3=(STUDENT *)malloc(sizeof(STUDENT));
        stu3=search_by_id(stu,n,iid);
        if(stu3==NULL)
        {
          printf("没有找到这个学生\n");
        }
        else
        {
          printf("该学生的学号为%ld,ics课程成绩为%.2f,pdp课程成绩为%.2f,ds课程成绩为%.2f,dl课程成绩为%.2f\n",stu3->id,stu3->score.ics,stu3->score.pdp,stu3->score.ds,stu3->score.dl);
          //free(stu3);
        }
        
        break;
      case 4:
        printf("请输入要修改的学生的id,以及修改后的ics、pdp、ds、dl成绩\n");
        STUDENT *stu4 = (STUDENT *)malloc(sizeof(STUDENT));
        if (stu4 == NULL) 
        {
          printf("内存分配失败!\n");
          goto START;
        }

        if (scanf("%ld %f %f %f %f", &stu4->id, &stu4->score.ics, &stu4->score.pdp, &stu4->score.ds, &stu4->score.dl) != 5) 
          {
            printf("输入无效!\n");
              free(stu4);
              goto START;
          }

        int re=modify(stu,n,stu4);
        if(re==0)
        {
          printf("没有找到该学生!\n");
        }
        else
        {
          printf("修改成功!\n");
        }
        free(stu4);
        break;
      case 5:
        printf("请输入要删除的学生的id\n");
        STUDENT *stu5=(STUDENT *)malloc(sizeof(STUDENT));
         if (stu5 == NULL) 
        {
          printf("内存分配失败!\n");
          goto START;
        }
        fflush(stdin);
        scanf("%ld", &stu5->id);
        int ret=delect(stu,n,stu5);
        if(ret==0)
        {
          printf("没有找到该学生!\n");
        }
        else
        {
          printf("删除成功!\n");
          n--;
        }
        free(stu5);
        break;
      case 6 :
        if(n==0)
        {
          printf("NO student!\n");
          goto START;
        }
        else
        {
         caculate_total(stu,n);
         break;
        }
      case 7:
       if(n==0)
        {
          printf("NO student!\n");
          goto START;
        }
        else
        {
         caculate_aver(stu,n);
         break;
        }
     case 8:
        printf("请输入要计算的课程名称:ics、pdp、ds或dl\n");
        char sub[32];
        scanf("%s", sub);
        if (strcmp(sub, "ics") == 0)
        { 
          sort_ics(stu,n);
          print(stu, n);
          break;
        }
        else if (strcmp(sub, "pdp") == 0)
        {
          sort_pdp(stu, n);
          print(stu, n);
          break;
        }
        else if (strcmp(sub, "ds") == 0)
        {
          sort_ds(stu, n);
          print(stu, n);
          break;
        }
        else if (strcmp(sub, "dl") == 0)
        {
          sort_dl(stu,n);
          print(stu, n);
          break;
        }
        else
        {
          printf("输入错误!请输入正确的课程!\n");
          break;
        }
      case 9:
        if(n==0)
        {
          printf("NO student!\n");
          goto START;
        }
        else
        {
         analysis(stu,n);
         break;
        }
      case 10:
        printf("请输入要保存到的文件名\n");
        char fn10[256];
        scanf("%s",fn10);
        save(stu,n,&fn10);
        break;
      case 11:
        printf("请输入要读取的文件名\n");
        char fn11[256];
        scanf("%s",fn11);
        ans rete;
        rete=load(&fn11);
        n=rete.num;
        stu=rete.stun;
        printf("success to load!\n");
        break;
      case 0:
        printf("success to quit!\n");
        goto END;
      default:
        printf("input wrong!please input the right number!\n");
        break;
  } 

  }
END:
  return 0;
}

使用while(1)的死循环和goto语句实现反复操作和退出程序。在各个函数中,一定要注意申请完的动态内存在结束前要释放掉。对全局变量的改动要当心。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值