From e3f513208617e78570c55e3f995f743ac5185f31 Mon Sep 17 00:00:00 2001 From: LuChiChick <1084116302@qq.com> Date: Fri, 21 Nov 2025 17:45:12 +0800 Subject: [PATCH] Basic CSV table class and test code --- Inc/CSV_Utilities.hpp | 94 ++++++++++++++++++ Src/CSV_Utilities.cpp | 223 ++++++++++++++++++++++++++++++++++++++++++ Src/Command_Solve.cpp | 12 +++ 3 files changed, 329 insertions(+) create mode 100644 Inc/CSV_Utilities.hpp create mode 100644 Src/CSV_Utilities.cpp diff --git a/Inc/CSV_Utilities.hpp b/Inc/CSV_Utilities.hpp new file mode 100644 index 0000000..63c81f9 --- /dev/null +++ b/Inc/CSV_Utilities.hpp @@ -0,0 +1,94 @@ +#ifndef __CSV_EXPORTER__ +#define __CSV_EXPORTER__ + +extern "C" +{ +#include "stdint.h" +} + +namespace CSV_Type +{ + // 错误类型 + typedef enum + { + CSV_ERROR_NONE, // None Error + CSV_ERROR_MEM_ALLOCATE_FAILED, // 内存分配失败 + CSV_ERROR_COLUMN_NOT_FOUND, // 未查找到指定列 + } CSV_Err; + +} + +class CSV_Table +{ +protected: + size_t mem_use; // 存储占用 + size_t column_count; // 列计数 + + struct Column_List_Node_Struct + { + char *column_title_str; // 列标题 + size_t element_count; // 下属内容长度 + + struct Cell_List_Node // 单元格节点 + { + char *content_str; // 内容字符串 + Cell_List_Node *p_next_cell; // 列表索引 + } *Cell_List_Head, *Cell_List_End; // 表头、表尾 + + Column_List_Node_Struct *p_next_column; // 下一列 + } *Column_List_Head, *Column_List_End; // 列表横向表头、表尾 + +public: + // 构造函数 + CSV_Table(); + // 析构函数 + ~CSV_Table(); + + /** + * @brief 清理缓存数据并回到空白状态 + * @param null + * @return null + */ + void reset(); + + /** + * @brief 在末尾新增列 + * @param title_name_str 列标题 + * @return CSV_Err 错误类型 + */ + CSV_Type::CSV_Err append_column(const char *title_name_str); + + /** + * @brief 在指定标题的列表后新增列 + * @param target_column_title_str 目标列标题 + * @param title_name_str 插入的列标题 + * @return CSV_Err 错误类型 + */ + CSV_Type::CSV_Err insert_column_after(const char *target_column_title_str, const char *title_name_str); + + /** + * @brief 在指定标题的列表后新增列 + * @param target_column_title_str 目标列标题 + * @param title_name_str 插入的列标题 + * @return CSV_Err 错误类型 + */ + CSV_Type::CSV_Err insert_column_after(size_t target_column_position, const char *title_name_str); + + /** + * @brief 指定列末尾新增单元格 + * @param column_title_str 列标题 + * @param cell_content_str 单元格内容串 + * @return CSV_Err 错误类型 + */ + CSV_Type::CSV_Err append_cell(const char *column_title_str, const char *cell_content_str); + + /** + * @brief 指定列末尾新增单元格 + * @param column_position 列位置计数 + * @param cell_content_str 单元格内容串 + * @return CSV_Err 错误类型 + */ + CSV_Type::CSV_Err append_cell(size_t column_position, const char *cell_content_str); +}; + +#endif \ No newline at end of file diff --git a/Src/CSV_Utilities.cpp b/Src/CSV_Utilities.cpp new file mode 100644 index 0000000..3c7272b --- /dev/null +++ b/Src/CSV_Utilities.cpp @@ -0,0 +1,223 @@ +#include "CSV_Utilities.hpp" + +extern "C" +{ +#include "stdlib.h" +#include "string.h" +#include "stdio.h" +} + +CSV_Table::CSV_Table() +{ + this->column_count = 0; + this->mem_use = 0; + this->Column_List_End = this->Column_List_Head = nullptr; +} + +CSV_Table::~CSV_Table() +{ + this->reset(); +} + +void CSV_Table::reset() +{ + // 清理尾指针 + this->Column_List_End = nullptr; + this->column_count = 0; + this->mem_use = 0; + + // 清理头指针及其内容 + if (this->Column_List_Head != nullptr) + { + // 释放列 + while (this->Column_List_Head != nullptr) + { + decltype(this->Column_List_Head) p_column = this->Column_List_Head; + + // 释放单元格列表 + while (p_column->Cell_List_Head != nullptr) + { + decltype(p_column->Cell_List_Head) p_cell = p_column->Cell_List_Head; + + // 释放单元格内容 + if (p_cell->content_str != nullptr) + free(p_cell->content_str); + + p_column->Cell_List_Head = p_cell->p_next_cell; + free(p_cell->content_str); + } + + // 释放标题 + if (p_column->column_title_str != nullptr) + free(p_column->column_title_str); + + this->Column_List_Head = p_column->p_next_column; + free(p_column); + } + } +} + +CSV_Type::CSV_Err CSV_Table::append_column(const char *title_name_str) +{ + + // 开辟新节点 + decltype(this->Column_List_Head) p_new_column = (decltype(this->Column_List_Head))malloc(sizeof(*(this->Column_List_Head))); + if (p_new_column == nullptr) + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + this->mem_use += sizeof(*p_new_column); + // 节点初始化 + p_new_column->Cell_List_Head = p_new_column->Cell_List_End = nullptr; + p_new_column->p_next_column = nullptr; + p_new_column->element_count = 0; + + // 存储列标题名 + if (title_name_str != nullptr) + { + char *p_title = (char *)malloc(strlen(title_name_str) + 1); // +1 for '\0' + if (p_title == nullptr) + { + free(p_new_column); + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + } + + this->mem_use += strlen(title_name_str) + 1; + strcpy(p_title, title_name_str); + p_new_column->column_title_str = p_title; + } + else + p_new_column->column_title_str = nullptr; + + // 插入列链表 + if (this->column_count == 0) + this->Column_List_End = this->Column_List_Head = p_new_column; + else + { + this->Column_List_End->p_next_column = p_new_column; + this->Column_List_End = p_new_column; + } + + this->column_count++; + return CSV_Type::CSV_ERROR_NONE; +} + +CSV_Type::CSV_Err CSV_Table::insert_column_after(const char *target_column_title_str, const char *title_name_str) +{ + size_t count = 0; + decltype(this->Column_List_Head) p_column = this->Column_List_Head; + while (p_column != nullptr) + { + if (!strcmp(p_column->column_title_str, target_column_title_str)) + return this->insert_column_after(count, title_name_str); + + p_column = p_column->p_next_column; + count++; + } + return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; +} + +CSV_Type::CSV_Err CSV_Table::insert_column_after(size_t target_column_position, const char *title_name_str) +{ + if ((target_column_position + 1) > this->column_count) + return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; + + decltype(this->Column_List_Head) p_column = this->Column_List_Head; + for (size_t count = 0; count < target_column_position; count++) + p_column = p_column->p_next_column; + + // 开辟新节点 + decltype(p_column) p_new_column = (decltype(p_column))malloc(sizeof(*(p_column))); + if (p_new_column == nullptr) + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + this->mem_use += sizeof(*p_new_column); + + // 节点初始化 + p_new_column->Cell_List_Head = p_new_column->Cell_List_End = nullptr; + p_new_column->p_next_column = nullptr; + p_new_column->element_count = 0; + + // 存储列标题名 + if (title_name_str != nullptr) + { + char *p_title = (char *)malloc(strlen(title_name_str) + 1); // +1 for '\0' + if (p_title == nullptr) + { + free(p_new_column); + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + } + + this->mem_use += strlen(title_name_str) + 1; + strcpy(p_title, title_name_str); + p_new_column->column_title_str = p_title; + } + else + p_new_column->column_title_str = nullptr; + + // 链接节点 + p_new_column->p_next_column = p_column->p_next_column; + p_column->p_next_column = p_new_column; + this->column_count++; + + // 目标位置在末尾时 + if (target_column_position == this->column_count - 1) + this->Column_List_End = p_new_column; + + return CSV_Type::CSV_ERROR_NONE; +} + +CSV_Type::CSV_Err CSV_Table::append_cell(const char *column_title_str, const char *cell_content_str) +{ + size_t count = 0; + decltype(this->Column_List_Head) p_column = this->Column_List_Head; + while (p_column != nullptr) + { + if (!strcmp(p_column->column_title_str, column_title_str)) + return this->append_cell(count, cell_content_str); + + p_column = p_column->p_next_column; + count++; + } + return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; +} + +CSV_Type::CSV_Err CSV_Table::append_cell(size_t column_position, const char *cell_content_str) +{ + if ((column_position + 1) > this->column_count) + return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; + + decltype(this->Column_List_Head) p_column = this->Column_List_Head; + for (size_t count = 0; count < column_position; count++) + p_column = p_column->p_next_column; + + decltype(p_column->Cell_List_Head) p_new_cell = (decltype(p_column->Cell_List_Head))malloc(sizeof(*(p_column->Cell_List_Head))); + if (p_new_cell == nullptr) + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + this->mem_use += sizeof(*p_new_cell); + + if (cell_content_str != nullptr) + { + char *p_content = (char *)malloc(strlen(cell_content_str) + 1); // +1 for '\0' + if (p_content == nullptr) + { + free(p_new_cell); + return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; + } + + this->mem_use += strlen(cell_content_str) + 1; + strcpy(p_content, cell_content_str); + p_new_cell->content_str = p_content; + } + else + p_new_cell->content_str = nullptr; + p_new_cell->p_next_cell = nullptr; + + if (p_column->element_count == 0) + p_column->Cell_List_Head = p_column->Cell_List_End = p_new_cell; + else + { + p_column->Cell_List_End->p_next_cell = p_new_cell; + p_column->Cell_List_End = p_new_cell; + } + + p_column->element_count++; + return CSV_Type::CSV_ERROR_NONE; +} \ No newline at end of file diff --git a/Src/Command_Solve.cpp b/Src/Command_Solve.cpp index b5944b1..ea35d36 100644 --- a/Src/Command_Solve.cpp +++ b/Src/Command_Solve.cpp @@ -4,6 +4,7 @@ extern "C" { #include "windows.h" +#include "CSV_Utilities.hpp" } DLT_File File; @@ -11,6 +12,17 @@ DLT_File File; // 命令行处理 void Pre_Command_Solve(void) { + CSV_Table CSV; + CSV.append_column("Test column"); + CSV.append_column("Test column 2"); + CSV.append_column("Test column 3"); + CSV.insert_column_after("Test column 2", "Test insert column"); + + CSV.append_cell("Test column 2", "1"); + CSV.append_cell("Test column 3", "1"); + CSV.append_cell("Test column 3", "2"); + CSV.append_cell("Test column 3", "3"); + // 获取命令行 int argc; LPWSTR *argv;