C上的环形缓冲区

时间:2017-03-20 12:27:29

标签: c

我刚开始学习C语言。现在我的任务是编写一个简单的环形缓冲区。 我写了一段代码,但它没有用。我无法解决问题,显然,我在推送和弹出功能中指出了错误的参数。它需要使用缓冲区的头部,尾部和大小(我认为问题在于尾部,但是不能正常得到)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ringBuffer 
{
    void *bufferData;
    int head;
    int tail;
    int size;
    int numElements;
};

void bufferInitialization(struct ringBuffer *buffer, int size) 
{
    buffer->size = size;
    buffer->head = 0;
    buffer->tail = 0;
    buffer->numElements = 0;
    buffer->bufferData = (void*)malloc(sizeof(int)*size);
}

void bufferFree(struct ringBuffer *buffer)
{
    free(buffer->bufferData);
}

int pushBack(struct ringBuffer *buffer, int *data)
{

    /*  int i;
    i = buffer->head + buffer->tail + 1;
    if (i >= buffer->size) 
    {
        i = 0;
    }
    buffer->bufferData[i] = data;*/
    memcpy((void*)buffer->head, data, buffer->size);
    buffer->head = buffer->head + buffer->size;
    if (buffer->head == buffer->tail)
    { 
        buffer->head = (int)buffer->bufferData; //error?
    }
    buffer->numElements++;
    return 0;
}

int popFront(struct ringBuffer *buffer, void *data)
{
    //void * bufferData;

    /*bufferData = buffer->bufferData[buffer->head];
    buffer->head++;
    buffer->tail--;
    if (buffer->head == buffer->size) 
    {
        buffer->head = 0;
    }
    //return bufferData;*/

    memcpy(data, (void*)buffer->tail, buffer->size); //error?
    buffer->tail = buffer->tail + buffer->size;

    if ((void*)buffer->tail == buffer->bufferData)
    { 
        buffer->tail = (int)buffer->bufferData; //error?
    }
    buffer->numElements--;
    return 0;
}

int main() 
{
    struct ringBuffer buffer;
    int size = 5;
    //*buffer->size = 6;
    bufferInitialization(&buffer, size);
    char *data[] = { "1" , "2", "3", "4" , "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" };

    for (int i = 0; i < size; i++)
    {
        printf("Push: data[%d] = %s\n", i, *data[i]);
        pushBack(&buffer, (int*)data[i]);
    }
    printf("\n");
    for (int i = 0; i < size; i++)
    {
        printf("PushBack: queue[%d] = %s\n", i, (ringBuffer*)popFront(&buffer, (void*)data[i])); // !!!
    }
    printf("\n");

    for (int i = 0; i < size; i++)
    {
        printf("PopFront: data[%d] = %s\n", i, *data[i]);
        pushBack(&buffer, (int*)data[i]);
    }
    printf("\n");
    system("pause");
    return 0;
    }

感谢您提供任何帮助和建议!

3 个答案:

答案 0 :(得分:1)

好吧,我决定在缓冲区结构中只使用4个值,看起来效果很好。在代码的末尾有一个dataBuffer检查。

现在我需要编写一个printBuffer函数,只是为了在dataBuffer中显示从HEAD到TAIL的值但是我注意到了一个问题:每次我在缓冲区中写入一个值时,HEAD和TAIL之间的差值总是1(正如我所理解的那样) buffer为空,size = 8且data []中只有6个值,它必须显示为bufferData [0] = 1 ... bufferData [5] = 6,但结果工作不正确。你能解释一下吗?请问如何将printBuffer函数带到可接受的形式?

感谢。这是我的代码(它可以工作,到处检查):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ringBuffer
{
    int *bufferData;
    int head;
    int tail;
    int size;
};

void bufferFree(struct ringBuffer *buffer)
{
    free(buffer->bufferData);
}

void bufferInitialization(struct ringBuffer *buffer, int size)
{
    buffer->size = size;
    buffer->head = 0;
    buffer->tail = 0;
    buffer->bufferData = (int*)malloc(sizeof(int) * size);
}

void printBuffer(struct ringBuffer *buffer, int i, int size)
{
    printf("Values from HEAD to TAIL: ");
    if (buffer->head == buffer->tail)
    {
        printf("Head and tail are equals\n");
    }
    else
    {
        printf("bufferData[%d] = %d\n", i, buffer->bufferData);
    }
}

int pushBack(struct ringBuffer *buffer, int data)
{
    buffer->bufferData[buffer->tail++] = data;
    if (buffer->tail == buffer->size)
    {
        buffer->tail = 0;
    }
    return 0;
}

int popFront(struct ringBuffer *buffer)
{
    if (buffer->head != buffer->tail)
    {
        buffer->head++;
        if (buffer->head == buffer->size)
        {
            buffer->head = 0;
        }
    }
    return 0;
}

int main(int argc, char* argv[])
{
    struct ringBuffer buffer;
    int size = 8;
    int data[] = { 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 }; // 20 values
    int dataSize = sizeof(data)/sizeof(data[0]);

    /* Test implimention with 1 element in dataBuffer */
    bufferInitialization(&buffer, size);
    printf("Head : %d - Tail: %d\n", buffer.head, buffer.tail);
    pushBack(&buffer, 5);
    printf("Head : %d - Tail: %d\n", buffer.head, buffer.tail);
    popFront(&buffer);
    printf("Head : %d - Tail: %d\n", buffer.head, buffer.tail);
    printf("\nnumElements in data = %d : bufferSize = %d\n\n", dataSize, size);
    bufferFree(&buffer);

    /* Implimention with dada[] */
    printf("INITIALIZATION\n");
    bufferInitialization(&buffer, size);
    printf("Head : %d - Tail: %d\n", buffer.head, buffer.tail);

    /* pushBack call */
    printf("\nPUSHBACK\n\n");
    for (int i = 0; i < dataSize; i++)
    {
        pushBack(&buffer, data[i]);
        printf("Head : %d - Tail : %d :: Data = %d (data[%d])   \n", buffer.head, buffer.tail, data[i], i);
        /*for (int k = buffer.head; k<=buffer.tail; k++)
        { 
            // Print methode from head to tail
            printBuffer((ringBuffer*)buffer.bufferData, i, size);
        }*/
        popFront(&buffer);
    }
    popFront(&buffer);
    printf("Head : %d - Tail : %d :: (popFront)\n", buffer.head, buffer.tail);
    /* bufferData check */
    printf("\nbufferData check:\n");
    for (int i = 0; i < size; i++)
    {
        printf("[%d] = %d  ", i, buffer.bufferData[i]);
    }
    printf("\nHead : %d - Tail : %d\n", buffer.head, buffer.tail);
    bufferFree(&buffer);
    system("pause");
    return 0;
}

答案 1 :(得分:0)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ringBuffer 
{
    char *bufferData;
    void *bufferEnd;

    int head;
    int tail;

    int size;
    int used;
    int capacity; // "вместимость"
};

void bufferInitialization(struct ringBuffer *buffer, int capacity, int size) 
{
    buffer->bufferData = (char*)malloc(capacity * size);
    if (buffer->bufferData == 0)
    { 
        buffer->bufferEnd = (char *)buffer->bufferData + capacity * size;
    }
    buffer->capacity = capacity;
    buffer->used = 0;
    buffer->size = size;
    buffer->head = *buffer->bufferData;
    buffer->tail = *buffer->bufferData;
}

void bufferFree(struct ringBuffer *buffer)
{
    free(buffer->bufferData);
}

int pushBack(struct ringBuffer *buffer, char *data)
{
    if (buffer->used == buffer->capacity) {
        printf("Capacity error\n");
        buffer->bufferData = 0; //??
    }
    memcpy((ringBuffer*)buffer->head, data, buffer->size);
    buffer->head = buffer->head + buffer->size;
    if (buffer->head == (char)buffer->bufferEnd)
    {
        buffer->head = (char)buffer->bufferData;
    }
    buffer->used++;
    return 0;
}

int popFront(struct ringBuffer *buffer, char *data)
{
    if (buffer->used == 0) 
    {
        printf("Buffer is clear\n");
    }
    memcpy(data, (ringBuffer*)buffer->tail, buffer->size); 
    buffer->tail = (char)buffer->tail + buffer->size;
    if (buffer->tail == (char)buffer->bufferEnd)
    {
        buffer->tail = (char)buffer->bufferData;
    }
    buffer->used--;
    return 0;
}

int main() 
{
    struct ringBuffer buffer;
    int size = 6;
    int capacity = 10;
    bufferInitialization(&buffer, capacity, size);
    char *data[] = { "1" , "2", "3", "4" , "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" };

    for (int i = 0; i < size; i++)
    {
        printf("Push: data[%d] = %d\n", i, *data[i]);
        pushBack(&buffer, (char*)data[i]);
    }
    printf("\n");

    for (int i = 0; i < size; i++)
    {
        printf("PushBack: queue[%d] = %s\n", i, (ringBuffer*)popFront(&buffer, (char*)data[i])); // !!!
    }
    printf("\n");

    for (int i = 0; i < size; i++)
    {
        printf("PopFront: data[%d] = %s : %s\n", i, *data[i]);
        pushBack(&buffer, (char*)data[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}

答案 2 :(得分:0)

这是一个没有memcpy的示例。因此,您可以在复制时看到缓冲区末端的问题。它没有经过测试,但展示了如何继续。这是一个char铃声,所以你必须写一个字符。没有检查\0,因此如果您读写“字符串”,则必须包含它们。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ringBuffer 
{
    char *bufferData;
    char *head;
    char *tail;
    char *end;
    int size;
    int free;
};

void bufferInitialization(struct ringBuffer *buffer, int size) 
{
    buffer->size = size;
    buffer->used = 0;
    buffer->head = 
    buffer->tail =
    buffer->bufferData = malloc(size);
    buffer->end  = buffer->bufferData + size;
}

int pushBack(struct ringBuffer *buffer, char *data, int size)
{
    if(size > buffer->size - buffer->used) return -1;

    for( ; size>0 && buffer->used < buffer->size; buffer->used++, size--) {
        *buffer->head = *data;
        buffer->head++;
        data++;
        if(buffer->head == buffer->end) buffer->head = buffer->bufferData;
    }
    return 0;
}

int popFront(struct ringBuffer *buffer, char *data, int size)
{
    if(size > buffer->used) return -1;

    for( ; size>0 && buffer->used > 0; buffer->used--, size--) {
        *data = *buffer->tail;
        buffer->tail++;
        data++;
        if(buffer->tail == buffer->end) buffer->tail = buffer->bufferData;
    }
    return 0;
}