首页 > 编程语言 >C++解析ini文件

C++解析ini文件

时间:2024-08-06 18:24:24浏览次数:10  
标签:const Section C++ char pCurIniNode ini Key return 解析

目录

这篇文章简单讨论一下ini文件。

一.什么是ini文件

ini文件其实就是一种配置文件,常见于Windows的系统配置文件,当然也可以是其他用途,你的用法你说了算。

二.ini文件的格式一般是什么样的

看个例子

;这是注释
[section1]
key1=value1
key2=value2
[section2]
key3=value3
key4=value4

ini文件包括节(section)、键值对(通常称为参数,parameter)和注释(comment)。

1.节

1.每一个section包含若干个parameter。

2.每一个section独占一行,名称由[]包围,比如[sectionName]。

3.每一个section的生效范围,从当前section开始到下一个section的开始(或者文件结尾),这其中所有的parameter都属于这个section。

4.section不应该重复。

2.参数

1.parameter以键值对的形式存在,比如key=value。

2.同一个section中的parameter不应该重复。

3.注释

1.注释用;表示。

2.注释独占一行。

三.C++实现ini文件的解析

重点来了,这里展示一种C++解析ini文件的简易代码写法,主要是描述一种解析的思维,大致测试过了。

直接看代码

//inifile.h

#ifndef INIFILE_H
#define INIFILE_H

#include <iostream>
#include <string>

#define ERR_MES_1 "输入值不合法"
#define ERR_MES_2 "打开文件失败"
#define ERR_MES_3 "配置项不存在"

const char TYPE_NULL = '0';
const char TYPE_SECTION = '1';
const char TYPE_PARAMETER = '2';
const char TYPE_COMMENT = '3';

typedef struct  IniNode
{
	char m_Type;
	std::string m_Text;
	IniNode* m_pPrev;
	IniNode* m_pNext;

}IniNode, * pIniNode;

typedef struct IniSec
{
	pIniNode m_pSection;
	pIniNode m_pParameter;
	std::string m_SectionText;
	std::string m_ParameterText;
}IniSec, * pIniSec;

class IniFile
{
public:
	IniFile();
	~IniFile();
	bool ReadIniFile(const char* FilePathName);
	bool WriteIniFile(const char* FilePathName);
	bool WriteParameter(const char* Section, const char* Key, const char* Value);
	bool WriteParameter(const char* Section, const char* Key, const bool Value);
	bool WriteParameter(const char* Section, const char* Key, const int Value);
	bool WriteParameter(const char* Section, const char* Key, const double Value);
	std::string ReadParameter(const char* Section, const char* Key, const char* Default);
	bool ReadParameter(const char* Section, const char* Key, const bool Default);
	int ReadParameter(const char* Section, const char* Key, const int Default);
	double ReadParameter(const char* Section, const char* Key, const double Default);
	bool DeleteParameter(const char* Section, const char* Key);
	bool DeleteSection(const char* Section);
	int GetErrCode();
	std::string GetErrMes();

protected:
	void FreeIniList();
	void CreateIniNode();
	void Trim(char* Buffer);
	pIniNode FindSection(const char* Section);
	pIniSec FindParameter(const char* Section, const char* Key);
	void AddIniNode(char Type, const char* Text);
	bool WriteParameterPublic(const char* Section, const char* Key, const char* Value);
	std::string ReadParameterPublic(const char* Section, const char* Key, const char* Default);

private:
	FILE* m_pIniFileHandle;
	pIniNode m_pIniList;
	pIniNode m_pCurIniNode;
	int m_LastErrCode;
	std::string m_LastErrMes;
};

#endif // !INIFILE_H
//inifile.cpp

#include "inifile.h"

IniFile::IniFile()
{
	m_LastErrCode = 0;
	m_LastErrMes = "";
	m_pCurIniNode = nullptr;
	m_pIniFileHandle = nullptr;
	m_pIniList = nullptr;
}

IniFile::~IniFile()
{
	FreeIniList();
	fclose(m_pIniFileHandle);
}

int IniFile::GetErrCode()
{
	return m_LastErrCode;
}

std::string IniFile::GetErrMes()
{
	return m_LastErrMes;
}

bool IniFile::ReadIniFile(const char* FilePathName)
{
	if (!strcmp(FilePathName, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return false;
	}
	if (!(m_pIniFileHandle = fopen(FilePathName, "r")))
	{
		m_LastErrCode = 2;
		m_LastErrMes = ERR_MES_2;
		return false;
	}
	FreeIniList();
	char filebuf[256] = { 0 };
	char* pchr = nullptr;
	while (fgets(filebuf, 256, m_pIniFileHandle))
	{
		Trim(filebuf);
		CreateIniNode();

		if (';' == filebuf[0])
		{
			m_pCurIniNode->m_Type = TYPE_COMMENT;
		}
		else if ('[' == filebuf[0] && strchr(filebuf, ']'))
		{
			m_pCurIniNode->m_Type = TYPE_SECTION;

		}
		else if (strchr(filebuf, '='))
		{
			m_pCurIniNode->m_Type = TYPE_PARAMETER;

		}
		else
		{
			m_pCurIniNode->m_Type = TYPE_NULL;
		}
		m_pCurIniNode->m_Text = filebuf;
	}

	fclose(m_pIniFileHandle);
	return true;
}

bool IniFile::WriteIniFile(const char* FilePathName)
{
	if (!strcmp(FilePathName, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return false;
	}
	char FilePathNameBat[256] = { 0 };
	strcpy(FilePathNameBat, FilePathName);
	strcat(FilePathNameBat, ".bak");
	FILE* FileIniTemp = fopen(FilePathName, "r");
	FILE* FileBatTemp = fopen(FilePathNameBat, "w");
	if (!FileIniTemp || !FileBatTemp)
	{
		m_LastErrCode = 2;
		m_LastErrMes = ERR_MES_2;
		return false;
	}
	char FileStr[256] = { 0 };
	while (fgets(FileStr, 256, FileIniTemp))
	{
		fprintf(FileBatTemp, "%s", FileStr);
	}
	fclose(FileIniTemp);
	fclose(FileBatTemp);

	if (!(m_pIniFileHandle = fopen(FilePathName, "w")))
	{
		m_LastErrCode = 2;
		m_LastErrMes = ERR_MES_2;
		return false;
	}
	m_pCurIniNode = m_pIniList;

	while (m_pCurIniNode)
	{
		fprintf(m_pIniFileHandle, "%s\n", m_pCurIniNode->m_Text.data());
		m_pCurIniNode = m_pCurIniNode->m_pNext;
	}

	fclose(m_pIniFileHandle);
	return true;
}

bool IniFile::WriteParameter(const char* Section, const char* Key, const char* Value)
{
	return WriteParameterPublic(Section, Key, Value);
}

bool IniFile::WriteParameter(const char* Section, const char* Key, const bool Value)
{
	char StrValue[256] = { 0 };
	itoa(Value, StrValue, 2);
	return WriteParameterPublic(Section, Key, StrValue);
}

bool IniFile::WriteParameter(const char* Section, const char* Key, const int Value)
{
	char StrValue[256] = { 0 };
	itoa(Value, StrValue, 10);
	return WriteParameterPublic(Section, Key, StrValue);
}

bool IniFile::WriteParameter(const char* Section, const char* Key, const double Value)
{
	char StrValue[256] = { 0 };
	sprintf_s(StrValue, "%f", Value);
	return WriteParameterPublic(Section, Key, StrValue);
}

std::string IniFile::ReadParameter(const char* Section, const char* Key, const char* Default)
{
	return ReadParameterPublic(Section, Key, Default);
}

bool IniFile::ReadParameter(const char* Section, const char* Key, const bool Default)
{
	char DefaultString[2] = { 0 };
	if (Default)
	{
		DefaultString[0] = '1';
	}
	else
	{
		DefaultString[0] = '0';
	}
	std::string RetStr = ReadParameterPublic(Section, Key, DefaultString);
	return atoi(RetStr.data());
}

int IniFile::ReadParameter(const char* Section, const char* Key, const int Default)
{
	char DefaultString[256] = { 0 };
	itoa(Default, DefaultString, 10);
	std::string RetStr = ReadParameterPublic(Section, Key, DefaultString);
	return atoi(RetStr.data());
}

double IniFile::ReadParameter(const char* Section, const char* Key, const double Default)
{
	char DefaultString[256] = { 0 };
	sprintf_s(DefaultString, "%f", Default);
	std::string RetStr = ReadParameterPublic(Section, Key, DefaultString);
	return atof(RetStr.data());
}

bool IniFile::DeleteParameter(const char* Section, const char* Key)
{
	if (!strcmp(Section, "") || !strcmp(Key, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return false;
	}
	pIniSec pIniSecTemp = FindParameter(Section, Key);
	if (!pIniSecTemp)
	{
		m_LastErrCode = 3;
		m_LastErrMes = ERR_MES_3;
		return false;
	}
	m_pCurIniNode = pIniSecTemp->m_pParameter;
	m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext;
	if (m_pCurIniNode->m_pNext)
	{
		m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev;
	}

	delete m_pCurIniNode;
	delete pIniSecTemp;
	return true;
}

bool IniFile::DeleteSection(const char* Section)
{
	if (!strcmp(Section, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return false;
	}
	pIniNode pSectionIniNodeTemp = FindSection(Section);
	if (!pSectionIniNodeTemp)
	{
		m_LastErrCode = 3;
		m_LastErrMes = ERR_MES_3;
		return false;
	}
	pIniNode pCurNextIniNode = nullptr;
	m_pCurIniNode = pSectionIniNodeTemp->m_pNext;
	while (m_pCurIniNode && m_pCurIniNode->m_Type == TYPE_PARAMETER)
	{
		pCurNextIniNode = m_pCurIniNode->m_pNext;
		m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext;
		if (m_pCurIniNode->m_pNext)
		{
			m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev;
		}
		delete m_pCurIniNode;
		m_pCurIniNode = pCurNextIniNode;
	}
	m_pCurIniNode = pSectionIniNodeTemp;
	m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext;
	if (m_pCurIniNode->m_pNext)
	{
		m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev;
	}
	delete m_pCurIniNode;
	return true;
}

void IniFile::FreeIniList()
{
	if (nullptr == m_pIniList)
	{
		return;
	}
	pIniNode pNextIniNodeTemp = nullptr;
	while (nullptr != m_pIniList)
	{
		pNextIniNodeTemp = m_pIniList->m_pNext;
		delete m_pIniList;
		m_pIniList = pNextIniNodeTemp;
	}
}

void IniFile::CreateIniNode()
{
	pIniNode pIniNodeTemp = new IniNode;
	memset(pIniNodeTemp, 0, sizeof(IniNode));


	if (nullptr == m_pIniList)
	{
		m_pIniList = pIniNodeTemp;
		m_pCurIniNode = pIniNodeTemp;
		return;
	}

	m_pCurIniNode = m_pIniList;
	while (m_pCurIniNode->m_pNext)
	{
		m_pCurIniNode = m_pCurIniNode->m_pNext;
	}

	m_pCurIniNode->m_pNext = pIniNodeTemp;
	pIniNodeTemp->m_pPrev = m_pCurIniNode;

	m_pCurIniNode = pIniNodeTemp;
}

void IniFile::Trim(char* Buffer)
{
	int i = 0;
	int len = strlen(Buffer);
	for (i = len - 1; i >= 0; i--)
	{
		if (' ' != Buffer[i] && '\t' != Buffer[i] && '\n' != Buffer[i])
		{
			break;
		}
		Buffer[i] = 0;
	}
	for (i = 0; i < len; i++)
	{
		if (' ' != Buffer[i] && '\t' != Buffer[i] && '\n' != Buffer[i])
		{
			break;
		}
	}
	if (0 != i)
	{
		strncpy(Buffer, Buffer + i, len - i);
		Buffer[len - i] = 0;
	}
}

pIniNode IniFile::FindSection(const char* Section)
{
	m_pCurIniNode = m_pIniList;
	while (m_pCurIniNode)
	{
		if (!strcmp(m_pCurIniNode->m_Text.data(), Section) && m_pCurIniNode->m_Type == TYPE_SECTION)
		{
			return m_pCurIniNode;
		}
		m_pCurIniNode = m_pCurIniNode->m_pNext;
	}

	return nullptr;
}

pIniSec IniFile::FindParameter(const char* Section, const char* Key)
{
	m_pCurIniNode = m_pIniList;
	pIniSec pIniSecTemp = new IniSec;
	char Buf[256] = { 0 };
	char* pChr = nullptr;

	while (m_pCurIniNode)
	{
		if (!strcmp(m_pCurIniNode->m_Text.data(), Section) && m_pCurIniNode->m_Type == TYPE_SECTION)
		{
			pIniSecTemp->m_pSection = m_pCurIniNode;
			pIniSecTemp->m_SectionText = m_pCurIniNode->m_Text;
			m_pCurIniNode = m_pCurIniNode->m_pNext;

			while (m_pCurIniNode && m_pCurIniNode->m_Type == TYPE_PARAMETER)
			{
				strcpy(Buf, m_pCurIniNode->m_Text.data());
				if (pChr = strchr(Buf, '='))
				{
					*pChr = 0;
					Trim(Buf);
					if (!strcmp(Buf, Key))
					{
						pIniSecTemp->m_pParameter = m_pCurIniNode;
						pIniSecTemp->m_ParameterText = m_pCurIniNode->m_Text;
						return pIniSecTemp;
					}
				}
				m_pCurIniNode = m_pCurIniNode->m_pNext;
			}
			break;
		}
		m_pCurIniNode = m_pCurIniNode->m_pNext;
	}

	delete pIniSecTemp;
	return nullptr;
}

void IniFile::AddIniNode(char Type, const char* Text)
{


	if (Type == TYPE_SECTION)
	{
		m_pCurIniNode->m_Type = TYPE_SECTION;
		m_pCurIniNode->m_Text = Text;
	}
	else if (Type == TYPE_PARAMETER)
	{
		m_pCurIniNode->m_Type = TYPE_PARAMETER;
		m_pCurIniNode->m_Text = Text;
	}
	return;
}

bool IniFile::WriteParameterPublic(const char* Section, const char* Key, const char* Value)
{
	if (!strcmp(Section, "") || !strcmp(Key, "") || !strcmp(Value, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return false;
	}

	char Parameter[256] = { 0 };
	strcpy(Parameter, Key);
	strcat(Parameter, "=");
	strcat(Parameter, Value);
	pIniNode pSectionNodeTemp = FindSection(Section);
	pIniSec pIniSecTemp = nullptr;
	if (!pSectionNodeTemp)
	{
		CreateIniNode();
		AddIniNode(TYPE_SECTION, Section);
		CreateIniNode();
		AddIniNode(TYPE_PARAMETER, Parameter);
	}
	else
	{
		if (!(pIniSecTemp = FindParameter(Section, Key)))
		{
			pIniNode pIniNodeTemp = new IniNode;
			memset(pIniNodeTemp, 0, sizeof(IniNode));

			pIniNodeTemp->m_pNext = pSectionNodeTemp->m_pNext;
			pSectionNodeTemp->m_pNext = pIniNodeTemp;
			if (pIniNodeTemp->m_pNext)
			{
				pIniNodeTemp->m_pNext->m_pPrev = pIniNodeTemp;
			}
			pIniNodeTemp->m_pPrev = pSectionNodeTemp;
			m_pCurIniNode = pIniNodeTemp;
			AddIniNode(TYPE_PARAMETER, Parameter);
		}
		else
		{
			m_pCurIniNode = pIniSecTemp->m_pParameter;
			AddIniNode(TYPE_PARAMETER, Parameter);
		}
	}
	delete pIniSecTemp;
	pIniSecTemp = nullptr;

	return true;
}

std::string IniFile::ReadParameterPublic(const char* Section, const char* Key, const char* Default)
{
	if (!strcmp(Section, "") || !strcmp(Key, "") || !strcmp(Default, ""))
	{
		m_LastErrCode = 1;
		m_LastErrMes = ERR_MES_1;
		return {};
	}
	std::string Ret;
	pIniSec pIniSecTemp = FindParameter(Section, Key);
	char* pChr = nullptr;
	if (pIniSecTemp)
	{
		char Buf[256] = { 0 };
		strcpy(Buf, pIniSecTemp->m_ParameterText.data());
		if (pChr = strchr(Buf, '='))
		{
			strcpy(Buf, pChr + 1);
		}

		Ret = Buf;

	}
	else
	{
		Ret = Default;
	}

	delete pIniSecTemp;
	return Ret;
}

四.其他

说一个小技巧,如果担心格式写的不对,可以用熟悉的编辑器中设置文档格式这个功能调整一下,当然调整之后也要进行确认。

标签:const,Section,C++,char,pCurIniNode,ini,Key,return,解析
From: https://blog.csdn.net/2401_85919417/article/details/140903234

相关文章

  • Stable Fast 3D技术解析 - Stability AI推出0.5秒将图片转为3D模型
    一、介绍StableFast3D,由StabilityAI推出,是一项颠覆性的3D建模技术,它通过AI算法将单张图片迅速转换为高质量的3D模型,极大地缩短了传统3D建模的时间,同时保持了模型的细节和真实感。关键要点StableFast3D能在仅0.5秒内从单张图片生成高质量的3D资产。S......
  • [AGC005B] Minimum Sum 题解
    题目传送门看到这道题很多人用单调栈,其实用笛卡尔树本质差不多,但是思维难度更小。不知道笛卡尔树的同学可以看这里简单说来,笛卡尔树的一个子树可以代表一个区间,且左子树上点的下标小于根节点,右子树上点的坐标大于根节点。这道题要求所有子区间的\(\texttt{min}\)值之和,其实......
  • 【C++/STL】map和set的封装(红黑树)
     ......
  • minio安装(rpm方式)
    环境:OS:Centos7 1.下载minio下载地址如下wgethttps://dl.min.io/server/minio/release/linux-amd64/ 2.安装[root@host135milvus]#rpm-ivhminio-20240803043323.0.0-1.x86_64.rpmPreparing...#################################[100%]......
  • #GPT-4o mini 来袭:开发者如何驾驭新一代AI模型?#
    要有效驾驭GPT-4oMini这一新一代AI模型,开发者需要注意以下几个关键点:理解模型特性:GPT-4oMini以高效性和精确性著称,这意味着在项目中使用时,应充分利用其高效率来减少计算时间,同时确保输出的准确度。API集成:开发者需要熟悉OpenAI提供的API文档,学会如何通过API调用来......
  • 利用miniprogram-ci工具实现一键上传微信小程序代码
    本文由ChatMoney团队出品利用miniprogram-ci工具在后台实现一键上传微信小程序代码,避免了微信开发者工具的繁琐。一、部署node环境我用的是宝塔,可以直接在宝塔上安装Node.js版本管理器二、安装miniprogram-cinpminstallminiprogram-ci--save安装在指定文件夹里,这个......
  • 基于capl的hex文件解析
    目录前言一、IntelHEX文件格式简介二、CAPL语言概述三、基于CAPL的hex文件解析步骤四、注意事项前言基于CAPL(CommunicationAccessProgrammingLanguage)的hex文件解析主要涉及对IntelHEX文件格式的理解和CAPL编程语言的运用。IntelHEX文件是一种由符合IntelHEX......
  • 关于BeautifulSoup解析
    一.导包frombs4importBeautifulSoup二.建立BeautifulSoup的HTML内容main_page=BeautifulSoup(content,"html.parser")        由于没有安装lxml包,可以直接引入html.parser来完成1.拿标签    (1):语法find(“标签名”,attrs={属性键:属性值}), 获......
  • C++学习笔记----Strings与String View(4)-- 字符串操作
        今天讲点简单易懂的,字符串操作,当然了,不是全部,列出几个典型的字符串操作,完整地可以参考相关资料,网上一搜一把哦。substr(pos,len):返回特定位置pos,特定长度的子字符串。find(str):返回字符串的位置,如未找到则返回string::npos。replace(pos,len,str):用新的字符串str......
  • C++学习笔记----Strings与String View(5)-- 字符串文本
    今天我们继续来学习C++的string:1、字符串文本    字符串文本通常会被解析成字符指针常量(constchar*)或者字符数组常量(constchar[]),如果想要达到声名std::string常量的目的,则需要在声明时在常量字符串后加一个s,示例如下: autostring1{"HelloWorld"}; //string1为......