队列-数组队列实现-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//
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值