C++ Stack values not working correctly - c++

I am trying to implement a system that would perform something like say the user enters 4 5 +. It would add the 4 and 5 (9) and push 9 into the stack.
For some reason the values in the stack are huge numbers so I believe it has something to do with a pointer or accessing a wrong field but I'm pulling my hair out trying to find the error. Any help on what I'm doing wrong?
#include "stack.h"
int main()
{
stack Test;
bool stop = false;
float runningtotal = 0;
while (stop == false)
{
char input;
cin >> input;
if (input == '+') {
int value1 = Test.top();
Test.pop();
int value2 = Test.top();
Test.pop();
cout << value1+value2 << endl;
Test.push(value1 + value2);
}
cout << Test.top();
std::getchar();
std::getchar();
}
And the implementation of stack
#include "stack.h"
stack::stack()
{
maxsize = MaxSize;
currentsize = 0;
sptr = new StackElement[maxsize];
}
stack::~stack()
{
delete [] sptr;
}
void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++;
} else {
cout << "Stack is full ;-;";
}
}
void stack::pop()
{
if (currentsize == 0) {
cout << "Empty stack? ;-;";
return;
}
currentsize--;
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);
}
}

void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++; //<--- incrementing after so nothing in [currentsize] now
} else {
cout << "Stack is full ;-;";
}
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);// should use currentsize-1
// latest filled cell
// since its pushing from top
}
}
Be sure to convert those ascii codes(49 ish) from keyboard to integer type explanations.
input - 48 should do it.

Related

How to initialize the dynamic array of struct in the constructor?

This is a Stack class based on a dynamic array of struct for Depth First Search (DFS). The program is not able to run whenever it encounters the function, push(), which shows that the array is not successfully initialized in the constructor.
I have tried to look for the error and even changing the dynamic array of struct into parallel arrays but it still does not work. I apologize if the problem seems to be too simple to be solved as I do not have a strong foundation in C++.
#include <iostream>
#include <iomanip>
#ifndef HEADER_H
#define HEADER_H
using namespace std;
struct Value
{
int row; // row number of position
int col; // column number of position
//operator int() const { return row; }
};
class ArrayStack
{
public:
int top;
Value* array;
ArrayStack();
bool isEmpty();
bool isFull();
void push(int r, int c);
void pop();
int poprowvalue(int value);
int popcolvalue(int value);
int peekrow(int pos);
int peekcol(int pos);
int count();
void change(int pos, int value1, int value2);
void display();
void resize();
private:
int size;
};
ArrayStack::ArrayStack()
{
//Initialize all variablies
top = -1;
size = 10;
Value * array = new Value[size];
for (int i = 0; i < size; i++)
{
array[i].row = 0;
array[i].col = 0;
}
}
bool ArrayStack::isEmpty()
{
if (top == -1)
return true;
else
return false;
}
bool ArrayStack::isFull()
{
if (top == size - 1)
return true;
else
return false;
}
void ArrayStack::resize()
{
if (isFull())
size *= 2;
else if (top == size / 4)
size /= 2;
}
void ArrayStack::push(int r, int c)
{
if (isEmpty() == false)
resize();
array[top + 1].row = r;
array[top + 1].col = c;
top++;
}
void ArrayStack::pop()
{
int value;
if (isEmpty())
{
cout << "Stack underflow" << endl;
}
else
{
poprowvalue(array[top].row);
popcolvalue(array[top].col);
array[top].row = 0;
array[top].col = 0;
top--;
}
}
int ArrayStack::poprowvalue(int v)
{
return v;
}
int ArrayStack::popcolvalue(int v)
{
return v;
}
int ArrayStack::peekrow(int pos)
{
if (isEmpty())
cout << "Stack underflow" << endl;
else
return array[pos].row;
}
int ArrayStack::peekcol(int pos)
{
if (isEmpty())
cout << "Stack underflow" << endl;
else
return array[pos].col;
}
int ArrayStack::count()
{
return (top + 1);
}
void ArrayStack::change(int pos, int value1, int value2)
{
if (isEmpty())
cout << "Stack underflow" << endl;
else
{
array[pos].row = value1;
array[pos].col = value2;
}
}
void ArrayStack::display()
{
for (int i = size - 1; i > -1; i--)
{
cout << array[i].row << " " << array[i].col << endl;
}
}
#endif
I expect it to run well but an exception is always thrown on line 80, which is as follows:
Exception thrown at 0x00007FF6A160487C in Assignment1.exe: 0xC0000005: Access violation writing location 0x0000000000000000.
The problem is this line right here:
Value * array = new Value[size];
This declares a new array variable. You are allocating that array instead, and not your member variable array.
The answer is simple, just change it to this instead:
array = new Value[size];

realloc(): invalid old size even when malloc() is used to allocate memory

I am trying to implement a Dynamic Stack in c++.
i have 3 members in class stack
1.cap is the capacity.
2.top- points to top of stack
3. arr- pointer to an integer.
in the class constrcutor I am allocating memory to stack(malloc).
later in the meminc() I am trying to realloc the memory.
I have written a function meminc() to realloc the memory but i get this invalid old size error.
It would be helpful if you let me know what is wrong in this code. I will also appreciate any advice given to me.
Thank you.
#include <iostream>
using namespace std;
#define MAXSIZE 5
class stack {
int cap;
int top;
int *arr;
public:
stack();
bool push(int x);
bool full();
bool pop();
bool empty();
bool meminc();
};
stack::stack()
{
cap = MAXSIZE;
arr = (int *)malloc(sizeof(int)*MAXSIZE);
top = -1;
}
bool stack::meminc()
{
cap = 2 * cap;
cout << cap << endl;
this->arr = (int *)realloc(arr, sizeof(int)*cap);
return(arr ? true : false);
}
bool stack::push(int x)
{
if (full())
{
bool x = meminc();
if (x)
cout << "Memory increased" << endl;
else
return false;
}
arr[top++] = x;
return true;
}
bool stack::full()
{
return(top == MAXSIZE - 1 ? true : false);
}
bool stack::pop()
{
if (empty())
return false;
else
{
top--;
return true;
}
}
bool stack::empty()
{
return(top == -1 ? true : false);
}
int main()
{
stack s;
char y = 'y';
int choice, x;
bool check;
while (y == 'y' || y == 'Y')
{
cout << " 1.push\n 2.pop\n" << endl;
cin >> choice;
switch (choice)
{
case 1: cout << "Enter data?" << endl;
cin >> x;
check = s.push(x);
cout << (check ? " push complete\n" : " push failed\n");
break;
case 2: check = s.pop();
cout << (check ? " pop complete\n" : " pop failed\n");
break;
default: cout << "ERROR";
}
}
}
To add to john's answer,
the way you're using realloc() is ... flawed.
bool stack::meminc()
{
cap = 2 * cap;
cout << cap << endl;
this->arr = (int *)realloc(arr, sizeof(int)*cap);
return(arr ? true : false);
}
If realloc() fails it will return nullptr and the only pointer (arr) to the original memory region will be gone. Also, instead of return(arr ? true : false); you should simply use return arr != nullptr;.
The righttm way to use realloc():
bool stack::meminc()
{
int *temp = (int*) realloc(arr, sizeof(*temp) * cap * 2);
if(!temp)
return false;
cap *= 2;
arr = temp;
return true;
}
Also, where is your copy-ctor, assignment operator and d-tor?
The full function is incorrect. It should be
bool stack::full()
{
return(top == cap - 1 ? true : false);
}
or more simply and with added const
bool stack::full() const
{
return top == cap - 1;
}
Also you are using the top variable incorrectly. Since top starts at -1 you should increment top before you set the value, not afterwards
arr[++top] = x;
Not a bug, but from a design perpective meminc should be a private function.

C++: How to check whether same number of letters 'a' and 'b' are present in a string using a stack

I need to check if number of letters "a" is equal to number of letters "b" using stack.
So i understand logic of this task, but my code doesn't work.
Logic:
If current letter == to letter in stack (s.pop()) or stack is empty then push into stack
else pop from stack
after end of cycle check size of stack. If it is empty so number of letters is equl, else not
I already have class stack
#include <string>
#include <iostream>
#include <cstdlib> // для system
using namespace std;
class stack {
public:
stack() {
ptr = 0;
}
~stack() {}
bool push(int val) {
if (ptr >= MAXSIZE) return false;
body[ptr++] = val; return true;
}
bool pop(int *val) {
if (ptr == 0) return false;
*val = body[--ptr]; return true;
}
bool empty() {
return ptr == 0;
}
private:
enum { MAXSIZE = 100 };
int body[MAXSIZE];
int ptr; // указатель на последний элемент
};
int main()
{
stack s;
std::string str;
std::cout << "Enter your ab string ";
getline(std::cin, str);
for (int c : str) {
if (c == s.pop(&c) || s.empty()) {
s.push(c);
}
else {
s.pop(&c);
}
}
if (s.empty()) {
cout << "YES\n";
system("pause");
return 0;
}
else {
cout << "NO\n";
system("pause");
}
}
result for abab, aabb, ab 'YES'
for aaabb, aba 'NO'
You need a method to look at current value on top of stack without popping it:
class stack {
...
int top() { // never use on an empty stack
return body[ptr-1];
}
...
};
That way you can write:
for (int c : str) {
// short circuit evaluation ensures that top is never called on an empty stack
if (s.empty() || (c == s.top()) {
s.push(c);
}
else {
s.pop(&c);
}
If you cannot, you must push back the popped value if it should not have been popped:
for (int c : str) {
int d;
if (! s.pop(&d)) { // s was empty
s.push(c);
}
else if (c == d) {
s.push(d); // should not have been popped
s.push(c);
}
}
You can push everytime you see a.
for (int c = 0; c < str.size() ; ++c) {
if (str[c] == 'a') s.push('a');
}
if ((s.size() * 2) == str.size()) cout << "YES\n"; else cout << "NO\n";
stack::size can be implemented this way:
int stack::size() {
return ptr;
}

Creating a Reverse Polish calculator in C++

Assignment: For this assignment, you are to write a program, which will calculate the results of Reverse Polish expressions that are provided by the user.
You must handle the following situations (errors):
Too many operators (+ - / *)
Too many operands (doubles)
Division by zero
The program will take in a Polish expression that separates the operators and operands by a single space, and terminates the expression with an equals sign.
The program will continue to take and evaluate expressions until the user enters a zero (0) on a line by itself followed by a new line.
Problem 1: I am having a problem with telling the user that there are too many operators and operands. I tried to code it but I have no
idea where to begin with this.
Problem 2: I want the program to end when the user inputs 0, but it is not doing anything when I do it in my program.
#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>
using namespace std;
class Node
{
double data;
Node *top;
Node *ptr;
public:
Node()
{
top = NULL;
ptr = NULL;
}
bool isEmpty()
{
return top == 0;
}
void pushValue(double val)
{
Node *next = new Node;
next->data = val;
next->ptr = top;
top = next;
}
double popVal()
{
if (isEmpty())
{
cout << "Error: Too many operators" << endl;
}
else
{
Node *next = top->ptr;
double ret = top->data;
delete top;
top = next;
return ret;
}
}
//Displays the answer of the equation
void print()
{
cout << "= " << top->data << endl;
}
};
bool isOperator(const string& input)
{
string ops[] = { "+", "-", "*", "/" };
for (int i = 0; i < 4; i++)
{
if (input == ops[i])
{
return true;
}
}
return false;
}
//This function tells the operators what to do with the values.
void performOp(const string& input, Node& stack)
{
double Val1, Val2;
int errorCheck = 0;
Val1 = stack.popVal();
Val2 = stack.popVal();
if (input == "+")
{
stack.pushValue(Val1 + Val2);
}
else if (input == "-")
{
stack.pushValue(Val1 - Val2);
}
else if (input == "*")
{
stack.pushValue(Val1 * Val2);
}
else if (input == "/" && Val2 != 0)
{
stack.pushValue(Val1 / Val2);
}
if (input == "/" && Val2 == 0)
{
cout << "Error: Division by zero" << endl;
errorCheck = 1;
}
if (errorCheck == 0)
{
stack.print();
}
}
int main()
{
cout << "Reverse Polish Notation Calculator!" << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "Enter your values followed by your operators(Enter 0 to exit)" << endl;
string input;
Node stack;
//Checks the user's input to see which function to use.
while (true)
{
cin >> input;
double num;
if (stringstream(input) >> num)
{
stack.pushValue(num);
}
else if (isOperator(input))
{
performOp(input, stack);
}
else if (input == "0")
{
return 0;
}
}
}

C++ Strange behavior in my own stack class

Here is a program with my Stack class and some another functions.
ReadTheFile() - reads numbers, which are stored in num_file.txt, and returns a vector with those numbers.
IntervalCheck() - adds the numbers of the specific range from input vector and returns a vector with those numbers only.
VecToMyStack() - adds numbers from a vector to a stack.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#define STACK_EMPTY -1
#define OUT_OF_STACK -2
using namespace std;
template <class T>
class Stack {
private:
struct Node{
T element;
Node *prevElement;
};
size_t NumberOfElements;
Node *tempAdr;
Node *topElement;
Node *newElement;
Node *erasedElement;
public:
Stack(){
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
}
~Stack(){
cout << endl << "I'm a destructor";
while(NumberOfElements !=0 ){
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
}
delete topElement;
}
void push(T input_element){
tempAdr = topElement;
topElement = new Node;
topElement->element = input_element;
topElement->prevElement = tempAdr;
NumberOfElements++;
}
void pop(){
if (NumberOfElements == 0) throw STACK_EMPTY;
else {
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
}
}
T top(){
return NumberOfElements != 0 ? topElement->element : throw STACK_EMPTY;
}
void insert(size_t position, T input_element){
if (position >= NumberOfElements) throw OUT_OF_STACK;
else {
tempAdr = topElement;
for (size_t i = 0; i < position; i++){
tempAdr = tempAdr->prevElement;
}
newElement = new Node;
newElement->element = input_element;
newElement->prevElement = tempAdr->prevElement;
tempAdr->prevElement = newElement;
NumberOfElements++;
}
}
void erase(size_t position){
if (position >= (NumberOfElements-1)) throw OUT_OF_STACK;
else{
tempAdr = topElement;
for (size_t i = 0; i < position; i++){
tempAdr = tempAdr->prevElement;
}
erasedElement = tempAdr->prevElement;
tempAdr->prevElement = tempAdr->prevElement->prevElement;
delete erasedElement;
NumberOfElements--;
}
}
void print(){
if (NumberOfElements != 0){
tempAdr = topElement;
for (size_t i = 0; i < NumberOfElements; i++){
cout << tempAdr->element << " ";
tempAdr = tempAdr->prevElement;
}
}
}
size_t size() { return NumberOfElements; }
};
vector<int> ReadTheFile() {
vector<int> vec_from_file;
int buffer;
ifstream basefile;
basefile.open("num_file.txt", ios::in);
if (basefile.is_open()) {
do {
if (basefile >> buffer)
vec_from_file.push_back(buffer);
else {
basefile.clear();
basefile.ignore(1, ' ');
}
} while (!basefile.eof());
basefile.close();
}
else cout << "Unable to open file" << endl;
return vec_from_file;
}
vector<int> IntervalCheck(vector<int> vec_for_check){
vector<int> out_vec;
if (vec_for_check.empty()) cout << "There is nothing to check";
else {
int begin_int, end_int;
do {
cin.clear();
cin.sync();
cout << "Input the first and the last value of the interval: ";
cin >> begin_int >> end_int;
} while (cin.fail());
for (auto &k : vec_for_check)
if (k > begin_int && k < end_int)
out_vec.push_back(k);
}
return out_vec;
}
Stack<int> VecToMyStack(vector<int> input_vec){
Stack<int> output_st;
if (input_vec.empty()) {
cout << "the end";
}
else {
for (auto &k : input_vec){
output_st.push(k);
}
}
return output_st;
}
int main(){
int choice = 0;
do {
cin.clear();
cin.sync();
VecToMyStack(IntervalCheck(ReadTheFile())).print();
cout << "Would you like to measure another interval? 1-yes 2-no";
cin >> choice;
} while (choice == 1);
system("pause");
return 0;
}
The whole program should push numbers from the file to a stack, and print this stack, using the print() method of the class. For example, if there is a num_file.txt with
0 1 2 3 4 5 6 7 8 9 10
inside, the program is expected to work in that way:
Input the first and the last value of the interval: 0 10 /* zero and
ten are inputed by the user*/
1 2 3 4 5 6 7 8 9
Would you like to measure another interval? 1-yes 2-no
But when the VecToMyStack(IntervalCheck(ReadTheFile())).print(); line is executed, I'm getting
Access violation reading location 0xFEEEFEEE.
exception. It seemes like the destructor of my Stack class is running before the print()function. Why does that happen? Is there something special what I should add to my Stack class or to VecToMyStack() function?
Finally, after a couple of hours of research, I've got that missing peace of code:
Stack(const Stack &object){
tempAdr = object.topElement;
T * tempMas=new T[object.NumberOfElements];
for (size_t i = 0; i < object.NumberOfElements; i++){
tempMas[i] = tempAdr->element;
tempAdr = tempAdr->prevElement;
}
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
for (int i = object.NumberOfElements - 1; i >= 0; i--){
push(tempMas[i]);
}
delete[] tempMas;
}
I know that my Stack class is still uncomplete without the overloaded assignment operator, but at least my code runs fine.