Implement CSV export function

This commit is contained in:
LuChiChick 2025-11-25 14:22:06 +08:00
parent 28728840a5
commit 87cc8637db
3 changed files with 198 additions and 7 deletions

View File

@ -16,6 +16,8 @@ namespace CSV_Type
CSV_ERROR_COLUMN_NOT_FOUND, // 未查找到指定列
CSV_ERROR_ILLEGAL_COLUMN_POSITION, // 非法列位置
CSV_ERROR_ILLEGAL_CELL_POSITION, // 非法单元格位置
CSV_ERROR_FILE_CREATE_FAILED, // 文件创建失败
CSV_ERROR_FILE_WRITE_FAILED, // 文件写入失败
} CSV_Err;
}
@ -23,8 +25,9 @@ namespace CSV_Type
class CSV_Table
{
protected:
size_t mem_use; // 存储占用
size_t column_count; // 列计数
size_t mem_use; // 存储占用
size_t column_count; // 列计数
size_t max_element_depth; // 最大元素深度
struct Column_List_Node_Struct
{
@ -111,8 +114,8 @@ public:
/**
* @brief
* @param target_column_title_str
* @param target_cell_position
* @param title_name_str
* @param target_cell_position
* @param cell_content_str
* @return CSV_Err
*/
CSV_Type::CSV_Err insert_cell_after(const char *target_column_title_str, size_t target_cell_position, const char *cell_content_str);
@ -120,11 +123,36 @@ public:
/**
* @brief
* @param target_column_title_str
* @param target_cell_position
* @param title_name_str
* @param target_cell_position
* @param cell_content_str
* @return CSV_Err
*/
CSV_Type::CSV_Err insert_cell_after(size_t target_column_position, size_t target_cell_position, const char *cell_content_str);
/**
* @brief
* @param target_column_title_str
* @param target_cell_position
* @param cell_content_str
* @return CSV_Err
*/
CSV_Type::CSV_Err insert_cell_before(const char *target_column_title_str, size_t target_cell_position, const char *cell_content_str);
/**
* @brief
* @param target_column_title_str
* @param target_cell_position
* @param cell_content_str
* @return CSV_Err
*/
CSV_Type::CSV_Err insert_cell_before(size_t target_column_position, size_t target_cell_position, const char *cell_content_str);
/**
* @brief
* @param file_name_str
* @return CSV_Err
*/
CSV_Type::CSV_Err export_to_file(const char *file_name_str);
};
#endif

View File

@ -11,6 +11,7 @@ CSV_Table::CSV_Table()
{
this->column_count = 0;
this->mem_use = 0;
this->max_element_depth = 0;
this->Column_List_End = this->Column_List_Head = nullptr;
}
@ -23,6 +24,7 @@ void CSV_Table::reset()
{
// 清理尾指针
this->Column_List_End = nullptr;
this->max_element_depth = 0;
this->column_count = 0;
this->mem_use = 0;
@ -304,6 +306,10 @@ CSV_Type::CSV_Err CSV_Table::append_cell(size_t target_column_position, const ch
}
p_target_column->element_count++;
if (p_target_column->element_count > this->max_element_depth)
this->max_element_depth = p_target_column->element_count;
return CSV_Type::CSV_ERROR_NONE;
}
@ -372,5 +378,158 @@ CSV_Type::CSV_Err CSV_Table::insert_cell_after(size_t target_column_position, si
}
p_target_column->element_count++;
if (p_target_column->element_count > this->max_element_depth)
this->max_element_depth = p_target_column->element_count;
return CSV_Type::CSV_ERROR_NONE;
}
CSV_Type::CSV_Err CSV_Table::insert_cell_before(const char *target_column_title_str, size_t target_cell_position, const char *cell_content_str)
{
size_t count = 0;
decltype(this->Column_List_Head) p_target_column = this->Column_List_Head;
while (p_target_column != nullptr)
{
if (!strcmp(p_target_column->column_title_str, target_column_title_str))
return this->insert_cell_before(count, target_cell_position, cell_content_str);
p_target_column = p_target_column->p_next_column;
count++;
}
return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND;
}
CSV_Type::CSV_Err CSV_Table::insert_cell_before(size_t target_column_position, size_t target_cell_position, const char *cell_content_str)
{
if ((target_column_position + 1) > this->column_count)
return CSV_Type::CSV_ERROR_ILLEGAL_COLUMN_POSITION;
decltype(this->Column_List_Head) p_target_column = this->Column_List_Head;
for (size_t count = 0; count < target_column_position; count++)
p_target_column = p_target_column->p_next_column;
if (!(((target_cell_position + 1) <= p_target_column->element_count) || ((target_cell_position == 0) && (p_target_column->element_count == 0))))
return CSV_Type::CSV_ERROR_ILLEGAL_CELL_POSITION;
decltype(p_target_column->Cell_List_Head) p_new_cell = (decltype(p_target_column->Cell_List_Head))malloc(sizeof(*(p_target_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;
if (p_target_column->element_count == 0)
{
p_new_cell->p_next_cell = nullptr;
p_target_column->Cell_List_Head = p_target_column->Cell_List_End = p_new_cell;
}
else
{
if (target_cell_position == 0)
{
p_new_cell->p_next_cell = p_target_column->Cell_List_Head;
p_target_column->Cell_List_Head = p_new_cell;
}
else
{
decltype(p_new_cell) p_pre_target_cell = p_target_column->Cell_List_Head;
for (size_t count = 0; count < target_cell_position - 1; count++)
p_pre_target_cell = p_pre_target_cell->p_next_cell;
p_new_cell->p_next_cell = p_pre_target_cell->p_next_cell;
p_pre_target_cell->p_next_cell = p_new_cell;
}
}
p_target_column->element_count++;
if (p_target_column->element_count > this->max_element_depth)
this->max_element_depth = p_target_column->element_count;
return CSV_Type::CSV_ERROR_NONE;
}
CSV_Type::CSV_Err CSV_Table::export_to_file(const char *file_name_str)
{
// 打开文件
FILE *p_file = fopen(file_name_str, "wb");
if (p_file == nullptr)
return CSV_Type::CSV_ERROR_FILE_CREATE_FAILED;
// 横向元素表
decltype(this->Column_List_Head->Cell_List_Head) *p_parallel_cell_list = nullptr;
// 输出内容
if (this->column_count != 0)
{
p_parallel_cell_list = (decltype(this->Column_List_Head->Cell_List_Head) *)malloc(sizeof(*this->Column_List_Head->Cell_List_Head) * this->column_count);
if (p_parallel_cell_list == nullptr)
return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED;
// 输出标题及填充横向列表
{
size_t count = 0;
for (decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; p_target_column != nullptr; p_target_column = p_target_column->p_next_column)
{
if (fprintf(p_file, "%s,", p_target_column->column_title_str) < 0)
goto file_write_error;
p_parallel_cell_list[count] = p_target_column->Cell_List_Head;
count++;
}
fseek(p_file, -1, SEEK_CUR);
if (fprintf(p_file, "\r\n") < 0)
goto file_write_error;
}
// 输出横向行内容
{
for (size_t row_count = 0; row_count < this->max_element_depth; row_count++)
{
for (size_t column_count = 0; column_count < this->column_count; column_count++)
{
if (p_parallel_cell_list[column_count] != nullptr)
{
if (fprintf(p_file, strstr(p_parallel_cell_list[column_count]->content_str, ",") ? "\"%s\"," : "%s,", p_parallel_cell_list[column_count]->content_str) < 0)
goto file_write_error;
p_parallel_cell_list[column_count] = p_parallel_cell_list[column_count]->p_next_cell;
}
else
{
if (fprintf(p_file, ",") < 0)
goto file_write_error;
}
}
fseek(p_file, -1, SEEK_CUR);
if (fprintf(p_file, "\r\n") < 0)
goto file_write_error;
}
}
free(p_parallel_cell_list);
}
fclose(p_file);
return CSV_Type::CSV_ERROR_NONE;
// 写入错误处理
file_write_error:
if (p_parallel_cell_list != nullptr)
free(p_parallel_cell_list);
fclose(p_file);
return CSV_Type::CSV_ERROR_FILE_WRITE_FAILED;
}

View File

@ -23,12 +23,16 @@ void Pre_Command_Solve(void)
CSV.insert_column_before("Test column", "Test insert column before Head");
CSV.insert_column_before("Test column", "Test insert column before Origin");
CSV.insert_cell_before("Test column 2", 0, "0");
CSV.append_cell("Test column 2", "1");
CSV.insert_cell_before("Test column 2", 0, "Insert");
CSV.insert_cell_after("Test column 3", (unsigned)0, "Insert Cell");
CSV.append_cell("Test column 3", "1");
CSV.append_cell("Test column 3", "2");
CSV.append_cell("Test column 3", "MyWawwww,dwadawdawd");
CSV.append_cell("Test column 3", "3");
CSV.export_to_file("new.csv");
// 获取命令行
int argc;
LPWSTR *argv;