C++解析ini文件

ops/2024/9/29 5:22:54/

目录

  • 一.什么是ini文件
  • 二.ini文件的格式一般是什么样的
    • 1.节
    • 2.参数
    • 3.注释
  • 三.C++实现ini文件的解析
  • 四.其他

这篇文章简单讨论一下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;
}

四.其他

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


http://www.ppmy.cn/ops/89963.html

相关文章

unity2D游戏开发17战斗精灵

导入 将PlayerFight32x32.png拖Player文件夹进去 设置属性 创建动画剪辑 选中前四帧,右键Create|Animation,将动画命名为player-ire-east 其他几个动画也创建好后,将其拖到Animations|Animations文件夹 选中PlayerController,再点击Animator 创建新的Blend Tree Graph,并重…

【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载 本章将分享C增加的几种常见特性&#xff0c;主要内容为引用与内联函数 | auto关键字与for循环 | 指针空值&#xff0c;这些知识看似很多&#xff0c;实际也不少。本章篇幅长&#…

C语言宠物系统

功能有增加宠物信息&#xff0c;显示宠物信息&#xff0c;删除宠物信息&#xff0c;修改功能和排序功能&#xff0c;可以选择姓名排序&#xff0c;年龄排序&#xff0c;价格排序。进阶的功能有文件操作&#xff0c;动态内存开辟。。 test.c源文件 #include "Pet.h"v…

Spring框架中的IoC(Inversion of Control,控制反转)和DI

Spring框架中的IoC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;和DI&#xff08;Dependency Injection&#xff0c;依赖注入&#xff09;是其核心思想之一&#xff0c;它们共同实现了对象的创建、配置和依赖关系的注入&#xff0c;从而极大地提高了应用程…

数据面试问题的记录——7.29

技术问题&#xff1a; 1、SQL中的where和having的区别 where 是取数范围 having是聚合后的结果的筛选范围 2、Python中pass、continue、break的区别 都是循环中使用 pass不起作用&#xff0c;可以在没有实际运行内容时占位 continue继续执行循环 break停止整个循环 逻…

浅谈【C#】代码注册COM组件

在C#中注册COM组件通常涉及到使用regasm工具或者在代码中使用System.Runtime.InteropServices命名空间下的RegisterTypeForComClients方法。 下面是两种方法的简要说明和示例&#xff1a; 1、使用 regasm 工具 regasm 是一个命令行工具&#xff0c;用于将.NET程序集注册为CO…

DB-GPT_0.5.10安装__部署Qwen2-72b模型(Ubuntu)——报错记录

官网地址在这里——源码部署 (yuque.com)&#xff0c;英文地址——Source Code Deployment | DB-GPT (dbgpt.site) 官网给了三种部署方式&#xff1a;源码部署、Docker部署、Docker-Compose部署&#xff0c;这里我选择的部署方式是源码部署&#xff0c;Docker部署的教程我感觉…

Unity引擎简介

初探Unity引擎与C#编程&#xff1a;开发游戏的起点 引言 在当今游戏开发领域中&#xff0c;Unity引擎无疑是一颗耀眼的明星。它以其强大的功能和跨平台的优势&#xff0c;成为了许多开发者的首选工具。而作为Unity引擎的官方语言&#xff0c;C#&#xff08;C Sharp&#xff09…