多文件编程实现学生管理系统
使用结构体以及函数提高了代码的复用性
每个函数三要素都做了详细注释
1.main.c
#include <stdio.h>
#include "calen.h"
int main(int argc, const char *argv[])
{
int chose; //chose为用户的选择,1-6
int ret;
//1.定义一个结构体类型为class_t cls的名为cls的变量用来表示班级
class_t cls;
//2.初始化班级内的学生人数
cls.n = -1; //访问claas_t内部的n(当前学生人数) 从0到29,总计30 -1表示当前班级没人
while (1)
{
//打印表头
puts("***********************欢迎进入学生管理系统*********************");
puts("************1.添加 2.删除 3.修改 4.查询 5.排序 6.退出************");
puts("*************************************************************");
printf("输入您的选择:");
scanf("%d", &chose);
while (getchar() != '\n')
; //处理垃圾字符,每次scanf后尽量处理 getchar获取的是’\n’一直为真
switch (chose)
{
case ADDSTU: //1.添加学生
add_studen(&cls);
break;
case DELSTU: //2.删除学生
ret = del_student(&cls);
printf("删除了%d个学生\n", ret);
break;
case MODSTU: //3.修改学生
modify_student(&cls);
break;
case CHKSTU: //4.查询学生
show_student(&cls);
break;
case SOTSTU: //5.排序,按照成绩
sort_student(&cls);
break;
case QITSTU: //6.退出
printf("退出学生管理系统,欢迎下次使用\n");
break;
default:
printf("选择错误,请重新选择\n");
continue; //continue代表退出本层的本次循环
}
}
return 0;
}
2.stu.c
#include "calen.h"
//功能:判断班级内学生人数是否为空
//参数:班级的地址
//返回值:成功返回1(代表班级人数满),否则返回0
int class_stu_full(class_t *cls)
{
return cls->n >= (MAXSTU - 1) ? 1 : 0; //条件运算符,表达式为真返回1,否则返回0
}
// 1.添加功能的实现
//功能:从终端输入学生的姓名,性别,分数
//参数:学生的结构体指针
//返回值:-1代表插入信息失败,0为成功
int input_stu_info(stu_t *stu)
{
{
again: //goto只能在当前函数内跳转,可以向前跳转,也可以向后跳转
printf("请输入(name sex score"); //goto一般用在统一出错处理
int ret = scanf("%s %c %d", stu->name, &stu->sex, &stu->score); //scanf的返回值为输入占位符的个数
if (ret != 3)
{ //返回值用ret接 3代表成功,其他值代表失败
printf("输入错误,请重新输入\n"); //此处goto代表输入错误就一直输入,直到输入正确为止
while (getchar() != '\n')
; //吃掉垃圾字符
goto again;
}
while (getchar() != '\n')
; //吃掉垃圾字符
if (stu->sex != 'm' && stu->sex != 'w')
{ //只能输入'm'和'w'两个字符,其他都为错误
printf("性别输入有误,请重新输入\n");
goto again;
}
if (stu->score < 0 || stu->score > 100)
{
printf("分数输入错误,请重新输入\n");
goto again;
}
return 0;
}
}
//功能:向班级内添加学生信息
//参数:班级的指针
//返回值:-1代表添加信息失败。0为成功
int add_studen(class_t *cls)
{
//1.添加之前判断班级内的人数是否已经满了
if (class_stu_full(cls))
{ //调用函数判断,实参为班级人数,次函数返回值1代表满
printf("班级内人数已满");
return -1;
}
//2.如果没有满,就添加学生,输入学生信息
input_stu_info(&cls->stu[++(cls->n)]); //调用函数,cls->n 为当前学生人数,必须随着插入人数的增加而增加
//3.如果成功返回 0
return 0;
}
//4.查询功能的实现
//功能:展示所有学生的信息
//参数:班级的指针
//返回值:无
void show_student(class_t *cls)
{ //将学生信息遍历一次,使用for循环
for (int i = 0; i < cls->n; i++)
{
printf("name=%-10s sex=%c score=%d\n", cls->stu[i].name, cls->stu[i].sex, cls->stu[i].score);
}
}
//功能:判断班级内人数是否为空
//参数:班级的指针
//返回值:为空返回真,否则返回0
int class_stu_empty(class_t *cls)
{
return cls->n == -1 ? 1 : 0;
}
//2.删除功能的实现
//功能:根据输入的学生姓名,删除对应的学生
//参数:班级的指针
//返回值:成功返回删除的学生个数,失败则返回-1
int del_student(class_t *cls)
{
char name[20] = {0};
//1.判断班级是否为空
if (class_stu_empty(cls))
{
printf("班级内没有学生\n");
return -1;
}
//2.输入删除想要删除的学生名单
printf("请输入想要删除的学生\n");
scanf("%s", name);
while (getchar() != '\n')
;
//3.拿输入的学生姓名和班级内的学生进行比较
int i = 0, j = 0;
for (i = 0, j = 0; i < cls->n; i++)
{
if (strcmp(name, (cls->stu[i].name)))
{ //输入学生的姓名和班级内某个学生相等的时间不进入if语句,i一直加
cls->stu[j] = cls->stu[i]; //不相等就进入if语句,将i此时的下标给到j,完成位置的替换
j++;
}
}
//4.修改班级内n的值
cls->n -= (i - j);
//5.返回值
return (i - j);
}
//5.排序功能的实现
//功能:根据学生的成绩进行排序(冒泡排序 优化版)
//参数:
//返回值:
int sort_student(class_t *cls)
{
stu_t stu;
int i, j, flag;
for (i = 0; i < cls->n; i++)
{
for (j = 0; j < cls->n - i; j++)
{
if (cls->stu[j].score > cls->stu[j + 1].score)
{
stu = cls->stu[j];
cls->stu[j] = cls->stu[j + 1];
cls->stu[j + 1] = stu;
flag = 1;
}
}
if (0 == flag)
{ //表示上一步没有进入if循环,此时已经有序排列,减少了多余的排列
break;
}
}
}
//3.根据姓名修改学生信息
//功能:根据输入的学生姓名修改信息
//参数:班级的指针
//返回值:
int modify_student(class_t *cls)
{
char name[20] = {0};
//1.判断班级内是否没有人
if (class_stu_full(cls))
{
printf("班级内没有人,修改失败\n");
return -1;
}
//2.输入学生名字
printf("请输入想要修改的学生姓名");
scanf("%s", name);
while (getchar() != '\n')
;
//3.通过名字查找想要修改的学生的姓名
int flags = 0;
int which = 0;
for (int i = 0; i < cls->n; i++)
{
if (strcmp(name, cls->stu[i].name) == 0)
{ //strcmp逐位比较两个字符串的ascii码,相等返回0
printf("%d.name=%-10s sex=%c score=%d\n", i, cls->stu[i].name, cls->stu[i].sex, cls->stu[i].score);
flags = 1; // 执行if语句后,改变flags的值,表示查询到学生
}
if (0 == flags)
{
printf("查不到此人,请重新输入\n");
return -1;
}
//4.输入想要修改的下标,防止有名字相同的情况
printf("请输入想要修改的学生的下标:");
scanf("%d", &which);
}
//5.输入新的信息
input_stu_info(&cls->stu[which]);
}
3.stu.h
#ifndef __CALEN_H__
#define __CALEN_H__
#include <stdio.h> //包含printf等函数的头文件
#include <string.h> //包含strcmp,strcpy,strcat等函数的头文件
#include <stdlib.h> //包含getchar等函数的头文件
#define ADDSTU 1 //1.添加
#define DELSTU 2 //2.删除
#define MODSTU 3 //3.修改
#define CHKSTU 4 //4.查询modify_student(class_t *cls)
#define SOTSTU 5 //5.排序
#define QITSTU 6 //6.退出
#define MAXSTU 30 //最大可容纳的学生人数
typedef struct
{
char name[20]; //定义了一个数组用来保存姓名
char sex; // 性别
int score; //分数
} stu_t; //重新定义了一个类型为stu_t的结构体类型
typedef struct
{
stu_t stu[MAXSTU]; //班级内能容纳的学生人数
int n; //班级内的当前学生人数
} class_t; //重新定义了一个类型为class_t的结构体类型
int add_studen(class_t *cls); //1.添加函数
void show_student(class_t *cls); //4.查询函数
int modify_student(class_t *cls); //3.修改
int del_student(class_t *cls); //2.删除
int sort_student(class_t *cls); //5.排序
#endif