C++使用文件IO实现一个简易的存取模块

TANXL_DATABASE VERSION_1_1

此存取功能通过两个链表结构和一个类来实现,目前还有很大的改进空间(未来将主要用于独立游戏的存档/读取功能)。具体每个函数的功能都在注释中做出了解释。进行一次初始化后(调用默认数据函数Data()),会在本地生成一个.USD格式的文件(Unsorted data)通过调用SortDataBase函数即可对数据进行整理并生成一个.SD格式的文件(Sorted data)无论是.SD还是.USD格式的文件都可以通过Get_LocalData函数获取,所有数据在文件中都是原样储存的,可以通过记事本打开进行查看,以下为生成的文件截图。
在这里插入图片描述

TANXL_DATABASE.H VERSION_1_1

#ifndef IOSTREAM
#define IOSTREAM
#include<iostream>
#endif

#ifndef FSTREAM
#define FSTREAM
#include<fstream>
#endif

#ifndef SSTREAM
#define SSTREAM
#include<sstream>
#endif

struct Data_Chain//数据链表
{
	explicit Data_Chain(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, std::string D_C = NULL, int I_D = NULL, std::string D_D = NULL, int I_E = NULL, std::string D_E = NULL) :
		Id_1(I_A), Id_2(I_B), Id_3(I_C), Id_4(I_D), Id_5(I_E), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C), Sd_4(D_D), Sd_5(D_E), exac(NULL) {}
	int Id_1, Id_2, Id_3, Id_4, Id_5;
	std::string Sd_1, Sd_2, Sd_3, Sd_4, Sd_5;
	Data_Chain* exac;
};

struct Id_Chain//类型链表
{
	explicit Id_Chain(int A, int B, Id_Chain* N = NULL, Data_Chain* E = NULL) :LevelA(A), LevelB(B), next(N), exac(E) {}
	Id_Chain* next;//next指向Type类型的下一个对象
	Data_Chain* exac;//exac指向该Type类型下的下一个Exac对象
	int LevelA, LevelB;
};

class TANXL_DataBase
{
private:
	struct
	{
		unsigned Item_Status{ 0 };
		std::string Code;
		std::string Name;
		std::string Oth1;
		std::string Oth2;
		std::string Oth3;
	}Item_Instance;

	Id_Chain* IC_head;
	int TDB_Status;
	bool Is_Instance_Data;
	bool Is_Chain_Empty;
	unsigned Status_1, Status_2, Status_3, Status_4, Status_5;
	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);
	void* operator new(size_t Size, const TANXL_DataBase&);//禁止单例的new行为
	void Append_Chain(Data_Chain& New_Data, int A, int B);//链表添加内容
	void Get_Item_Status();//获取物品数值 并加载到结构中
	void Clear_Chain();//清理链表
	void ResetInstance();//重置Item结构的内容
	inline void UpdateStat(int Num);//更新级别数值 级别数值用于记录当前行的\t数量
	inline void OstreamSpace(std::ostream& os);//根据级别输出空格
	inline void Combine_Status();
public:
	TANXL_DataBase();
	bool Get_LocalData(std::string File_Name, bool Is_UnSort = false);//获取本地数据 并新建一个链表 Is_Unsort用于区分打开的是否为处理后的文件 即后缀.usd和.sd
	void Set_Instance(unsigned Num, std::string Set);//编辑实例 0x12345 1代表Code位 2代表Name位 3代表Oth1位 依此类推
	void Get_Specified(int levelA, int levelB, int Nums);//读取指定Type(A)_Exac(B)级别的物品 并载入到单例结构中 Nums表示链表中的第几个(从0开始)
	void Set_Specified(int levelA, int levelB, int Nums, int level, int Id, std::string Data);//修改指定Type(A)_Exac(B)级别的物品 Nums表示链表中的第几个(从0开始) level取值范围为1~5 用于选定Name Code Oth1 ...
	void Remove_Chain(int levelA, int levelB);//删除某一节点与其下所有内容
	void Print_Data();//输出当前链表中的所有内容
	void AppendItem(bool To_File = true);//向本地文件中(.usd)添加Item物品 此函数会导致Item单例重置
	void Combine_File(std::string FileA, std::string FileB);//将FileA和FileB的内容整合到FileA中 仅限USD格式文件使用
	void SortDataBase(bool Mode = true, std::string Out_File_Name = "Tanxl_Data", std::string In_File_Name = "Tanxl_DataBase");//使本地(.usd)文件的内容合理化 Out_File_Name为输出文件名 现在具有保存链表修改功能
	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 = 0);//拆分单行内容获取信息

void Reset_Chain(int levelA, int levelB, int Nums);//重置链表某一单元 Nums表示A,B level下的第几个(从0开始)

void Data(bool Mode = true);//测试用默认数据 为true时每次添加的同时还会在屏幕上打印

2022/03/03 00:23 WILD_CHICKEN_PROGRAMING VERSION_1_1

#include "Tanxl_DataBase.h"

TANXL_DataBase TDB_Instance;

std::string Combine_Char(std::string data, int Start, int End)
{
	if (End < Start)
		return "error";
	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 };
	for (int i = 0; i < data.length(); i++)
	{
		if (Lock != -1 && Last != -1)
			return Combine_Char(data, Lock, Last);
		if ((data[i] == ':' || data[i] == '>') && Mode == 0)//获取单例数据0~15
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
		else if (((data[i] == '>' && Lock == -1) || (data[i] == '<' && Lock != -1)) && Mode == 1)//获取储存的信息
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
		else if (((data[i] == '<' && Lock == -1) || (data[i] == ':' && Lock != -1)) && Mode == 2)//信息条目
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
	}
	if (Lock != -1 && Last != -1)
		return Combine_Char(data, Lock, Last);
	return "error";
}

void Reset_Chain(int A, int B, int Nums)
{
	TDB_Instance.Set_Specified(A, B, Nums, 3, 0, "NULL");
	TDB_Instance.Set_Specified(A, B, Nums, 4, 0, "NULL");
	TDB_Instance.Set_Specified(A, B, Nums, 5, 0, "NULL");
}

char* Combine_Char(char data[], int Start, int End)
{
	return nullptr;
}

void Data(bool Mode)
{
	for (unsigned Content = 0x11f55; Content < 0x12000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x21f55; Content < 0x22000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x31f55; Content < 0x32000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x41f55; Content < 0x42000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
}

std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s)
{
	if (s.Status_1 + s.Status_2 + s.Status_3 + s.Status_4 + s.Status_5)
	{
		s.Get_Item_Status();
		fot << "<Type_Status :" << s.Status_1 << ">" << std::endl; s.UpdateStat(1);
		s.OstreamSpace(fot); fot << "<Exac_Status :" << s.Status_2 << ">" << std::endl; s.UpdateStat(1);
		s.OstreamSpace(fot); fot << "<TDBS_Item>" << std::endl; s.UpdateStat(1);
		if (s.Status_1) {
			s.OstreamSpace(fot);
			fot << "<Code: " << s.Status_1 << ">" << s.Item_Instance.Code << "</Code>" << std::endl;
		}
		if (s.Status_2) {
			s.OstreamSpace(fot);
			fot << "<Name: " << s.Status_2 << ">" << s.Item_Instance.Name << "</Name>" << std::endl;
		}
		if (s.Status_3) {
			s.OstreamSpace(fot);
			fot << "<Oth1: " << s.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl;
		}
		if (s.Status_4) {
			s.OstreamSpace(fot);
			fot << "<Oth2: " << s.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl;
		}
		if (s.Status_5) {
			s.OstreamSpace(fot);
			fot << "<Oth3: " << s.Status_5 << ">" << s.Item_Instance.Oth3 << "</Oth3>" << std::endl;
		}
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</TDBS_Item>" << std::endl;
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</Exac_Status>" << std::endl;
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</Type_Status>" << std::endl;
	}
	return fot;
}

inline void TANXL_DataBase::Set_Code(std::string set, unsigned status){ Item_Instance.Code = set; Status_1 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Name(std::string set, unsigned status){ Item_Instance.Name = set; Status_2 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth1(std::string set, unsigned status){ Item_Instance.Oth1 = set; Status_3 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth2(std::string set, unsigned status){ Item_Instance.Oth2 = set; Status_4 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth3(std::string set, unsigned status){ Item_Instance.Oth3 = set; Status_5 = status; Combine_Status(); }

TANXL_DataBase::TANXL_DataBase() :TDB_Status(0), Is_Instance_Data(false), Is_Chain_Empty(true), IC_head(new Id_Chain(0, 0)), Status_1(0), Status_2(0), Status_3(0), Status_4(0), Status_5(0) {}

inline void TANXL_DataBase::UpdateStat(int Num)
{
	TDB_Status += Num;
}

inline void TANXL_DataBase::OstreamSpace(std::ostream& os)
{
	for (int i = 0; i < TDB_Status; i++)os << "\t";
}

inline void TANXL_DataBase::Combine_Status()
{
	Item_Instance.Item_Status = (Status_1 << 16) + (Status_2 << 12) + (Status_3 << 8) + (Status_4 << 4) + Status_5;
}

void* TANXL_DataBase::operator new(size_t Size, const TANXL_DataBase&)
{
	return 0;
}

void TANXL_DataBase::ResetInstance()
{
	Status_1 = 0x0, Status_2 = 0x0, Status_3 = 0x0, Status_4 = 0x0, Status_5 = 0x0;
	Combine_Status();
	Is_Instance_Data = false;
}

void TANXL_DataBase::Set_Instance(unsigned Num, std::string Set)
{
	int SetTimes{ 0 };
	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++;
	}
	if (SetTimes)
		Is_Instance_Data = true;
}

void TANXL_DataBase::AppendItem(bool To_File)
{
	if (!Is_Instance_Data)
	{ 
		std::cout << "添加失败! 结构内容为空" << std::endl;
		return;
	}
	else if (To_File)
	{
		Is_Instance_Data = true;
		std::fstream out("Tanxl_DataBase.usd", std::ios::app);
		if (out.is_open())
		{
			out << *this;
			this->ResetInstance();
			out.close();
		}
	}
	else
	{
		Data_Chain* Temp = new Data_Chain(
			Status_1, Item_Instance.Code,
			Status_2, Item_Instance.Name,
			Status_3, Item_Instance.Oth1,
			Status_4, Item_Instance.Oth2,
			Status_5, Item_Instance.Oth3);
		Append_Chain(*Temp, Status_1, Status_2);
	}
}

void TANXL_DataBase::SortDataBase(bool Mode, std::string Out_File_Name, std::string In_File_Name)
{
	if (Mode)
		if (!Get_LocalData(In_File_Name, true))
		{
			std::cout << "Sort_DataBase Failed - There is no such file" << std::endl;
			return;
		}
	std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	Id_Chain* before_PIC = new Id_Chain(0, 0);
	out << "<Tanxl_DataBase Information>" << std::endl;
	while (PIC != NULL)
	{
		std::cout << "PIC->LevelA :" << PIC->LevelA << "-- before_PIC->LevelA :" << before_PIC->LevelA;
		std::cout << "---PIC->LevelB :" << PIC->LevelB << "-- before_PIC->LevelB :" << before_PIC->LevelB << std::endl;
		if (PIC->LevelA != before_PIC->LevelA)
			out << "\t<Type_Status: " << PIC->LevelA << ">" << std::endl;
		if (PIC->LevelA != before_PIC->LevelA || (PIC->LevelA == before_PIC->LevelA && PIC->LevelB != before_PIC->LevelB))
			out << "\t\t<Exac_Status: " << PIC->LevelB << ">" << std::endl;
		out << "\t\t\t<TDBS_Item>" << std::endl;
		if (PDC->Id_1)
			out << "\t\t\t\t<Code: " << PDC->Id_1 << ">" << PDC->Sd_1 << "</Code>" << std::endl;
		if (PDC->Id_2)
			out << "\t\t\t\t<Name: " << PDC->Id_2 << ">" << PDC->Sd_2 << "</Name>" << std::endl;
		if (PDC->Id_3)
			out << "\t\t\t\t<Oth1: " << PDC->Id_3 << ">" << PDC->Sd_3 << "</Oth1>" << std::endl;
		if (PDC->Id_4)
			out << "\t\t\t\t<Oth2: " << PDC->Id_4 << ">" << PDC->Sd_4 << "</Oth2>" << std::endl;
		if (PDC->Id_5)
			out << "\t\t\t\t<Oth3: " << PDC->Id_5 << ">" << PDC->Sd_5 << "</Oth3>" << std::endl;
		out << "\t\t\t</TDBS_Item>" << std::endl;
		if (PDC->exac == NULL)
		{
			out << "\t\t</Exac_Status>" << std::endl;
			if (PIC->next == NULL)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
			}
			else if (PIC->next->LevelA != PIC->LevelA)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
			else
			{
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
		}
		else
		{
			before_PIC = PIC;
			PDC = PDC->exac;
		}
	}
	out << "</Tanxl_DataBase Information>" << std::endl;
	out.close();
	if (Mode)
	{
		Clear_Chain();
		std::string s = In_File_Name + ".usd";
		remove(s.c_str());
	}
}

void TANXL_DataBase::Append_Chain(Data_Chain& New_Data, int A, int B)
{
	Is_Chain_Empty = false;
	Id_Chain* PIC = IC_head;
	Id_Chain* before_PIC = NULL;
	if (PIC->LevelA == 0 && PIC->LevelB == 0)//链表为空修改类型链表表头
	{
		PIC->LevelA = A;
		PIC->LevelB = B;
		PIC->exac = &New_Data;
		return;
	}
	else
	{
		bool Flag{ false };
		Id_Chain* Chain_Temp = new Id_Chain(A, B);
		while (PIC != NULL)
		{
			if (A == PIC->LevelA && B == PIC->LevelB)
			{
				Chain_Temp = PIC;
				Flag = true;
			}
			else if (A < PIC->LevelA || (A == PIC->LevelA && B < PIC->LevelB))//链表不为空对插入的类型链表排序
			{
				if (before_PIC == NULL)
				{
					Chain_Temp->next = IC_head;
					IC_head = Chain_Temp;
					Flag = true;
				}
				else if (before_PIC != NULL)
				{
					Chain_Temp->next = PIC;
					before_PIC->next = Chain_Temp;
					Flag = true;
				}
			}
			if (Flag == true)
			{
				New_Data.exac = Chain_Temp->exac;
				Chain_Temp->exac = &New_Data;
				return;
			}
			before_PIC = PIC;
			PIC = PIC->next;
		}
		if (PIC == NULL && before_PIC != NULL && Flag == false)
		{
			before_PIC->next = Chain_Temp;
			New_Data.exac = Chain_Temp->exac;
			Chain_Temp->exac = &New_Data;
			return;
		}
	}
	std::cout << "Append False : Due to Unknown Reason !" << std::endl; system("pause");
	return;
}

bool TANXL_DataBase::Get_LocalData(std::string File_Name, bool Is_UnSort)
{
	int Exac_Data{}, Length_Line{ 50 }, IData[5]{ 0 }, Target{ -1 };
	std::string SData[5]{}, S_Line{};
	char Line[50]{};
	if (Is_UnSort)
		File_Name += ".usd";
	else
		File_Name += ".sd";
	std::fstream in(File_Name, std::ios::in);
	if (in.is_open())
	{
		while (in.getline(Line, Length_Line))
		{
			S_Line = static_cast<std::string>(Line);
			if (Combine_Char(S_Line, 1, 5) == "Type")//获取一个完整数据,并生成Data_Chain传入添加函数
			{
				std::string s = Divid_Char(S_Line, 0);
				int Type_Data{ std::stoi(Divid_Char(S_Line, 0)) };
				while (in.getline(Line, Length_Line) && (Combine_Char(S_Line, 1, 5) != "/Exa"))
				{
					S_Line = static_cast<std::string>(Line);
					std::string Label{ Combine_Char(S_Line, 1, 5) };
					if (Label == "/TDB")
					{
						Data_Chain* Data_Temp = new Data_Chain(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2], IData[3], SData[3], IData[4], SData[4]);
						Append_Chain(*Data_Temp, Type_Data, Exac_Data);
						continue;
					}
					if (Label == "Exac")
						Exac_Data = std::stoi(Divid_Char(S_Line, 0));
					else
					{
						if (Label == "Code")
							Target = 0;
						else if (Label == "Name")
							Target = 1;
						else if (Label == "Oth1")
							Target = 2;
						else if (Label == "Oth2")
							Target = 3;
						else if (Label == "Oth3")
							Target = 4;
						if (Target == -1)
							continue;
						IData[Target] = std::stoi(Divid_Char(S_Line, 0));
						SData[Target] = Divid_Char(S_Line, 1);
						Target = -1;
					}
				}
			}
		}
		in.close();
		return true;
	}
	else
		return false;
}

void TANXL_DataBase::Clear_Chain()
{
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	while (PIC != NULL)
	{
		if (PDC != NULL)
		{
			PIC->exac = PDC->exac;
			delete PDC;
			PDC = PIC->exac;
		}
		else
		{
			Id_Chain* before_PIC = PIC;
			PIC = PIC->next;
			delete before_PIC;
		}
	}
	Is_Chain_Empty = true;
	TANXL_DataBase::IC_head = new Id_Chain(0, 0);
}

void TANXL_DataBase::Get_Specified(int A, int B, int Nums)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				Status_1 = PDC->Id_1;  Item_Instance.Code = PDC->Sd_1;
				Status_2 = PDC->Id_2;  Item_Instance.Name = PDC->Sd_2;
				Status_3 = PDC->Id_3;  Item_Instance.Oth1 = PDC->Sd_3;
				Status_4 = PDC->Id_4;  Item_Instance.Oth2 = PDC->Sd_4;
				Status_5 = PDC->Id_5;  Item_Instance.Oth3 = PDC->Sd_5;
				Combine_Status();
				return;
			}
			PIC = PIC->next;
		}
		std::cout << "获取失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "获取失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Get_Item_Status()
{
	Status_1 = ((Item_Instance.Item_Status & 0xf0000) >> 16);
	Status_2 = ((Item_Instance.Item_Status & 0x0f000) >> 12);
	Status_3 = ((Item_Instance.Item_Status & 0x00f00) >> 8);
	Status_4 = ((Item_Instance.Item_Status & 0x000f0) >> 4);
	Status_5 = (Item_Instance.Item_Status & 0x0000f);
}

void TANXL_DataBase::Combine_File(std::string FileA, std::string FileB)
{
	int Length_Line{ 50 };
	char Line[50]{};
	std::fstream in(FileB + ".usd", std::ios::in);
	std::fstream out(FileA + ".usd", std::ios::app);
	if (in.is_open() && out.is_open())
	{
		out << std::endl;
		while (in.getline(Line, Length_Line))
			out << Line << std::endl;
	}
	else
		std::cout << "Faild : Can not open this file !" << std::endl;
}

void TANXL_DataBase::Print_Data()
{
	Id_Chain* PIC = IC_head;
	while (PIC != NULL)
	{
		std::cout << "Id_Chain :" << PIC->LevelA << "-" << PIC->LevelB << std::endl;
		Data_Chain* PDC = PIC->exac;
		while (PDC != NULL)
		{
			std::cout << "\tData_Chain :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << "-" << PDC->Id_4 << "-" << PDC->Id_5 << std::endl;
			PDC = PDC->exac;
		}
		PIC = PIC->next;
	}
}

void TANXL_DataBase::Set_Specified(int A, int B, int Nums, int level, int Id, std::string Data)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				switch (level)
				{
				case 1://禁止修改Type级别
					PDC->Sd_1 = Data;
					return;
				case 2://禁止修改Exac级别
					PDC->Sd_2 = Data;
					return;
				case 3:
					PDC->Id_3 = Id;
					PDC->Sd_3 = Data;
					return;
				case 4:
					PDC->Id_4 = Id;
					PDC->Sd_4 = Data;
					return;
				case 5:
					PDC->Id_5 = Id;
					PDC->Sd_5 = Data;
					return;
				}
			}
			PIC = PIC->next;
		}
		std::cout << "修改失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "修改失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Remove_Chain(int A, int B)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* before_PIC = NULL;
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				if (PIC == IC_head)
					IC_head = PIC->next;
				else
					before_PIC->next = PIC->next;
				Data_Chain* PDC = PIC->exac;
				while (PDC != NULL)
				{
					PIC->exac = PDC->exac;
					delete PDC;
					PDC = PIC->exac;
				}
				delete PIC;
				return;
			}
			before_PIC = PIC;
			PIC = PIC->next;
		}
		std::cout << "删除失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "删除失败! 链表内容为空" << std::endl;
}

TANXL_DATABASE VERSION_1_2

//_VERSION_1_2_ UPDATE LOG
// Combine_File函数从类中移除改为公用函数
// 考虑到数据连续储存新增Status为0合法的可选功能
// 修复因Get_LocalData函数导致的整理出额外内容的问题
// 修改Reset_Chain函数 将重置的物品数值置为-1
// SortDataBase函数现在可用于清理被重置的物品

TANXL_DATABASE.H VERSION_1_2

#ifndef IOSTREAM
#define IOSTREAM
#include<iostream>
#endif

#ifndef FSTREAM
#define FSTREAM
#include<fstream>
#endif

#ifndef SSTREAM
#define SSTREAM
#include<sstream>
#endif

struct Data_Chain//数据链表
{
	explicit Data_Chain(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, std::string D_C = NULL, int I_D = NULL, std::string D_D = NULL, int I_E = NULL, std::string D_E = NULL) :
		Id_1(I_A), Id_2(I_B), Id_3(I_C), Id_4(I_D), Id_5(I_E), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C), Sd_4(D_D), Sd_5(D_E), exac(NULL) {}
	int Id_1, Id_2, Id_3, Id_4, Id_5;
	std::string Sd_1, Sd_2, Sd_3, Sd_4, Sd_5;
	Data_Chain* exac;
};

struct Id_Chain//类型链表
{
	explicit Id_Chain(int A, int B, Id_Chain* N = NULL, Data_Chain* E = NULL) :LevelA(A), LevelB(B), next(N), exac(E) {}
	Id_Chain* next;//next指向Type类型的下一个对象
	Data_Chain* exac;//exac指向该Type类型下的下一个Exac对象
	int LevelA, LevelB;
};

class TANXL_DataBase
{
private:
	struct
	{
		unsigned Item_Status{ 0 };
		std::string Code;
		std::string Name;
		std::string Oth1;
		std::string Oth2;
		std::string Oth3;
	}Item_Instance;

	Id_Chain* IC_head;
	int TDB_Status;
	bool Is_Instance_Data;
	bool Is_Chain_Empty;
	bool Is_Zero_Legal;//值为true时0成为合法值 可在输出中显示/使用
	unsigned Status_1, Status_2, Status_3, Status_4, Status_5;
	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);
	void* operator new(size_t Size, const TANXL_DataBase&);//禁止单例的new行为
	void Append_Chain(Data_Chain& New_Data, int A, int B);//链表添加内容
	void Get_Item_Status();//获取物品数值 并加载到结构中
	void Clear_Chain();//清理链表
	void ResetInstance();//重置Item结构的内容
	inline void UpdateStat(int Num);//更新级别数值 级别数值用于记录当前行的\t数量
	inline void OstreamSpace(std::ostream& os);//根据级别输出空格
	inline void Combine_Status();//组合Status各物品级别并合并到Item_Instance中
public:
	TANXL_DataBase(bool Zero_Legal = false);
	bool Get_LocalData(std::string File_Name, bool Is_UnSort = false);//获取本地数据 并新建一个链表 Is_Unsort用于区分打开的是否为处理后的文件 即后缀.usd和.sd
	void Set_Instance(unsigned Num, std::string Set);//编辑实例 0x12345 1代表Code位 2代表Name位 3代表Oth1位 依此类推
	void Get_Specified(int levelA, int levelB, int Nums);//读取指定Type(A)_Exac(B)级别的物品 并载入到单例结构中 Nums表示链表中的第几个(从0开始)
	void Set_Specified(int levelA, int levelB, int Nums, int level, int Id, std::string Data);//修改指定Type(A)_Exac(B)级别的物品 Nums表示链表中的第几个(从0开始) level取值范围为1~5 用于选定Name Code Oth1 ...
	void Remove_Chain(int levelA, int levelB);//删除某一节点与其下所有内容
	void Print_Data();//输出当前链表中的所有内容
	void AppendItem(bool To_File = true);//向本地文件中(.usd)添加Item物品 此函数会导致Item单例重置
	void SortDataBase(bool Mode = true, std::string Out_File_Name = "Tanxl_Data", std::string In_File_Name = "Tanxl_DataBase");//使本地(.usd)文件的内容合理化 Out_File_Name为输出文件名 现在具有保存链表修改功能
	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 = 0);//拆分单行内容获取信息

void Reset_Chain(TANXL_DataBase TDB, int levelA, int levelB, int Nums);//重置链表某一单元 Nums表示A,B level下的第几个(从0开始)

void Data(bool Mode = true);//测试用默认数据 为true时每次添加的同时还会在屏幕上打印

void Combine_File(std::string FileA, std::string FileB);//将FileA和FileB的内容整合到FileA中 仅限USD格式文件使用

2022/03/07 16:26 WILD_CHICKEN_PROGRAMING VERSION_1_2

#include "Tanxl_DataBase.h"

TANXL_DataBase TDB_Instance;

std::string Combine_Char(std::string data, int Start, int End)
{
	if (End < Start)
		return "error";
	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 };
	for (int i = 0; i < data.length(); i++)
	{
		if (Lock != -1 && Last != -1)
			return Combine_Char(data, Lock, Last);
		if ((data[i] == ':' || data[i] == '>') && Mode == 0)//获取单例数据0~15
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
		else if (((data[i] == '>' && Lock == -1) || (data[i] == '<' && Lock != -1)) && Mode == 1)//获取储存的信息
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
		else if (((data[i] == '<' && Lock == -1) || (data[i] == ':' && Lock != -1)) && Mode == 2)//信息条目
		{
			if (Lock == -1)
			{
				Lock = i + 1;
				continue;
			}
			else
				Last = i;
		}
	}
	if (Lock != -1 && Last != -1)
		return Combine_Char(data, Lock, Last);
	return "error";
}

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)
{
	for (unsigned Content = 0x11f55; Content < 0x12000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x21f55; Content < 0x22000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x31f55; Content < 0x32000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
	for (unsigned Content = 0x41f55; Content < 0x42000; 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;
		//system("pause");
		TDB_Instance.AppendItem();
	}
}

void Combine_File(std::string FileA, std::string FileB)
{
	int Length_Line{ 50 };
	char Line[50]{};
	std::fstream in(FileB + ".usd", std::ios::in);
	std::fstream out(FileA + ".usd", std::ios::app);
	if (in.is_open() && out.is_open())
	{
		out << std::endl;
		while (in.getline(Line, Length_Line))
			out << Line << std::endl;
	}
	else
		std::cout << "Faild : Can not open this file !" << std::endl;
}

std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s)
{
	if ((s.Status_1 + s.Status_2 + s.Status_3 + s.Status_4 + s.Status_5) || s.Is_Zero_Legal)
	{
		s.Get_Item_Status();
		fot << "<Type_Status :" << s.Status_1 << ">" << std::endl; s.UpdateStat(1);
		s.OstreamSpace(fot); fot << "<Exac_Status :" << s.Status_2 << ">" << std::endl; s.UpdateStat(1);
		s.OstreamSpace(fot); fot << "<TDBS_Item>" << std::endl; s.UpdateStat(1);
		if (s.Status_1 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Code: " << s.Status_1 << ">" << s.Item_Instance.Code << "</Code>" << std::endl;
		}
		if (s.Status_2 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Name: " << s.Status_2 << ">" << s.Item_Instance.Name << "</Name>" << std::endl;
		}
		if (s.Status_3 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth1: " << s.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl;
		}
		if (s.Status_4 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth2: " << s.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl;
		}
		if (s.Status_5 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth3: " << s.Status_5 << ">" << s.Item_Instance.Oth3 << "</Oth3>" << std::endl;
		}
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</TDBS_Item>" << std::endl;
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</Exac_Status>" << std::endl;
		s.UpdateStat(-1); s.OstreamSpace(fot); fot << "</Type_Status>" << std::endl;
	}
	return fot;
}

inline void TANXL_DataBase::Set_Code(std::string set, unsigned status){ Item_Instance.Code = set; Status_1 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Name(std::string set, unsigned status){ Item_Instance.Name = set; Status_2 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth1(std::string set, unsigned status){ Item_Instance.Oth1 = set; Status_3 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth2(std::string set, unsigned status){ Item_Instance.Oth2 = set; Status_4 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth3(std::string set, unsigned status){ Item_Instance.Oth3 = set; Status_5 = status; Combine_Status(); }

TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) :TDB_Status(0), Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal), IC_head(new Id_Chain(0, 0)), Status_1(0), Status_2(0), Status_3(0), Status_4(0), Status_5(0) {}

inline void TANXL_DataBase::UpdateStat(int Num)
{
	TDB_Status += Num;
}

inline void TANXL_DataBase::OstreamSpace(std::ostream& os)
{
	for (int i = 0; i < TDB_Status; i++)os << "\t";
}

inline void TANXL_DataBase::Combine_Status()
{
	Item_Instance.Item_Status = (Status_1 << 16) + (Status_2 << 12) + (Status_3 << 8) + (Status_4 << 4) + Status_5;
}

void* TANXL_DataBase::operator new(size_t Size, const TANXL_DataBase&)
{
	return 0;
}

void TANXL_DataBase::ResetInstance()
{
	Status_1 = 0x0, Status_2 = 0x0, Status_3 = 0x0, Status_4 = 0x0, Status_5 = 0x0;
	Combine_Status();
	Is_Instance_Data = false;
}

void TANXL_DataBase::Set_Instance(unsigned Num, std::string Set)
{
	int SetTimes{ 0 };
	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++;
	}
	if (SetTimes)
		Is_Instance_Data = true;
}

void TANXL_DataBase::AppendItem(bool To_File)
{
	if (!Is_Instance_Data)
	{ 
		std::cout << "添加失败! 结构内容为空" << std::endl;
		return;
	}
	else if (To_File)
	{
		Is_Instance_Data = true;
		std::fstream out("Tanxl_DataBase.usd", std::ios::app);
		if (out.is_open())
		{
			out << *this;
			this->ResetInstance();
			out.close();
		}
	}
	else
	{
		Data_Chain* Temp = new Data_Chain(
			Status_1, Item_Instance.Code,
			Status_2, Item_Instance.Name,
			Status_3, Item_Instance.Oth1,
			Status_4, Item_Instance.Oth2,
			Status_5, Item_Instance.Oth3);
		Append_Chain(*Temp, Status_1, Status_2);
	}
}

void TANXL_DataBase::SortDataBase(bool Mode, std::string Out_File_Name, std::string In_File_Name)
{
	if (Mode)
		if (!Get_LocalData(In_File_Name, true))
		{
			std::cout << "Sort_DataBase Failed - There is no such file" << std::endl;
			return;
		}
	std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	Id_Chain* before_PIC = new Id_Chain(0, 0);
	out << "<Tanxl_DataBase Information>" << std::endl;
	while (PIC != NULL)
	{
		std::cout << "PIC->LevelA :" << PIC->LevelA << "-- before_PIC->LevelA :" << before_PIC->LevelA;
		std::cout << "---PIC->LevelB :" << PIC->LevelB << "-- before_PIC->LevelB :" << before_PIC->LevelB << std::endl;
		if (PDC->Id_3 + PDC->Id_4 + PDC->Id_5 == -3)//用于判断是否需要执行清理步骤
		{
			if (PDC->exac != NULL)
				PDC = PDC->exac;
			else if (PIC->next != NULL)
			{
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
			else
				break;
			continue;
		}
		if (PIC->LevelA != before_PIC->LevelA)
			out << "\t<Type_Status: " << PIC->LevelA << ">" << std::endl;
		if (PIC->LevelA != before_PIC->LevelA || (PIC->LevelA == before_PIC->LevelA && PIC->LevelB != before_PIC->LevelB))
			out << "\t\t<Exac_Status: " << PIC->LevelB << ">" << std::endl;
		out << "\t\t\t<TDBS_Item>" << std::endl;
		if (PDC->Id_1 || Is_Zero_Legal)
			out << "\t\t\t\t<Code: " << PDC->Id_1 << ">" << PDC->Sd_1 << "</Code>" << std::endl;
		if (PDC->Id_2 || Is_Zero_Legal)
			out << "\t\t\t\t<Name: " << PDC->Id_2 << ">" << PDC->Sd_2 << "</Name>" << std::endl;
		if (PDC->Id_3 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth1: " << PDC->Id_3 << ">" << PDC->Sd_3 << "</Oth1>" << std::endl;
		if (PDC->Id_4 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth2: " << PDC->Id_4 << ">" << PDC->Sd_4 << "</Oth2>" << std::endl;
		if (PDC->Id_5 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth3: " << PDC->Id_5 << ">" << PDC->Sd_5 << "</Oth3>" << std::endl;
		out << "\t\t\t</TDBS_Item>" << std::endl;
		if (PDC->exac == NULL)
		{
			out << "\t\t</Exac_Status>" << std::endl;
			if (PIC->next == NULL)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
			}
			else if (PIC->next->LevelA != PIC->LevelA)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
			else
			{
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
		}
		else
		{
			before_PIC = PIC;
			PDC = PDC->exac;
		}
	}
	out << "</Tanxl_DataBase Information>" << std::endl;
	out.close();
	if (Mode)
	{
		Clear_Chain();
		std::string s = In_File_Name + ".usd";
		remove(s.c_str());
	}
}

void TANXL_DataBase::Append_Chain(Data_Chain& New_Data, int A, int B)
{
	Is_Chain_Empty = false;
	Id_Chain* PIC = IC_head;
	Id_Chain* before_PIC = NULL;
	if (PIC->LevelA == 0 && PIC->LevelB == 0)//链表为空修改类型链表表头
	{
		PIC->LevelA = A;
		PIC->LevelB = B;
		PIC->exac = &New_Data;
		return;
	}
	else
	{
		bool Flag{ false };
		Id_Chain* Chain_Temp = new Id_Chain(A, B);
		while (PIC != NULL)
		{
			if (A == PIC->LevelA && B == PIC->LevelB)
			{
				Chain_Temp = PIC;
				Flag = true;
			}
			else if (A < PIC->LevelA || (A == PIC->LevelA && B < PIC->LevelB))//链表不为空对插入的类型链表排序
			{
				if (before_PIC == NULL)
				{
					Chain_Temp->next = IC_head;
					IC_head = Chain_Temp;
					Flag = true;
				}
				else if (before_PIC != NULL)
				{
					Chain_Temp->next = PIC;
					before_PIC->next = Chain_Temp;
					Flag = true;
				}
			}
			if (Flag == true)
			{
				New_Data.exac = Chain_Temp->exac;
				Chain_Temp->exac = &New_Data;
				return;
			}
			before_PIC = PIC;
			PIC = PIC->next;
		}
		if (PIC == NULL && before_PIC != NULL && Flag == false)
		{
			before_PIC->next = Chain_Temp;
			New_Data.exac = Chain_Temp->exac;
			Chain_Temp->exac = &New_Data;
			return;
		}
	}
	std::cout << "Append False : Due to Unknown Reason !" << std::endl; system("pause");
	return;
}

bool TANXL_DataBase::Get_LocalData(std::string File_Name, bool Is_UnSort)
{
	int Exac_Data{}, Length_Line{ 50 }, IData[5]{ 0 }, Target{ -1 };
	std::string SData[5]{};
	char Line[50]{};
	if (Is_UnSort)
		File_Name += ".usd";
	else
		File_Name += ".sd";
	std::fstream in(File_Name, std::ios::in);
	if (in.is_open())
	{
		while (in.getline(Line, Length_Line))
		{
			std::string S_Line{ static_cast<std::string>(Line) };
			if (Combine_Char(S_Line, 1, 5) == "Type")//获取一个完整数据,并生成Data_Chain传入添加函数
			{
				std::string s = Divid_Char(S_Line, 0);
				int Type_Data{ std::stoi(Divid_Char(S_Line, 0)) };
				while (in.getline(Line, Length_Line) && (Combine_Char(S_Line, 1, 5) != "/Exa"))
				{
					S_Line = static_cast<std::string>(Line);
					std::string Label{ Combine_Char(S_Line, 1, 5) };
					if (Label == "/TDB")
					{
						Data_Chain* Data_Temp = new Data_Chain(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2], IData[3], SData[3], IData[4], SData[4]);
						IData[0] = 0; IData[1] = 0; IData[2] = 0; IData[3] = 0; IData[4] = 0;
						Append_Chain(*Data_Temp, Type_Data, Exac_Data);
						continue;
					}
					if (Label == "Exac")
						Exac_Data = std::stoi(Divid_Char(S_Line, 0));
					else
					{
						if (Label == "Code")
							Target = 0;
						else if (Label == "Name")
							Target = 1;
						else if (Label == "Oth1")
							Target = 2;
						else if (Label == "Oth2")
							Target = 3;
						else if (Label == "Oth3")
							Target = 4;
						if (Target == -1)
							continue;
						IData[Target] = std::stoi(Divid_Char(S_Line, 0));
						SData[Target] = Divid_Char(S_Line, 1);
						Target = -1;
					}
				}
			}
		}
		in.close();
		return true;
	}
	else
		return false;
}

void TANXL_DataBase::Clear_Chain()
{
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	while (PIC != NULL)
	{
		if (PDC != NULL)
		{
			PIC->exac = PDC->exac;
			delete PDC;
			PDC = PIC->exac;
		}
		else
		{
			Id_Chain* before_PIC = PIC;
			PIC = PIC->next;
			delete before_PIC;
		}
	}
	Is_Chain_Empty = true;
	TANXL_DataBase::IC_head = new Id_Chain(0, 0);
}

void TANXL_DataBase::Get_Specified(int A, int B, int Nums)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				Status_1 = PDC->Id_1;  Item_Instance.Code = PDC->Sd_1;
				Status_2 = PDC->Id_2;  Item_Instance.Name = PDC->Sd_2;
				Status_3 = PDC->Id_3;  Item_Instance.Oth1 = PDC->Sd_3;
				Status_4 = PDC->Id_4;  Item_Instance.Oth2 = PDC->Sd_4;
				Status_5 = PDC->Id_5;  Item_Instance.Oth3 = PDC->Sd_5;
				Combine_Status();
				return;
			}
			PIC = PIC->next;
		}
		std::cout << "获取失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "获取失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Get_Item_Status()
{
	Status_1 = ((Item_Instance.Item_Status & 0xf0000) >> 16);
	Status_2 = ((Item_Instance.Item_Status & 0x0f000) >> 12);
	Status_3 = ((Item_Instance.Item_Status & 0x00f00) >> 8);
	Status_4 = ((Item_Instance.Item_Status & 0x000f0) >> 4);
	Status_5 = (Item_Instance.Item_Status & 0x0000f);
}

void TANXL_DataBase::Print_Data()
{
	Id_Chain* PIC = IC_head;
	while (PIC != NULL)
	{
		std::cout << "Id_Chain :" << PIC->LevelA << "-" << PIC->LevelB << std::endl;
		Data_Chain* PDC = PIC->exac;
		while (PDC != NULL)
		{
			std::cout << "\tData_Chain :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << "-" << PDC->Id_4 << "-" << PDC->Id_5 << std::endl;
			PDC = PDC->exac;
		}
		PIC = PIC->next;
	}
}

void TANXL_DataBase::Set_Specified(int A, int B, int Nums, int level, int Id, std::string Data)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				switch (level)
				{
				case 1://禁止修改Type级别
					PDC->Sd_1 = Data;
					return;
				case 2://禁止修改Exac级别
					PDC->Sd_2 = Data;
					return;
				case 3:
					PDC->Id_3 = Id;
					PDC->Sd_3 = Data;
					return;
				case 4:
					PDC->Id_4 = Id;
					PDC->Sd_4 = Data;
					return;
				case 5:
					PDC->Id_5 = Id;
					PDC->Sd_5 = Data;
					return;
				}
			}
			PIC = PIC->next;
		}
		std::cout << "修改失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "修改失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Remove_Chain(int A, int B)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* before_PIC = NULL;
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				if (PIC == IC_head)
					IC_head = PIC->next;
				else
					before_PIC->next = PIC->next;
				Data_Chain* PDC = PIC->exac;
				while (PDC != NULL)
				{
					PIC->exac = PDC->exac;
					delete PDC;
					PDC = PIC->exac;
				}
				delete PIC;
				return;
			}
			before_PIC = PIC;
			PIC = PIC->next;
		}
		std::cout << "删除失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "删除失败! 链表内容为空" << std::endl;
}

TANXL_DATABASE VERSION_1_3

持续改进。考虑到本地文件以及链表都是按降序在生成时自动排好的,而在相关查询删除的代码时间复杂度都是N,因此决定更改旧的自定义数据结构模式,改为std::vector容器,用于降低时间复杂度。std::vector可支持折半查找,预计所有查询删除的时间复杂度能降低到logN。在其他方面没有太大变动,可以直接使用原有的使用例。(此版本存在BUG,1.4已更正)

#include "Tanxl_DataBase.h"
int main()
{
    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();
}//使用例
//_VERSION_1_3_ UPDATE LOG
// LAST_UPDATE 2022-03-07 17:29:04
// Divid_Char 函数简化 增强可读性与扩展性
// UpdateStat 函数功能整合进 OstreamSpace 函数
// 移除主类的 operator new 私有函数
// 针对0合法的情况对各项相关函数进行修改
// 新增 Short后缀链表 Vector后缀链表用于提示效率
// Append_Chain 剔除重复输入
// Print_Data 函数及相关内容重写

TANXL_DATABASE.H VERSION_1_3

#ifndef IOSTREAM
#define IOSTREAM
#include<iostream>
#endif

#ifndef FSTREAM
#define FSTREAM
#include<fstream>
#endif

#ifndef SSTREAM
#define SSTREAM
#include<sstream>
#endif

#ifndef VECTOR
#define VECTOR
#include<vector>
#endif

enum Is_Sorted
{
	SORTED_LOCAL_FILE = 0x0,
	UNSORT_LOCAL_FILE = 0x1
};

enum ESort_Mode//为SortDataBase函数提供的功能枚举
{
	SORT_LOCALFILE    = 0,
	SORT_V2_LOCALFILE = 1, //V2版本读取效率更高
	SORT_MEMORY       = 2,
	SORT_V2_MEMORY    = 3
};

enum EDivid_Mode//为Divid_Char函数提供的功能枚举
{
	GET_STATUS_DATA  = 0,
	GET_STORAGE_DATA = 1,
	GET_STATUS_TAG   = 2
};

struct Data_Chain//数据链表 (即将淘汰)
{
	explicit Data_Chain(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, std::string D_C = NULL, int I_D = NULL, std::string D_D = NULL, int I_E = NULL, std::string D_E = NULL) :
		Id_1(I_A), Id_2(I_B), Id_3(I_C), Id_4(I_D), Id_5(I_E), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C), Sd_4(D_D), Sd_5(D_E), exac(NULL) {}
	int Id_1, Id_2, Id_3, Id_4, Id_5;
	std::string Sd_1, Sd_2, Sd_3, Sd_4, Sd_5;
	Data_Chain* exac;
};

struct Data_Chain_Short//短数据链表(V2)
{
	explicit Data_Chain_Short(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, 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), exac(NULL) {}
	int Id_1, Id_2, Id_3;
	std::string Sd_1, Sd_2, Sd_3;
	Data_Chain_Short* exac;
};

struct Data_Chain_Vector//短数据链表(Vector)
{
	explicit Data_Chain_Vector(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, 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_Chain_Vector//短类型链表(Vector)
{
	explicit Id_Chain_Vector(int A, int B) :
		LevelA(A), LevelB(B), StrA("NULL"), StrB("NULL"), exac(NULL) {}
	int LevelA, LevelB;
	std::string StrA, StrB;
	std::vector<Data_Chain_Vector*> exac;//用于支持折半查找
};

struct Id_Chain_Short//短类型链表(V2)
{
	explicit Id_Chain_Short(int A, int B, Id_Chain_Short* N = NULL, Data_Chain_Short* S = NULL) :
		LevelA(A), LevelB(B), next(N), exac(S) {}
	Id_Chain_Short* next;//next指向Type类型的下一个对象
	Data_Chain_Short* exac;
	int LevelA, LevelB;
};

struct Id_Chain//类型链表 (即将淘汰)
{
	explicit Id_Chain(int A, int B, Id_Chain* N = NULL, Data_Chain* E = NULL) :
		LevelA(A), LevelB(B), next(N), exac(E) {}
	Id_Chain* next;//next指向Type类型的下一个对象
	Data_Chain* exac;//exac指向该Type类型下的下一个Exac对象
	int LevelA, LevelB;
};

class TANXL_DataBase
{
private:
	struct
	{
		unsigned Item_Status{ 0 };
		std::string Code;
		std::string Name;
		std::string Oth1;
		std::string Oth2;
		std::string Oth3;
	}Item_Instance;

	std::vector<Id_Chain_Vector*> IC_Vector;

	Id_Chain* IC_head;
	int TDB_Status;//级别数值 用于记录当前行的\t数量
	bool Is_Instance_Data;
	bool Is_Chain_Empty;
	bool Is_Zero_Legal;//值为true时0成为合法值 可在输出中显示/使用
	unsigned Status_1, Status_2, Status_3, Status_4, Status_5;
	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);
	void Append_Chain(Data_Chain_Vector& New_Data, int LevelA, int LevelB);//链表添加内容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, bool Is_UnSort = SORTED_LOCAL_FILE);//获取本地数据 并新建一个链表 Is_Unsort用于区分打开的是否为处理后的文件 即后缀.usd和.sd
	bool Get_ShortData(std::string File_Name);//仅限Sorted的V2数据使用 可用于获取其中的数据并加入链表
	//↓编辑实例 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 levelA, int levelB, int Nums);//读取指定Type(A)_Exac(B)级别的物品 并载入到单例结构中 Nums表示链表中的第几个(从0开始)
	void Set_Specified(int levelA, int levelB, int Nums, int level, int Id, std::string Data);//修改指定Type(A)_Exac(B)级别的物品 Nums表示链表中的第几个(从0开始) level取值范围为1~5 用于选定Name Code Oth1 ...
	void Remove_Chain(int levelA, int levelB);//删除某一节点与其下所有内容
	void Print_Data();//输出当前链表中的所有内容
	void AppendItem(bool To_File = true);//向本地文件中(.usd)添加Item物品 此函数会导致Item单例重置
	//↓使本地(.usd)文件的内容合理化 In_File_Name为输入文件名 Out_File_Name为输出文件名 现在具有保存链表修改功能
	//↓Mode为true时从文件中读取数据 需要提供In/Out_File_Name 执行后清空内存中的链表  Mode为false时直接对当前内存中的链表进行整理 可以使现有链表改为升序 执行后不清空
	void SortDataBase(int Mode = SORT_LOCALFILE, 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_DATA);//拆分单行内容获取信息

void Reset_Chain(TANXL_DataBase TDB, int levelA, int levelB, 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/04/01 23:36 WILD_CHICKEN_PROGRAMING VERSION_1_3

#include "Tanxl_DataBase.h"

TANXL_DataBase TDB_Instance(true);

std::string Combine_Char(std::string data, int Start, int End)
{
	if (End < Start)
		return "错误 : Combine_Char 的输入值Start大于End的值";
	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 0://获取单例数据0~15
		Left = ':'; Right = '>';
		break;
	case 1://获取储存的信息
		Left = '>'; Right = '<';
		break;
	case 2://信息条目
		Left = '<'; Right = ':';
		break;
	case 3://V3链表主副键String
		Left = ':'; Right = ':';
		break;
	default:
		return "错误 : Divid_Char 没有此条目的功能(0~3 为合法内容,而你输入了" + std::to_string(Mode) + ")";
	}
	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);
	}
	return "失败 : Divid_Char 读取错误 不存在满足条件的内容";
}

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)
{
	int Length_Line{ 50 };
	char Line[50]{};
	std::fstream in(FileB + ".usd", std::ios::in);
	std::fstream out(FileA + ".usd", std::ios::app);
	if (in.is_open() && out.is_open())
	{
		out << std::endl;
		while (in.getline(Line, Length_Line))
			out << Line << std::endl;
	}
	else
		std::cout << "失败 : Combine_File 无法打开的指定文件" << std::endl;
}

std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s)
{
	if ((s.Status_1 + s.Status_2 + s.Status_3 + s.Status_4 + s.Status_5) || s.Is_Zero_Legal)
	{
		s.Get_Item_Status();
		fot << "<Type_Status :" << s.Status_1 << ">" << std::endl;
		s.OstreamSpace(fot, 1); fot << "<Exac_Status :" << s.Status_2 << ">" << std::endl;
		s.OstreamSpace(fot, 1, 1); fot << "<TDBS_Item>" << std::endl;
		if (s.Status_1 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Code: " << s.Status_1 << ">" << s.Item_Instance.Code << "</Code>" << std::endl;
		}
		if (s.Status_2 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Name: " << s.Status_2 << ">" << s.Item_Instance.Name << "</Name>" << std::endl;
		}
		if (s.Status_3 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth1: " << s.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl;
		}
		if (s.Status_4 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth2: " << s.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl;
		}
		if (s.Status_5 || s.Is_Zero_Legal) {
			s.OstreamSpace(fot);
			fot << "<Oth3: " << s.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; Status_1 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Name(std::string set, unsigned status){ Item_Instance.Name = set; Status_2 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth1(std::string set, unsigned status){ Item_Instance.Oth1 = set; Status_3 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth2(std::string set, unsigned status){ Item_Instance.Oth2 = set; Status_4 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth3(std::string set, unsigned status){ Item_Instance.Oth3 = set; Status_5 = status; Combine_Status(); }

TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) :TDB_Status(0), Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal), IC_head(new Id_Chain(0, 0)), IC_Vector(NULL), Status_1(0), Status_2(0), Status_3(0), Status_4(0), Status_5(0) {}

inline void TANXL_DataBase::OstreamSpace(std::ostream& os, int Before, int After)
{
	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 = (Status_1 << 16) + (Status_2 << 12) + (Status_3 << 8) + (Status_4 << 4) + Status_5;
}

void TANXL_DataBase::ResetInstance()
{
	Status_1 = 0x0, Status_2 = 0x0, Status_3 = 0x0, Status_4 = 0x0, 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)
{
	if (!Is_Instance_Data)
	{ 
		std::cout << "添加失败! 结构内容为空" << std::endl;
		return;
	}
	else if (To_File)
	{
		Is_Instance_Data = true;
		std::fstream out("Tanxl_DataBase.usd", std::ios::app);
		if (out.is_open())
		{
			out << *this;
			this->ResetInstance();
			out.close();
		}
	}
	else
	{
		Data_Chain_Vector* Temp = new Data_Chain_Vector(
			//Status_1, Item_Instance.Code,
			//Status_2, Item_Instance.Name,
			Status_3, Item_Instance.Oth1,
			Status_4, Item_Instance.Oth2,
			Status_5, Item_Instance.Oth3);
		Append_Chain(*Temp, Status_1, Status_2);
	}
}

void TANXL_DataBase::SortDataBase(int Mode, std::string Out_File_Name, std::string In_File_Name)
{
	if (Mode == SORT_MEMORY || Mode == SORT_V2_MEMORY)
		if (!Get_LocalData(In_File_Name, true))
		{
			std::cout << "Sort_DataBase Failed - There is no such file" << std::endl;
			return;
		}
	std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	Id_Chain* before_PIC = new Id_Chain(0, 0);
	out << "<Tanxl_DataBase Information>" << std::endl;
	while (PIC != NULL)
	{
		std::cout << "PIC->LevelA :" << PIC->LevelA << "-- before_PIC->LevelA :" << before_PIC->LevelA;
		std::cout << "---PIC->LevelB :" << PIC->LevelB << "-- before_PIC->LevelB :" << before_PIC->LevelB << std::endl;
		if (PDC->Id_3 + PDC->Id_4 + PDC->Id_5 == -3)//用于判断是否需要执行清理步骤  2022/3/17 22:26 错误的文件名会导致此处发生错误
		{
			std::cout << "检测到需要执行清理步骤 ProcessinG" << std::endl;
			if (PDC->exac != NULL)
				PDC = PDC->exac;
			else if (PIC->next != NULL)
			{
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
			else
				break;
			continue;
		}
		if (PIC->LevelA != before_PIC->LevelA)
			out << "\t<Type_Status: " << PIC->LevelA << ">" << std::endl;
		if (PIC->LevelA != before_PIC->LevelA || (PIC->LevelA == before_PIC->LevelA && PIC->LevelB != before_PIC->LevelB))
			out << "\t\t<Exac_Status: " << PIC->LevelB << ">" << std::endl;
		out << "\t\t\t<TDBS_Item>" << std::endl;
		if (Mode == SORT_MEMORY || Mode == SORTED_LOCAL_FILE)
		{
			if (PIC->LevelA || Is_Zero_Legal)
				out << "\t\t\t\t<Code: " << PDC->Id_1 << ">" << PDC->Sd_1 << "</Code>" << std::endl;
			if (PIC->LevelB || Is_Zero_Legal)
				out << "\t\t\t\t<Name: " << PDC->Id_2 << ">" << PDC->Sd_2 << "</Name>" << std::endl;
		}
		if (PDC->Id_3 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth1: " << PDC->Id_3 << ">" << PDC->Sd_3 << "</Oth1>" << std::endl;
		if (PDC->Id_4 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth2: " << PDC->Id_4 << ">" << PDC->Sd_4 << "</Oth2>" << std::endl;
		if (PDC->Id_5 || Is_Zero_Legal)
			out << "\t\t\t\t<Oth3: " << PDC->Id_5 << ">" << PDC->Sd_5 << "</Oth3>" << std::endl;
		out << "\t\t\t</TDBS_Item>" << std::endl;
		if (PDC->exac == NULL)//Type & Exac 区域结束判断
		{
			out << "\t\t</Exac_Status>" << std::endl;
			if (PIC->next == NULL)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
			}
			else if (PIC->next->LevelA != PIC->LevelA)
			{
				out << "\t</Type_Status>" << std::endl;
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
			else
			{
				before_PIC = PIC;
				PIC = PIC->next;
				PDC = PIC->exac;
			}
		}
		else
		{
			before_PIC = PIC;
			PDC = PDC->exac;
		}
	}
	out << "</Tanxl_DataBase Information>" << std::endl;
	out.close();
	if (Mode == SORT_MEMORY || Mode == SORT_V2_MEMORY)
	{
		Clear_Chain();
		std::string s = In_File_Name + ".usd";
		remove(s.c_str());
	}
}

void TANXL_DataBase::Append_Chain(Data_Chain_Vector& New_Data, int LevelA, int LevelB)
{	
	if (Is_Chain_Empty)
	{
		IC_Vector.push_back(new Id_Chain_Vector(LevelA, LevelB));
		IC_Vector.at(0)->exac.push_back(&New_Data);
		Is_Chain_Empty = false;
		return;
	}
	int Mid = IC_Vector.size() / 2;
	int Left = 0;
	int Right = static_cast<int>(IC_Vector.size()) - 1 <= 0 ? 0 : static_cast<int>(IC_Vector.size()) - 1;

	while (true)
	{
		Id_Chain_Vector* PIC = IC_Vector.at(Mid);
		if (PIC->LevelA * 16 + PIC->LevelB == LevelA * 16 + LevelB)//LevelA B匹配时
		{
			PIC->exac.push_back(&New_Data);
			Is_Chain_Empty = false;
			return;
		}
		else if (Left == Right && PIC->LevelA * 16 + PIC->LevelB != LevelA * 16 + LevelB)
		{
			this->IC_Vector.insert(IC_Vector.begin() + Left, new Id_Chain_Vector(LevelA, LevelB));
			IC_Vector.at(1 + Left)->exac.push_back(&New_Data);
			Is_Chain_Empty = false;
			return;
		}
		else if (PIC->LevelA * 16 + PIC->LevelB < LevelA * 16 + LevelB)
		{
			Left = Mid;
			Mid = (Left + Right) / 2;
		}
		else if (PIC->LevelA * 16 + PIC->LevelB > LevelA * 16 + LevelB)
		{
			Right = Mid;
			Mid = (Left + Right) / 2;
		}
	}
	std::cout << "Append False : Due to Unknown Reason !" << std::endl; system("pause");
	return;
}

bool TANXL_DataBase::Get_LocalData(std::string File_Name, bool Is_UnSort)
{
	int Exac_Data{}, Length_Line{ 50 }, IData[5]{ 0 }, Target{ -1 };
	std::string SData[5]{};
	char Line[50]{};
	if (Is_UnSort)
		File_Name += ".usd";
	else
		File_Name += ".sd";
	std::fstream in(File_Name, std::ios::in);
	if (in.is_open())
	{
		while (in.getline(Line, Length_Line))
		{
			std::string S_Line{ static_cast<std::string>(Line) };
			if (Combine_Char(S_Line, 1, 5) == "Type")//获取一个完整数据,并生成Data_Chain传入添加函数
			{
				int Type_Data{ std::stoi(Divid_Char(S_Line, GET_STATUS_DATA)) };
				while (in.getline(Line, Length_Line) && (Combine_Char(S_Line, 1, 5) != "/Exa"))
				{
					S_Line = static_cast<std::string>(Line);
					std::string Label{ Combine_Char(S_Line, 1, 5) };
					if (Label == "/TDB")
					{
						Data_Chain_Vector* Data_Temp = new Data_Chain_Vector(/*IData[0], SData[0], IData[1], SData[1], */ IData[2], SData[2], IData[3], SData[3], IData[4], SData[4]);
						/*IData[0] = 0; IData[1] = 0; */IData[2] = 0; IData[3] = 0; IData[4] = 0;
						Append_Chain(*Data_Temp, Type_Data, Exac_Data);
						continue;
					}
					if (Label == "Exac")
						Exac_Data = std::stoi(Divid_Char(S_Line, GET_STATUS_DATA));
					else
					{
						if (Label == "Code")
							Target = 0;
						else if (Label == "Name")
							Target = 1;
						else if (Label == "Oth1")
							Target = 2;
						else if (Label == "Oth2")
							Target = 3;
						else if (Label == "Oth3")
							Target = 4;
						if (Target == -1)
							continue;
						IData[Target] = std::stoi(Divid_Char(S_Line, GET_STATUS_DATA));
						SData[Target] = Divid_Char(S_Line, GET_STORAGE_DATA);
						Target = -1;
					}
				}
			}
		}
		in.close();
		return true;
	}
	else
		return false;
}

bool TANXL_DataBase::Get_ShortData(std::string File_Name)
{
	int Length_Line{ 50 }, IData[5]{ 0 }, Target{ -1 };
	std::string SData[5]{};
	char Line[50]{};
	int Type_Data{}, Exac_Data{};
	File_Name += ".sd";
	std::fstream in(File_Name, std::ios::in);
	if (in.is_open())
	{
		while (in.getline(Line, Length_Line))
		{
			std::string S_Line{ static_cast<std::string>(Line) };
			if (Combine_Char(S_Line, 1, 5) == "Type")//获取一个完整数据,并生成Data_Chain传入添加函数
				Type_Data = std::stoi(Divid_Char(S_Line, GET_STATUS_DATA));
			if (Combine_Char(S_Line, 1, 5) == "Exac")
				Exac_Data = std::stoi(Divid_Char(S_Line, GET_STATUS_DATA));
			else
			{
				while (in.getline(Line, Length_Line) && (Combine_Char(S_Line, 1, 5) != "/Exa"))
				{
					S_Line = static_cast<std::string>(Line);
					std::string Label{ Combine_Char(S_Line, 1, 5) };
					if (Label == "/TDB")
					{
						Data_Chain_Vector* Data_Temp = new Data_Chain_Vector(/*Type_Data, SData[0], Exac_Data, SData[1], */IData[2], SData[2], IData[3], SData[3], IData[4], SData[4]);
						/*IData[0] = 0; IData[1] = 0; */IData[2] = 0; IData[3] = 0; IData[4] = 0;
						Append_Chain(*Data_Temp, Type_Data, Exac_Data);
						continue;
					}
					else
					{
						if (Label == "Oth1")
							Target = 2;
						else if (Label == "Oth2")
							Target = 3;
						else if (Label == "Oth3")
							Target = 4;
						if (Target == -1)
							continue;
						IData[Target] = std::stoi(Divid_Char(S_Line, GET_STATUS_DATA));
						SData[Target] = Divid_Char(S_Line, GET_STORAGE_DATA);
						Target = -1;
					}
				}
			}
		}
		in.close();
		return true;
	}
	else
		return false;
}

void TANXL_DataBase::Clear_Chain()
{
	Id_Chain* PIC = IC_head;
	Data_Chain* PDC = PIC->exac;
	while (PIC != NULL)
	{
		if (PDC != NULL)
		{
			PIC->exac = PDC->exac;
			delete PDC;
			PDC = PIC->exac;
		}
		else
		{
			Id_Chain* before_PIC = PIC;
			PIC = PIC->next;
			delete before_PIC;
		}
	}
	Is_Chain_Empty = true;
	IC_head = new Id_Chain(0, 0);
}

void TANXL_DataBase::Get_Specified(int A, int B, int Nums)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				Status_1 = PDC->Id_1;  Item_Instance.Code = PDC->Sd_1;
				Status_2 = PDC->Id_2;  Item_Instance.Name = PDC->Sd_2;
				Status_3 = PDC->Id_3;  Item_Instance.Oth1 = PDC->Sd_3;
				Status_4 = PDC->Id_4;  Item_Instance.Oth2 = PDC->Sd_4;
				Status_5 = PDC->Id_5;  Item_Instance.Oth3 = PDC->Sd_5;
				Combine_Status();
				return;
			}
			PIC = PIC->next;
		}
		std::cout << "获取失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "获取失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Get_Item_Status()
{
	Status_1 = ((Item_Instance.Item_Status & 0xf0000) >> 16);
	Status_2 = ((Item_Instance.Item_Status & 0x0f000) >> 12);
	Status_3 = ((Item_Instance.Item_Status & 0x00f00) >> 8 );
	Status_4 = ((Item_Instance.Item_Status & 0x000f0) >> 4 );
	Status_5 = ( Item_Instance.Item_Status & 0x0000f       );
}

void TANXL_DataBase::Print_Data()//输出当前链表中的所有内容 V3 updated
{
	Id_Chain_Vector* PIC{};
	Data_Chain_Vector* PDC{};
	int PIC_Count{ 0 }, PDC_Count{ 0 };
	do
	{
		PIC = this->IC_Vector.at(PIC_Count++);
		std::cout << "Id_Chain_Vector :" << PIC->LevelA << "-" << PIC->LevelB << std::endl;
		do
		{
			PDC = PIC->exac.at(PDC_Count++);
			std::cout << "\tData_Chain_Vector :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << std::endl;
		} while (PDC != PIC->exac.at(static_cast<int>(PIC->exac.size())-1));
	} while (PIC != this->IC_Vector.at(static_cast<int>(this->IC_Vector.size()) - 1));
}

void TANXL_DataBase::Set_Specified(int A, int B, int Nums, int level, int Id, std::string Data)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				Data_Chain* PDC = PIC->exac;
				while (Nums > 0 && PDC->exac != NULL)
				{
					Nums--;
					PDC = PDC->exac;
				}
				switch (level)
				{
				case 1://禁止修改Type级别
					PDC->Sd_1 = Data;
					return;
				case 2://禁止修改Exac级别
					PDC->Sd_2 = Data;
					return;
				case 3:
					PDC->Id_3 = Id;
					PDC->Sd_3 = Data;
					return;
				case 4:
					PDC->Id_4 = Id;
					PDC->Sd_4 = Data;
					return;
				case 5:
					PDC->Id_5 = Id;
					PDC->Sd_5 = Data;
					return;
				}
			}
			PIC = PIC->next;
		}
		std::cout << "修改失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "修改失败! 链表内容为空" << std::endl;
}

void TANXL_DataBase::Remove_Chain(int A, int B)
{
	if (!Is_Chain_Empty)
	{
		Id_Chain* before_PIC = NULL;
		Id_Chain* PIC = IC_head;
		while (PIC != NULL)
		{
			if (PIC->LevelA == A && PIC->LevelB == B)
			{
				if (PIC == IC_head)
					IC_head = PIC->next;
				else
					before_PIC->next = PIC->next;
				Data_Chain* PDC = PIC->exac;
				while (PDC != NULL)
				{
					PIC->exac = PDC->exac;
					delete PDC;
					PDC = PIC->exac;
				}
				delete PIC;
				return;
			}
			before_PIC = PIC;
			PIC = PIC->next;
		}
		std::cout << "删除失败! 查找相关内容不成功" << std::endl;
		return;
	}
	std::cout << "删除失败! 链表内容为空" << std::endl;
}

TANXL_DATABASE VERSION_1_4

在上一版的基础上,根据其思想对绝大多数代码进行了重写,总体效率得到大幅度提升。1.5将在文件操作方面进行优化,降低每次整理重复内容的次数。由于接口方面没有太大的修改,原使用例仍然可直接用于运行。

//_VERSION_1_4_ UPDATE LOG
// LAST_UPDATE 2022-04-01 23:40:38
// 修复Print_Data()没有重置Counts的错误
// 修复Append_Chain()插入的位置向后偏移一位的错误
// 增加两个快速定位函数 以logN的时间复杂度获取指针
// Set_Specified()现在修改TypeExac会转移数据的位置
// Remove_Chain()功能重写以提升效率
// Get_Specified()功能重写以提升效率
// Clear_Chain()功能重写以提升效率
// 移除 Data_Chain Id_Chain Data_Chain_Short Id_Chain_Short
// 为了统一操作将所有LevelA-LevelB修改为Type-Exac
// Get_LocalData()功能部分重写以支持新数据结构
// SortDataBase()重写 提升性能并调整枚举功能

TANXL_DATABASE.H VERSION_1_4

#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,
};

struct Data_Chain_Vector//短数据链表(Vector)
{
	explicit Data_Chain_Vector(int I_A = NULL, std::string D_A = NULL, int I_B = NULL, std::string D_B = NULL, int I_C = NULL, 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_Chain_Vector//短类型链表(Vector)
{
	explicit Id_Chain_Vector(int Type, int Exac, std::string Code = "NULL", std::string Name = "NULL") :
		Type(Type), Exac(Exac), StrA(Code), StrB(Name), exac(NULL) {}
	int Type, Exac;
	std::string StrA, StrB;
	std::vector<Data_Chain_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_Chain_Vector*> IC_Vector;
	int Current_Location;
	int TDB_Status;//级别数值 用于记录当前行的\t数量
	bool Is_Instance_Data;
	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_Chain_Vector* Id_Chain_Locate(int Type, int Exac);//时间复杂度为logN的Id_Chain快速定位函数 Type Exac 指Id_Chain的同名变量
	Data_Chain_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_Chain_Vector& New_Data, Id_Chain_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);//获取本地数据 并新建一个链表 Is_Unsort用于区分打开的是否为处理后的文件 即后缀.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_Chain_Vector和Data_Chain_Vector中的内容
	void Print_Data();
	void AppendItem(bool To_File = true);//向本地文件中(.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/04/04 23:08 WILD_CHICKEN_PROGRAMING VERSION_1_4

#include "Tanxl_DataBase.h"

TANXL_DataBase TDB_Instance(true);

std::string Combine_Char(std::string data, int Start, int End)
{
	if (End < Start)
		return "错误 : Combine_Char 的输入值Start大于End的值";
	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:
		return "错误 : Divid_Char 没有此条目的功能(0~3 为合法内容,而你输入了" + std::to_string(Mode) + ")";
	}
	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);
	}
	return "失败 : Divid_Char 读取错误 不存在满足条件的内容";
}

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)
{
	int Length_Line{ 50 };
	char Line[50]{};
	std::fstream in(FileB + ".usd", std::ios::in);
	std::fstream out(FileA + ".usd", std::ios::app);
	if (in.is_open() && out.is_open())
	{
		out << std::endl;
		while (in.getline(Line, Length_Line))
			out << Line << std::endl;
	}
	else
		std::cout << "失败 : Combine_File 无法打开的指定文件" << std::endl;
}

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) :
	TDB_Status(0), Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal),
	IC_Vector(NULL),Current_Location(0) {}

inline void TANXL_DataBase::OstreamSpace(std::ostream& os, int Before, int After)
{
	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)
{
	if (!Is_Instance_Data)
	{ 
		std::cout << "添加失败! 结构内容为空" << std::endl;
		return;
	}
	else if (To_File)
	{
		Is_Instance_Data = true;
		std::fstream out("Tanxl_DataBase.usd", std::ios::app);
		if (out.is_open())
		{
			out << *this;
			this->ResetInstance();
			out.close();
		}
	}
	else
	{
		Data_Chain_Vector* DTemp = new Data_Chain_Vector(
			Item_Instance.Status_3, Item_Instance.Oth1,
			Item_Instance.Status_4, Item_Instance.Oth2,
			Item_Instance.Status_5, Item_Instance.Oth3);
		Id_Chain_Vector* ITemp = new Id_Chain_Vector(
			Item_Instance.Status_1, Item_Instance.Status_2,
			Item_Instance.Code, Item_Instance.Name);
		Append_Chain(*DTemp, *ITemp);
	}
}

// V3 UPDATED COD ↓   OLD STYLE COD ↑

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))
		{
			std::cout << "SortDataBase() Failed ! : 未能成功匹配文件" << std::endl;
			return;
		}
	if (Is_Chain_Empty)
	{
		std::cout << "SortDataBase() Failed ! : 获取到的数据为空" << std::endl;
		return;
	}
	std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);
	Id_Chain_Vector* PIC{ this->IC_Vector.at(0) };
	out << "<Tanxl_DataBase Information>" << std::endl;
	std::vector<Id_Chain_Vector*>::iterator IOIE{ IC_Vector.end() };
	std::vector<Id_Chain_Vector*>::iterator IOIB{ IC_Vector.begin() };
	do
	{
		std::vector<Data_Chain_Vector*>::iterator IODE{ (*IOIB)->exac.end() };
		std::vector<Data_Chain_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_Chain_Vector& New_Data, Id_Chain_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 }, Right{ static_cast<int>(IC_Vector.size()) - 1 <= 0 ? 0 : static_cast<int>(IC_Vector.size()) - 1 }, Value{ New_Id.Type * 16 + New_Id.Exac };
	while (true)
	{
		int Mid{ (Left + Right) / 2 };
		Id_Chain_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;
		}
	}
	std::cout << "Append() Failed ! : 未知原因" << std::endl;
	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_Chain_Vector* Data_Temp = new Data_Chain_Vector(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2]);
						Id_Chain_Vector* Id_Temp = new Id_Chain_Vector(Type_Stat, Exac_Stat, Type_Data, Exac_Data);
						IData[0] = 0; IData[1] = 0; IData[2] = 0; SData[0] = ""; SData[1] = ""; SData[2] = "";
						Append_Chain(*Data_Temp, *Id_Temp);
						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_Chain_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) })
	{
		Id_Chain_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;
	}
	std::cout << "Get_Specified() Failed ! : 未能成功匹配相同值" << std::endl;
}

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_Chain_Vector* PIC{};
		Data_Chain_Vector* PDC{};
		int PIC_Count{ 0 };
		std::vector<Id_Chain_Vector*>::iterator IOI = IC_Vector.end() - 1;
		do
		{
			int PDC_Count{ 0 };
			PIC = this->IC_Vector.at(PIC_Count++);
			std::vector<Data_Chain_Vector*>::iterator IOD = PIC->exac.end() - 1;
			std::cout << "Id_Chain_Vector :" << PIC->Type << " - " << PIC->StrA << " - " << PIC->Exac << " - " << PIC->StrB << std::endl;
			do
			{
				PDC = PIC->exac.at(PDC_Count++);
				std::cout << "\tData_Chain_Vector :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << std::endl;
			} while (PDC != *IOD);
		} while (PIC != *IOI);
		return;
	}
	std::cout << "Print_Data() Failed ! : 链表内容为空" << std::endl;
}

void TANXL_DataBase::Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data) //V3 Updated
{
	if (Data_Chain_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;
		}
	std::cout << "Set_Specified() Failed ! : 查找相关内容不成功或链表内容为空" << std::endl;
}

void TANXL_DataBase::Remove_Chain(int Type, int Exac)
{
	if (Id_Chain_Vector * PIC{ Id_Chain_Locate(Type, Exac) })
	{
		for (int i{ 0 }; i < PIC->exac.size(); i++)
			delete PIC->exac.at(i);//释放 Data_Chain_Vector
		PIC->exac.clear();
		delete PIC;//释放 Id_Chain_Vector
		IC_Vector.erase(IC_Vector.begin() + Current_Location);
	}
}

Id_Chain_Vector* TANXL_DataBase::Id_Chain_Locate(int Type, int Exac)//有优化空间
{
	int Left{ 0 }, Right{ static_cast<int>(IC_Vector.size()) - 1 >= 0 ? static_cast<int>(IC_Vector.size()) - 1 : 0 }, Value{ Type * 16 + Exac };
	if (Left == Right)
	{
		if (Value == IC_Vector.at(0)->Type * 16 + IC_Vector.at(0)->Exac)
		{
			Current_Location = 0;
			return IC_Vector.at(0);
		}
		std::cout << "Id_Chain_Locate Failed ! : 未能成功匹配相同值" << std::endl;
		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)
			{
				std::cout << "Id_Chain_Locate Failed ! : 未能成功匹配相同值" << std::endl;
				return NULL;
			}
		}
	}
	std::cout << "Id_Chain_Locate Failed ! : 未知原因" << std::endl;
	return NULL;
}

Data_Chain_Vector* TANXL_DataBase::Data_Chain_Locate(int Type, int Exac, int Depth)
{
	Id_Chain_Vector* PIC{ Id_Chain_Locate(Type, Exac) };
	if (PIC->exac.size() < Depth)
	{
		std::cout << "Data_Chain_Locate Failed ! : 超出当前容器最大深度" << std::endl;
		return NULL;
	}
	else if (Depth < 0 && Depth + static_cast<int>(PIC->exac.size()) >= 0)
		return PIC->exac.at(Depth + PIC->exac.size());
	return PIC->exac.at(Depth);
}

void TANXL_DataBase::Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac)
{
	Id_Chain_Vector* PIC{ Id_Chain_Locate(OldType, OldExac) };
	Append_Chain(*PIC->exac.at(OldDepth), *new Id_Chain_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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WiChP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值