You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言程序使用fopen()无法持久化保存输入至文件的问题

C语言库存管理程序文件读写问题修复

核心问题分析

  1. 加载文件的模式错误
    loadFromFile函数中使用fopen("inventory.txt", "w"),"w"是写入模式:文件不存在时会创建空文件,存在则直接清空内容。这不仅无法读取原有数据,还会破坏已有文件;若程序无当前目录的创建权限,会直接打开失败,触发"No existing inventory file found"提示。

  2. feof的错误使用
    用while (!feof(file))作为循环条件会导致多读一次数据,因为feof仅在读取操作失败后才会置位,正确逻辑应基于读取函数的返回值判断循环是否继续。

  3. fscanf的格式问题
    fscanf(file, "%f\n", &items[*count].price)中的\n会匹配任意空白字符,读取数字后残留的换行符会干扰后续fgets读取,导致数据错位。

  4. 保存时的权限问题
    提示"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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:38:09