allocated memory gets reclaimed - c++

hi I'm tying to code my own list class actually it works like the std::vector class. The problem is when I use new to allocate memory for the next list,
it Works fine. but when i try to allocate memory for the target(data) it gets reclaimed when the program reaches to the end of the scope of push_back()
I dont understand why this two do not happen the same way and how can I use allocated memory for my data without it getting distroyed?
the code is here
#include <iostream>
#include <cstdlib>
using namespace std;
struct pos{
int x;
int y;
pos()
{
x = y = 0;
}
pos(int x, int y)
{
this->x = x;
this->y = y;
}
pos& operator=(pos rhs)
{
x = rhs.x;
y = rhs.y;
return *this;
}
bool operator==(const pos& rhs)
{
if(x == rhs.x && y == rhs.y)
return true;
else
return false;
}
~pos()
{
cout << "x =" << x << ", y =" << y << "got distorted!" << endl;
}
};
class list {
private:
pos *target;
list* next;
int index;
public :
list();
list(pos target);
void push_back (int first , int second);
void push_back (const pos target);
pos pop_back();
pos* search(int first , int second);
pos* search(pos target);
int erase(int index);
pos get(int index);
void change(const pos target,int index);
void change(int first,int second,int index);
~list();
};
void print(list lst);
// function declarations
list::~list()
{
cout << "list is destroyed!" << endl;
if(target != NULL)
delete target;
if(next != NULL)
delete next;
}
list::list()
{
target = NULL;
next = NULL;
index = 0;
}
list::list(pos target)
{
this->target = new pos(target);
index = 0;
next = NULL;
}
void list::push_back(const pos target)
{
cout << "push_back() begin" << endl;
list* it = this;
while(it->next != NULL)
{
it = it->next;
}
if(it->target == NULL)
{
it->target = new pos(target);
}
else
{
it->next = new list;
it->next->index = it->index+1;
//option one
it->next->target = new pos(target);
//option two
it->next->target = (pos*)malloc(sizeof(pos));
(*it->next->target) = target;
//it->next->next is already NULL
}
cout << "push_back() end" << endl;
}
void list::push_back(int first , int second)
{
push_back(pos(first,second));
}
pos list::pop_back()
{
print(*this);
list* it = this;
cout << "address of x is" << this << endl;
cout << "this->target is" << this->target << endl;
cout << (*target).x << endl;
if(it->target == NULL)
return *(new pos); // an error is occurred there is not any data to return! must find another solution maybe throw an exception
if(it->next == NULL)
{
pos return_data = *(it->target);
delete it->target;
it->target = NULL;
return return_data;
}
while(it->next->next != NULL)
{
cout << "it->target is" << it->target << endl;
it = it->next;
}
pos return_data = *(it->next->target);
delete it->next;
it->next = NULL;
return return_data;
}
pos* list::search(pos target)
{
list* it = this;
do
{
if(target == *(it->target))
return it->target;
if(it->next != NULL)
it = it->next;
else
return NULL;
}while(1);
}
pos* list::search(int first , int second){
return search(pos(first,second));
}
int list::erase(int index){
if(index < 0)
return 0;
list *it = this , *it_next = this->next;
if(index == 0)
{
if(it->next == NULL)
{
delete it->target;
return 1;
}
while(it_next->next != NULL)
{
it->target = it_next->target;
it = it_next;
it_next = it_next->next;
}//needs to be completed
}
do
{
if(it_next->index == index)
{
it->next = it_next->next;
delete it_next;
return 1;
}
if(it_next->next != NULL)
{
it = it_next;
it_next = it_next->next;
}
else
return 0;
}while(1);
return 1;
}
pos list::get(int index)
{
if(index < 0)
return *(new pos);//error
list* it = this;
do
{
if(it->index == index)
{
return *(it->target);
}
if(it->next != NULL)
it = it->next;
else
return *(new pos);//error , index is bigger than [list size] - 1
}while(1);
}
void list::change(const pos target,int index)
{
if(index < 0)
return ;//error
list* it = this;
do
{
if(it->index == index)
{
*(it->target) = target;
}
if(it->next != NULL)
it = it->next;
else
return;//error , index is bigger than [list size] - 1
}while(1);
}
void list::change(const int first,const int second,int index)
{
change(pos(first,second),index);
}
void print(list lst)
{
int idx = 0;
while(!(lst.get(idx)==pos(0,0)))
{
cout << "index " << idx << " : x = " << lst.get(idx).x << ", y = " << lst.get(idx).y << endl;
idx++;
}
}
int main(int argc, char const *argv[])
{
list x;
cout << "address of x is" << &x << endl;
x.push_back(1,1);
x.push_back(2,2);
x.push_back(3,3);
x.push_back(4,4);
x.push_back(5,5);
print(x);
cout << "--------------------------" << endl;
x.pop_back();
print(x);
cout << "--------------------------" << endl;
cout << x.get(2).x << endl;
x.erase(2);
print(x);
cout << "--------------------------" << endl;
return 0;
}
in other words why it->next->target and/or it->target get destroyed when push_back returns?

In
void list::push_back(const pos target)
target is being passed by value, so the target inside push_back is a temporary copy. When the function ends the copy will go out of scope and be destroyed. This is what you are seeing. Annoying, but not your real problem.
list violates the Rule of Three. This means when a list is copied it is not copied correctly. The pointers are copied and not the items pointed-at. Every time a list is copied, both the original and the copy point at the same places. When the copy goes out of scope and is destroyed, it takes the original's data with it.
It just so happens that you pass exclusively by value, so there is a lot of copying and destroying going on. The print function, for example, will incorrectly copy and then obliterate the provided listwhen it returns.
Solution: Add a copy constructor and an assignment operator to list that works its way through the list and copies all of the links and read up on pass by reference.

What is being destroy (or destructor being called) is the temporary that created as input parameter on the following line:
push_back(pos(first,second));

Related

How to Visit Each Node in Chained Hash Table Linked Lists

I am writing chained hash table code.
I do not understand why my linked list traversal does not stop at NULL when I set entry->next->next = NULL after I insert.
I have omitted code which is not useful for my question:
What is causing the linked list traversal in `printTable' to loop forever?
ChainHash.h:
class Entry {
private:
string key;
int value;
Entry *next;
friend class HashTable_CH;
public:
Entry(string k, int v) {
key = k;
value = v;
next = NULL;
}
};
class HashTable_CH {
private:
Entry **slots;
const int DEFAULT_CAP = 11;
const float load_factor = 0.5;
int capacity;
int size;
//int isPrime(int n) {
//int calculateGrowSize() {
int hash(string k) {
int c = 0;
for (int i = 0; i < k.length(); i++)
c += int(k[i]);
return c % capacity;
}
//int probe(int hash, int index) {
public:
HashTable_CH() {
slots = new Entry*[DEFAULT_CAP];
capacity = DEFAULT_CAP;
size = 0;
for (int i = 0; i < DEFAULT_CAP; i++)
slots[i] = NULL;
}
void Insert(string key, int value) {
if (float(size) / float(capacity) >= load_factor)
//grow();
return;
int h = hash(key);
if (slots[h] == NULL) {
slots[h] = new Entry(key, value);
size++;
return;
} else {
Entry *entry = slots[h];
while (entry->next != NULL)
entry = entry->next;
entry->next = new Entry(key, value);
entry->next->next = NULL;
}
}
//bool Search(string, int &value) {
//void Remove(string key) {
void printTable() {
for (int i = 0; i < capacity; i++) {
cout << "Slot " << i << ": ";
if (slots[i] == NULL)
cout << "*****";
else {
Entry **temp = slots;
while (temp != NULL) {
cout << "Key: " << slots[i]->key << ", " << slots[i]->value;
}
}
} cout << "\n";
} cout << "\n";
}
};
testChainedHash.cpp:
#include"ChainHash.h"
int main() {
HashTable_CH t1;
t1.Insert("froyo", 500);
t1.Insert("froyo", 600);
t1.Insert("froyo", 700);
t1.printTable();
}
Here:
while (temp != NULL) {
cout << "Key: " << slots[i]->key << ", " << slots[i]->value;
}
Do you see the problem?

LinkedList Backtracking

I'm trying to backtrack through a linkedlist I have created to solve a knight's tour problem, but once I hit a condition requiring me to backtrack, it totally empties the list. I have figured out it is because when I return false from the function findpath() to keep my while loop going, it continually loops back through the goback() function. What I'm having trouble figuring out is why. When i go through the goback function and call the calcmove function, it pushes the correct move to the structure I have declared, so passing false should keep the loop going and restart with the boolean cando and figuring out if that is false or not. But, it should be true because I just tested it and pushed it to the stack. Instead, it's emptying the list after I backtrack for the first time. So calcmove() would just be returning false every time after the first pop. But I don't see why that's happening. I need to return false to keep the loop going. What I need it to do is go back only once, find a new move, and continue on. Why would it be looping back to the function where the value on the list gets popped? If the value worked, and a new move is created (which I did verify it is doing correctly), it should be ready to call with a new (true) boolean. Is this just an inherently bad way of implementing the backtracking?
#include "stdafx.h"
#include "Header.h"
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <iomanip>
llist list;
Move m;
int board[8][8];
int cx[] = { -2, -1, 1, 2, 2, 1, -2, -1 };
int cy[] = { 1, 2, 2, 1, -1, -2, -1, -2 };
int movenum = 1;
Move first;
/*Check to see if move is within the constraints of the board*/
bool constraints(int k, int b) {
if ((k < 0) || (b < 0) || (k > 7) || (b > 7) || (board[k][b] != -1)) {
return true;
}
else {
return false;
}
}
/* Initialization of 8x8 board, fill the array with -1 */
void initboard() {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
board[x][y] = -1;
}
}
}
/* Output the current board array */
void printboard(int arr[8][8]) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
cout << std::setw(2) << arr[x][y] << " ";
}
cout << endl;
}
}
void updateboard(int k, int b) {
board[k][b] = movenum;
movenum++;
}
bool calcmove(int x, int y, int i) {
for (i; i < 9; i++) {
int a0 = x + cx[i];
int a1 = y + cy[i];
/*if(board[a0][a1] == board[first.x][first.y]){
}*/
if (constraints(a0, a1) == false) {
updateboard(a0, a1);
m.x = a0;
m.y = a1;
m.index = i;
list.push(m);
//list.display();
return true;
}
}
return false;
}
void goback(int k, int b) {
board[k][b] = -1;
list.display();
Move m = list.pop();
bool cando = calcmove(m.x, m.y, m.index);
cout << "prev is " << m.x << " , " << m.y << endl;
if (cando) {
return;
}
else {
goback(m.x,m.y);
}
}
bool findpath(){
bool cando = calcmove(m.x, m.y, 0);
if (cando) {
return false;
}
else {
movenum--;
goback(m.x, m.y);
return false; /*------> inserting this here drains the list*/
}
return true;
}
int main()
{
int m1 = 1;
int m2 = 2; //random
first.x = m1;
first.y = m2;
first.index = 0;
list.push(first); //push first node on to stack
initboard();
updateboard(m1, m2); //update board
while (!findpath()) {
;
}
printboard(board);
}
the .h file:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include <ostream>
using std::cout;
using std::endl;
using std::setw;
struct Move {
int x;
int y;
uint32_t index;
};
struct node
{
public:
Move info;
struct node *next;
};
class llist {
struct node *start;
public:
void push(Move coords) {
struct node *p = new node;
p = newnode(coords);
if (start == NULL) {
start = p;
}
else {
p->next = start;
start = p;
//cout << "pushed" << endl;
}
}
Move pop() {
if (start == NULL) {
throw std::runtime_error("The list is empty");
}
else {
struct node *temp = new node;
temp = start;
Move data = start->info;
start = start->next;
delete temp;
//cout << "pop successful" << endl;
return data;
}
}
node *newnode(Move value) {
struct node *temp = new(struct node);
if (temp == NULL) {
return 0;
}
else {
temp->info = value;
temp->next = NULL;
return temp;
}
}
void display()
{
struct node *temp;
if (start == NULL)
{
cout << "The List is Empty" << endl;
return;
}
temp = start;
cout << "Elements of list are: " << endl;
while (temp != NULL)
{
cout << temp->info.x << "->";
temp = temp->next;
}
cout << "empty" << endl;
}
};
The goal of this is to create a linked list, solve the problem using the list for backtracking (push the current move unless no moves are available, then pop the previous values), and return the completed board.

EXC_BAD_ACCESS with stack/list c++

I am working on my RPN calculator project.
At this moment I would like to put all the numbers from an entered calculation on stack, but unfortunately the process finishes with exit code 11 and I am stuck. It extacly happens when I type for example 3, and then 3+3.
I debugged it and I can see that the problem is in the line:
if(header!= nullptr) {
in here:
cell* List::Last() {
if(header!= nullptr) {
cell *i;
for(i = header; i->next != nullptr; i = i->next);
return i;
}
else return nullptr;
}
Exception EXC_BAD_ACCESS. I suppose it has something to do with my header in the list, but I have no idea why. I have read about this exception but it still doesn't help me. As far as I can see, most people get it with arrays. I would be very grateful for any hints... My full code is here (it is not finished yet, so it might seem that there is a lot of useless methods):
#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;
}
try this:
cell* List::Last() {
cell *i = header;
while(i->next != nullptr && i != nullptr)i=i->next;
return i;
}
Thank you for all your help. I managed to cope with that problem.
Maybe this will help somebody, I post my code below.
#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;
}

Memory address instead of value in cout of class [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to write own simple forward list implementation. I'd like to access element by cout << list[0]. I wrote the following code but instead of value I got something like x637c00539997. What did I do wrong?
What else can I improve in my code?
#include <iostream>
#include <assert.h>
#include <cstdio>
#include <cstring>
#include <memory>
using namespace std;
class myList{
public:
class myListExceptionEmpty: public exception
{
public:
virtual const char* what() const throw()
{
return "EMPTY";
}
};
void push_back(int valve);
int getSize();
bool isEmpty();
void removeFirst();
void remove(int x);
void dump();
void pop_front();
struct elem
{
std::shared_ptr<elem> next;
int val;
};
class proxy
{
public:
std::shared_ptr<myList::elem> position;
proxy(std::shared_ptr<myList::elem> pos)
{
position = pos;
}
};
std::shared_ptr<myList::proxy> operator[](int position);
private:
std::shared_ptr<elem> start;
std::shared_ptr<elem> getLastElement();
std::shared_ptr<proxy> current;
int size = 0;
};
ostream& operator<<(std::ostream& os, myList::proxy& obj)
{
os << obj.position->val;
return os;
}
shared_ptr<myList::proxy> myList::operator[](int position)
{
std::shared_ptr<elem> p = start;
for(int i=0;i<position;i++)
{
p = p->next;
if (p == NULL) throw std::out_of_range("out");
}
//cout << p->val;
std::shared_ptr<proxy> tmp(new myList::proxy(p));
current = tmp;
return current;
}
std::shared_ptr<myList::elem> myList::getLastElement()
{
std::shared_ptr<elem> p = start;
while(p->next != NULL ) p = p->next;
return p;
}
bool myList::isEmpty()
{
return size;
}
void myList::dump()
{
std::shared_ptr<elem> x = start;
while (x != NULL)
{
cout << x->val << endl;
x = x->next;
}
}
void myList::push_back(int valve)
{
std::shared_ptr<elem> p, n(new elem());
n->next = NULL;
n->val = valve;
p = start;
if(p != NULL)
{
while(p->next != NULL ) p = p->next;
p->next = n;
}
else start = n;
size++;
}
void myList::remove(int x)
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
if (p->val == x)
{
prv->next = p->next;
size--;
}
prv = p;
p = p->next;
}
}
void myList::pop_front()
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
prv = p;
p = p->next;
}
prv->next = NULL;
}
void myList::removeFirst()
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p;
p = start;
cout << start->val << endl;
if(p!= NULL)
{
start = p->next;
}
size--;
}
int myList::getSize()
{
return size;
}
int main()
{
myList array;
int size;
cin >> size;
char a;
int tmp;
for (int i=0; i<size; ++i) {
std::cin >> a;
if (a == 'D')
{
try{
array.removeFirst();
}
catch (myList::myListExceptionEmpty &e)
{
cout << e.what() << endl;
}
}
else if (a == 'A')
{
int tmp;
std::cin >> tmp;
array.push_back(tmp);
cout << "elem" << array[0];
}
else if (a == 'S') cout /*<< "Size:"*/ << array.getSize() << endl;
}
}
With regard to the question "what else to improve":
You're using shared pointers, great! Instead of using new use the corresponding routine make_shared (see C++ documentation).
Do not define classes in classes. Let each class have its own header and source file. It increases readability dramatically and even compiling gets faster by splitting all classes into different files (best way: use include guards). This way you can also leave the namespaces like myList::elem.
Use <cassert> instead of <assert.h>. You're using C++11 anyway, so why the need to use an old C-library?!
Just an example: Change void myList::remove(int x) to void myList::remove(const int& x). Let the compiler know that x is a read-only object. Do not call the int-copy constructor here (also at other code lines).
With regard to your 2nd question: your overloaded operator [] returns a shared-pointer and not the object this pointer is pointing at. Thus, it will print the address of the pointer.
This is program after fix. I used cout << *array[0]; instead of cout << array[0];. Than you for help
#include <iostream>
#include <memory>
using namespace std;
class MyListProxy;
class MyListExceptionEmpty: public exception
{
public:
virtual const char* what() const throw(){
return "EMPTY";
}
};
class MyList{
public:
void push_back(int valve);
int getSize() { return size; };
bool empty() { return size; };
void removeFirst();
void remove(const int& x);
void dump();
void pop_front();
void clear() {this->start = NULL; size = 0;}
struct elem
{
shared_ptr<elem> next;
int val;
};
shared_ptr<MyListProxy> operator[](int position);
private:
shared_ptr<elem> start;
shared_ptr<MyListProxy> current;
shared_ptr<elem> getEnd();
int size = 0;
};
class MyListProxy
{
public:
shared_ptr<MyList::elem> position;
MyListProxy(shared_ptr<MyList::elem> pos)
{
position = pos;
}
};
ostream& operator<<(ostream& os, MyListProxy& obj)
{
os << obj.position->val;
return os;
}
shared_ptr<MyListProxy> MyList::operator[](int position)
{
if (start == NULL) throw out_of_range("out");
shared_ptr<elem> p = start;
for(int i=0;i<position;i++){
p = p->next;
if (p == NULL) throw out_of_range("out");
}
return make_shared <MyListProxy>(p);
}
shared_ptr<MyList::elem> MyList::getEnd()
{
if (start == NULL) return start;
shared_ptr<elem> p = start;
while(p->next != NULL ) p = p->next;
return p->next;
}
void MyList::dump()
{
shared_ptr<elem> x = start;
while (x != NULL)
{
cout << x->val << endl;
x = x->next;
}
}
void MyList::push_back(int valve)
{
shared_ptr<elem> p;
auto last = this->getEnd();
auto a = make_shared<elem>();
last = a;
last->val = valve;
size++;
}
void MyList::remove(const int& x)
{
if (size == 0) throw MyListExceptionEmpty();
shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
if (p->val == x)
{
prv->next = p->next;
size--;
}
prv = p;
p = p->next;
}
}
void MyList::pop_front()
{
if (size == 0) throw MyListExceptionEmpty();
start = start->next;
}
int main()
{
MyList array;
int size;
cin >> size;
char a;
int tmp;
for (int i=0; i<size; ++i) {
cin >> a;
if (a == 'D')
{
try{
cout << *array[0];
array.pop_front();
}
catch (MyListExceptionEmpty &e)
{
cout << "EMPTY" << endl;
}
catch (out_of_range &e)
{
cout << "EMPTY" << endl;
}
}
else if (a == 'A')
{
int tmp;
cin >> tmp;
array.push_back(tmp);
}
else if (a == 'S') cout /*<< "Size:"*/ << array.getSize() << endl;
cout << "SIZE::" << array.getSize() << endl;
}
}

Reversing a singly-linked list in C++

I am having an issue with my attempt at recursively reversing my implementation of a singly-linked list.
I have read other similar questions regarding this process, however, in my attempt at implementing this process in my own program, I've come up short.
This is my attempt below (which is slightly different than what is presented in the code that follows thereafter):
Note: My list uses a root pointer which holds no significant data, and serves only as an address with which to reference data in the list.
void IntList::reverse(Node* t_node) {
if(t_node == NULL) {
reverse(root);
} else
if(t_node->next == NULL) {
cout << "In (swapping): " << t_node->value << endl;
root->next = t_node;
} else {
cout << "In: " << t_node->value << endl;
Node* tmp = t_node->next;
reverse(t_node->next);
tmp->next = t_node;
}
return NULL;
}
I lose reference somewhere and print endlessly when trying to display the list. I am really at a loss as to what the error I've made is, but suspect it may have something to do with how I handle my root.
Here is the program in its entirety (all functioning apart from the reverse() methods) for completeness.
#ifndef INTLIST_H
#define INTLIST_H
#include<iostream>
using namespace std;
class IntList {
private:
struct Node {
int value;
Node* next;
};
int size;
Node* root;
void destroy();
public:
IntList() { root = new Node; root->next = 0; root-> value = 0; size = 0;}
IntList(const IntList& list) { this->root = list.root; this->size = list.size; }
~IntList() {}
void appendNode(int val);
void insertNode(int pos, int val);
void deleteNode(int pos);
int searchNode(int val);
int getSize() const;
void print() const;
Node* reverse(Node* t_node);
int &operator[](int element) const;
void pop_back();
void pop_front();
void push_back(int val);
void push_front(int val);
};
void IntList::appendNode(int val) {
push_back(val);
}
void IntList::insertNode(int pos, int val) {
Node* tmp;
Node* current = root;
for(int i = 0; i < pos && current->next != NULL; i++) {
current = current->next;
}
tmp = new Node;
tmp->value = val;
tmp->next = current->next;
current->next = tmp;
size++;
}
void IntList::deleteNode(int pos) {
Node* tmp;
Node* current = root;
if(pos <= size-1) {
for(int i = 0; i < pos; i++) {
current = current->next;
}
tmp = current->next;
current->next = tmp->next;
delete tmp;
size--;
} else {
cout << "ERROR: Out of range." << endl;
}
}
int IntList::searchNode(int val) {
int position = 0;
Node* current = root->next;
if(size != 0) {
for(position = 0; position < size && current->value != val; position++) {
current = current->next;
}
} else {
cout << "ERROR: List is empty." << endl;
position = -1;
}
return position;
}
int IntList::getSize() const {
return size;
}
void IntList::print() const {
Node* current = root->next;
cout << "List: ";
while(current != NULL) {
cout << current->value << " ";
current = current->next;
}
if(getSize() == 0) {
cout << "Empty.";
}
cout << endl;
}
IntList::Node* IntList::reverse(Node* t_node) {
#define REVERSE
#ifndef REVERSE
if(t_node == NULL) {
reverse(root);
} else
if(t_node->next == NULL) {
cout << "In (swapping): " << t_node->value << endl;
root->next = t_node;
} else {
cout << "In: " << t_node->value << endl;
Node* tmp = t_node->next;
reverse(t_node->next);
tmp->next = t_node;
}
#endif //reverses list, but causes infinite loop in display
return NULL;
}
int &IntList::operator[](int pos) const {
Node* current = root->next;
if(pos <= size-1) {
for(int i = 0; i < pos; i++) {
current = current->next;
}
} else {
cout << "ERROR: Out of bounds.";
current = NULL;
}
return current->value;
}
void IntList::pop_back() {
deleteNode(size-1);
}
void IntList::pop_front() {
deleteNode(0);
}
void IntList::push_back(int val) {
insertNode(size, val);
}
void IntList::push_front(int val) {
insertNode(0, val);
}
#endif
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<iostream>
using namespace std;
template<typename T>
class LinkedList {
private:
struct Node {
T value;
Node* next;
};
int size;
Node* root;
void destroy();
public:
LinkedList() { root = new Node; root->next = 0; root-> value = 0; size = 0;}
LinkedList(const LinkedList &) {}
~LinkedList() {}
void appendNode(T val);
void insertNode(int pos, T val);
void deleteNode(int pos);
int searchNode(T val);
int getSize() const;
void print() const;
void reverse(Node* t_node);
int &operator[](int element) const;
void pop_back();
void pop_front();
void push_back(T val);
void push_front(T val);
};
template <typename T>
void LinkedList<T>::appendNode(T val) {
push_back(val);
}
template <typename T>
void LinkedList<T>::insertNode(int pos, T val) {
Node* tmp;
Node* current = root;
for(int i = 0; i < pos && current->next != NULL; i++) {
current = current->next;
}
tmp = new Node;
tmp->value = val;
tmp->next = current->next;
current->next = tmp;
size++;
}
template <typename T>
void LinkedList<T>::deleteNode(int pos) {
Node* tmp;
Node* current = root;
if(pos <= size-1) {
for(int i = 0; i < pos; i++) {
current = current->next;
}
tmp = current->next;
current->next = tmp->next;
delete tmp;
size--;
} else {
cout << "ERROR: Out of range." << endl;
}
}
template <typename T>
int LinkedList<T>::searchNode(T val) {
int position = 0;
Node* current = root->next;
if(size != 0) {
for(position = 0; position < size && current->value != val; position++) {
current = current->next;
}
} else {
cout << "ERROR: List is empty." << endl;
position = -1;
}
return position;
}
template <typename T>
int LinkedList<T>::getSize() const {
return size;
}
template <typename T>
void LinkedList<T>::print() const {
Node* current = root->next;
cout << "List: ";
while(current != NULL) {
cout << current->value << " ";
current = current->next;
}
if(getSize() == 0) {
cout << "Empty.";
}
cout << endl;
}
template <typename T>
void LinkedList<T>::reverse(Node* t_node) {
/*
if(t_node == NULL) {
reverse(root);
} else
if(t_node->next == NULL) {
cout << "In (swapping): " << t_node->value << endl;
root->next = t_node;
} else {
cout << "In: " << t_node->value << endl;
Node* tmp = t_node->next;
reverse(t_node->next);
tmp->next = t_node;
}
*/ //reverses list, but causes infinite loop in display
}
template <typename T>
int &LinkedList<T>::operator[](int pos) const {
Node* current = root->next;
if(pos <= size-1) {
for(int i = 0; i < pos; i++) {
current = current->next;
}
} else {
cout << "ERROR: Out of bounds.";
current = NULL;
}
return current->value;
}
template <typename T>
void LinkedList<T>::pop_back() {
deleteNode(size-1);
}
template <typename T>
void LinkedList<T>::pop_front() {
deleteNode(0);
}
template <typename T>
void LinkedList<T>::push_back(T val) {
insertNode(size, val);
}
template <typename T>
void LinkedList<T>::push_front(T val) {
insertNode(0, val);
}
#endif
//test driver
int main() {
IntList i_list;
int n;
cout << "Appending node: value = " << 0 << endl;
i_list.appendNode(0);
i_list.print();
cout << endl;
n = 5;
cout << "Inserting nodes (at their values). Node values = { ";
for(int i = 0; i < n; i++) {
cout << i << " ";
i_list.insertNode(i,i);
}
cout << "}" << endl;
i_list.print();
cout << endl;
cout << "Deleting node at position: " << i_list.getSize()-1 << endl;
i_list.deleteNode(i_list.getSize()-1);
i_list.print();
cout << endl;
cout << "Searching for value: " << 3 << endl;
cout << "Found at: " << i_list.searchNode(3) << endl;
cout << endl;
i_list.print();
cout << "List size: " << i_list.getSize() << endl;
cout << endl;
n = 3;
cout << "Calling node at list[" << n << "]: " << i_list[n] << endl;
cout << endl;
i_list.print();
cout << "Deleting node from back position." << endl;
i_list.pop_back();
i_list.print();
cout << endl;
i_list.print();
cout << "Deleting node from front position." << endl;
i_list.pop_front();
i_list.print();
cout << endl;
n = 9;
i_list.print();
cout << "Adding node (value = " << n << ") to back position." << endl;
i_list.push_back(n);
i_list.print();
cout << endl;
n = 8;
i_list.print();
cout << "Adding node (value = " << n << ") to front position." << endl;
i_list.push_front(n);
i_list.print();
cout << endl;
i_list.print();
cout << "Copying list to new list." << endl;
IntList t_list(i_list);
cout << endl;
cout << "List copy:" << endl;
t_list.print();
cout << endl;
/*
* Showing functionality transfers over to LinkedList template class
* generally, for primitive data types (lacks absolutely generality
* for data which can't be passed directly to cout).
*/
cout << "List functionality transfers generally to LinkedList class:" << endl;
LinkedList<int> int_list;
LinkedList<double> double_list;
LinkedList<char> char_list;
cout << "Appending nodes:" << endl;
n = 5;
for(int i = 0; i < n; i++){
int_list.appendNode(i);
}
int_list.print();
n = 5;
for(int i = 0; i < n; i++){
double_list.appendNode(i+0.1);
}
double_list.print();
n = 5;
for(int i = 0; i < n; i++){
char_list.appendNode('A' + i);
}
char_list.print();
cout << "Removing nodes:" << endl;
n = 5;
for(int i = 0; i < n; i++){
int_list.pop_back();
}
int_list.print();
n = 5;
for(int i = 0; i < n; i++){
double_list.pop_back();
}
double_list.print();
n = 5;
for(int i = 0; i < n; i++){
char_list.pop_back();
}
char_list.print();
return 0;
}
EDIT: I've revised my algorithm, and I believe it works algorithmically, but functionally it may be doing something which is causing a memory issue. I'm not sure as to why that may be, but here it is:
void IntList::reverse() {
IntList tmp(*this);
int list_size = size;
for(int i = 0; i < list_size; i++) {
this->insertNode(i, tmp[tmp.getSize()-1]);
this->pop_back();
tmp.pop_back();
}
}
In fact, if my [] operator overload were functioning within this method (which for some reason it is not?) I could do away with the tmp list and just reference the last value in the list directly as this[size-1].
What is the issue here?
Your problem is that after the reverse() the last element in your list will point to the root element instead of pointing to null. One solution could be an explicit check for that condition so you would get:
void IntList::reverse(Node* t_node) {
if(t_node == NULL) {
reverse(root);
return;
}
if(t_node->next == NULL) {
cout << "In (swapping): " << t_node->value << endl;
root->next = t_node;
} else {
cout << "In: " << t_node->value << endl;
Node* tmp = t_node->next;
reverse(t_node->next);
// If this node was the first node it will now be the last
if (t_node == root) {
tmp->next = NULL;
} else {
tmp->next = t_node;
}
}
}
That doesn't work if it should be possible to reverse a subpart of the list though. If that is something you need, then you probably need to use a helper function which handles all elements but the first one.
Suppose we have the IntList {1,2,3}, which actually has this form:
0 -> 1 -> 2 -> 3
Then we call reverse(root), so that t_node has the same value as root (and therefore points to (0)).
Node* tmp = t_node->next;
So tmp points to (1).
reverse(t_node->next);
Suppose this works, and the list is now 0->1->3->2
tmp->next = t_node;
So now 1->0. The list is now a loop, and the other nodes have been lost.
It is not clear what you intended this function to do, but you must have misunderstood something.
EDIT: You are attempting a high-level solution when you do not understand the low-level mechanics.
Your copy constructor:
IntList(const IntList& list) { this->root = list.root; this->size = list.size; }
performs what we call a "shallow copy"; it copies the pointer members, but not the things they point to. If you have a list A that looks like this:
0->1->2->3
and then call IntList B(A);, you'll get something that looks like this:
0
|
v
0->1->2->3
If you then call A.pop_back() and B.pop_back(), what do you think will happen?
And more to the point, what are you trying to do? Do you want to know how to write a recursive function, or is that no longer necessary?