I was trying to make a queue program on my own, but when I enqueue an element and then display the queue, I find an extra element already lying around in my queue. Also, I am not able to add the number of elements as I decided from the size of the queue because of the garbage numbers eating up space in my queue. Here's the code for it :
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void enqueue();
void dequeue();
void display();
int main(){
int size;
printf("Enter the size of the queue : ");
scanf("%d", &size);
int choice, element;
int queue[size];
int front = 0;
int rear = 0;
while(true){
printf("Queue Operations\nPress 1 for Enqueue\nPress 2 for Dequeue\nPress 3 for Display\nPress 4 for exit\n");
scanf("%d", &choice);
switch(choice){
case 1:{
if(rear == size - 1){
printf("Overflow!\n");
}
else{
printf("Enter the element you want to enqueue : ");
scanf("%d", &element);
queue[rear] = element;
rear ;
}
break;
}
case 2:{
if(front == rear){
printf("Underflow!\n");
}
else{
printf("The element deleted is %d\n", queue[front]);
front = 1;
size =1;
}
break;
}
case 3:{
if(front == rear){
printf("Queue is empty.\n");
}
else{
for(int i = front; i <= rear; i ){
printf("%d ", queue[i]);
}
printf("\n");
}
break;
}
case 4:{
exit(0);
}
default:{
printf("Invalid Choice.\nTry again.\n");
break;
}
}
}
return 0;
}
CodePudding user response:
Your dequeue operation is wrong. First, you never need to change the front
variable, which will/should always be zero. Second, you must not change the value of size
after the array has been initialized with a given value for that.
Instead, your dequeue operation should simply move each of the remaining entries in the queue to locations at indexes one less than their current ones. You could do this in a loop, like this:
for (int i = 0; i < rear; i) queue[i] = queue[i 1];
However, you can do this more efficiently by calling the memmove
function:
memmove(queue, queue 1, sizeof(int) * rear);
Whichever way you choose, you then need to decrement rear
after the shifts.
Also, the condition in the for
loop for your display option should be i < rear
, not i <= rear
; and, your overflow check should be for rear == size
.
Here's a rework of your code applying the corrections I have outlined above:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h> // For "memmove"
int main() {
int size;
printf("Enter the size of the queue : ");
scanf("%d", &size);
int choice, element;
int queue[size];
int rear = 0;
while (true)
{
printf("Queue Operations:\n"
"Press 1 for Enqueue\n"
"Press 2 for Dequeue\n"
"Press 3 for Display\n"
"Press 4 for exit\n"
);
scanf("%d", &choice);
switch (choice) {
case 1: {
if (rear == size) { // Note: Using size not size - 1
printf("Overflow!\n");
}
else {
printf("Enter the element you want to enqueue : ");
scanf("%d", &element);
queue[rear] = element;
rear ;
}
break;
}
case 2: {
if (rear == 0) {
printf("Underflow!\n");
}
else {
printf("The element deleted is %d\n", queue[0]);
// for (int i = 0; i < rear; i) queue[i] = queue[i 1];
memmove(queue, queue 1, sizeof(int) * rear);
rear--;
}
break;
}
case 3: {
if (rear == 0) {
printf("Queue is empty.\n");
}
else {
for (int i = 0; i < rear; i ) { // Note: i < rear not i <= rear
printf("%d ", queue[i]);
}
printf("\n");
}
break;
}
case 4: {
exit(0);
}
default: {
printf("Invalid Choice.\nTry again.\n");
break;
}
}
}
}
CodePudding user response:
The condition in the for loop
for(int i = front; i <= rear; i ){
printf("%d ", queue[i]);
}
is incorrect. At least you have to write
for(int i = front; i < rear; i ){
printf("%d ", queue[i]);
}
Also this statement
size =1
does not make a sense because the size of the dynamically allocated array is fixed.
And the condition in this if statement
case 1:{
if(rear == size - 1){
printf("Overflow!\n");
}
is also incorrect. You should write
case 1:{
if(rear == size){
printf("Overflow!\n");
}
Pay attention to that you should make a circular queue. To do so you should introduce one more variable something like full
that is set when rear
is equal to front
and queue is not empty.
And that is more important it is better to introduce a structure that describes the queue.
Here is a demonstration program that shows how it can be done.
#include <stdio.h>
#include <stdlib.h>
struct Queue
{
int *a;
size_t size;
size_t front;
size_t rear;
int full;
};
int init( struct Queue *queue, size_t n )
{
*queue = ( struct Queue ){ NULL, 0, 0, 0, 0 };
int success = 0;
if (n)
{
queue->a = malloc( n * sizeof( int ) );
if (( success = queue->a != NULL ))
{
queue->size = n;
}
}
return success;
}
void clear( struct Queue *queue )
{
free( queue->a );
*queue = ( struct Queue ){ NULL, 0, 0, 0, 0 };
}
int enqueue( struct Queue *queue, int value )
{
int success = queue->size != 0 && !queue->full;
if (success)
{
queue->a[queue->rear ] = value;
queue->rear %= queue->size;
queue->full = queue->front == queue->rear;
}
return success;
}
int dequeue( struct Queue *queue, int *value )
{
int success = queue->front != queue->rear || queue->full;
if (success)
{
*value = queue->a[queue->front ];
queue->front %= queue->size;
queue->full = 0;
}
return success;
}
void display( const struct Queue *queue )
{
if (queue->front == queue->rear && !queue->full)
{
puts( "The queue is empty." );
}
else
{
printf( "The queue is " );
size_t current = queue->front;
do
{
printf( "%d ", queue->a[current ] );
current %= queue->size;
} while (current != queue->rear);
putchar( '\n' );
}
}
int is_full( const struct Queue *queue )
{
return queue->full;
}
int main( void )
{
struct Queue queue;
printf( "Enter the size of the queue: " );
size_t n = 0;
if (scanf( "%zu", &n ) != 1 || !init( &queue, n ))
{
puts( "Error. Can not reserve memory for the queue." );
}
else
{
enum { Exit = 0, Enqueue = 1, Dequeue = 2, Display = 3 };
size_t n = 0;
do
{
puts( "Queue Operations\n\n"
"Press 1 for Enqueue\n"
"Press 2 for Dequeue\n"
"Press 3 for Display\n"
"Press 0 for Exit\n" );
printf( "Your choice: " );
if (scanf( "%zu", &n ) != 1) break;
switch (n)
{
case Exit:
{
break;
}
case Enqueue:
{
if (is_full( &queue ))
{
puts( "\nThe queue is full. You can not add a new value." );
}
else
{
printf( "\nEnter the element you want to enqueue : " );
int value;
if (scanf( "%d", &value ) != 1)
{
puts( "You interrupted the input" );
}
else
{
enqueue( &queue, value );
printf( "The value %d is added to the queue.\n", value );
}
}
break;
}
case Dequeue:
{
int value;
if (!dequeue( &queue, &value ))
{
puts( "Error. The queue is empty." );
}
else
{
printf( "\nThe removed element is %d\n", value );
}
break;
}
case Display:
{
putchar( '\n' );
display( &queue );
break;
}
default:
{
puts( "Invalid input." );
break;
}
}
if (n == 0) break;
putchar( '\n' );
} while (n != 0);
clear( &queue );
}
}
Enjoy!:)