鱼C论坛

 找回密码
 立即注册
查看: 1521|回复: 3

[已解决]C语言学生管理系统的一个关于文件读写的bug

[复制链接]
发表于 2023-2-4 22:17:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
向前辈们请教问题,以下是我写的学生管理系统,但是在文件存储出现了以下bug:

                               
登录/注册后可看大图

在存入的不同学生中出现了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[20];//学号
        char name[50];//姓名
        char sex[3];//性别
        char department[10];//班级
        char birth[20];//出生日期
        char contact[20];//联系方式
        char address[50];//家庭住址
        int score[6];//成绩
}stu[100];
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[a].num, stu[a].name, stu[a].sex, stu[a].department, stu[a].birth, stu[a].contact, stu[a].address, stu[a].score[0], stu[a].score[1], stu[a].score[2], stu[a].score[3], stu[a].score[4], stu[a].score[5]);
                fprintf(fp, "\r\n");
        }
        fclose(fp);
}

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

        //写入文件
        storage();
}

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

//修改
void modify() {
        int flag = 0;
        int i;
        printf("请输入要修改的学生的学号:");
        char num[20];
        scanf("%s", &num);
        for (i = 0; i < n; i++) {
                if (strcmp(num, stu[i].num) == 0) {
                        printf("请输入要修改的姓名:");
                        scanf("%s", stu[i].name);
                        printf("请输入要修改的性别:");
                        scanf("%s", stu[i].sex);
                        printf("请输入要修改的班级:");
                        scanf("%s", stu[i].department);
                        printf("请输入要修改的出生日期:");
                        scanf("%s", stu[i].birth);
                        printf("请输入要修改的联系方式:");
                        scanf("%s", stu[i].contact);
                        printf("请输入要修改的家庭住址:");
                        scanf("%s", stu[i].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[i].num, stu[i].name, stu[i].sex, stu[i].department, stu[i].birth, stu[i].contact, stu[i].address, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].score[3], stu[i].score[4], stu[i].score[5]);
                printf("\n");
        }

}

//删除
void del() {
        int flag = 0;
        printf("请输入要删除的学生的学号或者姓名:\n");
        char str[20];
        int i, j;
        scanf("%s", str);
        for (i = 0; i < n; i++) {
                if (strcmp(str, stu[i].name) == 0 || strcmp(str, stu[i].num) == 0) {
                        for (j = i; j < n - 1; j++) {
                                stu[j] = stu[j + 1];
                        }
                        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[i].num > stu[j].num) {
                                        struct student temp;
                                        temp = stu[i];
                                        stu[i] = stu[j];
                                        stu[j] = temp;
                                }
                        }
                }
                break;
        }
        case 2: {
                //按姓名排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                if (strcmp(stu[i].name, stu[j].name) > 0) {
                                        struct student temp;
                                        temp = stu[i];
                                        stu[i] = stu[j];
                                        stu[j] = temp;
                                }
                        }
                }
                break;
        }
        case 3: {
                //按班排序
                for (i = 0; i < n - 1; i++) {
                        for (j = i + 1; j < n; j++) {
                                if (strcmp(stu[i].department, stu[j].department) > 0) {
                                        struct student temp;
                                        temp = stu[i];
                                        stu[i] = stu[j];
                                        stu[j] = 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[i].score[k];
                                        sum2 += stu[j].score[k];
                                }
                                if (sum1 > sum2) {
                                        struct student temp;
                                        temp = stu[i];
                                        stu[i] = stu[j];
                                        stu[j] = 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[j].score[course - 1] > stu[j + 1].score[course - 1]) {
                                        temp = stu[j];
                                        stu[j] = stu[j + 1];
                                        stu[j + 1] = temp;
                                }
                        }
                }
                break;
        }
        }
        //写入文件
        storage();
}

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

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")  ;
        }       
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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[20];//学号
        char name[50];//姓名
        char sex[3];//性别
        char department[10];//班级
        char birth[20];//出生日期
        char contact[20];//联系方式
        char address[50];//家庭住址
        int score[6];//成绩
} stu[100] ;

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")  ;
        }       
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-5 00:55:38 | 显示全部楼层
谢谢大佬的回复,把大佬的函数使用到我的代码之后bug修复了,不过萌新还有一点点问题,如果是想存储为文本格式的话应该怎么办呢,(对于二进制格式的理解新手并不是十分明朗),其次我也注意到了大佬代码中关于学生人数n的计算比原代码更优解,我还是向拜问一下如果使用原代码的n自增为何会出现如图的bug呢,再次感谢大佬的回复。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[n].num, stu[n].name, stu[n].sex, stu[n].department, stu[n].birth, stu[n].contact, stu[n].address, &stu[n].score[0], &stu[n].score[1], &stu[n].score[2], &stu[n].score[3], &stu[n].score[4], &stu[n].score[5]);
                        n ++                                 ;
                }
                fclose(fp)                                   ;    
        }
        int choose                                           ;
        printf("欢迎使用学生信息管理系继续,请选择功能:\n") ;
        . . . . . .
        因为你每次都是整个文件读写,所以,用 fopen("student.txt"  , "r") 读,用 fopen("student.txt"  , "w") 写文件就可以了,没必要用 "r+"、"w+" 等打开模式,再有就是必须注意,文件读写操作完成的时候,必须及时关闭文件!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-17 20:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表