[英]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));
您的代码有几处需要改进的地方,所以让我们一一介绍。 首先,您看到的行为是因为链接列表中所有节点的结构成员name
和type
都指向相同的内存位置,即分别指向name1
和type1
。
struct list {
char *name;
char *type;
// other members
};
这里, name
是指向字符的指针, type
。 在main
的do while
循环中,您在每次迭代中分别将每个节点的名称和类型读入数组name1
和type1
中。 因此, name1
和type1
的先前值将被覆盖并因此丢失。 现在,您要为每个新创建的节点的相应成员分配name1
和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
strdup
分配足够的内存来复制传递给它的字符串。 它本质上与malloc
和strcpy
做相同的事情。 在此处了解更多信息。
现在让我们从程序的顶部开始讨论其他事情。
malloc.h
已过时,不是标准的。 请改用stdlib.h
。 这里更多。 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.