首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C 语言】文件操作 ( 学生管理系统 | 插入数据 | 查询数据 | 删除数据 )

【C 语言】文件操作 ( 学生管理系统 | 插入数据 | 查询数据 | 删除数据 )

作者头像
韩曙亮
发布2023-03-29 21:05:10
发布2023-03-29 21:05:10
1K00
代码可运行
举报
运行总次数:0
代码可运行

文章目录

一、学生管理系统


实现一个简易学生管理系统 , 验证文件操作 ;

1、插入数据

从命令行接收数据 , 放入结构体成员中 , 最后将结构体数据写出到内存中 ;

代码语言:javascript
代码运行次数:0
运行
复制
/*
 * 插入学生数据
 */
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 成员 , 查询是否是要查询的学生姓名 ; 如果是则打印该数据 ;

代码语言:javascript
代码运行次数: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;
}

3、删除数据

将所有的学生数据一次性全部读取出来 ;

然后逐个遍历 , 使用 结构体指针 , 逐个遍历上述全部数据 ;

遍历的同时 , 写出数据 , 如果学生的名字不是要删除的名字 , 则重新写出到文件中 , 否则数据丢弃 , 这样就实现了数据删除操作 ;

代码语言:javascript
代码运行次数: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;
}

二、完整代码


代码示例 :

代码语言:javascript
代码运行次数: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 可执行文件 ;

代码语言:javascript
代码运行次数:0
运行
复制
gcc main.c -o student

输入错误参数 : 如果输入参数小于 2 个 , 则提示参数信息 ;

插入数据 :

查询数据 :

删除数据 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、学生管理系统
    • 1、插入数据
    • 2、查询数据
    • 3、删除数据
  • 二、完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档