调试c中的一个链表数组



我的项目遇到了一个问题,起初我制作了一个链表,它工作正常,但后来我不得不编辑它,使其成为一个链表数组,但它只是以错误的方式存储,我想,这是我的代码,它出了什么问题?

#include <stdio.h>
#include <stdlib.h>
struct node
{
int coeff;
int power;
struct node* Next;
};

void Insert(int X,int Y, struct node* L, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}

void PrintList(struct node* L)
{
struct node* P = L;
printf("%d %d ",P->coeff,P->power);
printf("n");
P=P->Next;
}

int main()
{
struct node* head[3] ;
for(int q =0 ; q!= 3 ; q++)
{
head[q] = malloc(sizeof(struct node));
}

Insert(1,2,head[0],&head[0]);
Insert(2,3,head[0],&head[0]);
Insert(1,2,head[1],&head[1]);
Insert(2,2,head[1],&head[1]);


for(int i=0 ;i!=3;i++){

PrintList(head[i]);
}

return 0;
}

在LinkedList中只有一个头。您已经分配了3个不同的头,并且正在尝试向这些头添加节点。因此,下面的答案假设您打算有3个不同的LinkedLists,每个列表的头都在一个数组中。

此行中来自malloc()的内存

head[q] = malloc(sizeof(struct node));

未初始化。在这里,使用calloc()显得更加谨慎。所以,

head[q] = calloc(sizeof(struct node), 1); //Initialize everything to 0

接下来,Insert()中的一个参数是多余的,并且也不符合调用代码。它是的标志

void Insert(int ,int , struct node* , struct node*)

但是你用调用它

void Insert(int ,int , struct node* , struct node**)

我想,在这种情况下,删除最后一个参数应该是可以的,因为您不是在修改传入的struct node*指针,而是在修改其内容。如果您将struct node*更改为指向Insert()函数中的其他内容(例如P = temp;等(,那么传入struct node**将更有意义。因此,将您的代码更改为

void Insert(int X,int Y, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}

以及的调用代码

Insert(2,3,head[0]);
Insert(1,2,head[0]);
Insert(1,2,head[1]);
Insert(2,2,head[1]);

接下来,将PrintList更改为实际遍历LinkedList:

void PrintList(struct node* L)
{
struct node* P = L;
while(P) {
printf("%d %dn",P->coeff,P->power);
P=P->Next;
}
}

除此之外,我只是添加了一些日志记录,以更好地澄清正在打印的LinkedList。

for(int i=0 ;i!=3;i++){
printf("Printing list %d:n", i);
PrintList(head[i]);
printf("*****n");
}

这给出了输出:

Printing list 0:
0 0
1 2
2 3
*****
Printing list 1:
0 0
2 2
1 2
*****
Printing list 2:
0 0
*****

显然,LinkedLists的所有head都是0初始化的,因此显示为0 0。根据程序的期望,它们可以被初始化为合适的,也可以完全从PrintList()函数中删除。

在处理C项目时,应始终启用编译器警告。如果你这样做,编译器将发出类似的警告

warning: passing argument 4 of ‘Insert’ from incompatible pointer type [-Wincompatible-pointer-types]

这只是代码中的第一个问题。在主函数中分配的节点中也有未初始化的字段。

与其有一个修改列表的函数,不如定义一个向列表添加新节点并返回新列表的函数。下面是另一种方法,它还使用方便的宏函数来分配内存和计算数组的长度。该代码还将指针隐藏在类型定义后面,并定义一个释放列表的函数。

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) ((int) (sizeof (array) / sizeof (array)[0]))
#define NEW_ARRAY(pointer, length) 
{ 
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); 
if ((pointer) == NULL) { 
fprintf(stderr, "Allocating memory with malloc failed: %sn", strerror(errno)); 
exit(EXIT_FAILURE); 
} 
}
#define NEW(pointer) NEW_ARRAY((pointer), 1)
typedef struct node *List;
struct node {
int coeff;
int power;
struct node *next;
};

List NewList(int coeff, int power, List next)
{
List node;
NEW(node);
node->coeff = coeff;
node->power = power;
node->next = next;
return node;
}

void FreeList(List list)
{
if (list != NULL) {
FreeList(list->next);
free(list);
}
}

void PrintList(List list)
{
while (list != NULL) {
printf("%d %dn", list->coeff, list->power);
list = list->next;
}
}

int main(void)
{
List head[3] ;
head[0] = NewList(1, 2, NewList(2, 3, NULL));
head[1] = NewList(1, 2, NewList(2, 2, NULL));
head[2] = NULL;
for (int i = 0; i < LEN(head); i++) {
PrintList(head[i]);
FreeList(head[i]);
}
return 0;
}

最新更新