哈尔滨工业大学

 

  1. 实验目的

熟悉一维、二维数组、结构体做函数参数,排序、查找、统计分析等常用算法,自顶向下、逐步求精的模块化设计思想以及增量测试方法,同时发挥出学生个人的主管能动性,创造出有意思的新功能,提高程序的健壮性和可移植性。

  1. 实验内容和要求

1.实验内容

学生成绩管理系统V6.0

某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入)。参考学生成绩管理系统V5.0,定义结构体类型,用结构体数组作函数参数,如果能够把用户输入的数据存盘,下次运行时读出,那就更有用了,编程实现如下菜单驱动的学生成绩管理系统:

(1)录入每个学生的学号、姓名和各科考试成绩;

(2)计算每门课程的总分和平均分;

(3)计算每个学生的总分和平均分;

(4)按每个学生的总分由高到低排出名次表;

(5)按每个学生的总分由低到高排出名次表;

(6)按学号由小到大排出成绩表;

(7)按姓名的字典顺序排出成绩表;

(8)按学号查询学生排名及其考试成绩;

(9)按姓名查询学生排名及其考试成绩;

(10)按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;

(11)输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分;

(12)将每个学生的记录信息写入文件;

(13)从文件中读出每个学生的记录信息并显示。

要求程序运行后先显示如下菜单,并提示用户输入选项:

Management for Students' scores

1.Input record

2.Caculate total and average score of every course

3.Caculate total and average score of every student

4.Sort in descending order by score

5.Sort in ascending order by score

6.Sort in ascending order by number

7.Sort in dictionary order by name

8.Search by number

9.Search by name

10.Statistic analysis

11.List record

12.Write to a file

13.Read from a file

0.Exit

Please Input your choice:

然后,根据用户输入的选项执行相应的操作。

 

请按照下面的定义及函数原型编程

#define   MAX_LEN  10                     /* 字符串最大长度 */

#define   STU_NUM 30                       /* 最多的学生人数 */

#define   COURSE_NUM 6                     /* 最多的考试科目数 */

typedef struct student

{

    long num;  /* 每个学生的学号 */

    char name[MAX_LEN];                   /* 每个学生的姓名 */

    float score[COURSE_NUM];      /* 每个学生COURSE_NUM门功课的成绩 */

    float sum;                       /* 每个学生的总成绩 */

    float aver;                   /* 每个学生的平均成绩 */

}STU;

int   Menu(void);

void  ReadScore(STU stu[], int n, int m);

void  AverSumofEveryStudent(STU stu[], int n, int m);

void  AverSumofEveryCourse(STU stu[], int n, int m);

void  SortbyScore(STU stu[],int n,int m,int (*compare)(float a,float b));

int   Ascending(float a, float b);

int   Descending(float a, float b);

void  SwapFloat(float *x, float *y);

void  SwapLong(long *x, long *y);

void  SwapChar(char x[], char y[]);

void  AsSortbyNum(STU stu[], int n, int m);

void  SortbyName(STU stu[], int n, int m);

void  SearchbyNum(STU stu[], int n, int m);

void  SearchbyName(STU stu[], int n, int m);

void  StatisticAnalysis(STU stu[], int n, int m);

void  PrintScore(STU stu[], int n, int m);

 

输入格式:

( 1 )录入学生的人数:

                 **要求输入数据格式为:"%d"

                 **提示信息为:"Input student number(n<30):\n"

( 2 )录入课程数:

               **要求输入数据格式为:"%d"

               **提示信息为:"Input course number(m<=%d):\n"

( 3 )录入每个学生的学号、姓名和考试成绩: 

               **要求学号、姓名的输入数据格式为:"%ld%s"

               **要求考试成绩的输入数据格式为:"%f"

               **提示信息为:"Input student's ID, name and score:\n"             

 

输出格式:

计算每门课程的总分和平均分:

              **要求输出总分与平均分格式为:"course %d:sum=%.0f,aver=%.0f\n"

计算每个学生的总分和平均分:

              **要求输出总分与平均分格式为:"student %d: sum=%.0f,aver=%.0f\n"

按成绩由高到低排出名次表:

              **要求学号、姓名的输出格式为:"%ld\t%s\t"

              **要求成绩的输出格式为:"%.0f\t"

              **要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

              **提示信息为:"Sort in descending order by score:\n"

按成绩由低到高排出名次表:   

              **要求学号、姓名的输出格式为:"%ld\t%s\t"

              **要求成绩的输出格式为:"%.0f\t"

              **要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

              **提示信息为:"Sort in ascending order by score:\n"

按学号由小到大排出成绩表:     

              **要求学号、姓名的输出格式为:"%ld\t%s\t"

              **要求成绩的输出格式为:"%.0f\t"

              **要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

              **提示信息为:"Sort in ascending order by number:\n"

按姓名的字典顺序排出成绩表      

              **要求学号、姓名的输出格式为:"%ld\t%s\t"

              **要求成绩的输出格式为:"%.0f\t"

              **要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

              **提示信息为:"Sort in dictionary order by name:\n"

按学号查询学生排名及其考试成绩:

               **如果未查到此学号的学生,提示信息为:"Not found!\n";

               **如果查询到该学生

                   # 要求学号、姓名的输出格式为:"%ld\t%s\t"

                   # 要求成绩的输出格式为:"%.0f\t"

                   # 要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

               **提示信息为:"Input the number you want to search:\n"

按姓名查询学生排名及其考试成绩;

               **如果未查到此学号的学生,提示信息为:"Not found!\n";

               **如果查询到该学生

                   # 要求学号、姓名的输出格式为:"%ld\t%s\t"

                   # 要求成绩的输出格式为:"%.0f\t"

                   # 要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

               **提示信息为:"Input the name you want to search:\n"

按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,统计每个类别的人数以及所占的百分比:

                **成绩<60输出提示格式为:"<60\t%d\t%.2f%%\n";

                **成绩=100输出格式为:"%d\t%d\t%.2f%%\n";

                **其他要求输出百分比格式为:"%d-%d\t%d\t%.2f%%\n"

                **提示信息为: "For course %d:\n"

输出每个学生的学号、姓名、考试成绩,以及课程总分和平均分             

              **要求学号、姓名的输出格式为:"%ld\t%s\t"

              **要求成绩的输出格式为:"%.0f\t"

              **要求总分及平均分的输出格式为:"%.0f\t%.0f\n"

选择退出(菜单项0)

                **提示信息:"End of program!"

菜单项选择错误(不在0-11之间)

                **提示信息:"Input error!\n"

 

2.实验要求

采用自顶向下、逐步求精的模块化设计思想设计一个学生管理系统。要求按系统的需求分析、系统设计(总体设计、各个模块的设计)、系统实现(各个模块的实现)、系统测试等过程组织报告内容,说明采用了什么数据结构和算法,遇到哪些问题,这些问题是如何解决的,本设计的亮点和难点在哪里,实验结果如何,有哪些收获和学习体会。

3.系统功能需求分析

学生成绩管理系统 V6.0

(1)录入每个学生的学号、姓名和各科考试成绩;

(2)计算每门课程的总分和平均分;

(3)计算每个学生的总分和平均分;

(4)按每个学生的总分由高到低排出名次表;

(5)按每个学生的总分由低到高排出名次表;

(6)按学号由小到大排出成绩表;

(7)按姓名的字典顺序排出成绩表;

(8)按学号查询学生排名及其考试成绩;

(9)按姓名查询学生排名及其考试成绩;

(10)按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;

(11)输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分;

(12)将每个学生的记录信息写入文件;

(13)从文件中读出每个学生的记录信息并显示。

要求程序运行后先显示如下菜单,并提示用户输入选项:

4.实验环境

采用了Windows 10 操作系统,使用了Codeblocks16.01的开发环境。

所需要函数库文件有<stdio.h>,<string.h>,<stdlib.h>。

  1. 系统设计

  1. 系统功能模块划分

下图是学生成绩管理系统V6.0的程序结构图

展示了该程序系统各个模块之间的结构图

 

2. 算法设计

<>1)2)3)

 

其中比较有亮点的是暗文密码输入系统,保证了输入的安全性。

3. 数据结构设计

3.1数据流图:

 

 

 

3.2顶层数据字典:

采用了结构体储存学生个人信息

#define   MAX_LEN  10                               /* 字符串最大长度 */

#define   STU_NUM 30                                   /* 最多的学生人数 */

#define   COURSE_NUM 6                          /* 最多的考试科目数 */

typedef struct student

{

      long num;                                                 /* 每个学生的学号 */

    char name[MAX_LEN];                   /* 每个学生的姓名 */

    float score[COURSE_NUM];        /* 每个学生COURSE_NUM门功课的成绩 */

    float sum;                                /* 每个学生的总成绩 */

    float aver;                                   /* 每个学生的平均成绩 */

} STU;

 

序号

字段名

字段含义

类型

长度

默认值

说明

  1.  

num

学生学号

long

10

 

 

 

0

 

 

  1.  

name

学生的姓名

char []

10

 

  1.  

score

学生每门功课的成绩

float []

6

 

  1.  

sum

学生总成绩

float

 

 

  1.  

aver

学生品均成绩

float

 

 

  1.  

stu

储存学生信息的结构体

struct []

 

 

 

4.各模块(函数)的功能和接口设计:

4.1各个模块之间的逻辑关系图

模块逻辑关系图如下:

 

  

4.2各个模块的外部接口设计

学生成绩管理系统V6.0:

  1. Main(void):

功能:完成学生数目,课程数目的录入,显示部分信息和函数调用的功能

参数:void

函数返回值:无

  1. int Menu(void);

功能:显示主菜单

参数:void

函数返回值:a(使用者选择函数的功能序号)

  1. void input(STU stu[],int stunum,int cosnum);

功能:录入每个学生的学号、姓名和各科考试成绩;

参数:

STU stu[]:存放学生信息的结构体

int stunum:学生数目的形参

int cosnum:课程数目的形参

函数返回值:无

  1. void  AverSumofEveryStudent(STU stu[], int n, int m);

功能:计算每门课程的总分和平均分;

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  AverSumofEveryCourse(STU stu[], int n, int m);

功能:计算每个学生的总分和平均分

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  SortbyScore(STU stu[],int n,int m,int (*compare)(float a,float b));

功能:按所给函数参数的顺序排出名次表

参数:

STU stu[]:存放学生信息的结构体

int n: 学生数目的形参

int m: 课程数目的形参

int (*compare)(float a,float b): 函数指针compare指向另一个两个浮点型形参的函数。

函数返回值:无

  1. int   Ascending(float a, float b);

功能:按每个学生的总分由低到高排出名次表

参数:

float a: 存放浮点类型数据形参

float b: 存放浮点类型数据形参

函数返回值:a<b

  1. int   Descending(float a, float b);

功能:按每个学生的总分由高到低排出名次表

参数:

float a: 存放浮点类型数据形参

float b: 存放浮点类型数据形参

函数返回值:a>b

  1. void  SwapFloat(float *x, float *y);

功能:交换两个浮点型数据的值

参数:

float *x: 存放浮点类型指针的形参

float *y: 存放浮点类型指针的形参

函数返回值:无

  1. void  SwapLong(long *x, long *y);

功能:交换两个长整型数据的值

参数:

long *x: 存放长整型类型指针的形参

long *y: 存放长整型类型指针的形参

函数返回值:无

  1. void  SwapChar(char x[], char y[]);

功能:交换两个字符串的内容

参数:

char x[]:存放字符串类型数据的形参

char y[]:存放字符串类型数据的形参

函数返回值:无

  1. void  AsSortbyNum(STU stu[], int n, int m);

功能:按学号由小到大排出成绩表;

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  SortbyName(STU stu[], int n, int m);

功能:按姓名的字典顺序排出成绩表

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  SearchbyNum(STU stu[], int n, int m);

功能:按学号查询学生排名及其考试成绩

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  SearchbyName(STU stu[], int n, int m);

功能:按姓名查询学生排名及其考试成绩

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  StatisticAnalysis(STU stu[], int n, int m);

功能:按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void  PrintScore(STU stu[], int n, int m);

功能:输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void Writetofile(STU stu[],int n,int m);

功能:将每个学生的记录信息写入文件

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. void Readfromfile(STU stu[],int *n,int *m);

功能:从文件中读出每个学生的记录信息并显示

参数:

STU stu[]:存放学生信息的结构体

int m:学生数目的形参

int n:课程数目的形参

函数返回值:无

  1. 系统实现

1.系统的总流程图:

菜单驱动的系统的主流程一般为:

 

 

 

开始

 

输入学生数据

 

此学生的序数是否大于学生总数

 

从第一个学生开始排序

 

此学生成绩至少比前几位学生中一位成绩低?

 

交换与该学生位置

 

对下一位学生进行排序

 

结束

 

N

 

Y

 

N

 

Y

 

 

开始

输入所查找学生的学号

输入学号与该学生相同

从第一个学生的学号开始匹配

对下一位学生进行匹配

输出该学生的 学号 姓名 成绩

输出未查询到相关信息

结束

学号是否存在

Y

N

Y

N

 

开始

输入学生信息

目前学生数i+1

i达到最大值?

输出插入后的信息

结束

Y

N

开始

输入学生信息

程序是否进行

回车键继续

输出学生学号姓名成绩

结束

Y

N

2.程序的全部源代码:

学生管理系统V6.0

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <conio.h>


#define MAX_PSD_LEN 20

#define   MAX_LEN  10                      /* 字符串最大长度 */

#define   STU_NUM 30                       /* 最多的学生人数 */

#define   COURSE_NUM 6                     /* 最多的考试科目数 */

typedef struct student

{

    long num; /* 每个学生的学号 */

    char name[MAX_LEN];                /* 每个学生的姓名 */

    float score[COURSE_NUM]; /* 每个学生COURSE_NUM门功课的成绩 */

    float sum;                       /* 每个学生的总成绩 */

    float aver;                   /* 每个学生的平均成绩 */

} STU;

inline int Menu(void)

{

    int a;

    printf("======================Welcome to the to the student info manage system v6.0==========================\n");

    printf("Management for Students' scores\n");

    printf("1.Input record\n");

    printf("2.Caculate total and average score of every course\n");

    printf("3.Caculate total and average score of every student\n");

    printf("4.Sort in descending order by score\n");

    printf("5.Sort in ascending order by score\n");

    printf("6.Sort in ascending order by number\n");

    printf("7.Sort in dictionary order by name\n");

    printf("8.Search by number\n");

    printf("9.Search by name\n");

    printf("10.Statistic analysis\n");

    printf("11.List record\n");

    printf("12.Write to a file\n");

    printf("13.Read from a file\n");

    printf("14.Sign up to Admin\n");

    printf("0.Exit\n");

    printf("=======================================================================================================\n");

    printf("Please Input your choice:\n");

STAT :

    {

        int ret=scanf(" %d",&a);

        if(ret!=1)

        {

            printf("Input Error!\nPlease enter again:\n");

            fflush(stdin);

            goto STAT;

        }

    }

    return a;

}


inline void input(STU stu[],int stunum,int cosnum)

{

    int i,j;

    printf("Input student's ID, name and score:\n");

    for (i=0; i< stunum; i++)

    {

        scanf("%ld%s",&stu[i].num,&stu[i].name);

        for(j=0; j<cosnum; j++)

        {

            scanf("%f",&stu[i].score[j]);

        }

    }

    for (i=0; i<stunum; i++)

    {

        for(j=0; j<cosnum; j++)

        {

            stu[i].sum+=stu[i].score[j];

        }

        stu[i].aver=stu[i].sum/cosnum;

    }

    return 0;

}


inline void ReadScore(STU stu[], int n, int m)

{



}


inline void AverSumofEveryStudent(STU stu[], int n, int m)

{

    int i,j;


    for (i=0; i<n; i++)

    {

        printf("student %d: sum=%.0f,aver=%.0f\n",i+1,stu[i].sum,stu[i].aver);

    }

    return 0;

}


inline void AverSumofEveryCourse(STU stu[], int n, int m)

{

    int i,j;

    float sum[COURSE_NUM]= {0},av[COURSE_NUM]= {0};

    for (i=0; i<m; i++)

    {

        for(j=0; j<n; j++)

        {

            sum[i]+=stu[j].score[i];

        }

        av[i]=sum[i]/n;

        printf("course %d:sum=%.0f,aver=%.0f\n",i+1,sum[i],av[i]);

    }


    return 0;

}

inline void SortbyScore(STU stu[],int n,int m,int (*compare)(float a,float b))

{

    int i,j,k,ii;


    for(i=0; i<n-1; i++)

    {

        k=i;

        for(j=i+1; j<n; j++)

        {

            if((*compare)(stu[j].aver,stu[k].aver))

                k=j;

        }

        if(k!=i)

        {

            SwapFloat(&stu[k].aver,&stu[i].aver);

            SwapFloat(&stu[k].sum,&stu[i].sum);

            SwapChar(stu[k].name,stu[i].name);

            SwapLong(&stu[k].num,&stu[i].num);

            for(ii=0; ii<m; ii++)

            {

                SwapFloat(&stu[k].score[ii],&stu[i].score[ii]);

            }

        }

    }

    return 0;

}


inline int Ascending(float a, float b)    /*按每个学生的总分由高到低排出名次表*/

{

    return a<b;

}


inline int Descending(float a, float b)

{

    return a>b;

}


inline void SwapFloat(float *x, float *y)

{

    float t2;


    t2=*x;

    *x=*y;

    *y=t2;

    return 0;

}

inline void SwapLong(long *x, long *y)

{

    long t1;


    t1=*x;

    *x=*y;

    *y=t1;

    return 0;

}

inline void SwapChar(char x[], char y[])

{

    char str[MAX_LEN];


    strcpy(str,x);

    strcpy(x,y);

    strcpy(y,str);

    return 0;

}

inline void AsSortbyNum(STU stu[], int n, int m)

{

    int i,j,k,ii;


    for(i=0; i<n-1; i++)

    {

        k=i;

        for(j=i+1; j<n; j++)

        {

            if(stu[j].num<stu[k].num)

                k=j;

        }

        if(k!=i)

        {

            SwapFloat(&stu[k].aver,&stu[i].aver);

            SwapFloat(&stu[k].sum,&stu[i].sum);

            SwapChar(stu[k].name,stu[i].name);

            SwapLong(&stu[k].num,&stu[i].num);

            for(ii=0; ii<m; ii++)

            {

                SwapFloat(&stu[k].score[ii],&stu[i].score[ii]);

            }

        }

    }

    return 0;

}

inline void SortbyName(STU stu[], int n, int m)

{

    int i,j,k,ii;


    for(i=0; i<n-1; i++)

    {

        k=i;

        for(j=i+1; j<n; j++)

        {

            if(strcmp(stu[j].name,stu[k].name)<0)

                k=j;

        }

        if(k!=i)

        {

            SwapFloat(&stu[k].aver,&stu[i].aver);

            SwapFloat(&stu[k].sum,&stu[i].sum);

            SwapChar(stu[k].name,stu[i].name);

            SwapLong(&stu[k].num,&stu[i].num);

            for(ii=0; ii<m; ii++)

            {

                SwapFloat(&stu[k].score[ii],&stu[i].score[ii]);

            }

        }

    }



}

inline void SearchbyNum(STU stu[], int n, int m)

{

    long number;

    int i,j,ii;


    printf("Input the number you want to search:\n");

    scanf("%ld",&number);

    for(i=0; i<n; i++)

    {

        if(stu[i].num==number)

        {

            printf("%ld\t%s\t",stu[i].num,stu[i].name);

            for(j=0; j<m; j++)

                printf("%.0f\t",stu[i].score[j]);


            printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            return 0;

        }

    }

    printf("Not found!\n");

    return 0;

}

inline void SearchbyName(STU stu[], int n, int m)

{

    int i,j;

    char stuname[MAX_LEN];


    printf("Input the name you want to search:\n");

    scanf("%s",stuname);

    for(i=0; i<n; i++)

    {

        if(!strcmp(stuname,stu[i].name))

        {

            printf("%ld\t%s\t",stu[i].num,stu[i].name);

            for(j=0; j<m; j++)

                printf("%.0f\t",stu[i].score[j]);


            printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            return 0;

        }

    }

    printf("Not found!\n");

    return 0;

}

inline void StatisticAnalysis(STU stu[], int n, int m)

{

    int i,j,total;

    for(j=0; j<m; j++)

    {

        int t[COURSE_NUM]= {0};

        printf("For course %d:\n",j+1);

        for(i=0; i<n; i++)

        {

            if(stu[i].score[j]>=0&&stu[i].score[j]<60)

                t[0]++;

            else if(stu[i].score[j]<70)

                t[1]++;

            else if(stu[i].score[j]<80)

                t[2]++;

            else if(stu[i].score[j]<90)

                t[3]++;

            else if(stu[i].score[j]<100)

                t[4]++;

            else if(stu[i].score[j]==100)

                t[5]++;

        }

        for(i=0; i<6; i++)

        {

            if(i==0)

                printf("<60\t%d\t%.2f%%\n",t[i],(float)t[i]/n*100);

            else if(i==5)

                printf("%d\t%d\t%.2f%%\n",(i+5)*10,t[i],(float)t[i]/n*100);

            else

            {

                printf("%d-%d\t%d\t%.2f%%\n",(i+5)*10,(i+5)*10+9,t[i],(float)t[i]/n*100);

            }

        }

    }

    return 0;

}


inline void PrintScore(STU stu[], int n, int m)

{

    int i,j;

    for (i=0; i< n; i++)

    {

        printf("%ld\t%s\t",stu[i].num,stu[i].name);

        for(j=0; j<m; j++)

            printf("%.0f\t",stu[i].score[j]);


        printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

    }

}


inline void Writetofile(STU stu[],int n,int m)

{

    FILE *fp;

    int i,j;


    if((fp=fopen("student.txt","w"))== NULL)

    {


        printf("Failure to open score.txt! \n");

        exit(1);

    }

    fprintf(fp,"%d\t%d\n",n,m);

    for(i=0; i<n; i++)

    {

        fprintf(fp,"%10ld%10s",stu[i].num,stu[i].name);

        for(j=0; j<m; j++)

        {


            fprintf(fp,"%10.0f",stu[i].score[j]);

        }

        fprintf(fp,"%10.0f%10.0f\n",stu[i].sum,stu[i].aver);

    }

    fclose(fp);

    return 0;

}


inline void Readfromfile(STU stu[],int *n,int *m)

{

    FILE *fp;

    int i,j;


    if((fp=fopen("student.txt","r"))== NULL)

    {


        printf("Failure to open score.txt! \n");

        exit(1);

    }

    fscanf(fp,"%d\t%d",n,m);

    for(i=0; i<*n; i++)

    {

        fscanf(fp,"%10ld",&stu[i].num);

        fscanf(fp,"%10s",stu[i].name);

        for(j=0; j<*m; j++)

        {


            fscanf(fp,"%10f",&stu[i].score[j]);

        }

        fscanf(fp,"%10f%10f\n",&stu[i].sum,&stu[i].aver);

    }

    fclose(fp);

    return 0;

}


inline admin(STU stu[],int n,int m)

{

    printf("========================Welcome to the to the admin version=========================\n");

    printf("You have 2 options.\n");

    printf("1.login.\n");

    printf("2.exit.\n");

    printf("3.change your password.\n");

printf("=====================================================================================\n");

    char pw[MAX_PSD_LEN]="admin",pw2[MAX_PSD_LEN]="123456";

    int a;

    char PassWord[MAX_PSD_LEN],*p=PassWord,ch;

    char PassWord1[MAX_PSD_LEN],*p1=PassWord1,*p2=pw2;

    int count=0;


    printf("Please select your option!\n");

    scanf("%d",&a);


    if(a==1)

    {

        printf("Please Enter your password:\n");

        ch=getch();

        while(ch!=13&&count<MAX_PSD_LEN-1)       /*当按下回车键或密码长度达到19,则退出循环*/

        {

            if(ch==8)                       /*如果按下的是向前删除键,则...*/

            {

                if(count)              /*如果密码串中字符数大于零,则向前删除一个字符*/

                {

                    p--;

                    count--;

                    printf("\b ");/*光标回退一格,将星号(*)改为空格*/

                    printf("\b"); /*光标重新回退一格*/

                }

            }

            else if((ch<='Z'&&ch>='A')||(ch<='z'&&ch>='a')||(ch<='9'&&ch>='0'))

                /*如果输入的是密码的有效字符*/

            {

                printf("*");          /*输出一个星号*/

                count++;

                *p=ch;                /*记录密码内容*/

                p++;

            }

            ch=getch();                    /*等待输入下一个字符*/

        }

        PassWord[count]=0;

        printf("\n");

        if(strcmp(PassWord,pw)==0)

        {


            printf("You have successfully login!\n");

            n=adminsystem(stu,n,m);

            return n;

        }

        else

        {

            printf("Your password isn't correct!\n");

            return n;

        }

    }


    else if(a==2)

    {


        printf("You have successfully exit the Admin system!\n");

        return n;

    }

    else if(a==3)

    {

        count=0;

        printf("Please enter your old password:\n");

        ch=getch();

        while(ch!=13&&count<MAX_PSD_LEN-1)       /*当按下回车键或密码长度达到19,则退出循环*/

        {

            if(ch==8)                       /*如果按下的是向前删除键,则...*/

            {

                if(count)              /*如果密码串中字符数大于零,则向前删除一个字符*/

                {

                    p--;

                    count--;

                    printf("\b ");/*光标回退一格,将星号(*)改为空格*/

                    printf("\b"); /*光标重新回退一格*/

                }

            }

            else if((ch<='Z'&&ch>='A')||(ch<='z'&&ch>='a')||(ch<='9'&&ch>='0'))

                /*如果输入的是密码的有效字符*/

            {

                printf("*");          /*输出一个星号*/

                count++;

                *p=ch;                /*记录密码内容*/

                p++;

            }

            ch=getch();                    /*等待输入下一个字符*/

        }

        PassWord[count]=0;

        printf("\n");

        if(strcmp(PassWord,pw)==0)

        {

            count=0;


            printf("Congratulations!Please enter your new password:\n");

            ch=getch();

            while(ch!=13&&count<MAX_PSD_LEN-1)       /*当按下回车键或密码长度达到19,则退出循环*/

            {

                if(ch==8)                       /*如果按下的是向前删除键,则...*/

                {

                    if(count)              /*如果密码串中字符数大于零,则向前删除一个字符*/

                    {

                        p2--;

                        count--;

                        printf("\b ");/*光标回退一格,将星号(*)改为空格*/

                        printf("\b"); /*光标重新回退一格*/

                    }

                }

                else if((ch<='Z'&&ch>='A')||(ch<='z'&&ch>='a')||(ch<='9'&&ch>='0'))

                    /*如果输入的是密码的有效字符*/

                {

                    printf("*");          /*输出一个星号*/

                    count++;

                    *p2=ch;                /*记录密码内容*/

                    p2++;

                }

                ch=getch();                    /*等待输入下一个字符*/

            }

            pw2[count]=0;

            printf("\n");

            printf("Please enter again:\n");


            count=0;

            ch=getch();

            while(ch!=13&&count<MAX_PSD_LEN-1)       /*当按下回车键或密码长度达到19,则退出循环*/

            {

                if(ch==8)                       /*如果按下的是向前删除键,则...*/

                {

                    if(count)              /*如果密码串中字符数大于零,则向前删除一个字符*/

                    {

                        p1--;

                        count--;

                        printf("\b ");/*光标回退一格,将星号(*)改为空格*/

                        printf("\b"); /*光标重新回退一格*/

                    }

                }

                else if((ch<='Z'&&ch>='A')||(ch<='z'&&ch>='a')||(ch<='9'&&ch>='0'))

                    /*如果输入的是密码的有效字符*/

                {

                    printf("*");          /*输出一个星号*/

                    count++;

                    *p1=ch;                /*记录密码内容*/

                    p1++;

                }

                ch=getch();                    /*等待输入下一个字符*/

            }

            PassWord1[count]=0;

            printf("\n");

            if(!strcmp(PassWord1,pw2))

            {

                strcpy(pw,PassWord1);

                printf("Your password has been successfully changed!\n");

                return n;

            }

            else

                printf("tow times does NOT match!\n");

                return n;

            }


        else

        {

            printf("Your password isn't correct!\n");

            return n;

        }


    }

    else

    {

        printf("Input Error!\n");

        return n;

    }


}

inline adminsystem(STU stu[],int n,int m)

{

    int n1;

    long num;

    char x;


    printf("1.add a student info\t\n");

    printf("2.delete a student info\t\n");

    printf("3.exit\n");

    scanf("%d",&n1);

    switch(n1)

    {

    case 1:

    {

        printf("please enter the student number you want to add:");

        num=-1;

        while(num<0)

        {

            scanf("%ld",&num);

            printf("\n");

            if(num<=0)

                printf("Input Error!\n""Please enter again:\n");

        }


        int i,j;


        printf("Input to be added student's ID, name and score:\n");

        for (i=0; i<num; i++)

        {

            scanf("%ld%s",&stu[n+i].num,&stu[n+i].name);

            for(j=0; j<m; j++)

            {

                scanf("%f",&stu[i+n].score[j]);

            }

        }

        for (i=0; i<num; i++)

        {

            for(j=0; j<m; j++)

            {

                stu[i+n].sum+=stu[i+n].score[j];

            }

            stu[i+n].aver=stu[i+n].sum/m;

            n=n+num;

            return n;

        }

        break;

        case 2:

        {

            printf("Please enter the student's student number you want to delete:\n");

            scanf("%ld",&num);


            int i,j;

            for(i=0; i<n; i++)

            {

                if(stu[i].num==num)

                {

                    printf("%ld\t%s\t",stu[i].num,stu[i].name);

                    for(j=0; j<m; j++)

                        printf("%.0f\t",stu[i].score[j]);


                    printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);


                    printf("Are you SURE to delete(y/n)?\n");

                    scanf(" %c",&x);

                    char name1[MAX_LEN]= {0};


                    if(x=='y'||x=='Y')

                    {

                        stu[i].num=0;

                        strcpy(stu[i].name,name1);

                        for(j=0; j<m; j++)

                            stu[i].score[j]=0;


                        stu[i].sum=0;

                        stu[i].aver=0;

                        return n=n-1;

                    }

                    else if(x=='n'||x=='N')

                    {


                        return n;

                    }

                    else

                        printf("Input Error!\n");

                    return n;

                }

            }

            printf("Not found!\n");

            return n;

        }

        break;

        case 3:

            return n;

        default:

            printf("Input Error!");

            return n;

        }


    }

}

int main()

{

    int stunum=-1,cosnum=-1;


    while(stunum<0||stunum>30)

    {

        printf("Input student number(n<=30):\n");

        scanf("%d",&stunum);

        if(stunum<0||stunum>30)

        {


            printf("Input Error!Please Enter Again:\n");

        }

    }

    while(cosnum<0||cosnum>6)

    {

        printf("Input course number(m<=%d):\n",COURSE_NUM);

        scanf("%d",&cosnum);

        if(cosnum<0||cosnum>6)

        {


            printf("Input Error!Please Enter Again:\n");

        }

    }


    STU stu[STU_NUM]= {0};


    int flag=1,a,i,j;

    while(flag)

    {

        a=Menu();

        switch (a)

        {

        case 1:

            input(stu,stunum,cosnum);

            break;

        case 2:

            AverSumofEveryCourse(stu,stunum,cosnum);

            break;

        case 3:

            AverSumofEveryStudent(stu,stunum,cosnum);

            break;

        case 4:

            SortbyScore(stu,stunum,cosnum,Descending);

            printf("Sort in descending order by score:\n");

            for (i=0; i< stunum; i++)

            {

                printf("%ld\t%s\t",stu[i].num,stu[i].name);

                for(j=0; j<cosnum; j++)

                    printf("%.0f\t",stu[i].score[j]);


                printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            }

            break;

        case 5:

            SortbyScore(stu,stunum,cosnum,Ascending);

            printf("Sort in ascending order by score:\n");

            for (i=0; i< stunum; i++)

            {

                printf("%ld\t%s\t",stu[i].num,stu[i].name);

                for(j=0; j<cosnum; j++)

                    printf("%.0f\t",stu[i].score[j]);


                printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            }

            break;

        case 6:

            printf("Sort in ascending order by number:\n");

            AsSortbyNum(stu,stunum,cosnum);

            for (i=0; i< stunum; i++)

            {

                printf("%ld\t%s\t",stu[i].num,stu[i].name);

                for(j=0; j<cosnum; j++)

                    printf("%.0f\t",stu[i].score[j]);


                printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            }

            break;

        case 7:

            printf("Sort in dictionary order by name:\n");

            SortbyName(stu,stunum,cosnum);

            for (i=0; i< stunum; i++)

            {

                printf("%ld\t%s\t",stu[i].num,stu[i].name);

                for(j=0; j<cosnum; j++)

                    printf("%.0f\t",stu[i].score[j]);


                printf("%.0f\t%.0f\n",stu[i].sum,stu[i].aver);

            }

            break;

        case 8:

            SearchbyNum(stu,stunum,cosnum);

            break;

        case 9:

            SearchbyName(stu,stunum,cosnum);

            break;

        case 10:

            StatisticAnalysis(stu,stunum,cosnum);

            break;

        case 11:

            PrintScore(stu,stunum,cosnum);

            break;

        case 12:

            Writetofile(stu,stunum,cosnum);

            break;

        case 13:

            Readfromfile(stu,&stunum,&cosnum);

            break;

        case 14:

            stunum=admin(stu,stunum,cosnum);

            break;

        case 0:

            printf("End of program!\n");

            flag=0;

            exit(0);

        default:

            printf("Input error!\n");

        }

    }

    return 0;

}
  1. 系统测试

1.程序调试中遇到的问题和解决方法及思路

在调试过中,我并没有碰到一些难点问题。只是程序调试的过程中会出现一些小错误,我通过单步执行,一点点找到错误,分析出错误的原因,然后逐个地更正错误,最后让程序更加完善。

举个例子,在用户在菜单界面进行选择菜单输入数字时候,不小心输成了英文,这会使得scanf读取错误,系统会无限循环,进而造成程序安乐死。

于是,我通过使用scanf函数的return值来进行判断,是否带到要求,并同时用fflush(stdin)进行清空缓冲区,这样问题就完美解决了。

2.实验结果

略。

  1. 分析总结、收获和体会

通过这次C语言实验设计,我发现其实设计一个如此长的系统并不是一件非常难的事情,然而将这个系统完善好才是比较难的一件事。尤其是在Debug过程中出现了许多问题,有些问题,一找就是一两个小时,十分令人头疼。写程序容易改程序难啊!

在写程序的过程中,了解到了之前没学过的一些知识,比如

  1. system(“cls”);是一个清屏函数;

  2. getchar();是程序停滞时使用的;

  3. 学习编写了暗文密码的输入系统,原来我们平时日常生活中经常输入的账户密码看不见原来是这个原理;

  4. 学会了文件的基本操作;

  5. inline (内联函数)的使用:内联函数的代码会在任何调用它的地方展开,使得程序占用内存空间更少;

  6. 采用了函数指针,将程序中的升序和降序两个函数抽象成一个独立的通用排序函数,使程序更加简洁,提高了程序的通用性,减少了重复代码。

在写程序的过程中我也总结出来了几点经验:

  1. 在程序的开始或者相关函数调用的时候增加一段错误处理代码。可以增加整个工程的容错性,提高程序的使用性能;

  2. 将程序中的绝对路径引用改为相对路径引用可以提高整个程序的移植性能;

  3. 多打备注有利于检查;

  4. 函数的模块化思想有利于程序的debug,也有利于提高程序的通用性,减少重复代码。

在这次设计中,我的优点不仅是将上述的经验和知识运用到我的代码中去,而且我也将程序写的非常标准,不省略任何一个return 0;对程序健壮性也做了优化,即使在输入菜单时不小心输入错了,程序也不会卡死,会重新让用户输入。

当然,在写代码的时候我也发现了我的许多不足,比如说一些基本功不扎实,老犯一些低级错误,导致程序出错,要解决这个问题,编程序的时候一定要细心,多看看书,多看些典型的算法,扎实基本功。还有一件重要的事情就是程序的美观性,以后的系统可以通过使用不同的颜色,不同的样式,更多的图片,来使得程序更加美观,让用户使用的时候心情舒畅。

完成这次大作业后,我不惧怕再编一个更长甚至更复杂的系统,只要静下心来,将系统划分成各个模块,分别击破,一个更宏大的操作系统就完成了,并非想象中的那么困难,原来我也可以编出这样的系统。将编程当做一件快乐的事情去做。

通往一名合格的程序员之路还有很长,在计算机编程中还有好多新的东西等待我们去探索,更底层的语言值得我们学习,更高级的语言值得我们去寻味。因此,我打算在今后的两年里面逐步学习JAVA,PYTHON,APP开发,汇编语言学习等等,极大地开发自己在计算机领域的兴趣。

要成为一名高级程序员,我还需要一路披荆斩棘,克服困难,不懈努力!

参考文献

[1] 苏小红,王宇颖,孙志岗.C语言程序设计(第3版)[M].北京:高等教育出版社.2015

[2] 苏小红,王宇颖,孙志岗.C语言程序设计学习指导(第3版)[M].北京:高等教育出版社.2015

[3] Stephen Prata.C Primer Plus中文版(第六版)[M].北京:人民邮电出版社.2016