隊列-數組隊列實現-DTU緩衝區原型.c

// 緩衝區-數組隊列實現 可在VC6.0下編譯通過
// 使用MTK平臺做DTU產品的時候,需要將串口的數據緩存到內存,然後通過網絡發送數據,
// 所以要記錄下來本次存入數據長度和數據內容,以便下次發往網絡時可將本次存入數據整段發送出去
// 另外,MTK中,動態分配內存效率較整體分配內存穩定性差,採用數組隊列形式實現
// 功能,向緩衝區讀寫數據
// 對外接口 dtu_buffer_get_data / dtu_buffer_add_data
// 本程序實現記錄本次存入數據多少,下次取出來時,會取出相同數量數據
// 最多容納數據數量份數爲MAX_L_SIZE,最多容納數據總和爲MAX_SIZE
#include <stdio.h>
#include <memory.h>

#include <stdlib.h>
#include <time.h>

#define MAX_SIZE 1024                       // 緩衝區最大容納數據總和

struct arrQueue                             // 聲明隊列的頭和尾節點,數據存儲元素
{
    unsigned char       data[MAX_SIZE+1];   // 定義數組隊列元素,能容納MAX_SIZE字節
    unsigned int        front;              // 含有數據的第一個下標
    unsigned int        rear;               // 含有數據的最後一個元素下標,rear所在的元素不存數據
}queue;

void initQueue()
{
    memset(queue.data, '\0', sizeof(queue.data));
    queue.front = 0;
    queue.rear  = 0;
}


void enQueue(unsigned char *pElement, unsigned int *len)//向queue中存入長度爲len字節數據,len返回長度實際存入的長度
{
    // 如果rear在front前面一位,則表明緩衝區已經滿,無法存入數據
    // 當rear在最後一位,front在最前一位,也是沒有空間
    if ((queue.rear+1)%(MAX_SIZE+1) == queue.front)
    {
        *len = 0;
        return;
    }

    // 如果rear在front前面一位以上,則rear與front之間就是空閒區域,長度爲front-rear-1
    if (queue.rear+1<queue.front)
    {
        // 存入數據位len與剩餘空間較小者
        *len = *len <= (queue.front-queue.rear-1) ? *len : queue.front-queue.rear-1;
        
        memcpy(&queue.data[queue.rear], pElement, *len);
        queue.rear += *len;
    }
    else    // 如果 rear在front後面,或者相等時,並且有空間
    {
        // 剩餘空間大小爲 MAX_SIZE-(rear-front), 可寫入的數據位長度與剩餘空間較小者
        *len = *len <= (MAX_SIZE-(queue.rear-queue.front)) ? *len : MAX_SIZE-(queue.rear-queue.front);
        // 如果front爲0,則rear就在小於等於MAX_SIZE的位置,只需要隊列尾部保存數據
        if (queue.front==0)
        {
            memcpy(&queue.data[queue.rear], pElement, *len);
            queue.rear += *len;
        }
        else // 如果front不爲0,則 隊列尾保存了數據,隊列頭部有可能需要保存數據
        {
            // 如果尾部可以保存數據,則直接保存數據
            if ((MAX_SIZE+1-queue.rear) >= *len)
            {
                memcpy(&queue.data[queue.rear], pElement, *len);
                queue.rear = (queue.rear + *len)%(MAX_SIZE+1);
            }
            else // 如果尾部保存不了數據,頭部還需要保存數據,尾部保存的數據長度爲:MAX_SIZE+1-queue.rear
            {
                memcpy(&queue.data[queue.rear], pElement, MAX_SIZE+1-queue.rear);
                queue.rear = *len-(MAX_SIZE+1-queue.rear);
                memcpy(&queue.data[0], pElement+(*len-queue.rear), queue.rear);
            }
        }
    }
}

void deQueue(unsigned char *pElement, unsigned int *len)//向queue中取出長度爲len字節數據,len返回長度實際取出的長度
{
    // 如果爲空數據
    if ((*len==0) || (queue.rear==queue.front))
    {
        *len = 0;
        return;
    }

    // 如果 rear在front後面,則直接取出數據
    if (queue.rear > queue.front)
    {
        *len = *len <= (queue.rear-queue.front) ? *len : (queue.rear-queue.front);
        memcpy(pElement, &queue.data[queue.front], *len);
        queue.front += *len;
    }
    else    // 如果rear在front前面
    {
        // 隊列中數據長度爲 rear+(MAX_SIZE+1-front)
        *len = *len <= queue.rear+(MAX_SIZE+1-queue.front) ? *len : queue.rear+(MAX_SIZE+1-queue.front);
        
        // 如果尾部可以取出*len的數據則直接取,尾部數據大小爲MAX_SIZE+1-queue.front
        if (*len <= MAX_SIZE+1-queue.front)
        {
            memcpy(pElement, &queue.data[queue.front], *len);
            queue.front = (queue.front + *len) % (MAX_SIZE+1);
        }
        else    // 如果尾部取完,還需要取數據,則取頭部數據
        {
            memcpy(pElement, &queue.data[queue.front], (MAX_SIZE+1-queue.front));
            queue.front = *len-(MAX_SIZE+1-queue.front);
            memcpy(&pElement[*len-queue.front], &queue.data[0], queue.front);
        }
    }
}

unsigned int lenQueue()     // 隊列存了多少數據
{
    return (queue.rear+MAX_SIZE+1-queue.front)%(MAX_SIZE+1);
}


/////////////////////////////////長度數組隊列///////////////////////////////////
#define MAX_L_SIZE      128   // 最多存入數據份數,一次存入數據位一份數據
struct LQueue
{
    unsigned int data[MAX_L_SIZE];
    unsigned int front;
    unsigned int rear;
}lqueue;

void initLQueue()
{
    memset(lqueue.data, '\0', sizeof(lqueue.data));
    lqueue.front = 0;
    lqueue.rear = 0;
}

void enLQueue(unsigned int *len)    // 插入長度len, len不能爲0,插入正確len不改變,插入錯誤len爲0
{
    if ((lqueue.rear+1)%MAX_L_SIZE == lqueue.front)     // 隊列已滿
    {
        *len = 0;
    }
    else
    {
        lqueue.data[lqueue.rear] = *len;
        lqueue.rear = (lqueue.rear+1)%MAX_L_SIZE;
    }

}

void deLQueue(unsigned int *len)    // 返回一個長度len數值,len爲0則隊列爲空
{
    if (lqueue.rear == lqueue.front)    // 隊列爲空
    {
        *len = 0;
    }
    else
    {
        *len = lqueue.data[lqueue.front];
        lqueue.data[lqueue.front] = 0;  // 還原數據爲0
        lqueue.front = (lqueue.front+1)%MAX_L_SIZE;
    }
}

unsigned int lenLQueue()            // 獲取隊列存入多少len數值
{
    return (lqueue.rear+MAX_L_SIZE-lqueue.front)%MAX_L_SIZE;
}
/////////////////////////////////長度隊列///////////////////////////////////



// 緩衝區對外兩個接口函數
//////////////////////////////////////////////////////////////////////
// 寫入數據到緩衝區,若緩衝區存不下需要放入的數據,則刪除前面存入的數據
unsigned char dtu_buffer_add_data(const unsigned char *pbuf, unsigned int len)
{
    unsigned int len_t = 0;
    unsigned char pbuf_t[128] = {0x0, };
    if ((pbuf==NULL) || (len==0))
    {
        return 0;
    }
    
    while (MAX_SIZE-lenQueue() < len)   // 如果緩衝區滿了,則刪除以前的的數據
    {
        deLQueue(&len_t);
        deQueue((unsigned char*)pbuf_t, &len_t);
        printf("【%d-%s】\r\n", len_t, pbuf_t);
    }
    if (MAX_L_SIZE==lenLQueue()+1)      // 如果長度隊列滿了,則刪除一個長度隊列
    {
        deLQueue(&len_t);
        deQueue((unsigned char*)pbuf_t, &len_t);
        printf("【%d-%s】\r\n", len_t, pbuf_t);
    }

    enLQueue(&len);
    enQueue((unsigned char*)pbuf, &len);

    return 1;
}

// 從緩衝區獲取內容
unsigned char dtu_buffer_get_data(unsigned char* pbuf, unsigned int* len)
{
    unsigned char result = 0;
    if (pbuf==NULL)
        return result;

    deLQueue((unsigned int*)len);
    deQueue((unsigned char*)pbuf, (unsigned int*)len);
    if (*len)
        result = 1;

    return result;
}

/////////////////////////////////////////////////////////////////////////

void main()
{
    int i = 0;
    int len = 1;
    char buf[32];
    initQueue();

    // 測試1,正常情況
    queue.front = 0;
    queue.rear  = 0;
    // 測試2,front在前,rear在後
    //queue.front   = 5;
    //queue.rear    = 7;
    // 測試3,front在後,rear在前
    //queue.front   = 26;
    //queue.rear    = 8;

    // 測試四個存入////////////////////////

    printf("begin==========\r\n");
    for (i=0, len=1; len; i++)
    {
        len = 4;
        buf[0] = 'A'+4*i;
        buf[1] = 'A'+4*i+1;
        buf[2] = 'A'+4*i+2;
        buf[3] = 'A'+4*i+3;
        printf("%d-", lenQueue());
        enQueue(buf, &len);
        printf("%d ", len);
    }
    printf("\r\n");
    for (i=0; i<MAX_SIZE+1; i++)
    {
        printf("%c ", queue.data[i]);
    }
    printf("\r\n");
    // 測試四個存入 end////////////////////

    // 測試四個取出////////////////////////
    for (i=0, len=1; len; i++)
    {
        len = 4;
        printf("%d-", lenQueue());
        deQueue(buf, &len);
        buf[len] = '\0';
        printf("%d-%s\r\n", len, buf);
    }
    printf("end============\r\n");
    // 測試四個取出 end////////////////////


    // 採用隨機數測試//////////////////////
{
    int value_f;
    int value_r;
    srand(time(0));
    value_f = rand() % (MAX_SIZE+1);
    value_r = rand() % (MAX_SIZE+1);
    initQueue();
    queue.front = value_f;
    queue.rear  = value_r;
    printf("\r\nbegin========== %d %d\r\n", value_f, value_r);

    for (i=0, len=1; len; i++)
    {
        len = 4;
        buf[0] = 'A'+4*i;
        buf[1] = 'A'+4*i+1;
        buf[2] = 'A'+4*i+2;
        buf[3] = 'A'+4*i+3;
        printf("%d-", lenQueue());
        enQueue(buf, &len);
        printf("%d ", len);
    }
    printf("\r\n");
    for (i=0; i<MAX_SIZE+1; i++)
    {
        printf("%c ", queue.data[i]);
    }
    printf("\r\n");

    for (i=0, len=1; len; i++)
    {
        len = 4;
        printf("%d-", lenQueue());
        deQueue(buf, &len);
        buf[len] = '\0';
        printf("%d-%s\r\n", len, buf);
    }
    printf("\r\nend============\r\n");
}
    // 採用隨機數測試 end//////////////////


    ////////////////////////////測試lqueue////////////////////////
    initLQueue();
    lqueue.front    = 0;
    lqueue.rear     = 0;

    // 測試存入////////////////////////
    printf("\r\nlqueue begin==========\r\n");
    for (i=0, len=i+1; len; i++)
    {
        len = i+1;
        enLQueue(&len);
        printf("%d-%d ", lenLQueue(), len);

        if (!((i+1)%3))     // 測試取出一部分數據
        {
            deLQueue(&len);
            printf("de-%d ", len);
        }
    }
    printf("\r\n");
    for (i=0; i<MAX_L_SIZE; i++)
    {
        printf("%d ", lqueue.data[i]);
    }
    printf("\r\n");

    // 測試取出/////////////////////////////
    for (len = 1; len; )
    {
        printf("%d-", lenLQueue());
        deLQueue(&len);
        printf("%d ", len);
    }
    printf("\r\n");
    for (i=0; i<MAX_L_SIZE; i++)
    {
        printf("%d ", lqueue.data[i]);
    }
    printf("\r\nlqueue end============\r\n");
    // 測試end////////////////////
    ////////////////////////////測試lqueue////////////////////////

    // 測試 dtu_buffer_add_data / dtu_buffer_get_data
    ////////////////////////////測試 begin////////////////////////
    printf("add begin============\r\n");
    len = 4;
    i = 0;
    while (i!=10)
    {
        sprintf(buf, "abc%d", i);
        dtu_buffer_add_data(buf, len);
        i++;
    }
    printf("add end=============\r\n");
    printf("get begin============\r\n");
    while (dtu_buffer_get_data(buf, &len) )
    {
        printf("%d-%s\r\n", len, buf);
    }
    printf("get end=============\r\n");
    // 測試end////////////////////
    ////////////////////////////測試 end//////////////////////////
}
發佈了17 篇原創文章 · 獲贊 55 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章