我看到其他一些关于如何打印链表的帖子,但没有一个对我有帮助,所以我决定发布我自己的代码。这是问题所在:
我可以添加一个名字和年龄完全正常,但第二个我添加另一个名称和年龄它覆盖前一个。
所以,如果我输入:
马特和21,然后查尔斯和34.它只输出查尔斯和34。 如何让它输出一切? 提前感谢您的帮助! :)
这是我的代码:
#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
#define pause system ("pause")
// prototype variables
struct node * initnode(char*, int);
void printnode(struct node*);
struct node{
char name[20];
int age;
struct node *next;
};
struct node *head = (struct node*) NULL;
struct node *end = (struct node*) NULL;
struct node* initnode(char *name, int age){
struct node *ptr;
ptr = (struct node*) calloc(3, sizeof(struct node));
if(ptr == NULL)
return (struct node*) NULL;
else {
strcpy(ptr->name, name);
ptr->age = age;
return ptr;
}
}
void printnode(struct node *ptr) {
printf("Name -> %s\n", ptr->name);
printf("Age -> %d\n", ptr->age);
}
main() {
char name[20];
int age, choice = 1;
struct node *ptr;
while(choice != 3){
system("cls");
printf("1. Add a name\n");
printf("2. List nodes\n");
printf("3. Exit");
printf("\nEnter Menu Selection: ");
scanf("%d", &choice);
switch(choice) {
case 1: printf("\nEnter a name: ");
scanf("%s", name);
printf("Enter age: ");
scanf("%d", &age);
ptr = initnode(name, age);
break;
case 2: if(ptr == NULL) {
printf("Name %s not found\n", name);
} else
printnode(ptr);
pause;
break;
case 3: exit(3);
default: printf("Invalid Entry");
}// end of switch
}// end of main
}
哦,我知道一些“#include”可能没用。我一整天都在添加和删除代码。
答案 0 :(得分:1)
只是一个翻拍者:
ptr = (struct node*) calloc(3, sizeof(struct node));
是错误的,因为您正在分配3 * sizeof(struct node)
,它应该是
ptr = (struct node*) calloc(1, sizeof(struct node));
您的代码遗漏了很多东西。您没有将您创建的节点链接到任何链接列表。在整个代码中,您没有使用next
。您必须在此代码上进行更多工作。
问题不仅来自链表的打印。问题来自如何创建链表
我可以向你推荐一个链表的模板,它可以帮助你开发这样的程序。此模板包含用于处理链接列表的函数和宏,如
您可以从此link
获取链接列表模板(list.h)以下link包含如何使用它的示例
请参阅以上链接中的该段
只需很少的修改(删除列表的硬件预取) items)我们也可以在我们的应用程序中使用此列表。一个可用的版本 这个文件可以在这里下载。
答案 1 :(得分:1)
虽然您已经定义了head
和end
指针,这些指针会生成链接列表,但您实际上并没有使用它们来存储新信息。创建新节点并将其存储在ptr
变量中后,您实际上并未将其存储在列表中。
我建议添加另一个方法addnode
,将新创建的节点添加到head
和end
指针定义的链接列表中。
void addnode(struct node *ptr) {
if (end == NULL) {
head = ptr;
end = ptr;
}
else {
end = end->next = ptr;
}
}
从广义上讲,我们检查列表中是否有任何项目;如果没有,列表的开头和结尾都将由同一个节点表示:列表中唯一的一个节点!否则,我们让当前结束后的节点成为要添加的节点,然后将我们的全局end
指针移动到现在的最后一个节点。
这允许我们维护一个以上节点的链(列表中的条目)。然后,在打印整个列表时,我们必须遵循从第一个节点(head
)到最后一个节点的整个链。我们可以通过一个简单的循环执行此操作:不是简单地在我们在printnode()
中维护的临时ptr
变量上调用main()
,我们写道:
struct node *current = head;
while (current != end) {
printnode(current);
current = current->next;
}
答案 2 :(得分:0)
这一行:
ptr = initnode(name, age);
是你总是覆盖名称/年龄的原因,因为你声明了一个名为ptr
的本地节点,并且每次添加一个值时都会用下一个节点覆盖该节点。
在节点结构中查看struct node *next;
元素?您需要将其指向为创建多个节点而创建的下一个节点,类似于:
ptr->next = initnode(name, age);
第一个节点的特殊情况是链接列表,第一个节点ptr
为空,所以当你的列表长度为0时,你需要设置ptr
来自{{ 1}},下次需要设置init_node()
的{{1}}元素,然后需要更新ptr以使其成为当前节点:
ptr
当然这样做会导致你“松开”列表的开头。这就是你的next
进来的地方。如果你将ptr = ptr->next;
初始化为head
,那么从不动摇,你将始终记住列表的开头位置。
您还有一个变量:
head
你必须不断更新每次添加,以便始终指向最后添加的元素...如果你关心。通常情况下,ptr
或struct node *end = (struct node*) NULL;
或end
指针是否会产生双重链接列表。
答案 3 :(得分:0)
我能够添加一个名字和年龄完全没问题,但第二个我 添加另一个名称和年龄,它会覆盖前一个名称。
您的代码不会覆盖前一个节点,它会将其替换为新节点并泄漏您之前的节点。 (泄漏是你已经分配的内存,然后丢失任何指针,因此你永远不能释放它。)这是创建一个新节点的行:
ptr = initnode(name, age);
如果ptr
是指向列表中第一个节点的指针,则应将新节点添加到列表末尾,而不是将其分配给ptr
。