C语言_循环队列具体实现


Note:

  本代码用C语言编写,已经用于实际的项目中,在队列的申请过程中,也进行错误判断,可通过错误判断函数中枚举类型的值来判断,队列哪个过程出现错误。此外对于使用c++的朋友,本人建议将该数据结构封装成一个类来使用,将其操作函数变成成员函数,变量改为私有变量。(并发操作过程中,应给队列加锁,如在结构体或类中定义锁机制)


头文件queue.h

#ifndef _QUEUE_H
#define _QUEUE_H
typedef unsigned char  Q_U8Data;
typedef unsigned short Q_U16Data;
typedef unsigned int   Q_U32Data;


typedef struct _tQueueInfo
{
	Q_U8Data *pDataBuf;
	Q_U16Data MaxQueueSize;
	Q_U32Data Front;
	Q_U32Data Rear;
    Q_U32Data QueueLength;
}QueueInfo, *pQueueInfo;


void Queue_Init(pQueueInfo pQInfo,Q_U16Data MaxSize);
void Queue_ClearData(pQueueInfo pQInfo);
Q_U32Data Queue_GetLength(pQueueInfo pQInfo);
void Queue_AddData(Q_U8Data *pSrcBuf, pQueueInfo pQInfo, Q_U16Data DataCnt);
void Queue_AddOneData(Q_U8Data SrcData, pQueueInfo pQInfo);
void Queue_GetData(Q_U8Data *pBuf, pQueueInfo pQInfo, Q_U32Data DataCnt);
void Queue_GetOneData(Q_U8Data *DestData, pQueueInfo pQInfo);
void  Queue_DummyRead(pQueueInfo pQInfo,Q_U16Data DataCnt);

#endif



源文件queue.c

#include "queue.h"
#include "malloc.h"
#include "delay.h"
#include <stdio.h>
#include <string.h>
#include "comm.h"

//*****************************错误处理部分*****************
enum ERROR_CODE
{
    ERR_QUEUE_MALLOC_FAIL = 1,
    ERR_QUEUE_DATA_FULL,
    ERR_QUEUE_DATA_NULL,
    ERR_MALLOC_FAIL,
    ERR_COMM_MALLOC_FAIL,
    ERR_NAND_MALLOC_FAIL,
    ERR_UPAN_WRITE_FAIL,
    ERR_UPAN_CLOSE_FAIL,
    ERR_UPAN_OPEN_FAIL,
    ERR_NAND_BADBLOCK_FULL,
    ERR_MAINPROC_FAIL,
    ERR_BBM_MALLOC_FAIL,
};

void ErrorHandle(U32 u32ErrCode)
{
    while(1)
    {
//        Led_Error();
        printf("error code = %x \r\n", u32ErrCode);
        DelayMs(500);
       // COMM_WriteCmd(COMM_MAINCMD_CONTROL,COMM_SUBCMD_CONTROL_ERROR);
        DelayMs(500);
    }   
}
//*****************************错误处理部分*****************


void Queue_Init(pQueueInfo pQInfo,Q_U16Data MaxSize)
{
	Q_U8Data *pBuf;
	pBuf = mymalloc(SRAMIN,MaxSize);
	if(pBuf == NULL)
	{
		ErrorHandle(ERR_QUEUE_MALLOC_FAIL);
	}
	pQInfo->pDataBuf = pBuf;
	pQInfo->MaxQueueSize = MaxSize;

	pQInfo->Front = 0;
	pQInfo->Rear = 0;
    pQInfo->QueueLength = 0;
}

void Queue_ClearData(pQueueInfo pQInfo)
{
    pQInfo->Front = 0;
	pQInfo->Rear = 0;
    pQInfo->QueueLength = 0;
}

Q_U32Data Queue_GetLength(pQueueInfo pQInfo)
{
	Q_U32Data Ret;
	Ret = (pQInfo->Rear - pQInfo->Front + (pQInfo->MaxQueueSize)) % (pQInfo->MaxQueueSize);   //取余是当Real < Front时
	return Ret;
}

/******************数据空间************************

  | ---------- | ------------- | ---------------- | 
  0          Front            Rear               256

该数据空间大小申请的是256,数据以头尾相连的方式进行存取,
函数首先判断的是存入的空间是否足够,即除开front--rear段,
剩下的空间是否足够存入buf,其次开始存入时,先按顺序存入
在rear到256的数据段,最后存入的是0--front的数据段。
****************************************************/
void Queue_AddData(Q_U8Data *pAddBuf, pQueueInfo pQInfo, Q_U16Data DataCnt)
{
	Q_U16Data u16QCnt;
  	Q_U16Data u16QLen;
 	u16QLen = (pQInfo->Rear - pQInfo->Front + (pQInfo->MaxQueueSize)) % (pQInfo->MaxQueueSize);
    if(u16QLen + DataCnt > pQInfo->MaxQueueSize)//判断是否超出256 
	{
		while(1)
		{
			printf("Queue Size is overflow!In src:%s Line:%d\r\n",__FILE__,__LINE__);
			DelayMs(100);
		}
	}
	else
	{
		u16QCnt = (pQInfo->MaxQueueSize) - pQInfo->Rear;//计算Rear后可存空间(剩余的就是Front前可存空间)
		if(u16QCnt >= DataCnt)//front--rear段足够存下
		{
			memcpy(pQInfo->pDataBuf + pQInfo->Rear, pAddBuf, DataCnt);
		}
		else//分两段存,先是front--rear段,然后是0--front段
		{
			memcpy(pQInfo->pDataBuf + pQInfo->Rear, pAddBuf, u16QCnt);
            memcpy(pQInfo->pDataBuf, pAddBuf + u16QCnt, DataCnt - u16QCnt);
		}
     pQInfo->Rear = (pQInfo->Rear + DataCnt)%(pQInfo->MaxQueueSize);
     pQInfo->QueueLength += DataCnt;
	}
}

void Queue_GetData(Q_U8Data *pSaveBuf, pQueueInfo pQInfo, Q_U32Data DataCnt)
{
	Q_U16Data u16QCnt;
	Q_U16Data u16QLen;
	u16QLen = (pQInfo->Rear - pQInfo->Front + (pQInfo->MaxQueueSize)) % (pQInfo->MaxQueueSize);
	if(u16QLen < DataCnt)
	{
		while(1)
		{
			printf("Queue is not enough data to read!In src:%s Line:%d\r\n",__FILE__,__LINE__);
			DelayMs(100);
		}
	}
	else
	{
		u16QCnt = (pQInfo->MaxQueueSize) - pQInfo->Front;
		if(u16QCnt >= DataCnt)
		{
			memcpy(pSaveBuf, pQInfo->pDataBuf + pQInfo->Front, DataCnt);
		}
		else
		{
			memcpy(pSaveBuf, pQInfo->pDataBuf + pQInfo->Front, u16QCnt);
			memcpy(pSaveBuf + u16QCnt, pQInfo->pDataBuf, DataCnt - u16QCnt);
		}
	}
	pQInfo->Front = (pQInfo->Front + DataCnt)%(pQInfo->MaxQueueSize);
	pQInfo->QueueLength -= DataCnt;
}

//丢弃数据函数
//在队列里移动Front,模拟读出的过程移动Front,但是没有Buf接收,形成丢弃
void Queue_DummyRead(pQueueInfo pQInfo,Q_U16Data DataCnt)
{
	Q_U16Data u16QLen;
	u16QLen = (pQInfo->Rear - pQInfo->Front + (pQInfo->MaxQueueSize)) % (pQInfo->MaxQueueSize);
	if(u16QLen < DataCnt)
	{
		while(1)
		{
			printf("Queue is not enough data to read!In src:%s Line:%d\r\n",__FILE__,__LINE__);
			DelayMs(100);
		}
	
	else
	{
		pQInfo->Front = (pQInfo->Front + DataCnt)%(pQInfo->MaxQueueSize);
		pQInfo->QueueLength -= DataCnt;
	} 
}



函数调用方法

QueueInfo	Q_UART1Info;		 //定义一个队列结构体
Queue_Init(&Q_UART1Info, 256);	 //初始化队列结构体,并设置其最大为256个字节

if(Queue_GetLength(&Q_UART1Info) > 100)
{
	//队列中的数据长度 > 100个字节时才进行处理
	Queue_GetData(...);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中,FIFO循环队列实现可以使用数组或链表来实现循环队列是一种先进先出(FIFO)的数据结构,它允许在队列的后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。循环队列实现需要记录队列的长度、队首和队尾的位置,以及队内有效元素的个数。 以下是使用数组实现FIFO循环队列的示例代码: ```c typedef struct { int* arr; // 存放数据的数组 int front; // 队首位置 int rear; // 队尾位置 int count; // 队内有效元素个数 int N; // 循环队列的长度 } MyCircularQueue; // 创建循环队列 MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue)); obj->arr = (int*)malloc(sizeof(int) * (k + 1)); // 开辟比有效数据多1个的空间 obj->N = k + 1; obj->front = obj->rear = obj->count = 0; return obj; } // 入队操作 bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { if (obj->count == obj->N - 1) { return false; // 队列已满 } obj->arr[obj->rear = value; obj->rear = (obj->rear + 1) % obj->N; obj->count++; return true; } // 出队操作 bool myCircularQueueDeQueue(MyCircularQueue* obj) { if (obj->count == 0) { return false; // 队列为空 } obj->front = (obj->front + 1) % obj->N; obj->count--; return true; } // 获取队首元素 int myCircularQueueFront(MyCircularQueue* obj) { if (obj->count == 0) { return -1; // 队列为空 } return obj->arr[obj->front]; } // 获取队尾元素 int myCircularQueueRear(MyCircularQueue* obj) { if (obj->count == 0) { return -1; // 队列为空 } return obj->arr[(obj->rear - 1 + obj->N) % obj->N]; } // 检查队列是否为空 bool myCircularQueueIsEmpty(MyCircularQueue* obj) { return obj->count == 0; } // 检查队列是否已满 bool myCircularQueueIsFull(MyCircularQueue* obj) { return obj->count == obj->N - 1; } // 释放队列占用的内存空间 void myCircularQueueFree(MyCircularQueue* obj) { free(obj->arr); free(obj); } ``` 以上代码中,我们使用了一个数组(`arr`)来存放数据,通过维护 `front` 和 `rear` 来指示队首和队尾的位置,使用 `count` 来记录队内有效元素的个数,使用 `N` 来记录循环队列的长度。入队操作使用取模运算来实现循环队列的特性,出队操作和获取队首、队尾元素的操作也相应地进行了调整。通过以上的代码实现,我们可以实现一个C语言的FIFO循环队列。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C语言循环队列的表示与实现实例详解](https://download.csdn.net/download/weixin_38516040/14001535)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【数据结构】循环队列(C语言实现)](https://blog.csdn.net/Hello_World_213/article/details/124822852)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C语言实现循环队列](https://blog.csdn.net/weixin_62029250/article/details/121688210)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值