Ring buffer in C++

In this tutorial, we will learn about creating a ring buffer in C++. We will implement this using a C++ array. This is also known as a circular buffer. It is useful when input and output speeds are different. To understand this, consider a network that is slower than the speed at which the host can communicate. So, instead of discarding the packets, it stores in a buffer and transmits it.

Ring buffer in C++

A ring buffer or a circular buffer is a fixed size buffer. It has a head and a tail which tells the starting and the ending of the buffer. It obeys First In First Out(FIFO) fashion which means the data which comes first will be processed first. The insertion of new data is done at the tail i.e. end and after processing deletion is done from the head. In this tutorial, we will implement a ring buffer in C++ using an array. We have to consider this array as a circular loop having continuous memory blocks to store data.

We can perform many operations on the ring buffer. But in this tutorial, we will do basic operations – insertion and deletion.
Before insertion, we must check whether the buffer is full or not. And before deletion, we have to check whether an element is there in the buffer to delete. Let’s begin the implementation of the ring buffer in C++.

Implementation of ring buffer in C++

So now we will write a C++ program to implement a ring buffer. The data structure we use here is a C++ array. We divide the whole program into some functions to reduce the complexity and for better understanding. The user-defined functions we use in the program are –

  • check_full() – To insert an element there must be free space in the buffer. So we need to check whether the buffer is full or not before insertion.
  • check_empty() – There must be an element to delete in the buffer. So we have to check whether the buffer is empty or not.
  • insert() – This function will insert new data into the ring buffer at the tail i.e. end.
  • del() – This function deletes data that is at the head i.e. start position.
  • display() – It displays the ring buffer or circular buffer.

Check_full() function

To check whether the buffer is full or not we have to check the values of head and tail. If the head is one greater than tail we can say that array is full. Because, if the array is full then the tail must be pointing to the previous element of the element which head is pointing to. The function prototype is –

int check_full(int, int);

Check_empty() function

We can say that the buffer is empty when the head and tail point to nothing i.e. value of both head and tail is -1. Initially, the value of both the head and tail is -1. The function prototype of this function is –

int check_empty(int, int);

Insert() function

This function provides basic input function. To insert an element into the array we use this function. It inserts a new element at the end of the buffer i.e. at the tail position. It takes input from the user, increments the tail value by 1 and inserts the new element there. The function prototype is given below –

int insert(int [], int &, int &);

Del() function

We use this function to delete an element from the buffer. The deletion is done at the head position. This function stores the deleted element in a temporary variable and increments the head value by 1. The function prototype is –

int del(int [], int &, int &);

Display() function

This function displays the data stored in the buffer. The elements are displayed from head position to tail position. The prototype of this function is –

void display(int [], int, int);

Incrementing head/tail value – While incrementing the value of head or tail, we can’t simply add 1 to the current value. Because, if the tail is pointing to the last index of the array then we have to increment the value of tail and set it to 0 while insertion. So we write the following equations –

  • Incrementing head (in case of deletion) – head=(head+1)%MAX_SIZE
  • Incrementing tail (in case of insertion) – tail=(tail+1)%MAX_SIZE

Program for ring buffer in C++

So, now we will see the C++ program to implement a ring buffer using a C++ array data structure. It has a fixed size. So, in the program, we consider the size of the buffer as 3. The ring buffer implemented in the program stores integer data. The program is given below –

#include<iostream>
#define MAX_SIZE 3
using namespace std;
int check_full(int,int);
int check_empty(int,int);
int insert(int [],int &,int &);
int del(int [],int &,int &);
void display(int [],int,int);
int main()
{
  int ring_buffer[MAX_SIZE],choice,num;
  int head=-1;	//INITIALLY
  int tail=-1;

  do
  {
    cout<<"\n\nMENU :";
    cout<<"\n\t1. INSERT ELEMENT";
    cout<<"\n\t2. DELETE ELEMENT";
    cout<<"\n\t3. DISPLAY\n\t4. EXIT";
    cout<<"\nENTER YOUR CHOICE : ";
    cin>>choice;

    switch(choice)
    {
      case 1:
        if(!check_full(head,tail))
        {
          num=insert(ring_buffer,head,tail);
          cout<<"\nINSERTED ELEMENT : "<<num;
        }
        else
          cout<<"RING BUFFER FULL : NO SPACE TO INSERT";
        break;
      case 2:
        if(!check_empty(head,tail))
        {
          num=del(ring_buffer,head,tail);
          cout<<"\nDELETED ELEMENT : "<<num;
        }
        else
          cout<<"\nRING BUFFER EMPTY : NO ELEMENT TO DELETE";
        break;
      case 3:
        display(ring_buffer,head,tail);
        break;
      case 4:
        cout<<"THANK TOU!!!";
        break;
      default:
        cout<<"\nPLEASE ENTER A VALID OPTION";
    }
  }while(choice!=4);
}
int check_full(int h,int t)
{
  if(h==(t+1)%MAX_SIZE)
    return 1;
  else
    return 0;
}
int check_empty(int h,int t)
{
  if(h==-1 && t==-1)
    return 1;
  else
    return 0;
}
int insert(int buffer[],int &h,int &t)
{
  int element;
  cout<<"ENTER THE ELEMENT : ";
  cin>>element;
  if(h==-1 && t==-1)
  {
    t++;
    h++;
  }
  else
    t=(t+1)%MAX_SIZE;
  buffer[t]=element;
  cout<<"ELEMENT INSERTED SUCCESSFULLY";
  return element;
}
int del(int buffer[],int &h,int &t)
{
  int element;
  element=buffer[h];
  h=(h+1)%MAX_SIZE;
  cout<<"ELEMENT DELETED SUCCESSFULLY";
  if(h==(t+1)%MAX_SIZE)
    h=t=-1;
  return element;
}
void display(int buffer[],int h,int t)
{
  cout<<"RING BUFFER : ";
  if(!check_empty(h,t))
  {
    int i=h;
    while(1)
    {
      cout<<buffer[i]<<" ";
      if(i==t)
        break;
      i=(i+1)%MAX_SIZE;
    }
  }
  else
    cout<<"EMPTY";
}

So, the program above implements a ring buffer using a C++ array. The main() function in the program creates a menu-driven code. So, we use a switch statement to different operations as per the user’s choice.

  • Case 1 – To insert
    We have to check whether the buffer has an empty space. If empty space is available then check_full() returns 0 and we can insert the element by calling insert() function.
  • Case 2 – To delete
    To delete an element from the buffer, the buffer must contain at least one element. So, we call check_empty() function which returns 0 if element is available. Then we call the del() function to delete an element.
  • Case 3 – To display
    Here we display the values stored in the buffer sequentially from head position to tail position using display() function.
  • Case 4 – To exit
    If the user wants to exit from the program we terminate the loop using a condition.

C++ program output

So, after executing this program we get the following output –

[email protected]:~/cppprogram$ g++ ring.cpp
[email protected]:~/cppprogram$ ./a.out

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 1
ENTER THE ELEMENT : 1
ELEMENT INSERTED SUCCESSFULLY
INSERTED ELEMENT : 1

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 1
ENTER THE ELEMENT : 2
ELEMENT INSERTED SUCCESSFULLY
INSERTED ELEMENT : 2

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 1
ENTER THE ELEMENT : 3
ELEMENT INSERTED SUCCESSFULLY
INSERTED ELEMENT : 3

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 1
RING BUFFER FULL : NO SPACE TO INSERT

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 2
ELEMENT DELETED SUCCESSFULLY
DELETED ELEMENT : 1

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 1
ENTER THE ELEMENT : 4
ELEMENT INSERTED SUCCESSFULLY
INSERTED ELEMENT : 4

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 3
RING BUFFER : 2 3 4

MENU :
  1. INSERT ELEMENT
  2. DELETE ELEMENT
  3. DISPLAY
  4. EXIT
ENTER YOUR CHOICE : 4
THANK TOU!!!
[email protected]:~/cppprogram$

Let’s analyze the above output –

  • Iteration 1 – We insert a number 1 into the buffer.
  • Iteration 2 – We insert a number 2 into the buffer.
  • Iteration 3 – We insert a number 3 into the buffer.
  • Iteration 4 – We try to insert a number. But the buffer is full as the maximum size is defined 3.
  • Iteration 5 – We delete an element. So, 1 is deleted according to FIFO fashion.
  • Iteration 6 – We again insert a number 4 into the buffer.
  • Iteration 7 – We display the ring buffer contents. So, at this moment it contains 2,3, and 4.
  • Iteration 8 – We terminate the program.

You can also implement a ring buffer using other C++ data structures such as structure. Thanks for reading this tutorial and I hope it helped you a lot.

Also read:

Leave a Reply

Your email address will not be published. Required fields are marked *