我正在尝试创建两个列表,优点和缺点,然后打印它们 . 但我无法弄清楚我做错了什么 .
我尝试使用gdb在线调试程序,我发现错误在函数fgets()中 .
#include <stdio.h>
#include <string.h>
typedef struct list{
char ** reason;
} list;
void printMenu();
void printList(list * myList, int len1);
int main(void)
{
int keepGoing = 0;
int choice = 0;
int i = 0;
int j = 0;
list * pros;
list * cons;
while (!keepGoing){
printMenu();
scanf("%d", &choice);
pros = (list*)malloc(sizeof(list));
cons = (list*)malloc(sizeof(list));
switch (choice){
case 1:
i++;
printf("Enter a reason to add to list PRO: ");
pros = (list*)realloc(pros, i*sizeof(list));
fgets(pros->reason[i], 50, stdin);
pros->reason[strcspn(pros->reason[i], "\n")] = 0;
break;
case 2:
j++;
cons = (list*)realloc(cons->reason, j*sizeof(list));
printf("Enter a reason to add to list CON: ");
fgets(cons->reason[j], 50, stdin);
cons->reason[strcspn(cons->reason[j], "\n")] = 0;
break;
case 3:
printf("PROS:\n");
printList(pros, i);
printf("CONS:\n");
printList(cons, j);
break;
case 4:
keepGoing = 1;
break;
default:
printf("Invalid value.");
keepGoing = 1;
}
}
free(pros);
free(cons);
getchar();
return 0;
}
void printList(list * reasons, int len1){
int i = 0;
for (i = 0; i < len1; i++){
printf("%s\n", reasons->reason[i]);
}
}
void printMenu(){
printf("Choose option:\n");
printf("1 - Add PRO reason\n");
printf("2 - Add CON reason\n");
printf("3 - Print reasons\n");
printf("4 - Exit\n");
}
3 回答
有很多问题 . 以前的评论和答案仍然适用 .
这是一个干净的解决方案 .
列表结构现在是自包含的,无需跟踪单独变量中的字符串数
添加了自包含
AddString
函数不再需要
malloc
正确释放所有已分配的内存
删除了一些逻辑错误(
keepGoing
的反转逻辑)仍有改进的余地 . 特别是没有错误检查内存分配功能 .
无需动态分配这些:
list * pros; list * cons;
. 像pros = (list*)realloc(pros, i*sizeof(list));
这样的代码没有任何意义 .相反,将它们声明为纯变量 .
list pros
.您需要动态分配的是成员
pros.reason
. 您需要分配它指向的指针数组,然后您需要分配各个数组 .你有问题
因为您要使用的内存无效 .
pros->reason
未指向有效内存,因此您无法取消引用它,这会导致undefined behavior .在索引到
pros->reason
之前,需要使pros->reason
指向有效的内存位置 .之后,如果希望将
pros->reason[i]
用作fgets()
的目标,则还需要使pros->reason[i]
指向有效内存 .除了这个问题之外,还有另一个问题使得这段代码无意义,即在循环的每次迭代中调用
malloc()
. 您只需要调用malloc()
一次,以获取由内存分配器函数分配的指针(到内存),然后在循环内使用realloc()
将其调整到所需的内存 .