C 中的链表(显然 malloc 不想成为我的朋友)
我很高兴自己昨晚就能让它正常工作,而且在我第一次尝试时也没有出现任何错误或警告!但是,当然,我换了一堆填充物,然后把它搞砸了...... 当我尝试使用 gdb 时,this.ytxt 中的列表似乎加载到内存中效果很好。我觉得问题出在写法上。现在。它再次工作,但只写入文件的第一行。我注释掉了整个函数并打印了测试标记,但仍然无法弄清楚。 这个想法是从文件中读取可变数量的行并将它们成对打印。 (实际上 它本来就像学习抽认卡,但我从来没有抽出时间来完成那部分)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct member{ //This emulates a dictionary
char key[20]; //and links each word+definition pair to the next pair.
char def[20];
struct member *ptr;
};
struct member *root;
struct member *curr;
FILE *f;
int fill_list(){ //Fill each member struct with next two lines of
curr=root;
char this[20]; //FILE *f
while(EOF){
if(!fgets(this,20,f)) break;
strcpy(curr->key,this);
if(!fgets(this,20,f)) break;
strcpy(curr->def,this);
curr=curr->ptr;
curr=malloc(sizeof(struct member));
curr->ptr=0;
}
return 0;
}
void free_all(){
curr=NULL;
while(curr!=root){
curr=root;
while(curr->ptr)curr=curr->ptr;
free(curr);
}
}
int terminate(int i){ //The terminate function closes file and
free_all(); //frees malloc'd memory, then returns main func's
fclose(f); //return value.
return i;
}
int main(){
f=fopen("this.txt","r");
if(!f)return -1;
root=malloc(sizeof(struct member));
root->ptr=NULL;
fill_list();
curr=root;
if ( curr != 0 ) {
while ( curr != 0 ) {
printf( "%s", curr->key );
curr = curr->ptr;
}
}
free_all();
return terminate(0);
}
I was so pleased with myself getting this to work last night without any errors or warnings on my first try too! But, of course, I changed a bunch of stuffed and screwed it up...
When I tried to gdb it, the list from this.ytxt seemed load to memory just fine. I think the problem was writing it. Now. it works again but only writes the first line of the file. I commented out whole functions and printf'd test marks and still couldn't figure it out.
the idea is to read a variable number of lines from a file and print them in pairs. (Actually
it was meant to be like study flashcards but I never got around to that part)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct member{ //This emulates a dictionary
char key[20]; //and links each word+definition pair to the next pair.
char def[20];
struct member *ptr;
};
struct member *root;
struct member *curr;
FILE *f;
int fill_list(){ //Fill each member struct with next two lines of
curr=root;
char this[20]; //FILE *f
while(EOF){
if(!fgets(this,20,f)) break;
strcpy(curr->key,this);
if(!fgets(this,20,f)) break;
strcpy(curr->def,this);
curr=curr->ptr;
curr=malloc(sizeof(struct member));
curr->ptr=0;
}
return 0;
}
void free_all(){
curr=NULL;
while(curr!=root){
curr=root;
while(curr->ptr)curr=curr->ptr;
free(curr);
}
}
int terminate(int i){ //The terminate function closes file and
free_all(); //frees malloc'd memory, then returns main func's
fclose(f); //return value.
return i;
}
int main(){
f=fopen("this.txt","r");
if(!f)return -1;
root=malloc(sizeof(struct member));
root->ptr=NULL;
fill_list();
curr=root;
if ( curr != 0 ) {
while ( curr != 0 ) {
printf( "%s", curr->key );
curr = curr->ptr;
}
}
free_all();
return terminate(0);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
详细说明乍得的答案,您可以:
编辑:我想我只是补充一点,如果我要对您的代码进行轻微修改,这就是我要做的。如果我从头开始,我就不会以这种方式构建循环,也不会拥有像 curr 这样不必要的全局变量。 sarnold 提出的观点也是如此,即您只有一个临时缓冲区。更不用说您在列表中的最后一个条目可能无效;仅在成功将两个字符串读入两个临时缓冲区之后才分配列表中的下一个成员条目可能是一个更好的主意。
Elaborating on Chad's answer, you could have:
EDIT: thought I'd just add that if I was going to make slight modifications to your code this is what I'd do. If I were to do it from scratch I wouldn't structure the loop that way or have unnecessary global variables like curr. Same goes for the point made by sarnold where you only have a single temporary buffer. Not to mention that your last entry in the list could be invalid; it might be a better idea to allocate the next member entry in the list only after you successfully read the two strings into two temporary buffers.
一些可能的错误:
没有名为“this”的变量。 “this”是C++保留字。 (如果您以 C 语言进行编译,则可能没问题)
您的 free_all() 函数看起来很可疑。我看了几眼才弄清楚发生了什么事。看起来您正在尝试通过遍历到尾部、释放最后一个节点并再次从根顶部开始来释放链表。与以线性方式释放相比,这将具有 n 平方性能。我想你想说的是:
Some possible bugs:
Do not have variables named "this". "this" is C++ reserved word. (Probably ok if you are compiling as C)
Your free_all() function looks suspicious. It took me a few glances to figure out what was going on. It looks like you are trying to free the linked list by traversing to the tail, deallocating the last node, and starting back from the top of the root again. This will have n-squared performance compared to freeing in a linear fashion. I think you want to say this:
您的
while(EOF)
循环永远不会在此处终止 -EOF
在stdio.h
中定义为(-1):
在自己的程序中重新定义
EOF
是不明智的。如果您确实想要无限循环,请使用 while(1) 或 for(;;) 之一;这两个都是非常明显的无限循环,并且都是无限循环的常见 C 习惯用法。更好的方法是将循环的退出条件重写到 while() 中,但有时这很困难。 (
do { /* foo */ } while ()
有时是完美的解决方案,在这里可能更好。)我不确定你到底应该做什么来修复你的
while( )
循环条件,因为我不完全确定它应该做什么:您不妨直接读入
curr->key
和curr-> ;def
。 (如果您希望即使在出现错误时也能保持对象的一致性,那么读入临时存储是有意义的,但是您需要两个个临时变量,并在两个<之后更新值/em> IO 命令。由您决定。)在这一小部分中,您用下一个节点的值覆盖
curr
指针。然后分配一个新节点并再次覆盖 curr 指针。然后将新分配的对象中的 curr->ptr 指针清空。curr
对象现在具有未初始化的curr->key
和curr->def
字符数组。这是故意的吗? (允许半初始化的对象存在于程序中通常会导致灾难。)Your
while(EOF)
loop will never terminate here --EOF
is defined instdio.h
to(-1)
:It would be unwise to redefine
EOF
in your own program.If you really want an infinite loop, please use one of
while(1)
orfor(;;)
; Both of these are very obviously infinite loops, and both of these are common C idioms for infinite loops. Better would be re-writing your loop's exit condition into thewhile()
, but sometimes that is difficult. (do { /* foo */ } while ()
is sometimes the perfect solution, and is probably better here.)I'm not sure what exactly you should do to fix your
while()
loop condition, because I'm not entirely sure what it is supposed to be doing:You might as well be reading directly into
curr->key
andcurr->def
. (Reading into temporary storage makes sense if you want to keep your objects consistent even in the face of errors, but you'd need two temporary variables for that, and update the values after both IO commands. Up to you.)In this small piece, you over-write the
curr
pointer with the value of the next node. Then you allocate a new node and over-write thecurr
pointer again. Then you null out thecurr->ptr
pointer in the newly allocated object. Thecurr
object now has uninitializedcurr->key
andcurr->def
character arrays. Is this intentional? (Allowing half-initialized objects to live in your program is usually a recipe for disaster.)在
fill_list()
中,您错误地分配了对象。In
fill_list()
you incorrectly allocating objects.