文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言队列和应用详情

2024-04-02 19:55

关注

1.队列的原理

队列原理其实就像一个管道,如果我们不断往管道里面塞乒乓球,每个乒乓球在管道里就会排列一条队形。先进去的乒乓球就会先出来,这个就是队列的先进先出的规则。

球从左边进去,进去的动作就是入列,然后进去的球在管道里排成一个队列,这个叫队列缓存,说白了就是数组,那么这里存了5个球就相当于是buff[5];这样的意思,最右边出来的1号球就是最早进去的球,出来的这个动作叫出列,所以遵循了先进先出的规则。

2.队列的作用

队列最主要的作用就是用来缓存数据,比方说串口接收数据,我们一般定义一个数组来存储数据,但是假如串口数据频率很快,可能这个数组里存储的数据还没处理完,下一组串口数据又过来了,那么这时候数组里的数据就会被新数据覆盖,导致老的数据丢失。像这种就可以通过队列的方式来处理,每收到一个字节数据都先入列,然后应用程序同步解析处理,根据队列先进先出的规则,那么老的数据就不会被新的数据“插队”了。

基于这种缓存数据的技术,可以灵活应用在各种场景,比如说:

3.队列程序设计思路

其实实现队列的方法有很多种,但是工作原理都是一样的,我们要编写代码,首先要很清楚队列的工作原理。

入列和出列的原理懂了,那么应该怎么样用程序来实现呢?

4.入列

根据上文的说法,入列就是把数据存进数组的操作,我们平时存数组一般都是buff[0]=1;这样操作。不过在队列中我们要考虑队列里当前存在多少个数据的情况,如果有数据,那么我们就不能从[0]这个下标开始入列,所以我们在入列时要考虑两个问题:

丢弃,以新的数据替换。
第二个问题先暂时不管,先看第一个问题。根据前面学过的数组与指针,通过指针的特性,我们在用1个指针来代表队尾,然后这个队尾指针指向队列缓存数组的首地址,当入列1个数据时,我们的队尾指针就+1,这样是不是就能够知道当前队列缓存的可以存储的地址了?

5.出列

数据入列以后自然要取出来,那么我们取的时候也是有原则的,不能乱取,而是从最早入列那个数据的地址开始取,所以这个出列的数组下标我们称为队头,同样我们可以使用指针变量来代表这个队头。
我们看看下面这个图是一个出列的流程,我们这个是满编队的队列,总共有1,2,3,4,5个数据,那么队头指针指向队列缓存首地址,接着第一个出列的就是数据1,出列后队头指针加1,就指向数据2的地址,那么数据2出列后,队头指针又加1,指向数据3的地址,以此类推,这样就可以实现先进先出的原则。

6.掌握队列程序编写

那么我们知道原理后就可以用程序来实现它了,因为一个产品中,会有很多队列代表不同的数据,比如说消息我有一个队列,底层串口接收我也有一个队列,所以我们吧队列的一些操作,比如说入列,出列的操作单独写成函数接口,方便程序不同区域的调用。

#include <stdio.h>
#include "Queue.h"
Queue4 KeyMsg;

int main(int argc, char *argv[])
{
    unsigned char a; 
    QueueEmpty(KeyMsg);
    printf("site:%d\r\n",sizeof(KeyMsg.Buff)); 
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("&buff[0]=0x%x, &buff[1]=0x%x, &buff[2]=0x%x, &buff[3]=0x%x \r\n",&KeyMsg.Buff[0],&KeyMsg.Buff[1],&KeyMsg.Buff[2],&KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 1;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 2;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 3;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 4;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 5;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    QueueDataOut(KeyMsg,&a);
    printf("a=%d\r\n",a); 
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    return 0;
}

queue.c代码

void S_QueueEmpty(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff)
{
    *Head = pBuff;
    *Tail = pBuff; 
}

void S_QueueDataIn(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen)
{
    unsigned char num;
    //关闭中断 
    for(num=0; num < DataLen; num++,pData++)
    {    
        **Tail = *pData;        //这里把数据入列 
        (*Tail)++;                //队尾指针加1
         if(*Tail == pBuff+Len)
         {
             *Tail = pBuff; 
         }
        if(*Tail == *Head)
        {
            
            if(++(*Head) == pBuff+Len)
            {
                *Head = pBuff;    
            }
        }
    }
    //打开中断 
}

unsigned char S_QueueDataOut(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData)
{
    unsigned char status;
    //关闭中断 
    status = 0;
    if(*Head != *Tail)
    {
        *pData = **Head;
        status = 1;
        if(++(*Head) == pBuff+Len)
        {
            *Head = pBuff;
        }
    }
    //恢复中断 
    return status;
}

unsigned short S_QueueDataLen(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len)
{
    if(*Tail > *Head)
    {
        return *Tail-*Head;
    }
    if(*Tail < *Head)
    {
        return *Tail+Len-*Head;    
    }
}

queue.h代码

#ifndef _QUEUE_H_
#define _QUEUE_H_

extern void S_QueueEmpty(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff);
extern void S_QueueDataIn(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen);
extern unsigned char S_QueueDataOut(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData); 
extern unsigned short S_QueueDataLen(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len); 

#define QueueEmpty(x)  S_QueueEmpty((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)(x).Buff)

#define QueueDataIn(x,y,z) S_QueueDataIn((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff),y,z)
#define QueueDataOut(x,y)  S_QueueDataOut((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff),y)
#define QueueDataLen(x)     S_QueueDataLen((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff))
 
typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[4];    //队列缓存 
}Queue4;

typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[128];    //队列缓存 
}Queue128;

typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[512];    //队列缓存 
}Queue512;
#endif

7.队列的应用

串口的应用:

如果产品有两个功能,一个功能需要灯一秒闪1次,另一个功能需要灯1秒闪2次,在功能切换很快的情况下,需要功能正常并且灯的闪烁正常,那么就需要队列了。

到此这篇关于C语言队列和应用详情的文章就介绍到这了,更多相关C语言队列和应用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯