2017-03-20 76 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; 
}