【问题标题】:ring / circular Buffer - buffer implementation and printing values between head and tail环形/循环缓冲区 - 缓冲区实现和打印头部和尾部之间的值
【发布时间】:2017-03-28 05:34:27
【问题描述】:

我是编程的初学者,但我对循环缓冲区的任务有点卡住了。我为我的环形缓冲区编写了函数 push 和 pop ,它是如何工作的,它似乎是有效的。但是,当我使用 pushBack 和循环“for”中的每个元素实现 dataBuffer 时,我得到了不同的 head 值。在我的示例中可以看到(我只能在结构中使用 4 个值 + 第 5 个被添加用于计算头尾之间的元素数):

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

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

    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);
    }

    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 bufferSize(struct ringBuffer *buffer)
    {
        //int numElements;
        //numElements = (buffer->size + buffer->head + buffer->tail) % buffer->size; // 8 + 0 + 6 % 8 = 6; 
        if (buffer->head >= buffer->tail)
        {
            return (buffer->head - buffer->tail);
        }
        else
        {
            return ((buffer->size - buffer->tail) + buffer->head);
        }

        /*if (buffer->head = !buffer->tail)
        {
        for (buffer->head = 0; buffer->head < buffer->tail; buffer->head++)
        {
        printf("head[%d] and tail[%d] --> bufferData = %d", buffer->head, buffer->tail, buffer->bufferData);
        }
        }*/
        return 0;
    }

    int printBuffer(struct ringBuffer *buffer)
    {
        int size = bufferSize((ringBuffer*)buffer->size);
        int i = buffer->head;
        while (buffer->size >= 0) 
        {
            if (!buffer->bufferData)
            {
                printf("Buffer is empty\n");
                return -1;
            }
            else if (i == buffer->size)
            {

        i = 0;
            }
            printf("    \n");
            buffer->size--;
        }
        /*printf("Values from HEAD to TAIL: ");
        if (buffer->head == buffer->tail)
        {
            printf("Head and tail are equals, not possible to show data\n");
        }
        else
        {
            printf("bufferData[%d] = %d\n", buffer->bufferData);
        }*/
    }

    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]);
        bufferInitialization(&buffer, size);

        printf("1st implementation\n");
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        //printf("Current num elements = \n", bufferSize((ringBuffer*)buffer.num));

        printf("2nd implementation\n");
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        bufferFree(&buffer);

        printf("\nInisialization\n");
        bufferInitialization(&buffer, size);
        printf("head = %d, tail = %d - then implementation\n", buffer.head, buffer.tail);
        for (int i = 0; i < dataSize; i++)
        {
            pushBack(&buffer, data[i]);
            printf("head = %d, tail = %d, dataBuffer = %d\n", buffer.head, buffer.tail, data[i]);
            popFront(&buffer);
        }
        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;
    }

我还必须编写一个函数来显示“头”和“尾”之间的元素数量。对于 for 循环,head 和 tail 之间始终存在 1 值,在第一个实现中,head 始终 = 0(当所有缓冲区都实现时,head = tail)。这里的名字是bufferSize。我必须打印出来。

如何解决head和tail的这个问题以及如何编写正确的printBuffer函数?

谢谢

【问题讨论】:

    标签: c


    【解决方案1】:

    这显然是因为您的第一个和第二个实现不使用您在for 循环中使用的popFront(...) 函数。 popFront(...) 正在向前移动你的头,很明显,如果你在同一个周期中推送和弹出数据,你将永远不会在缓冲区中获得超过 1 条记录。

    【讨论】:

    • 无论如何这不是正确的方法。在第一次实现期间,缓冲区是空的,因此应该从 head = 0 到 tail =7(在我的情况下大小为 8 字节时缓冲区的末尾)开始实现,并且只有在第二个圆圈中才能移动头部。或者我什么都没有。
    • 什么圈子?请举例说明您的程序输出,并说明您认为错误的地方。
    • 这里是输出的结果。我把popFront放在循环之前的第二个测试实现ibb.co/k7AGtv
    • 那么问题出在哪里?我编译了你的程序,它完美地完成了它应该做的事情。顺便说一句,在第二个实现中没有头部偏移(从你的第一个帖子复制代码)。我用 Visual Studio 2015 C++ 编译器编译了你的程序。我只需要改变分配部分,但它不应该改变程序的行为。
    • 好吧,看来我并没有完全理解并确定它应该如何工作。由于尾部值,我感到困惑(第二次实现)。现在我用循环实现更改了部分,并将其分为 3 个部分:dataSize = 20 所以第一个是从到 5,第二个是从 5 到 13,第三个是从 13 到
    【解决方案2】:

    好吧,我似乎没有完全理解并确定它应该如何工作。由于尾部值,我感到困惑(第二次实现)。

    现在我用循环实现更改了部分,并将其分为 3 个部分:dataSize = 20,所以第一个是从 5 到 5,第二个是从 5 到 13,第三个是从 13 到 bufferData 作为回报)。

    很抱歉提出这么愚蠢的问题,但我真的很想学习和理解。

    这是我的更正代码和编译结果。 https://ibb.co/e6jnGF

    #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);
    }
    
    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 bufferSize(struct ringBuffer *buffer)
    {
        if (buffer->head >= buffer->tail)
        {
            return (buffer->head - buffer->tail);
        }
        else
        {
            return buffer->size - ((buffer->size - buffer->tail) + buffer->head);
        }
        for (buffer->head = 0; buffer->head < buffer->tail; buffer->head++)
        {
            printf("head[%d] and tail[%d] --> bufferData = %d", buffer->head, buffer->tail, buffer->bufferData);
        }
        return 0;
    }
    
    int printBuffer(struct ringBuffer *buffer)
    {
        for (int i = buffer->head; i < buffer->tail; i++)
        {
            if (buffer->head == buffer->tail)
            {
                printf("Head and tail are equals, not possible to show data\n");
            }
            else
            {
                printf("bufferData = %d\n", buffer->bufferData);
            }
        }
        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]);
    
        bufferInitialization(&buffer, size);
        printf("1st implementation\n");
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail); popFront(&buffer);
        printf("bufferSize = %d\n", bufferSize(&buffer));
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        printf("bufferSize = %d\n", bufferSize(&buffer));
    
        printf("2nd implementation\n");
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        pushBack(&buffer, 10);  printf("head = %d, tail = %d\n", buffer.head, buffer.tail);
        printf("bufferSize = %d\n", bufferSize(&buffer));
        bufferFree(&buffer);
    
        printf("\nInisialization\n");
        bufferInitialization(&buffer, size);
        printf("head = %d, tail = %d - then implementation\n", buffer.head, buffer.tail);
    
        for (int i = 0; i < 5; i++)
        {
            pushBack(&buffer, data[i]);
            printf("head = %d, tail = %d, dataBuffer = %d\n", buffer.head, buffer.tail, data[i]);
        }
        printf("bufferSize = %d\n", bufferSize(&buffer));
        popFront(&buffer);
        printBuffer(&buffer);
        printBuffer((ringBuffer*)buffer.bufferData);
    
        for (int i = 5; i < 13; i++)
        {
            pushBack(&buffer, data[i]);
            printf("head = %d, tail = %d, dataBuffer = %d\n", buffer.head, buffer.tail, data[i]);
        }
        printf("bufferSize = %d\n", bufferSize(&buffer));
        popFront(&buffer);
        printBuffer(&buffer);
        printBuffer((ringBuffer*)buffer.bufferData);
    
        for (int i = 13; i < dataSize; i++)
        {
            pushBack(&buffer, data[i]);
            printf("head = %d, tail = %d, dataBuffer = %d\n", buffer.head, buffer.tail, data[i]);
        }
        printf("bufferSize = %d\n", bufferSize(&buffer));
        popFront(&buffer);
        printBuffer(&buffer);
        printBuffer((ringBuffer*)buffer.bufferData);
    
    
    
        /* 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;
    }
    

    【讨论】:

    • 有人可以发表评论吗?我还没有解决。 @nopasara
    猜你喜欢
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多