From 10109e989a045db0fdf6d1fdb8fc541b9fd98cec Mon Sep 17 00:00:00 2001 From: guishenking Date: Fri, 15 Aug 2025 14:04:04 +0800 Subject: [PATCH] V0.1 --- .gitignore | 1 + CMakeLists.txt | 36 ++++++ src/lib/queue/queue.c | 280 ++++++++++++++++++++++++++++++++++++++++++ src/lib/queue/queue.h | 58 +++++++++ src/main.c | 77 ++++++++++++ 5 files changed, 452 insertions(+) create mode 100644 .gitignore create mode 100755 CMakeLists.txt create mode 100644 src/lib/queue/queue.c create mode 100644 src/lib/queue/queue.h create mode 100755 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f3d6549 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..449cbe3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.20) + +project(My_ptotocol VERSION 0.1 LANGUAGES CXX C) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_COMPILER gcc) +set(CMAKE_C_STANDARD_REQUIRED ON) +# set(CMAKE_CXX_STANDARD 23) +# set(CMAKE_CXX_COMPILER g++) +# set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0") + +include_directories( + . + src/lib/queue +) +set(PROJECT_SOURCES + src/main.c + src/lib/queue/queue.c +) +add_executable(${PROJECT_NAME} + ${PROJECT_SOURCES} +) +target_link_libraries(${PROJECT_NAME} +) + +include(GNUInstallDirs) +install(TARGETS ${PROJECT_NAME} + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) \ No newline at end of file diff --git a/src/lib/queue/queue.c b/src/lib/queue/queue.c new file mode 100644 index 0000000..56d61c1 --- /dev/null +++ b/src/lib/queue/queue.c @@ -0,0 +1,280 @@ +/** + * @file queue.c + * @author guishenking (guishenking@outlook.com) + * @brief + * @version 0.1 + * @date 2025-08-14 + * + * @copyright Copyright (c) 2025 + * + */ +#include "queue.h" +#include +#include + +/** + * @brief 初始化队列 + * + * @param queue + * @param elem_size 数据类型大小 + */ +bool queue_init(queue_t *queue, size_t elem_size) { + queue->head = NULL; + queue->tail = NULL; + queue->size = 0; + if(elem_size == 0) { + return false; // 元素大小不能为0 + } + queue->elem_size = elem_size; + return true; +} + +/** + * @brief 入队 + * + * @param queue + * @param value + * @return true + * @return false + */ +bool queue_enqueue(queue_t *queue, const void *value) { + // 分配新节点 + if (queue->size >= QUEUE_MAX_SIZE) { + return false; + } + queue_node_t *node = (queue_node_t *)malloc(sizeof(queue_node_t)); + if (!node) { + return false; + } + // 分配数据空间并复制数据 + node->data = malloc(queue->elem_size); + // 检查数据分配是否成功 + if (!node->data) { + // 数据分配失败,此时node还未加入链表,只需释放node本身即可 + free(node); + return false; + } + // 复制数据到节点 + memcpy(node->data, value, queue->elem_size); + // 将下一级节点添加到队列 + node->next = NULL; + // 如果队列为空,设置头尾指针 + if (queue->tail) { + // 如果队列不为空,将新节点添加到尾部 + queue->tail->next = node; + } else { + // 如果队列为空,将新节点设置为头部 + queue->head = node; + } + // 更新尾部指针并增加队列大小 + queue->tail = node; + queue->size++; + return true; +} + +/** + * @brief 从队列头部出队 + * + * @param queue + * @param value + * @return true + * @return false + */ +bool queue_dequeue_head(queue_t *queue, void *value) { + // 检查队列是否为空 + if (queue->size == 0) { + return false; + } + queue_node_t *node = queue->head; + // 复制头部数据到输出参数 + memcpy(value, node->data, queue->elem_size); + // 更新头部指针 + queue->head = node->next; + // 如果头部为空,更新尾部指针 + if (!queue->head) { + queue->tail = NULL; + } + // 释放节点和数据 + free(node->data); + free(node); + queue->size--; + return true; +} + +/** + * @brief 从队列尾部出队 + * + * @param queue + * @param value + * @return true + * @return false + */ +bool queue_dequeue_tail(queue_t *queue, void *value) { + if (queue->size == 0) { + return false; + } + queue_node_t *prev = NULL; + queue_node_t *node = queue->head; + // 找到最后一个节点 + while (node && node->next) { + prev = node; + node = node->next; + } + memcpy(value, node->data, queue->elem_size); + if (prev) { + prev->next = NULL; + queue->tail = prev; + } else { + // 只有一个节点 + queue->head = NULL; + queue->tail = NULL; + } + free(node->data); + free(node); + queue->size--; + return true; +} + +/** + * @brief 查询队列指定位置的数据 + * + * @param queue 队列指针 + * @param index 位置(0为头部) + * @param value 输出数据指针 + * @return true 查询成功 + * @return false 越界或队列为空 + */ +bool queue_peek_at(const queue_t *queue, size_t index, void *value) { + if (index >= queue->size || queue->size == 0) { + return false; // 越界或队列为空 + } + queue_node_t *node = queue->head; + for (size_t i = 0; i < index; ++i) { + node = node->next; + } + memcpy(value, node->data, queue->elem_size); + return true; +} + +/** + * @brief 抛弃队列前n个数据 + * + * @param queue 队列指针 + * @param n 要抛弃的元素数量 + * @return size_t 实际抛弃的元素数量 + */ +size_t queue_drop_head(queue_t *queue, size_t n) { + size_t dropped = 0; + if (n == 0 || queue->size == 0) { + return 0; + } + if (n >= queue->size) { + dropped = queue->size; + queue_clear(queue); + return dropped; + } + while (dropped < n && queue->size > 0) { + queue_node_t *node = queue->head; + queue->head = node->next; + free(node->data); + free(node); + queue->size--; + dropped++; + } + if (!queue->head) { + queue->tail = NULL; + } + return dropped; +} + +/** + * @brief 抛弃队列尾部n个数据 + * + * @param queue 队列指针 + * @param n 要抛弃的元素数量 + * @return size_t 实际抛弃的元素数量 + */ +size_t queue_drop_tail(queue_t *queue, size_t n) { + size_t dropped = 0; + if (n == 0 || queue->size == 0) { + return 0; + } + if (n >= queue->size) { + // 清空整个队列 + dropped = queue->size; + queue_clear(queue); + return dropped; + } + for (size_t i = 0; i < n; ++i) { + queue_node_t *prev = NULL; + queue_node_t *node = queue->head; + // 找到最后一个节点 + while (node && node->next) { + prev = node; + node = node->next; + } + if (!node) break; + if (prev) { + prev->next = NULL; + queue->tail = prev; + } else { + // 只有一个节点 + queue->head = NULL; + queue->tail = NULL; + } + free(node->data); + free(node); + queue->size--; + dropped++; + } + return dropped; +} + +/** + * @brief 判断队列是否为空 + * + * @param queue + * @return true + * @return false + */ +bool queue_is_empty(const queue_t *queue) { + return queue->size == 0; +} + +/** + * @brief 获取队列长度 + * + * @param queue + * @return size_t + */ +size_t queue_length(const queue_t *queue) { + return queue->size; +} + +/** + * @brief 清空队列 + * + * @param queue + */ +void queue_clear(queue_t *queue) { + queue_node_t *node = queue->head; + while (node) { + queue_node_t *next = node->next; + free(node->data); + free(node); + node = next; + } + queue->head = NULL; + queue->tail = NULL; + queue->size = 0; +} + +/** + * @brief 销毁队列 + * + * @param queue + */ +void queue_destroy(queue_t *queue) { + queue_clear(queue); + // 如果有其他资源分配,可在此释放 +} \ No newline at end of file diff --git a/src/lib/queue/queue.h b/src/lib/queue/queue.h new file mode 100644 index 0000000..6a54e82 --- /dev/null +++ b/src/lib/queue/queue.h @@ -0,0 +1,58 @@ +/** + * @file queue.h + * @author guishenking (guishenking@outlook.com) + * @brief + * @version 0.1 + * @date 2025-08-14 + * + * @copyright Copyright (c) 2025 + * + */ +#ifndef _GSK_queue_H +#define _GSK_queue_H + +#include +#include + +#define QUEUE_MAX_SIZE (1024) +// 定义队列节点 +typedef struct queue_node { + void *data; + struct queue_node *next; +} queue_node_t; + +// 定义队列结构 +typedef struct { + queue_node_t *head; + queue_node_t *tail; + size_t size; + size_t elem_size; +} queue_t; + +//初始化队列 +bool queue_init(queue_t *queue, size_t elem_size); + +// 入队操作 +bool queue_enqueue(queue_t *queue, const void *value); +// 出队操作 + +// 从队列头部出队 +bool queue_dequeue_head(queue_t *queue, void *value); +// 从队列尾部出队 +bool queue_dequeue_tail(queue_t *queue, void *value); +// 查询队列指定位置的数据 +bool queue_peek_at(const queue_t *queue, size_t index, void *value); +// 抛弃队列前n个数据 +size_t queue_drop_head(queue_t *queue, size_t n); +// 抛弃队列尾部n个数据 +size_t queue_drop_tail(queue_t *queue, size_t n); +// 检查队列是否为空 +bool queue_is_empty(const queue_t *queue); +// 获取队列长度 +size_t queue_length(const queue_t *queue); +// 清空队列 +void queue_clear(queue_t *queue); +// 销毁队列 +void queue_destroy(queue_t *queue); + +#endif // !_GSK_queue_H \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..f5fe211 --- /dev/null +++ b/src/main.c @@ -0,0 +1,77 @@ +/** + * @file main.c + * @author guishenking (guishenking@outlook.com) + * @brief + * @version 0.1 + * @date 2025-08-15 + * + * @copyright Copyright (c) 2025 + * + */ +#include "queue.h" +#include + + + +void print_queue(const queue_t *queue) { + printf("Queue(size=%zu): ", queue_length(queue)); + for (size_t i = 0; i < queue_length(queue); ++i) { + int val; + queue_peek_at(queue, i, &val); + printf("%d ", val); + } + printf("\n"); +} + +int main(void) { + queue_t q; + int ret; + // 初始化队列,存储int类型 + if (!queue_init(&q, sizeof(int))) { + printf("Init failed!\n"); + return -1; + } + + // 入队 + for (int i = 1; i <= 10; ++i) { + ret = queue_enqueue(&q, &i); + printf("Enqueue %d: %s\n", i, ret ? "OK" : "FAIL"); + } + print_queue(&q); + + // 查询第3个元素 + int val = 0; + if (queue_peek_at(&q, 2, &val)) { + printf("Peek index 2: %d\n", val); + } + + // 从头部出队 + for (int i = 0; i < 2; ++i) { + if (queue_dequeue_head(&q, &val)) { + printf("Dequeue head: %d\n", val); + } + } + print_queue(&q); + + // 从尾部出队 + if (queue_dequeue_tail(&q, &val)) { + printf("Dequeue tail: %d\n", val); + } + print_queue(&q); + + // 抛弃前3个 + size_t dropped = queue_drop_head(&q, 3); + printf("Drop head 3, actually dropped: %zu\n", dropped); + print_queue(&q); + + // 抛弃尾部10个(超出队列长度,实际清空) + dropped = queue_drop_tail(&q, 10); + printf("Drop tail 10, actually dropped: %zu\n", dropped); + print_queue(&q); + + // 销毁队列 + queue_destroy(&q); + printf("Queue destroyed.\n"); + + return 0; +} \ No newline at end of file