From 914450ecb65bdf31ee7f0d0e34bdf90591260938 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Sun, 15 Dec 2024 21:14:12 +0800 Subject: [PATCH] mv text_io2 2 dsv_io --- example/text_io_ex.cpp | 28 +++-- lib/io.h | 2 +- lib/io/{text_io2.cpp => dsv_io.cpp} | 168 ++++++++++++++++++++-------- lib/io/{text_io2.h => dsv_io.h} | 154 ++++++++++++++++++------- tool/dsviewer/dsviewer.cpp | 10 +- 5 files changed, 258 insertions(+), 104 deletions(-) rename lib/io/{text_io2.cpp => dsv_io.cpp} (64%) rename lib/io/{text_io2.h => dsv_io.h} (74%) diff --git a/example/text_io_ex.cpp b/example/text_io_ex.cpp index 3bad1b0..d5dfac5 100644 --- a/example/text_io_ex.cpp +++ b/example/text_io_ex.cpp @@ -32,19 +32,27 @@ using namespace gctl; int main(int argc, char const *argv[]) try { -/* - text_content tc; + + dsv_io tc; tc.set_delimeter('|'); - tc.load_text("tmp/world_data", ".txt", HasColumnName); + tc.load_text("tmp/world_data", ".txt", BothHead); tc.info(); - _1s_array name; - tc.get_column("Name_s", name); - name.show(std::cout, ','); -*/ + //_1s_vector name = tc.get_row_names(); + //display_vector(name); - geodata_content tc; - tc.load_text("tmp/topo", ".txt", HasColumnName); + _1s_array name; + //tc.get_column("Name_s", name); + //name.show(std::cout, ','); + + tc.get_row("AUS", name); + name.show(std::cout, ','); + + tc.save_csv("out", BothHead); + +/* + geodsv_io tc; + tc.load_text("tmp/topo", ".txt", ColumnHead); array topo; tc.get_column_point3dc(0, 1, 2, topo); @@ -65,7 +73,7 @@ int main(int argc, char const *argv[]) try std::clog << std::setprecision(12) << tc.cell(0, 0) << "\n"; tc.info(); - +*/ return 0; } catch(std::exception &e) diff --git a/lib/io.h b/lib/io.h index 8ffabf0..ae60207 100644 --- a/lib/io.h +++ b/lib/io.h @@ -31,7 +31,7 @@ #include "io/mesh_io.h" #include "io/native_io.h" #include "io/text_io.h" -#include "io/text_io2.h" +#include "io/dsv_io.h" #include "io/gmsh_io.h" #include "io/surfer_io.h" #include "io/tetgen_io.h" diff --git a/lib/io/text_io2.cpp b/lib/io/dsv_io.cpp similarity index 64% rename from lib/io/text_io2.cpp rename to lib/io/dsv_io.cpp index 8b6a940..a5e6fee 100644 --- a/lib/io/text_io2.cpp +++ b/lib/io/dsv_io.cpp @@ -25,11 +25,13 @@ * Also add information on how to contact you by electronic and paper mail. ******************************************************/ -#include "text_io2.h" +#include "dsv_io.h" -gctl::text_content::text_content() +gctl::dsv_io::dsv_io() { // 设置基础参数 + file_ = ""; + corner_name_ = "row-idx"; att_sym_ = '#'; tag_sym_ = '!'; deli_sym_ = ' '; @@ -38,14 +40,16 @@ gctl::text_content::text_content() col_num_ = 0; } -gctl::text_content::~text_content() +gctl::dsv_io::~dsv_io() { clear(); } -gctl::text_content::text_content(std::string filename, std::string file_exten, text_head_type_e t) +gctl::dsv_io::dsv_io(std::string filename, std::string file_exten, table_headtype_e t) { // 设置基础参数 + file_ = ""; + corner_name_ = "row-idx"; att_sym_ = '#'; tag_sym_ = '!'; deli_sym_ = ' '; @@ -56,24 +60,31 @@ gctl::text_content::text_content(std::string filename, std::string file_exten, t load_text(filename, file_exten, t); } -void gctl::text_content::clear() +void gctl::dsv_io::clear() { + file_ = ""; + corner_name_ = "row-idx"; + att_sym_ = '#'; + tag_sym_ = '!'; + deli_sym_ = ' '; + head_num_ = 0; + row_num_ = 0; + col_num_ = 0; destroy_vector(heads_); destroy_vector(annotates_); destroy_vector(tags_); destroy_vector(lines_); destroy_vector(col_names_); + destroy_vector(row_names_); destroy_vector(table_); return; } -void gctl::text_content::load_text(std::string filename, std::string file_exten, text_head_type_e t) +void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table_headtype_e t) { std::ifstream infile; open_infile(infile, filename, file_exten); - clear(); - std::string tmp_line; std::stringstream tmp_ss; for (int i = 0; i < head_num_; i++) // 跳过前n行 包括空行 但不会保存空行 @@ -107,10 +118,11 @@ void gctl::text_content::load_text(std::string filename, std::string file_exten, else lines_.push_back(tmp_line); } infile.close(); - - if (t == HasColumnName) + + std::string head_str = ""; + if (t == ColumnHead || t == BothHead) { - parse_string_to_vector(lines_[0], deli_sym_, col_names_); + head_str = lines_[0]; lines_.erase(lines_.begin()); } @@ -145,24 +157,61 @@ void gctl::text_content::load_text(std::string filename, std::string file_exten, } } - for (size_t i = col_names_.size(); i < col_num_; i++) + if (t == ColumnHead || t == BothHead) { - col_names_.push_back("col-" + std::to_string(i + 1)); + parse_string_to_vector(head_str, deli_sym_, col_names_); + + for (size_t i = col_names_.size(); i < col_num_; i++) + { + col_names_.push_back("col-" + std::to_string(i + 1)); + } + } + + if (t == RowHead || t == BothHead) + { + col_num_ -= 1; // 列数目减一 + if (t == BothHead) + { + corner_name_ = col_names_[0]; + col_names_.erase(col_names_.begin()); + } + + row_names_.resize(row_num_); + for (size_t i = 0; i < row_num_; i++) + { + row_names_[i] = table_[i][0].str_; + table_[i].erase(table_[i].begin()); + } + + for (size_t i = row_names_.size(); i < row_num_; i++) + { + row_names_.push_back("row-" + std::to_string(i + 1)); + } } file_ = filename + file_exten; return; } -void gctl::text_content::load_csv(std::string filename, text_head_type_e t) +void gctl::dsv_io::load_csv(std::string filename, table_headtype_e t) { set_delimeter(','); load_text(filename, ".csv", t); return; } -void gctl::text_content::save_text(std::string filename, std::string file_exten) +void gctl::dsv_io::save_text(std::string filename, std::string file_exten, table_headtype_e t) { + if ((t == ColumnHead || t == BothHead) && col_names_.empty()) + { + throw std::runtime_error("[gctl::dsv_io::save_text] Row/Column names not instored."); + } + + if ((t == RowHead || t == BothHead) && row_names_.empty()) + { + throw std::runtime_error("[gctl::dsv_io::save_text] Row/Column names not instored."); + } + std::ofstream outfile; open_outfile(outfile, filename, file_exten); @@ -181,15 +230,22 @@ void gctl::text_content::save_text(std::string filename, std::string file_exten) outfile << "# " << annotates_[i] << std::endl; } - outfile << col_names_[0]; - for (size_t j = 1; j < col_names_.size(); j++) + if (t == BothHead) outfile << corner_name_ << deli_sym_; + + if (t == ColumnHead || t == BothHead) { - outfile << deli_sym_ << col_names_[j]; + outfile << col_names_[0]; + for (size_t j = 1; j < col_names_.size(); j++) + { + outfile << deli_sym_ << col_names_[j]; + } + outfile << std::endl; } - outfile << std::endl; for (int i = 0; i < row_num_; i++) { + if (t == RowHead || t == BothHead) outfile << row_names_[i] << deli_sym_; + outfile << table_[i][0].str_; for (size_t j = 1; j < col_num_; j++) { @@ -202,14 +258,14 @@ void gctl::text_content::save_text(std::string filename, std::string file_exten) return; } -void gctl::text_content::save_csv(std::string filename) +void gctl::dsv_io::save_csv(std::string filename, table_headtype_e t) { set_delimeter(','); - save_text(filename, ".csv"); + save_text(filename, ".csv", t); return; } -void gctl::text_content::init_table(int row, int col) +void gctl::dsv_io::init_table(int row, int col, table_headtype_e t) { row_num_ = row; col_num_ = col; @@ -224,52 +280,68 @@ void gctl::text_content::init_table(int row, int col) } } - col_names_.resize(col_num_); - for (size_t i = 0; i < col_num_; i++) + if (t == RowHead || t == BothHead) { - col_names_[i] = "col-" + std::to_string(i + 1); + row_names_.resize(row_num_); + for (size_t i = 0; i < row_num_; i++) + { + row_names_[i] = "row-" + std::to_string(i + 1); + } + } + + if (t == ColumnHead || t == BothHead) + { + col_names_.resize(col_num_); + for (size_t i = 0; i < col_num_; i++) + { + col_names_[i] = "col-" + std::to_string(i + 1); + } } return; } -void gctl::text_content::init_table(int row, int col, const std::vector &names) -{ - init_table(row, col); - set_column_names(names); - return; -} - -void gctl::text_content::set_head_records(const std::vector &heads) +void gctl::dsv_io::set_head_records(const std::vector &heads) { heads_ = heads; head_num_ = heads_.size(); return; } -void gctl::text_content::set_annotoations(const std::vector &att) +void gctl::dsv_io::set_annotoations(const std::vector &att) { annotates_ = att; return; } -void gctl::text_content::set_tags(const std::vector &tags) +void gctl::dsv_io::set_tags(const std::vector &tags) { tags_ = tags; return; } -void gctl::text_content::set_column_names(const std::vector &names) +void gctl::dsv_io::set_column_names(const std::vector &names) { - if (col_num_ != col_names_.size()) + if (col_num_ != names.size()) { - throw std::runtime_error("[gctl::text_content::set_column_names] Invalid name size."); + throw std::runtime_error("[gctl::dsv_io::set_column_names] Invalid name size."); } col_names_ = names; return; } -void gctl::text_content::cell(int r, int c, double d, int p) +void gctl::dsv_io::set_row_names(const std::vector &names) +{ + if (row_num_ != names.size()) + { + throw std::runtime_error("[gctl::dsv_io::set_column_names] Invalid name size."); + } + + row_names_ = names; + return; +} + +void gctl::dsv_io::cell(int r, int c, double d, int p) { std::stringstream ss; if (p != 6) ss.precision(p); @@ -279,7 +351,7 @@ void gctl::text_content::cell(int r, int c, double d, int p) return; } -void gctl::text_content::info() +void gctl::dsv_io::info() { std::clog << "File: " << file_ << "\n------------\n"; std::clog << "Head(s): " << head_num_ << "\n"; @@ -304,11 +376,11 @@ void gctl::text_content::info() return; } -void gctl::geodata_content::fill_column_point2dc(int xid, int yid, const array &data, int p) +void gctl::geodsv_io::fill_column_point2dc(int xid, int yid, const array &data, int p) { if (xid >= col_num_ || yid >= col_num_ || xid == yid) { - throw std::runtime_error("[gctl::geodata_content::fill_column_point2dc] Invalid column index."); + throw std::runtime_error("[gctl::geodsv_io::fill_column_point2dc] Invalid column index."); } std::stringstream ss; @@ -328,11 +400,11 @@ void gctl::geodata_content::fill_column_point2dc(int xid, int yid, const array

&data, int p) +void gctl::geodsv_io::fill_column_point3dc(int xid, int yid, int zid, const array &data, int p) { if (xid >= col_num_ || yid >= col_num_ || zid >= col_num_ || xid == yid || yid == zid || xid == zid) { - throw std::runtime_error("[gctl::geodata_content::fill_column_point3dc] Invalid column index."); + throw std::runtime_error("[gctl::geodsv_io::fill_column_point3dc] Invalid column index."); } std::stringstream ss; @@ -357,11 +429,11 @@ void gctl::geodata_content::fill_column_point3dc(int xid, int yid, int zid, cons return; } -void gctl::geodata_content::get_column_point2dc(int xid, int yid, array &data) +void gctl::geodsv_io::get_column_point2dc(int xid, int yid, array &data) { if (xid >= col_num_ || yid >= col_num_ || xid == yid) { - throw std::runtime_error("[gctl::geodata_content::fill_column_point2dc] Invalid column index."); + throw std::runtime_error("[gctl::geodsv_io::fill_column_point2dc] Invalid column index."); } data.resize(row_num_); @@ -373,11 +445,11 @@ void gctl::geodata_content::get_column_point2dc(int xid, int yid, array &data) +void gctl::geodsv_io::get_column_point3dc(int xid, int yid, int zid, array &data) { if (xid >= col_num_ || yid >= col_num_ || zid >= col_num_ || xid == yid || yid == zid || xid == zid) { - throw std::runtime_error("[gctl::geodata_content::fill_column_point3dc] Invalid column index."); + throw std::runtime_error("[gctl::geodsv_io::fill_column_point3dc] Invalid column index."); } data.resize(row_num_); diff --git a/lib/io/text_io2.h b/lib/io/dsv_io.h similarity index 74% rename from lib/io/text_io2.h rename to lib/io/dsv_io.h index 72b255d..bb38c17 100644 --- a/lib/io/text_io2.h +++ b/lib/io/dsv_io.h @@ -57,10 +57,16 @@ namespace gctl } }; - enum text_head_type_e + /** + * @brief 表格的头信息类型 + * + */ + enum table_headtype_e { - HasColumnName, - NoColumnName, + NoHead, // 没有表头 + BothHead, // 同时有行与列表头 + ColumnHead, // 只有列表头 + RowHead, // 只有行表头 }; /** @@ -70,13 +76,14 @@ namespace gctl * 1. 以'#'开始的行均为注释行,标识符可由用户指定; * 2. 以'#!'开始的行均为标记行,标识符可由用户指定; * 3. 文本开始可以包含n行头信息; - * 4. 数据体为一个row*col大小的表格。 + * 4. 数据体为一个row*col大小的表格; + * 5. 数据体可以包含一列行名称与列名称。 * */ - class text_content + class dsv_io { protected: - std::string file_; + std::string file_, corner_name_; // 头信息行数 表格行数 表格列数 int head_num_, row_num_, col_num_; // 注释行起始符 标记行起始符 分割符 @@ -84,7 +91,7 @@ namespace gctl // 头信息行 注释行 标记行 std::vector heads_, annotates_, tags_; // 内容行与表格 - std::vector col_names_; + std::vector col_names_, row_names_; std::vector lines_; std::vector > table_; @@ -93,13 +100,13 @@ namespace gctl * @brief Construct a new text content object * */ - text_content(); + dsv_io(); /** * @brief Destroy the text content object * */ - ~text_content(); + ~dsv_io(); /** * @brief Construct a new text descriptor object and load text file @@ -107,7 +114,7 @@ namespace gctl * @param filename 文件名 * @param file_exten 文件扩展名 */ - text_content(std::string filename, std::string file_exten = ".txt", text_head_type_e t = NoColumnName); + dsv_io(std::string filename, std::string file_exten = ".txt", table_headtype_e t = NoHead); /** * @brief 设置列分隔符 @@ -195,6 +202,13 @@ namespace gctl */ const std::vector& get_column_names(){return col_names_;} + /** + * @brief 返回行名称 + * + * @return 行名称 + */ + const std::vector& get_row_names(){return row_names_;} + /** * @brief 设置头信息 * @@ -223,6 +237,13 @@ namespace gctl */ void set_column_names(const std::vector &names); + /** + * @brief 设置行数据名称 + * + * @param names 行名称 + */ + void set_row_names(const std::vector &names); + /** * @brief 清理字符串向量对象 * @@ -235,14 +256,14 @@ namespace gctl * @param filename 文件名 * @param file_exten 文件扩展名 */ - void load_text(std::string filename, std::string file_exten = ".txt", text_head_type_e t = NoColumnName); + void load_text(std::string filename, std::string file_exten = ".txt", table_headtype_e t = NoHead); /** * @brief 读入CSV文件 * * @param filename 文件名 */ - void load_csv(std::string filename, text_head_type_e t = HasColumnName); + void load_csv(std::string filename, table_headtype_e t = ColumnHead); /** * @brief 将内容写入文件 @@ -250,14 +271,14 @@ namespace gctl * @param filename 文件名 * @param file_exten 文件扩展名 */ - void save_text(std::string filename, std::string file_exten = ".txt"); + void save_text(std::string filename, std::string file_exten = ".txt", table_headtype_e t = NoHead); /** * @brief 将内容写入CSV文件 * * @param filename 文件名(无后缀) */ - void save_csv(std::string filename); + void save_csv(std::string filename, table_headtype_e t = ColumnHead); /** * @brief 初始化表格 @@ -265,16 +286,7 @@ namespace gctl * @param row 行数 * @param col 列数 */ - void init_table(int row, int col); - - /** - * @brief 初始化表格 - * - * @param row 行数 - * @param col 列数 - * @param names 列名称 - */ - void init_table(int row, int col, const std::vector &names); + void init_table(int row, int col, table_headtype_e t = ColumnHead); /** * @brief 填充列 @@ -303,6 +315,15 @@ namespace gctl */ template void fill_row(int idx, const array &data, int p = 6); + /** + * @brief 填充行 + * + * @tparam T 数据类型 + * @param name 行名称 + * @param data 行数据 + */ + template void fill_row(std::string name, const array &data, int p = 6); + /** * @brief 获取列数据 * @@ -329,6 +350,15 @@ namespace gctl * @param data 行数据 */ template void get_row(int idx, array &data); + + /** + * @brief 获取行数据 + * + * @tparam T 数据类型 + * @param name 行名称 + * @param data 行数据 + */ + template void get_row(std::string name, array &data); /** * @brief 获取表格单元数据 @@ -368,11 +398,11 @@ namespace gctl }; template - void text_content::fill_column(int idx, const array &data, int p) + void dsv_io::fill_column(int idx, const array &data, int p) { if (idx >= col_num_) { - throw std::runtime_error("[gctl::text_content::fill_column] Invalid column index."); + throw std::runtime_error("[gctl::dsv_io::fill_column] Invalid column index."); } if constexpr (std::is_same::value) @@ -402,11 +432,11 @@ namespace gctl } template - void text_content::fill_column(std::string name, const array &data, int p) + void dsv_io::fill_column(std::string name, const array &data, int p) { if (col_names_.empty()) { - throw std::runtime_error("[gctl::text_content::fill_column] No column names instored."); + throw std::runtime_error("[gctl::dsv_io::fill_column] No column names instored."); } for (size_t i = 0; i < col_names_.size(); i++) @@ -418,16 +448,16 @@ namespace gctl } } - throw std::runtime_error("[gctl::text_content::fill_column] No column found by the input name."); + throw std::runtime_error("[gctl::dsv_io::fill_column] No column found by the input name."); return; } template - void text_content::fill_row(int idx, const array &data, int p) + void dsv_io::fill_row(int idx, const array &data, int p) { if (idx >= row_num_) { - throw std::runtime_error("[gctl::text_content::fill_row] Invalid row index."); + throw std::runtime_error("[gctl::dsv_io::fill_row] Invalid row index."); } if constexpr (std::is_same::value) @@ -455,11 +485,32 @@ namespace gctl } template - void text_content::get_column(int idx, array &data) + void dsv_io::fill_row(std::string name, const array &data, int p) + { + if (row_names_.empty()) + { + throw std::runtime_error("[gctl::dsv_io::fill_row] No row names instored."); + } + + for (size_t i = 0; i < row_names_.size(); i++) + { + if (row_names_[i] == name) + { + fill_row(i, data, p); + return; + } + } + + throw std::runtime_error("[gctl::dsv_io::fill_row] No row found by the input name."); + return; + } + + template + void dsv_io::get_column(int idx, array &data) { if (idx >= col_num_) { - throw std::runtime_error("[gctl::text_content::get_column] Invalid column index."); + throw std::runtime_error("[gctl::dsv_io::get_column] Invalid column index."); } data.resize(row_num_); @@ -471,11 +522,11 @@ namespace gctl } template - void text_content::get_column(std::string name, array &data) + void dsv_io::get_column(std::string name, array &data) { if (col_names_.empty()) { - throw std::runtime_error("[gctl::text_content::get_column] No column names instored."); + throw std::runtime_error("[gctl::dsv_io::get_column] No column names instored."); } for (size_t i = 0; i < col_names_.size(); i++) @@ -487,16 +538,16 @@ namespace gctl } } - throw std::runtime_error("[gctl::text_content::get_column] No column found by the input name."); + throw std::runtime_error("[gctl::dsv_io::get_column] No column found by the input name."); return; } template - void text_content::get_row(int idx, array &data) + void dsv_io::get_row(int idx, array &data) { if (idx >= row_num_) { - throw std::runtime_error("[gctl::text_content::get_column] Invalid row index."); + throw std::runtime_error("[gctl::dsv_io::get_row] Invalid row index."); } data.resize(col_num_); @@ -507,11 +558,32 @@ namespace gctl return; } - class geodata_content : public text_content + template + void dsv_io::get_row(std::string name, array &data) + { + if (row_names_.empty()) + { + throw std::runtime_error("[gctl::dsv_io::get_row] No row names instored."); + } + + for (size_t i = 0; i < row_names_.size(); i++) + { + if (row_names_[i] == name) + { + get_row(i, data); + return; + } + } + + throw std::runtime_error("[gctl::dsv_io::get_row] No row found by the input name."); + return; + } + + class geodsv_io : public dsv_io { public: - geodata_content(){}; - ~geodata_content(){}; + geodsv_io(){}; + ~geodsv_io(){}; void fill_column_point2dc(int xid, int yid, const array &data, int p = 6); diff --git a/tool/dsviewer/dsviewer.cpp b/tool/dsviewer/dsviewer.cpp index 899f43a..f171c27 100644 --- a/tool/dsviewer/dsviewer.cpp +++ b/tool/dsviewer/dsviewer.cpp @@ -30,7 +30,7 @@ #include "editline.h" cmd_pair curr_cmd; // Executing command -gctl::text_content tc; // Grid object +gctl::dsv_io tc; // Grid object extern "C" { @@ -226,9 +226,11 @@ void load_file(const std::vector &cmd_units) copy_str[i] = cmd_units[i + 2]; } - text_head_type_e ht = NoColumnName; - if (copy_str[0] == "nohead") ht = NoColumnName; - else if (copy_str[0] == "hashead") ht = HasColumnName; + table_headtype_e ht = NoHead; + if (copy_str[0] == "nohead") ht = NoHead; + else if (copy_str[0] == "column") ht = ColumnHead; + else if (copy_str[0] == "row") ht = RowHead; + else if (copy_str[0] == "both") ht = BothHead; if (copy_str[1] != "null") tc.set_delimeter(copy_str[1][0]); if (copy_str[2] != "null") tc.set_tag_symbol(copy_str[2][0]);