C中的单链表输出不正确
所以我正在做一些链表修改,我试着加载一个带有数字的列表,然后打印出来。下面是我的代码:C中的单链表输出不正确,c,linked-list,output,C,Linked List,Output,所以我正在做一些链表修改,我试着加载一个带有数字的列表,然后打印出来。下面是我的代码: #include <stdio.h> #include <stdlib.h> typedef struct stack { int data; struct stack *next; }*stack; stack create_s(void){ stack s = (void*)malloc(sizeof(stack)); s->next = NULL
#include <stdio.h>
#include <stdlib.h>
typedef struct stack {
int data;
struct stack *next;
}*stack;
stack create_s(void){
stack s = (void*)malloc(sizeof(stack));
s->next = NULL;
return s;
}
void push_s(stack s, int data) {
while (s->next != NULL) {
s = s->next;
}
s->next = (void*)malloc(sizeof(stack));
s=s->next;
s->data = data;
s->next = NULL;
}
void print_s(stack s) {
if (s==NULL) {
return;
}
else {
while (s->next != NULL) {
printf("%d\n",s->data);
s=s->next;
}
}
}
int main (void) {
stack s = create_s();
push_s(s,2);
push_s(s,4);
push_s(s,6);
push_s(s,8);
print_s(s);
return 0;
}
应该是什么时候
2
4
6
8
它是否在开始时打印我的结构的地址?还有,为什么它不打印我的最后一个元素
谢谢代码包含几个错误,但首先引人注目的是,您的内存分配显然已经中断
stack s = (void*)malloc(sizeof(stack));
您将stack
定义为指针类型。这意味着sizeof(stack)
的计算结果为指针大小,而上面的malloc
分配了足够的空间来存储单个指针,而不足以存储整个struct stack
对象。push\s
中也存在相同的内存分配错误
这里有一些建议
堆栈定义为
typedef struct stack{
int data;
struct stack *next;
} stack;
并在需要指针的地方使用stack*
。也就是说,使*
可见,而不是将其“隐藏”在typedef名称中。这将使您的代码更易于阅读
malloc
的结果。无论如何,当它已经是void*
时,将它强制转换为void*
有什么意义呢sizeof
,除非你真的必须这样做。喜欢将sizeof
与表达式一起使用。学习使用下列malloc
习惯用法
T *p = malloc(sizeof *p);
或者,在你的情况下
struct stack *s = malloc(sizeof *s);
这将分配适当大小的内存块数据值)。在代码中,您从未初始化该头部节点中的数据值。然而,在print_s
函数中,您试图从head节点打印数据
值。难怪您将垃圾(-1853045587
)作为输出的第一行。不要打印第一个节点。跳过它,如果它真的是一个哨兵
此外,print_s
中的循环终止条件看起来很奇怪
while (s->next != NULL)
为什么要检查s->next
中的NULL
而不是检查s
本身?此条件将提前终止循环,而不会尝试打印列表中最后一个节点。这就是为什么在输出中看不到最后一个元素(8
)的原因。代码包含几个错误,但首先引人注目的是,内存分配显然已经中断
stack s = (void*)malloc(sizeof(stack));
您将stack
定义为指针类型。这意味着sizeof(stack)
的计算结果为指针大小,而上面的malloc
分配了足够的空间来存储单个指针,而不足以存储整个struct stack
对象。push\s
中也存在相同的内存分配错误
这里有一些建议
不要在typedef名称后面隐藏指针类型。将您的堆栈定义为
typedef struct stack{
int data;
struct stack *next;
} stack;
并在需要指针的地方使用stack*
。也就是说,使*
可见,而不是将其“隐藏”在typedef名称中。这将使您的代码更易于阅读
不要强制转换malloc
的结果。无论如何,当它已经是void*
时,将它强制转换为void*
有什么意义呢
不要在类型中使用sizeof
,除非你真的必须这样做。喜欢将sizeof
与表达式一起使用。学习使用下列malloc
习惯用法
T *p = malloc(sizeof *p);
或者,在你的情况下
struct stack *s = malloc(sizeof *s);
这将分配适当大小的内存块
此外,正如@WhozCraig在评论中所指出的,列表中的第一个节点显然应该作为“哨兵”头节点(具有未定义的数据值)。在代码中,您从未初始化该头部节点中的数据值。然而,在print_s
函数中,您试图从head节点打印数据
值。难怪您将垃圾(-1853045587
)作为输出的第一行。不要打印第一个节点。跳过它,如果它真的是一个哨兵
此外,print_s
中的循环终止条件看起来很奇怪
while (s->next != NULL)
为什么要检查s->next
中的NULL
而不是检查s
本身?此条件将提前终止循环,而不会尝试打印列表中最后一个节点。这就是您在输出中看不到最后一个元素(8
)的原因。可以通过更改以下内容来修复给定输出的实际原因:
s=s->next;
s->data = data;
到
给定输出的实际原因可以通过更改以下内容来修复:
s=s->next;
s->data = data;
到
我很好奇为什么将节点命名为堆栈!:我很好奇为什么要将节点命名为堆栈!:pOne另一个问题:create_s
使用未初始化的data
成员创建节点。@WhozCraig:是的,你是对的。我没有立即意识到,push_s
会迭代到列表的末尾。我有点“假设”它增加了列表的开头。不知道这个答案的否决票是从哪里来的,这里的一切都是明确正确的(+1,顺便说一句)@user3558437是一个传统的实现。如果你不知道,这不是一堆。如果有什么事的话,那就是排队。谢谢你们的帮助。我对这一切都不熟悉,只是在尝试。我采纳了你的建议。另一个问题是:create\u s
使用未初始化的data
成员创建节点。@WhozCraig:是的,你是对的。我没有立即意识到,push_s
会迭代到列表的末尾。我有点“假设”它增加了列表的开头。对这个答案的否决票来自何方也没有任何线索。这里的一切都很清楚