我想写一些代码来练习C语言,我想做的(只是练习,没有任何用处)是创建一个库存系统,你可以在上面添加或删除一个项目。
我决定用一个动态字符串数组来实现它。因为我对C语言很陌生,所以很难理解指针和其他东西是怎么回事,但我最终得到了它。
我设法编写了一些代码。但我有一个问题,我似乎无法调试,我不明白它来自哪里,这是我的代码(可能真的被诅咒)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int addItemToInventory(char ***Inv_content,int *Inv_length,char* Item)
{
int item_name_size=strlen(Item);
if (*Inv_length==0) //If The size of the inventory is 0, I have to create the array.
{
*Inv_content = malloc((1) * sizeof(char*));
if (*Inv_content) // malloc succeed
{
*Inv_content[0] = malloc((item_name_size+1) * sizeof(char));
if (*Inv_content[0]) // malloc succeed
{
strcpy(*Inv_content[0], Item);
*Inv_length+=1;
}
else // malloc failed
{
printf("Impossible to allocate memory for item '%s' in InvContent[0] \n", Item);
return(2);
}
}
else // malloc failed
{
printf("Impossible to allocate memory for Inv. (Create New Inv)\n");
return(1);
}
}
else //the size of the inventory is greater than zero, I have to expand the current array and add the item to the new slot
{
char **tmp_pnt;
tmp_pnt= realloc(*Inv_content, (*Inv_length+1) * sizeof(char*));
if (tmp_pnt)
{
*Inv_content=tmp_pnt;
*Inv_content[*Inv_length] = malloc((item_name_size+1) * sizeof(char));
if (*Inv_content[*Inv_length])
{
strcpy(*Inv_content[*Inv_length], Item);
*Inv_length+=1;
}
else // malloc failed
{
printf("unable to allocate memory for item '%s' in InvContent[%d]\n", Item, *Inv_length);
return(2);
}
}
else // realloc failed
{
printf("Impossible to allocate memory for Inv. (Add Item (realloc))\n");
return(1);
}
}
return(0);
}
所以,我希望代码足够清晰,正如你所看到的,这个函数有3个参数:
- 指向清单本身的指针(以便直接对其进行更改)
- 一个指向库存大小的指针,原因相同
- 和要添加的项目名称
现在问题来了,这是我用来测试我的函数的主要函数:
int main()
{
//int run = 1;
char **Inv_content = NULL;
int Inv_length=0;
//int Item_index=-1;
char Item1[12]="Great Sword";
char Item2[8]="Big Bow";
addItemToInventory(&Inv_content, &Inv_length, Item1);
addItemToInventory(&Inv_content, &Inv_length, Item2);
printf("\n");
for (int i=0; i<=Inv_length-1;i++)
{
printf ("Item %d : %s \n", i, Inv_content[i]);
}
}
结果是
- 第一件:巨剑
- 项目2:(NULL)
当调用函数一次,没有问题,我认为我的函数的第一部分(Case when size = 0)工作正常。当调用第二次时,它输出“(null)”作为结果,就像数组中没有任何东西一样。当调用第三次(或更多次)时,情况更糟,它崩溃了“分段错误”。
这是我发现的,第二部分按预期工作,当printf("%s", *Inv_content[1])
在函数内部时,即使在它的末尾,它也会输出“Big bow”,就像预期的那样,但是一旦它离开函数,当打印inv_content[1]时,它会输出(null),就像它在函数退出时被擦除一样。
最后,我不明白为什么我在调用3+次时会出现分段错误,因为它不会与2(这应该是相同的情况)
无论如何,我希望你们能帮助我了解更多发生了什么,这样我就不会在未来犯这些错误:)谢谢
3条答案
按热度按时间z2acfund1#
对于初学者来说,函数应该至少声明为
其次,根据条件将函数体分成两部分是没有意义的
函数在语句中包含错误,例如
你需要写
该函数可以如下所示
请注意,该功能不应发出任何消息。
函数的调用者将决定是否根据函数的返回值输出消息。
另外,在函数中不使用魔术数字0、1和2,而是可以引入枚举,例如
例如,在函数write中
这个函数有一些严重的问题。如果字符串
item
的字符数组没有被分配,但是指针数组已经被重新分配了。所以这个函数的行为在逻辑上是不一致的。最好用下面的方法重写函数
该功能看起来更清晰,没有逻辑上的不一致。
wj8zmpe12#
*Inv_content[*Inv_length]
正在查找您的数组旁边的下一个数组(可能已分配,也可能未分配)。您希望使用(*Inv_content)[*Inv_length]
来查找数组 * 中的选定项 *。另外,这里有一个稍微不那么糟糕的代码版本,你在代码中重写了至少
strdup
,并且使用了错误的大小类型:v6ylcynt3#
我想先指出你正在做three star programming。你所谓的库存,实际上是一个
InventoryItem
对象的Inventory
容器。你不必尊重这一点,但你应该写更多的文档来弥补复杂性,因为单个指针已经足够复杂了,因为不清楚它是否指向堆,堆栈,这种复杂性也使得更改设计变得更加困难,部分原因是与指针争论的“沉没时间成本”,部分原因是与InventoryItem
的实现细节的严重耦合。我想提出一个粗略的,更统一的设计,最初似乎更复杂,但实际上更简单,因为:
1.所有的东西都明确地放在堆上。
1.每个
InventoryItem
都有责任照顾好自己,而不会让Inventory
承担构建和释放InventoryItem
的复杂细节。1.长度与库存指针一起分组,使得一次拥有多个库存变得更简单,而无需执行诸如拥有库存指针数组和另一个长度数组之类的操作。