文章目录
一、学生管理系统
1、插入数据
2、查询数据
3、删除数据
二、完整代码
一、学生管理系统
实现一个简易学生管理系统 , 验证文件操作 ;
1、插入数据
从命令行接收数据 , 放入结构体成员中 , 最后将结构体数据写出到内存中 ;
/* * 插入学生数据 */ int insert() { // 要写入文件的结构体 struct student s1 = {0}; // 打开要写入的文件 FILE *p = fopen("student.dat", "w"); // 打开失败直接退出 if(p == NULL) return 0; while (1) { // 提示输入学生名字 printf("input student's name:\n"); // 阻塞等待命令行中用户输入学生名字 scanf("%s", s1.name); // 如果用户输入 quit , 则退出循环 , 保存文件 if(strcmp(s1.name, "quit")==0) break; // 提示输入某个学生的年龄 printf("input %s's age:\n", s1.name); // 命令行阻塞等待用户输入学生年龄 scanf("%d", &s1.age); // 将结构体写出到文件中 fwrite(&s1, 1, sizeof (struct student), p); } // 关闭文件 fclose(p); return 0; }
2、查询数据
从命令行中输入要查询的学生信息 , 如果查询全部学生信息 , 则传入 “all” ;
循环从文件中读取单个结构体信息 , 逐个遍历结构体的 name 成员 , 查询是否是要查询的学生姓名 ; 如果是则打印该数据 ;
/* * 查询学生数据 */ int query() { // 缓存信息用的结构体 struct student s = { 0 }; // 要查询的数组 char name[30] = { 0 }; // 提示输入要查询的学生名字 printf("input student's name:"); // name 数组接收控制台输入的字符串 scanf("%s", name); // 打开文件 FILE *p = fopen("student.dat", "r"); // 文件打开失败退出 if (p == NULL) return 0; // 使用该变量记录是否查询到学生信息 int status = 0; // 循环读取 student 结构体数据 // 每次都可以读取到一个学生数据 // 判断该数据是否是要查询的学生数据 while(1) { // 从文件中读取一个结构体大小的数据 fread(&s, 1, sizeof(struct student), p); // 判断是否读取到文件末尾, 注意 feof 必须在文件操作之后才能调用 if (feof(p)) break; // 如果学生名字是 all , 则打印所有学生信息 if (strcmp(name, "all") == 0) { // 打印学生信息 printf("name=%s, age=%d\n", s.name, s.age); // 标记信息找到 status = 1; } else { // 对比本次读取的学生信息是否是要查询的信息 if (strcmp(name, s.name) == 0) { // 打印要查询的学生信息 printf("name=%s, age=%d\n", s.name, s.age); // 标记信息找到 status = 1; } } } // 关闭文件 fclose(p); // 如果学生信息没有找到, 打印提示信息 if (status == 0) printf("student %s not found\n", name); return 0; }
3、删除数据
将所有的学生数据一次性全部读取出来 ;
然后逐个遍历 , 使用 结构体指针 , 逐个遍历上述全部数据 ;
遍历的同时 , 写出数据 , 如果学生的名字不是要删除的名字 , 则重新写出到文件中 , 否则数据丢弃 , 这样就实现了数据删除操作 ;
/* * 删除学生 */ int delete() { // 打开学生信息文件 FILE *p = fopen("student.dat", "r"); // 如果打开失败, 退出 if (p == NULL) return 0; // 获取文件大小 , 将文件指针跳转到文件结尾 fseek(p, 0, SEEK_END); // 获取文件指针位置 , 该位置就是文件大小 int size = ftell(p); // 为学生类型结构体分配堆内存空间, 分配文件大小空间 struct student *s = malloc(size); // 文件指针指向开始位置 fseek(p, 0, SEEK_SET); // 将所有的文件数据读取到堆内存中 fread(s, 1, size, p); // 关闭文件 fclose(p); // 提示要删除的学生名字 printf("input delete student's name: "); // 获取要删除的学生名字 char name[30] = { 0 }; // 从命令行接收学生名字 scanf("%s", name); // 统计文件中记录了多少个学生信息 int n = size / sizeof(struct student);//得到了多少记录数 // 循环控制变量 int i; // 以写的方式打开文件 , 本次写入文件是覆盖写出文件 p = fopen("student.dat", "w"); // 循环遍历结构体数据 for(i = 0; i < n; i++) { // 学生数据不是要删除的数据, 才能写出到文件中 if (strcmp(s[i].name, name) != 0) // 写出一条学生数据结构体 fwrite(&s[i], 1, sizeof(struct student), p); } // 关闭文件 fclose(p); // 释放内存中的文件数据内存 free(s); return 0; }
二、完整代码
代码示例 :
#include <stdio.h> #include <stdlib.h> #include <string.h> // 存储学生姓名和年龄结构体 struct student { char name[30]; // 姓名 int age; // 年龄 }; /* * 插入学生数据 */ int insert() { // 要写入文件的结构体 struct student s1 = {0}; // 打开要写入的文件 FILE *p = fopen("student.dat", "w"); // 打开失败直接退出 if(p == NULL) return 0; while (1) { // 提示输入学生名字 printf("input student's name:\n"); // 阻塞等待命令行中用户输入学生名字 scanf("%s", s1.name); // 如果用户输入 quit , 则退出循环 , 保存文件 if(strcmp(s1.name, "quit")==0) break; // 提示输入某个学生的年龄 printf("input %s's age:\n", s1.name); // 命令行阻塞等待用户输入学生年龄 scanf("%d", &s1.age); // 将结构体写出到文件中 fwrite(&s1, 1, sizeof (struct student), p); } // 关闭文件 fclose(p); return 0; } /* * 查询学生数据 */ int query() { // 缓存信息用的结构体 struct student s = { 0 }; // 要查询的数组 char name[30] = { 0 }; // 提示输入要查询的学生名字 printf("input student's name:"); // name 数组接收控制台输入的字符串 scanf("%s", name); // 打开文件 FILE *p = fopen("student.dat", "r"); // 文件打开失败退出 if (p == NULL) return 0; // 使用该变量记录是否查询到学生信息 int status = 0; // 循环读取 student 结构体数据 // 每次都可以读取到一个学生数据 // 判断该数据是否是要查询的学生数据 while(1) { // 从文件中读取一个结构体大小的数据 fread(&s, 1, sizeof(struct student), p); // 判断是否读取到文件末尾, 注意 feof 必须在文件操作之后才能调用 if (feof(p)) break; // 如果学生名字是 all , 则打印所有学生信息 if (strcmp(name, "all") == 0) { // 打印学生信息 printf("name=%s, age=%d\n", s.name, s.age); // 标记信息找到 status = 1; } else { // 对比本次读取的学生信息是否是要查询的信息 if (strcmp(name, s.name) == 0) { // 打印要查询的学生信息 printf("name=%s, age=%d\n", s.name, s.age); // 标记信息找到 status = 1; } } } // 关闭文件 fclose(p); // 如果学生信息没有找到, 打印提示信息 if (status == 0) printf("student %s not found\n", name); return 0; } /* * 删除学生 */ int delete() { // 打开学生信息文件 FILE *p = fopen("student.dat", "r"); // 如果打开失败, 退出 if (p == NULL) return 0; // 获取文件大小 , 将文件指针跳转到文件结尾 fseek(p, 0, SEEK_END); // 获取文件指针位置 , 该位置就是文件大小 int size = ftell(p); // 为学生类型结构体分配堆内存空间, 分配文件大小空间 struct student *s = malloc(size); // 文件指针指向开始位置 fseek(p, 0, SEEK_SET); // 将所有的文件数据读取到堆内存中 fread(s, 1, size, p); // 关闭文件 fclose(p); // 提示要删除的学生名字 printf("input delete student's name: "); // 获取要删除的学生名字 char name[30] = { 0 }; // 从命令行接收学生名字 scanf("%s", name); // 统计文件中记录了多少个学生信息 int n = size / sizeof(struct student);//得到了多少记录数 // 循环控制变量 int i; // 以写的方式打开文件 , 本次写入文件是覆盖写出文件 p = fopen("student.dat", "w"); // 循环遍历结构体数据 for(i = 0; i < n; i++) { // 学生数据不是要删除的数据, 才能写出到文件中 if (strcmp(s[i].name, name) != 0) // 写出一条学生数据结构体 fwrite(&s[i], 1, sizeof(struct student), p); } // 关闭文件 fclose(p); // 释放内存中的文件数据内存 free(s); return 0; } /* * 打印学生管理系统帮助信息 */ void printf_help() { printf("help info :\n"); printf("i : insert student data\n"); printf("q : query student data\n"); printf("d : delete student data\n"); } /* * 函数入口 * 参数 i 表示插入数据 * 参数 q 表示查询数据 * 参数 d 表示删除数据 */ int main(int argc, char **args) { // 判断参数个数是否合法 if (argc < 2){ // 提示正确的参数信息 printf_help(); return 0; } // 插入数据 if (strcmp(args[1], "i") == 0) insert(); // 查询数据 if (strcmp(args[1], "q") == 0) query(); // 删除数据 if (strcmp(args[1], "d") == 0) delete(); return 0; }
编译程序 : 生成 student.exe 可执行文件 ;
gcc main.c -o student
输入错误参数 : 如果输入参数小于 2 个 , 则提示参数信息 ;
插入数据 :
查询数据 :
删除数据 :