0

概略報告

有益なフィードバックをありがとう。cin.clear()とても役に立ちました。nextNULLに設定することについての発言もそうでした。しかし、最後の問題 (コメントで診断されたとおり) は、私がCtrl+Dエスケープに使用していて、cin >> kこれを正しく処理していなかったことです。while 条件 (更新されたコードを参照)に追加k > 0し、負の数でエスケープすると、すべてが機能し始めました。


大量のコードを投稿するのは嫌いですが、これ以上削除することはできないと思います。ポイントは、私のプログラムは最初のゴーアラウンドでは機能しますが、2 番目のゴーアラウンドでは機能しないということです。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か?(最初の 4 行は stdin からのものです。 を参照してくださいmain。) ここで何がうまくいかないのでしょうか? 同じロジックが最初に機能する理由がわかりませんが、2回目は機能しません。

おそらく、最初のリンクされたリストのメモリを解放していないためでしょうか?

4

4 に答える 4

3

このコードには複数の問題があります。

  1. 最後の要素にを設定nextするのを忘れました。NULLこれにより、空でないリストでクラッシュが発生します。

  2. std::cin.clear()再度読み取る前に必要です。EOF フラグは「スティッキー」です。

  3. このprint_list()関数は空のリストを処理しません。これは、空のリストに対してクラッシュします。

これらの問題のいずれかが原因で、プログラムが終了またはクラッシュするため、すべてを修正する必要があります。1 つのエラーが空のリストに対してプログラムをクラッシュさせ、別のエラーが空でないリストに対してクラッシュを引き起こすことに注意してください。この 2 つの間で、プログラムはすべてのリストに対してクラッシュします。運が良ければ、少なくとも。運が悪いとクラッシュしないかもしれません。

エラー #1 と #3 を自動的にキャッチするツールのリストを次に示します。

  • GDB (gdb ./a.outの代わりに実行し./a.out、 でコンパイルすることを忘れないでください-g)
  • マッドフラップ (でコンパイル-fmudflap -lmudflap)
  • Valgrind (valgrind ./a.out代わりに実行./a.out)
  • Clang 静的アナライザー

したがって、これら 4 つのツールのうち少なくとも 1 つを使用する必要があります。同じプロジェクトで 4 つすべてを使用するのが好きです。

于 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;
}

この問題は、2 番目の read_list() 関数呼び出しのcinが原因で発生します。最初の read_list()、print_list() はうまく機能します。

ただし、デバッガーによると、 read_list()から返された後にListNodeが作成されず、 list2が0x0、つまりNULLであり、2 番目のprint_list()セグメンテーション違反が発生します。

2 番目の 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
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;
}

または、このようなもの。最後にリンクリストを作成してからかなりの時間が経ちました。

于 2013-03-12T06:23:55.447 に答える
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 に答える