C阵列链接列表,将数组链表分配给另一个

时间:2017-08-12 20:42:52

标签: c arrays linked-list variable-assignment

我正在尝试编写一个包含链表数组的简单字典,但在调用显示函数后我一直在丢失数据。

这是我的结构定义

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]}

2 个答案:

答案 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;并使用显式指针和数组。