void IntQueue::enqueue(int num)
{
if (isFull())
throw std::runtime_error("The queue is full");
else
{
// Calculate the new rear position
rear = (rear + 1) % queueSize;
// Insert new item
queueArray[rear] = num;
// Update item count
numItems++;
}
}
after I throw this exception how can I rewrite the main program so that it catches overflow exceptions when they occur. The exception handler for queue overflow should print an appropriate error message and then terminate the program. here is the main program
int main()
{
IntQueue iQueue(5);
cout << "Enqueuing 5 items...\n";
// Enqueue 5 items.
for (int x = 0; x < 5; x++)
iQueue.enqueue(x);
// Attempt to enqueue a 6th item.
cout << "Now attempting to enqueue again...\n";
iQueue.enqueue(5);
// Deqeue and retrieve all items in the queue
cout << "The values in the queue were:\n";
while (!iQueue.isEmpty())
{
int value;
iQueue.dequeue(value);
cout << value << endl;
}
}
Wrap the part that can throw with try-block.
For example,
try
{
for (int x = 0; x < 5; x++)
iQueue.enqueue(x);
// Attempt to enqueue a 6th item.
cout << "Now attempting to enqueue again...\n";
iQueue.enqueue(5);
}
catch (const std::runtime_error& e)
{
cout << "Error: " << e.what() << endl; // Print error message
exit(1); // Terminate with non-zero exit code
}
Related
In all queue array implementations I have seen, when they 'pop an element from front', they basically change the front tag of the queue to the next element. but then the capacity of the queue is technically reduced (since array is used). How hasn't this caused problems yet or how is this considered valid?
Edit : https://www.softwaretestinghelp.com/queue-in-cpp/
Take the illustration in this link under consideration. When we perform the dequeue operation, we change the pointer of front to the next element. From this point on, any operation we perform will be done with respect to the 2nd position of array as the front element. Now if we go on adding elements to the full capacity of queue, we would, the maximum no. of elements that we could fit in the queue would be 1 less than the capacity of the array (which we had defined earlier).
You are right with your concern about the C++ implementation given in the article https://www.softwaretestinghelp.com/queue-in-cpp/. With that implementation, basically when you dequeue an element, the pointer to the "first" of the queue shift 1 unit to the right (in the underlying array), and that reduce the capacity of the queue.
The correct way to implement such a queue should be similar to the Java implementation provided in that very article. As you can see, every array indices are pre-processed with % this.max_size. That makes the array accessing become "circular", i.e. when we access an index k >= this.max_size, the real array index is back to the range [0, this.max_size - 1]. As a result, all the slot in the underlying array are used, which makes the capacity of the queue remain the same after the dequeue or enqueue operation.
Here is the corrected version of the C++ implementation.
#include <iostream>
#define MAX_SIZE 5
using namespace std;
class Queue
{
private:
int myqueue[MAX_SIZE], front, rear;
public:
Queue ()
{
front = -1;
rear = -1;
}
bool isFull ()
{
if ((rear - front + MAX_SIZE) % MAX_SIZE == MAX_SIZE - 1)
{
return true;
}
return false;
}
bool isEmpty ()
{
if (front == -1)
return true;
else
return false;
}
void enQueue (int value)
{
if (isFull ())
{
cout << endl << "Queue is full!!";
}
else
{
if (front == -1)
front = 0;
rear++;
myqueue[rear % MAX_SIZE] = value;
cout << value << " ";
}
}
int deQueue ()
{
int value;
if (isEmpty ())
{
cout << "Queue is empty!!" << endl;
return (-1);
}
else
{
value = myqueue[front % MAX_SIZE];
if (front >= rear)
{ //only one element in queue
front = -1;
rear = -1;
}
else
{
front++;
}
cout << endl << "Deleted => " << value << " from myqueue";
return (value);
}
}
/* Function to display elements of Queue */
void displayQueue ()
{
int i;
if (isEmpty ())
{
cout << endl << "Queue is Empty!!" << endl;
}
else
{
cout << endl << "Front = " << front;
cout << endl << "Queue elements : ";
for (i = front; i <= rear; i++)
cout << myqueue[i % MAX_SIZE] << "\t";
cout << endl << "Rear = " << rear << endl;
}
}
};
int
main ()
{
Queue myq;
myq.deQueue (); //deQueue
cout << "Queue created:" << endl;
myq.enQueue (10);
myq.enQueue (20);
myq.enQueue (30);
myq.enQueue (40);
myq.enQueue (50); //enqueue 60 => queue is full
myq.enQueue (60);
myq.displayQueue ();
//deQueue =>removes 10, 20
myq.deQueue ();
myq.deQueue ();
//queue after dequeue
myq.displayQueue ();
myq.enQueue (70);
myq.enQueue (80);
myq.enQueue (90); //enqueue 90 => queue is full
myq.displayQueue ();
return 0;
}
I've been trying to output "Queue is full" which was declared in my other code. How do I catch this?
this is my main
int main() {
IntQueue iQueue(5);
try {
cout << "Enqueuing 5 items...\n";
// Enqueue 5 items.
for (int x = 0; x < 5; x++)
iQueue.enqueue(x);
} catch (...) {
// Attempt to enqueue a 6th item.
cout << "Now attempting to enqueue again...\n";
iQueue.enqueue(5);
}
and this is my other code
if (isFull())
throw std::runtime_error("Queue is full");
else {
cout << "Enqueueing: " << num << endl;
// Calculate the new rear position
rear = (rear + 1) % queueSize;
// Insert new item
queueArray[rear] = num;
// Update item count
numItems++;
}
Here is how you catch an exception and print its message:
try {
// ...
} catch (std::runtime_error const& e) {
std::cout << e.what() << '\n'; // or std::cerr, std::perror, or smth else
}
Any code under the catch block is meant to catch any exception thrown in the try block, which means you should write any code that could throw exceptions in it:
try {
// trying to enqueue 6 items, which is above limit.
for (int x = 0; x < 6; x++) {
iQueue.enqueue(x);
}
} catch (exception e) {
cout << e.what() << '\n';
}
UPDATE: If i change async_receive_from to receive_from then there will not be any problems with rebinding. Somehow async... causes that. Previously i had one thread for every socket(with receive_from), but i had to make it work in one thread as too many threads are spawned during programm runs.
Socket is closed (i have checked), but rebinding to it causes an error. Here is an example:
#include "stdafx.h"
#include "Mmsystem.h"// for accurate timers
#pragma comment (lib,"Winmm.lib")// for accurate timers
using namespace std;
typedef shared_ptr<boost::asio::ip::udp::socket> SHP_Socket;
boost::asio::io_service io_service_;
vector<int> ports;
vector<SHP_Socket> vecSock;
vector<boost::asio::ip::udp::endpoint> vecEndpoint;
vector<boost::shared_ptr<boost::thread>> receive_threads;
bool process_all_finishing;
uint8_t Data[8000];
void receive_h(boost::system::error_code ec, size_t szPack, int i)
{
if (process_all_finishing == false)
{
cout << "\n" << i;
string f = boost::to_string(Data);
int sz = f.size();
if (sz > 12)
{
vector<int> a;
for (int i = 0; i < 100; ++i)
a.push_back(i);
a.clear();
}
}
}
void Run_io()
{
while (process_all_finishing == false)
{
io_service_.run_one();
}
cout << "\nRun_io finished";
}
void receive()
{
while (process_all_finishing == false)
{
this_thread::sleep_for(chrono::milliseconds(1));
for (unsigned i = 0; i < vecSock.size(); ++i)
{
vecSock[i]->async_receive_from(boost::asio::buffer(Data, 8000), vecEndpoint[i], boost::bind(receive_h,_1,_2,i));
}
}
cout << "\nreceive finished";
}
int main()
{
timeBeginPeriod(1);
setlocale(LC_ALL, "Russian");
try
{
ports.push_back(29005);
ports.push_back(29007);
ports.push_back(29009);
ports.push_back(29001);
vecSock.resize(3);
vecEndpoint.resize(3);
for (int i = 0; i < 3; ++i)
{
vecSock[i].reset(new boost::asio::ip::udp::socket(io_service_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), ports[i])));
}
boost::shared_ptr<boost::thread> thread_re(new boost::thread(receive));
boost::shared_ptr<boost::thread> thread_io(new boost::thread(Run_io));
receive_threads.push_back(thread_re);
receive_threads.push_back(thread_io);
cout << "\nvecSock=3 created, giving it to work for 1 second:";
this_thread::sleep_for(chrono::seconds(1));
process_all_finishing = true;
cout << "\nSent flag to stop threads and wait for threads to finish for 1 second";
this_thread::sleep_for(chrono::seconds(1));
for (int i = 0; i < vecSock.size(); ++i)
{
cout << "\nSocket " << i << " opened =\t" << vecSock[i]->is_open();
vecSock[i]->cancel();
vecSock[i]->close();
cout << "\nSocket " << i << " counter =\t" << vecSock[i].use_count();
cout << "\nSocket " << i << " opened =\t" << vecSock[i]->is_open();
vecSock[i].reset();
cout << "\nSocket " << i << " counter =\t" << vecSock[i].use_count();
cout << "\n";
}
this_thread::sleep_for(chrono::seconds(1));
vecSock.clear();
vecSock.resize(4);
vecEndpoint.resize(4);
for (int i = 0; i < 4; ++i)
{
vecSock[i].reset(new boost::asio::ip::udp::socket(io_service_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), ports[i])));
}
cout << "\nvecSock=4 created";
}
catch (boost::exception& e)
{
cerr <<"\n\a\a"<< boost::diagnostic_information(e);
system("pause");
}
return 0;
}
This causes an binding error (exeption) which i have redirected to console with try-catch.
Throw location unknown (consider using BOOST_THROW_EXCEPTION) Dynamic
exception type: class boost::exception_detail::clone_impl > std::exception::what: bind: Usually are
allowed only one usage of each socket address (Protocol/network
address/port)
Can ony one help? I have tried all, what I could find in references c++ and boost and nothing helped this error.
Below is the code for STACK with no overflow since I am using vector concept. Program seems to be working fine as long as I push integers, but as soon as I push float value (for testing) the output screen goes to infinite loop and debugger doesn't even stop at cin statement and it simply crosses it without giving the control to the console window.
#include"iostream"
class Mystack
{
private:
int *input;
int top;
int capacity;
public:
Mystack();
~Mystack();
void push(int x);
int pop();
int topElement() const;
bool isEmpty() const;
void print();
};
Mystack::Mystack()
{
top = -1;
capacity = 5;
input = new int[capacity];
}
Mystack::~Mystack()
{
delete[]input;
}
void Mystack::push(int x)
{
if (top + 1 == capacity)
{
int *vec = new int[capacity+capacity];
for (int i = 0; i <=top; i++)
{
vec[i] = input[i];
}
input = vec;
capacity = capacity * 2;
top++;
input[top] = x;
}
else
{
top++;
input[top] = x;
}
}
int Mystack::pop()
{
if (isEmpty())
{
throw std::out_of_range("Stack Underflow");
}
else
{
std::cout << "The popped element is" << input[top];
return input[top--];
}
}
bool Mystack::isEmpty() const
{
if (top == -1)
{
std::cout << "Is Empty" << std::endl;
return true;
}
else
{
std::cout << "Not Empty" << std::endl;
return false;
}
}
int Mystack::topElement() const
{
if (top == -1)
{
throw std::out_of_range("No Element to Display");
}
else
{
std::cout << "The top element is : " << input[top];
return input[top];
}
}
void Mystack::print()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
int main()
{
Mystack s1;
int num, ch = 1;
while (ch >0)
{
std::cout << "\n1. PUSH" << std::endl;
std::cout << "2. TOP" << std::endl;
std::cout << "3. IsEmpty" << std::endl;
std::cout << "4. POP" << std::endl;
std::cout << "5. EXIT" << std::endl;
std::cout << "6. Print" << std::endl;
std::cout << "Enter the choice" << std::endl;
std::cin >> ch; // DEBUGGER DOES NOT GIVE CONTROL TO CONSOLE WINDOW AND ASK FOR INPUT ONCE I PUT FLOAT VALUES, IT SIMPLE CROSSES IT
switch (ch)
{
case 1:
std::cout << "Enter the number to be pushed" << std::endl;
std::cin >> num;
s1.push(num);
break;
case 2:
std::cout << "Get the TOP Element" << std::endl;
try
{
s1.topElement();
}
catch (std::out_of_range &oor)
{
std::cerr << "Out of Range error:" << oor.what() << std::endl;
}
break;
case 3:
std::cout << "Check Empty" << std::endl;
s1.isEmpty();
break;
case 4:
std::cout << "POP the element" << std::endl;
try
{
s1.pop();
}
catch (const std::out_of_range &oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
break;
case 5: exit(0);
case 6:
s1.print();
break;
default:
std::cout << "Enter a valid input";
break;
}
}
std::cin.get();
}
Once you input the int value for example as 1.1 (invalid int value). Input conversion error occurs and the input stream because of invalid data ignores the rest of the operation even the cin. Make your code more generic in order for it to handle float or double or char.
I get the following assertion errors after the control passes the return statement:
_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
CrtIsValidHeapPointer(pUserData)
while trying to run this code:
main.cpp
#include <iostream>
#include "Queue.h"
#include "Customer.h"
using namespace std;
int main() {
Queue q1;
Queue q2(3);
Queue q3(5);
for (int i = 0; i < 13; i++)
{
Customer c(i);
bool in = q1.enqueue(c);
if (i <= 9 && !in)
{
cout << "ERROR: default size is smaller than 10!!" << endl;
}
else if (i > 9 && in)
{
cout << "ERROR: default size is bigger than 10!!" << endl;
}
}
q1.print();
cout << "0 1 2 3 4 5 6 7 8 9 ***********" << endl;
for (int i = 0; i < 10; i++)
{
Customer el = q1.dequeue();
if (i != el.getId()){
cout << "Error: dequeue order is not correct!!";
}
}
cout << endl;
Customer underflow = q1.dequeue();
if (underflow.getId() != 0)
{
cout << "ERROR: underflow not taken care of!!" << endl;
}
Customer c1(12, "moni");
if (!q3.enqueue(c1))
{
cout << "ERROR: cannot add element to queue 3!!" << endl;
}
Customer c2(14, "mobi");
if (!q3.enqueue(c2)){
cout << "ERROR: cannot add element to queue 3!!" << endl;
}
Queue q4(q3);
if (q3.dequeue().getId() != 12)
{
cout << "ERROR: cdequeue should return the first element in line (12)!!" << endl;
}
if (!q4.enqueue(21)){
cout << "ERROR: cannot add element to queue 4!!" << endl;
}
if (!q4.enqueue(7)){
cout << "ERROR: cannot add element to queue 4!!" << endl;
}
if (!q4.enqueue(332)){
cout << "ERROR: cannot add element to queue 4!!" << endl;
}
if (q4.enqueue(12)){
cout << "ERROR: add element number 6 to queue with size 5 (q4)!!" << endl;
}
q4.print();
cout << "12 14 21 7 332 ***********" << endl;
q3.print();
cout << "14 ***********" << endl;
q2.print();
cout << "queue is empty! ***********" << endl;
q2 = q3;
q2.print();
cout << "14 ***********" << endl;
if (!q2.enqueue(17)){
cout << "ERROR: cannot add element to queue 2!!" << endl;
}
if (!q2.enqueue(18)){
cout << "ERROR: cannot add element to queue 2!!" << endl;
}
if (!q2.enqueue(3521)){
cout << "ERROR: cannot add element to queue 2!!" << endl;
}
q2.print();
cout << "14 17 18 3521 ***********" << endl;
q3.print();
cout << "14 ***********" << endl;
return 0;
}
Queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdio.h>
#include "Customer.h"
class Queue {
private:
Customer *elements; // Holds the elements of this queue.
int mSize; // Size of the queue
int mTop; // Index of the last element in the queue.
public:
static const int DEFAULT_SIZE = 10;
// Default constructor
Queue() : mSize(DEFAULT_SIZE), mTop(-1) {
elements = new Customer[DEFAULT_SIZE];
}
// Copy constructor
Queue(const Queue &q) : mSize(q.mSize), mTop(q.mTop) {
elements = new Customer[mSize];
for(int i = 0; i <= mTop; i++){
elements[i] = q.elements[i];
}
}
// Initialize a new Queue with the specified size.
explicit Queue(int size) : mSize(size), mTop(-1) {
elements = new Customer[size];
}
// Add the given Customer to the end of the queue.
// Returns true if the Customer was added, false if the Queue is full.
bool enqueue(Customer);
// Remove the first Customer from the Queue.
// Returns the Customer that was removed.
Customer dequeue();
// Print the IDs of the Customers in this Queue in the order
// in which they will be attended.
void print() const;
~Queue() {
delete[] elements;
}
};
#endif
Any ideas?
Took a quick look so but I think the problem is somewhere in your implementation of bool enqueue(Customer).
When you do the following:
Customer c(i);
bool in = q1.enqueue(c);
what is happening in enqueue? Is a copy of Customer being made properly?
Not specifically an answer but I think this will drive you in the right direction or perhaps you can post the code for Customer?