• 数据结构:基于数组实现简单的数据缓存区(简单队列)


    1 前言

    在我们使用CAN或者以太网调试时,经常需要缓存最近n次收到的数据,以便于我们对数据进行分析。
    实现这一想法我们很容易就会想到队列,队列就是一种先进先出的数据结构,之前在《数据结构:基于数组的环形队列(循环队列)实现》介绍了基于数组的环形队列(循环队列)的实现,使用到了头尾2个指针,根据头尾指针的关系其实我们可以只使用尾指针就实现循环队列。
    下面介绍一种只使用尾指针实现简单的数据缓存区(简单队列)的方法。

    2 简单队列实现

    2.1 简单队列的定义

    #define MAX_DATA_NO 10   // 数据存储量
    #define MAX_DATA_BUFF 10 // 数据缓存区大小
    typedef struct
    {
        int fullFlg;                              /* 队列满标志 0-未满 1-满*/
        int dataTail;                             /* 队列尾指针 */
        int dataTotalCount;                       /* 总共数据量 */
        int dataLen[MAX_DATA_NO];                 /* 数据长度 */
        int dataBuff[MAX_DATA_NO][MAX_DATA_BUFF]; /* 数据缓存区 */
    } s_queue_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.2 初始化简单队列

    /**
     * @brief 初始化简单队列
     *
     * @param sQueue 简单队列地址
     */
    void init_squeue(s_queue_t *sQueue)
    {
        sQueue->fullFlg = 0;
        sQueue->dataTail = 0;
        sQueue->dataTotalCount = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    初始化简单队列的操作很简单,就是将尾指针、队列满标志、接收数据计数全部清零。

    2.3 添加数据到队列

    /**
     * @brief 添加数据到简单队列
     *
     * @param sQueue 简单队列地址
     * @param dataLen 数据长度
     * @param dataBuff 数据缓存区
     */
    void add_data_to_squeue(s_queue_t *sQueue, int dataLen, int *dataBuff)
    {
        int i;
        sQueue->dataLen[sQueue->dataTail] = dataLen;
        for (i = 0; i < dataLen; i++)
        {
            sQueue->dataBuff[sQueue->dataTail][i] = dataBuff[i];
        }
        sQueue->dataTail++;
        if (sQueue->dataTail >= MAX_DATA_NO)
        {
            sQueue->dataTail = 0;
        }
        sQueue->dataTotalCount++;
        if (sQueue->dataTotalCount >= MAX_DATA_NO)
        {
            sQueue->fullFlg = 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    添加数据到队列就是将数据、数据长度写到尾指针指向的数据缓存区,然后将尾指针后移一位(超出缓存区容量时跳转到0)。

    2.4 简单队列数据打印

    /**
     * @brief 打印简单队列数据
     *
     * @param dataHead 数据头
     * @param dataNum 数据数量
     * @param sQueue 简单队列地址
     */
    void printf_squeue_data(int dataHead, int dataNum, s_queue_t *sQueue)
    {
        int p;
        int i, j, k = 0;
        printf("Num   Len  Data\r\n");
        for (i = 0; i < dataNum; i++)
        {
            p = dataHead + i;
            if (p >= MAX_DATA_NO)
            {
                p -= MAX_DATA_NO;
            }
            printf("%-3d   %-2d   ", ++k, sQueue->dataLen[p]);
            for (j = 0; j < sQueue->dataLen[p]; j++)
            {
                printf("%d ", sQueue->dataBuff[p][j]);
            }
            printf("\r\n");
        }
    }
    /**
     * @brief 简单队列数据处理
     *
     * @param sQueue 队列地址
     */
    void squeue_data_pro(s_queue_t *sQueue)
    {
        int i, j;
        int dataHead, dataTail;
        printf("Total data count : %d\r\n", sQueue->dataTotalCount);
        if (sQueue->fullFlg != 1)
        {
            printf_squeue_data(0, sQueue->dataTotalCount, sQueue);
        }
        else
        {
            dataHead = sQueue->dataTail;
            printf_squeue_data(dataHead, MAX_DATA_NO, sQueue);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    简单队列数据打印分为2个部分:
    (1)数据解析部分
    根据简单队列句柄的队列满标志求得队列头指针值、数据数量。
    (2)数据打印部分
    根据传入的队列头和数据数量打印队列数据信息。

    3 测试

    3.1 添加7个数据(队列未满情况)

    测试程序如下:

    int main(void)
    {
        int i;
        int data[10] = {0, 11, 12, 13, 14, 15, 16, 17, 18, 19};
        s_queue_t sQueue;
        init_squeue(&sQueue);
        for (i = 0; i < 7; i++)
        {
            data[0]++;
            add_data_to_squeue(&sQueue, 10, data);
        }
        squeue_data_pro(&sQueue);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    向简单队列添加7个数据,首个数据从1-7。打印结果如下:
    在这里插入图片描述
    测试正常。

    3.2 添加700个数据(队列满情况)

    测试程序如下:

    int main(void)
    {
        int i;
        int data[10] = {0, 11, 12, 13, 14, 15, 16, 17, 18, 19};
        s_queue_t sQueue;
        init_squeue(&sQueue);
        for (i = 0; i < 700; i++)
        {
            data[0]++;
            add_data_to_squeue(&sQueue, 10, data);
        }
        squeue_data_pro(&sQueue);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    向简单队列添加700个数据,首个数据从1-700。打印结果如下:
    在这里插入图片描述
    测试正常。

  • 相关阅读:
    Docker搭建harbor仓库
    Tdengine技术实践
    探索UniApp分包
    软件设计模式系列之五——建造者模式
    ERV-Net:一种用于脑肿瘤分割的高效3D残差神经网络| 文献速递-深度学习肿瘤自动分割
    指定编码“gbk“,防止中文字符乱码
    Linux中mysql的安装、远程访问、基础操作、文件导入
    R语言风险价值:ARIMA,GARCH,Delta-normal法滚动估计VaR(Value at Risk)和回测分析股票数据...
    什么是区块链,解释区块链的原理和应用场景
    java计算机毕业设计动漫论坛系统MyBatis+系统+LW文档+源码+调试部署
  • 原文地址:https://blog.csdn.net/kevin1499/article/details/136771545