TANXL_DATABASE VERSION_1_6
独立游戏存档模块由之前的CSDN文章中的 C++使用文件IO实现一个简易的存取模块 微调改进而来,在内存方面降低了单个储存单元的大小,使用指针来获取内容。同时加入了内存申请是否成功的判断,其他详细内容均在程序注释中进行了标明。(此项目仍然会持续进行改进)
TANXL_DATABASE.H VERSION_1_6
//_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格式文件使用
2022/03/03 00:23 WILD_CHICKEN_PROGRAMING VERSION_1_6
#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);
}
使用范例
TANXL_DataBase NData;
int n = 0x11111, i = 5;
while (i--)
{
std::cout << "Updating : " << n << std::endl;
NData.Set_Instance(n++, "Updating" + std::to_string(n));
std::cout << NData;
NData.AppendItem(false);
}
NData.Print_Data();
此示例会生成一组数据并在控制台中输出,更多详情请参见接口介绍。