Napstablook 发表于 2023-2-4 22:17:00

C语言学生管理系统的一个关于文件读写的bug

向前辈们请教问题,以下是我写的学生管理系统,但是在文件存储出现了以下bug:
https://imgloc.com/i/N6vQE
在存入的不同学生中出现了0 0 0 0 0 0 (初步怀疑是分数存储问题)
且变量学生人数n在打断点后发现增加不正常,在 读取文件 代码上也可能存在问题。
以下为新手代码,敬请各位前辈斧正。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
struct student {
        char num;//学号
        char name;//姓名
        char sex;//性别
        char department;//班级
        char birth;//出生日期
        char contact;//联系方式
        char address;//家庭住址
        int score;//成绩
}stu;
int n = 0;//学生人数

//写入文件
void storage() {
        FILE* fp;
        int a, b;
        fp = fopen("student.txt", "w+");
        for (a = 0; a < n; a++) {
                fprintf(fp, "%s %s %s %s %s %s %s %d %d %d %d %d %d", stu.num, stu.name, stu.sex, stu.department, stu.birth, stu.contact, stu.address, stu.score, stu.score, stu.score, stu.score, stu.score, stu.score);
                fprintf(fp, "\r\n");
        }
        fclose(fp);
}

//插入
void insert() {
        printf("请输入要插入的学生的学号:");
        scanf("%s", &stu.num);
        printf("请输入要插入的学生的姓名:");
        scanf("%s", stu.name);
        printf("请输入要插入的学生的性别:");
        scanf("%s", stu.sex);
        printf("请输入要插入的学生的班级:");
        scanf("%s", stu.department);
        printf("请输入要插入的学生的出生日期:");
        scanf("%s", stu.birth);
        printf("请输入要插入的学生的联系方式:");
        scanf("%s", stu.contact);
        printf("请输入要插入的学生的家庭住址:");
        scanf("%s", stu.address);
        printf("请输入要插入的学生的语文成绩:");
        scanf("%d", &stu.score);
        printf("请输入要插入的学生的数学成绩:");
        scanf("%d", &stu.score);
        printf("请输入要插入的学生的英语成绩:");
        scanf("%d", &stu.score);
        printf("请输入要插入的学生的物理成绩:");
        scanf("%d", &stu.score);
        printf("请输入要插入的学生的化学成绩:");
        scanf("%d", &stu.score);
        printf("请输入要插入的学生的生物成绩:");
        scanf("%d", &stu.score);
        n++;

        //写入文件
        storage();
}

//查询
void search() {
        int flag = 0;//查询标志
        int i, j;
        printf("请输入要查询的学生的学号或者姓名:\n");
        char str;
        scanf("%s", str);
        for (i = 0; i < n; i++) {
                if (strcmp(str, stu.name) == 0 || strcmp(str, stu.num) == 0) {
                        printf("学号:%s 姓名:%s 性别:%s 班级:%s 出生日期:%s 联系方式:%s 家庭住址:%s 成绩:", stu.num, stu.name, stu.sex, stu.department, stu.birth, stu.contact, stu.address);
                        for (j = 0; j < 6; j++) {
                                printf("%d ", stu.score);
                        }
                        printf("\n");
                        flag = 1;
                        break;
                }
        }
        if (flag == 0)printf("没有找到相应的学生信息!\n");
}

//修改
void modify() {
        int flag = 0;
        int i;
        printf("请输入要修改的学生的学号:");
        char num;
        scanf("%s", &num);
        for (i = 0; i < n; i++) {
                if (strcmp(num, stu.num) == 0) {
                        printf("请输入要修改的姓名:");
                        scanf("%s", stu.name);
                        printf("请输入要修改的性别:");
                        scanf("%s", stu.sex);
                        printf("请输入要修改的班级:");
                        scanf("%s", stu.department);
                        printf("请输入要修改的出生日期:");
                        scanf("%s", stu.birth);
                        printf("请输入要修改的联系方式:");
                        scanf("%s", stu.contact);
                        printf("请输入要修改的家庭住址:");
                        scanf("%s", stu.address);
                        flag = 1;
                        break;
                }
        }
        if (flag == 0)printf("没有找到该学生!\n");

        //写入文件
        storage();
}

//浏览
void show() {
        int i,j;
        for (i = 0; i < n; i++) {
                printf("学号:%s 姓名:%s 性别:%s 班级:%s 出生日期:%s 联系方式:%s 家庭住址:%s 语文成绩:%d 数学成绩:%d 英语成绩:%d 物理成绩:%d 化学成绩:%d 生物成绩:%d", stu.num, stu.name, stu.sex, stu.department, stu.birth, stu.contact, stu.address, stu.score, stu.score, stu.score, stu.score, stu.score, stu.score);
                printf("\n");
        }

}

//删除
void del() {
        int flag = 0;
        printf("请输入要删除的学生的学号或者姓名:\n");
        char str;
        int i, j;
        scanf("%s", str);
        for (i = 0; i < n; i++) {
                if (strcmp(str, stu.name) == 0 || strcmp(str, stu.num) == 0) {
                        for (j = i; j < n - 1; j++) {
                                stu = stu;
                        }
                        flag = 1;
                        n--;
                        break;
                }
        }
        printf("删除成功!\n");
        if (flag == 0)printf("没有找到该学生!\n");

        //写入文件
        storage();
}

//排序
void sort()
{
        printf("请输入要排序的方式(1.按学号排序 2.按姓名排序 3.按班级排序 4.按总分排序 5.按某科分数排序):\n");
        int way, i, j;
        scanf("%d", &way);
        switch (way) {
        case 1: {
                //按学号排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                if (stu.num > stu.num) {
                                        struct student temp;
                                        temp = stu;
                                        stu = stu;
                                        stu = temp;
                                }
                        }
                }
                break;
        }
        case 2: {
                //按姓名排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                if (strcmp(stu.name, stu.name) > 0) {
                                        struct student temp;
                                        temp = stu;
                                        stu = stu;
                                        stu = temp;
                                }
                        }
                }
                break;
        }
        case 3: {
                //按班排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                if (strcmp(stu.department, stu.department) > 0) {
                                        struct student temp;
                                        temp = stu;
                                        stu = stu;
                                        stu = temp;
                                }
                        }
                }
                break;
        }
        case 4: {
                //按总分排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                int sum1 = 0, sum2 = 0, k;
                                for (k = 0; k < 6; k++) {
                                        sum1 += stu.score;
                                        sum2 += stu.score;
                                }
                                if (sum1 > sum2) {
                                        struct student temp;
                                        temp = stu;
                                        stu = stu;
                                        stu = temp;
                                }
                        }
                }
                break;
        }
        case 5: {
                //按某科分数排序
                struct student temp;
                printf("请输入要排序的科目(1.语文 2.数学 3.英语 4.物理 5.化学 6.生物):\n");
                int course;
                scanf("%d", &course);
                for (i = 0; i < n - 1; i++) {
                        for (j = 0; j < n - 1 - i; j++) {
                                if (stu.score > stu.score) {
                                        temp = stu;
                                        stu = stu;
                                        stu = temp;
                                }
                        }
                }
                break;
        }
        }
        //写入文件
        storage();
}

//输出成绩最高的三名学生
void highscore()
{
        struct student temp;
        int i, j, k;
        for (i = 0; i < 3; i++) {
                int maxscore = 0;
                int index = 0;
                for (j = 0; j < n; j++) {
                        int sum = 0;
                        for (k = 0; k < 6; k++) {
                                sum += stu.score;
                        }
                        if (sum > maxscore) {
                                maxscore = sum;
                                index = j;
                        }
                }
                temp = stu;
                stu.score = -1;
        }
        printf("成绩最高的三名学生的信息如下:\n");
        int a, b;
        for (a = 0; a < 3; a++) {
                printf("学号:%s 姓名:%s 性别:%s 班级:%s 出生日期:%s 联系方式:%s 家庭住址:%s 成绩:", temp.num, temp.name, temp.sex, temp.department, temp.birth, temp.contact, temp.address);
                for (b = 0; b < 6; b++) {
                        printf("%d ", temp.score);
                }
                printf("\n");
        }
}



int main() {
        //读取文件
        FILE* fp;
        fp = fopen("student.txt", "r+");
        if (fp == NULL) {
                fp = fopen("student.txt", "w+");
        }
        else {
                while (!feof(fp)) {
                        fscanf(fp, "%s %s %s %s %s %s %s %d %d %d %d %d %d", &stu.num, stu.name, stu.sex, stu.department, stu.birth, stu.contact, stu.address, &stu.score, &stu.score, &stu.score, &stu.score, &stu.score, &stu.score);
                        n++;
                }
        }

                int choose;
                printf("欢迎使用学生信息管理系继续,请选择功能:\n");
                printf("1.插入\n");
                printf("2.查询\n");
                printf("3.修改\n");
                printf("4.浏览\n");
                printf("5.删除\n");
                printf("6.排序\n");
                printf("7.输出成绩最高的三名学生\n");
                printf("0.退出\n");
                printf("请输入你的选择:\n");
                scanf("%d", &choose);
                switch (choose) {
                case 1:insert(); break;
                case 2:search(); break;
                case 3:modify(); break;
                case 4:show(); break;
                case 5:del(); break;
                case 6:sort(); break;
                case 7:highscore(); break;
                case 0:return 0;
                default:printf("输入有误!\n");
                }
       
        return 0;
}

jackz007 发表于 2023-2-4 22:43:59

本帖最后由 jackz007 于 2023-2-4 23:40 编辑

          文件无需写成文本格式,写成二进制格式岂不简单?直接向文件中写入结构数据映像,读写数据都会简单很多。
#define _CRT_SECURE_NO_WARNINGS

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

struct student {
      char num;//学号
      char name;//姓名
      char sex;//性别
      char department;//班级
      char birth;//出生日期
      char contact;//联系方式
      char address;//家庭住址
      int score;//成绩
} stu ;

int n = 0; //学生人数

void save(void)
{
      FILE * fp                                                          ;
      if((fp = fopen("student.dat" , "wb"))) {
                fwrite(stu , sizeof(struct student) , n , fp)            ;
                fclose(fp)                                                 ;
                printf("文件保存完毕。\n")                                 ;
      } else {
                fprintf(stderr , "错误 : 无法创建文件 \"student.dat\"\n");
      }      
}

void load(void)
{
      FILE * fp                                                          ;
      if((fp = fopen("student.dat" , "rb"))) {
                fseek(fp , 0 , 2)                                          ;
                n = ftell(fp) / sizeof(struct student)                     ;
                fseek(fp , 0 , 0)                                          ;
                fread(stu , sizeof(struct student) , n , fp)               ;
                fclose(fp)                                                 ;
                printf("文件读取完毕。\n")                                 ;
      } else {
                fprintf(stderr , "错误 : 无法打开文件 \"student.dat\"\n");
      }      
}

Napstablook 发表于 2023-2-5 00:55:38

谢谢大佬的回复,把大佬的函数使用到我的代码之后bug修复了,不过萌新还有一点点问题,如果是想存储为文本格式的话应该怎么办呢,(对于二进制格式的理解新手并不是十分明朗),其次我也注意到了大佬代码中关于学生人数n的计算比原代码更优解,我还是向拜问一下如果使用原代码的n自增为何会出现如图的bug呢,再次感谢大佬的回复。

jackz007 发表于 2023-2-5 12:02:17

本帖最后由 jackz007 于 2023-2-5 12:07 编辑

Napstablook 发表于 2023-2-5 00:55
谢谢大佬的回复,把大佬的函数使用到我的代码之后bug修复了,不过萌新还有一点点问题,如果是想存储为文本 ...

int main(void)
{
      //读取文件
      FILE * fp                                          ;
      if((fp = fopen("student.txt", "r"))) {
                while (! feof(fp)) {
                        fscanf(fp , "%s%s%s%s%s%s%s%d%d%d%d%d%d", &stu.num, stu.name, stu.sex, stu.department, stu.birth, stu.contact, stu.address, &stu.score, &stu.score, &stu.score, &stu.score, &stu.score, &stu.score);
                        n ++                                 ;
                }
                fclose(fp)                                 ;   
      }
      int choose                                           ;
      printf("欢迎使用学生信息管理系继续,请选择功能:\n") ;
      . . . . . .
      因为你每次都是整个文件读写,所以,用 fopen("student.txt", "r") 读,用 fopen("student.txt", "w") 写文件就可以了,没必要用 "r+"、"w+" 等打开模式,再有就是必须注意,文件读写操作完成的时候,必须及时关闭文件!
页: [1]
查看完整版本: C语言学生管理系统的一个关于文件读写的bug