介绍
前面写了一篇学生管理系统demo,但是觉得还是少了c中关键的文件相关操作,所以在这里也顺带把文件操作也加到学生管理系统里面去。当然,这里就没有学生系统那么复杂了,主要还是文件的操作。
实现
首先还是照旧,先定义学生信息和课程信息,但是这里就没有用链表存储学生信息了,直接放文件里,要的时候再拿,因为主要是讲解文件操作,故没有作缓存:
#define MAX_NAME_LENGTH20
#define MAX_COURSE_NAME_LENGTH30
#define MAX_COURSE5
static char g_course[MAX_COURSE][MAX_COURSE_NAME_LENGTH] =
{"c语言", "算法", "c++语言", "英语", "数学"};
///@brief 定义学生信息
typedef struct _Student
{
int no;///< 学号 唯一
char name[MAX_NAME_LENGTH];///< 姓名
float score[MAX_COURSE];///< 每个课程的分数
}Student;
下面就是文件操作读操作:
///@brief 从文件中读出学生信息
void readFromFile(const char* fileName)
{
Student stu = {0};
int i = 0;
int count = 0;
FILE* fp = fopen(fileName, "rb");
if (NULL == fp)
{
printf("open file[%s] failed.\n", fileName);
return;
}else
{
printf("open file[%s] success.\n", fileName);
}
printf("学号 姓名 ");
for (i = 0; i < MAX_COURSE; ++ i)
{
printf("%s ", g_course[i]);
}
printf("\n");
while ( !feof(fp))
{
count = fread(&stu, sizeof(Student), 1, fp);
if (ferror(fp))
{
printf("fread error.\n");
break;
}
if (0 == count)
{
break;
}
printf("%d %6s ", stu.no, stu.name);
for (i = 0; i < MAX_COURSE; ++ i)
{
printf("%4.2f ", stu.score[i]);
}
printf("\n");
}
fclose(fp);
return;
}
首先用fopen打开,fopen第一个是文件名,不难理解。主要还是在第2个参数上,其模式比较多,主要有以下几种模式:
r:只读模式,如果文件不存在,则fopen返回失败。
w:只写模式,如果文件存在,则会把文件内存清空。
a:在文件的末尾追加数据,并且在新数据之前不清除EOF标志(这是文档的解释,但是我查看了下,还是没有发现这个EOF标志),如果文件不存在则创建。
r+:以读写的方式打开文件,文件必须存在。
w+:以读写的方式打开文件,并把文件内存清空。
a+:在文件的末尾追加数据,并且在新数据的后面保存EOF标志,如果文件不存在则创建。
t:以文本的模式打开,Ctrl+Z被认为是文件末尾,而且写入文件时会把\r\n写成\n,读出的,把\n读成\r\n。此标志windows下特有, linux无。
b:以二进制模式打开,文件内容是怎样就怎样。此标志windows下特有, linux无。
打开文件之后,就是fread读取文件,这里直接把学生信息读取到结构体当中,并且在循环开始处用feof判断是否已经到了文件尾。ferror用来判断文件操作是否失败,而fread返回0则说明没有内容可以读取。
后面接着就是写入学生信息到文件:
///@brief 把学生信息写入文件
void writeToFile(const char* fileName, Student* stu)
{
FILE* fp = fopen(fileName, "a+b");
if (NULL == fp)
{
printf("open file[%s] failed.\n", fileName);
return;
}else
{
printf("open file[%s] success.\n", fileName);
}
fwrite(stu, sizeof(Student), 1, fp);
fclose(fp);
}
调用fwrite一次性把整个学生结构体追加到文件末尾。
然后就是输入信息的界面:
///@brief 增加学生
void addStudentMenu(const char* fileName)
{
int i = 0;
Student stu = {0};
printf("请输入学生的信息:\n");
printf("学号:");
scanf("%d", &(stu.no));
printf("姓名:");
scanf("%s", stu.name);
for (i = 0; i < MAX_COURSE; ++ i)
{
printf("%s分数:", g_course[i]);
scanf("%f", &(stu.score[i]));
}
writeToFile(fileName, &stu);
printf("插入学生信息成功。\n");
}
///@brief 退出系统
void exitMenu()
{
printf("谢谢使用。\n");
}
///@brief 从文件中读取学生信息
void readStudentInfo()
{
char fileName[256] = {0};
char quit = 'n';
printf("请输入需要读取学生信息的文件名:");
scanf("%s", fileName);
readFromFile(fileName);
}
///@brief 把学生信息写入文件
void writeStudentToFile()
{
char fileName[256] = {0};
char quit = 'n';
printf("请输入需要写入学生信息的文件名:");
scanf("%s", fileName);
addStudentMenu(fileName);
}
main函数:
int main(int argc, char* argv[])
{
mainMenu();
return 0;
}
主体界面如下:
总结
总体来说,文件操作不算太复杂,一起也就这么几个函数:fopen(打开文件),fread(读文件),fwrite(写文件),fclose(关闭文件),feof(判断文件是否到文件尾),ferror(判断文件指示器是否有错误),fflush(把缓存写入到流中)。
[download id=”1016″ template=”button”]