简体   繁体   English

在C程序中打印链接列表

[英]Printing a linked list in C program

I have see some other posts about how to print out a linked list, but none of them were helpful to me, so I decided to post my own code. 我看到一些关于如何打印链表的帖子,但是没有一个对我有帮助,所以我决定发布我自己的代码。 Here is the problem: 这是问题所在:

I am able to add in a name and age perfectly fine, but the second I add in another name and age it overwrites the previous one. 我可以添加一个名字和年龄完全正常,但第二个我添加另一个名称和年龄它覆盖了前一个。

So if i input: 所以,如果我输入:

Matt and 21, then charles and 34. It will only output charles and 34. How do I get it to output everything? 马特和21,然后查尔斯和34.它只会输出查尔斯和34.如何输出它输出一切? Thank you in advance for the help! 提前感谢您的帮助! :) :)

Here is my code: 这是我的代码:

#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

}

Oh and I know that some of the "#include's" might not be useful. 哦,我知道一些“#include”可能没用。 I've been adding and deleting code all day. 我一整天都在添加和删除代码。

Just a remamrk: 只是一个翻拍者:

ptr = (struct node*) calloc(3, sizeof(struct node));

is wrong because you are allocating 3 * sizeof(struct node) and it should be 是错误的,因为你正在分配3 * sizeof(struct node) ,它应该是

ptr = (struct node*) calloc(1, sizeof(struct node));

Your code is missing many things. 你的代码遗漏了很多东西。 you are not linking the node you create to any linked list. 您没有将您创建的节点链接到任何链接列表。 in the whole code you are not using next . 在整个代码中你没有使用next You have to work more on this code. 您必须在此代码上进行更多工作。

The problem is not only coming from the print of the linked list. 问题不仅来自链表的打印。 the problem come from how to create the linked list 问题来自如何创建链表

I can suggest to you a template of linked list which can help in developing such program. 我可以向你推荐一个链表的模板,它可以帮助你开发这样的程序。 this template contains functions and macro to treate linked list like 此模板包含用于处理链表的函数和宏

  • adding to linked list in the head 添加到头部的链表
  • adding to linked list in the tail 添加到尾部的链表
  • removing from linked list... 从链接列表中删除...

you can get the linked list template (list.h) from this link 您可以从此链接获取链接列表模板(list.h)

The following link contains an example of how use it 以下链接包含如何使用它的示例

Please refer to this paragraph in the above link 请参阅上面链接中的这一段

With very little modifications (removing hardware prefetching of list items) we can also use this list in our applications. 只需很少的修改(删除列表项的硬件预取),我们也可以在我们的应用程序中使用此列表。 A usable version of this file is available here for download. 此处提供此文件的可用版本供下载。

While you have defined head and end pointers, which would make a linked list, you are not actually using these to store your new information. 虽然您已经定义了可以创建链接列表的head指针和end指针,但实际上并没有使用它们来存储新信息。 After having created your new node and storing it in the ptr variable, you don't actually store it in the list. 创建新节点并将其存储在ptr变量中后,实际上并未将其存储在列表中。

I would suggest adding another method, addnode , which adds this newly-created node to the linked list defined by the head and end pointers. 我建议添加另一个方法addnode ,它将这个新创建的节点添加到由headend指针定义的链表中。

void addnode(struct node *ptr) {
    if (end == NULL) {
        head = ptr;
        end = ptr;
    }
    else {
        end = end->next = ptr;
    }
}

Broadly, we check if we have any items already in the list; 从广义上讲,我们检查列表中是否有任何项目; if not, both the start and the end of the list will be represented by the same node: the only one in the list! 如果没有,列表的开头和结尾都将由同一个节点表示:列表中唯一的一个节点! Otherwise, we let the node after the current end be the node to add, and then move our global end pointer to what is now the last node. 否则,我们让当前结束后的节点成为要添加的节点,然后将我们的全局end指针移动到现在的最后一个节点。

This allows us to maintain a chain of more than one node (entry in the list). 这允许我们维护一个以上节点的链(列表中的条目)。 We must then, when printing the entire list, follow this entire chain, from the first node ( head ) to the last. 然后,当打印整个列表时,我们必须遵循整个链,从第一个节点( head )到最后一个节点。 We can do this with a simple loop: instead of simply calling printnode() on the temporary ptr variable we maintain in main() , we write: 我们可以通过一个简单的循环来做到这一点:我们不是简单地在main()维护的临时ptr变量上调用printnode() main() ,而是编写:

struct node *current = head;
while (current != end) {
    printnode(current);
    current = current->next;
}

This line here: 这一行在这里:

ptr = initnode(name, age);

is why you're always overwriting the name/age, because you declared a local node called ptr and every time you add a value you overwrite that node with the next node. 这就是为什么你总是覆盖名称/年龄,因为你声明了一个名为ptr的本地节点,每次添加一个值时,你都会用下一个节点覆盖该节点。

See that struct node *next; 看到struct node *next; element in your node structure? 节点结构中的元素? You need to point that to the next node created in order to have more than 1 node, sort of like: 您需要指向创建的下一个节点,以便拥有多个节点,类似于:

ptr->next = initnode(name, age);

There's a special case of the first node when it comes to linked lists, your first node ptr is empty, so when your list is 0 in length, you need to set ptr from init_node() , the next time you need to set ptr 's next element, and then you need to update ptr so that it is the current node: 第一个节点有链接列表的特殊情况,你的第一个节点ptr是空的,所以当你的列表长度是0时,你需要从init_node()设置ptr ,下次你需要设置ptr ' next元素,然后你需要更新ptr,以便它是当前节点:

ptr = ptr->next;

Of course doing this causes you to "loose" the start for the list. 当然这样做会导致你“松散”列表的开头。 That's where your head comes in. When you start if you initialize head to ptr , then never move head, you'll always remember where the start of your list is. 这就是你的head进来的地方。当你开始初始化headptr ,然后从不移动头部时,你将始终记住列表的开头位置。

You also have a variable: 你还有一个变量:

struct node *end = (struct node*) NULL;

You'll have to keep updating that with every addition in order to always point to the last element added... if you care. 你必须不断更新每次添加,以便始终指向添加的最后一个元素...如果你关心。 Normally end or last or tail pointers are if you're going to make a double linked list. 如果你打算制作一个双链表,通常是endlasttail指针。

I am able to add in a name and age perfectly fine, but the second I add in another name and age it overwrites the previous one. 我可以添加一个名字和年龄完全正常,但第二个我添加另一个名称和年龄它覆盖了前一个。

Your code doesn't overwrite the previous node, it replaces it with a new node and leaks the one you had before. 您的代码不会覆盖前一个节点,它会将其替换为新节点并泄漏您之前的节点。 (A leak is a piece of memory that you've allocated and then lost any pointers to, so that you can never deallocate it.) Here's the line that creates a new node: (泄漏是你分配的一块内存,然后丢失任何指针,以便你永远不能解除分配。)这是创建一个新节点的行:

ptr = initnode(name, age);

If ptr is the pointer to the first node in the list, you should be adding the new node to the end of the list, not assigning it to ptr . 如果ptr是指向列表中第一个节点的指针,则应将新节点添加到列表的末尾,而不是将其分配给ptr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM