我想查看链表的所有项目。
我创建了一个三项列表,当我使用下面的" 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;
}
答案 0 :(得分:1)
好吧,我在代码中看到了两个主要问题:
malloc()
返回的内存包含未指定的内容,并且您希望它具有有用的内容。然后是奇怪的事情:
total_items
作为指针传递。temp
作为参数传递?答案 1 :(得分:0)
在遍历列表时,您应该检查temp
的值,以确保它在尝试访问之前不是NULL
。至少,您应该使用以下内容:
for ( i = 0; i < *total_items && temp != NULL; i++ )
...
虽然迭代像
这样的列表更常见while ( temp != NULL ) // or just while ( temp )
{
...
temp = temp->next;
}
您对temp
的使用似乎很困惑;在您致电main
后,show_items
中是否有任何用途?如果没有,你应该将它作为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;如上所述,此代码不应尝试输出任何内容。如果您要发布您遇到问题的实际代码,或者如果它太大,请将其缩小为问题的代表性样本,这将使每个人的生活更轻松。
修改强>
咄。现在我看到了问题。您永远不会在next
结构中正确设置generic_item
项目。
因此,您有两个指针可以跟踪列表的头部和尾部,where_is_first_item
和where_is_last_item
。当您将第一个项目添加到列表中时,您创建generic_item
并设置您的头尾指针,通过各自的next
成员指向它,为您提供类似的内容(使用head
和tail
代替where_is_first_item
和where_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
指针值的有效性要困难得多。