一文带你入门ini格式

引入:


以蜂鸣器为例,每次我们增加新的设备,


都需要添加两个新文件:


修改程序代码,手动添加:

缺点: 不利于维护

设备类节点直接通过ini文件配置


 什么是.ini文件


ini文件通常以纯文本形式存在,并且包含了一个或多个节(sections)以及每个节下的键值对(keyvalue pairs)。这些键值对用来指定应用程序的各种设置。
比如Linux系统里就有非常多这类格式的文件,如Linux下的打印机服务程序启动配置文
件/lib/systemd/system/cups.service:
 

举例:

cat /lib/systemd/system/dbus.service 


这种.server文件的格式就是 ini格式

[字段]
若干 键值对(key = value)

[sesction]
name = key

[Install]
Also=cups.socket cups.path
WantedBy=printer.target multi-user.target
 

在配置ini之前我们需要 安装ini文件对应的解析库 inih

inih解析库介绍

inih 是一个轻量级的 C 库,用于解析 INI 格式的配置文件。这个库由 Ben Hoyt 开发,并在 GitHub 上提供源 代码( https://github.com/benhoyt/inih )。 inih 库的设计目标是简单易用,同时保持最小的依赖性。

特点

以下是关于 inih 库的一些特点:
跨平台: inih 库是跨平台的,可以在多种操作系统和编译器环境下使用。
体积小: inih 库只有几个 C 文件,非常适合嵌入到其他项目中。
可定制:用户可以通过回调函数来处理读取到的键值对,使得处理方式非常灵活。
易于集成:只需要将 ini.c ini.h 两个文件添加到你的项目中即可开始使用。
支持注释: inih 库可以正确地处理以分号或哈希字符开头的行作为注释。
错误处理:如果在解析过程中遇到错误, ini_parse() 函数会返回一个负数。
要使用 inih 库,你需要在你的代码中包含 ini.h 头文件,并调用 ini_parse() 函数来解析 INI 文件。 ini_parse() 函数接受三个参数:要解析的文件名、一个回调函数以及一个用户数据指针。每当找到一个新的键值对 时,都会调用回调函数。

安装

apt-cache  search libinih

sudo apt install libinih-dev

方法二:

(博主方法一没下好,直接上Github下载)

直接到Github上面下载,然后通过FileZilla传送到虚拟机

下载zip文件 --> 解压  --> 传送得到这样一个文件夹

里面内容如下:

示例代码

查看C语言的示例代码

ini的简单使用:

新建一个 文件夹 -- ini

把前面我我们提到的ini.c , ini.h  文件创送过来

gdevice.ini

[lock]
key=0x44
gpio_pin=8
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=1
voice_set_status=1

[beep]
key=0x45
gpio_pin=9
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=1


[BR led]
key=0x42
gpio_pin=5
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0

[LV led]
key=0x41
gpio_pin=2
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0

[fan]
key=0x43
gpio_pin=7
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0

case1 -- 打印信息:

initest.c

/* Example: parse a simple configuration file */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ini.h"



  #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0

static int handler(void* user, const char* section, const char* name,
                   const char* value)
{

    printf("section = %s, name = %s, value = %s\n", section, name, value);
    return 1;
}

int main(int argc, char* argv[])
{


    if (ini_parse("gdevice.ini", handler, NULL) < 0) {
        printf("Can't load 'gdevice.ini'\n");
        return 1;
    }


    return 0;
}

运行结果

case2 --  配置设备节点

其实就是把ini文件里面的设备消息,用头插法插入到对应的设备节点里面

initest.c

/* Example: parse a simple configuration file */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ini.h"
#include "gdevice.h"


// 没引入wiringpi库要手动定义宏

#ifndef LOW
#define LOW 0
#define  HIGH 1
#endif


#ifndef OUTPUT
#define OUTPUT 1
#define INPUT 0
#endif



#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0


static struct gdevice *pdevhead = NULL;

static int handler_gdevice(void* user, const char* section, const char* name,const char* value)
{
    struct gdevice *pdev = NULL;
    if(NULL ==  pdevhead)
    {
        pdevhead = (struct gdevice *)malloc(sizeof(struct gdevice));
        memset(pdevhead, 0, sizeof(struct gdevice));
        pdevhead->next = NULL;
        strcpy(pdevhead->dev_name,section);     
   }
    //printf("section = %s, name = %s, value = %s\n", section, name, value);

    else if(0 != strcmp(section, pdevhead->dev_name))// 当section对不上的时候,表示到了下一个设备
    {
        // 把新节点(设备)使用头插法插入
        pdev = (struct gdevice *)malloc(sizeof(struct gdevice));
        memset(pdev, 0, sizeof(struct gdevice));
        strcpy(pdev->dev_name,section);
        pdev->next = pdevhead;
        pdevhead = pdev;

    }
   
   if(NULL != pdevhead)
   {
    if(MATCH(pdevhead->dev_name, "key"))
    {
        sscanf(value, "%x", &pdevhead->key); //把value(string)的值 转为int类型 16进行格式 传递给  pdevhead->key)
        printf("%d  pdevhead->key = 0x%x\n",__LINE__,pdevhead->key);
  
    }

    else if(MATCH(pdevhead->dev_name, "gpio_pin"))
    {
      pdevhead->gpio_pin = atoi(value);
    }
   
    else if(MATCH(pdevhead->dev_name, "gpio_mode"))
    {
       
        if(strcmp(value, "OUTPUT") == 0)
        {
            pdevhead->gpio_mode = OUTPUT;
        }
        else if(strcmp(value, "INPUT") == 0)
        {
            pdevhead->gpio_mode = INPUT;
        }
        else
        {
            printf("gpio_mode error\n");
        }

    }
   
    else if(MATCH(pdevhead->dev_name, "gpio_status"))
    {
       
        if(strcmp(value, "LOW") == 0)
        {
            pdevhead->gpio_mode = LOW;
        }
        else if(strcmp(value, "HIGH") == 0)
        {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
            pdevhead->gpio_mode = HIGH;
        }
        else
        {
            printf("gpio_status error\n");
        }

    }

    else if(MATCH(pdevhead->dev_name, "check_face_status"))
    {
      pdevhead->check_face_status = atoi(value);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    }

      else if(MATCH(pdevhead->dev_name, "voice_set_status"))
    {
      pdevhead->voice_set_status     = atoi(value);
    }




   }



    return 1;
}



int main(int argc, char* argv[])
{
    
    struct gdevice *pdev = NULL;
     
    //printf("before handler_gdevice %d",__LINE__);
    if (ini_parse("gdevice.ini", handler_gdevice, NULL) < 0) {
        printf("Can't load 'gdevice.ini'\n");
        return 1;
    }
    //printf("after handler_gdevice %d",__LINE__);
    //打印每个设备的信息来测试是否配置成功

    pdev = pdevhead;
    while (pdev != NULL)
    {
       //printf("inside %d",__LINE__);

       printf("dev_name:%s\n",pdev->dev_name);
       printf("key:%x\n",pdev->key);
       printf("gpio_pin:%d\n",pdev->gpio_pin);
       printf("gpio_mode:%d\n",pdev->gpio_mode);
       printf("gpio_status:%d\n",pdev->gpio_status);
       printf("check_face_status:%d\n",pdev->check_face_status); 
       printf("voice_set_status:%d\n",pdev->voice_set_status);

       pdev= pdev->next;
    }
    


    return 0;
}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/638486.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快速搭建流媒体服务

1、安装流媒体服务 源码地址&#xff1a;https://gitee.com/ossrs/srs 本次采用docker安装 docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 8000:8000/udp -p 10080:10080/udp registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 查看运行效果&#xff…

[LLM-Agents]浅析Agent工具使用框架:MM-ReAct

上文LLM-Agents]详解Agent中工具使用Workflow提到MM-ReAct框架&#xff0c;通过结合ChatGPT 与视觉专家模型来解决复杂的视觉理解任务的框架。通过设计文本提示&#xff08;prompt design&#xff09;&#xff0c;使得语言模型能够接受、关联和处理多模态信息&#xff0c;如图像…

QQ技术导航源码附带交易系统

网站功能 QQ登录 友联自助交换 友情链接交易功能 多功能搜索 ico小图标本地化 网站图片本地化 蜘蛛日志 文章评论 网站评论 自助链接匿名提交站点&#xff0c;添加友链访问网站自动审核通过 VIP 会员等级 VIP 付费升级 单个文章或者站点付费快审 多背景图片可自定义背景图片…

【数据结构】第七节:堆

个人主页&#xff1a; 深情秋刀鱼-CSDN博客 数据结构专栏&#xff1a;数据结构与算法 源码获取&#xff1a;数据结构: 上传我写的关于数据结构的代码 (gitee.com) ​ 目录 一、堆 1.堆的概念 2.堆的定义 二、堆的实现 1.初始化和销毁 2.插入 向上调整算法 3.删除 向下调整算法…

9.STL中list的常见操作(图文并茂)

目录 1.list的介绍及使用 1.1.list的构造 1.2 list iterator的使用 1.3. list capacity 1.4.list modifiers 1.5.list的迭代器失效 1.list的介绍及使用 list介绍 &#xff0c;可以通过以下图直观的感受到 vector 和 list 的区别 Vector 插入代价高&#xff0c;但便于排…

LabVIEW与串口通讯在运行一段时间后出现数据接收中断的问题

这些问题可能与硬件、软件或通信协议有关。以下是详细的原因分析和可能的解决方案&#xff1a; 一、硬件原因 串口线缆或接口问题&#xff1a; 由于长时间使用&#xff0c;串口线缆可能出现接触不良或损坏。接口松动也可能导致通讯中断。 解决方案&#xff1a;检查并更换串口…

【区块链】智能合约漏洞测试

打开Ganache vscode打开智能合约漏洞工程 合约内容 pragma solidity >0.8.3;contract EtherStore {mapping(address > uint) public balances;function deposit() public payable {balances[msg.sender] msg.value;emit Balance(balances[msg.sender]);}function with…

完成商品属性分组和商品属性关联维护

文章目录 1.前端页面搭建1.复制attrgroup-attr-relation.vue到src/views/modules/commodity下2.加入超链接和引入组件 src/views/modules/commodity/attrgroup.vue1.加入超链接2.引入组件 3.数据池加入变量4.使用组件1.引用组件2.添加方法3.测试&#xff0c;点击关联&#xff0…

【笔记】Qt 按钮控件介绍(QPushButton,QCheckBox,QToolButton)

文章目录 QAbstractButton 抽象类(父类)QAbstractButton 类中的属性QAbstractButton 类中的函数QAbstractButton 类中的信号QAbstractButton 类中的槽 QPushButton 类(标准按钮)QPushButton 类中的属性QPushButton 类中的函数、槽 QCheckBox 类(复选按钮)QCheckBox 类的属性QCh…

【全部更新完毕】2024电工杯A题数学建模详细思路代码文章分享

A 题&#xff1a;园区微电网风光储协调优化配置 摘要 在全球范围内&#xff0c;气候变化和环境污染问题日益严重&#xff0c;减少碳排放和实现可持续发展成为各国的共同目标。新能源&#xff0c;尤其是风能和光伏发电&#xff0c;因其清洁、可再生的特性&#xff0c;正在全球范…

国产化服务器设计 原理图:905-多路PCIe的阵列计算全国产化服务器

多路PCIe的阵列计算全国产化服务器 多路PCIe的阵列计算全国产化服务器以国产化处理器&#xff08;海光、飞腾ARM、算能RSIC V&#xff09;为主板&#xff0c;扩展6-8路PCIe3.0X4计算卡&#xff1b; 计算卡为全国产化的AI处理卡&#xff08;瑞星微ARM&#xff0c;算能AI&#x…

C++语言学习(五)—— 类与对象(一)

目录 一、类类型的定义 二、类成员的访问控制 2.1 什么是"类内"和"类外" 2.2 对于访问控制属性的说明 三、类类型的使用 3.1 进行抽象 3.2 声明类 3.3 实现类 3.4 使用类 四、构造函数的引入 五、析构函数的引入 六、重载构造函数的引入 6.1 …

权限维持--windows

隐藏文件 ①文件属性隐藏 如何排查&#xff1a; 使用dir命令无法看到有特殊属性的文件需使用/a ②真隐藏 相当于给原本的文件增加系统文件属性、存档文件属性、只读文集属性、隐藏文件属性 如何排查&#xff1a; 取消受保护的操作系统文件 ③利用ADS隐藏 使用数据流 echo &…

我把PostgreSQL最核心的插件撸干净了!!!

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

USB抓包工具:bushound安装及使用

一、环境搭建 下载busbound6.01安装包&#xff0c;安装完成&#xff0c;重启电脑。 二、工具配置 按照下图配置工具&#xff1a; 使能自动识别新设备 2. 设置抓取数据的容量 三、抓包 回到capture选项卡&#xff0c;在页面的右下角有个run的按钮&#xff0c;点击使能&…

Multi-Attention Transformer for Naturalistic Driving Action Recognition

标题&#xff1a;用于自然驾驶行为识别的多注意力Transformer 源文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2023W/AICity/papers/Dong_Multi-Attention_Transformer_for_Naturalistic_Driving_Action_Recognition_CVPRW_2023_paper.pdfhttps://openaccess…

快速幂算法6

eg: n10&#xff0c;10%20, 10/25, 5%21,4* 5/22, 2%20,4*256 0/20, 1024 递归算法 #include<iostream> using namespace std; long long quick_pow(int b,int e) {if(b0)return 0;if(e0)return 1;if(e%20){int tempquick_pow(b,e/2);return temp*temp;}if(e%2!0)…

MATLAB modem.qammod和randint函数

实在是受不了MATLAB改函数了 试图找到如何修改代码&#xff0c;诶嘿&#xff0c;失败了&#xff0c;那我就自己写一下吧 randint函数 %% P pre-MMSE clear all;clc % 参数设置 N_frame 100; %帧数 N_packet 1000; % 分组数 b 2; % 每符号比特数 M 2 ^ b; % 调制阶数 mod…

Flutter笔记:Widgets Easier组件库-使用隐私守卫

Flutter笔记 Widgets Easier组件库&#xff1a;使用隐私守卫 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https:…

local dimming(局部调光)介绍

文章目录 1. 什么是local dimming2. 工作原理3. 类型4. 优点5. 缺点和局限7. 技术发展趋势 1. 什么是local dimming local dimming&#xff08;局部调光&#xff09;是电视和显示器中用于提升画面对比度和画质的背光技术。其基本原理是将背光源&#xff08;通常是LED&#xff…