如何在C语言中动态分配结构体数组?实现可变长度购物列表
要实现无固定大小限制的购物列表,你需要把原来的固定数组改成动态内存分配,核心是用malloc/realloc来按需分配空间。以下是具体修改步骤和代码:
1. 更新头文件的结构体定义
把ShoppingList里的固定数组改成指针,这样才能动态分配内存:
#ifndef SHOPPING_LIST_H #define SHOPPING_LIST_H struct GroceryItem { char productName[20]; float amount; char unit[10]; }; struct ShoppingList { int length; // 当前已添加的条目数量 struct GroceryItem* itemList; // 指向动态分配的条目数组的指针 }; // 函数声明不变 void addItem(struct ShoppingList *list); void printList(struct ShoppingList *list); void editItem(struct ShoppingList *list); void removeItem(struct ShoppingList *list); void saveList(struct ShoppingList *list); void loadList(struct ShoppingList* list); #endif
2. 初始化购物列表(main函数)
初始化时要把动态数组指针设为NULL,表示当前没有分配内存,还要记得程序结束后释放内存避免泄漏:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include "ShoppingList.h" #include<stdlib.h> int main(void) { struct ShoppingList shoppingList; shoppingList.length = 0; shoppingList.itemList = NULL; // 初始化空指针 int option; do { printf("\n\nWelcome to the shopping list manager!\n"); printf("=====================================\n\n"); printf("1. Add an item\n"); printf("2. Display the shopping list\n"); printf("3. Remove an item\n"); printf("4. Change an item\n"); printf("5. Save list\n"); printf("6. Load list\n"); printf("7. Exit\n"); printf("What do you want to do? "); scanf("%d", &option); switch (option) { case 1: addItem(&shoppingList); break; case 2: printList(&shoppingList); break; case 3: removeItem(&shoppingList); break; case 4: editItem(&shoppingList); break; case 5: saveList(&shoppingList); break; case 6: loadList(&shoppingList); break; case 7: break; default: printf("Please enter a number between 1 and 7\n"); } } while (option != 7); // 释放动态分配的内存 if (shoppingList.itemList != NULL) { free(shoppingList.itemList); shoppingList.itemList = NULL; // 置空防止野指针 } return 0; }
3. 修改addItem函数实现
每次添加条目时,用realloc动态扩容内存,同时要检查内存分配是否成功:
#define _CRT_SECURE_NO_WARNINGS #include"ShoppingList.h" #include<stdio.h> #include<stdlib.h> void addItem(struct ShoppingList* list) { // 扩容内存:分配能容纳length+1个条目的空间 struct GroceryItem* temp = realloc(list->itemList, sizeof(struct GroceryItem) * (list->length + 1)); if (temp == NULL) { printf("内存分配失败,无法添加新条目!\n"); return; } list->itemList = temp; // 分配成功后更新指针 // 输入商品信息,逻辑和原来一致 printf("Name for product: "); scanf("%s", list->itemList[list->length].productName); do { printf("Enter the amount: "); scanf("%f", &list->itemList[list->length].amount); if (list->itemList[list->length].amount <= 0.0) { printf("Input is invalid.\n"); } } while (list->itemList[list->length].amount <= 0.0); printf("Enter unit of item: "); scanf("%s", list->itemList[list->length].unit); printf("%s was added to the shoppinglist.\n", list->itemList[list->length].productName); list->length++; }
关键细节说明
realloc的用法:如果原指针是NULL(第一次添加时),realloc等价于malloc;如果原指针已有内存,会把原有数据复制到新的内存空间,然后释放旧空间。- 内存分配失败检查:
realloc可能返回NULL(比如系统内存不足),必须判断,否则会导致程序崩溃。 - 内存释放:动态分配的内存不会自动回收,必须用
free手动释放,否则会造成内存泄漏。 - 指针的数组式访问:动态分配的指针可以像普通数组一样用
[下标]访问元素,C语言会自动处理指针偏移。
额外提示
- 原代码中
addItem函数有个错误:return 0;但函数返回类型是void,这个问题已经在修改后的代码中移除了。 - 如果要支持带空格的商品名,后续可以把
scanf("%s")换成fgets,注意处理换行符。
内容的提问来源于stack exchange,提问作者Hejhej12
相关产品推荐
相关产品推荐

