在我的上一篇博文中已经讲到循环队列的特点作用以及C语言实现,当然实现和操作的方式比较简单,在实际项目应用中略显粗糙。因此,这一篇提供一个进阶篇的实现与操作接口。具体函数作用可以参见我的注释部分,使用的时候直接把里面的接口函数放在一个头文件里面直接调用就可以啦,十分方便易用,但是可以实现的功能不可小觑哦,比如我在写高速USB设备驱动(20MB/s)以及网络抓包缓存的时候用到的都是这个看似简单的数据结构,所以还没有熟练运用的要加把劲了。需要注意的地方包括:

<1> 不再利用上一篇中 “q->front = (q->rear + 1) % q->size” 的关系来进行队列空还是满的判断了,这次利用 space 剩余缓存空间大小来判断。

<2> 写缓冲区的时候,要进行缓冲区剩余空间大小 space 的判断,如果要写入空间小于等于剩余空间,那么就可以将数据完全写入缓冲区,此时写入长度等于要写入的数据长度,否则只能将部分数据写入缓冲区,返回长度就等于剩余空间大小了。

<3> 读缓冲区同理,要进行当前缓冲区中可用缓存的大小的判断,也即已写入缓存大小的判断。若要读出的数据长度小于已写入缓存,那么返回长度为希望读出的数据长度,否则为已写入缓存的长度。

<4> 在写入和读出的时候尤其需要注意到达缓冲区边界的时候,数据和读写位置的处理。如果读写到了边界,那么就要分两次读取了,另外读写位置一定不能超越分配的缓冲区边界,所以在循环队列中数据的读写位置前移的时候都要对缓冲区长度取余以保证数据操作的安全性。

  下面就是代码部分了,若有不明或不妥之处,可以直接 send comments to me :-D

/** Queue operation API - 1.0** Copyright (C) 2016 SoldierJazz (SoldierJazz@163.com)** This program is free software; you can redistribute it and/or* modify it. **/#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*** Queue - queue structure* @buf: queue buffer* @read: position of read* @write: position of write* @size: buffer size* @space: writable buffer size*/
typedef struct {char *buf;unsigned int read;unsigned int write;unsigned int size;unsigned int space;
} Queue;#define Avail(q) (q->size - q->space)/*** Queue_Init - init a queue* @q: pointer of queue* @size: size of buffer in queue** Must be called when started. */
void Queue_Init(Queue *q, int size)
{q->buf = (char *)malloc(sizeof(char) * size);q->read = 0;q->write = 0;q->size = size;q->space = size;
}/*** Queue_Destroy - destroy a queue* @q: pointer of queue*/
void Queue_Destroy(Queue *q)
{free(q->buf);
}/*** Queue_Empty - tests whether a queue is empty* @q: the queue to test*/
bool Queue_Empty(Queue *q)
{return (q->space == q->size);
}/*** Queue_Full - tests whether a queue is full* @q: the queue to test*/
bool Queue_Full(Queue *q)
{return (q->space == 0);
}/*** AddQueue - add a byte to queue* @q: the queue to add to* @val: the char to add*/
bool AddQueue(Queue *q, char val)
{if (!Queue_Full(q)) {q->buf[q->write] = val;q->write = (q->write + 1) % q->size;q->space--;return true;} return false;
}/*** DelQueue - delete a byte from queue* @q: the queue to delete from* @val: the char deleted*/
bool DelQueue(Queue *q, char *val)
{if (!Queue_Empty(q)) {*val = q->buf[q->read];q->read = (q->read + 1) % q->size;q->space++;return true;}return false;
}/*** WriteQueue - write buffers to queue* @q: the queue to write in* @buf: pointer of write buffer* @len: length of write buffer*/
static int WriteQueue(Queue *q, char *buf, unsigned int len)
{unsigned int ret = 0;unsigned int rest = q->size - q->write;if (!Queue_Full(q)) {if (q->space >= len) {ret = len;if (rest >= len) {memcpy(q->buf + q->write, buf, len);q->write = (q->write + len) % q->size;q->space -= len;} else {memcpy(q->buf + q->write, buf, rest);q->write = 0;memcpy(q->buf, buf + rest, len - rest);q->write = len -rest;q->space -= len;}} else {ret = q->space;if (rest >= q->space) {memcpy(q->buf + q->write, buf, q->space);q->write = (q->write + q->space) % q->size;q->space = 0;} else {memcpy(q->buf + q->write, buf, rest);q->write = 0;memcpy(q->buf, buf + rest, q->space - rest);q->write = q->space -rest;q->space = 0;}}   } return ret;
}/*** ReadQueue - read buffers from queue* @q: the queue to read from* @buf: pointer of read buffer* @len: read length*/
static int ReadQueue(Queue *q, char *buf, unsigned int len)
{unsigned int rest = q->size - q->read;unsigned int ret = 0;if (!Queue_Empty(q)) {if (Avail(q) >= len) {ret = len;if (rest >= len) {memcpy(buf, q->buf + q->read, len);q->read = (q->read + len) % q->size;q->space += len;} else {memcpy(buf, q->buf + q->read, rest);q->read = 0;memcpy(buf + rest, q->buf, len - rest);q->read = len -rest;q->space += len;}return len;} else {ret = Avail(q);if (rest >= Avail(q)) {memcpy(buf, q->buf + q->read, Avail(q));q->read = (q->read + Avail(q)) % q->size;q->space = q->size;} else {memcpy(buf, q->buf + q->read, rest);q->read = 0;memcpy(buf + rest, q->buf, Avail(q) - rest);q->read = Avail(q) -rest;q->space = q->size;}}} return ret;
}void main()
{int ret = 0;char buf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};char buf2[10];Queue q;Queue_Init(&q, 10);ret = WriteQueue(&q, buf, 5);printf("writed %d bytes.\n", ret);ret = ReadQueue(&q, buf2, 2);printf("readed %d bytes.\n", ret);ret = WriteQueue(&q, buf, 10);printf("writed %d bytes.\n", ret);ret = ReadQueue(&q, buf2, 7);printf("readed %d bytes.\n", ret);ret = ReadQueue(&q, buf2, 7);printf("readed %d bytes.\n", ret);Queue_Destroy(&q);
}

运行结果如下:


关于循环队列主题的系列文章,可移步至以下链接:
1. 《循环队列及C语言实现<一>》
2. 《循环队列及C语言实现<二>》
3. 《循环队列及C语言实现<三>》

循环队列及C语言实现二相关推荐

  1. 循环队列及C语言实现三

    在之前的博客中给出了设计循环队列的思路以及源码,这些可都是经过我长期大数据测试的验证哦.当然,现在的很多开源项目和一些封装好的类或接口也都有类似的队列实现方法,之所以我还在使用自己写的这一套方法,主要 ...

  2. 循环队列及C语言实现一

    循环队列是为了充分利用内存,进行数据操作的一种基本算法.具体实现方式可划分为:链式队列和静态队列,这里所谓的静态是指在一片连续的内存区域进行数据操作.本文只讲述静态队列,也是最简单的实现方式,链式队列 ...

  3. 循环队列c语言的实现,循环队列的C语言实现

    生活中有很多队列的影子,比如打饭排队,买火车票排队问题等,可以说与时间相关的问题,一般都会涉及到队列问题:从生活中,可以抽象出队列的概念,队列就是一个能够实现"先进先出"的存储结构 ...

  4. 数据结构(严蔚敏)之五——循环队列(c语言实现)

    在这里我先强调几点概念: 1.在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置. 2.在单队列中我们判断队列是否为空的条件是:Q.front==Q.rear;而在循环队列 ...

  5. 顺序循环队列类c#语言,C#--循环队列的顺序存储

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  6. leetcode 622——设计循环队列

    leetcode 622--设计循环队列(C语言提交) 题目链接:leetcode 622--设计循环队列 题目描述: 设计你的循环队列实现. 循环队列是一种线性数据结构,其操作表现基于 FIFO(先 ...

  7. 循环队列–C语言实现–数据结构

    循环队列–C语言实现–数据结构 目录 循环队列C语言实现数据结构 目录 一 要求 二 循环队列 三 循环队列的算法设计 1 建立循环队列 2 置空队列 3 入队 4 出队 5 打印队 四 程序 1 程 ...

  8. c语言循环队列入列算法,C语言——循环队列和链队列的基本运算

    // 循环队列 #include #include "SeqQue.h" // 循环队列的基本运算 /* const int maxsize = 20; typedef struc ...

  9. 【数据结构】顺序循环队列及其实现(C语言)

    给定一个大小为MAXSIZE的数组储存一个队列,经过若干次的插入和删除以后,当队尾指针 rear = MAXSIZE 时,呈现队列满的状态,而事实上数组的前部可能还有空闲的位置.为了有效地利用空间,引 ...

最新文章

  1. js实现当前导航菜单高亮显示
  2. 用树莓派获取天气状况
  3. sql2005备份还原详解
  4. J2ME开发环境配置(MyEclipse插件+WTK+jdk)
  5. jquery无法找到其他父级子集解决方法
  6. 当MySQL执行XA事务时遭遇崩溃,且看华为云如何保障数据一致性
  7. 全国主要省会城市和地区手机离线地图数据文件下载地址
  8. 无人车系统(四):轨迹跟踪PID控制
  9. java联机对战五子棋游戏(SWT版)
  10. Mac视频下载转换器MovieSherlock使用教程
  11. OpenAI公开Dota 2论文:胜率99.4%,「手术」工具连续迁移训练
  12. Riverbed助力Interplex成功使用机器人技术
  13. BZOJ4049 : [Cerc2014] Mountainous landscape
  14. HIVE最全面入门指南
  15. 我的第一个安卓应用程序_我如何设计我的第一个应用程序
  16. Burpsuite 使用教程
  17. 结庐在人境,而无车马喧
  18. 签电子合同的流程是怎样的
  19. MySQL修改用户密码及配置远程访问
  20. 什么是Socks5代理?

热门文章

  1. c#同类型操作最终得到的结果将是同类型
  2. 在Solaris系统下如何更改网络配置?
  3. 用aspnet_compiler发布网站 (转载:My way of my life )
  4. Aspx页面javascript的几个trick
  5. docker部署flask_使用Docker,GCP Cloud Run和Flask部署Scikit-Learn NLP模型
  6. 数据中台是下一代大数据_全栈数据科学:下一代数据科学家群体
  7. leetcode809. 情感丰富的文字
  8. 服务器创建多个dhcp服务_如何在15分钟内创建无服务器服务
  9. django-rest-framework解析请求参数过程详解
  10. rz和sz上传下载文件