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