0

总结报告

感谢所有有用的反馈。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吗?(前四行来自标准输入。请参阅main。)这里出了什么问题?我不明白为什么相同的逻辑第一次会起作用,但第二次不会。

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

4

4 回答 4

3

此代码存在多个问题。

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

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

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

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

以下是可以自动捕获错误 #1 和 #3 的工具列表:

  • GDB(运行gdb ./a.out而不是./a.out,记得编译-g
  • 挡泥板(用 编译-fmudflap -lmudflap
  • Valgrind(运行valgrind ./a.out而不是./a.out
  • Clang 静态分析器

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

于 2013-03-12T06:10:52.013 回答
1

您应该在第一个 read_list() 之后调用 cin.clear() 。 原因可以在这里找到

以下代码运行良好:

#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 >> 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;
}
于 2013-03-12T06:24:15.730 回答
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');

程序崩溃会解决。

于 2013-03-12T06:27:19.713 回答
0
head = NULL;
while (cin >> k) {
   if (head == NULL) {
      head = tail = new ListNode;
   } else {

我希望你能看到问题。首先将 head 设置为 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;
}

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

于 2013-03-12T06:23:55.447 回答