C语言文件操作菜单程序创建空文件、选项2/3功能异常排查问询
问题排查结果
你的代码存在多个逻辑错误、变量作用域错误、IO操作遗漏,以下是具体问题和修复方案:
核心共性问题
- 变量作用域错误:你把
userfile文件名数组、item结构体数组、n条目数量、pf文件指针这些需要跨菜单选项共享的变量,全部定义在了switch的单个case分支内部,属于局部变量,离开当前分支后变量就会失效,其他分支访问到的都是非法内存值。 fflush(stdin)是未定义行为:C标准只规定fflush对输出流有效,清空输入流不能用这个写法,Linux/Windows下表现不一致,建议用while(getchar()!='\n')替代。goto跳转逻辑冗余:用循环实现菜单更规范,避免滥用goto。
各菜单选项的单独问题
选项1(创建文件)
- 逻辑冗余:提示输入文件名后用
scanf("%d", &name)读整数值完全没用,后续也没用到name变量。 - 没有实际创建文件:你只是拼接了文件名存在局部的
userfile数组里,根本没有调用fopen创建文件,你看到的空文件其实是选项2调用fopen("w")生成的。
选项2(添加组件)
- 遗漏写入文件的逻辑:你把用户输入的所有结构体数据都存在了内存的
item数组里,全程没有调用fprintf/fwrite把数据写入到打开的文件指针pf里,关闭文件后自然没有内容。 - 打开模式错误:用
"w"模式打开文件会清空原有内容,每次添加条目都会覆盖之前的记录,需要追加内容应该用"a+"模式。 - 数据没有持久化:录入的
n、item数组都是局部变量,跳转回菜单后数据全部丢失,选项3读不到。
选项3(显示条目)
- 打开文件判断条件错误:你写的是
if(!userfile),正确应该是if(!pf),判断文件指针是否为空。 - 遗漏读文件的逻辑:你直接循环输出内存里的
item数组,根本没有调用fscanf/fread从打开的文件里读数据,输出的都是乱码或者空值。 - 输出函数参数错误:输出到控制台应该用
printf,如果要写文件才需要fprintf并且第一个参数传文件指针。
修复后的核心代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> // 结构体定义提到全局,所有分支都可以用 struct date { int day; int month; int year; }; struct details { char name[20]; int price; int code; int qty; struct date mfg; }; int main() { int num; // 共享变量提到main开头,作用域覆盖整个程序 char userfile[255] = {0}; struct details item[50]; int n = 0; while(1) { printf("\n1. Create a file."); printf("\n2. Add a component to the list."); printf("\n3. Display the current list of component."); printf("\n4. Exit program."); printf("\n\nChoose either these four menu = "); scanf("%d", &num); // 替换fflush(stdin) while(getchar() != '\n'); switch (num) { case 1: printf("\n\nPlease enter file name: "); char username[250] = {0}; scanf("%s", username); while(getchar() != '\n'); sprintf(userfile, "%s.txt", username); // 实际创建文件 FILE *tmp = fopen(userfile, "w"); if(tmp) fclose(tmp); printf("File %s created successfully\n", userfile); break; case 2: if(strlen(userfile) == 0) { printf("Please create file first!\n"); break; } FILE *pf = fopen(userfile, "a+"); if (!pf) { fprintf(stderr, "File opening failed!\n"); return EXIT_FAILURE; } int add_cnt; printf("Enter number of items to add:"); scanf("%d", &add_cnt); while(getchar() != '\n'); for (int i = 0; i < add_cnt; i++) { struct details tmp_item; printf("Item name: \n"); scanf("%s", tmp_item.name); while(getchar() != '\n'); printf("Item code: \n"); scanf("%d", &tmp_item.code); while(getchar() != '\n'); printf("Quantity: \n"); scanf("%d", &tmp_item.qty); while(getchar() != '\n'); printf("price: \n"); scanf("%d", &tmp_item.price); while(getchar() != '\n'); printf("Manufacturing date(dd-mm-yyyy): \n"); scanf("%d-%d-%d", &tmp_item.mfg.day, &tmp_item.mfg.month, &tmp_item.mfg.year); while(getchar() != '\n'); // 写入文件 fprintf(pf, "%s %d %d %d %d %d %d\n", tmp_item.name, tmp_item.code, tmp_item.qty, tmp_item.price, tmp_item.mfg.day, tmp_item.mfg.month, tmp_item.mfg.year); item[n++] = tmp_item; } fclose(pf); break; case 3: if(strlen(userfile) == 0) { printf("Please create file first!\n"); break; } pf = fopen(userfile, "r"); if (!pf) { fprintf(stderr, "File opening failed!\n"); return EXIT_FAILURE; } printf(" ***** INVENTORY ***** \n"); printf("------------------------------------------------------------------\n"); printf("S.N.| NAME | CODE | QUANTITY | PRICE | MFG.DATE \n"); printf("------------------------------------------------------------------\n"); int idx = 0; struct details tmp_item; // 从文件读数据输出 while(fscanf(pf, "%s %d %d %d %d %d %d", tmp_item.name, &tmp_item.code, &tmp_item.qty, &tmp_item.price, &tmp_item.mfg.day, &tmp_item.mfg.month, &tmp_item.mfg.year) == 7) { printf("%d %-15s %-d %-5d %-5d %d/%d/%d \n", idx + 1, tmp_item.name, tmp_item.code, tmp_item.qty, tmp_item.price, tmp_item.mfg.day, tmp_item.mfg.month, tmp_item.mfg.year); idx++; } printf("------------------------------------------------------------------\n"); fclose(pf); break; case 4: printf("Exit Program, Thank You, Sayonara"); return 0; } } return 0; }
内容的提问来源于stack exchange,提问作者Muhammad Rahimy
相关产品推荐
相关产品推荐

