在C程序中打印链接列表

时间:2013-04-10 16:59:22

标签: c pointers linked-list printf

我看到其他一些关于如何打印链表的帖子,但没有一个对我有帮助,所以我决定发布我自己的代码。这是问题所在:

我可以添加一个名字和年龄完全正常,但第二个我添加另一个名称和年龄它覆盖前一个。

所以,如果我输入:

马特和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”可能没用。我一整天都在添加和删除代码。

4 个答案:

答案 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)

虽然您已经定义了headend指针,这些指针会生成链接列表,但您实际上并没有使用它们来存储新信息。创建新节点并将其存储在ptr变量中后,您实际上并未将其存储在列表中。

我建议添加另一个方法addnode,将新创建的节点添加到headend指针定义的链接列表中。

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

你必须不断更新每次添加,以便始终指向最后添加的元素...如果你关心。通常情况下,ptrstruct node *end = (struct node*) NULL; end指针是否会产生双重链接列表。

答案 3 :(得分:0)

  

我能够添加一个名字和年龄完全没问题,但第二个我   添加另一个名称和年龄,它会覆盖前一个名称。

您的代码不会覆盖前一个节点,它会将其替换为新节点并泄漏您之前的节点。 (泄漏是你已经分配的内存,然后丢失任何指针,因此你永远不能释放它。)这是创建一个新节点的行:

ptr = initnode(name, age);

如果ptr是指向列表中第一个节点的指针,则应将新节点添加到列表末尾,而不是将其分配给ptr