我声明了一个用C实现的链表如下:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
然后我将列表头部全局声明为:
nodeList list; // head of the list - does not contain relevant data
最后,我有一个函数id(char * s)
,其中只有一个字符串s
作为参数。
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
问题是,当我运行这个程序并调用foo("somestring")
时,程序执行error: not found
部分并中止执行,尽管字符串somestring
在列表中。
我尝试通过插入一些printf()
来执行相同的程序以进行调试,并且它完美地工作,除了它输出附加字符和输出。
每次添加一些打印行时都会发生这种情况,例如:如果我取消注释我在上面的例子中写的两个printf()
(其中一个或两个,我得到相同的成功结果)。如果在没有参数或空字符串""
的情况下调用printf,它就不起作用。
我无法弄清楚发生了什么,我仔细检查了列表创建和填充函数,我完全确定它们正常工作。我尝试更改while
休息条件,但这也不起作用。我在Linux(使用gcc)和Windows(使用CodeBlocks编辑器的集成编译器)上观察到类似的行为
printf指令如何影响程序呢?
编辑:此代码是Yacc编写的语法分析器的一部分。整个代码可以在下面找到。这是一个很长的阅读,并没有完成,但上面的代码已经过测试并用于解释。
答案 0 :(得分:0)
查看提供的源代码时,探索链表的算法有两种方法可以在while循环比较中错过节点。
方式1 - 仅从列表的第二个节点开始。
在比较之前放置node = node->next;
会强制第一次比较为&(list)->next
而不是&(list)
。
要从第一个节点开始,只需将
node = node->next;
放在后面 比较。
方式2 - 永远不会以列表的最后一个节点结束。
在while条件下使用(node->next != NULL)
将强制退出循环,然后再比较最后一个节点=> node->next = NULL;
。
要以最后一个节点结束,只需将while条件更改为
(node != NULL)
。
<强>解决方案:强>
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
答案 1 :(得分:0)
实际错误是函数返回的变量的错误类型声明:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
函数返回值为nodeType*
,p被实例化为nodeList*
。
这两种类型的声明非常简单,这就是程序可以运作的原因。
可以找到工作代码here。
printf()
的奇怪行为可能是由printf参数所需的堆空间引起的:由于此函数接受任意数量的参数,因此将它们保存在列表中。这个列表在堆中实例化,从那里错误的createPoint
实现中覆盖旧数据。