EXC_BAD_ACCESS堆栈/列表 C++



我正在研究我的RPN计算器项目。 此时我想将输入计算中的所有数字放在堆栈上,但不幸的是该过程以退出代码 11 结束,我卡住了。当我输入例如 3,然后输入 3+3 时,它就会发生。 我调试了它,我可以看到问题出在以下行中:

if(header!= nullptr) {

在这里:

cell* List::Last() {
if(header!= nullptr) {
cell *i;
for(i = header; i->next != nullptr; i = i->next);
return i;
}
else return nullptr;
}

例外EXC_BAD_ACCESS。我想这与我在列表中的标题有关,但我不知道为什么。我已经阅读了有关此异常的信息,但它仍然对我没有帮助。据我所知,大多数人都是通过数组来获得的。我将非常感谢任何提示...我的完整代码在这里(它还没有完成,所以看起来有很多无用的方法):

#include <iostream>
using namespace std;
typedef int element;
struct cell
{
element element;
cell * next;
};
class List {
protected:
cell * header;
public:
List();
~List();
void Insert(element x, cell * p);
void Delete(cell * p);
element Retrieve(cell * p);
cell * Locate(element x);
cell * First();
cell * Next(cell * p);
cell * Previous(cell * p);
cell * Last();
void print();
bool empty() {
return header == nullptr;
}
};
List::List() {
header = nullptr;
}
List::~List() {
cell *tmp;
while(header != nullptr) {
tmp = header;
header = header->next;
delete tmp;
}
}
void List::Insert(element x, cell * p) {
cell *tmp;
if (p != nullptr) {
tmp = p->next;
p->next = new cell;
p->next->element = x;
p->next->next = tmp;
} else {
header = new cell;
header->element = x;
header->next = nullptr;
}
}
element List::Retrieve(cell * p) {
return p->element;
}
void List::Delete(cell *p) {
cell* tmp;
tmp=p->next;
p->next = p->next->next;
delete tmp;
}
void List::print() {
for (cell *i = header; i != nullptr; i = i->next) {
cout << i->element << endl;
}
}
cell* List::Locate(element x) {
cell* tmp;
tmp = header;
while(tmp->next != nullptr) {
if(tmp->next->element == x) return tmp;
tmp = tmp->next;
}
return tmp;
}
cell* List::First() {
return header;
}
cell* List::Last() {
if(header!= nullptr) {
cell *i;
for(i = header; i->next != nullptr; i = i->next);
return i;
}
else return nullptr;
}
cell* List::Next(cell *p) {
return p->next;
}
cell* List::Previous(cell *p) {
cell* tmp;
tmp = header;
while(tmp->next != p) tmp = tmp->next;
return tmp;
}
class Stack {
List * list;
public:
Stack();
element top();
element pop();
void push(element x);
bool empty();
void makenull();
};
Stack::Stack() {
list = new List();
}
element Stack::top() {
return this->list->Retrieve(this->list->Last());
}
element Stack::pop() {
int tmp = this->list->Retrieve(this->list->Last());
cell* c = this->list->Previous(list->Last());
this->list->Delete(c);
return tmp;
}
void Stack::push(element x) {
this->list->Insert(x, this->list->Last());
}
bool Stack::empty() {
return this->list->empty();
}
void Stack::makenull() {
delete list;
}
class RPN {
Stack *stack;
public:
RPN();
int type;
int result;
char calculation[];
int menu();
int calculate();
bool isNum(char c);
bool isOperand(char c);
void putOnStack();
void enterCalculation();
void convertToRPN();
void convertFromRPN();
};
RPN::RPN() {
stack = new Stack();
type = 0;
result = 0;
}
int RPN::menu() {
cout << endl << "Choose option:" << endl;
cout << "1. Convert to RPN" << endl;
cout << "2. Convert from RPN" << endl;
cout << "3. RPN calculator" << endl;
cout << "4. Regular calculator" << endl;
cout << "5. Finish" << endl;
cin >> type;
switch (type) {
case 1:
enterCalculation();
convertFromRPN();
break;
case 2:
enterCalculation();
convertToRPN();
break;
case 3:
enterCalculation();
convertFromRPN();
calculate();
break;
case 4:
enterCalculation();
calculate();
break;
case 5:
break;
default:
cout << "Nie ma takiej opcji!" << endl;
break;
}
return type;
}
bool RPN::isNum(char c) {
return isdigit(c);
}
bool RPN::isOperand(char c) {
return c == '+' || c == '-' || c == '/' || c == '*';
}
void RPN::putOnStack() {
for(int i = 0; i < strlen(calculation); i++)
if(isNum(calculation[i])) stack->push(calculation[i]);
}
void RPN::enterCalculation() {
cout << "Type your calculation:" << endl;
cin >> calculation;
putOnStack();
}
void RPN::convertToRPN() {
}
void RPN::convertFromRPN() {
}
int RPN::calculate() {
return result;
}

int main() {
auto *rpn = new RPN();
while(rpn->type != 5)
rpn->menu();
return 0;
}

试试这个:

cell* List::Last() {
cell *i = header;
while(i->next != nullptr && i != nullptr)i=i->next;
return i;
}

感谢您的所有帮助。我设法解决了这个问题。 也许这会帮助某人,我在下面发布我的代码。

#include <iostream>
using namespace std;
typedef string element;
struct cell {
string element;
cell * next;
};
class List {
public:
cell * header;
List();
~List();
element Retrieve(cell * p);
cell* Previous(cell * p);
cell * Last();
void Insert(const element &x, cell * p);
void Delete(cell * p);
bool empty() {
return header == nullptr;
}
};
List::List() {
header = nullptr;
}
List::~List() {
cell *tmp;
while(header != nullptr) {
tmp = header;
header = header->next;
delete tmp;
}
}
element List::Retrieve(cell * p) {
return p->element;
}
void List::Delete(cell *p) {
cell* tmp;
if(p->next == nullptr) {
cout << "Error! No next element to delete!" << endl;
} else if(p->next->next == nullptr) {
delete p->next;
p->next = nullptr;
} else {
tmp = p->next;
p->next = p->next->next;
delete tmp;
}
}
cell* List::Previous(cell *p) {
if(p == header) {
cout << "There is no previous element for the header!" << endl;
return nullptr;
} else {
if(header -> next == p) {
return header;
} else {
cell *tmp = header;
while(tmp->next != p) tmp = tmp->next;
return tmp;
}
}
}
void List::Insert(const element &x, cell * p) {
cell *tmp;
if (p != nullptr) {
if(p -> next == nullptr) {
p->next = new cell;
p->next->element = x;
p->next->next = nullptr;
} else {
tmp = p->next;
p->next = new cell;
p->next->element = x;
p->next->next = tmp;
}
} else {
header = new cell;
header->element = x;
header->next = nullptr;
}
}
cell* List::Last() {
if(header != nullptr) {
if(header-> next == nullptr) return header;
else {
cell *i;
for(i = header; i->next != nullptr; i = i->next);
return i;
}
}
else return nullptr;
}
class Stack {
public:
List * list;
Stack();
void push(const element &x);
void makenull();
bool empty();
element pop();
element top();
};
Stack::Stack() {
list = new List();
}
void Stack::makenull() {
this->list->header = nullptr;
}
bool Stack::empty() {
return this->list->empty();
}
element Stack::top() {
return this->list->Retrieve(this->list->Last());
}
element Stack::pop() {
string tmp;
if(list->Last() == list->header) {
tmp = this->list->header->element;
this->list->header = nullptr;
} else {
tmp = this->list->Retrieve(this->list->Last());
cell* c = this->list->Previous(list->Last());
this->list->Delete(c);
}
return tmp;
}
void Stack::push(const element &x) {
if(this->list->header != nullptr) {
this->list->Insert(x, this->list->Last());
} else {
this->list->header = new cell;
this->list->header->element = x;
this->list->header->next = nullptr;
}
}
class RPN {
public:
RPN();
~RPN();
Stack *stack;
int type;
string calculation;
int menu();
string convertToRPN();
string convertFromRPN();
double calculateRPN();
void enterCalculation();
bool isNum(string s);
bool isOperator(char c);
int compareOperators(string op1, string op2);
};
RPN::RPN() {
stack = new Stack();
type = 0;
}
RPN::~RPN() {
delete stack;
}
int RPN::menu() {
cout << endl << "Choose option:" << endl;
cout << "1. Convert from RPN" << endl;
cout << "2. Convert to RPN" << endl;
cout << "3. RPN calculator" << endl;
cout << "4. Calculator" << endl;
cout << "5. Exit" << endl;
cin >> type;
cin.ignore();
switch (type) {
case 1:
enterCalculation();
convertFromRPN();
break;
case 2:
enterCalculation();
convertToRPN();
break;
case 3:
enterCalculation();
calculateRPN();
break;
case 4:
enterCalculation();
calculation = convertToRPN();
calculateRPN();
break;
case 5:
break;
default:
cout << "No such option! Choose a correct one." << endl;
break;
}
return type;
}
bool RPN::isNum(string s) {
return !s.empty() && std::find_if(s.begin(), s.end(), [](char c) { return !isdigit(c); }) == s.end();
}
bool RPN::isOperator(char c) {
return (c == '+' || c == '-' || c == '*' || c == '/');
}
int RPN::compareOperators(string op1, string op2) {
if ((op1[0] == '*' || op1[0] == '/') && (op2[0] == '+' || op2[0] == '-')) return -1;
else if ((op1[0] == '+' || op1[0] == '-') && (op2[0] == '*' || op2[0] == '/')) return 1;
return 0;
}
void RPN::enterCalculation() {
calculation[0] = 0;
cout << "Input expression:" << endl;
getline(cin, calculation);
}
string RPN::convertToRPN() {
auto len = static_cast<int>(calculation.length());
stack->makenull();
string RPNcalc;
RPNcalc.clear();
int j = 0;
int par1 = 0;
int par2 = 0;
while(isspace(calculation[j])) j++;
if(!isNum(string(1, calculation[j])) && (calculation[j] != '(')) {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
j = 0;
while(isspace(calculation[len-1-j])) j++;
if(!isNum(string(1, calculation[len-1-j])) && (calculation[len-1-j] != ')')) {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
for (int i = 0; i < len; i++) {
if (isNum(string(1, calculation[i])) || calculation[i] == '.') {
if(isspace(calculation[i+1])) {
RPNcalc.push_back(calculation[i]);
RPNcalc.push_back(' ');
} else {
if(isNum(string(1, calculation[i])) && calculation[i+1] != '.' && !isNum(string(1, calculation[i]))) {
RPNcalc.push_back(calculation[i]);
RPNcalc.push_back(' ');
} else if(isOperator(calculation[i+1])) {
RPNcalc.push_back(calculation[i]);
RPNcalc.push_back(' ');
} else if(calculation[i+1] == ')') {
RPNcalc.push_back(calculation[i]);
RPNcalc.push_back(' ');
} else {
RPNcalc.push_back(calculation[i]);
}
}
} else if (isOperator(calculation[i])) {
while(!stack->empty() && stack->top()[0] != '(' && compareOperators(stack->top(), string(1, calculation[i])) <= 0) {
RPNcalc.push_back(stack->pop()[0]);
RPNcalc.push_back(' ');
}
stack->push(string(1, calculation[i]));
} else if(calculation[i] == '(') {
par1++;
stack->push(string(1, calculation[i]));
} else if(calculation[i] == ')') {
par2++;
while(!stack->empty()) {
if(stack->top()[0] == '(') {
stack->pop();
break;
}
RPNcalc.push_back(stack->pop()[0]);
RPNcalc.push_back(' ');
}
} else if(isspace(calculation[i])) {
} else {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
}
if(par1 != par2) {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
while(!stack->empty()) {
if(RPNcalc.back() != ' ') RPNcalc.push_back(' ');
RPNcalc.push_back(stack->top()[0]);
stack->pop();
}
if(type != 4) cout << "RPN expression: " << RPNcalc << endl;
return RPNcalc;
}
string RPN::convertFromRPN() {
auto len = static_cast<int>(calculation.length());
stack->makenull();
string num;
string right;
string left;
string newExpr;
int j = 0;
while(isspace(calculation[j])) j++;
if(!isNum(string(1, calculation[j]))) {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
j = 0;
while(isspace(calculation[len-1-j])) j++;
if(!isOperator(calculation[len-1-j])) {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
for (int i = 0; i < len; i++) {
if (isOperator(calculation[i])) {
right = stack->pop();
left = stack->pop();
newExpr.clear();
newExpr += '(';
newExpr += left;
newExpr += ' ';
newExpr += calculation[i];
newExpr += ' ';
newExpr += right;
newExpr += ')';
stack->push(newExpr);
} else if (isNum(string(1, calculation[i])) || calculation[i] == '.') {
if(isspace(calculation[i+1])) {
num.push_back(calculation[i]);
stack->push(num);
num.clear();
} else num.push_back(calculation[i]);
} else if(isspace(calculation[i])) {
} else {
cout << "Expression incorrect!" << endl;
string errStr = "err";
return errStr;
}
}
newExpr = stack->top();
newExpr.erase(newExpr.begin());
newExpr.erase(newExpr.end()-1);
cout << "Infix notation: " << newExpr;
return newExpr;
}
double RPN::calculateRPN() {
auto len = static_cast<int>(calculation.length());
stack->makenull();
double a = 0;
double b = 0;
double result = 0;
string num;
num.clear();
if(isNum(string(1, calculation[len-1]))) {
cout << "Expression incorrect!" << endl;
return 0;
}
for (int i = 0; i < len; i++) {
if (isNum(string(1, calculation[i])) || calculation[i] == '.') {
if(isspace(calculation[i+1])) {
num.push_back(calculation[i]);
stack->push(num);
num.clear();
} else num.push_back(calculation[i]);
} else if (isOperator(calculation[i])) {
a = stod(stack->pop());
b = stod(stack->pop());
switch (calculation[i]) {
case '*':
stack->push(to_string(a * b));
break;
case '/':
stack->push(to_string(b / a));
break;
case '-':
stack->push(to_string(b - a));
break;
case '+':
stack->push(to_string(a + b));
break;
default:
break;
}
} else if(isspace(calculation[i])) {
} else {
cout << "Expression incorrect!" << endl;
return 0;
}
}
result = stod(stack->pop());
if(!stack->empty()) {
cout << "Expression incorrect!" << endl;
return 0;
}
cout << "Result: " << result << endl;
return result;
}
int main() {
cout << endl << "POSTFIX-INFIX CALCULATOR AND CONVERTER "<< endl;
auto *rpn = new RPN();
while(rpn->type != 5)
rpn->menu();
return 0;
}

最新更新