C/C++ 操作ini文件(SinpleIni 跨平台库)
最近在学习时,发现自己还不会操作ini文件,想着以前工作时接触到的项目或多或少都要用到ini文件去保存初始化程序的数据;所以赶紧去网上搜索以下C/C++操作ini文件都有些什么库可以玩玩;搜索到有:
1. inih:这是C语言小巧的库,更适合嵌入式开发;
2. iniparser:这是C语言的库,挺方便使用的,开源,两个.h文件和两个.c文件,但只能在Linux中使用;
3. simpleini:这是C++的库,挺方便使用的,跨平台,开源,就两个.h文件和一个.c文件,且支持中文;
所以最后我选择了simpleini这个库去学习使用!
目录
一、介绍
1. ini介绍
2. simpleini介绍
二、下载
三、使用
1. 加载ini文件
2. 简单配置
3. 增
1). 添加一个新的节点(section)
2). 添加一个新的 key和value
4. 改
1). 修改值(value)
5. 删
1). 删除 key 和 value
2). 当最后一个key也被删除掉后,section1也会被删除
3). 删除整个节点(section)和其下的所有键(key)
6. 查
1). 将下图中的ini文件内容读取打印显示
2). 遍历ini文件的所有内容
3). 遍历所有节点(section)
4). 遍历指定节点的键(key)
5). 获取一个键对应多个值
6). 获取指定节点(section)里有多少键值
7. 保存
1). 保存到文件
2). 保存到C++字符串
8. 中文乱码问题
四、封装
configdef.h
iniconfig.h
iniconfig.cpp
测试代码:
五、总结
一、介绍
1. ini介绍
ini文件由 [section] 节点 和 key 键 和 value 值 构成。
例如一个简单的ini文件如下所示:
[message]
name = 张三
age = 25
height = 173.2; 这是一个注释[server]
ip = 127.0.0.1
port = 6666
message就是节点,节点下方就是它的键和值;server也是一个节点。
如果需要注释,使用英文分号 ' ; ' 即可。
2. simpleini介绍
一个跨平台库,提供了一个简单的API来读取和写入ini风格的配置文件。它支持ASCII、MBCS和Unicode格式的数据文件。它被明确设计为可移植到任何平台,并已在Windows, WinCE和Linux上进行了测试。使用MIT许可证作为开源和免费发布.
功能概述
- MIT许可允许在所有软件中免费使用(包括GPL和商业软件)
- 多平台(Windows 95到Windows 10、Windows CE、Linux、Unix)
- 加载和保存ini风格的配置文件
- 在所有平台上,配置文件可以使用任何换行格式
- 对文件格式的自由接受
- 没有section的键/值,没有值的键
- 删除部分、键和值周围的空白
- 支持多行值(嵌入换行字符的值)
- 可选支持同名的多个键
- 可选的不区分大小写的节和键(仅针对ASCII字符)
- 在文件加载时以相同的顺序保存部分和键
- 尽可能保留文件、节和键上的注释
- 同时支持char或wchar_t编程接口
- 同时支持MBCS(系统区域设置)和UTF-8文件编码
- 在Linux/Unix上,系统区域设置不需要是UTF-8才能加载UTF-8文件
- 在节、键、值和注释中支持非ascii字符
- 通过用户编写的转换器类支持非标准字符类型或文件编码
- 支持以编程方式添加/修改值
- 在大多数编译器中应该编译没有警告
二、下载
GitHub链接:GitHub - brofield/simpleini: Cross-platform C++ library providing a simple API to read and write INI-style configuration files
https://github.com/brofield/simpleini
gitte链接:
simpleini: SimpleIni 是一个跨平台的 C++ 库,提供一个简单的 API 用于操作 ini 配置文件 (gitee.com)
https://gitee.com/mirrors/simpleini

下载后解压

这三个文件可在 Window 或 Linux 环境去使用!
三、使用
以下介绍的用法,Linux和Window环境均可使用!
包含头文件:
#include "SimpleIni.h"
#define FILE_NAME "./test1.ini"
test1.ini内容如下:

1. 加载ini文件
// 定义ini文档对象
CSimpleIniA ini;// 加载ini文件
SI_Error rc;
rc = ini.LoadFile(FILE_NAME); // 另一种方式:SI_Error LoadFile(FILE * a_fpFile);
if (rc < 0) { printf("加载 %s ini 文件失败!\n", FILE_NAME);return -1;
}
rc返回值有以下这些:
using SI_Error = int;constexpr int SI_OK = 0; //!< No error
constexpr int SI_UPDATED = 1; //!< An existing value was updated
constexpr int SI_INSERTED = 2; //!< A new value was inserted// note: test for any error with (retval < 0)
constexpr int SI_FAIL = -1; //!< Generic failure
constexpr int SI_NOMEM = -2; //!< Out of memory error
constexpr int SI_FILE = -3; //!< File error (see errno for detail error)
2. 简单配置
// 设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式
ini.SetUnicode(true);// 是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值
ini.SetMultiKey(false);
3. 增
SetValue
参数一:节点
参数二:键
参数三:值
返回值:SI_Error (也就是int类型)
1). 添加一个新的节点(section)
// 添加一个新的 section
rc = ini.SetValue("section1", nullptr, nullptr);
if (rc < 0) { printf("添加section1失败!\n");return -1;
}

2). 添加一个新的 key和value
// 添加一个新的 key和value
rc = ini.SetValue("section1", "name", "张三");
if (rc < 0) {printf("添加name失败!\n");return -1;
}
//const char *name = ini.GetValue("section1", "name", "");
//printf("name = %s\n", name);ini.SetValue("section1", "age", "24");
ini.SetValue("section1", "sex", "男");
注意:如果name存在,则会将name键(key)对应的值(value)修改为张三;

还可以使用SetLongValue、SetDoubleValue、SetBoolValue去添加:
ini.SetLongValue("server", "length", 173);
ini.SetDoubleValue("server", "weight", 53.5);
ini.SetBoolValue("server", "vip", true);
4. 改
SetValue
参数一:节点
参数二:键
参数三:值
返回值:SI_Error (也就是int类型)
1). 修改值(value)
// 修改value,如果键(name)不存在则添加该 key和value
rc = ini.SetValue("section1", "name", "李四");
if (rc < 0) { printf("修改name失败!\n");return -1;
}
//const char *name = ini.GetValue("section1", "name");
//printf("name = %s\n", name);
注意:如果要修改的值对应的键不存在,则会添加改键和值到section1节点中!

貌似无法修改节点(section) 和 键(key),我没有找到相关的api。。。
还可以使用SetLongValue、SetDoubleValue、SetBoolValue去添加:
ini.SetLongValue("server", "length", 1000);
ini.SetDoubleValue("server", "weight", 66.66);
ini.SetBoolValue("server", "vip", false);
5. 删
Delete
参数一:节点
参数二:键
返回值:bool
bool done = false;
1). 删除 key 和 value
// 删除 key
done = ini.Delete("section1", "name");
if (false == done) {printf("删除 section1 - name 失败!\n");return -1;
}

2). 当最后一个key也被删除掉后,section1也会被删除
// 如果最后一个key也被删除了,那么section也会被一起删除掉
bool deleteSectionIfEmpty = true;
done = ini.Delete("section1", "age", deleteSectionIfEmpty);
if (false == done) {printf("删除 section1 - age 失败!\n");return -1;
}
此时section1中还由两个key,随意上面的代码执行后只会将age给删除掉,并不会也把section1删掉;

如果将Delete的第三个参数值true去删除sex,那么section1也会一并删掉!
ini.Delete("section1", "sex", true);

将section1还原到一开始的的样子 ,方便下面第3点操作删除

3). 删除整个节点(section)和其下的所有键(key)
// 删除整个section和其中的所有键
done = ini.Delete("section1", nullptr);
if (false == done) {printf("删除整个section和其中的所有键 失败 !\n");return -1;
}
执行如上代码,就会将刚刚还原的section1都给删除掉!

6. 查
GetValue
参数一:节点
参数二:键
参数三:如果没找到,返回参数三指定的默认值
返回值:const char *
1). 将下图中的ini文件内容读取打印显示

int _int = std::stoi(ini.GetValue("section", "_int", "-1"));
printf("_int = %d\n", _int);long long _long = std::stoll(ini.GetValue("section", "_long", "-1"));
printf("_long = %lld\n", _long);double _double = std::stod(ini.GetValue("section", "_double", "0.0"));
printf("_double = %lf\n", _double);float _float = std::stof(ini.GetValue("section", "_float", "0.0"));
printf("_float = %f\n", _float);bool _bool = ini.GetBoolValue("section", "_bool", false);
printf("_bool = %s\n", _bool ? "true" : "false");std::string _string = ini.GetValue("section", "_string", "");
printf("_string = %s\n", _string.c_str());std::string _string2 = ini.GetValue("section", "_string2", "");
printf("_string2 = %s\n", _string2.c_str());char _char = ini.GetValue("section", "_char", "")[0];
printf("_char = %c\n", _char);std::string ip = ini.GetValue("server", "ip", "0.0.0.0");
printf("ip = %s\n", ip.c_str());int port = std::stoi(ini.GetValue("server", "port", "-1"));
printf("port = %d\n", port);std::string name1 = ini.GetValue("server", "name", "");
printf("name = %s\n", name1.c_str());

还可以使用GetLongValue、GetDoubleValue、GetBoolValue去查:
int lenght = ini.GetLongValue("server", "length", -1);
double weight = ini.GetDoubleValue("server", "weight", -1);
bool vip = ini.GetBoolValue("server", "vip", false);
2). 遍历ini文件的所有内容
GetAllSections:获取所有节点,参数一引用返回list链表;
GetSection:根据参数字符串,获取节点,返回multimap容器;
CSimpleIniA::TNamesDepend sections;
// get all sections
ini.GetAllSections(sections);
// 遍历所有 section 的 key 和 value
for (const auto &it : sections) {const CSimpleIniA::TKeyVal *pKeyVal = ini.GetSection(it.pItem);if (nullptr != pKeyVal) {for (const auto& it : *pKeyVal) {std::cout << it.first.pItem << " = " << it.second << std::endl;}}
}

3). 遍历所有节点(section)
CSimpleIniA::TNamesDepend sections1;
// 获取所有section
ini.GetAllSections(sections1);
// 遍历所有 sections
for (const auto &it : sections1) {std::cout << it.pItem << std::endl;
}

4). 遍历指定节点的键(key)
GetAllKeys:获取所有键,参数二引用返回list链表;
CSimpleIniA::TNamesDepend keys;
// get all keys in a section
ini.GetAllKeys("section", keys);
// 遍历 section 指定的所有 key
for (const auto &it : keys) {std::cout << it.pItem << std::endl;
}

5). 获取一个键对应多个值
首先,ini.SetMultiKey(true);得设置为true,否则只会获取到最后一个值,其他会被删除掉;
在ini文件中的server节点添加多几个name键

使用以下代码获取:
CSimpleIniA::TNamesDepend values;
// 获取 key 所对应的多个 value;ini.SetMultiKey(true);一定要设置为true,
// 否则就只会获取到最后一个,其他删除
ini.GetAllValues("server", "name", values);
// 遍历一个 key 对应多个 value;
for (const auto &it : values) {printf("name = %s\n", it.pItem);
}

6). 获取指定节点(section)里有多少键值
// 获取section里有多少值
int size = ini.GetSectionSize("section");
printf("section 的 key 个数:%d\n", size);

7. 保存
注意:以上增、删、改,只有执行保存代码后,才会在文件做出相应的修改!
1). 保存到文件
/* 保存到文件中 */
rc = ini.SaveFile(FILE_NAME);
if (rc < 0) { printf("保存 %s ini文件失败\n", FILE_NAME);
}
2). 保存到C++字符串
std::string strIni = "";
ini.Save(strIni);
printf("%s\n", strIni.c_str());

8. 中文乱码问题
window环境写入或者读取中文有乱码现象,将文件编码改成ANSI编码即可!
可以使用notepad++去修改,如下图:

Linux环境出现中文乱码问题,那就新建一个文件,然后再手动敲上需要的信息即可,例如
touch test1.ini 或 vim test1.ini
记得,千万别从从Window拷贝进Linux中,文件中是不会显示出乱码,但是读取写入时会有乱码!
我遇到的乱码问题,通过上面的方法就可以解决了!
四、封装
可以根据自己项目的具体需求去封装成方便调用的接口去使用!
例如我下面的用法:
configdef.h
这个是定义结构体的头文件,从ini文件中读取的数据都存放在结构体中!
#ifndef _COMMON_CONFIGDEF_H_
#define _COMMON_CONFIGDEF_H_#include <string>typedef struct st_env_config {// 对应ini文件// sectionint _int;long _long;double _double;float _float;bool _bool;std::string _string;char _char;// serverstd::string _ip;unsigned short _port;// 构造函数st_env_config() { }st_env_config(int _int, long _long, double _double, float _float, bool _bool, std::string _string, char _char, std::string _ip, unsigned short _port) {this->_int = _int;this->_long = _long;this->_double = _double;this->_float = _float;this->_bool = _bool;this->_string = _string;this->_char = _char;this->_ip = _ip;this->_port = _port;}// 赋值运算符重载st_env_config &operator=(const st_env_config &config) {if (this != &config) {this->_int = config._int;this->_long = config._long;this->_double = config._double;this->_float = config._float;this->_bool = config._bool;this->_string = config._string;this->_char = config._char;this->_ip = _ip;this->_port = _port;}return *this;}}_st_env_config;#endif // _COMMON_CONFIGDEF_H_
iniconfig.h
这个是封装simpleini的头文件
#ifndef _COMMON_INICONFIG_H_
#define _COMMON_INICONFIG_H_#include <string>#include "configdef.h"#include "../simpleini/SimpleIni.h"class Iniconfig {
public:Iniconfig();Iniconfig(const std::string &path, st_env_config &config);~Iniconfig();// 加载ini文件bool loadfile(const std::string &path);// 保存ini文件bool saveFile(const std::string &fileName);// 设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式void setUnicode(const bool utf8 = true);// 是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值,其他删除void setMultiKey(const bool multKey = false);// 获取ini文件中的数据,保存到结构体中bool getData(st_env_config &config);// 获取ini文件字符串std::string getIniStr();// 添加一个新的sectionbool addSection(const std::string §ion);// 添加一个新的key和value,value可以默认为空bool addValue(const std::string §ion, const std::string &key, const std::string &value = "");bool addLongValue(const std::string §ion, const std::string &key, const long value = 0);bool addDoubleValue(const std::string §ion, const std::string &key, const double value = 0.0);bool addBoolValue(const std::string §ion, const std::string &key, const bool value = false);// 修改value,如果key不存在,则会创建key和valuebool setValue(const std::string §ion, const std::string &key, const std::string &value);bool setLongValue(const std::string §ion, const std::string &key, const long value = 0);bool setDoubleValue(const std::string §ion, const std::string &key, const double value = 0.0);bool setBoolValue(const std::string §ion, const std::string &key, const bool value = false);// 删除keybool deleteKey(const std::string §ion, const std::string &key);// 删除key,如果最后一个key也被删除了,那么section也会被一起删除掉bool deleteKeys(const std::string §ion, const std::string &key, const bool deleteSectionIfEmpty = true);// 删除section,整个section和其中的所有键值bool deleteSection(const std::string §ion);// 获取string类型值std::string getValue(const std::string §ion, const std::string &key, const std::string &defualtValue = "");// 获取char类型值char getValueC(const std::string §ion, const std::string &key, const char &defualtValue = '\0');// 获取long、int、short类型long getLongValue(const std::string §ion, const std::string &key, const short &defualtValue = -1);// 获取double、float类型double getDoubleValue(const std::string §ion, const std::string &key, const double &defualtValue = 0.0);// 获取bool类型bool getBoolValue(const std::string §ion, const std::string &key, const bool &defualtValue = false);// 获取section里有多少值int getSectionSize(const std::string §ion);// 遍历所有void printAll();private:bool _isloaded; // 是否已经加载CSimpleIniA _ini; // ini操作对象
};#endif // _COMMON_INICONFIG_H_
iniconfig.cpp
这个是封装simpleini的cpp文件内容
#include "iniconfig.h"#include <stdio.h>
#include <iostream>Iniconfig::Iniconfig() : _isloaded(false) {_ini.SetUnicode(true); // 使用utf8编码_ini.SetMultiKey(false); // 不允许一个key对应多个value_isloaded = false;
}Iniconfig::Iniconfig(const std::string & path, st_env_config &config) {_ini.SetUnicode(true); // 使用utf8编码_ini.SetMultiKey(false); // 不允许一个key对应多个value_isloaded = false;SI_Error rc;rc = _ini.LoadFile(path.c_str()); // 另一种方式:SI_Error LoadFile(FILE * a_fpFile);if (rc < 0) {printf("加载 %s ini 文件失败!\n", path.c_str());_isloaded = false;return;} int _int = getLongValue("section", "_int", -1);long _long = getLongValue("section", "_long", -1);double _double = getDoubleValue("section", "_double", 0.0);float _float = getDoubleValue("section", "_float", 0.0);bool _bool = getBoolValue("section", "_bool", false);std::string _string = getValue("section", "_string", "");char _char = getValueC("section", "_char", '\0');std::string ip = getValue("server", "ip", "0.0.0.0");unsigned short port = getLongValue("section", "port", -1);config = st_env_config(_int, _long, _double, _float, _bool, _string, _char, ip, port);_isloaded = true;
}Iniconfig::~Iniconfig() {}// 加载ini文件
bool Iniconfig::loadfile(const std::string &path) {if (false == _isloaded) {SI_Error rc;rc = _ini.LoadFile(path.c_str()); // 另一种方式:SI_Error LoadFile(FILE * a_fpFile);if (rc < 0) {printf("加载 %s ini 文件失败!\n", path.c_str());_isloaded = false;return _isloaded;}_isloaded = true;} return _isloaded;
}bool Iniconfig::saveFile(const std::string & fileName) {SI_Error rc = _ini.SaveFile(fileName.c_str());if (rc < 0) {printf("保存 %s ini文件失败\n", fileName.c_str());return false;}_isloaded = false;return true;
}void Iniconfig::setUnicode(const bool utf8) {_ini.SetUnicode(utf8); // true:使用utf8编码
}void Iniconfig::setMultiKey(const bool multKey) {_ini.SetMultiKey(multKey); // false:不允许一个key对应多个value
}bool Iniconfig::getData(st_env_config & config) {if (true == _isloaded) {int _int = getLongValue("section", "_int", -1);long _long = getLongValue("section", "_long", -1);double _double = getDoubleValue("section", "_double", 0.0);float _float = getDoubleValue("section", "_float", 0.0);bool _bool = getBoolValue("section", "_bool", false);std::string _string = getValue("section", "_string", "");char _char = getValueC("section", "_char", '\0');std::string ip = getValue("server", "ip", "0.0.0.0");unsigned short port = getLongValue("section", "port", -1);config = st_env_config(_int, _long, _double, _float, _bool, _string, _char, ip, port);return true;}return false;
}std::string Iniconfig::getIniStr() {std::string str = "";if (true == _isloaded) {SI_Error rc = _ini.Save(str);if (rc < 0) {printf("获取ini文件字符串失败!\n");str = "";}}return str;
}bool Iniconfig::addSection(const std::string & section) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetValue(section.c_str(), nullptr, nullptr);if (rc < 0) {printf("添加 %s 节点失败!\n", section.c_str());return false;}return true;
}bool Iniconfig::addValue(const std::string & section, const std::string & key, const std::string & value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetValue(section.c_str(), key.c_str(), value.c_str());if (rc < 0) {printf("添加 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::addLongValue(const std::string & section, const std::string & key, const long value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetLongValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("添加 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::addDoubleValue(const std::string & section, const std::string & key, const double value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetDoubleValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("添加 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::addBoolValue(const std::string & section, const std::string & key, const bool value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetBoolValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("添加 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::setValue(const std::string & section, const std::string & key, const std::string & value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetValue(section.c_str(), key.c_str(), value.c_str());if (rc < 0) {printf("修改 %s value失败!\n", value.c_str());return false;}return true;
}bool Iniconfig::setLongValue(const std::string & section, const std::string & key, const long value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetLongValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("修改 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::setDoubleValue(const std::string & section, const std::string & key, const double value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetDoubleValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("修改 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::setBoolValue(const std::string & section, const std::string & key, const bool value) {if (false == _isloaded) { return false; }SI_Error rc = _ini.SetBoolValue(section.c_str(), key.c_str(), value);if (rc < 0) {printf("修改 %s key失败!\n", key.c_str());return false;}return true;
}bool Iniconfig::deleteKey(const std::string & section, const std::string & key) {if (false == _isloaded) { return false; }bool done = false;// 删除 keydone = _ini.Delete(section.c_str(), key.c_str());if (false == done) {printf("删除 %s - %s 失败!\n", section.c_str(), key.c_str());return false;}return true;
}bool Iniconfig::deleteKeys(const std::string & section, const std::string & key, const bool deleteSectionIfEmpty) {if (false == _isloaded) { return false; }bool done = false;done = _ini.Delete(section.c_str(), key.c_str(), deleteSectionIfEmpty);if (false == done) {printf("删除 %s - %s 失败!\n", section.c_str(), key.c_str());return false;}return true;
}bool Iniconfig::deleteSection(const std::string & section) {if (false == _isloaded) { return false; }bool done = false;done = _ini.Delete(section.c_str(), nullptr);if (false == done) {printf("删除整个 %s 和其下的所有 键 失败 !\n", section.c_str());return false;}return true;
}std::string Iniconfig::getValue(const std::string & section, const std::string & key, const std::string & defualtValue) {if (false == _isloaded) { return ""; }return _ini.GetValue(section.c_str(), key.c_str(), defualtValue.c_str());
}char Iniconfig::getValueC(const std::string & section, const std::string & key, const char & defualtValue) {if (false == _isloaded) { return '\0'; }std::string str = std::to_string(defualtValue);return _ini.GetValue(section.c_str(), key.c_str(), str.c_str())[0];
}long Iniconfig::getLongValue(const std::string & section, const std::string & key, const short & defualtValue) {if (false == _isloaded) { return -1; }return _ini.GetLongValue(section.c_str(), key.c_str(), defualtValue);
}double Iniconfig::getDoubleValue(const std::string & section, const std::string & key, const double & defualtValue) {if (false == _isloaded) { return -1.0; }return _ini.GetDoubleValue(section.c_str(), key.c_str(), defualtValue);
}bool Iniconfig::getBoolValue(const std::string & section, const std::string & key, const bool & defualtValue) {if (false == _isloaded) { return false; }return _ini.GetBoolValue(section.c_str(), key.c_str(), defualtValue);
}int Iniconfig::getSectionSize(const std::string & section) {if (false == _isloaded) { return -1; }return _ini.GetSectionSize(section.c_str());
}void Iniconfig::printAll() {CSimpleIniA::TNamesDepend sections;// get all sections_ini.GetAllSections(sections);// 遍历所有 section 的 key 和 valuefor (const auto &it : sections) {const CSimpleIniA::TKeyVal *pKeyVal = _ini.GetSection(it.pItem);if (nullptr != pKeyVal) {for (const auto& it : *pKeyVal) {std::cout << it.first.pItem << " = " << it.second << std::endl;}}}
}
测试代码:
st_env_config config;
Iniconfig cof(FILE_NAME, config);cof.addSection("abc");
cof.addValue("abc", "name", "a");
cof.addBoolValue("abc", "vip", true);
cof.addDoubleValue("abc", "length", 175.5);
cof.addLongValue("abc", "weight", 85);cof.setValue("abc", "name", "b");
cof.setBoolValue("abc", "vip", false);
cof.setDoubleValue("abc", "length", 188.8);
cof.setLongValue("abc", "weight", 90);//cof.deleteKey("abc", "name");
//cof.deleteKeys("abc", "vip");
//cof.deleteSection("abc");printf("name = %c\n", cof.getValueC("abc", "name"));
printf("name = %s\n", cof.getValue("abc", "name").c_str());
printf("bool = %d\n", cof.getBoolValue("abc", "vip"));
printf("lenght = %f\n", cof.getDoubleValue("abc", "length"));
printf("weight = %ld\n", cof.getLongValue("abc", "weight"));printf("%s\n", cof.getIniStr().c_str());
cof.saveFile(FILE_NAME);
五、总结
simpleini库的基本用法如上面展示的那样,具体还有一些其他的api,现在还用不到,等用到了,再来补充!
simpleini这个库应该也不算难,无非就是GetValue和SetValue的使用!
ini文件常用来初始化程序,例如存储一些软件启动时初始化的一些基础数据,学习完这个库后,日后如果有写一些小软件就可以使用ini去初始化了!
相关文章:
C/C++ 操作ini文件(SinpleIni 跨平台库)
最近在学习时,发现自己还不会操作ini文件,想着以前工作时接触到的项目或多或少都要用到ini文件去保存初始化程序的数据;所以赶紧去网上搜索以下C/C操作ini文件都有些什么库可以玩玩;搜索到有: 1. inih:这是…...
Cadence Allegro 导出Design Rules Check(DRC)Report报告详解
⏪《上一篇》 🏡《上级目录》 ⏩《下一篇》 目录 1,概述2,Design Rules Check(DRC)Report作用3,Design Rules Check(DRC)Report示例4,Design Rules Check(DRC)Report导出方法4.1,方法14.2,方法2B站关注“硬小...
Java的stream流
Java 8中引入的新特性,stream流通过与Lambda表达式结合,采用函数式编程,简化数组、集合操作,提高效率。 我们操作一个集合,就把他看作一个流,整个流依次执行,(可以类比为一个管道&a…...
Mybatis_相关配置解析和ResultMap
目录配置解析核心配置文件mybatis-config.xml 系统核心配置文件environments元素子元素节点:environmentmappers元素Mapper文件Properties优化typeAliases优化その他生命周期和作用域(Scope)方法作用域应用作用域方法作用域ResultMap提出问题…...
Python量化入门:利用中长期RSI寻找趋势拐点,抓大放小,蹲一个大机会!
一、RSI的原理 1. RSI简介 股票的涨跌说白了就是多空博弈造成的,多方力量更强则股票价格上涨,空方力量更强则股票价格下跌。那么我们如何来衡量股票的多空力量强弱呢? 上个世纪70年代,威尔斯威尔得发表了相对强弱指标,即我们常说的RSI(Relative Strength Index),RSI…...
案例14-代码结构逻辑混乱,页面设计不美观
目录 目录 一:背景介绍 二:思路&方案 三:过程 问题1:代码可读性差,代码结构混乱 问题2: 代码逻辑混乱,缺乏封装的意识 问题3:美观问题:问题和图标没有对应上 四…...
弱监督参考图像分割:Learning From Box Annotations for Referring Image Segmentation论文阅读笔记
弱监督参考图像分割:Learning From Box Annotations for Referring Image Segmentation论文阅读笔记一、Abstract二、引言三、相关工作A、全监督参考图像分割B、基于 Box 的实例分割C、带有噪声标签的学习四、提出的方法A、概述B、伪标签生成目标轮廓预测Proposal 选…...
Linux进程和任务管理和分析和排查系统故障
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...
【满分】【华为OD机试真题2023 JAVA】最多几个直角三角形
华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 最多几个直角三角形 知识点递归深搜 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 有N条线段,长度分别为a[1]-a[N]。现要求你计算这N条线段最多可以组合成几个直角三角形,每条线段只能使用一次,每个三…...
PyQt5可视化 7 饼图和柱状图实操案例 ②建表建项目改布局
目录 一、数据库建表 1 建表 2 插入数据 3 查看表数据 二、建立项目 1 新建项目 2 appMain.py 3 myMainWindow.py 4 myChartView.py 2.4.1 提升的后果 2.4.2 QmyChartView类说明 2.4.3 添加代码 三、修改myMainWindow.py程序,添加功能 1 打开数据库 …...
sonarqube指标详解
最近公司引入了sonar,作为代码质量检测工具,以期提高研发同学的代码质量,但是结果出来后,有些同学不清楚相应的指标内容,不知道应该重点关注哪些指标,于是查询了一下相关的资料,加以总结同时也分…...
耳机 喇叭接线分析
1 注意 1 首先必须接地 2 接某一个声道 2 分析 从三段式耳机结构可以得出: 模拟数据 必须的 结构 1 地 2 左or右信号 附加 我们要注意 耳机也是分左声道 右声道的 参考:耳机插头3.5与2.5三段与四段i版与n版等详解 在iPhone还没现在这么NB的时候&a…...
SpaceNet 建筑物检测
SpaceNet 建筑物检测 该存储库提供了一些 python 脚本和 jupyter 笔记本来训练和评估从SpaceNet卫星图像中提取建筑物的卷积神经网络。 用法...
蓝桥杯刷题第六天
第一题:星期计算问题描述本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。已知今天是星期六,请问 20的22次方天后是星期几?注意用数字 1 到 7 表示星期一到星期日。运行限制最大运行时间:1s最…...
Linux C++ 多线程高并发服务器实战项目一
文章目录1、项目介绍2、项目流程2.1、环境变量搬家2.2、设置进程title2.3、信号初始化2.4、开始监听端口2.5、创建守护进程2.6、创建子进程1、项目介绍 1、按照包头包体的格式收发数据包,解决粘包的问题 2、非常完整的多线程高并发服务器 3、根据收到数据包执行&…...
QML ComboBox简介
1.简介 ComboBox是一个组合按钮和弹出列表。它提供了一种以占用最小屏幕空间的方式向用户显示选项列表的方法。 ComboBox用数据模型填充。数据模型通常是JavaScript数组、ListModel或整数,但也支持其他类型的数据模型。 常用属性: count : int&#x…...
uniapp使用webview嵌入vue页面及通信
最近刚做的一个需求,web端(Vue)使用了FormMaking库,FormMaking是一个拖拉拽的动态设计表单、快速开发的一个东西,拖拽完之后最终可以导出一个很长的json,然后通过json再进行回显,快速开发&#…...
深度学习部署笔记(九): CUDA RunTime API-2.1内存管理
1. 前言 主要理解pinned memory、global memory、shared memory即可 2. 主机内存 主机内存很多名字: CPU内存,pinned内存,host memory,这些都是储存在内存条上的Pageable Memory(可分页内存) Page lock Memory(页锁定内存) 共同组成内存你…...
Idea+maven+spring-cloud项目搭建系列--11-2 dubbo鉴权日志记录数据统一封装
前言:使用dubbo做为通信组件,如果接口需要鉴权,和日志记录需要怎样处理; 1 鉴权: 1.1 在bootstrap.yml 中定义过滤器: dubbo.provider.filter: 过滤器的名字: 1.2 resources 目录下创建配置文…...
SOLIDWORKS免费培训 SW大型装配体模式课程
在SOLIDWORKS的使用过程中,大家经常会遇到大型装配体的处理问题,微辰三维的培训课程中也包含了一些大型装配体的技术培训,下面整理一些常见问题,供参考:大型装配体模式1.当我们打开一个大的装配体时,可能会…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
