<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
佇列原理其實就像一個管道,如果我們不斷往管道里面塞乒乓球,每個乒乓球在管道里就會排列一條隊形。先進去的乒乓球就會先出來,這個就是佇列的先進先出的規則。
球從左邊進去,進去的動作就是入列,然後進去的球在管道里排成一個佇列,這個叫佇列快取,說白了就是陣列,那麼這裡存了5個球就相當於是buff[5];這樣的意思,最右邊出來的1號球就是最早進去的球,出來的這個動作叫出列,所以遵循了先進先出的規則。
佇列最主要的作用就是用來快取資料,比方說串列埠接收資料,我們一般定義一個陣列來儲存資料,但是假如串列埠資料頻率很快,可能這個陣列裡儲存的資料還沒處理完,下一組串列埠資料又過來了,那麼這時候陣列裡的資料就會被新資料覆蓋,導致老的資料丟失。像這種就可以通過佇列的方式來處理,每收到一個位元組資料都先入列,然後應用程式同步解析處理,根據佇列先進先出的規則,那麼老的資料就不會被新的資料“插隊”了。
基於這種快取資料的技術,可以靈活應用在各種場景,比如說:
其實實現佇列的方法有很多種,但是工作原理都是一樣的,我們要編寫程式碼,首先要很清楚佇列的工作原理。
入列和出列的原理懂了,那麼應該怎麼樣用程式來實現呢?
根據上文的說法,入列就是把資料存進陣列的操作,我們平時存陣列一般都是buff[0]=1;這樣操作。不過在佇列中我們要考慮佇列裡當前存在多少個資料的情況,如果有資料,那麼我們就不能從[0]這個下標開始入列,所以我們在入列時要考慮兩個問題:
丟棄,以新的資料替換。
第二個問題先暫時不管,先看第一個問題。根據前面學過的陣列與指標,通過指標的特性,我們在用1個指標來代表隊尾,然後這個隊尾指標指向佇列快取陣列的首地址,當入列1個資料時,我們的隊尾指標就+1,這樣是不是就能夠知道當前佇列快取的可以儲存的地址了?
資料入列以後自然要取出來,那麼我們取的時候也是有原則的,不能亂取,而是從最早入列那個資料的地址開始取,所以這個出列的陣列下標我們稱為隊頭,同樣我們可以使用指標變數來代表這個隊頭。
我們看看下面這個圖是一個出列的流程,我們這個是滿編隊的佇列,總共有1,2,3,4,5個資料,那麼隊頭指標指向佇列快取首地址,接著第一個出列的就是資料1,出列後隊頭指標加1,就指向資料2的地址,那麼資料2出列後,隊頭指標又加1,指向資料3的地址,以此類推,這樣就可以實現先進先出的原則。
那麼我們知道原理後就可以用程式來實現它了,因為一個產品中,會有很多佇列代表不同的資料,比如說訊息我有一個佇列,底層串列埠接收我也有一個佇列,所以我們吧佇列的一些操作,比如說入列,出列的操作單獨寫成函數介面,方便程式不同區域的呼叫。
#include <stdio.h> #include "Queue.h" Queue4 KeyMsg; int main(int argc, char *argv[]) { unsigned char a; QueueEmpty(KeyMsg);/*初始化*/ printf("site:%drn",sizeof(KeyMsg.Buff)); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("&buff[0]=0x%x, &buff[1]=0x%x, &buff[2]=0x%x, &buff[3]=0x%x rn",&KeyMsg.Buff[0],&KeyMsg.Buff[1],&KeyMsg.Buff[2],&KeyMsg.Buff[3]); printf("rn"); a = 1; QueueDataIn(KeyMsg,&a,1);/*要用哪一個佇列,要存那個資料,要存多少個資料*/ printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); a = 2; QueueDataIn(KeyMsg,&a,1); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); a = 3; QueueDataIn(KeyMsg,&a,1); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); a = 4; QueueDataIn(KeyMsg,&a,1); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); a = 5; QueueDataIn(KeyMsg,&a,1); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); QueueDataOut(KeyMsg,&a);/*要用哪一個佇列,要取那個資料*/ printf("a=%drn",a); printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%xrn",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail); printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x rn",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]); printf("rn"); 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
串列埠的應用:
如果產品有兩個功能,一個功能需要燈一秒閃1次,另一個功能需要燈1秒閃2次,在功能切換很快的情況下,需要功能正常並且燈的閃爍正常,那麼就需要佇列了。
到此這篇關於C語言佇列和應用詳情的文章就介紹到這了,更多相關C語言佇列和應用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45