我正在尝试编写一个包含链表数组的简单字典,但在调用显示函数后我一直在丢失数据。
这是我的结构定义
typedef struct node{
int elem;
struct node *next;
}*L;
typedef L Dictionary[10];
这是我的展示
void display(Dictionary A)
{
int i;
for(i=0;i<10;i++){
printf("A[%d]: ",i);
while(A[i]!=NULL){
printf("%d\t",A[i]->elem);
A[i] = A[i]->next;
}
printf("\n");
}
}
解决方法是制作一个临时变量。
我试过
Dictionary tempStruct
for(i=0;i<10;i++){
tempStruct[i] = A[i];
}
它有效。但是有没有其他方法来分配比这个更有效的链表?
tempStruct = A;
无效,我得到incompatible types node** to Dictionary{*node[10]}
答案 0 :(得分:2)
您可以将显示功能中的循环更改为:
for(i=0;i<10;i++){
printf("A[%d]: ",i);
L tmp = A[i];
while(tmp!=NULL){
printf("%d\t",tmp->elem);
tmp = tmp->next;
}
printf("\n");
}
没有必要复制整个数组,导航链表的简单临时指针就足够了。
旁注:对于数组的副本,您尝试使用tempStruct = A;
分配。这有两个原因:
在您的函数中,A
没有数组类型。 C不支持将数组传递给函数。当函数具有带数组类型的参数时,它会自动调整为指针类型,而不是传递数组,而是传递指向数组第一个元素的指针。此效果通常表示为数组衰减为指针,它是您的消息incompatible types node** to Dictionary{*node[10]}
的原因。
即使A
具有数组类型,它仍然无法正常工作,因为C不允许分配数组。这有点令人惊讶,因为同样的事情适用于struct
。我不能想到为什么在C中不允许分配数组的原因,你应该记住你不能这样做。当然,你可以手动完成,如果你不想分配每个元素,你可以使用string.h
中声明的函数memcpy()
:
int foo[5];
int bar[5] = {1, 2, 3, 4, 5};
// instead of foo = bar;
memcpy(foo, bar, sizeof foo);
与您的问题无关,但我很难理解这段代码。您的typedef
对可读性来说是灾难性的。 永远不会隐藏typedef
后面的指针 - 为了理解处理指针的代码,重要的是指针明显。数组类型的typedef
至少也是有问题的。我建议使用以下代码:
typedef struct node {
int elem;
struct node *next;
} node;
// not strictly necessary, but IMHO, if you want to typedef a struct type,
// it's the least confusing option to name it the same as the struct tag.
#define DICTSIZE 10
void display(node **a) // variable names are often lowercase by convention
{
// to cope with ANY possible size, you need size_t, int might be too small
// include stddef.h or stdlib.h to use it. Of course, with 10 elements,
// int is enough.
for (size_t i = 0; i < DICTSIZE; ++i) {
printf("a[%zu]: ", i);
node *tmp = a[i];
// now it's obvious tmp is a pointer, so no need to explicitly
// write the != NULL ... (any pointer that's not NULL evaluates true)
while (tmp) {
printf("%d\t", tmp->elem);
tmp = tmp->next;
}
printf("\n");
}
}
还要注意一些添加的空格如何大大提高代码的可读性(因此,使用它们)。
我会认为您的原始显示功能已损坏,因为它修改了显示的内容。对于显示数据的函数,这不是预期的行为。如果要进一步改进代码,应使用const
明确表示函数不应修改它接收的内容,因此编译器可以捕获错误。在上面的示例中,display
的签名应该更像这样:
void display(const node *const *a)
第一个const
会使任何struct node
不可变,第二个const
(在星号之后)会使数组中的指针成为不可变的。有了这个,你还必须写
const node *tmp = a[i];
因为你不能将const指针指向非const指针。
答案 1 :(得分:0)
在显示功能中,使用A[i] = A[i]->next;
修改字典数组的条目,这样就会破坏数据结构并丢失数据。
您应该使用局部变量来枚举每个列表:
void display(Dictionary A) {
struct node *n;
int i;
for (i = 0; i < 10; i++) {
printf("A[%d]:", i);
for (n = A[i]; n; n = n->next) {
printf(" %d", n->elem);
}
printf("\n");
}
}
隐藏typedef后面的指针和数组是一个坏主意,它会导致读者和程序员的代码混乱。你应该typedef struct node node;
并使用显式指针和数组。