基于C语言文件操作完成的学生信息管理系统
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "tool.h"
#include "config.h"
typedef struct student
{
char studentID[STUDENTIDLEN + 2];
char name[NAMEMAX + 2];
char sex[SEXMAX + 2];
int age;
int chinesescore;
int mathscore;
int englishscore;
} STUDENT;
void initstudent(void);
#endif
student.c
#include "../include/student.h"
int addstudent(void);
int deletestudent(void);
int alterstudent(void);
int findstudent(void);
void printstudentinfo(void);
/*****************************************
* 函数原型 void initstudent(void)
* 函数功能 在输出界面打印系统信息,调用其他函数
*****************************************/
void initstudent(void)
{
int flag = 1, CMD = -1;
while(flag)
{
system("cls");
printf("***********欢迎使用学生信息管理系统**********\n");
printf("* *\n");
printf("* ----------------------------- *\n");
printf("* | Powered By Qin Yonghang | *\n");
printf("* ----------------------------- *\n");
printf("* *\n");
printf("* 1)添加学生信息 *\n");
printf("* 2)删除学生信息 *\n");
printf("* 3)修改学生信息 *\n");
printf("* 4)查询学生信息 *\n");
printf("* 5)显示所有学生信息 *\n");
printf("* 0)退出学生信息管理系统 *\n");
printf("* *\n");
printf("*********************************************\n");
printf("请输入命令:");
scanf("%d", &CMD);
switch(CMD)
{
case 0: flag = 0; break;
case 1: addstudent(); break;
case 2: deletestudent(); break;
case 3: alterstudent(); break;
case 4: findstudent(); break;
case 5: printstudentinfo(); break;
default: printf("输入命令出错!!"); system("pause");
}
}
}
/*********************************
* 函数原型 int addstudent(void)
* 函数功能 向文件studentinformation尾部写入学生信息
* @return 成功写入学生信息返回写入字节,失败返回-1
*********************************/
int addstudent(void)
{
FILE* studentfp;
int writecount = 0;
STUDENT studentinfo;
printf("请输入学生学号:");
scanf_s("%s", studentinfo.studentID, STUDENTIDLEN + 1);
scanf("*[^\n]"); scanf("*c"); //清除缓冲区
//输入出错处理
while(strlen(studentinfo.studentID) > STUDENTIDLEN )
{
printf("学生学号最多为%d位!!!\n", STUDENTIDLEN );
printf("请重新输入学生学号:");
scanf_s("%s", studentinfo.studentID, STUDENTIDLEN + 1);
scanf("%*[^\n]"); scanf("%*c");
}
printf("请输入学生姓名:");
scanf_s("%s", studentinfo.name, NAMEMAX + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentinfo.name) > NAMEMAX )
{
printf("学生姓名最多为%d位!!!\n", NAMEMAX);
printf("请重新输入学生姓名:");
scanf_s("%s", studentinfo.name, NAMEMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入学生性别:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentinfo.sex) > SEXMAX )
{
printf("学生性别最多为%d位!!!\n", SEXMAX );
printf("请重新输入学生性别:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入学生年龄:");
scanf("%d", &studentinfo.age);
scanf("*[^\n]"); scanf("*c");
while((studentinfo.age < 0) || (studentinfo.age > 100))
{
printf("输入年龄有误(输入年龄应在 10 - 18 之间)!!\n");
printf("请输入学生年龄:");
scanf("%d", &studentinfo.age);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入学生语文成绩:");
scanf("%d", &studentinfo.chinesescore);
scanf("*[^\n]"); scanf("*c");
while((studentinfo.chinesescore < 0) || (studentinfo.chinesescore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入学生语文成绩:");
scanf("%d", &studentinfo.chinesescore);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入学生数学成绩:");
scanf("%d", &studentinfo.mathscore);
scanf("*[^\n]"); scanf("*c");
while((studentinfo.mathscore < 0) || (studentinfo.mathscore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入学生数学成绩:");
scanf("%d", &studentinfo.mathscore);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入学生英语成绩:");
scanf("%d", &studentinfo.englishscore);
scanf("*[^\n]"); scanf("*c");
while((studentinfo.englishscore < 0) || (studentinfo.englishscore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入学生英语成绩:");
scanf("%d", &studentinfo.englishscore);
scanf("*[^\n]"); scanf("*c");
}
if((studentfp = fopen(FILENAME, "ab+")) == NULL)
{
printf("addstudent open text error!\n");
return -1;
}
writecount += fwrite(&studentinfo, 1, sizeof(STUDENT), studentfp);
writecount += fwrite("\r\n", 1, 2, studentfp);
fclose(studentfp);
return writecount;
}
/**********************************
* 函数原型 int deletestudent(void)
* 函数功能 从文件studentinformation中删除学生ID为studentID的学生信息
* @return 成功删除学生信息返回1,失败返回0
**********************************/
int deletestudent(void)
{
FILE* studentfp;
char studentID[STUDENTIDLEN + 2] = {0};
char studentIDbuffer[STUDENTIDLEN + 2] = {0};
long offset = 0;
int deleteflag = 0;
long studentfpsize;
printf("请输入待删除信息学号:");
scanf_s("%s", studentID, STUDENTIDLEN + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentID) > STUDENTIDLEN )
{
printf("学生学号最多为%d位!!!\n", STUDENTIDLEN);
printf("请重新输入学生学号:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
if((studentfp = fopen(FILENAME, "ab+")) == NULL)
{
printf("delete error!\n");
return 0;
}
studentfpsize = fsize(studentfp);
while(studentfpsize > offset)
{
fread(studentIDbuffer, STUDENTIDLEN, 1, studentfp);
if(strcmp(studentIDbuffer, studentID) == 0)
{
fseek(studentfp, -STUDENTIDLEN, 1);
fdelete(FILENAME, studentfp, offset, sizeof(STUDENT) + 2);
deleteflag = 1;
break;
}
offset += sizeof(STUDENT) + 2;
fseek(studentfp, offset, 0);
}
fclose(studentfp);
if(deleteflag)
printf("delete success!\n");
else
printf("delete error!\n");
return deleteflag;
}
/*********************************
* 函数原型 int alterstudent(void)
* 函数功能 更改文件studentinformation中与studentinfo->studentID相同的学生信息
* @param studentinfo 学生信息结构体,包含学生学号,姓名,性别,年龄,成绩
* @return 成功更改学生信息返回1,失败返回0
*********************************/
int alterstudent(void)
{
FILE* studentfp;
char studentIDbuffer[STUDENTIDLEN + 2] = {0};
long offset = 0;
int alterflag = 0;
long studentfpsize;
STUDENT studentinfo;
printf("请输入待更改学生学号:");
scanf_s("%s", studentinfo.studentID, STUDENTIDLEN + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentID) > STUDENTIDLEN )
{
printf("学生学号最多为%d位!!!\n", STUDENTIDLEN);
printf("请重新输入学生学号:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入更改后的学生姓名:");
scanf_s("%s", studentinfo.name, NAMEMAX + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentinfo.name) > NAMEMAX )
{
printf("学生姓名最多为%d位!!!\n", NAMEMAX);
printf("请重新输入学生姓名:");
scanf_s("%s", studentinfo.name, NAMEMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入更改后的学生性别:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentinfo.sex) > SEXMAX )
{
printf("学生性别最多为%d位!!!\n", SEXMAX );
printf("请重新输入学生性别:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
printf("请输入更改后的学生年龄:");
scanf("%d", &studentinfo.age);
while((studentinfo.age < 10) || (studentinfo.age > 18))
{
printf("输入年龄有误(输入年龄应在 10 - 18 之间)!!\n");
printf("请输入更改后的学生年龄:");
scanf("%d", &studentinfo.age);
}
printf("请输入更改后的学生语文成绩:");
scanf("%d", &studentinfo.chinesescore);
while((studentinfo.chinesescore < 0) || (studentinfo.chinesescore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入更改后的学生语文成绩:");
scanf("%d", &studentinfo.chinesescore);
}
printf("请输入更改后的学生数学成绩:");
scanf("%d", &studentinfo.mathscore);
while((studentinfo.mathscore < 0) || (studentinfo.mathscore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入更改后的学生数学成绩:");
scanf("%d", &studentinfo.mathscore);
}
printf("请输入更改后的学生英语成绩:");
scanf("%d", &studentinfo.englishscore);
while((studentinfo.englishscore < 0) || (studentinfo.englishscore > 150))
{
printf("输入成绩有误(输入成绩应在 0 - 150 之间)!!\n");
printf("请输入更改后的学生英语成绩:");
scanf("%d", &studentinfo.englishscore);
}
scanf("*[^\n]"); scanf("*c");
if((studentfp = fopen(FILENAME, "rb+")) == NULL)
{
printf("alter error!\n");
return 0;
}
studentfpsize = fsize(studentfp);
fseek(studentfp, 0, 0);
while(studentfpsize > offset)
{
fread(studentIDbuffer, STUDENTIDLEN, 1, studentfp);
if(strcmp(studentIDbuffer, studentinfo.studentID) == 0)
{
fseek(studentfp, -STUDENTIDLEN, 1);
fwrite(&studentinfo, sizeof(STUDENT), 1, studentfp);
alterflag = 1;
break;
}
offset += sizeof(STUDENT) + 2;
fseek(studentfp, offset, 0);
}
fclose(studentfp);
if(alterflag)
printf("更改成功!\n");
else
printf("更改失败!\n");
return alterflag;
}
/*********************************
* 函数原型 int findstudent(void)
* 函数功能 从文件studentinformation中查找学生ID为studentID的学生信息
* @return 成功查找返回学生信息结构体,失败返回-1
*********************************/
int findstudent(void)
{
FILE* studentfp;
long offset = 0;
long studentfpsize;
int findflag = 0;
char studentID[STUDENTIDLEN + 1] = {0};
STUDENT studentinfo;
printf("请输入待查找学生学号:");
scanf_s("%s", studentinfo.studentID, STUDENTIDLEN + 1);
scanf("*[^\n]"); scanf("*c");
while(strlen(studentID) > STUDENTIDLEN )
{
printf("学生学号最多为%d位!!!\n", STUDENTIDLEN);
printf("请重新输入学生学号:");
scanf_s("%s", studentinfo.sex, SEXMAX + 1);
scanf("*[^\n]"); scanf("*c");
}
if((studentfp = fopen(FILENAME, "ab+")) == NULL)
{
printf("查找失败!\n");
return -1;
}
studentfpsize = fsize(studentfp);
while(studentfpsize > offset)
{
fread(&studentinfo, sizeof(STUDENT), 1, studentfp);
if(strcmp(studentinfo.studentID, studentID) == 0)
{
findflag = 1;
break;
}
offset += sizeof(STUDENT) + 2;
fseek(studentfp, offset, 0);
}
fclose(studentfp);
if(findflag)
{
printf("查找成功!\n");
printf("学生信息如下:\n");
printf("学号: %s\n", studentinfo.studentID);
printf("姓名: %s\n", studentinfo.name);
printf("性别: %s\n", studentinfo.sex);
printf("年龄: %d\n", studentinfo.age);
printf("语文成绩: %d\n", studentinfo.chinesescore);
printf("数学成绩: %d\n", studentinfo.mathscore);
printf("英语成绩: %d\n", studentinfo.englishscore);
system("pause");
}
else
printf("查找失败!\n");
return findflag;
}
/**********************************************
* 函数原型 void printstudentinfo(void)
* 函数功能 打印文件studentinformation中的所有学生信息
**********************************************/
void printstudentinfo(void)
{
FILE* studentfp;
long offset = 0;
STUDENT studentinfo;
long studentfpsize;
int count = 0;
if((studentfp = fopen(FILENAME, "ab+")) == NULL)
{
printf("printstudentinfo open text error!\n");
return;
}
studentfpsize = fsize(studentfp);
while(studentfpsize > offset)
{
fread(&studentinfo, sizeof(studentinfo), 1, studentfp);
count++;
printf("学生信息如下:\n");
printf("学号: %s\n", studentinfo.studentID);
printf("姓名: %s\n", studentinfo.name);
printf("性别: %s\n", studentinfo.sex);
printf("年龄: %d\n", studentinfo.age);
printf("语文成绩: %d\n", studentinfo.chinesescore);
printf("数学成绩: %d\n", studentinfo.mathscore);
printf("英语成绩: %d\n", studentinfo.englishscore);
offset += sizeof(STUDENT) + 2;
fseek(studentfp, offset, 0);
}
fclose(studentfp);
printf("当前学生信息管理系统中共有%d名学生。\n", count);
system("pause");
}
tool.c
#include "../include/tool.h"
/*************************************
* 函数原型 long fsize(FILE* fp)
* 函数功能 求文件大小
* @param fp 文件fp
* @return 成功返回文件的大小
*************************************/
long fsize(FILE* fp)
{
long fp_len;
fpos_t fpos;
fgetpos(fp, &fpos);
fseek(fp, 0, 2);
fp_len = ftell(fp);
fsetpos(fp, &fpos);
return fp_len;
}
/*****************************************
* 函数原型 long fcopy(FILE* fdest, long offsetDest, FILE* fsource, long offsetSource, long size)
* 函数功能 从文件fsource地址offsetSource处复制size个字节到文件fdest地址offsetDest
* @param fdest 目标文件fp
* @param offsetDest 目标文件地址
* @param fsource 源文件fp
* @param offsetSource 源文件地址
* @param size 复制内容字节数
* @return 成功返回复制的字节数,失败返回-1
*****************************************/
long fcopy(FILE* fdest, long offsetDest, FILE* fsource, long offsetSource, long size)
{
long bytes = 0;
int buffer_len = 1024 * 4;
char* buffer = (char*)malloc(buffer_len);
int readCount;
long fdestsize = fsize(fdest), fsourcesize = fsize(fsource);
fpos_t Destoffsetrec, Sourceoffsetrec; //目标文件当前指针,源文件当前指针
if((offsetDest > fdestsize) || (offsetSource > fsourcesize))
{
printf("fcopy param error!\n");
return -1;
}
fgetpos(fdest, &Destoffsetrec);
fgetpos(fsource, &Sourceoffsetrec);
fseek(fdest, offsetDest, 0);
fseek(fsource, offsetSource, 0);
if(size == SIZE_MAX)
{
while((readCount = fread(buffer, 1, buffer_len, fsource)) > 0)
{
bytes += readCount;
fwrite(buffer, readCount, 1, fdest);
}
}
else if(size > 0)
{
while((readCount = fread(buffer, 1, buffer_len, fsource)) > 0)
{
bytes += readCount;
if(bytes > size)
{
bytes -= readCount;
fseek(fsource, offsetSource + bytes, 0);
readCount = fread(buffer, 1, size - bytes, fsource);
if(ferror(fsource))
printf("fread error!\n");
if(feof(fsource))
printf("fread reil error!\n");
fwrite(buffer, readCount, 1, fdest);
bytes += readCount;
break;
}
fwrite(buffer, readCount, 1, fdest);
}
}
else if(size == 0)
bytes = 0;
fsetpos(fdest, &Destoffsetrec);
fsetpos(fsource, &Sourceoffsetrec);
fflush(fdest);
free(buffer);
return bytes;
}
/**************************************************
* 函数原型 int finsert(const char* filename, FILE *fp, long offset, void *buffer, int len)
* 函数功能 向目标文件地址offset处插入len个字节
* @param fp 目标文件fp
* @param buffer 缓冲区,也就是要插入的内容
* @param offset 目标文件地址
* @param len 要插入的内容字节数,如果是字符串,不应该包括'\0'
* @return 成功返回插入的字节数,失败返回-1
**************************************************/
int finsert(const char* filename, FILE *fp, long offset, void *buffer, int len)
{
FILE* tempfp;
int bytes = -1;
fpos_t fpos;
long fpsize = fsize(fp);
fgetpos(fp, &fpos);
fseek(fp, offset, 0);
if((offset > fpsize) || (offset < 0) || (len < 0))
{
printf("finsert param error!\n");
return bytes;
}
if(len == 0)
bytes = 0;
else if(offset == fpsize)
{
bytes = fwrite(buffer, 1, len, fp);
printf("bytes1 = %d\n", bytes);
}
else
{
tempfp = tmpfile();
fcopy(tempfp, 0, fp, 0, offset);
bytes = fwrite(buffer, 1, len, tempfp);
fcopy(tempfp, offset + bytes, fp, offset, SIZE_MAX);
freopen(filename, "wb+", fp);
fcopy(fp, 0, tempfp, 0, SIZE_MAX);
fclose(tempfp);
}
fsetpos(fp, &fpos);
return bytes;
}
/***********************************************
* 函数原型 int fdelete(const char* filename, FILE *fp, long offset, int len)
* 函数功能 从目标文件地址offset处删除len个字节
* @param filename 执行删除操作的文件名
* @param fp 执行删除操作的文件fp
* @param offset 指针偏移量,也就是文件从哪里执行删除操作
* @param len 删除的字节长度
* @return 成功返回删除的字节长度,失败返回-1
***********************************************/
int fdelete(const char* filename, FILE *fp, long offset, int len)
{
FILE* tempfp;
int bytes = -1;
fpos_t fpos;
long fpsize = fsize(fp);
if((offset > fpsize) || (offset < 0) || (len < 0))
{
printf("fdelete param error!\n");
return bytes;
}
fgetpos(fp, &fpos);
fseek(fp, offset, 0);
if(offset == fpsize)
{
bytes = 0;
}
else if((offset + len) <= fpsize)
{
tempfp = tmpfile();
fcopy(tempfp, 0, fp, 0, offset);
fcopy(tempfp, offset, fp, offset + len, fpsize - offset - len);
freopen(filename, "wb+", fp);
fcopy(fp, 0, tempfp, 0, SIZE_MAX);
bytes = len;
fclose(tempfp);
}
else
{
tempfp = tmpfile();
fcopy(tempfp, 0, fp, 0, offset);
freopen(filename, "wb+", fp);
fcopy(fp, 0, tempfp, 0, SIZE_MAX);
bytes = offset + len - fpsize;
fclose(tempfp);
}
fsetpos(fp, &fpos);
return bytes;
}
config.h
#ifndef CONFIG_H
#define CONFIG_H
#define STUDENTIDLEN 10 //学生学号最大字节数
#define NAMEMAX 10 //学生姓名最大字节数
#define SEXMAX 5 //学生性别最大字节数
#define FILENAME "studentinformation.txt" //保存学生信息的文件名称(含路径)
#endif
main.c
#include "./include/student.h"
int main()
{
initstudent();
return 0;
}