ringbuffer.c

 avatar
unknown
c_cpp
8 days ago
4.4 kB
68
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// Node structure for the linked list
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// Ring buffer structure
typedef struct {
    Node* head;      // Points to the oldest element (front)
    Node* tail;      // Points to the newest element (back)
    int size;        // Current number of elements
    int capacity;    // Maximum capacity of the buffer
} RingBuffer;

// Create a new ring buffer with fixed capacity
RingBuffer* createRingBuffer(int capacity) {
    if (capacity <= 0) {
        return NULL;
    }
    
    RingBuffer* rb = (RingBuffer*)malloc(sizeof(RingBuffer));
    if (!rb) {
        return NULL;
    }
    
    rb->head = NULL;
    rb->tail = NULL;
    rb->size = 0;
    rb->capacity = capacity;
    
    return rb;
}

// Check if the buffer is empty
bool isEmpty(RingBuffer* rb) {
    return rb->size == 0;
}

// Check if the buffer is full
bool isFull(RingBuffer* rb) {
    return rb->size == rb->capacity;
}

// Add an element to the buffer (overwrites oldest if full)
bool push(RingBuffer* rb, int value) {
    if (!rb) {
        return false;
    }
    
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (!newNode) {
        return false;
    }
    
    newNode->data = value;
    newNode->next = NULL;
    
    // If buffer is empty
    if (isEmpty(rb)) {
        rb->head = newNode;
        rb->tail = newNode;
        rb->size = 1;
        return true;
    }
    
    // If buffer is full, remove the oldest element
    if (isFull(rb)) {
        Node* oldHead = rb->head;
        rb->head = rb->head->next;
        free(oldHead);
        rb->size--;
    }
    
    // Add new element to the end
    rb->tail->next = newNode;
    rb->tail = newNode;
    rb->size++;
    
    return true;
}

// Remove and return the oldest element
bool pop(RingBuffer* rb, int* value) {
    if (!rb || isEmpty(rb)) {
        return false;
    }
    
    Node* oldHead = rb->head;
    *value = oldHead->data;
    
    rb->head = rb->head->next;
    free(oldHead);
    rb->size--;
    
    // If buffer becomes empty, reset tail
    if (isEmpty(rb)) {
        rb->tail = NULL;
    }
    
    return true;
}

// Peek at the oldest element without removing it
bool peek(RingBuffer* rb, int* value) {
    if (!rb || isEmpty(rb)) {
        return false;
    }
    
    *value = rb->head->data;
    return true;
}

// Get the current size of the buffer
int getSize(RingBuffer* rb) {
    return rb ? rb->size : 0;
}

// Get the capacity of the buffer
int getCapacity(RingBuffer* rb) {
    return rb ? rb->capacity : 0;
}

// Display all elements in the buffer
void display(RingBuffer* rb) {
    if (!rb || isEmpty(rb)) {
        printf("Buffer is empty\n");
        return;
    }
    
    printf("Buffer contents (oldest to newest): ");
    Node* current = rb->head;
    while (current) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

// Clear all elements from the buffer
void clear(RingBuffer* rb) {
    if (!rb) {
        return;
    }
    
    Node* current = rb->head;
    while (current) {
        Node* temp = current;
        current = current->next;
        free(temp);
    }
    
    rb->head = NULL;
    rb->tail = NULL;
    rb->size = 0;
}

// Free the ring buffer
void destroyRingBuffer(RingBuffer* rb) {
    if (rb) {
        clear(rb);
        free(rb);
    }
}

// Example usage
int main() {
    // Create a ring buffer with capacity 5
    RingBuffer* rb = createRingBuffer(5);
    
    printf("Created ring buffer with capacity: %d\n\n", getCapacity(rb));
    
    // Push some elements
    printf("Pushing elements 1, 2, 3, 4, 5:\n");
    for (int i = 1; i <= 5; i++) {
        push(rb, i);
        printf("Pushed: %d, Size: %d\n", i, getSize(rb));
    }
    display(rb);
    
    printf("\nPushing elements 6 and 7 (should overwrite oldest):\n");
    push(rb, 6);
    printf("Pushed: 6, Size: %d\n", getSize(rb));
    push(rb, 7);
    printf("Pushed: 7, Size: %d\n", getSize(rb));
    display(rb);
    
    printf("\nPopping elements:\n");
    int value;
    while (pop(rb, &value)) {
        printf("Popped: %d, Size: %d\n", value, getSize(rb));
    }
    
    printf("\nTesting with empty buffer:\n");
    display(rb);
    
    // Clean up
    destroyRingBuffer(rb);
    
    return 0;
}
Editor is loading...
Leave a Comment