C语言图书管理系统计数异常、作者搜索失败问题求解
问题修复方案
1 add函数中p始终为0的修复
问题原因
- 你以
a追加模式打开文件,此时文件指针默认指向文件末尾,调用numofbooks统计数量时从末尾开始读,自然读不到任何:字符,返回值恒为0 numofbooks函数执行完后文件指针会停在EOF位置,后续如果要操作文件需要重置指针位置
修复代码
修改add函数的文件打开和统计逻辑:
void add() { int ans = 1; static int p; unsigned price, bpages, numavail; FILE *ptr = NULL; system("cls"); // 先以只读模式打开统计数量 ptr = fopen("books info.txt", "r"); if (ptr == NULL) { // 文件不存在则先创建空文件 ptr = fopen("books info.txt", "w"); if (ptr == NULL) { printf("Couldn't open the file...."); exit(1); } fclose(ptr); ptr = fopen("books info.txt", "r"); } p = numofbooks(ptr); fclose(ptr); printf("%d", p); // 此时可以正常输出已有图书数量 // 统计完成后再以追加模式打开写入新数据 ptr = fopen("books info.txt", "a"); if (ptr == NULL) { printf("Couldn't open the file...."); exit(1); } // 原有新增图书的循环逻辑保留即可 while (ans == 1) { printf("\nEnter The name of the book: "); fflush(stdin); gets(info[p].bname); fprintf(ptr, "Book name: %s\n", info[p].bname); fflush(stdin); printf("Enter The author of this book: "); gets(info[p].bauthor); fprintf(ptr, "Book author: %s\n", info[p].bauthor); fflush(stdin); printf("Enter The number of pages of this book: "); scanf("%u", &info[p].bpages); fprintf(ptr, "Number of pages: %u\n", info[p].bpages); fflush(stdin); printf("What is the price of the book (in EGP)? "); scanf("%u", &info[p].price); fprintf(ptr, "Price (in EGP): %u\n", info[p].price); printf("Number of books available: "); scanf("%u", &info[p].numavail); fprintf(ptr, "Number of books available: %u", info[p].numavail); fprintf(ptr, "\n---------------------------------------------------------\n"); printf("\nBook information saved successfully....\n"); p++; // 新增完成后p自增,方便连续新增多本图书 fflush(stdin); printf("\nEnter (1) to add another book, (0) to exit or (2) for main menu. "); scanf("%d", &ans); if (ans == 2) { fclose(ptr); system("cls"); return; // 不要直接调用main(),会导致栈溢出,用return返回主菜单即可 } } fclose(ptr); }
2 searchauthor函数始终输出Not found的修复
问题原因
- 文件名写错:代码中打开的是
books info,正确文件名是books info.txt,缺少后缀导致文件打开失败,统计到的图书数量为0,循环不会执行 - 没有把文件中的图书数据加载到全局
info结构体数组中,搜索时是在空数组中做比对,自然找不到匹配项 gets函数已被C标准废弃,容易出现缓冲区溢出问题,同时输入长度和结构体定义的长度不匹配也可能导致比对失败
修复步骤
- 先实现数据加载函数,把文件中的图书信息同步到
info数组:
void load_books_info() { FILE *ptr = fopen("books info.txt", "r"); if (ptr == NULL) return; int total = numofbooks(ptr); rewind(ptr); // 重置文件指针到开头 char buf[200]; for (int i = 0; i < total; i++) { // 逐行读取解析数据存入结构体 fgets(buf, sizeof(buf), ptr); sscanf(buf, "Book name: %[^\n]", info[i].bname); fgets(buf, sizeof(buf), ptr); sscanf(buf, "Book author: %[^\n]", info[i].bauthor); fgets(buf, sizeof(buf), ptr); sscanf(buf, "Number of pages: %u", &info[i].bpages); fgets(buf, sizeof(buf), ptr); sscanf(buf, "Price (in EGP): %u", &info[i].price); fgets(buf, sizeof(buf), ptr); sscanf(buf, "Number of books available: %u", &info[i].numavail); fgets(buf, sizeof(buf), ptr); // 跳过分割线 } fclose(ptr); }
- 修复searchauthor函数逻辑:
void searchauthor() { char in_name[100]; // 长度和结构体中bauthor字段匹配 int flag = 1; // 先加载文件数据到info数组 load_books_info(); FILE *ptr = fopen("books info.txt", "r"); if (ptr == NULL) { printf("无法打开图书文件\n"); return; } int num = numofbooks(ptr); fclose(ptr); printf("Enter the name of the author: "); // 替换gets为fgets,避免缓冲区溢出 fgets(in_name, sizeof(in_name), stdin); // 去掉fgets读取到的末尾换行符 in_name[strcspn(in_name, "\n")] = '\0'; for (int i = 0; i < num; i++) { if (strcmpi(in_name, info[i].bauthor) == 0) { printf("书名:%s 价格:%u EGP 库存:%u 页数:%u\n", info[i].bname, info[i].price, info[i].numavail, info[i].bpages); flag = 0; } } if (flag == 1) { printf("Not found."); } }
其他优化建议
- 不要调用
fflush(stdin),该行为是C标准未定义的,处理输入残留换行可以用while(getchar()!='\n');替代 - 程序启动时就调用一次
load_books_info,避免每次操作都重复读取文件
内容的提问来源于stack exchange,提问作者Ali Elneklawy
相关产品推荐
相关产品推荐

