所以我正在做一些链表修订,我试图只是加载一些数字列表,然后打印出来。下面是我的代码:
#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("%dn",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;
}
然而,我的输出是:
-1853045587
2
4
6
而不是
2
4
6
8
它在开始打印我的结构的地址吗?另外,为什么它不打印我的最后一个元素?
谢谢
代码包含几个错误,但首先引起注意的是您的内存分配已经明显损坏
stack s = (void*)malloc(sizeof(stack));
您将stack
定义为指针类型。这意味着sizeof(stack)
计算指针大小,上面的malloc
分配足够的空间来存储单个指针,不足以存储整个struct stack
对象。同样的内存分配错误也出现在push_s
中。
这里有一些建议
不要在typedef名称后面隐藏指针类型。将
stack
定义为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在评论中指出的那样,列表中的第一个节点显然应该作为"哨兵"头节点(未定义data
值)。在您的代码中,您从未初始化该头节点中的data
值。然而,在print_s
函数中,您尝试从头节点打印data
值。难怪输出的第一行是垃圾(-1853045587
)。不要打印第一个节点。如果它真的是用来做哨兵的,就跳过它。
而且,print_s
中的循环终止条件看起来很奇怪
while (s->next != NULL)
为什么你检查s->next
为NULL
而不是检查s
本身?此条件将提前终止循环,而不会尝试打印列表中的最后一个节点。这就是在输出中看不到最后一个元素(8
)的原因。
给定输出的实际原因可以通过以下更改来修复:
s=s->next;
s->data = data;
s->data = data;
s=s->next;