【问题标题】:Segfault when recursively searching a linked list in c++在 C++ 中递归搜索链表时的段错误
【发布时间】:2020-04-11 20:54:42
【问题描述】:

我的一个作业的一部分要求我递归搜索列表以查看其中是否包含双精度数。它打印一个关于它是否在列表中的字符串,但是在它完成循环后它崩溃并说存在分段错误。以下是使用递归方法的代码的隔离部分。

class Header
{
protected:
 //Create the struct for the list
 struct ListNode {
   double x;
   ListNode *next;
   ListNode(double v1, ListNode *n1 = nullptr) {
     double x = v1;
     next = n1;}
 };
 ListNode *head;

public:
 Header()
 {head = nullptr;}

 //Add doubles to the list
 void add(double var) {
  if(head == nullptr)
  {head = new ListNode(var);}

  else {
    ListNode *nodePtr = head;

    while(nodePtr->next != nullptr)
    {nodePtr = nodePtr->next;}

    nodePtr->next = new ListNode(var);
  }
 }

 //Call the function that performs the recursive function
 void recursiveMember(double var) const 
 {recursiveMember(head, var);}

private:
 //This is where the issue is
 void recursiveMember(ListNode *aList, double var) {
   if(aList == nullptr)
   {cout << var << " is not in the list" << endl;}

   if(var != aList->x)
   {recursiveMember(aList->next, var);}

   else
   {cout << var << " is in the list" << endl;}
 }
};

int main()
{
  //Create the object
  Header vars;

  //Populate the object
  vars.add(1.1);
  vars.add(2.2);
  vars.add(3.3);

  //Call the recursive function
  vars.recursiveMember(1.1);
  vars.recursiveMember(.5);

  return 0;
}

程序显示

1.1 is in the list
.5 is not in the list
Segmentation fault (core dumped)

这不一定是个问题,但是我需要在之后执行一些其他功能,并且段错误会导致程序在执行之前崩溃。

我使用gdb 调试器来隔离导致错误的代码,即 if(var != aList-&gt;x) 实现递归功能。

我缺少关于递归的东西吗?

【问题讨论】:

  • double x = v1 初始化一个名为 x 的局部变量。也名为 x 的数据成员保持未初始化状态。您的所有列表节点都包含垃圾值。

标签: c++ recursion linked-list


【解决方案1】:

如果aListnullptr,则需要从recursiveMember 函数返回。否则你访问的是无效节点。

if(aList == nullptr)
{
  cout << var << " is not in the list" << endl;
  return;
}

等效地,您可以有条件地进入第二个if 分支

if(aList == nullptr)
{
  cout << var << " is not in the list" << endl;
}
else if(var != aList->x)
// ...

另外,在您的 ListNode 构造函数中,您没有正确分配数据

ListNode(double v1, ListNode *n1 = nullptr) {
     double x = v1;   // this x is a local variable
     next = n1;
}

相反,您需要分配给member x

ListNode(double v1, ListNode *n1 = nullptr) {
     x = v1;   // this x is the member
     next = n1;
}

【讨论】:

    【解决方案2】:

    对于初学者,您不能从常量成员函数调用非常量成员函数。所以函数应该至少声明为

    void recursiveMember(ListNode *aList, double var) const;
    

    其次,私有成员函数接受指向头节点si的指针作为参数,它应该被声明为静态成员函数

    static void recursiveMember(ListNode *aList, double var);
    

    第三,private 和 public 函数都不能输出任何消息。它是函数的调用者决定是否输出任何东西。该函数应返回一个布尔值。

    所以第一个函数应该这样声明

    bool recursiveMember( double var ) const 
    {
        return recursiveMember( head, var);
    }
    

    第二个函数应该声明为

    static bool recursiveMember( const ListNode *aList, double var);
    

    此外,如果指针 aList 的当前值等于 nullptr,但您仍试图在第二个 if 语句中使用它来访问内存

    if(var != aList->x)
    {recursiveMember(aList->next, var);}
    

    即当aList 等于nullptr 时,函数没有返回。

    if(aList == nullptr)
    {cout << var << " is not in the list" << endl;}
    

    函数的定义方式如下

    static bool recursiveMember( const ListNode *aList, double var ) 
    {
        if ( aList == nullptr )
        {
            return false;
        }
        else if ( a:ist->var != var )
        {
            return recursiveMember( aList->next, var );
        }
        else
        {
            return true;
        }
    }
    

    在main中你应该检查被调用函数的返回值并输出相应的消息。

    注意在构造函数中你使用的是局部变量 x 而不是数据成员 x

       ListNode(double v1, ListNode *n1 = nullptr) {
         double x = v1;
         next = n1;}
    

    应该有

       ListNode(double v1, ListNode *n1 = nullptr) {
         x = v1;
         next = n1;}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-07
      • 2021-07-23
      • 2017-11-23
      • 2015-06-14
      • 1970-01-01
      • 1970-01-01
      • 2022-08-02
      • 1970-01-01
      相关资源
      最近更新 更多