C中的循环(环)缓冲区写入方法

时间:2014-06-28 23:49:41

标签: c file file-io buffer

我试图创建一个文本文件的精确副本,我正在使用循环缓冲区。

我使用的写入方法是:

void addItem(CircularBuffer *cBuff, BufferItem *cbItem) {
    cBuff->cBuffItems[cBuff->lastInd] = *cbItem;
    cBuff->lastInd = ( ((cBuff->lastInd) + 1) % cBuff->size);
    if (cBuff->lastInd == cBuff->startInd)
    {
        cBuff->startInd = (cBuff->startInd + 1) % cBuff->size; // Overwriting full buffer.
    }
}

以下是我将每个char复制到缓冲区的方法:

BufferItem result;
char ch;
while( ( ch = fgetc(fp) ) != EOF ){
    result.offset = ftell(fp);
    result.data = ch;
    addItem(&cBuff, &result);
}

它只写前三个字符然后给我一个分段错误。我确保缓冲区大小足够大,我尝试过不同的数据集,都给出了相同的结果(只有前3个字符被复制到缓冲区中)。

如果我不将它添加到缓冲区,只打印result.offset和result.data,我得到了我的期望。所以addItem一定是问题所在,如果我删除addItem中的第二行,它可以工作,但很明显它只会覆盖第一个点。

我做错了什么?

编辑:

这是循环缓冲区和循环缓冲区实现:

// Circular buffer items.
typedef  struct {
     char  data ;
     off_t offset ;
} BufferItem ;

// Circular buffer
typedef struct {
    int startInd; // Index of first element added to buffer.
    int lastInd; // Index of most recent element added to buffer.
    int size; // Number of elements in circular buffer.
    BufferItem *cBuffItems; // Circular buffer items.
} CircularBuffer;

void initializeBuffer(CircularBuffer *cBuff, int size) {
    cBuff->cBuffItems = calloc(cBuff->size, sizeof(BufferItem));
    cBuff->size  = size + 1;
    cBuff->startInd = 0;
    cBuff->lastInd   = 0;
}

就像我提到的,我做了初始化缓冲区,这里是main的简化版本:

int main( int argc, char *argv[] )
{
    if (argc != 4)
    {
        printf("Expected 3 arguments, received %d\n", argc - 1);
        return 1;
    }

    int bufSize; // Capacity of BufferItems in circular buffer.
    char *file; // Pathname of file to be copied.
    char *copy; // Name to be given to the copy.

    sscanf(argv[1], "%d", &bufSize);
    file = argv[2];
    copy = argv[3];

    initializeBuffer(&cBuff, bufSize);

    // Open file to be copied.
    FILE *fp = fopen(file, "r" );

    // Create copy file.
    FILE *cp = fopen(copy, "w+" ); // Overwrite if file exists.

    BufferItem result;
    char ch;
    while( ( ch = fgetc(fp) ) != EOF ){
        result.offset = ftell(fp);
        result.data = ch;
        addItem(&cBuff, &result);
    }

    fclose(fp);
    fclose(cp);

    return 0;
}// Main.

1 个答案:

答案 0 :(得分:1)

显示初始化代码后,问题很明显:您在设置之前使用cBuff->size

void initializeBuffer(CircularBuffer *cBuff, int size) {
    cBuff->cBuffItems = calloc(cBuff->size, sizeof(BufferItem));
    cBuff->size  = size + 1;
    cBuff->startInd = 0;
    cBuff->lastInd   = 0;
}

因此,您使用准随机大小,并获得相应的准随机结果。正如您现在所看到的那样,您最初没有显示的代码会导致问题 - 这就是我们必须要求查看可行示例的原因!

你可以非常简单地修复它:

void initializeBuffer(CircularBuffer *cBuff, int size) {
    cBuff->cBuffItems = calloc(size + 1, sizeof(BufferItem));
    cBuff->size  = size + 1;
    cBuff->startInd = 0;
    cBuff->lastInd   = 0;
}

这使用参数size而不是cBuff的未初始化元素。我建议分配一些项目,然后说有不同数量的项目可供使用会导致麻烦。我选择在这两个数字中添加一个;但总的来说,在没有增量的情况下使用size的值可能会更好。

您还可以重新排序分配(因此在分配cBuff->size之前设置cBuff->cBuffItems);这也有效(只要你使分配大小与记录的大小一致。

你应该可以检查calloc()的结果。