C程序设计:环形队列

1.头文件

#ifndef CJ_QUEUE_H
#define CJ_QUEUE_H

#include <stdbool.h>

typedef struct _CJQUEUE_HandleTypeDef
{
    unsigned int head;                      //队列头指针
    unsigned int tail;                      //队列尾指针
    unsigned int size;                      //队列缓存长度(初始化时赋值)
    unsigned char *buffer;                  //队列缓存数组(初始化时赋值)
}CJQUEUE_HandleTypeDef;

bool cj_queue_init(CJQUEUE_HandleTypeDef *queue, void *buf, int size);

int cj_queue_read(CJQUEUE_HandleTypeDef *queue, void *buf, int len);

int cj_queue_write(CJQUEUE_HandleTypeDef *queue, const void *buf, int len);

int cj_get_queue_bufRemainLen(CJQUEUE_HandleTypeDef *queue);

void cj_clear_queue(CJQUEUE_HandleTypeDef *queue);

#endif

2.实现

#include "cjqueue.h"
#include <string.h>
#include <stdio.h>

bool cj_queue_init(CJQUEUE_HandleTypeDef *queue, void *buf, int size)
{
	if (size <= 0)
	{
		return false;
	}
	queue->head = 0;
	queue->tail = 0;
	queue->size = size;
	queue->buffer = buf;
	return true;
}

int cj_queue_read(CJQUEUE_HandleTypeDef *queue, void *buf, int len)
{
    char *p = buf;

    int head = queue->head;
    int tail = queue->tail;
    int size = queue->size;
    unsigned char *data = queue->buffer;

    int i = 0;
    while (i < len && tail != head) // 按字节读取数据
    {
        *p++ = data[tail++];
        i++;
        tail %= size; // 通过取模方式避免了if分支
    }

    queue->tail = tail; // 更新queue->tail的值
    return i;           // 返回实际读取的字节数
}

int cj_queue_write(CJQUEUE_HandleTypeDef *queue, const void *buf, int len)
{
    int int_len = len;
    int allow_len = 0;

    int head = queue->head;
    int tail = queue->tail;
    int size = queue->size;
    unsigned char *data = queue->buffer;

    char *p = (char *)buf;
    int written_len = 0; // 记录成功写入的长度

    while (len > 0)
    {
        allow_len = (tail - head + size) % size;
        if(allow_len == 0)
            allow_len = size;

        if(len > allow_len)
            int_len = allow_len;
        else
            int_len = len;
        
        if((head + int_len) > size)
            int_len = (size - head);
        
        memcpy(data + head, p, int_len);
        p += int_len;
        head = (head + int_len) % size;
        written_len += int_len;
        len -= int_len;
        printf("written_len = %d, head = %d, tail = %d\n", written_len, head, tail);
        
        /* 超出队列极限 - 队列有效数据也全部清除 */
        if(tail == head)
        {
            printf("over flow !!!!!!!!!!!!!!\n");
            break;
        }
    }
    queue->head = head;
    return written_len; // 最后返回成功写入的长度
}

/* 队列中有效数据的长度 */
int cj_get_queue_bufRemainLen(CJQUEUE_HandleTypeDef *queue)
{
    int head = queue->head;
    int tail = queue->tail;
    int size = queue->size;

    return (head - tail + size) % size; 
}

void cj_clear_queue(CJQUEUE_HandleTypeDef *queue)
{
    queue->head = 0;
    queue->tail = 0;
}

3.注意事项

        1.在多线程的队列读写,应在读写时加锁来保护。

        2.环形队列读的速度慢于写时,一旦写的地址到达了读的地址时,队列将被清空。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值