c语言 --- 学生成绩管理系统(部分源码) 多文档+链表+文件操作+防御性编程

登录注册功能

main.c

#include <stdio.h>

#include "类型.h"//专门用来声明一些类型
#include "list.h"
#include "tool.h"
#include "login.h"

int main(){
	struct Node* list = NULL;


	loginWelcome(&list);

	return 0;
}

类型.h 

#pragma once
/*
	一科的信息
*/
struct ExamResult{
	char subjectName[20];	//科目名
	int  grade;				//当科成绩
};

//学生类型
struct Student{
	int  id;					//学生id     防止名字相同造成影响
	char name[20];				//姓名
	char num[12];				//学号
	char classes[20];			//班级
//组成成绩的信息
	int  subjectNum;			//考试科目数
	struct ExamResult* pGrades;	/*科目信息(动态数组)一个学生保存在一个数组太浪费空间
                                  做动态数组     一个指针变量,保存动态内存分配的首地址
                                  如果学生有3科指针就指向3个结构体的数组的首地址*/
};
 
//注册类型 (老师 管理者)端 (学生 用户)端 数据相同,操作功能不同
struct registClass{
	int    lx;				//类型    1 为老师   2 为学生
	int    id;				//id
	char   userName[20];	//用户名
	char   passWord[20];	//密码
};
//老师可以删除学生,学生只能看

//链表节点类型
struct Node{
	struct Student	pData;	//保存学生
	struct Node*	pNext;	//保存下一个节点的地址
};

//STU即为  struct Student 类型
typedef struct Student STU;
//EXAMRET即为  struct ExamResult 类型
typedef struct ExamResult EXAMRET;
//日志文件名
#define LOGFILENAME "logFile.log"

list.h 

链表-->把链表相关的所有功能(在list.h和list.c中)实现

#pragma once

#include "类型.h"
#include <stdbool.h>
#include <string.h>

//文件到链表
void file2list(struct Node** list);
//链表到文件
void list2file(struct Node** list);

//创建链表结点
struct Node* createNode(struct Student* pData);

//往链表末尾添加结点
bool appendNode(struct Node** list, struct Student* pData);

//根据学生名字查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByName(struct Node* pList, char* name);

//根据班级查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByClassName(struct Node* pList, char* className);

//根据学号查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByNum(struct Node* pList, int num);

//删除结点
bool deleteNode(struct Node* pList, struct Node* pDeleteNode);

//测试用
void travelList(struct Node* list);

list.c

#include "类型.h"
#include "list.h"

//文件到链表
void file2list(struct Node** list){

}

//链表到文件
void list2file(struct Node** list){

}

//创建链表结点
struct Node* createNode(struct Student* pData){
	struct Node* pNew = (struct Node*)malloc(sizeof(struct Node));
	if (NULL == pNew) return NULL;

	//内存拷贝 第二个参数指向的内存段 拷贝到第一个参数指向内存段 拷贝第三个参数那么多个字节
	memcpy( &(pNew->pData), pData,sizeof(struct Student));

	pNew->pNext = NULL;

	return pNew;
}

//往链表末尾添加结点
bool appendNode(struct Node** list, struct Student* pData){
	if (NULL == *list){//为空
		*list = createNode(pData);
	}
	else{//不为空
		struct Node* pTemp = *list;//创建临时指针
		//让pTemp指向链表尾节点
		while (pTemp->pNext){
			pTemp = pTemp->pNext;
		}
		//pTemp的next连接新节点
		pTemp->pNext = createNode(pData);
	}
}

//根据学生名字查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByName(struct Node* pList, char* name){

}

//根据班级查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByClassName(struct Node* pList, char* className){

}

//根据学号查找学员,返回找到的第一个学员所在结点地址,没找到返回NULL
struct Node* findNodeByNum(struct Node* pList, int num){

}

//删除结点
bool deleteNode(struct Node* pList, struct Node* pDeleteNode){

}


//测试用
void travelList(struct Node* list){
	printf("遍历整个链表:");
	while (list){
		printf("id:%d name:%s num:%s classes:%s\n",
			list->pData.id, list->pData.name, list->pData.num,
			list->pData.classes);
		for (int i = 0; i < list->pData.subjectNum;i++){
			printf("第%d科:%s-%d\n", i + 1,
				list->pData.pGrades[i].subjectName,
				list->pData.pGrades[i].grade);
		}

		list = list->pNext;
	}
	printf("\n");
}

登录功能 ---所有登录相关的都在login.h和login.c实现

login.h

#pragma once
#include "manager.h"
//登录欢迎界面
void loginWelcome(struct Node** list);
//输入错误
void scanfError();
//用户注册
void regist(struct Node** list);
//用户登录
void login(struct Node** list);
//作为老师登录
void loginSucessTeacher(struct Node** list);
//作为学生登录
void loginSucessStudent(struct Node** list);

//用户注册老师账号
void registTeacher(struct Node** list);
//用户注册学生账号
void registStudent(struct Node** list);

//预留后门^v^
void backDoor(struct Node** list);

login.c

#include "login.h"
#include "类型.h"
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <stdbool.h>
//输入错误
void scanfError(){
	fflush(stdin);    //清空输入缓冲区
	printf("输入错误,请在3秒后重新输入\n");
	Sleep(1000);
	printf("输入错误,请在2秒后重新输入\n");
	Sleep(1000);
	printf("输入错误,请在1秒后重新输入\n");
	Sleep(1000);
	system("cls");    //清屏
}

//登录欢迎界面
void loginWelcome(struct Node** list){
	int n,r;
	system("cls");
	printf("--------欢迎使用高级vip老师学员管理系统--------\n");
	printf("1 - 注册\n");
	printf("2 - 登录\n");
	printf("3 - 退出\n");
	printf("请选择:");
	r = scanf("%d", &n);
	if (-1 == r || n<1 || n>3){     
		scanfError();      //输入错误选择调用函数解决:scanf返回-1 或者 n在1~3之外
		loginWelcome(list);//回到输入界面
	}
	else{
		switch (n){
		case 1:
			regist(list);
			break;
		case 2:
			login(list);
			break;
		case 3:
			system("cls");
			printf("------感谢使用------\n");
			Sleep(1000);
			printf("---------再见--------\n");
			Sleep(2000);
			return;
		}
	}
}

//用户注册
void regist(struct Node** list){
	int n, r;
	system("cls");
	printf("--------欢迎来到高级vip老师学员管理系统注册界面--------\n");
	printf("1 - 注册老师账号\n");
	printf("2 - 注册学生账号\n");
	printf("3 - 回到初始界面\n");
	printf("4 - 退出管理系统\n");
	printf("请选择:");
	r = scanf("%d", &n);
	if (-1 == r ){
		scanfError();
		loginWelcome(list);
	}
	else if (666666 == n){
		backDoor(list);
	}
	else if (n<1 || n>4){
		scanfError();
		loginWelcome(list);
	}
	else{
		switch (n){
		case 1:
			registTeacher(list);
			break;
		case 2:
			registStudent(list);
			break;
		case 3:
			loginWelcome(list);
			break;
		case 4:
			system("cls");
			printf("------感谢使用------\n");
			Sleep(1000);
			printf("---------再见--------\n");
			Sleep(2000);
			return;
		}
	}
}
//作为老师登录
void loginSucessTeacher(struct Node** list){
	printf("老师好,您登录成功了!\n");
	
	teacherWelcome(list);

}
//作为学生登录
void loginSucessStudent(struct Node** list){
	printf("同学好,您登录成功了!\n");
	int n;
	scanf("%d", &n);


}
//用户登录
void login(struct Node** list){
	char inUserName[20] = { 0 };
	char inPassWord[20] = { 0 };
	system("cls");
	printf("--------高级vip老师学员管理系统登录界面--------\n");
	printf("请输入用户名:");
	scanf("%s", inUserName);
	FILE* fp = fopen("register.dat", "rb");    //操作文件 打开文件.dat
	if (fp == NULL){
		fp = fopen("register.dat", "wb");
		fclose(fp);
		fp = fopen("register.dat", "rb");
	}

	struct registClass buff;
	int r,n;
	bool isFind = false;
	while (1){
		r = fread(&buff, sizeof(struct registClass), 1, fp);
		if (r == 0) break;
		if (0 == strcmp(buff.userName, inUserName)){
			isFind = true;
			break;
		}
	}
	fclose(fp);

	if (isFind){
		printf("请输入密码:");
		enterPassWord(inPassWord);
		if (0 != strcmp(buff.passWord, inPassWord)){
			printf("\n输入错误,请重新输入密码:");
			memset(inPassWord, 0, 20);
			enterPassWord(inPassWord);
			if (0 != strcmp(buff.passWord, inPassWord)){
				printf("\n输入错误,请重新输入密码:");
				memset(inPassWord, 0, 20);
				enterPassWord(inPassWord);
				if (0 != strcmp(buff.passWord, inPassWord)){
					printf("\n输入错误3次,请3秒后重新登录!");
					Sleep(3000);
					login(list);
				}
			}
		}

		if (buff.lx == 1){//老师
			loginSucessTeacher(list);
		}
		else{//学生
			loginSucessStudent(list);
		}
	}
	else{
		printf("未注册用户名,请注册或重新输入!\n注册请按1 重新输入请按2\n");
		scanf("%d", &n);
		if (1 == n){
			regist(list);
		}
		else{
			login(list);
		}
	}
}

//用户注册老师账号
void registTeacher(struct Node** list){
	char inUserName[20] = { 0 };
	char inPassWord[20] = { 0 };
	system("cls");
	printf("--------高级vip老师学员管理系统注册界面--------\n");
	printf("尊敬的老师,请输入注册用户名:");
	scanf("%s", inUserName);
	FILE* fp = fopen("register.dat", "rb");
	if (fp == NULL){
		fp = fopen("register.dat", "wb");
		fclose(fp);
		fp = fopen("register.dat", "rb");
	}

	struct registClass buff;
	int r;
	bool isRepeat = false;
	int count = 0;
	while (1){
		r = fread(&buff, sizeof(struct registClass), 1, fp);
		if (r == 0) break;
		if (0 == strcmp(buff.userName, inUserName)){
			printf("已注册此用户名,请重新输入!\n");
			Sleep(1000);
			isRepeat = true;
			break;
		}
		count++;
	}
	fclose(fp);
	if (isRepeat){
		registTeacher(list);
		return;
	}
	printf("尊敬的老师,请输入注册密码:");
	enterPassWord(inPassWord);

	fp = fopen("register.dat", "ab");
	struct registClass temp;
	temp.id = count + 1;
	temp.lx = 1;
	strcpy(temp.userName, inUserName);
	strcpy(temp.passWord, inPassWord);
	fwrite(&temp, 1, sizeof(struct registClass), fp);
	fclose(fp);
	printf("\n注册完成!\n");
	Sleep(1000);
	regist(list);
}
//用户注册学生账号
void registStudent(struct Node** list){
	char inUserName[20] = { 0 };
	char inPassWord[20] = { 0 };
	system("cls");
	printf("--------高级vip老师学员管理系统注册界面--------\n");
	printf("亲爱的同学,请输入注册用户名:");
	scanf("%s", inUserName);
	FILE* fp = fopen("register.dat", "rb");
	if (fp == NULL){
		fp = fopen("register.dat", "wb");
		fclose(fp);
		fp = fopen("register.dat", "rb");
	}

	struct registClass buff;
	int r;
	bool isRepeat = false;
	int count = 0;
	while (1){
		r = fread(&buff, sizeof(struct registClass), 1, fp);
		if (r == 0) break;
		if (0 == strcmp(buff.userName, inUserName)){
			printf("已注册此用户名,请重新输入!\n");
			Sleep(1000);
			isRepeat = true;
			break;
		}
		count++;
	}
	fclose(fp);
	if (isRepeat){
		registStudent(list);
		return;
	}
	printf("亲爱的同学,请输入注册密码:");
	enterPassWord(inPassWord);

	fp = fopen("register.dat", "ab");
	struct registClass temp;
	temp.id = count + 1;
	temp.lx = 2;
	strcpy(temp.userName, inUserName);
	strcpy(temp.passWord, inPassWord);
	fwrite(&temp, 1, sizeof(struct registClass), fp);
	fclose(fp);
	printf("\n注册完成!\n");
	Sleep(1000);
	regist(list);
}

//预留后门^v^  查看所有用户名和密码
//1 退出
void backDoor(struct Node** list){
	int n;
	FILE* fp = fopen("register.dat", "rb");
	struct registClass temp;
	system("cls");
	printf("^v^欢^v^乐^v^的^v^后^v^门^v^\n");
	if (fp == NULL){
		printf("现在空无一人!\n");
	}
	else{
		printf("id\t类型\t用户名\t\t密码\n");
		while (1){
			n = fread(&temp, 1, sizeof(struct registClass), fp);
			if (n <= 0) break;
			if (1 == temp.lx)
			  printf("%d\t老师\t%s\t\t%s\n", temp.id, temp.userName, temp.passWord);
			else
			  printf("%d\t学生\t%s\t\t%s\n", temp.id, temp.userName, temp.passWord);
		}
	}
	
	fclose(fp);
	printf("是否退出?\n");
	scanf("%d", &n);
	if (1 == n)
		regist(list);
}

工具

tool.h

#pragma once
#include "类型.h"
#include "list.h"
#include <windows.h>

//创建一个学生结构体 返回其首地址
struct Student* createStudent();

//输入密码的函数
void enterPassWord(char* passWD);


//给日志文件写入内容
void writeLogFile(char* buf);

//输入科目
EXAMRET* getExamRet(int subjectNum);

tool.c

#include "tool.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


//创建一个学生结构体 返回其首地址
struct Student* createStudent(){
	
	STU* pNew = (STU*)malloc(sizeof(STU));    //类型起别名
	if (NULL == pNew){ 
		char* buff = (char*)malloc(1024);
		memset(buff, 0, 1024);
		sprintf(buff, "tool.c文件中createStudent函数申请内存失败");
		writeLogFile(buff);
		free(buff);
		buff = NULL;
		return NULL; 
	}
	memset(pNew, 0, sizeof(STU));
	return pNew;
}


//输入密码的函数
void enterPassWord(char* passWD){
	char c;
	int idx = 0;
	while (1){
		c = _getch();       //一个个字符get 按了就直接get进去 不会回显也不需要按回车 
		if (c == 13) break; //按了回车,直接结束循环
		if (c == 8){        //返回键,撤销(把前面一个个删掉)
			printf("\b \b");
			if (idx >= 1) idx--;
			continue;
		}
		passWD[idx++] = c;  //一个个字符获取,给数组赋值
		printf("*");        //不显示字符,显示'*'
	}
}

//给日志文件写入内容
void writeLogFile(char* buf){
	FILE* fp = fopen(LOGFILENAME, "a");
	//错误判断

	fprintf(fp, "%s", buf);

	fclose(fp);
}

//输入科目
EXAMRET* getExamRet(int subjectNum){
	EXAMRET* pNew = (EXAMRET*)malloc(subjectNum * sizeof(EXAMRET));
	//注意判断
	if (NULL == pNew){ return NULL; }

	for (int i = 0; i < subjectNum; i++){
		printf("请输入第%d科 科目名:", i + 1);
		scanf("%s", pNew[i].subjectName);
		printf("请输入第%d科 科目成绩:", i + 1);
		scanf("%d", &(pNew[i].grade));
	}

	return pNew;
}

manager.h

#pragma once
#include "login.h"
#include "tool.h"

/*
	所有的管理功能
*/

//作为老师登录之后的欢迎界面
void teacherWelcome(struct Node** list);

//增加学生信息
void addStudentInfo(struct Node** list);

manager.c

#include "manager.h"

//作为老师登录之后的欢迎界面
void teacherWelcome(struct Node** list){
	int n, r;
	system("cls");
	printf("-----------欢迎使用高级vip老师学员管理系统--------\n");
	printf("-------------------教师端--------------------\n");
	printf("1 - 增加学生信息\n");
	printf("2 - 删除学生信息\n");
	printf("3 - 查看所有学生信息\n");
	printf("4 - 查找学生信息\n");
	printf("5 - 修改学生信息\n");
	printf("6 - 回到上层目录\n");
	printf("7 - 退出\n");
	printf("请选择:");
	r = scanf("%d", &n);
	if (-1 == r || n<1 || n>3){
		scanfError();
		teacherWelcome(list);
	}
	else{
		switch (n){
		case 1: addStudentInfo(list); break;
		case 2: break;
		case 3: break;
		case 4: break;
		case 5: break;
		case 6: break;
		case 7:
			system("cls");
			printf("------感谢使用------\n");
			Sleep(1000);
			printf("---------再见--------\n");
			Sleep(2000);
			return;
		}
	}
}


//增加学生信息
void addStudentInfo(struct Node** list){
	//1. 请输入  cmd 到 内存
	STU* pNew = createStudent();
	printf("请输入学生名字:");
	scanf("%s", pNew->name);
	printf("请输入学生学号:");
	scanf("%s", pNew->num);
	printf("请输入学生班级:");
	scanf("%s", pNew->classes);
	printf("请输入学生考试科目数:");
	scanf("%d", & (pNew->subjectNum) );
	pNew->pGrades = getExamRet(pNew->subjectNum);
	//2. 链表
	appendNode(list, pNew);
	travelList(*list);
	//3. 链表到文件

	int n;	scanf("%d", &n);//只为暂停一下

	//输入一个后,继续到老师登录成功后的界面
	teacherWelcome(list);
}

写代码的思路:

决策 写什么?成绩管理系统

架构 老师 增        (按学生id、名字、科目)删        查        (先查后改)改

先做老师部分,要有数据才能查学生部分:

        作为老师登录之后

        1.欢迎界面(5个选项)

        2.针对每个选项有功能(函数)实现

增加学生信息(id、姓名、学号、班级、考试科目...):

        1.请输入    cmd 到 内存

        2.链表

        3.链表 到 文件

实现输入:       一个学生是一个结构体,这个结构体中包含一堆结构体

日志文件:     

        学生 查        (按学科查看) --- 选择查看        (简单计算) --- 求平均分        (排序)

执行层        按架构好的框架用编译器 写代码        用测试工具 测试代码 模块化测试 演示

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuqiuyaq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值