循环队列

在开发中很多时候需要用到循环队列来缓存数据,比如在串口通信中,可以将接收到的数据流先缓存到循环队列中,然后再从循环队列中取出数据做下一步的处理。这样可以有效的避免解析数据帧时繁琐的拼接处理。

        为了方便使用,封装了一个循环队列类,具体代码如下:

        头文件:

/********************************************************************
filename: 	CircularQueue.h
created:	2011-08-23
author:		firehood

purpose:	实现循环队列
            队列可以缓存的数据大小 = 队列长度 -1
			插入数据时在队列满的情况下会自动覆盖队列头部数据
*********************************************************************/
#pragma once
#include <windows.h>
#define DEFAULT_QUEUE_MAX_SIZE  512
class CCircularQueue
{
public:
	// 无参构造函数,默认创建队列的大小为512字节
	CCircularQueue(void);
	// 带参构造函数,创建指定大小的队列
	CCircularQueue(int nQueueSize);
	~CCircularQueue(void);
public:
	// 向队列尾部插入一个字节,队列满时会自动覆盖队列头部数据
	bool PushBack(unsigned char data);

	// 从队列头部取出一个字节
	bool PopFront(unsigned char &data);

	// 向队列尾部插入指定长度数据,队列满时会自动覆盖队列头部数据
	bool PushBack(unsigned char *pData, int size);
	
	// 从队列头部取出指定长度数据
	// 返回值:>0 返回实际取出的数据长度; <=0 失败
	int PopFront(unsigned char *pData, int size);
	
	// 重新调整队列大小
	bool Resize(int nQueueSize);
	
	// 当前队列缓存的数据大小
	int Size();
	// 队列当前剩余空间大小
	int RemainSize();
	// 队列是否为空
	bool IsEmpty();
	// 队列是否满
	bool IsFull();
    // 打印数据(测试使用)
	void PrintData();
private:
	unsigned char *m_pQueueBase; // 队列基址
	int m_QueueSize;             // 队列大小
	int m_Head, m_Tail;          // 队列头尾指针
	CRITICAL_SECTION  m_csRW;    // 读写锁
};
源文件:

/********************************************************************
filename: 	CircularQueue.cpp
created:	2011-08-23
author:		firehood

purpose:	实现循环队列
            队列可以缓存的数据大小 = 队列长度 -1
			插入数据时在队列满的情况下会自动覆盖队列头部数据
*********************************************************************/
#include "stdafx.h"
#include "CircularQueue.h"

CCircularQueue::CCircularQueue(void):
m_pQueueBase(NULL),
m_Head(0),
m_Tail(0),
m_QueueSize(DEFAULT_QUEUE_MAX_SIZE)
{
	m_pQueueBase = new unsigned char[m_QueueSize];
	ASSERT(m_pQueueBase);
	memset(m_pQueueBase, 0, m_QueueSize);
	InitializeCriticalSection(&m_csRW);
}

CCircularQueue::CCircularQueue(int nQueueSize):
m_pQueueBase(NULL),
m_Head(0),
m_Tail(0),
m_QueueSize(nQueueSize)
{
	m_pQueueBase = new unsigned char[m_QueueSize];
	ASSERT(m_pQueueBase);
	memset(m_pQueueBase, 0, m_QueueSize);
	InitializeCriticalSection(&m_csRW);
}

CCircularQueue::~CCircularQueue(void)
{
	if(m_pQueueBase)
	{
		delete[] m_pQueueBase;
		m_pQueueBase = NULL;
	}
	DeleteCriticalSection (&m_csRW);
}

// 向队列尾部插入一个字节,队列满时会自动覆盖队列头部数据
bool CCircularQueue::PushBack(unsigned char data)
{
	if(m_pQueueBase == NULL)
	{
		return false;
	}
	EnterCriticalSection(&m_csRW);

	m_pQueueBase[m_Tail]= data;
	m_Tail =(m_Tail+1) % m_QueueSize;
	if(m_Tail == m_Head)
	{
		m_Head = m_Tail+1;
		printf("Warning:lost data, Queue is full..\n");
	}

	LeaveCriticalSection(&m_csRW);
	return true;
}

// 从队列头部取出一个字节
bool CCircularQueue::PopFront(unsigned char &data)
{
	if(m_pQueueBase == NULL)
	{
		return false;
	}
	if(IsEmpty())
	{
		return false;
	}
    EnterCriticalSection(&m_csRW);

	data = m_pQueueBase[m_Head];
	m_Head=(m_Head+1) % m_QueueSize;

	LeaveCriticalSection(&m_csRW);
	return true;
}

// 向队列尾部插入指定长度数据,队列满时会自动覆盖队列头部数据
bool CCircularQueue::PushBack(unsigned char *pData, int size)
{
	if(m_pQueueBase == NULL || pData == NULL)
	{
		return false;
	}
	if(size >= m_QueueSize)
	{
		printf("PushBack failed: DataSize[%d] > MAX_QUEUE_SIZE[%d]\n" , size, (m_QueueSize-1));
		return false;
	}
	EnterCriticalSection(&m_csRW);
	int nRemianSize = RemainSize();
	int nTailToEndSize = m_QueueSize - m_Tail;
	if(size <= nTailToEndSize)
	{
		memcpy(m_pQueueBase+m_Tail, pData, size);
	}
	else
	{
		memcpy(m_pQueueBase+m_Tail, pData, nTailToEndSize);
		memcpy(m_pQueueBase,pData+nTailToEndSize, size-nTailToEndSize);
	}
	m_Tail = (m_Tail+size) % m_QueueSize;
	if(size >= nRemianSize)
	{
		printf("Warning:lost data, Queue is full..\n");
		m_Head = m_Tail+1;
	}
	LeaveCriticalSection(&m_csRW);
	return true;
}

// 从队列头部取出指定长度数据
// 返回值:>0 返回实际取出的数据长度; <=0 失败
int CCircularQueue::PopFront(unsigned char *pData, int size)
{
	if(pData == NULL || m_pQueueBase == NULL)
		return -1;
	
	EnterCriticalSection(&m_csRW);
	int nReadSize = (this->Size()>size) ? size : this->Size();
	int nHeadToEndSize = m_QueueSize - m_Head;
	if(nReadSize <= nHeadToEndSize)
	{
		memcpy(pData, m_pQueueBase+m_Head, nReadSize);
	}
	else
	{
		memcpy(pData,m_pQueueBase+m_Head, nHeadToEndSize);
		memcpy(pData+nHeadToEndSize,m_pQueueBase,nReadSize-nHeadToEndSize);
	}
	m_Head=(m_Head+nReadSize) % m_QueueSize;
	LeaveCriticalSection(&m_csRW);
	return nReadSize;
}

// 当前队列缓存的数据大小
int CCircularQueue::Size()
{
	return (m_Tail-m_Head+m_QueueSize) % m_QueueSize;
}

// 队列是否为空
bool CCircularQueue::IsEmpty()
{
	return (m_Head == m_Tail) ? true : false;
}

// 队列是否满 
bool CCircularQueue::IsFull()
{
	return (((m_Tail+1) % m_QueueSize) == m_Head) ? true : false;
}

// 队列当前剩余空间大小
int CCircularQueue::RemainSize()
{
	return ((m_QueueSize-1)-Size());
}

// 打印数据
void CCircularQueue::PrintData()
{
	int tempHead, tempTail;
	tempHead = m_Head;
	tempTail = m_Tail;
	printf("************************************************\n");
	printf("CirualarQueue Data:");
    while(tempHead != tempTail)
	{
		printf("0x%02x ", m_pQueueBase[tempHead]);
		tempHead=(tempHead+1) % m_QueueSize;
	}
	printf("\n");
	printf("************************************************\n");
}

// 重新调整队列大小
bool CCircularQueue::Resize(int nQueueSize)
{
	unsigned char *pNewQueue = NULL;
	// 申请新的队列空间
	pNewQueue = new unsigned char[nQueueSize];
	if(pNewQueue == NULL) // 申请内存失败
		return false;
	// 将队列原有数据拷贝到新队列中
	int len = PopFront(pNewQueue,nQueueSize);
	// 释放原来队列空间
	if(m_pQueueBase)
	{
		delete[] m_pQueueBase;
		m_pQueueBase = NULL;
	}
	// 使用新的队列空间
    m_pQueueBase = pNewQueue;
	m_QueueSize = nQueueSize;
	m_Head = 0;
	m_Tail = len;
	return true;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值