C語言循環數組做FIFO隊列

C語言循環數組做FIFO隊列

在做通信時,FIFO隊列queue是非常好用的,先完成接收通信把接收的數據存在隊列裏;然後再進行先進先出逐項處理。

C語言用循環數組,通過讀位置和寫位置循環來實現FIFO隊列功能。即數組隊列。

1 以1個字節爲單位的數組隊列的數據結構

使用數組隊列,爲了方便判斷隊列空和隊列滿,使用不完全填滿隊列,即保留一個元素始終不用

下面是兩個例子

char usart1_rev_buf[USART1_BUFFER_MAX_SIZE] = {0}; //usart receive buffer.
unsigned short usart1_r = 0; //usart receive buffer read position.
unsigned short usart1_w = 0; //usart receive buffer write position.

char sendBufForUsart[SEND_BUF_MAX_SIZE] = {0}; //usart send buffer.
unsigned short sendWrite = 0; //usart send buffer write position.
unsigned short sendRead = 0; //usart send buffer read position.

記住:

sendRead 是下一個將要讀取的位置,現在還未讀取。

 相當於隊列頭front,可執行delete操作。

sendWrite 是下一個將要寫入的位置,現在還未寫入。

 相當於隊列尾rear,可執行insert操作。

保留不用的元素位置是((sendRead+SEND_BUF_MAX_SIZE-1)%SEND_BUF_MAX_SIZE)。

判斷隊列空? sendRead == sendWrite

判斷隊列滿? (sendWrite+1)%SEND_BUF_MAX_SIZE == sendRead

寫操作

WrData爲待寫入的字節內容,WrBuf爲待寫入的內容buf,WrLen爲待寫的長度。

寫一個字節

      if ((usart1_w+1)%USART1_BUFFER_MAX_SIZE != usart1_r)
      {
           usart1_rev_buf[usart1_w] = WrData;
           usart1_w = (usart1_w+1) % USART1_BUFFER_MAX_SIZE;
      }  

寫多個字節

unsigned short emptyLen;
unsigned short tmpAddr;
unsigned short tmpLen;

emptyLen = (sendRead+SEND_BUF_MAX_SIZE-(sendWrite+1)) % SEND_BUF_MAX_SIZE;
if (emptyLen >= WrLen)
{
tmpAddr = (sendWrite+WrLen) % SEND_BUF_MAX_SIZE;
if (tmpAddr <= sendWrite) //If Circular array have inverse to begin.
{
tmpLen =WrLen - tmpAddr;
memcpy(&sendBufForUsart[sendWrite], WrBuf, tmpLen); //bug place
memcpy(&sendBufForUsart[0], WrBuf+tmpLen, tmpAddr);
}
else
{
memcpy(&sendBufForUsart[sendWrite], WrBuf, WrLen);
}

 sendWrite = tmpAddr;

}

讀操作

RdBuf爲存儲讀取內容的buf,RdLen爲待讀的長度。

讀一個字節

 if (usart1_r != usart1_w)    //Have new data in usart receive buffer.
 {
      *RdBuf = usart1_rev_buf[usart1_r];
      usart1_r = (usart1_r+1) % USART1_BUFFER_MAX_SIZE;     //Read out one byte.
 }

讀多個字節

 unsigned short validLen;
 unsigned short tmpAddr;
 unsigned short tmpLen;

 validLen = (sendWrite+SEND_BUF_MAX_SIZE-sendRead) % SEND_BUF_MAX_SIZE;
 if (validLen >= RdLen)
 {
     tmpAddr = (sendRead+RdLen) % SEND_BUF_MAX_SIZE;
     if (tmpAddr <= sendRead) //If Circular array have inverse to begin.
     {
       tmpLen =RdLen - tmpAddr;
       memcpy(RdBuf, &sendBufForUsart[sendRead], tmpLen);
       memcpy(RdBuf+tmpLen, &sendBufForUsart[0], tmpAddr);     
     }
     else
     {
       memcpy(RdBuf, &sendBufForUsart[sendRead], RdLen);
     }
     sendRead = tmpAddr;

}

10.2 以固定N_LEN個字節爲單位的隊列的數據結構。使用二維數組隊列。

要求每次寫隊列和每次讀隊列,長度都固定是N_LEN。

下面是一個例子,每次讀寫固定長度爲CMD_LENGTH,我使用二維數組實現。根據應用不同,也可選結構體數組。

char sendBufForUsart[SEND_BUF_MAX_NUM][CMD_LENGTH] = {0};
unsigned short sendWrite = 0;
unsigned short sendRead = 0;

寫CMD_LENGTH長度

      if ((sendWrite+1)%SEND_BUF_MAX_NUM != sendRead)    //Have new data.
      {
          memcpy(&sendBufForUsart[sendWrite][0], WrBuf, CMD_LENGTH);
          sendWrite = (sendWrite+1) % SEND_BUF_MAX_NUM;    //Read out one byte.
      }

讀CMD_LENGTH長度

      if (sendRead != sendWrite)
      {
          memcpy(RdBuf, &sendBufForUsart[sendRead][0], CMD_LENGTH);
          sendRead = (sendRead + 1) % SEND_BUF_MAX_NUM;
      }

用結構可以更明瞭的說明循環隊列的使用

*typedef struct{

  • valuetype data[MAXSIZE]; [>數據的存儲區<]
  • int font, rear; [>隊首隊尾<]
  • int num; [>隊列中元素的個數<]
    *}Circular_Queue;

轉自 :https://blog.csdn.net/shoutday/article/details/8204770#commentBox

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章