Ash*_*Ash 9 c memory pointers linked-list
我一直在做大学的C任务,并且一直试图理解我似乎对我的代码有一个错误.基本上,我的指针(和/或内存分配)似乎有问题.
此赋值主要是关于链表,因此结构包含指向列表中下一个元素的指针.显然,遍历列表直到我发现当前元素有一个指向下一个元素的NULL指针(然后我将其更改为指向我要添加的'new'元素的指针.
我遇到的问题是,由于某些原因,我的代码似乎完全搞砸了我的内存指针,因为它们会以某种方式变得混乱.它们似乎很好,但很快就会变成垃圾.
以下是我在XCode调试器中的手表向我展示的内容:
第一个圆圈显示了值作为列表中的第一个元素,据我所知,它最初设置正确,应为"C0001\0".第二个圆圈显示current->nextCategory
指针应为NULL(0x0),而是显示奇怪的内存地址(查看它的大小!).我认为这些问题是相关的,但由于我是C的新手,我不知道如何或为什么.
在任何一种情况下,当我签current->nextCategory != NULL
入我的while语句时,它会抛出EXC_BAD_ACCESS:
我花了几个小时把头发拉出来,因为我无法弄清楚我的程序到底发生了什么.我的指针做错了,还是使用malloc()
不当?
这是我的计划的相关部分:
/****************************************************************************
* Initialises the system to a safe empty state.
****************************************************************************/
void systemInit(GJCType* menu)
{
if (menu == NULL) {
fprintf(stderr, "can't initialize system with a null menu pointer.\n");
exit(EXIT_FAILURE);
}
menu->headCategory = NULL;
menu->numCategories = 0;
}
/****************************************************************************
* Loads all data into the system.
****************************************************************************/
int loadData(GJCType* menu, char* menuFile, char* submenuFile)
{
FILE *fp;
size_t len;
char *line;
char *buffer;
CategoryTypePtr category_p;
ItemTypePtr item_p;
char *catId;
if (menu == NULL)
return FALSE;
fp = fopen(menuFile, "r");
if(fp == NULL) {
fprintf(stderr, "can't open %s\n", menuFile);
return FALSE;
}
buffer = malloc(MAX_BUFFER_SIZE);
len = MAX_BUFFER_SIZE;
catId = malloc(ID_LEN + 1);
while((buffer = fgetln(fp, &len))) {
line = strtok(buffer, "\n\0");
category_p = malloc(sizeof(CategoryTypePtr));
if (!tokenizeCategory(line, category_p)) {
fprintf(stderr, "can't tokenize category:> %s\n", line);
free(category_p);
category_p = NULL;
free(buffer);
free(catId);
return FALSE;
}
pushCategory(menu, category_p);
free(category_p);
category_p = NULL;
}
fp = fopen(submenuFile, "r");
if(fp == NULL) {
fprintf(stderr, "can't open %s\n", submenuFile);
return FALSE;
}
while((buffer = fgetln(fp, &len))) {
line = strtok(buffer, "\n\0");
item_p = malloc(sizeof(ItemTypePtr));
if (!tokenizeItem(line, item_p, catId)) {
fprintf(stderr, "can't tokenize item:> %s\n", line);
free(item_p);
item_p = NULL;
free(buffer);
free(catId);
return FALSE;
}
category_p = findCategory(menu, catId);
pushItem(category_p, item_p);
free(item_p);
item_p = NULL;
}
free(buffer);
free(catId);
return TRUE;
}
void pushItem(CategoryTypePtr category, ItemTypePtr item)
{
ItemTypePtr current;
ItemTypePtr new;
if ((new = malloc(sizeof(ItemTypePtr))) == NULL) {
fprintf(stderr, "can't malloc enough memory for new item pointer.\n");
exit(EXIT_FAILURE);
}
*new = *item;
if (category->headItem == NULL) {
category->headItem = new;
} else {
current = category->headItem;
while (current->nextItem != NULL) {
current = current->nextItem;
}
current->nextItem = new;
}
category->numItems++;
}
void pushCategory(GJCType* menu, CategoryTypePtr category)
{
CategoryTypePtr current;
CategoryTypePtr new;
if ((new = malloc(sizeof(CategoryTypePtr))) == NULL) {
fprintf(stderr, "can't malloc enough memory for new category pointer.\n");
exit(EXIT_FAILURE);
}
*new = *category;
if (menu->headCategory == NULL) {
menu->headCategory = new;
} else {
current = menu->headCategory;
while (current->nextCategory != NULL) {
current = current->nextCategory;
}
current->nextCategory = new;
}
menu->numCategories++;
}
CategoryTypePtr findCategory(GJCType* menu, char* id)
{
CategoryTypePtr current;
current = menu->headCategory;
while (current != NULL) {
if (!strcmp(current->categoryID, id))
return current;
current = current->nextCategory;
}
return NULL;
}
/* This function takes the character delimited string and converts it into
* a category structure at the location of the category pointer supplied.
*/
int tokenizeCategory(char *data, CategoryTypePtr category)
{
char* buffer;
if (category == NULL || strlen(data) < 1)
return FALSE;
buffer = malloc(MAX_BUFFER_SIZE);
strcpy(buffer, data);
strcpy(category->categoryID, strtok(buffer, "|\n"));
category->drinkType = *(strtok(NULL, "|\n"));
strcpy(category->categoryName, strtok(NULL, "|\n"));
strcpy(category->categoryDescription, strtok(NULL, "|\n"));
category->numItems = 0;
category->nextCategory = NULL;
category->headItem = NULL;
free(buffer);
return TRUE;
}
/* This function takes the character delimited string and converts it into
* an item structure at the location of the item pointer supplied.
*/
int tokenizeItem(char *data, ItemTypePtr item, char* categoryId)
{
char* buffer;
int i;
if (item == NULL || strlen(data) < 1)
return FALSE;
buffer = malloc(MAX_BUFFER_SIZE);
strcpy(buffer, data);
strcpy(item->itemID, strtok(buffer, "|\n"));
strcpy(categoryId, strtok(NULL, "|\n"));
strcat(categoryId, "\0");
strcpy(item->itemName, strtok(NULL, "|\n"));
for (i = 0; i < NUM_PRICES; i++)
sscanf(strtok(NULL, "|\n"),"%d.%d",&(item->prices[i].dollars),&(item->prices[i].cents));
strcpy(item->itemDescription, strtok(NULL, "|\n"));
item->nextItem = NULL;
free(buffer);
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
标题定义:
/* System-wide constants. */
#define ID_LEN 5
#define MIN_NAME_LEN 1
#define MAX_NAME_LEN 25
#define MIN_DESC_LEN 1
#define MAX_DESC_LEN 250
#define NUM_PRICES 3
#define HOT 'H'
#define COLD 'C'
#define FALSE 0
#define TRUE 1
#define MAX_BUFFER_SIZE 1024
typedef struct category* CategoryTypePtr;
typedef struct item* ItemTypePtr;
/* Structure definitions. */
typedef struct price
{
unsigned dollars;
unsigned cents;
} PriceType;
typedef struct item
{
char itemID[ID_LEN + 1];
char itemName[MAX_NAME_LEN + 1];
PriceType prices[NUM_PRICES];
char itemDescription[MAX_DESC_LEN + 1];
ItemTypePtr nextItem;
} ItemType;
typedef struct category
{
char categoryID[ID_LEN + 1];
char categoryName[MAX_NAME_LEN + 1];
char drinkType; /* (H)ot or (C)old. */
char categoryDescription[MAX_DESC_LEN + 1];
CategoryTypePtr nextCategory;
ItemTypePtr headItem;
unsigned numItems;
} CategoryType;
typedef struct gjc
{
CategoryTypePtr headCategory;
unsigned numCategories;
} GJCType;
Run Code Online (Sandbox Code Playgroud)
sje*_*397 10
它看起来像你没有正确分配内存.
category_p = malloc(sizeof(CategoryTypePtr));
Run Code Online (Sandbox Code Playgroud)
这仅分配足够的内存来存储单个地址,而不是整个类别结构.尝试类似的东西:
category_p = malloc(sizeof(CategoryType));
Run Code Online (Sandbox Code Playgroud)