欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

学生管理系统C语言实现

程序员文章站 2022-05-06 09:40:51
...

近期做了一个学生管理系统,巩固了下文件io的知识!虽然只是一个小项目,不管对项目开发的认识有了一个小的提升。下面贴出各部分工作的代码。在codeblocks上编译完美运行。

先上图,程序运行后的菜单界面:

学生管理系统C语言实现

有基本的增删改查功能,还多了排序统计的辅助功能。

接下来分头文件和各个函数说明程序实现原理。

1.结构体头文件Studen.h(注意:头文件和.c文件不在同一个目录下,所以导入头文件时要使用绝对路径

该头文件定义了学生结构体,日期结构体和成绩结构体。

#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED

/*头文件定义*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include <process.h>
#include "Define.h"
#include "Function.h"

/*结构体定义*/
//成绩结构体
struct Score
{
	float C_score;          //c语言成绩
	float Database_score;   //数据库成绩
}SCORE;

//生日结构体
struct Birth
{
	int year;
	int month;
	int day;
}BIRTH;

//学生信息结构体
struct student
{
	char sex[3];            //性别
	int age;                //年龄
	char name[10];          //姓名
	char tel[15];           //电话
	char stu_no[5];         //学号
	float sum;              //成绩总和
	float avg;              //成绩平均值
	struct Birth birth;     //出生日期
	struct Score score;     //各项成绩
}STU[100];


#endif // STUDENT_H_INCLUDED

2.宏定义头文件Define.h

这个头文件定义了打印的输出格式,用一个变量代替一长串的输出格式,极大提高编程效率。注意各个变量的输出格式,例如整型的用%s输出,会造成不必要的错误。博主就在里面栽了跟头,都是很低级的错误。

#ifndef DEFINE_H_INCLUDED
#define DEFINE_H_INCLUDED

/*宏定义*/
#define LEN sizeof(struct student)  //结构体大小

//输出格式
#define FORMAT "%-5s%-9s%-5s%-5d%-14s%-4d-%-2d-%-5d%-7.1f%-7.1f%-7.1f%-7.1f\n"
#define DATA  STU[i].stu_no,STU[i].name,STU[i].sex,STU[i].age,STU[i].tel,STU[i].birth.year,STU[i].birth.month,STU[i].birth.day,\
                STU[i].score.C_score,STU[i].score.Database_score,STU[i].sum,STU[i].avg


#endif // DEFINE_H_INCLUDED

3.函数实现头文件Function.h

这个头文件声明各个函数。

#ifndef FUNCTION_H_INCLUDED
#define FUNCTION_H_INCLUDED

//#include "Student.h"
/*函数声明*/
void In();          //输入学生信息
void Show();        //显示学生信息
void Order();       //排序
void Del();         //删除
void Modify();      //修改
void Menu();        //菜单
void Insert();      //插入
void Total();       //总数
void Seek();        //查找


#endif // FUNCTION_H_INCLUDED

接下来是.c文件的实现。再次注意包含的头文件的路径,因为不是在一个工程目录下。

1.主函数main.c

主函数的作用就是打印菜单和接收用户的选择,并跳转到相应函数的实现。

#include "../inc/Student.h"
#include "../inc/Function.h"
int main(void)
{
    int n;
    Menu();
    scanf("%d",&n);
    while(n)
    {
        switch(n)
        {
            case 1: In(); break;
            case 2: Seek(); break;
            case 3: Del(); break;
            case 4: Modify(); break;
            case 5: Insert(); break;
            case 6: Order(); break;
            case 7: Total(); break;
            case 8: Show(); break;
            default :break;
        }
    getch();    //会等待你按下任意键,再继续执行下面的语句;
    Menu();     //执行完所选功能再次打印菜单
    scanf("%d",&n);
    }
    //printf("Goodbye!\n");
    printf("\n\t|------------------------感谢你的使用!-------------------------|\n");
    return 0;
}

2.函数功能实现function.h

(1)包含需要的头文件:(再再次强调绝对路径)

#include "../inc/Student.h"
#include "../inc/Function.h"
#include "../inc/Define.h"

(2)菜单 void Menu()

只用来打印菜单

void Menu()
{
    system("cls");
    printf("\n\n\n\n");
    printf("\t|-------------------------学生管理系统--------------------------|\n");
    printf("\t|                                                               |\n");
    printf("\t|\t\t\t  0.退出                                |\n");
    printf("\t|\t\t\t  1.输入学生信息                        |\n");
    printf("\t|\t\t\t  2.查找学生信息                        |\n");
    printf("\t|\t\t\t  3.删除学生信息                        |\n");
    printf("\t|\t\t\t  4.修改学生信息                        |\n");
    printf("\t|\t\t\t  5.插入学生信息                        |\n");
    printf("\t|\t\t\t  6.排序                                |\n");
    printf("\t|\t\t\t  7.学生人数                            |\n");
    printf("\t|\t\t\t  8.显示学生信息                        |\n");
    printf("\t|                                                               |\n");
    printf("\t|         作者:RongXiangXing       时间:2017/6/11             |\n");
    printf("\t|---------------------------------------------------------------|\n");
    printf("\t\t\t输入0-8选择相应的功能: ");
}

(3)输入学生信息函数 void In()

先到指定的文件中查看是否还有记录,如果没有记录,就打印没有记录的提示信息;有过有记录,就将已有记录显示出来。

void In()       //输入学生信息函数
{
    int i,m = 0;        //m是记录行数
    char ch[2];
    FILE *fp;       //定义文件指针
    if((fp = fopen("Database.txt","a+")) == NULL)
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);             //关闭文件
    if( m == 0)
        printf("没有记录!\n");
    else
    {
        system("cls");        //清屏
        Show();
    }
    if((fp = fopen("Database.txt","wb")) == NULL)
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(i = 0 ; i < m ; i++)
        fwrite(&STU[i],LEN,1,fp);       //向指定的磁盘文件写入信息
    printf("是否输入学生信息(y/n):");
    scanf("%s",ch);
    while(strcmp(ch,"Y") == 0 || strcmp(ch,"y") == 0)   //判断是否要输入信息
    {
        printf("学号:");
        scanf("%s",STU[m].stu_no);  //数组名就是首地址
        for( i = 0 ; i < m ; i++)
        {
            if(STU[i].stu_no == STU[m].stu_no)
            {
                printf("该学号已存在,请重新输入或将已有学号信息删除再输入!");
                getch();//会等待你按下任意键,再继续执行下面的语句;
                fclose(fp);
                return ;
            }
        }
        printf("姓名:");
        scanf("%s",STU[m].name);    //输入姓名
        printf("性别:");
        scanf("%s",STU[m].sex);     //输入性别,非数组要用取地址符&
        printf("年龄:");
        scanf("%d",&STU[m].age);    //输入年龄
        printf("电话:");
        scanf("%s",STU[m].tel);     //输入电话
        printf("出生日期:");
        scanf("%d%d%d",&STU[m].birth.year,&STU[m].birth.month,&STU[m].birth.day);//输入出生日期
        printf("C语言成绩:");
        scanf("%f",&STU[m].score.C_score);//输入C语言成绩
        printf("数据库成绩:");
        scanf("%f",&STU[m].score.Database_score);//输入数据库成绩
        STU[m].sum = STU[m].score.C_score + STU[m].score.Database_score;  //计算成绩总和
        STU[m].avg = STU[m].sum / 2.0;  //计算平均值
        if(fwrite(&STU[m],LEN,1,fp) != 1)
        {
            printf("无法存储信息,请检查输入格式!");
            getch();
        }
        else
        {
            printf("%s号学生信息已保存!\n",STU[m].stu_no);
            m++;        //记录增加
        }
        printf("是否继续录入信息?(y/n):");
        scanf("%s",ch);
    }
    fclose(fp);
    printf("输入操作完成,按任意键进入主菜单!\n");
}

运行界面:

学生管理系统C语言实现


(4)查询学生信息函数void Seek()

先按学号查询,如果没有找到,则提示使用姓名查询,若果仍没找到,打印提示信息。若找到则打印学生信息。

void Seek()     //查询学生信息函数
{
    FILE *fp;
    char ch[2],snum[5],sname[10];
    int i,m = 0;
    if((fp = fopen("Database.txt","rb")) == NULL)   //以只读方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);
    if(m == 0)
    {
        printf("没有记录!\n");
        return ;
    }
    printf("请输入要查询的学号:");
    scanf("%s",snum);
    for(i=0;i<m;i++)
    {
        if(strcmp(snum,STU[i].stu_no) == 0)
        {
            printf("学号  姓名   性别  年龄     电话       出生日期   C语言  数据库   sum   avg\n");
            printf(FORMAT,DATA);        //若找到按指定格式输出信息
            break;
        }
    }
    if(i == m)
    {
        printf("没有找到这名学生的记录!\n");
        printf("是否尝试进行姓名查找?(y/n):");
        scanf("%s",ch);
        for(i=0;i<m;i++)
        {
            if(strcmp(ch,"Y") == 0 || strcmp(ch,"y") == 0)
            {
                printf("请输入要查找学生的姓名:");
                scanf("%s",sname);
                if(strcmp(sname,STU[i].name) == 0)
                {
                    printf("学号  姓名   性别  年龄     电话       出生日期   C语言  数据库   sum   avg\n");
                    printf(FORMAT,DATA);        //若找到按指定格式输出信息
                    break;
                }
                else
                {
                    printf("仍然无法找到这名学生的记录!\n");
                    break;
                }
            }
        }
    }
    printf("查询操作完成,按任意键进入主菜单!\n");
}

运行界面:

学生管理系统C语言实现


(5)删除学生信息函数 void Del()

如果找到学生信息,提示是否删除。没找到则打印没有该学生信息。

void Del()      //删除学生信息函数
{
    FILE *fp;
    char ch[2],snum[5];
    int i,j,m = 0;
    if((fp = fopen("Database.txt","r+")) == NULL)   //以可读写方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);
    if(m == 0)
    {
        printf("没有记录!\n");
        return ;
    }
    printf("请输入要删除记录的学生学号:");
    scanf("%s",snum);
    for(i=0;i<m;i++)
    {
        if(strcmp(snum,STU[i].stu_no) == 0) //如果找到这个学生的记录
            break;
    }
    printf("学生记录已找到,是否确定删除?(y/n):");
    scanf("%s",ch);
    if(strcmp(ch,"Y") == 0 || strcmp(ch,"y") == 0)
    {
        for(j=i;j<m;j++)
        {
            STU[j] = STU[j+1];      //后面记录的信息往前移,删除该条记录
            m--;        //记录条数减少
        }
    }
    if((fp = fopen("Database.txt","wb")) == NULL)   //重新写入操作后的记录
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(j=0;j<m;j++)
    {
        if(fwrite(&STU[j],LEN,1,fp) != 1)
        {
            printf("写入信息失败!\n");
            getch();
        }
    }
    fclose(fp);
    printf("删除操作完成,按任意键进入主菜单!\n");
}

运行界面:

学生管理系统C语言实现


(6)修改学生信息函数 void Modify()

若找到要修改的学生信息的记录,则提示修改的各项信息,若没有找到,则打印查无此人的信息。

void Modify()   //修改学生信息函数
{
    FILE *fp;
    int i,j,m = 0;
    char snum[5];
    if((fp = fopen("Database.txt","r+")) == NULL)   //以可读写方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);


    Show();
    printf("请输入你想要修改信息的学生学号:");
    scanf("%s",snum);
    for(i=0;i<m;i++)
    {
        if(strcmp(snum,STU[i].stu_no) == 0)
        {
            printf("找到该学生的记录,现在你能进行更新信息!\n");
            printf("姓名:");
            scanf("%s",STU[i].name);    //输入姓名
            printf("性别:");
            scanf("%s",STU[i].sex);     //输入性别,非数组要用取地址符&
            printf("年龄:");
            scanf("%d",&STU[i].age);    //输入年龄
            printf("电话:");
            scanf("%s",STU[i].tel);     //输入电话
            printf("出生日期:");
            scanf("%d%d%d",&STU[i].birth.year,&STU[i].birth.month,&STU[i].birth.day);//输入出生日期
            printf("C语言成绩:");
            scanf("%f",&STU[i].score.C_score);//输入C语言成绩
            printf("数据库成绩:");
            scanf("%f",&STU[i].score.Database_score);//输入数据库成绩
            STU[i].sum = STU[i].score.C_score + STU[i].score.Database_score;  //计算成绩总和
            STU[i].avg = STU[i].sum / 2.0;  //计算平均值
            printf("学生信息修改成功!\n");
            break;
        }
    }
    if(i == m)
    {
        printf("没有找到该学生的记录!\n");
    }
    if((fp = fopen("Database.txt","wb")) == NULL)   //重新写入操作后的记录
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(j=0;j<m;j++)        //将修改后的信息重新写入磁盘文件
    {
        if(fwrite(&STU[j],LEN,1,fp) != 1)
        {
            printf("写入信息失败!\n");
            getch();
        }
    }
    fclose(fp);
    printf("修改操作完成,按任意键进入主菜单!\n");
}

运行界面:

学生管理系统C语言实现学生管理系统C语言实现


(7)插入学生信息函数

在要插入的学号的后面插入学生信息。

void Insert()   //插入学生信息函数
{
    FILE *fp;
    int i,j,k,m = 0;
    char snum[5];
    if((fp = fopen("Database.txt","r+")) == NULL)   //以可读写方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);
    if(m == 0)
    {
        printf("没有记录!\n");
        return ;
    }
    printf("请输入你想要插入的学号的位置(是在输入的学号后面插入):");
    scanf("%s",snum);
    for(i=0;i<m;i++)
    {
        if(strcmp(snum,STU[i].stu_no) == 0)
        {
            printf("找到要插入的学生的位置!现在你可以插入学生信息!\n");
            for(j=m-1;j>i;j--)
            {
                STU[j+1] = STU[j];      //从最后一条记录开始向后移,为要插入的信息提供空间
            }
            printf("学号:");
            scanf("%s",STU[i+1].stu_no);  //数组名就是首地址
            for(k=0 ; k<m ; k++)
            {
                if(STU[k].stu_no == STU[i+1].stu_no)
                {
                    printf("该学号已存在,请重新输入或将已有学号信息删除再输入!");
                    getch();//会等待你按下任意键,再继续执行下面的语句;
                    fclose(fp);
                    return ;
                }
            }
            printf("姓名:");
            scanf("%s",STU[i+1].name);    //输入姓名
            printf("性别:");
            scanf("%s",STU[i+1].sex);     //输入性别,非数组要用取地址符&
            printf("年龄:");
            scanf("%d",&STU[i+1].age);    //输入年龄
            printf("电话:");
            scanf("%s",STU[i+1].tel);     //输入电话
            printf("出生日期:");
            scanf("%d%d%d",&STU[i+1].birth.year,&STU[i+1].birth.month,&STU[i+1].birth.day);//输入出生日期
            printf("C语言成绩:");
            scanf("%f",&STU[i+1].score.C_score);//输入C语言成绩
            printf("数据库成绩:");
            scanf("%f",&STU[i+1].score.Database_score);//输入数据库成绩
            STU[i+1].sum = STU[i+1].score.C_score + STU[i+1].score.Database_score;  //计算成绩总和
            STU[i+1].avg = STU[m].sum / 2.0;  //计算平均值
            printf("成功插入学生信息!\n");
        }
    }
    if((fp = fopen("Database.txt","wb")) == NULL)   //重新写入操作后的记录
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(k=0;k<=m;k++)        //将修改后的信息重新写入磁盘文件,因为插入后记录加1,所以这里是<=m
    {
        if(fwrite(&STU[k],LEN,1,fp) != 1)
        {
            printf("写入信息失败!\n");
            getch();
        }
    }
    fclose(fp);
    printf("插入操作完成,按任意键进入主菜单!\n");
}

运行界面:

学生管理系统C语言实现


(8)按成绩总和排序学生信息void Order()  (也可以自己尝试按单科成绩排名)

void Order()    //排序学生信息
{
    FILE *fp;
    struct student t;   //定义student结构体对象,用于交换记录
    int i=0,j=0,m=0;
    if((fp = fopen("Database.txt","r+")) == NULL)   //以可读写方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);
    if(m == 0)
    {
        printf("没有记录!\n");
        return ;
    }
    if((fp = fopen("Database.txt","wb")) == NULL)   //重新写入操作后的记录
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(i=0;i<m;i++)        //使用冒泡排序法进行排序
    {
        for(j=0;j<m-i-1;j++)
        {
            if(STU[j].sum < STU[j+1].sum)
            {
                t = STU[j];
                STU[j] = STU[j+1];
                STU[j+1] = t;
            }
        }
    }
    if((fp = fopen("Database.txt","wb")) == NULL)   //重新写入操作后的记录
    {
        printf("无法代开文件!\n");
        return ;
    }
    for(i=0;i<m;i++)        //将修改后的信息重新写入磁盘文件,因为插入后记录加1,所以这里是<=m
    {
        if(fwrite(&STU[i],LEN,1,fp) != 1)
        {
            printf("写入信息失败!\n");
            getch();
        }
    }
    fclose(fp);
    printf("排序操作完成,按任意键进入主菜单后可按8显示功能查看!\n");
}

运行界面:

学生管理系统C语言实现


(8)求总人数函数void Total(),其实就是求出文件中的记录数

void Total()    //求总人数
{
    FILE *fp;
    int m=0;
    if((fp = fopen("Database.txt","r+")) == NULL)   //以可读写方式打开文件
    {
        printf("无法代开文件!\n");
        return ;
    }
    while(!feof(fp))        //feof(fp)表示到达文件末尾
    {
        if(fread(&STU[m],LEN,1,fp) == 1)    //若成功则返回实际读入的count数据,即1
            m++;            //记录条数增加
    }
    fclose(fp);
    if(m == 0)
    {
        printf("没有记录!\n");
        return ;
    }
    Show();
    printf("总共有 %d 名学生的信息!\n",m);
    printf("按任意键进入主菜单!\n");
}

运行界面:(打印出的学生信息,就是上一步已排序好的信息)

学生管理系统C语言实现


(9)显示学生信息函数void Show()

将文件中所有的学生信息记录打印出来。

void Show()     //显示已有记录
{
    FILE *fp;
    int i,m = 0;
    fp = fopen("Database.txt","rb");//以只读方式打开二进制流文件,打开二进制文件是因为速度快
    while(!feof(fp))
    {
        if(fread(&STU[m],LEN,1,fp) == 1)
            m++;
    }
    fclose(fp);
    printf("学号  姓名   性别  年龄     电话       出生日期   C语言  数据库   sum   avg\n");
    for(i = 0 ; i < m ; i++)
    {
        printf(FORMAT,DATA);    //将录入的信息按指定格式输出

    }
}

运行界面:

学生管理系统C语言实现


(10)退出程序

这一部分的代码其实就在main.c中,读者自己去体会吧,这里不做过多说明。

学生管理系统C语言实现


至此,学生管理系统程序实现和功能验证已完成。代码难度适中,读者可以自己去细心体会。博主还是在校大学生,实践能力不足,有错误的地方还请大家批评指正,共同进步!