繁体   English   中英

代码不打印链表C

[英]code not printing linked list C

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

我也尝试过使start和newnode局部变量,但是它不起作用。

您不能使用equal运算符来分配char * 相反,您必须使用功能strcpy

不要这样做:

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

但是这样做:

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

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

编辑:由于使用的是指针,因此必须在将值从一个指针复制到另一个指针之前分配内存(否则您将遇到段错误)。 因此,您还需要使用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));

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

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

这里, name是指向字符的指针, type maindo while循环中,您在每次迭代中分别将每个节点的名称和类型读入数组name1type1中。 因此, name1type1的先前值将被覆盖并因此丢失。 现在,您要为每个新创建的节点的相应成员分配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]

因此,所有节点的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

strdup分配足够的内存来复制传递给它的字符串。 它本质上与mallocstrcpy做相同的事情。 在此处了解更多信息。

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

  • malloc.h已过时,不是标准的。 请改用stdlib.h 这里更多。
  • C标准为main函数设置了两个签名: int main(void); 另一个是int main(int argc, char *argv[]); 这里更多。
  • 使用scanf读取字符串时,应防止缓冲区溢出。 如果用户输入的名称和类型超过9个字符,将导致不确定的行为,甚至崩溃。 您应将scanf("%s", name1)替换为scanf("%9s", name1) 格式字符串中的9表示scanf将最多读取9个非空白字符。 终止的空字节保留一个字符空间,它会自动添加。
  • 调用后立即检查malloc的返回值是否为NULL 这样,如果malloc未能分配内存,您的程序将很容易崩溃。
  • do while loop ,您do while loop else if块。 除非在循环的第一个迭代start->previous = start这不是您想要的),否则它将永远不会输入。 start->previous应该始终为NULL

暂无
暂无

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

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