我是C的新手,我试图编写一种递归搜索链表的方法,但是我没有成功。如果在链表的任何节点中找不到名称,则该函数包含返回0,并且找到1是。我似乎进入了无限循环。任何帮助将不胜感激!
#include<stdlib.h>
#include<string.h>
struct node
{
char name[1000];
struct node *next;
};
int contains(const struct node *pNode, const char *name)
{
int i;
int length = strlen(name);
int isEqual = 0;
while (pNode != NULL)
{
isEqual = 1;
for (i = 0; i < length; i++)
{
if (pNode->name[i] != name[i])
{
isEqual = 0;
}
}
}
contains(pNode->next, name);
return isEqual;
}
main()
{
struct node node1 = { "Sam", NULL };
struct node *node1Ptr = &node1;
struct node node2 = { "Anna", node1Ptr };
struct node *node2Ptr = &node2;
struct node node3 = { "Adam", node2Ptr };
struct node *node3Ptr = &node3;
int n, k;
// testing for a name that is the list
n = contains(node3Ptr, "Sam");
printf("%d\n", n);
// testing for a name that is not in the list
k = contains(node3Ptr, "Max");
printf("%d\n", k);
}
答案 0 :(得分:4)
您的功能可以简洁地写成:
#include <string.h>
...
int contains(const struct node *pNode, const char *name)
{
if(pNode == NULL)
return 0;
if(strcmp(pNode->name, name) == 0)
return 1;
return contains(pNode->next, name);
}
请注意,代码中对contains()
的递归调用的值永远不会被使用,因此不会给出任何有用的东西。它的调用在最后无条件地完成,这解释了无限循环。
编译启用所有(合理)警告(GCC和clang -Wall
),它应该告诉你许多boo-boos。作为一项个人政策,如果不是-Wall
干净,那么最好有充分的理由相信我是对的并且编译器过于热心。
您还可以简化数据结构的大部分设置,但这是另一次。
很高兴您根据需要使用const
进行装饰。
答案 1 :(得分:1)
int contains(const struct node *pNode, const char *name)
{
if (pNode == NULL) // Recursive base-case: If there is no Node,
{ // we are at the end of the list, and the name was never found.
return 0; // Therefore, return 0
}
// If this node matches the name, return 1.
// If this node does NOT match the name, check the next node.
return !strcmp(pNode->name, name)? 1 : contains(pNode->next, name);
}
如果你想要一个非常紧张的形式:
// Untested, but I think it works... or is at least close.
int contains(const struct node *pNode, const char *name)
{
return pNode? (!strcmp(pNode->name, name) || contains(pNode->next, name)) : pNode;
}
答案 2 :(得分:0)
您的无限循环是以下行的直接结果:
while (pNode != NULL)
因为永远不会改变 pNode
所指向的内容。基本上你反复检查Sam
......事实上,你甚至没有 来进行递归通话。
相反,你想要一个
if(pNode != NULL)
检查,如果没有,检查字符串。如果找到该字符串,则返回1,否则返回递归调用。
如果pNode==NULL
想要返回0。
答案 3 :(得分:0)
如果你到达列表的末尾,你不应该调用函数包含但是你无限地调用它。 在通话前添加此内容:
if (pNode ->next != null)
contains(pNode->next,name);
你还需要阻止它调用包含物品,如果你对物品这样做,那么你的情况就像:
if (pNode ->next != null && !isEqual)
contains(pNode->next,name);
答案 4 :(得分:0)
在 pnode NULL 之后的包含方法中,您再次调用导致无限循环的函数。
修改如下。
if(pnode== NULL) {
return 0;
}
答案 5 :(得分:0)
这是我修改代码的方法,现在它可以工作了。谢谢大家的帮助,我真的很感激,并且我对strcmp函数并不熟悉,但我会深入研究。再次,谢谢。
int contains(const struct node *pNode, const char *name){
int i;
int length = strlen(name);
int isEqual = 0;
if(pNode == NULL){
return isEqual;
}
isEqual = 1;
for (i = 0; i < length; i++)
{
if (pNode->name[i] != name[i])
{
isEqual = 0;
break;
}
}
return isEqual? isEqual : contains(pNode->next, name);
}