2017-03-20 21 views
-2

我刚开始学习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; 
    } 

感谢您的任何帮助和建议!

+2

你解决编写代码之前在纸上出现问题? –

+3

1)编写几个单元测试,以显示程序运行正常。 2)调试所有的单元测试失败时,您可以找到并修复您的逻辑错误。 3)利润 – AndyG

+2

“调试我的代码”不在这里的话题。你调试它,然后你告诉我们问题是什么。显示它做什么以及它应该做什么。最好有一个最小的,完整的和可验证的例子:https://stackoverflow.com/help/mcve – klutt

回答

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; 
} 
+0

欢迎来到Stack Overflow!虽然这段代码片段是受欢迎的,并且可能会提供一些帮助,但如果它包含* how *和* why *的解释](// meta.stackexchange.com/q/114762),它会[大大改进],这将解决问题。请记住,你正在为将来的读者回答这个问题,而不仅仅是现在问的人!请编辑您的答案以添加解释,并指出适用的限制和假设。 –

+0

您只需要尺寸,而不是容量和尺寸。您需要pushBack中的数据大小。如果数据只包含“a”,则不能memcpy buffer-> size字节。在memcpy之后,您将按数据大小递增缓冲区 - >头部。在memcpy之前,你必须检查,如果buffer-> size - buffer-> head是> =数据大小。 – Holger

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; 
} 
+0

为什么我们使用指针头部和尾部?和“结束”相同的问题 @Holger –

+0

比较指针'head == end'非常简单 – Holger

1

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

现在我需要编写一个printBuffer函数来显示dataBuffer中从HEAD到TAIL的值,但是我注意到一个问题:每次我在缓冲区中写入一个值时,HEAD和TAIL之间的差值总是为1(正如我所理解的当缓冲区为空时,size = 8,并且数据[]中只有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; 
}