代码不打印链表C.

时间:2014-02-19 16:11:55

标签: c data-structures linked-list

我正在编写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;
    }
}

我已经尝试过启动和newnode局部变量,但它不起作用。

2 个答案:

答案 0 :(得分:1)

您不能使用相等的运算符来分配char *。相反,您必须使用函数strcpy

不要这样做:

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

但是这样做:

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

目前,您的整个char*指向同一个内存块。

修改 由于您正在使用指针,因此必须在将值从一个指针复制到另一个指针之前分配内存(或者您将遇到段错误)。因此,您还需要使用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));

答案 1 :(得分:0)

您的代码有几点需要改进,所以让我们逐一介绍。首先,您看到的行为是因为链接列表中所有节点的结构成员nametype指向相同的内存位置,即name1和{{1} } 分别。

type1

此处,struct list { char *name; char *type; // other members }; 是指向字符的指针,因此name。在type中的do while循环中,您在每次迭代中分别将每个节点的名称和类型读入数组mainname1。因此,type1name1的先前值会被覆盖,从而丢失。现在,您要为每个新创建的节点的相应成员分配type1name1

type1

因此,所有节点的// 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] 成员都指向name,它只保留最后一个字符串读取,并且所有节点的类似name1成员都指向type最后一个字符串读。

既然我们已经讨论了你的程序的行为,那么解决方案是什么?您保持每个节点的名称和类型不会被输入的下一个值覆盖。每次为新节点读取内存时,都可以为它们分配内存。

type1

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 分配足够的内存来复制传递给它的字符串。它基本上与strdupmalloc完全相同。阅读更多相关信息here

现在让我们从程序的顶部开始讨论其他事情。

  • strcpy已弃用,不是标准版。请改用malloc.h。更多here
  • C标准规定了stdlib.h函数的两个签名:main,另一个是int main(void);更多here
  • 使用int main(int argc, char *argv[]);读取字符串时,应防止缓冲区溢出。如果用户输入的名称和类型超过9个字符,则会导致未定义的行为甚至崩溃。您应该将scanf替换为scanf("%s", name1)。格式字符串中的scanf("%9s", name1)表示9最多可读取9个非空白字符。一个字符空间留给它自动添加的终止空字节。
  • 在通话结束后立即检查scanf的{​​{1}}的返回值。如果malloc无法分配内存,那么您的程序就会崩溃。
  • NULL中不需要malloc阻止。它永远不会被输入,除非在循环的第一次迭代中它使else if不是你想要的。 do while loop应始终为start->previous = start