C语言程序使用fopen()无法持久化保存输入至文件的问题
C语言库存管理程序文件读写问题修复
核心问题分析
加载文件的模式错误
loadFromFile函数中使用fopen("inventory.txt", "w"),"w"是写入模式:文件不存在时会创建空文件,存在则直接清空内容。这不仅无法读取原有数据,还会破坏已有文件;若程序无当前目录的创建权限,会直接打开失败,触发"No existing inventory file found"提示。feof的错误使用
用while (!feof(file))作为循环条件会导致多读一次数据,因为feof仅在读取操作失败后才会置位,正确逻辑应基于读取函数的返回值判断循环是否继续。fscanf的格式问题fscanf(file, "%f\n", &items[*count].price)中的\n会匹配任意空白字符,读取数字后残留的换行符会干扰后续fgets读取,导致数据错位。保存时的权限问题
提示"Error opening file for saving"大概率是程序无当前目录写入权限,或文件被其他程序锁定。
修复步骤
1. 修正加载文件的打开模式
将loadFromFile中的fopen模式改为"r"(只读模式),仅用于读取已有文件:
FILE *file = fopen("inventory.txt", "r");
2. 修复循环读取逻辑
替换feof判断为读取函数返回值校验,同时处理fscanf后的换行符:
while (*count < MAX_ITEMS) { // 读取商品名,失败则退出循环 if (fgets(items[*count].itemName, sizeof(items[*count].itemName), file) == NULL) break; items[*count].itemName[strcspn(items[*count].itemName, "\n")] = '\0'; // 读取价格和库存,校验读取是否成功 if (fscanf(file, "%f", &items[*count].price) != 1) break; if (fscanf(file, "%d", &items[*count].stock) != 1) break; // 跳过价格和库存后的换行符,避免干扰后续fgets fgetc(file); // 读取关键词 if (fgets(items[*count].keyword, sizeof(items[*count].keyword), file) == NULL) break; items[*count].keyword[strcspn(items[*count].keyword, "\n")] = '\0'; (*count)++; }
3. 解决保存权限问题
若保存仍失败,检查:
- 当前目录是否有写入权限(如Windows系统下避免在Program Files目录运行,必要时用管理员权限启动)
- 确保
inventory.txt未被其他程序占用
修正后的完整代码
#include <stdio.h> #include <string.h> #define MAX_ITEMS 100 typedef struct { char itemName[50]; float price; int stock; char keyword[20]; } InventoryItem; void addItem(InventoryItem items[], int *count); void editItem(InventoryItem items[], int count); void deleteItem(InventoryItem items[], int *count); void displayItems(const InventoryItem items[], int count); void searchItems(const InventoryItem items[], int count); void saveToFile(const InventoryItem items[], int count); void loadFromFile(InventoryItem items[], int *count); int main() { InventoryItem items[MAX_ITEMS]; int count = 0; int choice; loadFromFile(items, &count); while (1) { printf("Menu:\n"); printf("1. Add Item\n"); printf("2. Edit Item\n"); printf("3. Delete Item\n"); printf("4. Display Items\n"); printf("5. Search Items\n"); printf("6. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); switch (choice) { case 1: addItem(items, &count); break; case 2: editItem(items, count); break; case 3: deleteItem(items, &count); break; case 4: displayItems(items, count); break; case 5: searchItems(items, count); break; case 6: saveToFile(items, count); return 0; default: printf("Invalid choice!\n"); } } return 0; } void addItem(InventoryItem items[], int *count) { if (*count >= MAX_ITEMS) { printf("Inventory is full!\n"); return; } printf("Enter item name: "); getchar(); // Clear newline from buffer fgets(items[*count].itemName, sizeof(items[*count].itemName), stdin); items[*count].itemName[strcspn(items[*count].itemName, "\n")] = '\0'; printf("Enter price: "); scanf("%f", &items[*count].price); printf("Enter stock: "); scanf("%d", &items[*count].stock); printf("Enter keyword: "); getchar(); // Clear newline from buffer fgets(items[*count].keyword, sizeof(items[*count].keyword), stdin); items[*count].keyword[strcspn(items[*count].keyword, "\n")] = '\0'; (*count)++; printf("Item added successfully!\n"); saveToFile(items, *count); } void editItem(InventoryItem items[], int count) { if (count == 0) { printf("No items to edit.\n"); return; } int index; printf("Enter item number to edit (1 to %d): ", count); scanf("%d", &index); if (index < 1 || index > count) { printf("Invalid item number.\n"); return; } index--; // Convert to zero-based index printf("Editing item #%d\n", index + 1); printf("Enter new item name: "); getchar(); // Clear newline from buffer fgets(items[index].itemName, sizeof(items[index].itemName), stdin); items[index].itemName[strcspn(items[index].itemName, "\n")] = '\0'; printf("Enter new price: "); scanf("%f", &items[index].price); printf("Enter new stock: "); scanf("%d", &items[index].stock); printf("Enter new keyword: "); getchar(); // Clear newline from buffer fgets(items[index].keyword, sizeof(items[index].keyword), stdin); items[index].keyword[strcspn(items[index].keyword, "\n")] = '\0'; printf("Item updated successfully!\n"); saveToFile(items, count); } void deleteItem(InventoryItem items[], int *count) { if (*count == 0) { printf("No items to delete.\n"); return; } int index; printf("Enter item number to delete (1 to %d): ", *count); scanf("%d", &index); if (index < 1 || index > *count) { printf("Invalid item number.\n"); return; } index--; // Convert to zero-based index for (int i = index; i < *count - 1; i++) { items[i] = items[i + 1]; } (*count)--; printf("Item deleted successfully!\n"); saveToFile(items, *count); } void displayItems(const InventoryItem items[], int count) { if (count == 0) { printf("No items to display.\n"); return; } printf("Inventory Items:\n"); for (int i = 0; i < count; i++) { printf("Item #%d\n", i + 1); printf("Name: %s\n", items[i].itemName); printf("Price: %.2f\n", items[i].price); printf("Stock: %d\n", items[i].stock); printf("Keyword: %s\n\n", items[i].keyword); } } void searchItems(const InventoryItem items[], int count) { if (count == 0) { printf("No items to search.\n"); return; } char keyword[20]; printf("Enter keyword to search: "); getchar(); // Clear newline from buffer fgets(keyword, sizeof(keyword), stdin); keyword[strcspn(keyword, "\n")] = '\0'; printf("Search Results:\n"); int found = 0; for (int i = 0; i < count; i++) { if (strstr(items[i].keyword, keyword) != NULL) { printf("Item #%d\n", i + 1); printf("Name: %s\n", items[i].itemName); printf("Price: %.2f\n", items[i].price); printf("Stock: %d\n", items[i].stock); printf("Keyword: %s\n\n", items[i].keyword); found = 1; } } if (!found) { printf("No items found with the keyword \"%s\".\n", keyword); } } void saveToFile(const InventoryItem items[], int count) { FILE *file = fopen("inventory.txt", "w"); if (file == NULL) { printf("Error opening file for saving.\n"); return; } for (int i = 0; i < count; i++) { fprintf(file, "%s\n", items[i].itemName); fprintf(file, "%.2f\n", items[i].price); fprintf(file, "%d\n", items[i].stock); fprintf(file, "%s\n", items[i].keyword); } fclose(file); printf("Items saved to file successfully!\n"); } // file opening void loadFromFile(InventoryItem items[], int *count) { FILE *file = fopen("inventory.txt", "r"); if (file == NULL) { printf("No existing inventory file found. Starting fresh.\n"); return; } while (*count < MAX_ITEMS) { if (fgets(items[*count].itemName, sizeof(items[*count].itemName), file) == NULL) break; items[*count].itemName[strcspn(items[*count].itemName, "\n")] = '\0'; if (fscanf(file, "%f", &items[*count].price) != 1) break; if (fscanf(file, "%d", &items[*count].stock) != 1) break; // 跳过price和stock后的换行符 fgetc(file); if (fgets(items[*count].keyword, sizeof(items[*count].keyword), file) == NULL) break; items[*count].keyword[strcspn(items[*count].keyword, "\n")] = '\0'; (*count)++; } fclose(file); printf("Items loaded from file successfully! %d items found.\n", *count); }
内容的提问来源于stack exchange,提问作者congi
相关产品推荐
相关产品推荐

