Я работаю над назначением связанного списка для курса структуры данных. Вставка значений работает нормально, но при попытке распечатать программу вылетает, как только она попадает в вставленное значение. Поэтому, если я использую функцию добавления в инструкции switch в драйвере, попробуйте вставить значение между любым из них, функция отображения будет аварийно завершена, как только она выведет новое значение данных. Я уже давно работаю над этим, и, похоже, не могу обернуться вокруг него. Любые советы высоко ценится.
list.h
// List.h
#ifndef LIST
#define LIST
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
typedef string ElementType;
class List
{
private:
class Node
{
public:
ElementType data;
Node * next;
Node()
: data(ElementType()), next(NULL)
{ }
Node(ElementType initData)
: data(initData), next(NULL)
{ }
}; // end of Node class
typedef Node * NodePointer;
public:
List();
/* Construct a List object
Precondition: none.
Postcondition: An empty List object has been constructed.
*/
List(const List &source);
/* Construct a copy of a List object.
Precondition: None.
Postcondition: A copy of source has been constructed.
*/
~List();
/* Destroys a List object.
Precondition: None.
Postcondition: Any memory allocated to the List object has been freed.
*/
const List & operator=(const List &rightSide);
/* Assign a copy of a List object to the current object.
Precondition: none
Postcondition: A copy of rightside has been assigned to this
object. A constant reference to this list is returned.
*/
int getSize() const;
/* Returns the size of the list (number of items in the list)
Precondition: none
Postcondition: The return value is the number of items in the list.
*/
bool empty() const;
/* Check if this List is empty
Precondition: none
Postcondition: The return value is true if this List object is empty;
otherwise the return value is false.
*/
void insert(ElementType dataVal, int index);
/* Insert a value into this List at a given index
Precondition: The index is valid (0 <= index <= the list size).
The first position is index 0, the second position is index 1, etc.
Postcondition: dataval has been inserted into the list at the position
determined by index (provided there is room and index is a legal
position).
*/
void erase(int index);
/* Remove the value from this List at a given index.
Precondition: The list is not empty and index is valid
(0 <= index < the list size).
Postcondition: the element at position index has been
removed (provided index is a legal position).
*/
void display(ostream &out) const;
/* Display the contents of this List
Precondition: ostream out is open
Postcondition: the items in this List have been output to stream out
*/
int find(ElementType value) const;
/* Find the first occurrence of a value in this List
Preconditions: None
Postconditions: The return value is the index of the first List item
that matches value. The first list item has index 0, the second has
index 1, etc. The return value is -1 if value is not found in the list.
*/
private:
NodePointer first;
int mySize;
}; // end of List class
#endif
List.cpp
#include "List.h"
#include <cassert>
// Definition of List constructor
List::List()
: first(0), mySize(0)
{}
// Definition of List copy constructor
List::List(const List &source)
{
first = 0;
if (!source.empty())
{
first = new List::Node(source.first->data);
List::NodePointer lastPtr = first,
origPtr = source.first->next;
while (origPtr != 0)
{
lastPtr->next = new List::Node(origPtr->data);
lastPtr = lastPtr->next;
origPtr = origPtr->next;
}
}
}
// Definition of List destructor
List::~List()
{
List::NodePointer currPtr = first,
nextPtr;
while (currPtr != 0)
{
nextPtr = currPtr->next;
delete currPtr;
currPtr = nextPtr;
}
}
const List & List::operator=(const List &rightSide)
{
if (this != &rightSide) // lhs != rhs
{
this->~List();
if (rightSide.empty())
first = 0;
else
{
first = new List::Node(rightSide.first->data);
List::NodePointer lastPtr = first,
rhsPtr = rightSide.first->next;
while (rhsPtr != 0)
{
lastPtr->next = new List::Node(rhsPtr->data);
lastPtr = lastPtr->next;
rhsPtr = rhsPtr->next;
}
}
}
return *this;
}
// Definition of getSize
int List::getSize() const
{
return mySize;
}
// Definition of empty
bool List::empty() const
{
return (first == 0);
}
// Definition of insert
void List::insert(ElementType dataVal, int index)
{
assert(index >= 0 && index <= mySize);
List::NodePointer ptr = first;
List::NodePointer predPtr = 0;
for (int i = 0; i < index; i++)
{
predPtr = ptr;
ptr = ptr->next;
}
List::NodePointer newPtr = new Node(dataVal);
if (predPtr != 0)
{
newPtr->next = predPtr->next;
predPtr->next = newPtr;
}
else
{
newPtr->next = first;
first = newPtr; //reset first
}
delete ptr; //return pointer to heap
mySize++;
}
// Definition of erase
void List::erase(int index)
{
assert(!empty() && (index >= 0) && (index < mySize));
List::NodePointer ptr = first;
List::NodePointer predPtr = 0;
for (int i = 0; i < index; i++)
{
predPtr = ptr;
ptr = ptr->next;
}
if (predPtr != 0)
{
ptr = predPtr->next;
predPtr->next = ptr->next;
}
else
{
ptr = first;
first = ptr->next;
}
delete ptr; //return pointer to heap
mySize--;
}
// Definition of display
void List::display(ostream &out) const
{
List::NodePointer ptr = first;
while (ptr != 0)
{
out << ptr->data << endl;
ptr = ptr->next;
}
}
// Definition of find
int List::find(ElementType value) const
{
List::NodePointer ptr = first;
int i = 0;
while (ptr != 0)
{
if (ptr->data == value)
return i;
i++;
ptr = ptr->next;
}
return -1;
}
Aaaand водитель
#include <cctype> // Provides toupper
#include <iostream> // Provides cout and cin
#include <cstdlib> // Provides EXIT_SUCCESS
#include <ctime> // Provides seed for rand.
using namespace std;
#include "List.h"
// PROTOTYPES:
void print_menu();
// Postcondition: A menu of choices has been printed.
string get_string();
// Postcondition: The user has been prompted to enter an integer number. The
// number has been read, echoed to the screen, and returned by the function.
string generate_string();
int main()
{
List test; // A List to perform tests on
char choice; // Command entered by the user
srand((unsigned int) time(0));
cout << "I have initialized an empty list of strings." << endl;
do
{
print_menu();
cout << "Enter choice: ";
cin >> choice;
choice = toupper(choice);
ElementType value;
int position;
switch (choice)
{
case 'A':
cout << "Enter the amount of items to add: ";
cin >> position;
for (int i = 0; i < position; i++)
{
test.insert(generate_string(), test.getSize());
}
break;
case 'E': // Is Empty
cout << "Empty: " << boolalpha << test.empty() << endl;
break;
case 'F': // add code to find item in the list.
break;
case 'P': //Print
test.display(cout);
break;
case 'I': //Insert
cout << "Enter value: ";
cin >> value;
cout << endl << "Enter position: ";
cin >> position;
test.insert(value, position);
break;
case 'R': //Erase
cout << endl << "Enter position: ";
cin >> position;
test.erase(position);
break;
case 'Q': cout << "Test program ended." << endl;
break;
default: cout << choice << " is invalid." << endl;
}
} while ((choice != 'Q'));
return EXIT_SUCCESS;
}
void print_menu()
{
cout << endl;
cout << "The following choices are available: " << endl;
cout << " A Add a number of random strings to end of list" << endl;
cout << " E Print the result from the empty( ) function" << endl;
cout << " F Find and item in the list using find( )" << endl;
cout << " P Print a copy of the entire list" << endl;
cout << " I Insert a new string with the insert(...) function" << endl;
cout << " R Remove a string with the erase( ) function" << endl;
cout << " Q Quit this test program" << endl;
}
char get_user_command()
// Library facilities used: iostream
{
char command;
cout << "Enter choice: ";
cin >> command; // Input of characters skips blanks and newline character
return command;
}
string get_string()
// Library facilities used: iostream
{
string result;
cout << "Please enter an string for the list: ";
getline(cin, result);
cout << result << " has been read." << endl;
return result;
}
string generate_string()
{
const int STR_LENGTH = 5; // Length of random generated strings.
string randomString;
for (int i = 0; i < STR_LENGTH; i++)
randomString += (char)((rand() % 52) + 65);
return randomString;
}
Еще раз спасибо.
Посмотрите на метод вставки:
delete ptr; //return pointer to heap
Если вы вставляете узел, не нужно ничего удалять. Этот код
newPtr->next = predPtr->next;
присваивает newPtr->next
с ptr
, который после удаления ptr
указывает на освобожденную память.
Создайте диаграмму (поля и стрелки) о том, как происходит вся операция, шаг за шагом. Это должно показать, где ваш код сбивается с пути.