简体   繁体   English

代码不打印链表C

[英]code not printing linked list C

I am writing C code to implement linked list.But while printing the contents of the list it prints the values taken for last node only.I have been debugging for long.Please help. 我正在编写C代码来实现链接列表,但是在打印列表内容时仅打印最后一个节点的值,我已经调试了很长时间了,请帮忙。

#include <stdio.h>
#include <malloc.h>

struct list {
    char *name;
    char *type;
    int occurance;
    struct list *prev;
    struct list *link;
};

struct list *start=NULL,*ptr,*newnode;

void main() {
    int choice = 0;
    char name1[10], type1[10];
    int occ;

    do {
        printf("Enter name:");
        scanf("%s", name1);
        printf("Enter type:");
        scanf("%s", type1);
        printf("Enter occurance:");
        scanf("%d", &occ);
        newnode = (struct list *)malloc(sizeof(struct list));
        newnode->link = NULL;
        newnode->prev = NULL;
        newnode->name = name1;
        newnode->type = type1;
        newnode->occurance = occ;
        if(newnode == NULL) {
            printf("Memory could not be allocated!");
            // exit(0);
        }
        if(start == NULL) {
            start = newnode;
            ptr = start;
            printf("start is: %s", start->name);
        }
        else if(start->link == NULL) {
            start->link = newnode;
            newnode->prev = start;
            ptr = newnode;
        }
        else {
            ptr->link = newnode;
            newnode->prev = ptr;
            ptr = ptr->link;
        }
        printf("Enter 1 to continue: ");
        scanf("%d", &choice);
    } while(choice == 1);

    // display
    ptr = start;
    while(ptr != NULL) {
        printf("%s ", ptr->name);
        printf("%s ", ptr->type);
        printf("%d \n", ptr->occurance);
        ptr = ptr->link;
    }
}

I have tried making start and newnode local variables as well but it doesn't work. 我也尝试过使start和newnode局部变量,但是它不起作用。

Your cannot use equal operator to assign a char * . 您不能使用equal运算符来分配char * Instead you must use function strcpy . 相反,您必须使用功能strcpy

Do not do this: 不要这样做:

newnode->name=name1;
newnode->type=type1;

But do this: 但是这样做:

strcpy(newnode->name, name1);
strcpy(newnode->type, type1);

Currently your whole char* are pointing to the same memory block. 当前,您的整个char*都指向同一内存块。

Edit: Since you are using pointers, you must allocate memory before copying value from one pointer to another (or you will encounter segfaults). 编辑:由于使用的是指针,因此必须在将值从一个指针复制到另一个指针之前分配内存(否则您将遇到段错误)。 So you also need to allocate your node's name and type memories with malloc : 因此,您还需要使用malloc分配节点的名称并键入malloc

//allocate memory of node's name attribute with the same amount as name1 (+1 for null terminating character)
newnode->name = malloc(sizeof(char) * (strlen(name1)+1));
newnode->type= malloc(sizeof(char) * (strlen(type1)+1));

There are several things to improve in your code so let's take it one by one. 您的代码有几处需要改进的地方,所以让我们一一介绍。 First, the behaviour you are seeing is because the structure members name and type of all nodes in your linked list point to the same memory location, ie, to name1 and type1 respectively. 首先,您看到的行为是因为链接列表中所有节点的结构成员nametype都指向相同的内存位置,即分别指向name1type1

struct list {
    char *name;
    char *type;
    // other members
};

Here, name is a pointer to a character and so is type . 这里, name是指向字符的指针, type In the do while loop in main , you read name and type of each node into the arrays name1 and type1 respectively in each iteration. maindo while循环中,您在每次迭代中分别将每个节点的名称和类型读入数组name1type1中。 Therefore, the previous values of name1 and type1 are overwritten and hence lost. 因此, name1type1的先前值将被覆盖并因此丢失。 Now you are assigning name1 and type1 to respective members of each newly created node. 现在,您要为每个新创建的节点的相应成员分配name1type1

// after allocating memory for a new node

newnode->name = name1;  // name1 evaluates to a pointer to name1[0]
newnode->type = type1;  // type1 evaluates to a pointer to type1[0]

Therefore name member of all nodes are pointing to name1 which only retains the last string read, and similarly type member of all nodes point to type1 which also has the last string read. 因此,所有节点的name成员都指向仅保留最近读取的字符串的name1 ,并且类似地,所有节点的type成员指向也具有最近读取的字符串的type1

Now that we have discussed the behaviour of your program, what's the solution? 既然我们已经讨论了您的程序的行为,那么解决方案是什么? You keep name and type of each node from getting overwritten by the next values entered. 您可以防止每个节点的名称和类型被输入的下一个值覆盖。 You do this by allocating memory for them every time you read them for a new node. 为此,可以在每次为新节点读取它们时为它们分配内存。

newnode->name = strdup(name1); // make a copy of name1 before it's overwritten
newnode->type = strdup(type1);  // make a copy of type1 before it's overwritten

strdup allocates enough memory to copy the string passed to it. strdup分配足够的内存来复制传递给它的字符串。 It essentially does the same thing as malloc and strcpy . 它本质上与mallocstrcpy做相同的事情。 Read more about it here . 在此处了解更多信息。

Now let's come to other things starting from the top of your program. 现在让我们从程序的顶部开始讨论其他事情。

  • malloc.h is deprecated and not standard. malloc.h已过时,不是标准的。 Use stdlib.h instead. 请改用stdlib.h More here . 这里更多。
  • The C standard lays down two signatures for the main function: int main(void); C标准为main函数设置了两个签名: int main(void); and the other is int main(int argc, char *argv[]); 另一个是int main(int argc, char *argv[]); More here . 这里更多。
  • While reading strings using scanf , you should guard against buffer overrun. 使用scanf读取字符串时,应防止缓冲区溢出。 If the user enters name and type which are longer than 9 characters, it will lead to undefined behaviour and even crash. 如果用户输入的名称和类型超过9个字符,将导致不确定的行为,甚至崩溃。 You should replace scanf("%s", name1) with scanf("%9s", name1) . 您应将scanf("%s", name1)替换为scanf("%9s", name1) The 9 in the format string means that scanf will read at most 9 non-whitespace characters. 格式字符串中的9表示scanf将最多读取9个非空白字符。 One character space is left for the terminating null byte which it adds automatically. 终止的空字节保留一个字符空间,它会自动添加。
  • Check the return value of malloc for NULL immediately after the call. 调用后立即检查malloc的返回值是否为NULL You program as such will simply crash if malloc fails to allocate memory. 这样,如果malloc未能分配内存,您的程序将很容易崩溃。
  • You don't need the else if block in your do while loop . do while loop ,您do while loop else if块。 It will never be entered except in the first iteration of the loop when it makes start->previous = start which is not what you want. 除非在循环的第一个迭代start->previous = start这不是您想要的),否则它将永远不会输入。 start->previous should always be NULL . start->previous应该始终为NULL

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

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