我是靠谱客的博主 神勇书包,最近开发中收集的这篇文章主要介绍相对通用的C语言队列,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

心血来潮加上上班摸鱼,写了个队列,感觉还是比较通用的吧,先看头文件:

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdint.h>

struct queue_handle_t
{
    //队列的名字
    char name[32];
    //创建内存地址的起始位置
    void *start_addr;
    //末尾地址
    void *finish_addr;
    //指向队首成员
    void *head_ptr;
    //指向队尾成员
    void *tail_ptr;
    //队列中最大成员数量
    uint32_t max_member;
    //队列中单个成员的尺寸
    uint32_t member_size;
    //当前成员数量
    uint32_t member_num;
    //是否被初始化
    uint16_t is_init;
    uint16_t is_creat;
    //内部用到的函数
    int (*internal_print)(const char *, ...);
    void *(*internal_malloc)(size_t);
    void (*internal_free)(void *);
};

/*
 * 初始化队列句柄
 * @param:
 *      handle:队列句柄
 * @note:
 *      在创建队列 creat_queue() 前调用
 * @return:
 *      0是成功
 */
int init_queue(struct queue_handle_t *handle,
               void *(*malloc_func)(size_t),
               void (*free_func)(void *),
               int (*log_func)(const char *format, ...));

/*
 * 创建队列
 * @param:
 *      handle:队列句柄
 *      name:队列的名字
 *      max_member:队列元素个数的最大数量
 *      size:每个元素的尺寸
 * @return:
 *      0是成功
 */
int creat_queue(struct queue_handle_t *handle, const char *name, const uint32_t max_member, const uint32_t size);

/*
 *删除队列
 *@param:
 *  handle:队列句柄
 */
int delete_queue(struct queue_handle_t *handle);

/*
 * 入队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 */
int entern_queue(struct queue_handle_t *handle, const void *data_ptr);
/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 *      会删除队首元素
 */
int read_queue(struct queue_handle_t *handle, void *data_ptr);

/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 *      不会删除队首元素
 */
int peek_queue(struct queue_handle_t *handle, void *data_ptr);

/*
 * 读取队尾的元素
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 */
int read_tail_queue(struct queue_handle_t *handle, void *data_ptr);

#endif

 

相信有的帅批看完头文件已经知道我是咋写的了,源文件:

//缺点:一个队列里的每个元素只能是大小一样的,在队列初始时就决定了队列的大小
#include "queue.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//提高这个值可以稍微提高一些安全性(避免空指针引用啥的)
#define QUEUE_SAFE_LEVEL 0

#define QUEUE_INIT_FLG 0XF1a5
#define QUEUE_CREAT_FLG 0XF1a5
#define QUEUE_LOG(fmt,arg...) if(handle->internal_print){handle->internal_print(fmt, ##arg);}

static inline int check_handle(struct queue_handle_t *handle)
{
#if QUEUE_SAFE_LEVEL >= 1
    if (handle == NULL)
    {
        return -1;
    }
    if (handle->is_init != QUEUE_INIT_FLG)
    {
        return -2;
    }
    if (handle->internal_malloc == NULL || handle->internal_free == NULL)
    {
        return -3;
    }
#endif
    return 0;
}


/*
 * 初始化队列句柄
 * @param:
 *      handle:队列句柄
 * @note:
 *      在创建队列时 creat_queue() 前调用
 * @return:
 *      0是成功
 */
int init_queue(struct queue_handle_t *handle,
               void *(*malloc_func)(size_t),
               void (*free_func)(void *),
               int (*log_func)(const char *format, ...))
{
    if (handle == NULL || malloc_func == NULL || free_func == NULL)
    {
        return -1;
    }
    memset(handle, 0, sizeof(struct queue_handle_t));
    handle->internal_malloc = malloc_func;
    handle->internal_free = free_func;
    handle->internal_print = log_func;
    handle->is_init = QUEUE_INIT_FLG;
    return 0;
}

/*
 * 创建队列
 * @param:
 *      handle:队列句柄
 *      name:队列的名字
 *      max_member:队列元素个数的最大数量
 *      size:每个元素的尺寸
 * @return:
 *      0是成功
 */
int creat_queue(struct queue_handle_t *handle, const char *name, const uint32_t max_member, const uint32_t size)
{
    void *p_start;
    uint32_t sum_size = max_member * size;
    if (check_handle(handle))
    {
        return -1;
    }
    //判断队列是否被创建
    if (handle->is_creat)
    {
        QUEUE_LOG("Warring:%s:%d:Queue %s May be Created Or Hnadle Not Init,New Queue Will Not be Createdn", __FUNCTION__, __LINE__, handle->name);
        return -1;
    }
    //队列名字是否合法
    if (strlen(name) <= 0 || strlen(name) >= 32)
    {
        QUEUE_LOG("Error:%s:%d:Queue Name Len Must More Than 0 But Less Than 32n", __FUNCTION__, __LINE__, handle->name);
        return -1;
    }
    p_start = handle->internal_malloc(sum_size);
    if (p_start == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Creat Failn", __FUNCTION__, __LINE__);
        handle->start_addr = NULL;
        return -1;
    }
    handle->start_addr = p_start;
    handle->head_ptr = p_start;
    handle->tail_ptr = p_start;
    handle->max_member = max_member;
    handle->member_size = size;
    handle->member_num = 0;
    handle->finish_addr = (uint8_t *)p_start + sum_size;
    handle->is_creat = QUEUE_CREAT_FLG;
    strcpy(handle->name, name);
    memset(handle->start_addr, 0, sum_size);
    return 0;
}

/*
 *删除队列
 *@param:
 *  handle:队列句柄
 */
int delete_queue(struct queue_handle_t *handle)
{
    if (check_handle(handle) || handle->start_addr == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Delete Failn", __FUNCTION__, __LINE__);
        return -1;
    }
    handle->internal_free(handle->start_addr);
    memset(handle, 0, sizeof(struct queue_handle_t));
    handle->start_addr = NULL;
    handle->finish_addr = NULL;
    return 0;
}

/*
 * 入队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 */
int entern_queue(struct queue_handle_t *handle, const void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断队列是否被创建
    if (handle->start_addr == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Enter Fail,Maybe Not Creatn", __FUNCTION__, __LINE__);
        return -1;
    }
    //判断元素数量是否达到上限
    if (handle->member_num >= handle->max_member)
    {
        QUEUE_LOG("Error:%s:%d:Queue Enter Fail,Member Too Muchn", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队尾指针已经来到内存边界,那么将尾指针指回开头
    if (handle->tail_ptr >= handle->finish_addr)
    {
        handle->tail_ptr = handle->start_addr;
    }
    memcpy(handle->tail_ptr, data_ptr, handle->member_size);
    handle->tail_ptr = (uint8_t *)handle->tail_ptr + handle->member_size;
    handle->member_num++;
    return 0;
}

/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 *      会删除队首元素
 */
int read_queue(struct queue_handle_t *handle, void *data_ptr)
{
   if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Lessn", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队首指针已经来到内存边界,那么将首指针指回开头
    if (handle->head_ptr >= handle->finish_addr)
    {
        handle->head_ptr = handle->start_addr;
    }
    memcpy(data_ptr, handle->head_ptr, handle->member_size);
    handle->head_ptr = (uint8_t*)handle->head_ptr + handle->member_size;
    handle->member_num--;
    return 0;
}


/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 *      不会删除队首元素
 */
int peek_queue(struct queue_handle_t *handle, void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Lessn", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队首指针已经来到内存边界,那么将首指针指回开头
    if (handle->head_ptr >= handle->finish_addr)
    {
        handle->head_ptr = handle->start_addr;
    }
    memcpy(data_ptr, handle->head_ptr, handle->member_size);
    return 0;
}

/*
 * 读取队尾的元素
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 */
int read_tail_queue(struct queue_handle_t *handle, void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Lessn", __FUNCTION__, __LINE__);
        return -1;
    }
    //指向最后一个元素
    if (handle->tail_ptr <= handle->start_addr)
    {
        handle->tail_ptr = (uint8_t *)handle->finish_addr - handle->member_size;
    }
    else
    {
        handle->tail_ptr = (uint8_t*)handle->tail_ptr - handle->member_size;
    }
    memcpy(data_ptr, handle->tail_ptr, handle->member_size);
    handle->member_num--;
    return 0;
}


#if 0

struct a_t
{
    uint64_t v1;
    char v2;
    uint64_t v3;
} a ,aa;

int main()
{
    struct queue_handle_t h1;
    uint16_t arr[5] = {1, 2, 3};
    uint16_t read;
    double count = 100000;
    init_queue(&h1,malloc,free,printf);
    creat_queue(&h1, "test", 100, sizeof(a));

    printf("%ldn", sizeof(struct a_t));

    for (double i = 0; i < count; i++)
    {
        a.v3 = i;
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        read_queue(&h1, &aa);
        read_tail_queue(&h1, &aa);
        read_tail_queue(&h1, &aa);
        read_queue(&h1, &aa);
        printf("%.10f%%r", 100 * (i / count));
        fflush(stdout);
    }
    printf("n%dn", aa.v3);
    return 0;
}

#endif


#undef QUEUE_INIT_FLG
#undef QUEUE_CREAT_FLG
#undef QUEUE_LOG

感觉单片机上也可以跑,什么,没有malloc?没事,用全局变量就可以了比如下面这样:

static char rnm_tq[100];

void *rnm_tq_malloc(size_t n)
{
    return &rnm_tq[0];
}

反正也是个静态队列。

哦,对了,如果涉及多线程的话,该还是得自己加锁的

最后

以上就是神勇书包为你收集整理的相对通用的C语言队列的全部内容,希望文章能够帮你解决相对通用的C语言队列所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部