循环队列及C语言实现二

  在我的上一篇博文中已经讲到循环队列的特点作用以及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语言实现<三>》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MAC下secureCRT无法保存密码的解决方法

From: http://www.php230.com/securecrt-for-mac-store-password.html 在mac下新安装了secureCRT&#xff0c;取代系统自带的终端工具&#xff0c;主要是为了方便链接服务器。 mac下面的secureCRT默认保存不上密码&#xff0c;我们选择了保存密码后&#xff0c;下次登录还是提…

微信小程序下拉刷新列表onPullDownRefresh;微信小程序上划加载列表onReachBottom;uni-app微信小程序下拉加载数据;uni-app微信小程序上划页面加载数据

需求&#xff1a;微信小程序列表加载有两种方式&#xff0c;分别是按住页面下拉加载数据数据&#xff08;触发onPullDownRefresh&#xff09;和直接上划滚动页面到底部加载数据&#xff08;触发onReachBottom函数&#xff09;。 本文主要是使用上划滚动页面触底加载数据&#x…

ARP协议在同网段及跨网段下的工作原理

一、ARP在同个网段下的工作原理 首先&#xff0c;每台主机都会在自己的ARP缓冲区中建立一个 ARP列表&#xff0c;以表示IP地址和MAC地址的对应关系。当源主机需要将一个数据包要发送到目的主机时&#xff0c;会首先检查自己 ARP列表中是否存在该 IP地址对应的MAC地址&#xff0…

如何查看服务器当前的负载信息

From: http://blog.csdn.net/mal327/article/details/7423750 如何查看服务器当前的负载信息http://www.flybaaa.com/help/69_1.html网吧内突然很卡&#xff0c;这个情况我相信大家都有遇见过&#xff0c;但是通过什么方法来排查是否linux服务器的负载过大导致的这个问题呢&am…

Realtek网卡如何识别具体型号是8111B/8111C/8111D还是8111E???

From: http://support.icafe8.com/technologynews/focus/1347.html 貌似在去年&#xff0c;Realtek网卡把型号都统一为Realtek GBE什么什么的这种名字&#xff0c;这个修改说实话&#xff0c;对有盘没啥影响&#xff0c;只要驱动装好&#xff0c;能上网就ok了&#xff0c;但是…

【leetcode77】Single Number

一题目描述&#xff1a; 给定一个数组&#xff0c;只有一个数字出现一次&#xff0c;其余都是两次&#xff0c;判断那个数字 思路&#xff1a; 不断取出数据进行异或&#xff0c;最后一个数字&#xff0c;因为相同的数字会抵消代码&#xff1a; public class Solution {public …

Remoting-1

什么是Remoting&#xff0c;简而言之&#xff0c;我们可以将其看作是一种分布式处理方式。从微软的产品角度来看&#xff0c;可以说Remoting就是DCOM的一种升级&#xff0c;它改善了很多功能&#xff0c;并极好的融合到.Net平台下。Microsoft .NET Remoting 提供了一种允许对象…

DEBUG 调试

1.Step Into (also F5) 跳入 2.Step Over (also F6) 跳过 3.Step Return (also F7) 执行完当前method&#xff0c;然后return跳出此method 4.step Filter 逐步过滤 一直执行直到遇到未经过滤的位置或断点(设置Filter:window-preferences-java-Debug-step Filtering) 5.resume 重…

promise使用详解

原文链接以及promise练习题 先说结论&#xff1a; promise是解决异步函数的一种方案 将异步操作以同步方式展现出来 避免了回调地狱 1.三种状态&#xff1a;padding–等待 resolved–成功–then rejected–失败–catch 2.promise上有then和catch方法 then接受一个参数是函数 这…

Android 对话框(Dialog)大全 建立你自己的对话框

Activities提供了一种方便管理的创建、保存、回复的对话框机制&#xff0c;例如 onCreateDialog(int), onPrepareDialog(int, Dialog), showDialog(int), dismissDialog(int)等方法&#xff0c;如果使用这些方法的话&#xff0c;Activity将通过getOwnerActivity()方法返回该Act…

HDU 5795

题意&#xff1a; 两人轮流从 n 堆 糖果里取糖果&#xff0c;每次可以1&#xff09; 选择一堆取任意个&#xff08;不为 0&#xff09;2) 选择一堆糖果分成 3 堆&#xff08;每堆数量 > 1)拿到最后一颗糖果的人赢。 解题 &#xff1a; 打表算出一些 sg 值&#xff0c;就可以…

mac下beyond compare配置图

配置Tab键为4个空格&#xff1a; 显示行号&#xff1a;

Win7下安装linux虚拟机

关于如何在Win7下搭建linux学习环境&#xff0c;特在此分享下. 一、工具 1、VMware-workstation-full-9.0.0-812388.exe 下载地址:http://pan.baidu.com/s/1bpFT0ZX 2、32位的CenOS系统镜像文件CentOS-6.7-i386-bin-DVD1.iso. 下载地址:http://pan.baidu.com/s/1cHrxLG…

el-table处理某一行样式;el-table表格row-class-name无效原因;el-table格式化某行样式和数据

如果是设置点击el-table某行变色或者hover 点击看这篇 情景&#xff1a;:row-class-name“tableRowClassName” 无效果 原因是&#xff1a;el-table的属性里 多了个stripe&#xff0c;stripe属性可以创建带斑马纹的表格。会影响到row-class-name的渲染。去掉stripe即可。 &l…

国内ios分亨组件,

2019独角兽企业重金招聘Python工程师标准>>> 1. 新浪微博 (支持新浪微博官方 SSO OAuth 及 iOS 6 特性&#xff09; 2. 微信&#xff08;仅支持分享到朋友&#xff09; 3. 网易微博 4. 腾讯微博 5. 豆瓣 6. 人人网 https://github.com/icyl…

el-table文字超出隐藏;el-table表格文字一行展示,超出隐藏,多余的内容会在 hover时显示 ;

el-table文字默认情况下若内容过多会折行显示&#xff0c;若需要单行显示可以给el-table-column使用show-overflow-tooltip属性&#xff0c;它接受一个Boolean&#xff0c;为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。 给el-table-column添加show-overflow-t…

ssh自动输入密码登录服务器/ssh免输入密码登录/非交互ssh 密码验证

From: http://www.linuxidc.com/Linux/2011-02/31921.htm 由于经常需要登录一些远程的服务器&#xff0c;每次都需要将密码重输一遍&#xff0c;如下&#xff1a; #ssh 用户名我的服务器的ip 用户名我的服务器的ips password: &#xff08;这里需要手动输入密码后回车&#x…

11g下如何查询trace文件名

eygle的书中有讲到查看数据库的内容&#xff0c;利用转储文件来查看 aler system dump datafile 3 block 9&#xff1b; roger提点说先oradebug setmypid&#xff0c;再dump&#xff0c;然后直接oradebug tracefile_name&#xff0c;就能够得到trace文件的完整路径了。 如图 转…

el-table表格格式化某一列数据;统一处理el-table表格某一列数据

以下代码可以直接复制使用 场景&#xff1a;table的原数据就是 姓名1234&#xff0c;但是现在想要改成统一的格式。可以使用formatter属性&#xff0c;它用于格式化指定列的值&#xff0c;接受一个Function&#xff0c;会传入两个参数&#xff1a;row和column&#xff0c;可以…

OpenWrt交换机手册(Switch Documentation)

如果你的设备含有不少于1个的LAN接口&#xff0c;那这个设备在不同的接口之间可能有一个被称为交换(switch)的特殊连接。大多数的内部构造如下图所示: 如果你想要更改这些端口如何互相连接的&#xff0c;你需要配置你的switch设备。 (see also network.interfaces) UCI config…