Ошибка сегментации C ++ в условном выражении связанного списка парсинга while для упорядоченной вставки - PullRequest
0 голосов
/ 22 февраля 2012

Это назначение класса для упорядоченной вставки в отсортированный связанный список.Я избегал доступа к нулевым указателям и добавил несколько строк отладочной информации, чтобы сузить ошибку сегмента до условного оператора самого цикла while.

Я могу добавить узел в пустой список и добавить узлы с меньшими ключами в начало списка, но я сталкиваюсь с ошибкой сегмента при добавлении ключа в конец непустого списка.Как показывают выходные данные отладки, проблемный цикл while успешно циклически повторяется, пока не увидит курсор-> следующий == NULL.Вот когда он выбрасывает ошибку сегмента.Я не пытаюсь получить доступ к пустому указателю, насколько я могу судить.Я очень тупой и буду признателен за любую помощь.Спасибо!

Я обозначил проблемную строку в коде ниже.

// Headers
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

struct Node {
  int id;
  string initials;
  double score;
  Node* next;
};
const int ESC = -9999;
const int ID_LIMIT = 1000000000;

int main(){  
  // initialize variables
  int temp_id = 0;  // temporary input
  Node* Start=NULL; // first node in linked list

  // get input until escape value is entered or input stream fails
  while ( temp_id != ESC && !cin.fail() ){
    cout << "\nPlease enter the student id, or "
         << ESC << " to finish inputing: ";
    cin >> temp_id;
    if ( temp_id >=0 && temp_id < ID_LIMIT ) { 
      // if valid input, continue input & create node
      string temp_inits;
      double temp_score;
      cout << "Please enter the student initials: " ;
      cin >> temp_inits;
      cout << "Please enter the student's test score: " ;
      cin >> temp_score;

      // create new node with input values
      Node* temp = new Node;
      temp->id = temp_id;
      temp->initials = temp_inits;
      temp->score = temp_score;
      temp->next = NULL;

      // TASK 4: SORTED INPUT
      if ( Start == NULL ) {  // if first node to be input
        Start = temp;         // point the first pointer to it
      }else{                  // otherwise
        if( temp->id < Start->id ){  // if new node should go before Start,
          temp->next = Start;        // move start after temp
          Start = temp;              // and reassign Start
        }else{
          Node* cursor = Start; // parse list for proper place or end
          cout << "\nDEBUG: while ( cursor-id:" << cursor->id ;
          cout << " < temp-id:" << temp->id;
          cout << " && cursor-next:" << cursor->next << " != NULL )";
// I THINK THE NEXT LINE IS THE CULPRIT
          while ( cursor->id < temp->id && cursor->next != NULL ) {
            cout << "\nDEBUG: { old cursor:" << cursor->id ;
            cursor = cursor->next;
            cout << ", new cursor:" << cursor->id << " }";
            cout << "\nDEBUG: while ( cursor-id:" << cursor->id ;
            cout << " < temp-id:" << temp->id;
            cout << " && cursor-next:" << cursor->next << " != NULL )";
          }
          cout << "\nDEBUG: insert temp-id:" << temp->id 
               << " after cursor-id:" << cursor->id ;
          temp->next = cursor->next;
          cursor->next = temp;  // inject new node into list.
          cursor = temp->next;
          cout << " before id " << cursor->id;
        }
      }
      cout << "Node with id=" << temp->id << ", initials=" << temp->initials 
           << ", and test score=" << temp->score << " added to the list.\n";

    }else{ // if invalid input & not escape value, print error
      if ( temp_id != ESC ) cout << "!!! Invalid input !!!\n";
    }   
  }

  return 0;
}

Вывод:

Please enter the student id, or -9999 to finish inputing: 654
Please enter the student initials: abc
Please enter the student's test score: 99.9
Node with id=654, initials=abc, and test score=99.9 added to the list.

Please enter the student id, or -9999 to finish inputing: 312
Please enter the student initials: qwe
Please enter the student's test score: 54.8
Node with id=312, initials=qwe, and test score=54.8 added to the list.

Please enter the student id, or -9999 to finish inputing: 987
Please enter the student initials: rty
Please enter the student's test score: 87.5

DEBUG: while ( cursor-id:312 < temp-id:987 && cursor-next:0x1c26040 != NULL )
DEBUG: { old cursor:312, new cursor:654 }
DEBUG: while ( cursor-id:654 < temp-id:987 && cursor-next:0 != NULL )
Segmentation fault

Я также пробовал цикл с ( ... cursor->next != 0 )и ( ... cursor->next )

Ответы [ 2 ]

1 голос
/ 22 февраля 2012
  while ( cursor->id < temp->id && cursor->next != NULL )
  {
      cursor = cursor->next;
  }

  temp->next = cursor->next;
  cursor->next = temp;  // inject new node into list.
  cursor = temp->next;
  cout << " before id " << cursor->id;

Когда цикл работает до тех пор, пока cursor не покажет последний узел, тогда cursor->next будет нулевым.После вставки нового узла (мне кажется, что он находится не в том месте, но не важно), новый узел является последним и имеет temp->next в качестве нулевого указателя.Затем cursor = temp->next устанавливает cursor в null, а следующий оператор вывода отладки, разыменовывая cursor через cursor->id, вылетает.

Конечно, я должен запустить его в отладчике.

И это одно сильное предложение, которое я имею для вас: используйте отладчик, а не только мозги.: -)

Второе сильное предложение: используйте абстракцию, назовите имя всего, что видно .Что означает определение небольших функций, например, для вставки списка.Тогда гораздо проще анализировать вещи.

0 голосов
/ 22 февраля 2012

Проблема в том, что после выхода из цикла while ():

  1>    temp->next = cursor->next;
  2>    cursor->next = temp;  // inject new node into list.
  3>    cursor = temp->next;
  4>    cout << " before id " << cursor->id;

Вы достигаете вышеуказанных строк с помощью курсора-> следующий == ноль (конец списка), и temp-> next также является нулевым. Строка 1 поэтому ничего не делает в этом случае. Строка 2 копирует временный адрес в курсор-> далее. На данный момент мы имеем:

temp: исходный адрес temp, temp-> next == NULL курсор: исходный адрес курсора, курсор-> следующий == исходный адрес временного секретаря

Затем вы копируете temp-> next в курсор (ухо!), Но temp-> next равно нулю, поэтому курсор теперь равен нулю. Поэтому, когда вы переходите к выполнению строки 4 и получаете курсор-> идентификатор, он пытается прочитать «null-> идентификатор» и вылетает.

...