我已经编写了一些代码,用于在第34页的单个链接列表中插入节点。位置,但当我运行项目时,我收到一个分段错误:11
当n == to sizeM时,我调用push_back,它将进入最后插入节点。当n ==到0时,我调用push_font,它将在开始时输入插入节点。这两个函数都可以工作,因为我已经调用它们在我的主文件中检查。在我进行任何调用之前,我的列表包含
440 330 110
headM指向440,这是列表中的第0个位置。
然后我进行3次调用以插入
刀片(40.3)
插入件(10,0)
插入件(33,2)
现在的名单应为10 440 33 330 110 40
我不确定出了什么问题,但我确信在插入33时我会做点什么。
这是我的simpleList.h,包含类
#ifndef Lab9_Simple_List__SimpleList__
#define Lab9_Simple_List__SimpleList__
typedef int ListItem;
class SimpleList {
private:
class Node {
public:
ListItem item;
Node *next;
};
Node *headM;
int sizeM;
void destroy();
// Deallocate all nodes, and sets headM to zero.
void copy(const SimpleList& source);
// List becomes copy of source.
public:
SimpleList(): headM(0), sizeM(0) { /* Point one */}
// PROMISES: creates empty list.
SimpleList(const SimpleList& source) { copy(source); }// copy constructor
SimpleList& operator =(const SimpleList& rhs); // assignment operator
~SimpleList() { destroy(); } // destructor
int size() const {return sizeM;}
void push_back(const ListItem& item);
// PROMISES:
// Adds a node with an item to the end of the list, and increments sizeM
void push_front(const ListItem& item);
// PROMISES:
// Adds a node with an item to the beginning of the list, and increments
// sizeM
void pop_back(const ListItem& item);
// PROMISES:
// The last node int list is removed
const ListItem& at(int n)const;
// PROMISES:
// An item is return at the nth position in the list.
// if n is less than 0 or greater than or equal sizeM gives the error
// message: "Illegal Access" and terminates the program
ListItem& at(int n);
// PROMISES:
// An item is return at the nth position in the list.
// if n is less than 0 or greater than or equal sizeM gives the error
// message: "Illegal Access" and terminates the program
void insert(const ListItem& theItem, int n);
// PROMISES:
// A node with a copy of theItem is inserted at the nth position, and sizeM
// will be incremented if the operation of insert was successfull.
// if n == sizeM calles push_back
// if n == 0 calls push_front
// if n < 0 or n > sizeM returns and does nothing.
void remove(int n);
// PROMISES:
// Does nothing if n < 0 or n > sizeM-1. Otherwise, if list is not empty
// removes the node at the position n.
};
#endif /* defined(Lab9_Simple_List__SimpleList__) */
这是我的文件,其中包含成员定义,那些不工作的是插入函数
#include <iostream>
using namespace std;
#include <stdlib.h>
#include "SimpleList.h"
SimpleList& SimpleList::operator =(const SimpleList& rhs)
{
if (this != &rhs) {
destroy();
copy(rhs);
}
sizeM = rhs.sizeM;
return *this;
}
ListItem& SimpleList::at(int n)
{
if(n < 0 || n >= sizeM)
{
cout << "\n Illegal Access. Program Terminates...";
exit(1);
}
Node * p = headM;
for(int i= 0; i < n; i++)
p = p -> next;
// point four
return p -> item;
}
const ListItem& SimpleList::at(int n)const
{
if(n < 0 || n >= sizeM){
cout << "\n Illegal Access. Program Terminates...";
exit(1);
}
Node * p = headM;
for(int i= 0; i < n; i++)
p = p -> next;
// point three - when reached for the first time
return p -> item;
}
void SimpleList::push_back(const ListItem& item)
{
Node *new_node = new Node;
if(new_node == NULL)
{
cout << "\nNo memory available to create a node" << endl;
exit(1);
}
new_node->item = item;
if (headM == 0) {
new_node->next = headM;
headM = new_node;
}
else
{
Node* p = headM;
while (p ->next != NULL)
p = p ->next;
p -> next = new_node;
new_node -> next = NULL;
}
sizeM++;
// point five - when reached for the third time
}
void SimpleList::push_front(const ListItem& item)
{
Node *new_node = new Node;
new_node->item = item;
new_node->next = headM;
headM = new_node;
sizeM++;
// point two
}
void SimpleList::destroy()
{
// This function is not properly designed.
cout << "\nSimpleList::destroy was called but didn't do the right job.";
headM = 0;
}
void SimpleList::copy(const SimpleList& source)
{
// this function is incomplete and is not properly designed. It doesnt do
// its job, makeing 'this' SimpleList object a copy of the scoure.
// The only effect of the next line is to tell the compiler
// not to generate an "unused argument" warning. If you are going to complete
// this funciton, don't leave it in your solution.
(void) source;
cout << "\nSimpleList::copy was called but didn't do the right job."
<< "--program is terminated.\n";
exit(1);
}
void SimpleList::insert(const ListItem& theItem, int n)
{
if (n < 0 || n > sizeM)
return;
else if (n == sizeM)
push_back(theItem);
else if (n == 0)
push_front(theItem);
else
{
Node* new_node = new Node;
new_node->item = theItem;
Node* temp = headM;
for(int i = 0; i < (n - 1) ; i++)
{
temp = temp->next;
}
new_node->next = temp->next;
temp->next = new_node;
sizeM++;
}
}
void SimpleList::remove(int n)
{
if( n < 0 || n > sizeM ) {
return;
}
Node* p = headM;
if(n == 0 && headM != NULL)
{
Node* const p_doomed = headM;
headM = p_doomed->next;
delete p_doomed;
--sizeM;
}
else{
for(int c = 0; c < n - 1; c++ )
{
p = p->next;
}
Node* const p_doomed = p->next;
p->next = p_doomed->next;
delete p_doomed;
--sizeM;
}
}
以下是我的主要文件
#include <iostream>
#include <iomanip>
using namespace std;
#include "SimpleList.h"
#define EXERCISE_B
void print(const SimpleList& list);
// PROMISES: prints values in the list from first node (node number 0) to
// the last node.
int main()
{
SimpleList list;
cout << "\nList just after creation -- is empty.";
list.push_front(50);
cout << "\nAfter calling push_front. list must have: 50\n";
print(list);
list.push_back(440);
list.at(0) = 770;
cout << "\nAfter calling push_back and at functions, list must have: 770 440\n";
print(list);
list.push_back(330);
list.push_back(220);
list.push_back(110);
cout << "\nAfter three more calls to push_back, list must have:"
"770, 440, 330, 220, 110\n";
print(list);
#if defined (EXERCISE_B)
list.remove(0);
list.remove(2);
cout << "\nAfter removing two nodes. list must have: 440, 330, 110\n";
print(list);
list.insert(40, 3); //insert node with the value of 40 at the 4th position
list.insert(20, -1); // do nothing
list.insert(30, 30000); // do nothing
list.insert(10, 0); //insert node with the value of 10 at the 1st position
list.insert(33, 2); // insert node with the value 33 at the 3rd position
cout << "\nTwo more nodes inserted, must have: 10, 440, 33, 330, 110, 40\n";
print(list);
list.remove(0);
list.remove(1);
list.remove(2);
list.remove(3);
list.remove(4);
list.remove(5);
cout << "\nAfter 6 removes, list must have: 440, 330, 40: \n";
print(list);
#endif
return 0;
}
void print(const SimpleList& list)
{
for(int i = 0; i < list.size(); i++)
cout << list.at(i) << " ";
}
这是我收到的输出
Haydns-MacBook-Pro:desktop Haydn$ g++ lab9_EXE_A.cpp simpleList.cpp
Haydns-MacBook-Pro:desktop Haydn$ ./a.out
List just after creation -- is empty.
After calling push_front. list must have: 50
50
After calling push_back and at functions, list must have: 770 440
770 440
After three more calls to push_back, list must have:770, 440, 330, 220, 110
770 440 330 220 110
After removing two nodes. list must have: 440, 330, 110
440 330 110
Two more nodes inserted, must have: 10, 440, 33, 330, 110, 40
Segmentation fault: 11
答案 0 :(得分:1)
问题出在void SimpleList::remove(int n)
if (n < 0 || n >= sizeM) { // CHange to >= and not > !!!
说明:
如果调用此函数时n
为0
且列表已为空(表示sizeM==0
和headM==nullptr
),则使用原始核心{{ 1}}会是假的。
这意味着该功能将继续,执行流程为:
n<0 || n>sizeM
如果调用该函数的时候...
p=headM; // meaning that p is now nullptr
if (n == 0 && headM != NULL) // false because `n==0 && headM==nullptr`
// if block ignored
else{ // here: (n!=0 || headM==NULL)
for (int c = 0; c < n - 1; c++) // the condition is false
// the loop body is ignored
Node* const p_doomed = p->next; // ouch !!!! p is nullptr => segfault !!!
与您的n
main()
的{{1}}大小相当,那么情况类似。当remove(3)
已经p->next
时,您尝试访问p
一次太多。