释放结构数组的元素?

时间:2018-03-30 16:55:40

标签: c

该程序用于创建项目清单,查看库存,并允许用户通过项目编号删除项目。一切都是通过一个结构数组,我通过一个函数移动数组中的所有其他内容后删除库存项目时很难释放数组元素。任何帮助表示赞赏。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INVENTORY_SIZE 100

typedef struct {
    char item_Number[4];
    char item_Name[20];
    float item_Profit;
    float latest_Price;
    float selling_Price;
    unsigned int stock;
    unsigned int total_Sold;
}InventoryItemType;

void MainMenu();
void displayInventory(InventoryItemType *, int);
void displaySales(InventoryItemType *, int);
InventoryItemType *addItem(void);
InventoryItemType deleteItem(InventoryItemType *, int);

int main()
{
    int i=0, item_count=0;
    char selection, code[4];
    InventoryItemType inventoryItems[MAX_INVENTORY_SIZE];
    while(1)
    {
        MainMenu();

        scanf(" %c", &selection);
        switch(selection) 
        {
        case 'A' :
            displayInventory(inventoryItems, item_count);
            system("pause");
            system("cls");
            continue;
        case 'B' :
            displaySales(inventoryItems, item_count);
            system("pause");
            system("cls");
            continue;
        case 'C' :
            if(item_count == MAX_INVENTORY_SIZE - 1)
            {
                printf("Array is full\n");
                system("pause");
                continue;
            }
            inventoryItems[item_count] = *addItem();
            item_count++;
            continue;
        case 'D' :
            *inventoryItems=deleteItem(inventoryItems, item_count);
            free(&inventoryItems[item_count]);
            item_count--;
            continue;
        case 'E' :
        case 'F' :
        case 'G' :
        case 'H' :
        default :
            printf("Invalid Entry\n" );
            system("pause");
        }
        system("cls");
    }
}
void MainMenu()
{
    printf("A. Display Inventory\n");
    printf("B. Display Sales\n");
    printf("C. Add Item\n");
    printf("D. Remove Item\n");
    printf("E. Enter Shipment\n");
    printf("F. Update Sales\n");
    printf("G. Sort\n");
    printf("H. Exit\n");
    printf("Make a selection\n");
}
void displayInventory(InventoryItemType *display, int key)
{
    system("cls");
    {
        int i;
        for(i=0; i<key; i++)
        {
            printf("Item No.:%s\n", display[i].item_Number);
            printf("Item Name:%s\n", display[i].item_Name);
            printf("Item Stock:%d\n",display[i].stock);
            printf("Item Purchased Price:%.2f\n", display[i].latest_Price);
            printf("Total Value of Items:%.2f\n", (display[i].stock)*(display[i].latest_Price));
            printf("\n");
        }
    }
}
void displaySales(InventoryItemType *display, int key)
{

    int i;
    float total_profit=0;
    system("cls");
    for(i=0; i<key; i++)
    {
        printf("Item No.:%s\n", display[i].item_Number);
        printf("Item Name:%s\n", display[i].item_Name);
        printf("Number of Item Sold:%d\n", display[i].total_Sold);
        printf("Item Selling Price:%.2f\n", display[i].selling_Price);
        printf("Total Profit from Item:%.2f\n", (display[i].selling_Price-display[i].latest_Price)*display[i].total_Sold);
        total_profit=total_profit+((display[i].selling_Price-display[i].latest_Price)*display[i].total_Sold);
        if(i==key-1)
        printf("\nTotal Over-all Profit:%.2f", total_profit);
        printf("\n\n");
    }
}
InventoryItemType *addItem(void)
{
    InventoryItemType *current = (InventoryItemType*) malloc (sizeof *current);
    system("cls");
    if(current == NULL)
        return NULL;
    printf("\nEnter details of item \n\n");
    printf("Enter Item no: \n");
    scanf("%s", current->item_Number);
    printf("Enter Item Name: \n");
    scanf("%s", current->item_Name);
    printf("Enter Stock: \n");
    scanf("%d", &current->stock);
    printf("Enter Purchase Price: \n");
    scanf("%f", &current->latest_Price);
    current->selling_Price=(current->latest_Price)*1.5;
    current->total_Sold=0;
    system("cls");
    return current;
}
InventoryItemType deleteItem (InventoryItemType *deleted, int item_count)
{
    char code[4];
    int i;
    printf("Enter Item Number to be Deleted\n");
    scanf("%3s", code);
    for(i=0;i<item_count;i++)
    {
        if(strcmp(code,deleted[i].item_Number)==0)
                break;
    }
    for(;i<item_count; i++)
        deleted[i]=deleted[i+1];
    return *deleted;
}  

在@Barmar的帮助下编辑:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INVENTORY_SIZE 100

typedef struct {
    char item_Number[4];
    char item_Name[20];
    float item_Profit;
    float latest_Price;
    float selling_Price;
    unsigned int stock;
    unsigned int total_Sold;
}InventoryItemType;
void MainMenu();
void displayInventory(InventoryItemType *[], int);
void displaySales(InventoryItemType *[], int);
InventoryItemType *addItem(void);
InventoryItemType deleteItem(InventoryItemType *, int);

int main()
{
    int i=0, item_count=0;
    char selection, code[4];
    InventoryItemType *inventoryItems[MAX_INVENTORY_SIZE];
    while(1)
    {
        MainMenu();

        scanf(" %c", &selection);
        switch(selection) 
        {
        case 'A' :
            displayInventory(inventoryItems, item_count);
            system("pause");
            system("cls");
            continue;
        case 'B' :
            displaySales(inventoryItems, item_count);
            system("pause");
            system("cls");
            continue;
        case 'C' :
            if(item_count == MAX_INVENTORY_SIZE - 1)
            {
                printf("Array is full\n");
                system("pause");
                continue;
            }
            inventoryItems[item_count] = addItem();
            item_count++;
            continue;
        case 'D' :
            **inventoryItems=deleteItem(*inventoryItems, item_count);
            item_count--;
            continue;
        case 'E' :
        case 'F' :
        case 'G' :
        case 'H' :
        default :
            printf("Invalid Entry\n" );
            system("pause");
        }
        system("cls");
    }
}
void MainMenu()
{
    printf("A. Display Inventory\n");
    printf("B. Display Sales\n");
    printf("C. Add Item\n");
    printf("D. Remove Item\n");
    printf("E. Enter Shipment\n");
    printf("F. Update Sales\n");
    printf("G. Sort\n");
    printf("H. Exit\n");
    printf("Make a selection\n");
}
void displayInventory(InventoryItemType *display[], int key)
{
    system("cls");
    {
        int i;
        for(i=0; i<key; i++)
        {
            printf("Item No.:%s\n", display[i]->item_Number);
            printf("Item Name:%s\n", display[i]->item_Name);
            printf("Item Stock:%d\n",display[i]->stock);
            printf("Item Purchased Price:%.2f\n", display[i]->latest_Price);
            printf("Total Value of Items:%.2f\n", (display[i]->stock)*(display[i]->latest_Price));
            printf("\n");
        }
    }
}
void displaySales(InventoryItemType *display[], int key)
{

    int i;
    float total_profit=0;
    system("cls");
    for(i=0; i<key; i++)
    {
        printf("Item No.:%s\n", display[i]->item_Number);
        printf("Item Name:%s\n", display[i]->item_Name);
        printf("Number of Item Sold:%d\n", display[i]->total_Sold);
        printf("Item Selling Price:%.2f\n", display[i]->selling_Price);
        printf("Total Profit from Item:%.2f\n", (display[i]->selling_Price-display[i]->latest_Price)*display[i]->total_Sold);
        total_profit=total_profit+((display[i]->selling_Price-display[i]->latest_Price)*display[i]->total_Sold);
        if(i==key-1)
        printf("\nTotal Over-all Profit:%.2f", total_profit);
        printf("\n\n");
    }
}
InventoryItemType *addItem(void)
{
    InventoryItemType *current = (InventoryItemType*) malloc (sizeof *current);
    system("cls");
    if(current == NULL)
        return NULL;
    printf("\nEnter details of item \n\n");
    printf("Enter Item no: \n");
    scanf("%s", current->item_Number);
    printf("Enter Item Name: \n");
    scanf("%s", current->item_Name);
    printf("Enter Stock: \n");
    scanf("%d", &current->stock);
    printf("Enter Purchase Price: \n");
    scanf("%f", &current->latest_Price);
    current->selling_Price=(current->latest_Price)*1.5;
    current->total_Sold=0;
    system("cls");
    return current;
}
InventoryItemType deleteItem (InventoryItemType *deleted, int item_count)
{
    char code[4];
    int i;
    printf("Enter Item Number to be Deleted\n");
    scanf("%3s", code);
    for(i=0;i<item_count;i++)
    {
        if(strcmp(code,deleted[i].item_Number)==0)
                break;
    }
    free(deleted[i]);
    for(;i<item_count; i++)
        deleted[i]=deleted[i+1];
    return *deleted;
}

2 个答案:

答案 0 :(得分:1)

inventoryItems的元素未动态分配,因此您无法释放它们。它们直接包含在数组中。当你这样做时:

inventoryItems[item_count] = *add_item();

您正在取消引用指针,而不是将指针存储在数组中。这会生成动态分配结构的副本,并丢弃其指针(因此会导致内存泄漏)。

您应该更改此数组的类型以包含指针:

InventoryItemType * inventoryItems[MAX_INVENTORY_SIZE];

然后你不应该取消引用addItem返回的指针,你应该直接分配它:

inventoryItems[item_count] = add_item();

你释放它:

free(inventoryItems[item_count]);

displayInventory()中,您将所有display[i].xxx更改为display[i]->xxx

答案 1 :(得分:1)

你遇到麻烦的原因是因为你实际上没有分配你想要释放的东西。

addItem函数中,您可以动态分配对象,填充对象并将其返回。但是,在调用函数中,您永远不会保存您返回的指针。您可以直接取消引用它,并通过赋值将内容复制到数组中的实例。这会导致内存泄漏。

稍后,当你去删除一个元素时,你会返回一个指向数组元素的指针,该元素是 not 动态分配的,所以你不能释放它。实际上,你甚至没有返回指向你删除的元素的指针,而是返回到数组的第一个元素,所以你甚至都没有尝试释放你期望的内容。

不是在addItem中动态分配内存,只需传入当前数组元素的地址并填充它。此外,无需在deleteItem中返回任何内容。

所以addItem现在应该是这样的:

void addItem(InventoryItemType *current)
{
    system("cls");
    if(current == NULL)
        return NULL;
    ...
    return;
}

你会这样称呼它:

addItem(&inventoryItems[item_count]);

对于deleteItem,将返回类型更改为void,然后在调用后删除对free的调用。

相关问题