为什么这个C ++链表程序终止了?

时间:2013-03-12 06:07:52

标签: c++ linked-list

摘要报告

感谢所有有用的反馈。 cin.clear()非常好;关于将next设置为NULL的说法也是如此。但是最终的问题(在评论中被诊断出来)是我使用Ctrl+D来逃避,cin >> k没有正确处理这个问题。当我将k > 0添加到while条件(请参阅更新的代码)并使用负数进行转义时,这一切都开始有效。


我讨厌发布大量代码,但我认为我无法进一步修改它。关键是我的程序首次复飞,但不是第二次。 (跳到main看看我的意思。)

#include <iostream>
using namespace std;

struct ListNode {
  int data;
  ListNode* next;
};

void print_list(ListNode* node) {
  cout << node->data << endl;
  while ((node = node->next) != NULL) {
    cout << node->data << endl;
  }
}

ListNode* read_list() {
  ListNode *head, *tail;
  int k;

  head = NULL;
  while ((cin >> k) && k > 0) {
       if (head == NULL) {
          head = tail = new ListNode;
       } else {
          tail->next = new ListNode;
          tail = tail->next;
       }
       tail->data = k;
       tail->next = NULL;
  }
  return head;
}

int main() {
  ListNode *list1, *list2;

  list1 = read_list();
  print_list(list1);    // Works

  list2 = read_list();
  print_list(list2);    // Does not work!

  return 0;
}

然后是输出:

Press ENTER or type command to continue
1
3
5
7
List1
1
3
5
7
List2

Command terminated

在打印List2之前,您是否看到它如何终止? (前四行来自stdin。请参阅main。)这里出了什么问题?我不明白为什么第一次使用相同的逻辑,而不是第二次。

也许是因为我没有释放第一个链表的内存?

4 个答案:

答案 0 :(得分:3)

此代码存在多个问题。

  1. 您忘记在最后一个元素上将next设置为NULL。这将导致任何非空列表崩溃。

  2. 在再次阅读之前,您需要std::cin.clear()。 EOF标志是“粘性的”。

  3. print_list()函数不处理空列表。任何空列表都会崩溃。

  4. 这些问题中的任何一个都会导致程序终止或崩溃,因此您必须修复所有这些问题。请注意一个错误如何使程序在空列表中崩溃,而另一个错误导致非空列表崩溃 - 在这两个错误列表之间,程序崩溃所有列表。好吧,如果你很幸运,至少。如果你不走运,它可能不会崩溃。

    这是一个自动捕获错误#1和#3的工具列表:

    • GDB(运行gdb ./a.out而不是./a.out,请记得使用-g进行编译)
    • Mudflap(使用-fmudflap -lmudflap编译)
    • Valgrind(运行valgrind ./a.out而不是./a.out
    • Clang静态分析仪

    所以,你应该至少使用这四种工具中的一种。我喜欢在同一个项目中使用所有四个。

答案 1 :(得分:1)

你应该在第一个read_list()之后调用cin.clear()。  The reason can be found here

以下代码效果很好:

#include <iostream>                                                                                                                    
using namespace std;

struct ListNode {
  int data;
  ListNode* next;
};

void print_list(ListNode* node) {
  cout << node->data << endl;
  while ((node = node->next) != NULL) {
    cout << node->data << endl;
  }
}

ListNode* read_list() {
  ListNode *head, *tail;
  int k;

  head = NULL;
  while (cin >> k) {
       if (head == NULL) {
          head = tail = new ListNode;
       } else {
          tail->next = new ListNode;
          tail = tail->next;
       }
       tail->data = k;
       tail->next = NULL;
  }
  return head;
}

int main() {
  ListNode *list1, *list2;

  list1 = read_list();
  print_list(list1);
  cin.clear(); // ADD this line 

  list2 = read_list();
  print_list(list2);

  return 0;
}

问题是由第二个read_list()函数调用中的 cin 引起的。 第一个read_list(),print_list()运行良好。

但是,根据调试器,从 read_list()返回后没有创建 ListNode ,list2是 0x0 ,即 NULL ,导致第二个 print_list()分段错误。

第二个read_list返回NULL的原因是while循环没有运行。声明 cin&gt;&gt;的值k false

另外

以上答案错误。如果只是修改read_list函数,问题仍然存在,如下所示。

ListNode* read_list() {
  ListNode *head, *tail;
  int k;

  head = NULL;
  while (cin >> k) {
       if (head == NULL) {
          head = tail = new ListNode;
       } else {
          tail->next = new ListNode;
          tail = tail->next;
       }
       tail->data = k;
       tail->next = NULL;
  }
  return head;
}

答案 2 :(得分:0)

head = NULL;
while (cin >> k) {
   if (head == NULL) {
      head = tail = new ListNode;
   } else {

我希望你能看到问题所在。首先将头设置为null,然后检查它是否为null。

尝试这样的事情:

ListNode* readList(ListNode* head)
{
    int data;
    cin >> data;

    ListNode* nNode = new ListNode;
    nNode->data = data;
    nNode->next = 0;

    if (head == null)
    {
        head = nNode;
    }
    else
    {
        ListNode* tail = head;
        while (tail->next != 0)
        {
            tail = tail->next;
        }
        tail->next = nNode;
    }

    return head;
}

或类似的东西。自从我上次创建链表以来已经有一段时间了。

答案 3 :(得分:0)

修改列表的打印方式:

void print_list(ListNode* node)
{
    while (node)
    {
        cout << node->data << endl;
        node = node->next;
    }
}

在第二个cin之前重置read_list

cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');

程序崩溃将解决。