Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm basically trying to reverse the stack by passing it to a function. However, the program just crashes when I run it and I can find no logical errors as I have even overloaded the assignment operator to deal with pointer data members.
#include <iostream>
using namespace std;
/***************************************************************************/
class AStack {
public:
AStack();
AStack(int);
~AStack();
AStack operator = (AStack s);
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
int capacity;
int* a;
int index = -1; // Index of the top most element
};
AStack::AStack() {
a = new int[25];
capacity = 25;
}
AStack::AStack(int size) {
a = new int[size];
capacity = size;
}
AStack::~AStack() {
delete[] a;
}
AStack AStack::operator = (AStack s) {
capacity = s.capacity;
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}
void AStack::push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int AStack::pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int AStack::top() {
if (index == -1) {
cout << "\n\nNo elements in the Stack\n\n";
return -1;
}
return a[index];
}
bool AStack::isEmpty() {
return (index == -1);
}
void AStack::flush() {
if (index == -1) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
while (index != -1) {
cout << a[index--] << " ";
}
cout << endl << endl;
}
/***************************************************************************/
void reverseStack(AStack& s1) {
AStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
/***************************************************************************/
int main() {
AStack s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
reverseStack(s1);
cout << "\n\nFlushing s1:\n";
s1.flush();
system("pause");
return 0;
}
You are not providing a copy-constructor, and your assignment operator takes the argument by value. The statement s1 = s2 creates a copy of s2 by calling the implicitly defined copy constructor that copies the pointer, then assigns to s1. At the end of the expression the copy is destroyed, calling delete [] on the pointer. At the end of the function the destructor for s2 runs and attempts to delete [] the same pointer again.
You need to provide a copy constructor that does the right thing.
Related
I am using a stack to reverse a given string. Each character of the string is pushed onto the stack, then they are popped back into a new string which is returned to main. But for some reason, the value of stack[top] in the stack class code never seems to change.
#include <iostream>
#include <string>
using namespace std;
const int size = 4;
class Stack{
private:
//char stack[size];
char* stack;
int top;
public:
Stack()
{
top = -1;
}
void Init_Size(int size)
{
stack = new char[size];
}
bool isFull()
{
if (top == (size - 1))
return true;
return false;
}
bool isEmpty()
{
if (top == -1)
return true;
return false;
}
void push(char c)
{
if (isFull())
{
cout << "STACK IS FULL" << endl;
return;
}
top++;
stack[top] == c;
cout << "PUSHED" << stack[top] << " ONTO STACK" << endl;
}
char pop()
{
if (isEmpty())
{
cout << "STACK IS EMPTY" << endl;
return '/'; //error
}
char temp = stack[top];
cout << stack[top] << endl;
top--;
cout << "POPPED" << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}
I tried using a normal array for the stack instead of a dynamic one, but no change, however, I did notice that the value of the stack array can be changed but only in the void Init_Size(int size) function and I'm not sure why.
I see a number of errors in your program:
size: You have a global constant size set to 4 which is used in your isFull function, independent of the local size parameter used in Init_Size. Make this a class variable instead.
Your push function has the line stack[top] == c with two = instead of one - thus comparing the value against stack instead of setting stack. Turn on warnings and you should have found this yourself
ReverseString assigns directly to result[i] without ever setting the size of result. You could have used the str variable instead, since that is just a copy.
Those three are the major errors that need fixing for your program to work, but there are several minor issues as well, like using namespace std; thereby making size ambigious, making unnecessary copies of strings, using new and c-style arrays etc.
You have a problem with creation and deletion of your arrays here in your program as well as a few small misshaps on the way.
Fix:
#include <iostream>
#include <string>
using namespace std;
class Stack{
private:
//char stack[size];
int size;
char* stack;
public:
Stack() : size(0), stack(NULL) {}
~Stack() {if (stack != NULL) delete stack;} //THIS IS NEEDED HERE
void Init_Size(int newSize)
{
if (stack != NULL) delete stack;
size = newSize;
stack = new char[newSize]; //CREATES DYNAMIC ARRAY WHICH YOU NEED TO REMEMBER TO REMOVE OTHERWISE MEMORY LEAK
}
void push(char c) //adds
{
//adding here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL) Init_Size(1);
char* newArray = new char[size+1];
for(int i = 0; i < size; i++)
{
newArray[i] = stack[i];
}
newArray[size] = c;
delete stack;
stack = newArray;
size++;
cout << "PUSHED " << stack[size-1] << " ONTO STACK" << endl;
}
char pop()
{
//removing here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL)
{
cout << "Stack empty" << endl;
return '\0';
}
char* newArray = new char[size-1];
for(int i = 0; i < size-1; i++)
{
newArray[i] = stack[i];
}
char temp = stack[size-1];
delete stack;
stack = newArray;
size--;
cout << "POPPED " << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}
The error pointed out was at the end just before the };
I don't even see any function overloading or any mismatching parameters.
This is simply a queue data structure that I was trying to implement. But unfortunately, I got these compiler errors. I am sharing the whole code so that easily one can help, since neither I have any function overloaded, not even the constructor nor I have used mismatched parameter. I guess image will help out to see the error.
template<class T>
class Queue {
private:
T* box;
int front;
int rear;
int number_Of_Elements;
int capacity;
public:
Queue(int cap = 0) {
capacity = cap;
front = rear = 0;
number_Of_Elements = 0;
}
bool Empty() {
return size == 0;
}
int next(int i) {
return ((i + 1) % capacity);
}
int previous(int i) {
return ((i + (capacity - 1)) % capacity);
}
int get_Number_Of_Elements() {
return number_Of_Elements;
}
void double_Box() {
T* temp = new T[capacity * 2];
for (int i = 0; i < size; i++) {
temp[i] = box[i];
}
front = 0;
rear = number_Of_Elements;
delete[] box;
box = temp;
}
const T& peek() {
T a = box[front];
front = next(front);
return a;
}
void printQueue() {
cout << "Front is at : " << front << endl;
cout << "Rear is at : " << rear << endl;
for (int i = 0; i < number_Of_Elements; i++) {
cout << "box[" << i << "]" << " : " << box[i] << endl;
}
cout << "------------------------" << endl;
}
void Enqueue(const T& data);
const T& Dequeue();
~Queue() {
delete[] box;
}
// error is exactly here -> };
};
Your problem is with size. You haven't declared it.
I think the compiler tries to use some global function called size instead but it fails.
After declaring the capacity member var, add
size_t size;
Demo
The answer is, there were issues, like some of the variables were not even initialized but they were being used, and the memory calculation errors were there. Like a pointer pointing somewhere in memory that actually does not exist.
I am required to implement a dynamic array that adjusts, dynamically, in accordance with the number of value (temperatures) that are input into the code. I have written the majority of the code for this to be possible, however I have run into a bug and for the life of me, have been unable to locate the issue.
The program is supposed to output the values of temp_a, make temp_b = temp_a, output the value of temp_b, and then clear the value of temp_a, and finally output the values of temp_b once more.
However, when I compile the program, it outputs that the list is full and cannot add any more values, meaning there is a logic error somewhere in the code.
Please forgive me for the lengthy code, as soon as I can locate the error, the code shall be separated into multiple compilations.
#include <iostream>
using namespace std;
class TemperatureList {
private:
int* temp; // pointer to dynamic array
short current_size; // current number of elements
short max_size; // max number of elements allowed in this list
public:
// Overloading assignment operator
void operator =(const TemperatureList& another_list);
// === Constructors ===
// Default constructor
TemperatureList();
// Constructor that accepts an integer parameter that specifies the max length of the list
TemperatureList(int max);
// Copy constructor that accepts another List as parameter
TemperatureList(const TemperatureList& another_list);
// Destructor
~TemperatureList();
// === Modifier functions ===
// add new_value to end of list if there is still space
void add_temperature(int new_value);
// === Accessor functions ===
// return current current_size of the list
short get_current_size();
// === Other functions ===
// return the last element, or 0 if the list is empty, with a warning output
int get_last();
// return element at the position-th position, or 0 if the list is empty, with a warning output
int get_temp(short position);
// returns if current_size == 0
bool set_temp(short position, int value);
// returns if current_size == 0
bool empty();
// returns if current_size == max_size
bool full();
// Output list separated by commas
friend ostream& operator <<(ostream& outs, const TemperatureList& list);
};
int main() {
TemperatureList temp_a;
temp_a.add_temperature(23.5);
temp_a.add_temperature(24.6);
cout << temp_a;
TemperatureList temp_b = temp_a;
cout << temp_b;
temp_a = TemperatureList();
cout << "Now there's no temperatures in a.\n";
cout << temp_a;
cout << "How about temperatures in b?\n";
cout << temp_b;
return 0;
}
void TemperatureList::operator =(const TemperatureList& another_list) {
delete[] temp;
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::TemperatureList() {
current_size = 0;
max_size = 0;
temp = NULL;
}
TemperatureList::TemperatureList(int max) : max_size(max) {
current_size = 0;
temp = new int[max];
}
TemperatureList::TemperatureList(const TemperatureList& another_list) {
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::~TemperatureList() {
//cout << "== I am in destructor ==\n";
delete[] temp;
}
void TemperatureList::add_temperature(int new_value) {
if (current_size < max_size) {
temp[current_size] = new_value;
current_size++;
}
else {
cout << "Cannot add value to the list. It is full.\n";
}
}
int TemperatureList::get_last() {
if (empty()) {
cout << "The list is empty\n";
return 0;
}
else {
return temp[current_size - 1];
}
}
int TemperatureList::get_temp(short position) {
if (current_size >= position) {
return temp[position - 1];
}
else {
cout << "There is no temperature\n";
return 0;
}
}
bool TemperatureList::set_temp(short position, int value) {
if (current_size >= position) {
temp[position - 1] = value;
return true;
}
else {
return false;
}
}
short TemperatureList::get_current_size() {
return current_size;
}
bool TemperatureList::empty() {
return (current_size == 0);
}
bool TemperatureList::full() {
return (current_size == max_size);
}
ostream& operator <<(ostream& outs, const TemperatureList& list) {
int i;
for (i = 0; i < (list.current_size - 1); i++) {
outs << list.temp[i] << ",";
}
outs << list.temp[i];
return outs;
}
The logic error seems to stem from the fact that you initialize your current_size and max_size to zero. So, unless your run the overloaded constructor (wherein you’re set the max_size), every call to addTemperature() is going to fail the (current_size < max_size) check because they are both equal to zero.
Why am I getting these errors?
invalid conversion from 'Queue*' to 'int'
conversion from 'Stack*' to non-scalar type 'Stack' requested
I've tried modifying Queue & Stack, but to no avail. I am doing an assignment that implements Stack using Queues & implements Queue using Stacks.
Stack.h
#ifndef STACK_H_
#define STACK_H_
#include <iostream>
using namespace std;
class Stack {
int size;
int capacity; // for dynamic allocated array
int stackTop;
int *arr;
public:
Stack();
void push(int val);
int pop();
bool isFull();
bool empty();
int top();
int peek(int pos);
int resize();
};
bool Stack::empty(){
return size == 0;
}
bool Stack::isFull(){
return size == capacity;
}
void Stack::push(int val){
if(isFull())
resize();
arr[++stackTop] = val;
size++;
}
int Stack::pop(){
if(empty())
return true;
return arr[stackTop--];
}
int Stack::peek(int pos){
if(pos > stackTop || pos < 0){
cout << "Empty Stack";
return 0;
}
else{
return arr[size - pos - 1];
}
}
int Stack::top(){
if(empty()){
return true;
}
return *arr;
}
int Stack::resize(){
return size;
}
Queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
#include <iostream>
using namespace std;
class Queue{
int f, r, *arr, size, capacity;
public:
Queue(): f(-1), r(-1), arr(nullptr), size(0), capacity(0){}
Queue(int cap): f(-1), r(-1), arr(new int[cap]), size(0), capacity(cap){}
~Queue(){delete []arr;}
Queue(const Queue ©){
f = copy.f;
r = copy.r;
arr = copy.arr;
size = copy.size;
capacity = copy.capacity;
}
Queue(Queue&& move){
f = move.f;
r = move.r;
arr = move.arr;
size = move.size;
capacity = move.capacity;
move.f = -1;
move.r = -1;
move.arr = nullptr;
move.size = 0;
move.capacity = 0;
}
Queue& operator=(const Queue& copyA){
if(this == ©A){
return *this;
}
f = copyA.f;
r = copyA.r;
arr = copyA.arr;
size = copyA.size;
capacity = copyA.capacity;
}
Queue& operator=(const Queue&& moveA){
if(this == &moveA){
return *this;
}
f = moveA.f;
r = moveA.r;
arr = moveA.arr;
size = moveA.size;
capacity = moveA.capacity;
// moveA.f = -1;
// moveA.r = -1;
// moveA.arr = nullptr;
// moveA.size = 0;
// moveA.capacity = 0;
return *this;
}
void enqueue(int x){
if(!full())
resize();
arr[f + r] = x;
size++;
}
int dequeue(){
if(!empty()){
return arr[++f];
} return -99999;
}
bool empty(){
return size == 0;
}
bool full(){
return size == capacity;
}
int peek(int pos){
if(pos > capacity || pos < 0){
cout << "Empty Queue";
return 0;
}else{
return arr[size - pos - 1];
}
}
void resize(){
int newSize = this->size * 2;
Queue *temp = new Queue[newSize];
int count = 0;
for(int i = 0; i < count; ++i){
int index = (f + 1) % size;
temp[i] = arr[index];
}
}
};
main.cpp
#include <iostream>
#include "Queue.h"
#include "Stack.h"
using namespace std;
int main(){
Queue q = new Queue(); //invalid conversion from 'Queue*' to 'int' [-fpermissive]
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
cout << q.dequeue() << '\n';
cout << q.dequeue() << '\n';
cout << q.dequeue() << '\n';
cout << endl;
Stack s = new Stack(); //conversion from 'Stack*' to non-scalar type 'Stack' requested
s.push(1);
s.push(2);
s.push(3);
cout << "current size: " << s.resize() << endl;
cout << s.top() << endl;
s.pop();
cout << s.top() << endl;
s.pop();
cout << s.top() << endl;
cout << "current size: " << s.resize() << endl;
return 0;
}
main.cpp:8:12: error: invalid conversion from 'Queue*' to 'int' [-fpermissive]
Queue q = new Queue();
^~~~~~~~~~~
20:12: error: conversion from 'Stack*' to non-scalar type 'Stack' requested
Stack s = new Stack();
^~~~~~~~~~~
The error would come from the line in main.cpp:
Queue q = new Queue();
The new keyword creates a pointer to the class object, so the correct syntax would be:
Queue *q = new Queue();
This is also shown in the C++ tutorial documentation here: http://www.cplusplus.com/doc/tutorial/classes/#pointers_to_classes
Same thing for the Stack pointer variable.
Note that this also means the syntax for using the objects must also change.
Instead of:
s.pop();
You will need to modify this to either:
(*s).pop();
or
s->pop();
Hope this helps!
When you instantiate with the new keyword, you create a pointer to the object. Thus, the correct instantiation would be the following:
Queue * q = new Queue();
Stack * s = new Stack();
When x is a pointer, then the value of x is the address of an object and *x is the actual object.
I don't agree with the answers advising getting it to work with new. It's unnecessary.
Instead of using new just leave them as normal stack variables. Then you're not burdened with having to later delete and you don't have to replace all instances of . to ->.
Simply
Queue q;
Stack s;
And your program remains otherwise unchanged.
(Do you perhaps come from a c# background? new is necessary there, but most often not necessary with C++)
I have a Stack class defined. Now, I want to reverse the stack by passing it to a reverseStack function. I want to know what happens in various scenarios. And finally, what is the best way to do it.
STACK IMPLEMENTATION:
class Stack {
public:
Stack() {
a = new int[25];
capacity = 25;
}
Stack(int size) {
a = new int[size];
capacity = size;
}
~Stack() {
delete[] a;
}
void push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int top();
bool isEmpty();
void flush();
private:
int capacity ;
int* a;
int index = -1; // Index of the top most element
};
SCENARIO-1:
void reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
s = s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
reverseStack(s);
return 0;
}
SCENARIO-2:
Stack reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
return s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
s = reverseStack(s);
return 0;
}
In Scenario-1 (which fails), what does s = s2 inside the function mean? I think it's a member-wise copy. Would it have worked if the data members didn't involve a pointer (int* a)?
Scenario-2 fails as well for the same reason. How do I accomplish what I'm trying to?
Should I have a copy-constructor (and how do I implement it?). How about overloading the assignment operator (again, how do I implement?) ?
I tried to implement it this way:
Stack Stack::operator = (Stack s) {
capacity = s.capacity;
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}
About the scenarios, the best one is the second because of the return value optimization, i.e: The compiler will probably optimize away the copy of the return value and prevent an unnecessary copy.
Now, you are using dynamic memory in your class, which means the default implementation of the copy constructor and assignment operator will not work for you.
Copy constructor, it's almost the same as the assignment operator you write
Stack::Stack(const Stack& s)
: capacity(s.capacity)
, a(new int[capacity])
, index(s.index)
{ // std::copy is just a shortcut, what you're doing is fine too
std::copy(s.a, s.a + capacity, a);
}
The assignment operator you wrote is wrong in two ways:
It should return a Stack object by reference
The parameter should be a const reference
The rest is just ok
Stack& Stack::operator = (const Stack& s) {
capacity = s.capacity;
a = new int[capacity];
for (int i = 0; i < capacity; i++) { // or std::copy
a[i] = s.a[i];
}
index = s.index;
return *this;
}
Update
Tentative implementation of the reverseStack function (without side-effects), assuming index contains the actual number of items in the stack
Stack reverseStack(const Stack& s) {
Stack s2(s.capacity);
for (int i = 0; i < s2.index; ++i) {
s2.a[i] = s2.a[s2.index -i];
}
return s2;
}
Update Thanks to user657267 from pointing out int* a = new int[capacity]; was wrong