本队列原理
- Node:节点
- xLinkQueue:节点控制器
-- head:总是指向队列头
-- end:总是指向队列尾
- 创建队列时,实际是创建了xLinkQueue,之后对队列的操作都是通过它
- 添加节点时,创建的Node,并将内容复制进它的buff中
- 弹出队列时,将Node中的内容先复制出来,在free释放内存
- 不是循环队列,有待改进
- 如果要增大单个节点的buff,需要更改堆内存Heap_Size的大小!
util.c
/**
工具包
*/
#include "util.h"
static uint8_t stateBuf[][12] = {"OK", "OVERSIZE", "OVERLENGTH", "EMPTY", "None", "Malloc"};
enum QUEUE_STATE {
QUEUE_OK = 0,
QUEUE_OVERSIZE,
QUEUE_OVERLENGTH, // 超过最大使用节点数
QUEUE_EMPTY, // 队列为空
QUEUE_NONE, // 没有队列
QUEUE_MALLOC
};
static uint8_t levelBuf[][10] = {"Error", "Warn", "Info"};
enum QUEUE_DEBUG {
QUEUE_ERROR = 0,
QUEUE_WARN,
QUEUE_INFO,
};
#define DEBUG 1
void queueDebug(enum QUEUE_DEBUG level, enum QUEUE_STATE state, char* ext)
{
#if DEBUG
printf("queue[%s]: %s - %s\r\n", levelBuf[level], stateBuf[state], ext);
#endif
}
void queueInfo(xLinkQueue* queue)
{
printf("************************\r\n");
printf("max:%d\r\n", queue->max);
printf("size:%d\r\n", queue->size);
printf("length:%d\r\n", queue->length);
printf("************************\r\n");
}
/**
遍历输出队列的buff
*/
void queueTraversal(xLinkQueue* queue)
{
Node* q = queue->head;
printf("********START********\r\n");
for(uint8_t i=0; i<queue->length; i++) {
printf("第%d/%d个:%s\r\n", i+1, queue->length, q->buff);
q = q->next;
}
printf("*********END*********\r\n");
}
/**
创建一个队列,返回队列控制句柄,max个节点,每个节点size字节大小
*/
xLinkQueue* queueCreate(uint16_t max, uint16_t size)
{
xLinkQueue* xqueue = (xLinkQueue*)malloc(sizeof(xLinkQueue));
// // 创建首节点
// Node* p =(Node*)malloc(sizeof(Node));
// p->buff =(uint8_t*)malloc(sizeof(uint8_t)*size);
// memset(p->buff, 0, sizeof(uint8_t)*size);
// p->next = NULL;
// // 队列首尾都指向头结点
// xqueue->head = p;
// xqueue->end = p;
xqueue->length = 0;
xqueue->size = size;
xqueue->max = max;
// Node* temp = p;
// // 创建剩余size-1个节点
// for(uint8_t i=1; i<size; i++) {
// Node* p =(Node*)malloc(sizeof(Node));
// p->buff =(uint8_t*)malloc(sizeof(uint8_t)*size);
// memset(p->buff, 0, sizeof(uint8_t)*size);
// p->next = NULL;
// temp->next = p;
// temp = temp->next;
// }
return xqueue;
}
/**
添加一个节点到队列
*/
uint8_t queueAdd(xLinkQueue* queue, uint8_t* src, uint16_t len)
{
if(queue == NULL) {
queueDebug(QUEUE_ERROR, QUEUE_NONE, "队列不存在");
return 0;
}
if(queue->length < queue->max) {
// 创建新节点
Node* newnode =(Node*)malloc(sizeof(Node));
if(newnode == NULL){
queueDebug(QUEUE_ERROR, QUEUE_MALLOC, "创建节点内存分配失败");
return 0;
}
// 申请内存
newnode->buff =(uint8_t*)malloc(sizeof(uint8_t)*(queue->size));
if(newnode->buff == NULL){
queueDebug(QUEUE_ERROR, QUEUE_MALLOC, "节点内存申请失败");
return 0;
}
memset(newnode->buff, 0, sizeof(uint8_t)*(queue->size));
// 数据填入新节点
if(len > queue->size) {
queueDebug(QUEUE_WARN, QUEUE_OVERSIZE, "大小超出,注意会有裁剪");
}
memcpy(newnode->buff, src, MIN(queue->size, len));
newnode->buff[len] = '\0';
// 新节点没有下一个节点
newnode->next = NULL;
// 获得尾节点
Node* endnode = queue->end;
// 连接 尾节点 -> 新节点
endnode->next = newnode;
// 更新尾节点
queue->end = newnode;
// 创建的是首节点
if(queue->length == 0) {
// 队列首尾都指向头结点
queue->head = newnode;
queue->end = newnode;
}
// 节点数+1
queue->length ++;
return 1;
}else {
queueDebug(QUEUE_ERROR, QUEUE_OVERLENGTH, "已达最大节点数");
return 0;
}
}
uint8_t queueEmpty(xLinkQueue* queue)
{
return queue->length==0? QTRUE: QFALSE;
}
/**
弹出队尾一个节点buff
*/
uint8_t queuePop(xLinkQueue* queue, uint8_t* buff)
{
if(queue == NULL) {
queueDebug(QUEUE_ERROR, QUEUE_NONE, "队列不存在");
return 0;
}
Node* q = queue->head;
if(queue->length > 0) {
if(buff != NULL) {
// 数据复制
memcpy(buff, q->buff, strlen((const char*)q->buff));
}
// 释放内存
free(q->buff);
q->buff = NULL;
free(q);
q = NULL;
// 更新首节点
queue->head = queue->head->next;
// 节点数-1
queue->length --;
return 1;
} else {
queueDebug(QUEUE_ERROR, QUEUE_EMPTY, "队列为空");
return 0;
}
}
/**
从内存中销毁整个队列
*/
void queueDestory(xLinkQueue* queue)
{
uint16_t total = queue->length;
for(uint8_t i=0; i<total; i++) {
queuePop(queue, NULL);
}
free(queue);
queue = NULL;
}
void queueTest()
{
// 创建一个有10个节点,每个节点10字节的队列
xLinkQueue* queue = queueCreate(10, 10);
uint8_t buff[10] = {0};
queuePop(queue, buff); // queue[Error]: EMPTY
queueAdd(queue, (uint8_t*)"01", 3);
queueAdd(queue, (uint8_t*)"23", 3);
queueAdd(queue, (uint8_t*)"45", 3);
queueAdd(queue, (uint8_t*)"67", 3);
queueAdd(queue, (uint8_t*)"89", 3);
queueAdd(queue, (uint8_t*)"asdfghjklqw", 12); // queue[Warn]: OVERSIZE
queueTraversal(queue);
queuePop(queue, buff);
printf("pop: %s\r\n", buff);
queueTraversal(queue);
queueAdd(queue, (uint8_t*)"aa", 3);
queueAdd(queue, (uint8_t*)"bb", 3);
queueAdd(queue, (uint8_t*)"cc", 3);
queueTraversal(queue);
// for(uint8_t i=0; i<10; i++) { // queue[Error]: EMPTY
// queuePop(q, NULL);
// }
// queueTraversal(q);
queueDestory(queue);
if(queuePop(queue, buff))
printf("pop: %s\r\n", buff);
printf("\r\ndemo end\r\n");
}
util.h
#ifndef __UTIL_H_
#define __UTIL_H_
#include "stm32f4xx.h"
#define MAX(x, y) (((x)>(y))? (x):(y))
#define MIN(x, y) (((x)<(y))? (x):(y))
#define QTRUE 1
#define QFALSE 0
typedef struct Node{
uint8_t *buff;
struct Node *next; // 下一个节点
}Node;
typedef struct xLinkQueue{
Node *end; // 队列尾节点
Node *head; // 队列头节点
uint8_t length; // 记录队列的长度(已使用多少个节点)
uint8_t size; // 每个节点的buff的大小
uint16_t max; // 队列最大节点数(最多使用多少个节点)
}xLinkQueue;
void queueTraversal(xLinkQueue* queue);
xLinkQueue* queueCreate(uint16_t max, uint8_t size);
uint8_t queueAdd(xLinkQueue* queue, uint8_t* src, uint16_t len);
uint8_t queuePop(xLinkQueue* queue, uint8_t* buff);
void queueDestory(xLinkQueue* queue);
uint8_t queueEmpty(xLinkQueue* queue);
void queueInfo(xLinkQueue* queue);
void queueTest(void);
#endif
测试
queue[Error]: EMPTY
queue[Warn]: OVERSIZE
********START********
第1/6个:01
第2/6个:23
第3/6个:45
第4/6个:67
第5/6个:89
第6/6个:asdfghjklq
*********END*********
pop: 01
********START********
第1/5个:23
第2/5个:45
第3/5个:67
第4/5个:89
第5/5个:asdfghjklq
*********END*********
********START********
第1/8个:23
第2/8个:45
第3/8个:67
第4/8个:89
第5/8个:asdfghjklq
第6/8个:aa
第7/8个:bb
第8/8个:cc
*********END*********
queue[Error]: EMPTY
demo end