循环队列是一种高效的数据结构,适用于缓冲区和数据流应用,例如串口通信接收缓冲。
一、简单的循环队列写法
typedef struct {
int buffer[SIZE];
int head;
int tail;
int count;
} CircularBuffer;
void push(CircularBuffer *cb, int data) {
if (cb->count < SIZE) {
cb->buffer[cb->head] = data;
cb->head = (cb->head + 1) % SIZE;
cb->count++;
}
}
int pop(CircularBuffer *cb) {
if (cb->count > 0) {
int data = cb->buffer[cb->tail];
cb->tail = (cb->tail + 1) % SIZE;
cb->count--;
return data;
}
return -1; // Buffer is empty
}
二、用循环队列写一个缓冲区模块
循环队列缓冲区模块:
代码示例:xqueue.h
#ifndef __XQUEUE_H__
#define __XQUEUE_H__
#include "stdint.h"
/* FIFO数据的类型,可以是结构体类型 */
#define qdata_t uint8_t
/* FIFO长度,实际存放的数据=FIFO_SIZE-1 */
#define FIFO_SIZE 6
typedef enum {
QUEUE_OK,
QUEUE_FULL,
QUEUE_EMPTY
}qstatus_t;
typedef struct {
uint16_t addr_wr; /* 写地址 */
uint16_t addr_rd; /* 读地址 */
uint16_t length; /* FIFO长度,实际存放的数据=length-1 */
qdata_t fifo[FIFO_SIZE];
}queue_t;
qstatus_t queue_reset(queue_t *q);
qstatus_t queue_read(queue_t *q, qdata_t *pdata);
qstatus_t queue_write(queue_t *q, qdata_t data);
int queue_isFull(queue_t *q);
int queue_isEmpty(queue_t *q);
int queue_print(queue_t *q);
#endif
代码示例:xqueue.c文件
#include "xqueue.h"
#include "stdio.h"
/* FIFO复位 */
qstatus_t queue_reset(queue_t *q)
{
int i = 0;
q->addr_wr = 0;
q->addr_rd = 0;
q->length = FIFO_SIZE;
for(i = 0; i < q->length; i++)
q->fifo[i] = 0;
return QUEUE_OK;
}
/* FIFO写入数据 */
qstatus_t queue_write(queue_t *q, qdata_t data)
{
if(queue_isFull(q))
{
printf("Write failed(%d), queue is full\n", data);
return QUEUE_FULL;
}
q->fifo[q->addr_wr] = data;
q->addr_wr = (q->addr_wr + 1) % q->length;
printf("write success: %02d\n", data);
queue_print(q);
return QUEUE_OK;
}
/* FIFO读出数据 */
qstatus_t queue_read(queue_t *q, qdata_t *pdata)
{
if(queue_isEmpty(q))
{
printf("Read failed, queue is empty\n");
return QUEUE_EMPTY;
}
*pdata = q->fifo[q->addr_rd];
q->addr_rd = (q->addr_rd + 1) % q->length;
printf("read success: %02d\n", *pdata);
queue_print(q);
return QUEUE_OK;
}
/* FIFO是否为空 */
int queue_isEmpty(queue_t *q)
{
return (q->addr_wr == q->addr_rd);
}
/* FIFO是否为满 */
int queue_isFull(queue_t *q)
{
return ((q->addr_wr + 1) % q->length == q->addr_rd);
}
/* FIFO内数据的个数 */
int queue_count(queue_t *q)
{
if(q->addr_rd <= q->addr_wr)
return (q->addr_wr - q->addr_rd);
//addr_rd > addr_wr;
return (q->length + q->addr_wr - q->addr_rd);
}
/* 打印当前FIFO内的数据和读写指针的位置 */
int queue_print(queue_t *q)
{
int i = 0;
int j = 0;
for(i = 0; i < q->addr_rd; i++)
printf(" ");
printf("rd=%d", q->addr_rd);
printf("\n");
for(i = 0; i < q->length; i++)
{
if(q->addr_wr > q->addr_rd)
{
if(i >= q->addr_rd && i < q->addr_wr)
printf("[%02d] ", q->fifo[i]);
else
printf("[ ] ");
}
else//addr_rd > addr_wr
{
if(i < q->addr_wr || i >= q->addr_rd)
printf("[%02d] ", q->fifo[i]);
else
printf("[ ] ");
}
}
printf("------count = %d\n", queue_count(q));
for(i = 0; i < q->addr_wr; i++)
printf(" ");
printf("wr=%d", q->addr_wr);
printf("\n");
return QUEUE_OK;
}
实际应用:
#include <stdio.h>
#include <stdlib.h>
#include "xqueue.h"
int main(int argc, char *argv[])
{
queue_t queue;
qdata_t data;
queue_reset(&queue);
queue_write(&queue, 1);
queue_write(&queue, 2);
queue_write(&queue, 3);
queue_read(&queue, &data);
queue_read(&queue, &data);
queue_write(&queue, 4);
queue_write(&queue, 5);
queue_write(&queue, 6);
queue_write(&queue, 7);
queue_read(&queue, &data);
queue_read(&queue, &data);
queue_read(&queue, &data);
queue_write(&queue, 8);
queue_write(&queue, 9);
queue_write(&queue, 10);
queue_read(&queue, &data);
system("pause");
return 0;
}
|