C语言中循环缓冲区的反向遍历

3
我有以下数组,打算将其用作循环缓冲区。
int array1[20]; 

一个线程写入该数组,另一个线程读取该数组。在读取时,我需要读取该数组中最后三个写入的值。
写入操作正常运行。我使用了:
writeIndex = (writeIndex + 1) %20;

写作。这将很好地滚动数组索引0到19。
对于阅读,我正在使用
readIndex = (readIndex -1)%20;

但当我尝试从索引0到19时,它不起作用。

在这里添加更多的代码。 - Grijesh Chauhan
你难道不想读取 writeIndex - 2writeIndex - 1writeIndex 吗?所以 readIndex = (writeIndex - 2) % 20 将会给出最后3次写入的起始位置。 - Hunter McMillen
7
尝试使用readIndex = (readIndex + 19)%20;。在这种情况下,您不希望处理负数。 - Todd Li
请注意,如果您维护readIndexwriteIndex,则很难存储20个项目。当readIndex == writeIndex时,这意味着队列是满的还是空的?(参见Knuth §2.2.2练习1)。最简单的解决方案是改为维护readIndexcount,其中count是当前在队列中的项目数,并在需要时从这些计算出writeIndex - rob mayoff
@YuxiuLi 很好,你得到了我的投票 :-) - cmaster - reinstate monica
显示剩余3条评论
3个回答

6
你的代码
readIndex = (readIndex - 1) % 20;

无法正常工作,因为当readIndex从0开始时,(readIndex - 1) % 20将计算为-1,然后您的数组访问将超出范围。

在这种情况下,您不希望处理负数。为避免发生这种情况,可以简单地将值加上20:

readIndex = (readIndex - 1 + 20) % 20;

或者简单地说
readIndex = (readIndex + 19) % 20;

readIndex从0开始时,您可以向后包装到19。


1

Yuxiu Li已经给出了实用的答案,这里是一些背景信息。

问题在于C语言中除法/取模的定义方式:除法向零舍入,取模由以下公式定义:

a%b == a - (a/b)*b

由于除法向零取整,-1/20 等于零。因此,-1%20 == -1 - 0*20 得到 -1,这不是数组的有效索引。

0

好的,先不考虑线程,这是一个能够实现你想要的功能的测试程序。但是你可能想要添加一些内容来确保至少有3个读数(我没有关注这个)。但是重要的计算是获取当前位置(bufferPos),并找到前3个(N)值。

哦,还有在我注释“lock”和“unlock”的地方,放置你的线程锁定...

#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE (20)
int bufferPos = 0;
int Databuffer[BUFSIZE] = {0};
int BufferWrite(int x)
{
    //lock
    Databuffer[bufferPos] = x;
    bufferPos = (bufferPos+1)%BUFSIZE;
    printf("write[%d] %d\n", bufferPos, Databuffer[bufferPos]);
    //unlock
}
int BufferRead(int count)
{
    int rdx;
    int position;
    //lock
    for( rdx=0; rdx<count; ++rdx )
    {
        position = ((bufferPos-1)-rdx);
        if( position<0 ) position = position+BUFSIZE;
        printf("read[%d:%d] %d\n", rdx, position, Databuffer[position]);
    }
    //unlock
}
int main(int argc, char* argv[])
{
    int ndx; int val;
    char line[999];
    for( ndx=0; ndx<100; ++ndx )
    {
        fgets(line,sizeof(line),stdin);
        BufferWrite(atoi(line));
        if( ndx%7 == 0 )  //read a few, occasionally
        {
            BufferRead(3);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接