帮忙看看这段c程序为何链表输出的不正确?
程序:
#include <stdio.h> #include <stdbool.h> #include<stdlib.h> struct tell{ char *num; int n; struct tell *next; }; struct tell *head = NULL; void cre_list(){ head = (struct tell *)malloc(sizeof(struct tell)); head->next = NULL; head->num = NULL; } void add_list(char *num,int n){ struct tell *pre = (struct tell *)malloc(sizeof(struct tell)); pre->num = num; pre->n = n; struct tell *p = head->next; head->next = pre; pre->next = p; } void pri_list(){ struct tell *p = head; for (; p->next != NULL; ) { p = p->next; printf("%s %dn",p->num,p->n); } } void dosomething(char *p){ char c[7]; int j=0,i = 0; for (i; i < 20; i++) { if (j>6) { break; } //printf("%Cn",p[i]); if (p[i]>='0' && p[i]<='9'){ c[j] = p[i]; // printf("%cn",c[j]); ++j; }else if (p[i]>='A' && p[i]<='Z') { c[j] = ((p[i]-65)/3)+48; ++j; } } add_list(c,1); } int main(void) { int count; char ch[20]; cre_list(); scanf("%d",&count); int i = 0; for(; i < count; i++){ getchar(); fgets(ch,20,stdin); dosomething(ch); } pri_list(); return 0; }
例如:
输入: 2 1234567 2345678
希望输出: 1234567 2345678
实际输出: 2345678 2345678
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
回复
多谢~以后多指教~
回复
你肯学,我就肯教,从来不强迫人。哈。
牢记鬼哥指点,不瞒鬼哥~不才顶多也就大一时间一年的c++学龄,而且还是再学校环境下~如今学习c其实是为了想参加acm大赛,现在看来c果然是够“低级”,以至于我这等做“高级”语言的头大啊~
菜鸟路过:昨天我也看了这个程序半天才看明白问题所在,最后看到上面一楼已经详细回答了就没有回答。今天看到上面的讨论想说两句。
堆与栈在程序执行的时候,函数malloc所分配的空间是在堆中,函数内部中直接定义的auto型变量应该是在栈中,每一个函数执行完了之后,关于这个函数在栈中分配的一个stack frame 区域就会被释放,这个区域存储的就是这个函数中使用的一些变量。而上面函数dosomething每次执行结束后, c[]这个数组的空间就会被释放。栈的性质都明白,所以执行下一个函数的时候这个区域很可能就会被下一个函数占用,然后里面的数据就......了。
总的来说全局变量,静态变量,malloc 这些的空间在堆中的量在函数间可调用(只要有地址),对其他函数栈中的变量的操作---只能是对前面层的函数的变量通过地址进行操作。
菜鸟路过,说得不对的地方还请指正。
咱不是这个圈里的。。。打酱油路过,不过近日有心再重新涉足下底层C、数据结构、算法等方面的知识,基础再打扎实些。
这段函数的关键问题所在一楼说的已经很清楚。就是指针指向空间的问题,代码中每次创建一个节点其num指向的都是一片不可靠的栈空间,栈空间当程序离开该函数后理论上是不可用的。
根据代码的流程应该是输出乱码,至于为什么输出两次相同的内容完全是应为PC在内存是使用上虽然说是随机的,但连续调用同一个函数时其使用的栈内存地址一般不会变。
内存非安全使用是C语言中常遇到的问题,有时也很难定位。且不同的内存问题其PC和单片机上造成的影响还不一样,要写出比较健壮的C代码需要对内存的知识有个比较好的理解。
@小吃店 @fcsong000833 @爪哇老妖
感谢指导,开始对c的内存不是很重视~所以觉得很诡异,但是经过几位的指点,貌似明白了出现这种情况的原因了。看来以后写c要格外小心,规范一点儿了~
不是抄书~不才学过一年c++,对c的精髓指针还不太理解,想借此机会补补c的知识,献丑了~
这代码写的,是不是楼主抄书的???哈。
出现这种现象的原因就出在18行的赋值上
#5 num为char*型,最好命名为 str
不才还是不太明白,为何会出现链表中节点数目正常,但是每个节点的值都是最后一次的结果这种情况,希望能给解释一下~Thanks !
回复
这是因为num为 char* 型,char*只是一个指针,它只指向字符串实际地址,并不保存字符串上的那些字符;而你的程序中2次传给它的都是main中char ch[20]的首地址。这两次的num所指的都是这个ch[20],而这个ch[20]的值被修改了
回复
再add_list()中传的是另一个char *c的首地址啊,c是一个函数中的局部变量,在第二次执行dosomething()时难道不是重新申请空间么?大哥的意思是,执行两次dosomething()中调用的add_list()传的参数c指向的是同一个地址,也就是说char *c没有被释放?
错误有两处,
1)35行 for (i; i < 20; i++)结束处应该给c[]加一个结束标志 ''
2)18行的字符指针不能直接赋值
建议改的地方一共5处,已加注释,代码如下: