C++ Circular queue class with a length of 100 - c++

I've got some questions on how to create and use a circular queue class in C++. The questions are in the code as comments because I am looking for general pointers on how to see if I'm on the right track.
Edit:
Adding the specific questions here for clarity:
Do I need a pointer for both the head and the tail of the queue?
Do I initialize a queue like this or is there a better way?
How do I dequeue and return the correct value?
The code:
#include <iostream>
#include <stdexcept>
using namespace std;
class Queue{
private:
int maxSize;
int *data; // Do I maybe need one for head and one for tail?
int counter; // Used to count the amount of elements in the queue.
public:
Queue();
Queue(int max=100);
~Queue();
void clear();
bool empty() const;
bool full() const;
int dequeue() throw (length_error);
void enqueue(int value) throw (length_error);
int length();
};
Queue :: Queue() // Is this the correct way to initialize the queue?
{
data[100];
counter = 0;
maxSize = 100;
}
void Queue::clear()
{
data = NULL;
}
bool Queue::empty()const
{
if(counter == 0)
return true;
return false;
}
bool Queue::full()const
{
if(counter == 100)
return true;
return false;
}
int Queue::length()
{
return counter;
}
int Queue::dequeue() throw (length_error) // How do I get the correct element and then return it.
{
if(counter >= 0)
{
counter--;
return counter;
}
return counter;
}
void Queue::enqueue(int value) throw(length_error)
{
if(counter < maxSize)
{
data[counter] = value;
counter++;
cout << "Adds the number at the end if there is room for it." << endl;
}
else
;// throw(length_error);
}
int main()
{
Queue minQueue;
minQueue.enqueue(10);
minQueue.enqueue(12);
minQueue.enqueue(14);
minQueue.enqueue(16);
minQueue.enqueue(18);
cout << "Empty: " << minQueue.empty() << endl;
cout << "Full: " << minQueue.full() << endl;
cout << "Length: " << minQueue.length() << endl;
minQueue.dequeue();
minQueue.clear();
system("pause");
}

Your code has some issues.
class Queue{
// ...
public:
// Queue(); // deleted this line, since it collides with the next ctor declation.
// A ctor with one optional argument includes a ctor with no arguments
Queue(int max=100);
~Queue();
}
//...
Queue::Queue(int max) // argument required!
{
data = new int[max]; // this is probably what you want
counter = 0;
maxSize = max;
}
void Queue::clear()
{
delete[] data; // see above, must match the allocation
}
int Queue::dequeue() throw (length_error)
{
if(counter > 0) // !!!! dont't decrease when 0
{
counter--;
return data[counter];
}
else
throw(length_error()); // an exception class length_error must exist!
}
These are a few starting points, fill the remaining gaps by yourself.

Related

Class Dynamic Array Bug

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.

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];

Why am I getting "invalid conversion from 'Queue*/Stack*' to 'int'" error message?

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 &copy){
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 == &copyA){
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++)

Using a stack to determine if an expression has balanced parentheses

I am working on my last school assignment for the semester and we are being introduced to stacks for the first time but I am having an issue with my program not analyzing the expression properly. Everything executes but the program always comes out with the result that expression is unbalanced. Any clues to point me in the right direction?
//
// main.cpp
// Balanced Parenthesis
#include "StringStack.h"
#include <iostream>
using namespace std;
int main ()
{
StringStack stack;
char entry;
int parCounter = 0;
cout << "This program will accept a string and determine whether it has balanced parenthesis.\n";
cout << "Please type a sentence to be analyzed\n";
while (cin.get (entry) && entry != '\n')
{
stack.push(entry);
}
if (stack.isEmpty()) {
cout << "The stack is empty./n";
}
else{
stack.pop(entry);
if (entry == ')') {
parCounter++;
}
else if(entry == '('){
parCounter--;
}
}
if (parCounter > 0 || parCounter < 0){
cout << "This expression has UNBALANCED parentheses\n";
}
else
{
cout << "This expression has BALANCED parentheses\n";
}
return 0;
}
// StringStack.h
// Balanced Par
#include <iostream>
using namespace std;
#ifndef StringStack_h
#define StringStack_h
//Define our stack class and its contents
class StringStack
{
private:
char *stackArray;
int stackSize;
char top;
public:
StringStack();
~StringStack() {delete[] stackArray;}
void push(char);
void pop(char &);
bool isBalanced();
bool isEmpty();
};
#endif
//Constructor
StringStack::StringStack()
{
stackArray = new char[stackSize];
top = 0;
}
//Function to determine if stack is empty.
bool StringStack::isEmpty()
{
if (top == 0)
return true;
else
return false;
}
//Function to push letters/puncuation onto the stack
void StringStack::push(char letter)
{
//if (isEmpty())
{
top++;
stackArray[top] = letter;
}
//else
//{
//exit(1);
//}
}
//Function to pop letters/puncuation off the stack
void StringStack::pop(char &letter)
{
if (isEmpty())
{
cout << "The stack is empty.\n";
exit(1);
}
else
{
letter = stackArray[top];
top--;
}
}
You're not initialising or setting the member stackSize anywhere. This makes new char[stackSize] undefined behaviour and anything could happen.
And after you fix that, you're only inspecting the top of the stack. You need a loop around the parCount - controlling if to run until the stack is empty.

Array Implementation of Queue: Strange Output

I am learning about queues and I wrote the following program which implements the queue as a linear array (NOT a circular one).
#include<iostream>
using namespace std;
class queue {
int front, max_queue, rear, count = 0;
int *items;
public:
queue(int);
~queue();
void enqueue(int);
void dequeue();
bool isEmpty();
int size();
void display();
};
queue::~queue() {
delete []items;
}
queue::queue(int max) {
front = -1;
rear = -1;
max_queue = max;
items = new int[max_queue];
}
void queue::enqueue(int n) {
if (count == max_queue)
cout << "queue is full, no enqueue possible";
else {
items[++rear] = n;
count++;
}
}
void queue::dequeue() {
if (count == 0)
cout << "no dequeue possible, queue already empty";
else {
front--;
count--;
}
}
bool queue::isEmpty() {
return ((count == 0) ? 1 : 0);
}
int queue::size() {
return count;
}
void queue::display() {
if (count == 0)
cout << "nothing to display";
else {
for (int i = front; i <= rear;)
cout << items[i++] << endl;
}
}
int main() {
queue *qe = new queue(10);
qe->enqueue(1);
qe->enqueue(2);
qe->enqueue(3);
qe->enqueue(4);
qe->display();
return 0;
}
I get the following output
49
1
2
3
4
RUN FINISHED; exit value 0; real time: 10ms; user: 0ms; system: 0ms
Why is there a 49 in my output.? Is it a garbage value? Does not using a circular array implementation,a probable cause?
I have no idea. Any help appreciated.
You're starting the display loop i with front which is -1. You're pointing to a spot before your queue.
If a queue is empty and you enqueue an element x, then x becomes both the front and the rear.
The issue is in your display function:
for (int i = front; i <= rear;)
cout << items[i++] << endl;
You're setting i=front, but you've previously set front=-1. Thus, you're attempting to access items[-1]. You can either set i=front+1:
for (int i = front + 1; i <= rear;)
cout << items[i++] << endl;
or continue until i<rear and use ++i instead of i++:
for (int i = front; i < rear;)
cout << items[++i] << endl;