[C++] Use a linked list to store, search, modify, and save ini file data

AnInitFile.h

/*
*支持"#"和";"开头注释,链表的方式存储数据
*/

#pragma once
#include "AnHeader.h"
namespace An
{
class  InitFileReader;
class  InitFileWriter;
struct ElementList;
struct RootNodeList;
struct LineTextList;

//前置声明TEXTCODETYPE,会报错还在找解决方案:https://cloud.tencent.com/developer/ask/51491
code from:https://www.cnblogs.com/rcg714786690/p/14246669.html
//code type
enum TEXTCODETYPE:int
{
	TEXT_UNKNOW = 0x0,
	TEXT_ANSI = 0x0001,
	TEXT_UTF8 = 0x0002,
};

	class AnInitFile
	{
	public:
		AnInitFile();
		AnInitFile(const char *filePath);
		~AnInitFile();
	public:
		bool Open(const char *filePath);
		bool GetParam(const char *root, const char *key,char *value);
		bool SetParam(const char *root, const char *key,const char *value,bool autoSave=true);
		bool Save(const char *filePath=nullptr, TEXTCODETYPE type= TEXTCODETYPE::TEXT_UTF8);
	private:
		char           defaultFilePath[AN_PARAMLEN_MAX];
		InitFileReader *pInitFileReader;
		InitFileWriter *pInitFileWriter;
	};

	class InitFileReader
	{
		//use friend 
		friend class AnInitFile;
	private:
		InitFileReader();
		~InitFileReader();
	private:
		RootNodeList *pRootNodeList;
		LineTextList *pLineTextList;
	private:
		bool Read(const char *filePath);
		bool Get(const char *root, const char *key,char *value);
		bool Set(const char *root, const char *key, const char *value);
		void Analyse();
		void Release();
		TEXTCODETYPE GetCodeType(const char *filePath);
	};

	class InitFileWriter
	{
		//use friend 
		friend class AnInitFile;
	private:
		InitFileWriter();
		~InitFileWriter();
	private:
		std::ofstream *writeStream;
	private:
		bool CreateWriter(const char *path);
		wirte
		bool Write(const char *data);
		bool Write(const char *data,int length);
	    ///save
		bool Flush();
		bool Flush(LineTextList *pLineTextList,RootNodeList *pRootNodeList);
		//sec find
		bool Find(const char *root, const char *key, char *value, RootNodeList *pRootNodeList);
	};

	struct ElementList
	{
		unsigned char Element[AN_PARAMLEN_MAX];
		ElementList *nextElement;

		ElementList()
		{
			memset(Element, 0, AN_PARAMLEN_MAX);
			nextElement = nullptr;
		}
	};
	struct RootNodeList
	{
		unsigned char Root[AN_PARAMLEN_MAX];
		ElementList *KeyList;
		ElementList *ValList;
		RootNodeList *nextRootNode;
		RootNodeList()
		{
			memset(Root, 0, AN_PARAMLEN_MAX);
			KeyList = nullptr;
			ValList = nullptr;
			nextRootNode = nullptr;
		}
	};
	struct
	struct LineTextList
	{
		unsigned int RowNo;
		unsigned char Text[AN_PARAMLEN_MAX];
		LineTextList *nextLineText;
		LineTextList()
		{
			RowNo = -1;
			memset(Text, 0, AN_PARAMLEN_MAX);
			nextLineText = nullptr;
		}
	};

}


AnInitFile.cpp

#include "AnInitFile.h"
#include <string>
#include <fstream>
#include <sstream>
#include <Windows.h>


using namespace An;

int strFind(char key, unsigned char *Src);
void getLine(std::ifstream &stream, unsigned char *line);
std::string  UTF8ToGB(const char* str);
///check code type
bool check_utf8_without_bom(std::string &file_name);
TEXTCODETYPE check_text_encode(std::string file_name);

AnInitFile::AnInitFile()
{
	pInitFileReader = new InitFileReader();
	pInitFileWriter = new InitFileWriter();

	memset(defaultFilePath, 0, AN_PARAMLEN_MAX);
}

An::AnInitFile::AnInitFile(const char * filePath)
{
	AnInitFile();
	Open(filePath);
}


AnInitFile::~AnInitFile()
{
	delete pInitFileReader;
	delete pInitFileWriter;
	pInitFileReader = nullptr;
	pInitFileWriter = nullptr;
}

bool AnInitFile::Open(const char * filePath)
{
	if (pInitFileReader != nullptr)
	{
		pInitFileReader->Release();
		if (pInitFileReader->Read(filePath))
		{
			memcpy(defaultFilePath, filePath, AN_PARAMLEN_MAX);
			return true;
		}
		return false;
	}	
	return false;
}

bool An::AnInitFile::GetParam(const char * root, const char * key,char * value)
{
	return pInitFileReader->Get(root, key, value);
}

bool An::AnInitFile::SetParam(const char * root, const char * key, const char * value, bool autoSave)
{
	if (pInitFileReader->Set(root, key, value))
	{
		if (autoSave)
		{
			Save();
			return true;
		}
	}
	return false;
}

bool An::AnInitFile::Save(const char * filePath, TEXTCODETYPE type)
{
	//暂时仅支持UTF8保存
	if(!pInitFileReader||!pInitFileWriter)
		return false;
	char Path[AN_PARAMLEN_MAX];
	if (!filePath)
	{
		memcpy(Path, defaultFilePath, AN_PARAMLEN_MAX);
	}
	else
	{
		memcpy(Path, filePath, AN_PARAMLEN_MAX);
	}
	if (pInitFileWriter->CreateWriter(Path))
	{
		pInitFileWriter->Flush(pInitFileReader->pLineTextList, pInitFileReader->pRootNodeList);
		return true;
	}
	return false;
}

InitFileReader::InitFileReader()
{
	pRootNodeList = nullptr;
	pLineTextList = nullptr;
}

InitFileReader::~InitFileReader()
{
	Release();
}

bool InitFileReader::Read(const char * filePath)
{
	//check Type
	TEXTCODETYPE type=GetCodeType(filePath);
	if (type == TEXTCODETYPE::TEXT_UNKNOW)return false;
	
	std::ifstream RStream(filePath);
	if (!RStream)return false;//not exist
	if (RStream.peek() == EOF)return false;//empty
	int Row = 0;
	void *pListHeadPtr = nullptr;
	//read
	while (RStream.peek() != EOF)
	{
		if (pLineTextList == nullptr)
		{
			pLineTextList = new LineTextList();
			memset(pLineTextList->Text, NULL, AN_PARAMLEN_MAX);
			getLine(RStream, pLineTextList->Text);
			if (type==TEXTCODETYPE::TEXT_UTF8)
			{
				std::string gbStr=UTF8ToGB((char *)pLineTextList->Text);
				memset(pLineTextList->Text, NULL, AN_PARAMLEN_MAX);
				memcpy(pLineTextList->Text, gbStr.c_str(), gbStr.size());
			}
			Row++;
			pLineTextList->RowNo = Row;
			pListHeadPtr = pLineTextList;
		}
		else
		{
			LineTextList *textList= new LineTextList();
			memset(textList->Text, NULL, AN_PARAMLEN_MAX);
			getLine(RStream, textList->Text);
			if (type == TEXTCODETYPE::TEXT_UTF8)
			{
				std::string gbStr = UTF8ToGB((char *)textList->Text);
				memset(textList->Text, NULL, AN_PARAMLEN_MAX);
				memcpy(textList->Text, gbStr.c_str(), gbStr.size());
			}
			Row++;
			textList->RowNo = Row;
			pLineTextList->nextLineText = textList;
			pLineTextList = textList;
		}
	}
	pLineTextList = (LineTextList*)pListHeadPtr;
	RStream.close();
	Analyse();
	return true;
}

bool InitFileReader::Get(const char * root, const char * key, char * value)
{
	if (pRootNodeList == nullptr)
	{
		value = nullptr;
		return false;
	}
	void *pRootHeadPtr = pRootNodeList;
	void *pKeyBeginPtr = pRootNodeList->KeyList;
	void *pValBeginPtr = pRootNodeList->ValList;

	void *pKeyNextList = nullptr;
	void *pValNextList = nullptr;

	while (pRootNodeList!=nullptr)
	{
		if (strcmp((char *)pRootNodeList->Root, root) == 0)
		{
			while (pRootNodeList->KeyList!=nullptr)
			{
				if (strcmp((char *)pRootNodeList->KeyList->Element, key) == 0)
				{
					memcpy(value, pRootNodeList->ValList->Element, AN_PARAMLEN_MAX);

					if (pKeyNextList&&pValNextList)
					{
						pRootNodeList->KeyList = (ElementList*)pKeyNextList;
						pRootNodeList->ValList = (ElementList*)pValNextList;
					}
					
					pRootNodeList = (RootNodeList*)pRootHeadPtr;
					pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
					pRootNodeList->ValList = (ElementList*)pValBeginPtr;
					return true;
				}

				pRootNodeList->KeyList = pRootNodeList->KeyList->nextElement;
				pRootNodeList->ValList = pRootNodeList->ValList->nextElement;
			}
		}
		pRootNodeList = pRootNodeList->nextRootNode;
		if (pRootNodeList)
		{
			pKeyNextList = pRootNodeList->KeyList;
			pValNextList = pRootNodeList->ValList;
		}
	}
	pRootNodeList = (RootNodeList*)pRootHeadPtr;
	pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
	pRootNodeList->ValList = (ElementList*)pValBeginPtr;
	return false;
}

bool An::InitFileReader::Set(const char * root, const char * key, const char * value)
{
	if (pRootNodeList == nullptr)
	{
		value = nullptr;
		return false;
	}
	void *pRootHeadPtr = pRootNodeList;
	void *pKeyBeginPtr = pRootNodeList->KeyList;
	void *pValBeginPtr = pRootNodeList->ValList;

	void *pKeyNextList = nullptr;
	void *pValNextList = nullptr;

	while (pRootNodeList!= nullptr)
	{
		if (strcmp((char *)pRootNodeList->Root, root) == 0)
		{
			while (pRootNodeList->KeyList!= nullptr)
			{
				if (strcmp((char *)pRootNodeList->KeyList->Element, key) == 0)
				{
					memcpy(pRootNodeList->ValList->Element,value,AN_PARAMLEN_MAX);
					if (pKeyNextList&&pValNextList)
					{
						pRootNodeList->KeyList = (ElementList*)pKeyNextList;
						pRootNodeList->ValList = (ElementList*)pValNextList;
					}

					pRootNodeList = (RootNodeList*)pRootHeadPtr;
					pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
					pRootNodeList->ValList = (ElementList*)pValBeginPtr;
					return true;
				}
				pRootNodeList->KeyList = pRootNodeList->KeyList->nextElement;
				pRootNodeList->ValList = pRootNodeList->ValList->nextElement;
			}
		}
		pRootNodeList = pRootNodeList->nextRootNode;
		if (pRootNodeList)
		{
			pKeyNextList = pRootNodeList->KeyList;
			pValNextList = pRootNodeList->ValList;
		}
	}
	pRootNodeList = (RootNodeList*)pRootHeadPtr;
	pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
	pRootNodeList->ValList = (ElementList*)pValBeginPtr;
	return false;
}

void InitFileReader::Analyse()
{
	void *pLineBeginPtr = nullptr;
	void *pRootBeginPtr = nullptr;
	void *pKeyBeginPtr = nullptr;
	void *pValBeginPtr = nullptr;

	pLineBeginPtr = pLineTextList;

	while (pLineTextList!=nullptr)
	{
		if (pLineTextList->Text[0] == '#' || pLineTextList->Text[0] == ';')
		{
			pLineTextList = pLineTextList->nextLineText;
			continue;
		}
		int len = strlen((const char *)pLineTextList->Text);
		if (pLineTextList->Text[0] == '['&&pLineTextList->Text[len-1]==']')
		{
			if (pRootNodeList == nullptr)
			{
				pRootNodeList = new RootNodeList();
				pRootBeginPtr = pRootNodeList;
				memcpy(pRootNodeList->Root, pLineTextList->Text + 1, len - 2);
			}
			else
			{
				if (pRootNodeList->KeyList != nullptr)
				{
					pRootNodeList->KeyList= (ElementList*)pKeyBeginPtr;
					pRootNodeList->ValList= (ElementList*)pValBeginPtr;
				}
				RootNodeList *rootList=new RootNodeList();
				memcpy(rootList->Root, pLineTextList->Text + 1, len - 2);
				pRootNodeList->nextRootNode = rootList;
				pRootNodeList = rootList;
			}
		}
		else if (strcmp((const char *)pLineTextList->Text, "=") > 0)
		{
			len = strlen((const char *)pLineTextList->Text);
			int Pos = strFind('=', pLineTextList->Text);
			if (Pos > 0)
			{
				if (pRootNodeList->KeyList == nullptr)
				{
					pRootNodeList->KeyList = new ElementList();
					pRootNodeList->ValList = new ElementList();
					pKeyBeginPtr = pRootNodeList->KeyList;
					pValBeginPtr = pRootNodeList->ValList;
					memcpy(pRootNodeList->KeyList->Element, pLineTextList->Text, Pos);
					memcpy(pRootNodeList->ValList->Element, pLineTextList->Text+ Pos+1, len-Pos-1);
				}
				else
				{
					ElementList *keyList = new ElementList();
					ElementList *valList = new ElementList();
					memcpy(keyList->Element, pLineTextList->Text, Pos);
					memcpy(valList->Element, pLineTextList->Text + Pos + 1, len - Pos - 1);
					pRootNodeList->KeyList->nextElement = keyList;
					pRootNodeList->ValList->nextElement = valList;
					pRootNodeList->KeyList = keyList;
					pRootNodeList->ValList = valList;
				}
			}
			
		}
		pLineTextList = pLineTextList->nextLineText;
	}
	if (pRootNodeList->KeyList != nullptr)
	{
		pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
		pRootNodeList->ValList = (ElementList*)pValBeginPtr;
	}
	pRootNodeList = (RootNodeList*)pRootBeginPtr;
	pLineTextList = (LineTextList*)pLineBeginPtr;
}

void InitFileReader::Release()
{
	if (pRootNodeList!=nullptr)
	{
		RootNodeList*n = nullptr, *m = nullptr;
		n = pRootNodeList;
		while (n!= nullptr)
		{
			m = n->nextRootNode;
			/
			ElementList *p = nullptr, *q = nullptr;
			p = n->KeyList;
			while (p!= nullptr)
			{
				q = p->nextElement;
				delete p;
				p = q;
			}
			///
			p = nullptr;
			q = nullptr;
			p = n->ValList;
			while (p!= nullptr)
			{
				q = p->nextElement;
				delete p;
				p = q;
			}
			delete n;
			n = m;
		}
		pRootNodeList = nullptr;
	}
	
	if (pLineTextList != nullptr)
	{
		delete pLineTextList;
		pLineTextList = nullptr;
	}	
}

TEXTCODETYPE InitFileReader::GetCodeType(const char * filePath)
{
	TEXTCODETYPE type = TEXTCODETYPE::TEXT_UNKNOW;
	type=check_text_encode(filePath);
	return type;
}


InitFileWriter::InitFileWriter()
{
	writeStream = nullptr;
}

InitFileWriter::~InitFileWriter()
{
	if (writeStream != nullptr)
	{
		delete writeStream;
		writeStream = nullptr;
	}
}

bool InitFileWriter::CreateWriter(const char * path)
{
	if (writeStream != nullptr)
	{
		delete writeStream;
		writeStream = nullptr;
	}
	writeStream = new std::ofstream();
	writeStream->open(path, std::ios::out);
	if (writeStream->is_open())
		return true;
	return false;
}

bool InitFileWriter::Write(const char * data)
{
	int len = strlen(data);
	return Write(data,len);
}

bool InitFileWriter::Write(const char * data, int length)
{
	if (!writeStream || !writeStream->is_open())
		return false;
	*writeStream << data << std::endl;
	//writeStream->write(data, length);
	return true;
}

bool InitFileWriter::Flush()
{
	if (!writeStream || !writeStream->is_open())
		return false;
	writeStream->flush();
	writeStream->close();
	return true;
}

bool InitFileWriter::Flush(LineTextList * pLineTextList, RootNodeList * pRootNodeList)
{
	if (!writeStream || !writeStream->is_open()|| !pLineTextList||!pRootNodeList)
		return false;

	void *pLineBeginPtr = pLineTextList;
	void *pRootHeadPtr = pRootNodeList;

	char RootName[AN_PARAMLEN_MAX];

	while (pLineTextList!=nullptr)
	{
		if (pLineTextList->Text[0] == '#' || pLineTextList->Text[0] == ';')
		{
			Write((char *)pLineTextList->Text);
		}
		else if (pLineTextList->Text[0] == '[')
		{
			int len = strlen((const char *)pLineTextList->Text);
			memset(RootName, 0, AN_PARAMLEN_MAX);
			memcpy(RootName, pLineTextList->Text + 1, len - 2);
			Write((char *)pLineTextList->Text);
		}
		else if (strcmp((const char *)pLineTextList->Text, "=") > 0)
		{
			int len = strlen((const char *)pLineTextList->Text);
			int Pos = strFind('=', pLineTextList->Text);
			if (Pos > 0)
			{
				char KeyName[AN_PARAMLEN_MAX],buff[AN_PARAMLEN_MAX];
				memset(KeyName,0, AN_PARAMLEN_MAX);
				memset(buff, 0, AN_PARAMLEN_MAX);
				memcpy(KeyName, pLineTextList->Text, Pos);
				if (Find(RootName, KeyName, buff, pRootNodeList))
				{
					len = strlen(KeyName) + strlen("=") + 1;
					strcat_s(KeyName, len, "=");
					len = strlen(KeyName) + strlen(buff) + 1;
					strcat_s(KeyName, len, buff);
					Write(KeyName);
				}
			}
			
		}	
		pLineTextList = pLineTextList->nextLineText;
	}
	Flush();
	pLineTextList = (LineTextList *)pLineBeginPtr;
	pRootNodeList = (RootNodeList *)pRootHeadPtr;
	return true;
}

bool InitFileWriter::Find(const char * root, const char * key, char * value, RootNodeList *pRootNodeList)
{
	if (pRootNodeList == nullptr)
	{
		value = nullptr;
		return false;
	}
	void *pRootHeadPtr = pRootNodeList;

	void *pKeyBeginPtr = pRootNodeList->KeyList;
	void *pValBeginPtr = pRootNodeList->ValList;

	void *pKeyNextList = nullptr;
	void *pValNextList = nullptr;

	while (pRootNodeList!= nullptr)
	{
		if (strcmp((char *)pRootNodeList->Root, root) == 0)
		{
			while (pRootNodeList->KeyList != nullptr)
			{
				if (strcmp((char *)pRootNodeList->KeyList->Element, key) == 0)
				{
					memcpy(value, pRootNodeList->ValList->Element, AN_PARAMLEN_MAX);
					if (pKeyNextList&&pValNextList)
					{
						pRootNodeList->KeyList = (ElementList*)pKeyNextList;
						pRootNodeList->ValList = (ElementList*)pValNextList;
					}
					pRootNodeList = (RootNodeList*)pRootHeadPtr;
					pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
					pRootNodeList->ValList = (ElementList*)pValBeginPtr;
					return true;
				}
				pRootNodeList->KeyList = pRootNodeList->KeyList->nextElement;
				pRootNodeList->ValList = pRootNodeList->ValList->nextElement;
			}
		}

		pRootNodeList = pRootNodeList->nextRootNode;
		if (pRootNodeList)
		{
			pKeyNextList = pRootNodeList->KeyList;
			pValNextList = pRootNodeList->ValList;
		}
	}
	pRootNodeList = (RootNodeList*)pRootHeadPtr;
	pRootNodeList->KeyList = (ElementList*)pKeyBeginPtr;
	pRootNodeList->ValList = (ElementList*)pValBeginPtr;
	return false;
}

int strFind(char key, unsigned char * Src)
{
	int len = strlen((const char *)Src);
	if (len <= 0)return -1;
	for (int i = 0; i < len; i++)
	{
		if (Src[i] == key)
		{
			return i;
		}
	}
	return -1;
}

void getLine(std::ifstream & stream, unsigned char * line)
{
	int idx = 0;
	char temp[AN_PARAMLEN_MAX];
	memset(temp, 0, AN_PARAMLEN_MAX);
	while (stream.get(temp[idx]) && temp[idx] != '\n')
	{
		idx++;
	}
	memcpy(line, temp, idx);
}
std::string  UTF8ToGB(const char* str)
{
	std::string result;
	WCHAR *strSrc;
	LPSTR szRes;

	//获得临时变量的大小
	int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	strSrc = new WCHAR[i + 1];
	MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);

	//获得临时变量的大小
	i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
	szRes = new CHAR[i + 1];
	WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

	result = szRes;
	delete[]strSrc;
	delete[]szRes;

	return result;
}
///Code From:https://www.cnblogs.com/rcg714786690/p/14246669.html
//检查是否为无BOM的UTF8
bool check_utf8_without_bom(std::string &file_name)
{
	std::ifstream file_in;
	file_in.open(file_name, std::ios::in);

	if (!file_in.is_open())
	{
		//cout << "打开文件失败" << endl;
		return false;
	}

	std::stringstream buffer;
	buffer << file_in.rdbuf();
	file_in.close();
	std::string text = buffer.str();

	size_t len = text.size();
	int n = 0;
	unsigned char ch;
	bool b_all_ascii = true;

	//0x00-0x7F为ASCII码范围

	for (size_t i = 0; i < len; ++i)
	{
		ch = text[i];

		if ((ch & 0x80) != 0)
		{
			b_all_ascii = false;
		}

		if (n == 0)
		{
			if (ch >= 0x80)
			{
				if (ch >= 0xFC && ch <= 0xFD)
				{
					n = 6;
				}
				else if (ch >= 0xF8)
				{
					n = 5;
				}
				else if (ch >= 0xF0)
				{
					n = 4;
				}
				else if (ch >= 0xE0)
				{
					n = 3;
				}
				else if (ch >= 0xC0)
				{
					n = 2;
				}
				else
				{
					return false;
				}
				n--;
			}
		}
		else
		{
			if ((ch & 0xC0) != 0x80)//在UTF-8中,以位模式10开始的所有字节是多字节序列的后续字节
			{
				return false;
			}
			n--;
		}
	}

	if (n > 0)
	{
		return false;
	}

	if (b_all_ascii)
	{
		return false;
	}

	return true;
}

TEXTCODETYPE check_text_encode(std::string file_name)
{
	/*
	ANSI                     无格式定义                        对于中文编码格式是GB2312;
	Unicode little endian    文本里前两个字节为FF FE           字节流是little endian
	Unicode big endian       文本里前两个字节为FE FF           字节流是big endian
	UTF-8带BOM               前两字节为EF BB,第三字节为BF     带BOM
	UTF-8不带BOM             无格式定义,需另加判断               不带BOM
	*/

	std::ifstream file_in(file_name, std::ios::binary);
	if (!file_in.is_open())
	{
		//cout << "打开文件失败" << endl;;
		return TEXT_UNKNOW;
	}

	int head;
	unsigned char ch;
	file_in.read((char*)&ch, sizeof(ch));
	head = ch << 8;
	file_in.read((char*)&ch, sizeof(ch));
	head |= ch;

	file_in.close();
	TEXTCODETYPE result_code= TEXTCODETYPE::TEXT_UNKNOW;
	switch (head)
	{
	case 0xFFFE:
		//result_code = TEXT_UTF16_LE;
		break;
	case 0xFEFF:
		//result_code = TEXT_UTF16_BE;
		break;
	case 0xEFBB:
		//result_code = TEXT_UTF8_BOM;
		break;
	default:
		if (check_utf8_without_bom(file_name))
			result_code = TEXTCODETYPE::TEXT_UTF8;
		else
			result_code = TEXTCODETYPE::TEXT_ANSI;
		break;
	}
	return result_code;
}

main.cpp

#include "AnInitFile.h"
An::AnInitFile cfg;
cfg.Open("config.ini");

char szBuff[AN_PARAMLEN_MAX];
ZeroMemory(szBuff, AN_PARAMLEN_MAX);
cfg.GetParam("Serial", "Com", szBuff);

char szBuff2[10];
ZeroMemory(szBuff2, 10);
cfg.GetParam("Serial", "Com", szBuff2);

Guess you like

Origin blog.csdn.net/qq_36251561/article/details/119872931