【问题标题】:View item of linked list查看链表项
【发布时间】:2014-08-18 19:29:14
【问题描述】:

我想查看一个链表的所有项目。

我创建了一个三项列表,当我使用下面的“show_items”函数时,它只显示第一个元素,其他项目无法显示,因为编译器给出了分段错误错误。

#include <stdio.h>
#include <stdlib.h>

struct list{
    int age;
    struct list *next;
};

void create_item(int *total_items, struct list *where_is_first_item, struct list *where_is_last_item)
{
struct list *generic_item;
generic_item = malloc(sizeof(struct list));
printf("\nage of item %d: ", (*total_items)+1);
scanf("%d", &generic_item->age);

if(*total_items == 0){

    where_is_first_item->next=generic_item;
    where_is_last_item->next=generic_item;
    printf("\nitem created\n");
}
else{

    where_is_last_item->next=generic_item;
    printf("\nitem created\n");
}

void show_items(int *total_items, struct list *where_is_first_item, struct list *temp){
    temp=where_is_first_item->next;
    int i;
    for(i=0;i<*total_items;i++){
        printf("age of element %d: %d\n", i+1, temp->age);
        temp=temp->next;
    }
}

int main (void){
    int total_items=0;
    struct list *where_is_first_item;
    where_is_first_item=malloc(sizeof(struct list));        
    struct list *temp;
    temp=malloc(sizeof(struct list));
    printf("\n\n\tCREATE A NEW ITEM\n");
    create_item(&total_items, where_is_first_item, where_is_last_item);
    total_items++;
    show_items(&total_items, where_is_first_item, temp);
    return 0;
}

【问题讨论】:

  • 你似乎没有初始化你的值。
  • 你还没有初始化generic_item-&gt;next

标签: c list linked-list


【解决方案1】:

嗯,我看到您向我们展示的代码中有两个主要问题:

  1. 我没有看到像您在问题陈述中声称的那样创建了三个成员。
  2. malloc() 返回的内存有未指定的内容,您希望它有有用的内容。

然后是奇怪的事情:

  1. 如果你从未修改过total_items,为什么还要将它作为指针传递。
  2. 如果您立即忽略传入的值,为什么还要将 temp 作为参数传递?

【讨论】:

    【解决方案2】:

    在遍历您的列表时,您应该检查temp 的值以确保它不是NULL,然后再尝试访问它。至少,您应该使用以下内容:

    for ( i = 0; i < *total_items && temp != NULL; i++ )
     ...
    

    虽然更常见的是遍历列表,例如

    while ( temp != NULL ) // or just while ( temp )
    {
      ...
      temp = temp->next;
    }
    

    您对temp 的用法似乎很混乱;在您调用show_items 之后,它在main 中是否有任何用途?如果没有,您应该将其设为 show_items 的本地地址,而不是将其作为参数传递:

    void show_items(int *total_items, struct list *where_is_first_item)
    {
      struct list *temp = where_is_first_item->next;
      ...
    }
    

    在您发布的代码中,total_items 被初始化为 0;如所写,此代码不应尝试输出任何内容。如果您发布您遇到问题的实际代码,或者如果它太大,则将其减少为问题的代表性示例,这将使每个人的生活更轻松。

    编辑

    呃。现在我看到了问题。您永远不会在 generic_item 结构中正确设置 next 项目。

    因此,您有两个指针来跟踪列表的头部和尾部,where_is_first_itemwhere_is_last_item。当您将第一项添加到列表中时,您创建 generic_item 并设置您的头和尾指针通过它们各自的 next 成员指向它,给您这样的东西(使用 headtail 而不是where_is_first_itemwhere_is_last_item 为简洁起见):

    head           generic_item   tail
    +--+--+        +--+--+        +--+--+
    |  | -+------->|  | -+-???    |  | -+---+
    +--+--+        +--+--+        +--+--+   |
                   ^                        |
                   |                        |
                   +------------------------+
    

    到目前为止一切顺利。但是,当您添加第二个项目时,您只会更新列表尾指针;您没有创建从第一项到第二项的显式链接,因此您最终会得到以下内容:

    head                          generic_item    tail
    +--+--+        +--+--+        +--+--+         +--+--+
    |  | -+------->|  | -+-???    |  | -+-???     |  | -+--+
    +--+--+        +--+--+        +--+--+         +--+--+  |
                                  ^                        |                         
                                  |                        |
                                  +------------------------+
    

    希望您能看到问题所在。第一个列表元素中的next 指针从未初始化,因此它包含一个与有效地址不对应的不确定值。

    向列表追加新元素时需要额外的步骤:

    struct list *pre = where_is_last_item->next;
    pre->next = generic_item;
    where_is_last_item->next = generic_item;
    

    这将为您提供以下内容:

    head           pre            generic_item    tail
    +--+--+        +--+--+        +--+--+         +--+--+
    |  | -+------->|  | -+------->|  | -+-???     |  | -+--+
    +--+--+        +--+--+        +--+--+         +--+--+  |
                                  ^                        |                         
                                  |                        |
                                  +------------------------+
    

    通常,您应该始终将next 成员初始化为NULL,而不是让它不确定。很容易针对NULL 进行测试;确定非NULL 指针值的有效性要困难得多。

    【讨论】:

    • 让我们试着解决这个问题。我没有使用 NULL,因为它只是一个测试,所以我只在创建三个项目后才执行“show_items”函数。稍后在最终版本中,我将使用您的解决方法。我应该将 temp 作为局部变量放在 show_items 函数中,但我再次放入 main 只是为了测试以避免错误,我错了。问题依旧,为什么要显示多个链表时会出现分段错误?
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多