我正在为数据结构课程进行链表作业。插入值工作正常,但是当尝试打印出来时,程序一旦点击插入的值就会崩溃。因此,如果我在驱动程序的 switch 语句中使用 add 功能,然后尝试在其中任何一个之间插入一个值,则显示函数将在输出新数据值后立即崩溃。我已经在这个上工作了一段时间,只是似乎无法理解它。任何建议将不胜感激。
列表.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
列表.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;
}
啊和司机
#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
后指向已释放的内存。
逐步制作整个操作的图表(框和箭头(。这应该显示您的代码误入歧途的地方。