2022/05/28 UPDATE TANXL_DATABASE VERSION_1_6

此版本僅在上一版的基礎上進行了很小的修改

上一版本:2022/04/04 UPDATE TANXL_DATABASE VERSION_1_5 - 嗶哩嗶哩 (bilibili.com)

主要修改內容:

//_VERSION_1_6_ UPDATE LOG

// LAST_UPDATE 2022-05-28 01:20

// 調整結構體內容/類成員 以降低連續儲存壓力

考慮到如此巨大的結構體在遊戲執行的過程中可能導致記憶體溢位(找不到這麼大的空間了),因此此版本在上一版的基礎上將資料結構縮小,將其成員變數改為指標,降低連續儲存的壓力(Vector使用中會產生碎片)。

標頭檔案改動內容

其次在檔案開頭都加上了#pragma once避免重複編譯。

原始檔的修改內容僅為操作成員轉為指標。

WiChG_DEV_2023///TANXL

HEAD_FILE//_VERSION_1_6_ UPDATE LOG // LAST_UPDATE 2022-05-28 01:20 // 調整結構體內容/類成員 以降低連續儲存壓力 #pragma once #ifndef IOSTREAM #define IOSTREAM #include<iostream> #endif #ifndef FSTREAM #define FSTREAM #include<fstream> #endif #ifndef STRING #define STRING #include<string> #endif #ifndef SSTREAM #define SSTREAM #include<sstream> #endif #ifndef VECTOR #define VECTOR #include<vector> #endif enum ESort_Mode//為SortDataBase函式提供的功能列舉 { SORT_LOCALF = 0, SORT_MEMORY = 2, }; enum EDivid_Mode//為Divid_Char函式提供的功能列舉 { GET_STATUS_DAT = 0, GET_STORAG_DAT = 1, GET_STATUS_TAG = 2, GET_STATUS_STR = 3, GET_OLDSTY_DAT = 4 }; enum ESet_Specified { SET_TYPE_STATUS = 0, SET_EXAC_STATUS = 1, SET_OTH1_STATUS = 2, SET_OTH2_STATUS = 3, SET_OTH3_STATUS = 4, }; enum ESet_Instance { SET_TYPE_0 = 0x00000, SET_EXAC_0 = 0x00000, SET_OTH1_0 = 0x00000, SET_OTH2_0 = 0x00000, SET_OTH3_0 = 0x00000, SET_TYPE_1 = 0x10000, SET_EXAC_1 = 0x01000, SET_OTH1_1 = 0x00100, SET_OTH2_1 = 0x00010, SET_OTH3_1 = 0x00001, SET_TYPE_2 = 0x20000, SET_EXAC_2 = 0x02000, SET_OTH1_2 = 0x00200, SET_OTH2_2 = 0x00020, SET_OTH3_2 = 0x00002, SET_TYPE_3 = 0x30000, SET_EXAC_3 = 0x03000, SET_OTH1_3 = 0x00300, SET_OTH2_3 = 0x00030, SET_OTH3_3 = 0x00003, SET_TYPE_4 = 0x40000, SET_EXAC_4 = 0x04000, SET_OTH1_4 = 0x00400, SET_OTH2_4 = 0x00040, SET_OTH3_4 = 0x00004, SET_TYPE_5 = 0x50000, SET_EXAC_5 = 0x05000, SET_OTH1_5 = 0x00500, SET_OTH2_5 = 0x00050, SET_OTH3_5 = 0x00005, SET_TYPE_6 = 0x60000, SET_EXAC_6 = 0x06000, SET_OTH1_6 = 0x00600, SET_OTH2_6 = 0x00060, SET_OTH3_6 = 0x00006, SET_TYPE_7 = 0x70000, SET_EXAC_7 = 0x07000, SET_OTH1_7 = 0x00700, SET_OTH2_7 = 0x00070, SET_OTH3_7 = 0x00007, SET_TYPE_8 = 0x80000, SET_EXAC_8 = 0x08000, SET_OTH1_8 = 0x00800, SET_OTH2_8 = 0x00080, SET_OTH3_8 = 0x00008, SET_TYPE_9 = 0x90000, SET_EXAC_9 = 0x09000, SET_OTH1_9 = 0x00900, SET_OTH2_9 = 0x00090, SET_OTH3_9 = 0x00009, SET_TYPE_10 = 0xa0000, SET_EXAC_10 = 0x0a000, SET_OTH1_10 = 0x00a00, SET_OTH2_10 = 0x000a0, SET_OTH3_10 = 0x0000a, SET_TYPE_11 = 0xb0000, SET_EXAC_11 = 0x0b000, SET_OTH1_11 = 0x00b00, SET_OTH2_11 = 0x000b0, SET_OTH3_11 = 0x0000b, SET_TYPE_12 = 0xc0000, SET_EXAC_12 = 0x0c000, SET_OTH1_12 = 0x00c00, SET_OTH2_12 = 0x000c0, SET_OTH3_12 = 0x0000c, SET_TYPE_13 = 0xd0000, SET_EXAC_13 = 0x0d000, SET_OTH1_13 = 0x00d00, SET_OTH2_13 = 0x000d0, SET_OTH3_13 = 0x0000d, SET_TYPE_14 = 0xe0000, SET_EXAC_14 = 0x0e000, SET_OTH1_14 = 0x00e00, SET_OTH2_14 = 0x000e0, SET_OTH3_14 = 0x0000e, SET_TYPE_15 = 0xf0000, SET_EXAC_15 = 0x0f000, SET_OTH1_15 = 0x00f00, SET_OTH2_15 = 0x000f0, SET_OTH3_15 = 0x0000f, }; struct Data_Vector//短資料表(Vector) { explicit Data_Vector(int I_A = 0, std::string D_A = NULL, int I_B = 0, std::string D_B = NULL, int I_C = 0, std::string D_C = NULL) : Id_1(I_A), Id_2(I_B), Id_3(I_C), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C) {} int Id_1, Id_2, Id_3; std::string Sd_1, Sd_2, Sd_3; }; struct Id_Vector//短型別表(Vector) { explicit Id_Vector(int Type, int Exac, std::string Code = "NULL", std::string Name = "NULL") : Type(Type), Exac(Exac), StrA(Code), StrB(Name), exac(new std::vector<Data_Vector*>) {} int Type, Exac; std::string StrA, StrB; std::vector<Data_Vector*>* exac;//用於支援折半查詢 }; class TANXL_DataBase { private: struct { unsigned Item_Status{ 0 }; unsigned Status_1{}; std::string Code; unsigned Status_2{}; std::string Name; unsigned Status_3{}; std::string Oth1; unsigned Status_4{}; std::string Oth2; unsigned Status_5{}; std::string Oth3; }Item_Instance; std::vector<Id_Vector*>* IC_Vector; int Current_Location; bool Is_Instance_Data;//用來判斷Item_Instance中是否有資料 bool Is_Chain_Empty;//用來判斷連結串列是否為空 bool Is_Zero_Legal;//值為true時0成為合法值 可在輸出中顯示/使用 inline void Set_Code(std::string set, unsigned status); inline void Set_Name(std::string set, unsigned status); inline void Set_Oth1(std::string set, unsigned status); inline void Set_Oth2(std::string set, unsigned status); inline void Set_Oth3(std::string set, unsigned status); Id_Vector* Id_Chain_Locate(int Type, int Exac);//時間複雜度為logN的Id_Chain快速定位函式 Type Exac 指Id_Chain的同名變數 Data_Vector* Data_Chain_Locate(int Type, int Exac, int Depth);//藉由Id_Chain_Locate函式對不同深度的Data_Chain定位 void Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac);//轉移Data_Chain到另一個Id_Chain下 void Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id);//連結串列新增內容V3 新增到Vector中 void Get_Item_Status();//獲取物品數值 並載入到結構中 void Clear_Chain();//清理連結串列 void ResetInstance();//重置Item結構的內容 inline void OstreamSpace(std::ostream& os, int Before = 0, int After = 0);//根據級別輸出空格 Before用於執行前對級別數值進行修改 After用於執行後 inline void Combine_Status();//組合Status各物品級別併合併到Item_Instance中 public: TANXL_DataBase(bool Zero_Legal = false);//建構函式 bool Get_LocalData(std::string File_Name);//獲取本地資料 並新建一個連結串列 支援開啟任意格式的檔案(.usd .sd) //↓編輯例項 0x12345 1代表Code位 2代表Name位 3代表Oth1位 依此類推 僅在Is_Zero_Legal為false時可以正常工作 //↓零合法時接受的十六進位制數為6位 0x123456 6用於表示當前指向的位編號 範圍1~5 1代表 Oth3位 2代表 Oth2位... 除最後一位以外 其餘位與零不合法時完全相反 void Set_Instance(unsigned Num, std::string Set); void Get_Specified(int Type, int Exac, int Nums);//讀取指定Type(A)_Exac(B)級別的物品 並載入到單例結構中 Nums表示連結串列中的第幾個(從0開始) //↓修改指定Type(A)_Exac(B)級別的物品 Nums表示連結串列中的第幾個(從0開始) level取值範圍為1~5 用於選定Type Exac Oth1 ... //↓修改OTH1 OTH2 OTH3的時候直接更改相關內容 修改TYPE-EXAC時 會轉移當前Data_Chain到新的符合修改後的TYPE-EXAC的Id_Chain下 void Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data); void Remove_Chain(int Type, int Exac);//刪除某一節點與其下所有內容 //↓輸出當前記憶體中的連結串列的所有內容 僅支援輸出Id_Vector和Data_Vector中的內容 當前記憶體為空時會丟擲錯誤 void Print_Data(); void AppendItem(bool To_File = true, std::string File_Name = "Tanxl_DataBase.usd");//向本地檔案中(.usd)新增Item物品 此函式會導致Item單例重置 //↓使本地(.usd)檔案的內容合理化 In_File_Name為輸入檔名 Out_File_Name為輸出檔名 現在具有儲存連結串列修改功能 //↓Mode為true時從檔案中讀取資料 需要提供In/Out_File_Name 執行後清空記憶體中的連結串列 Mode為false時直接對當前記憶體中的連結串列進行整理 可以使現有連結串列改為升序 執行後不清空 void SortDataBase(int Mode = SORT_LOCALF, std::string Out_File_Name = "Tanxl_Data", std::string In_File_Name = "Tanxl_DataBase"); friend std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s);//用於直接輸出當前Item單例內的資訊 }; std::string Combine_Char(std::string data, int Start, int End);//拆分char陣列獲取指定內容,Start為開始位置End為結束位置(結束位置不保留) std::string Divid_Char(std::string data, int Mode = GET_STATUS_DAT);//拆分單行內容獲取資訊 void Reset_Chain(TANXL_DataBase TDB, int Type, int Exac, int Nums);//重置連結串列某一單元 Nums表示A,B level下的第幾個(從0開始) void Data(bool Mode = true, bool Zero = true);//測試用預設資料 為true時每次新增的同時還會在螢幕上列印 Zero用於選擇新增模式 為True時新增的為0合法的資料 void Combine_File(std::string FileA, std::string FileB);//將FileA和FileB的內容整合到FileA中 僅限USD格式檔案使用SOURCE_FILE#pragma once #include "Tanxl_DataBase.h" TANXL_DataBase TDB_Instance(true); std::string Combine_Char(std::string data, int Start, int End) { if (End < Start) { throw "錯誤 : Combine_Char 的輸入值Start大於End的值"; return ""; } std::string New_data{}; for (int i = Start, j = 0; i < End; i++, j++) { if (data[i] == '\t' || data[i] == '<') { End++; j--; continue; } if (j < 0)j = 0; New_data = New_data + data[i]; } return New_data; } std::string Divid_Char(std::string data, int Mode) { int Lock{ -1 }, Last{ -1 }; char Left, Right; switch (Mode) { case GET_STATUS_DAT://獲取單例資料0~15 Left = '/'; Right = '>'; break; case GET_STORAG_DAT://獲取儲存的資訊 Left = '>'; Right = '<'; break; case GET_STATUS_TAG://資訊條目 Left = '<'; Right = ':'; break; case GET_STATUS_STR://V3連結串列主副鍵String Left = ':'; Right = '/'; break; case GET_OLDSTY_DAT: Left = ':'; Right = '>'; break; default: throw "錯誤 : Divid_Char 沒有此條目的功能(0~3 為合法內容,而你輸入了" + std::to_string(Mode) + ")"; return ""; } for (int i = 0; i < data.length(); i++)//獲取內容 { if ((data[i] == Left && Lock == -1) || (data[i] == Right && Lock != -1)) { if (Lock == -1) { Lock = i + 1; continue; } else Last = i; } if (Lock != -1 && Last != -1) return Combine_Char(data, Lock, Last); } throw "失敗 : Divid_Char 讀取錯誤 不存在滿足條件的內容"; return ""; } void Reset_Chain(TANXL_DataBase TDB, int A, int B, int Nums) { TDB.Set_Specified(A, B, Nums, 3, -1, "NULL"); TDB.Set_Specified(A, B, Nums, 4, -1, "NULL"); TDB.Set_Specified(A, B, Nums, 5, -1, "NULL"); } void Data(bool Mode, bool Zero) { if (!Zero) { for (unsigned Content = 0x111111; Content < 0x111ff6; Content += 11) { TDB_Instance.Set_Instance(Content++, "手槍"); TDB_Instance.Set_Instance(Content++, "地下水"); TDB_Instance.Set_Instance(Content++, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content++, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content++, std::to_string(rand() % 100)); if (Mode)std::cout << TDB_Instance; TDB_Instance.AppendItem(); } } else { for (unsigned Content = 0x11f55; Content < 0x12111; Content++) { TDB_Instance.Set_Instance(0x10000, "手槍"); TDB_Instance.Set_Instance(Content & 0x0f000, "地下水"); TDB_Instance.Set_Instance(Content & 0x00f00, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x000f0, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x0000f, std::to_string(rand() % 100)); if (Mode)std::cout << TDB_Instance; TDB_Instance.AppendItem(); } for (unsigned Content = 0x21f55; Content < 0x22111; Content++) { TDB_Instance.Set_Instance(0x20000, "步槍"); TDB_Instance.Set_Instance(Content & 0x0f000, "M4A1-S"); TDB_Instance.Set_Instance(Content & 0x00f00, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x000f0, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x0000f, std::to_string(rand() % 100)); if (Mode)std::cout << TDB_Instance; TDB_Instance.AppendItem(); } for (unsigned Content = 0x31f55; Content < 0x32111; Content++) { TDB_Instance.Set_Instance(0x30000, "重型武器"); TDB_Instance.Set_Instance(Content & 0x0f000, "Nova"); TDB_Instance.Set_Instance(Content & 0x00f00, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x000f0, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x0000f, std::to_string(rand() % 100)); if (Mode)std::cout << TDB_Instance; TDB_Instance.AppendItem(); } for (unsigned Content = 0x41f55; Content < 0x42111; Content++) { TDB_Instance.Set_Instance(0x40000, "微型衝鋒槍"); TDB_Instance.Set_Instance(Content & 0x0f000, "MP9"); TDB_Instance.Set_Instance(Content & 0x00f00, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x000f0, std::to_string(rand() % 100)); TDB_Instance.Set_Instance(Content & 0x0000f, std::to_string(rand() % 100)); if (Mode)std::cout << TDB_Instance; TDB_Instance.AppendItem(); } } } void Combine_File(std::string FileA, std::string FileB) { std::string Line{}; std::fstream in(FileB + ".usd", std::ios::in); if (!in.is_open()) std::fstream in(FileB + ".sd", std::ios::in); std::fstream out(FileA + ".sd", std::ios::app); if (in.is_open() && out.is_open()) { out << std::endl; while (std::getline(in, Line)) out << Line << std::endl; } else throw "失敗 : Combine_File 無法開啟的指定檔案"; } std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s) { if ((s.Item_Instance.Status_1 + s.Item_Instance.Status_2 + s.Item_Instance.Status_3 + s.Item_Instance.Status_4 + s.Item_Instance.Status_5) || s.Is_Zero_Legal) { s.Get_Item_Status(); fot << "<Type_Status : " << s.Item_Instance.Code << " / " << s.Item_Instance.Status_1 << ">" << std::endl; s.OstreamSpace(fot, 1); fot << "<Exac_Status : " << s.Item_Instance.Name << " / " << s.Item_Instance.Status_2 << ">" << std::endl; s.OstreamSpace(fot, 1, 1); fot << "<TDBS_Item>" << std::endl; if (s.Item_Instance.Status_3 || s.Is_Zero_Legal) { s.OstreamSpace(fot); fot << "<Oth1: " << s.Item_Instance.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl; } if (s.Item_Instance.Status_4 || s.Is_Zero_Legal) { s.OstreamSpace(fot); fot << "<Oth2: " << s.Item_Instance.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl; } if (s.Item_Instance.Status_5 || s.Is_Zero_Legal) { s.OstreamSpace(fot); fot << "<Oth3: " << s.Item_Instance.Status_5 << ">" << s.Item_Instance.Oth3 << "</Oth3>" << std::endl; } s.OstreamSpace(fot, -1); fot << "</TDBS_Item>" << std::endl; s.OstreamSpace(fot, -1); fot << "</Exac_Status>" << std::endl; s.OstreamSpace(fot, -1); fot << "</Type_Status>" << std::endl; } return fot; } inline void TANXL_DataBase::Set_Code(std::string set, unsigned status){ Item_Instance.Code = set; Item_Instance.Status_1 = status; Combine_Status(); } inline void TANXL_DataBase::Set_Name(std::string set, unsigned status){ Item_Instance.Name = set; Item_Instance.Status_2 = status; Combine_Status(); } inline void TANXL_DataBase::Set_Oth1(std::string set, unsigned status){ Item_Instance.Oth1 = set; Item_Instance.Status_3 = status; Combine_Status(); } inline void TANXL_DataBase::Set_Oth2(std::string set, unsigned status){ Item_Instance.Oth2 = set; Item_Instance.Status_4 = status; Combine_Status(); } inline void TANXL_DataBase::Set_Oth3(std::string set, unsigned status){ Item_Instance.Oth3 = set; Item_Instance.Status_5 = status; Combine_Status(); } TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) : Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal), IC_Vector(new std::vector<Id_Vector*>),Current_Location(0) {} inline void TANXL_DataBase::OstreamSpace(std::ostream& os, int Before, int After) { static int TDB_Status = 0;//級別數值 用於記錄當前行的Tab數量 TDB_Status += Before; for (int i = 0; i < TDB_Status; i++)os << "\t"; TDB_Status += After; } inline void TANXL_DataBase::Combine_Status() { Item_Instance.Item_Status = (Item_Instance.Status_1 << 16) + (Item_Instance.Status_2 << 12) + (Item_Instance.Status_3 << 8) + (Item_Instance.Status_4 << 4) + Item_Instance.Status_5; } void TANXL_DataBase::ResetInstance() { Item_Instance.Status_1 = 0x0; Item_Instance.Status_2 = 0x0; Item_Instance.Status_3 = 0x0; Item_Instance.Status_4 = 0x0; Item_Instance.Status_5 = 0x0; Combine_Status(); Is_Instance_Data = false; } void TANXL_DataBase::Set_Instance(unsigned Num, std::string Set) { int SetTimes{ 0 }; if (!Is_Zero_Legal) { if (0 < ((Num & 0xf0000) >> 16) && ((Num & 0xf0000) >> 16) <= 15) { Set_Code(Set, ((Num & 0xf0000) >> 16)); SetTimes++; } if (0 < ((Num & 0x0f000) >> 12) && ((Num & 0x0f000) >> 12) <= 15) { Set_Name(Set, ((Num & 0x0f000) >> 12)); SetTimes++; } if (0 < ((Num & 0x00f00) >> 8) && ((Num & 0x00f00) >> 8) <= 15) { Set_Oth1(Set, ((Num & 0x00f00) >> 8)); SetTimes++; } if (0 < ((Num & 0x000f0) >> 4) && ((Num & 0x000f0) >> 4) <= 15) { Set_Oth2(Set, ((Num & 0x000f0) >> 4)); SetTimes++; } if (0 < (Num & 0x0000f) && (Num & 0x0000f) <= 15) { Set_Oth3(Set, (Num & 0x0000f)); SetTimes++; } } else { if ((Num & 0x00000f) == 1) { Set_Code(Set, ((Num & 0xf00000) >> 20)); SetTimes++; } else if ((Num & 0x00000f) == 2) { Set_Name(Set, ((Num & 0x0f0000) >> 16)); SetTimes++; } else if ((Num & 0x00000f) == 3) { Set_Oth1(Set, ((Num & 0x00f000) >> 12)); SetTimes++; } else if ((Num & 0x00000f) == 4) { Set_Oth2(Set, ((Num & 0x000f00) >> 8)); SetTimes++; } else if ((Num & 0x00000f) == 5) { Set_Oth3(Set, ((Num & 0x0000f0) >> 4)); SetTimes++; } } if (SetTimes) Is_Instance_Data = true; } void TANXL_DataBase::AppendItem(bool To_File, std::string File_Name) { if (!Is_Instance_Data) { throw "新增失敗! 結構內容為空"; return; } else if (To_File) { Is_Instance_Data = true; std::fstream out(File_Name, std::ios::app); if (out.is_open()) { out << *this; this->ResetInstance(); out.close(); } } else { Data_Vector* DTemp = new Data_Vector( Item_Instance.Status_3, Item_Instance.Oth1, Item_Instance.Status_4, Item_Instance.Oth2, Item_Instance.Status_5, Item_Instance.Oth3); Id_Vector* ITemp = new Id_Vector( Item_Instance.Status_1, Item_Instance.Status_2, Item_Instance.Code, Item_Instance.Name); if (DTemp && ITemp)//判斷是否申請空間成功 Append_Chain(*DTemp, *ITemp); else throw "新增失敗! 申請記憶體空間失敗"; } } void TANXL_DataBase::SortDataBase(int Mode, std::string Out_File_Name, std::string In_File_Name) { if (Mode == SORT_LOCALF) if (!Get_LocalData(In_File_Name)) { throw "SortDataBase() Failed ! : 未能成功匹配檔案"; return; } if (Is_Chain_Empty) { throw "SortDataBase() Failed ! : 獲取到的資料為空"; return; } std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc); Id_Vector* PIC{ this->IC_Vector->at(0)}; out << "<Tanxl_DataBase Information>" << std::endl; std::vector<Id_Vector*>::iterator IOIE{ IC_Vector->end()}; std::vector<Id_Vector*>::iterator IOIB{ IC_Vector->begin() }; do { std::vector<Data_Vector*>::iterator IODE{ (*IOIB)->exac->end() }; std::vector<Data_Vector*>::iterator IODB{ (*IOIB)->exac->begin() }; std::cout << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl; std::cout << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl; out << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl; out << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl; do { if ((*IODB)->Id_1 + (*IODB)->Id_2 + (*IODB)->Id_3 == -3) continue; out << "\t\t\t<TDB_Item>" << std::endl; if ((*IODB)->Id_1 || Is_Zero_Legal) out << "\t\t\t\t<Oth1: " << (*IODB)->Id_1 << ">" << (*IODB)->Sd_1 << "</Oth1>" << std::endl; if ((*IODB)->Id_2 || Is_Zero_Legal) out << "\t\t\t\t<Oth2: " << (*IODB)->Id_2 << ">" << (*IODB)->Sd_2 << "</Oth2>" << std::endl; if ((*IODB)->Id_3 || Is_Zero_Legal) out << "\t\t\t\t<Oth3: " << (*IODB)->Id_3 << ">" << (*IODB)->Sd_3 << "</Oth3>" << std::endl; out << "\t\t\t</TDB_Item>" << std::endl; IODB++; } while (IODB != IODE); out << "\t\t</Exac_Status>" << std::endl; out << "\t</Type_Status>" << std::endl; IOIB++; } while (IOIB != IOIE); out << "</Tanxl_DataBase Information>" << std::endl; out.close(); Clear_Chain(); if (Mode == SORT_LOCALF) { std::string s = In_File_Name + ".usd"; remove(s.c_str()); } } void TANXL_DataBase::Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id) { if (Is_Chain_Empty) { IC_Vector->push_back(&New_Id); IC_Vector->at(0)->exac->push_back(&New_Data); Is_Chain_Empty = false; return; } int Left{ 0 }, Value{ New_Id.Type * 16 + New_Id.Exac }, Right{ static_cast<int>(IC_Vector->size()) - 1 <= 0 ? 0 : static_cast<int>(IC_Vector->size()) - 1 }; while (true) { int Mid{ (Left + Right) / 2 }; Id_Vector* PIC = IC_Vector->at(Mid); int PIC_Value{ PIC->Type * 16 + PIC->Exac }; if (PIC_Value == Value)//Type B匹配時 { PIC->exac->push_back(&New_Data); Is_Chain_Empty = false; return; } else if (Left == Right && PIC_Value != Value)//Type B不匹配 但已經是最接近的值時 { if (PIC_Value < Value) Left += 1; this->IC_Vector->insert(IC_Vector->begin() + Left, &New_Id); IC_Vector->at(Left)->exac->push_back(&New_Data); Is_Chain_Empty = false; return; } else if (PIC_Value < Value) Left = Mid; else if (PIC_Value > Value) Right = Mid; if (Left + 1 == Right) { if (PIC_Value < Value) Left = Right; else Right = Left; } } throw "Append() Failed ! : 未知原因"; return; } bool TANXL_DataBase::Get_LocalData(std::string File_Name) { std::fstream in(File_Name + ".usd", std::ios::in); if (!in.is_open()) std::fstream in(File_Name + ".sd", std::ios::in); if (in.is_open()) { std::string Type_Data{}, Exac_Data{};//需要使用時再定義 int Type_Stat{}, Exac_Stat{}; int IData[3]{ 0 }, Target{ -1 }; std::string SData[3]{}; std::string Line{}; while (std::getline(in, Line)) { std::string Tag{ Combine_Char(Line, 1, 5) }; if (Tag == "Type") { Type_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT)); Type_Data = Divid_Char(Line, GET_STATUS_STR); std::getline(in, Line); Exac_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT)); Exac_Data = Divid_Char(Line, GET_STATUS_STR); while (std::getline(in, Line)) { Tag = Combine_Char(Line, 1, 5); if (Tag == "Type") { Type_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT)); Type_Data = Divid_Char(Line, GET_STATUS_STR); } else if (Tag == "Exac") { Exac_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT)); Exac_Data = Divid_Char(Line, GET_STATUS_STR); } else if (Tag == "/TDB") { Data_Vector* Data_Temp = new Data_Vector(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2]); Id_Vector* Id_Temp = new Id_Vector(Type_Stat, Exac_Stat, Type_Data, Exac_Data); IData[0] = 0; IData[1] = 0; IData[2] = 0; SData[0] = ""; SData[1] = ""; SData[2] = ""; if (Data_Temp && Id_Temp) Append_Chain(*Data_Temp, *Id_Temp); else throw "新增失敗! 申請記憶體空間失敗"; continue; } else if (Tag == "Oth1") Target = 0; else if (Tag == "Oth2") Target = 1; else if (Tag == "Oth3") Target = 2; if (Target == -1) continue; IData[Target] = std::stoi(Divid_Char(Line, GET_OLDSTY_DAT)); SData[Target] = Divid_Char(Line, GET_STORAG_DAT); Target = -1; } } } in.close(); return true; } else return false; } void TANXL_DataBase::Clear_Chain() { for (int i = 0; i < IC_Vector->size(); i++) Remove_Chain(IC_Vector->at(i)->Type, IC_Vector->at(i)->Exac); Is_Chain_Empty = true; } void TANXL_DataBase::Get_Specified(int Type, int Exac, int Nums) { if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) }) { Id_Vector* PIC = { Id_Chain_Locate(Type, Exac) }; Item_Instance.Status_1 = PIC->Type; Item_Instance.Code = PIC->StrA; Item_Instance.Status_2 = PIC->Exac; Item_Instance.Name = PIC->StrB; Item_Instance.Status_3 = PDC->Id_1; Item_Instance.Oth1 = PDC->Sd_1; Item_Instance.Status_4 = PDC->Id_2; Item_Instance.Oth2 = PDC->Sd_2; Item_Instance.Status_5 = PDC->Id_3; Item_Instance.Oth3 = PDC->Sd_3; Combine_Status(); return; } throw "Get_Specified() Failed ! : 未能成功匹配相同值"; } void TANXL_DataBase::Get_Item_Status() { Item_Instance.Status_1 = ((Item_Instance.Item_Status & 0xf0000) >> 16); Item_Instance.Status_2 = ((Item_Instance.Item_Status & 0x0f000) >> 12); Item_Instance.Status_3 = ((Item_Instance.Item_Status & 0x00f00) >> 8 ); Item_Instance.Status_4 = ((Item_Instance.Item_Status & 0x000f0) >> 4 ); Item_Instance.Status_5 = ( Item_Instance.Item_Status & 0x0000f ); } void TANXL_DataBase::Print_Data()//輸出當前連結串列中的所有內容 V3 Updated { if (!Is_Chain_Empty) { Id_Vector* PIC{}; Data_Vector* PDC{}; int PIC_Count{ 0 }; std::vector<Id_Vector*>::iterator IOI = IC_Vector->end() - 1; do { int PDC_Count{ 0 }; PIC = this->IC_Vector->at(PIC_Count++); std::vector<Data_Vector*>::iterator IOD = PIC->exac->end() - 1; std::cout << "Id_Vector :" << PIC->Type << " - " << PIC->StrA << " - " << PIC->Exac << " - " << PIC->StrB << std::endl; do { PDC = PIC->exac->at(PDC_Count++); std::cout << "\tData_Vector :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << std::endl; } while (PDC != *IOD); } while (PIC != *IOI); return; } throw "Print_Data() Failed ! : 連結串列內容為空"; } void TANXL_DataBase::Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data) //V3 Updated { if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) }) switch (level) { case SET_TYPE_STATUS: Replace_Chain(Type, Exac, Nums, Id, Exac); return; case SET_EXAC_STATUS: Replace_Chain(Type, Exac, Nums, Type, Id); return; case SET_OTH1_STATUS: PDC->Id_1 = Id; PDC->Sd_1 = Data; return; case SET_OTH2_STATUS: PDC->Id_2 = Id; PDC->Sd_2 = Data; return; case SET_OTH3_STATUS: PDC->Id_3 = Id; PDC->Sd_3 = Data; return; } throw "Set_Specified() Failed ! : 查詢相關內容不成功或連結串列內容為空"; } void TANXL_DataBase::Remove_Chain(int Type, int Exac) { if (Id_Vector * PIC{ Id_Chain_Locate(Type, Exac) }) { for (int i{ 0 }; i < PIC->exac->size(); i++) delete PIC->exac->at(i);//釋放 Data_Vector PIC->exac->clear(); delete PIC;//釋放 Id_Vector IC_Vector->erase(IC_Vector->begin() + Current_Location); } } Id_Vector* TANXL_DataBase::Id_Chain_Locate(int Type, int Exac) { int Left{ 0 },Value{ Type * 16 + Exac }, Right{ static_cast<int>(IC_Vector->size()) - 1 >= 0 ? static_cast<int>(IC_Vector->size()) - 1 : 0 };; if (Left == Right) { if (Value == IC_Vector->at(0)->Type * 16 + IC_Vector->at(0)->Exac) { Current_Location = 0; return IC_Vector->at(0); } throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值"; return NULL; } else { while (Left != Right) { int Mid{ (Left + Right) / 2 }; int Mid_Value{ IC_Vector->at(Mid)->Type * 16 + IC_Vector->at(Mid)->Exac }; if (Mid_Value == Value) { Current_Location = Mid; return IC_Vector->at(Mid); } else if (Mid_Value > Value) Right = Mid; else if (Mid_Value < Value) Left = Mid; if (Left == Right) { throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值"; return NULL; } } } throw "Id_Chain_Locate Failed ! : 未知原因"; return NULL; } Data_Vector* TANXL_DataBase::Data_Chain_Locate(int Type, int Exac, int Depth) { Id_Vector* PIC{ Id_Chain_Locate(Type, Exac) }; if (PIC->exac->size() < Depth) { throw "Data_Chain_Locate Failed ! : 超出當前容器最大深度"; return NULL; } else if (Depth < 0 && Depth + static_cast<int>(PIC->exac->size()) >= 0) return PIC->exac->at(Depth + PIC->exac->size()); while (Depth + static_cast<int>(PIC->exac->size() < 0)) Depth += static_cast<int>(PIC->exac->size()); return PIC->exac->at(Depth); } void TANXL_DataBase::Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac) { Id_Vector* PIC{ Id_Chain_Locate(OldType, OldExac) }; Append_Chain(*PIC->exac->at(OldDepth), *new Id_Vector(Type, Exac)); if (PIC->exac->size() > OldDepth && OldDepth >= 0) PIC->exac->erase(PIC->exac->begin() + OldDepth); else if (PIC->exac->size() + OldDepth >= 0 && PIC->exac->size() + OldDepth < PIC->exac->size()) PIC->exac->erase(PIC->exac->begin() + PIC->exac->size() + OldDepth); }

SOURCE CODE FROM TEnGinE Version-0.1 Build-32 2022-08-18 22:13 TANXL

隨便看看 更多