C语言读取 ini 配置文件,修改/添加键值对

news2024/11/23 8:16:45

C语言读取 ini 配置文件,修改/添加键值对

C语言读取 ini 配置文件,对section中的键值对进行修改/添加,如果section不存在,则在末尾将新的section/key/value 添加进去。

一、了解什么是INI文件?

ini 文件是Initialization File的缩写,即初始化文件,这是用来配置应用软件以实现不同用户的要求。

二、INI文件的格式

INI文件由节、键、值组成。

一个简单的的INI文件例子如下:

/*test.ini*/
[city]
beijing =  hello-beijing
shanghai = hello-shanghai


#information
[study]
highschool = huafuyi
university = guofangkeda

[xinming]
name = lilei

如上例子,[city]就是节,=号左边的值是键,=号右边的是值。

  • 读取key对应的value值


/*
    * 功能:     读取key对应的value值
    * 入口参数: filename
    *                要读取的文件路径
    *            title
    *                配置文件中一组数据的标识
    *            key
    *                这组数据中要读出的值的标识
    * 返回值:   找到需要查的值则返回正确结果 0
    *            否则返回-1
    */
int GetIniKeyString(char* filename, char* title, char* key, char* buf)
{
    FILE* fp;
    int  flag = 0;
    char sTitle[64], * wTmp;
    char sLine[1024];
    // 节section字符串
    sprintf(sTitle, "[%s]", title);

    if (NULL == (fp = fopen(filename, "r"))) 
    {
        printf("open %s failed.\n", filename);
        perror("fopen failed.\n");
        return -1;
    }
    // 读取ini中的每一行
    while (NULL != fgets(sLine, 1024, fp)) 
    {
        // 处理ini文件中的注释行
        if (0 == strncmp("//", sLine, 2)) 
            continue;
        if (('#' == sLine[0]) || ';' == sLine[0])
            continue;

        // 定位=的位置
        wTmp = strchr(sLine, '=');
        if ((NULL != wTmp) && (1 == flag)) 
        {
            if (0 == strncmp(key, sLine, strlen(key))) 
            { // 长度依文件读取的为准  
                sLine[strlen(sLine) - 1] = '\0';
                fclose(fp);
                while (*(wTmp + 1) == ' ') 
                {
                    wTmp++;
                }
                // 获取key对应的value
                strcpy(buf, wTmp + 1);
                return 0;
            }
        }
        else 
        {
            if (0 == strncmp(sTitle, sLine, strlen(sTitle))) 
            { // 长度依文件读取的为准  
                // 不存在键值对的情况下,标记flag
                flag = 1; // 找到标题位置  
            }
        }
    }
    fclose(fp);
    return -1;
}
  • 修改/添加key-value键值对


/*OK--查找section中是否存在key,存在则将key对应的值修改为val,不存在则将key对应的val添加在section后面。*/
int PutIniKeyString2(char* filename, char* title, char* key, char* val)
{
    FILE* fpr, * fpw;
    int  flag = 0;
    int rtn = 0;
    char sLine[1024], sTitle[32], * wTmp;
    sprintf(sTitle, "[%s]", title);
    if (NULL == (fpr = fopen(filename, "r")))
    {
        printf("读取原文件失败.\n");
        return -1;// 读取原文件 
    }
    // 临时文件名
    sprintf(sLine, "%s.tmp", filename);
    if (NULL == (fpw = fopen(sLine, "w")))
    {
        printf("写入失败.\n");
        return -1;// 写入临时文件    
    }

    while (NULL != fgets(sLine, 1024, fpr))
    {
        if (2 != flag)
        { // 如果找到要修改的那一行,则不会执行内部的操作  
            wTmp = strchr(sLine, '=');
            if ((1 == flag))
            {
                // 找到对应的key
                if ((NULL != wTmp) && (0 == strncmp(key, sLine, strlen(key))))
                { // 长度依文件读取的为准 
                    flag = 2;// 更改值,方便写入文件  
                    sprintf(wTmp + 1, " %s\n", val);
                }
                else
                {
                    if ((sLine[0] == '\n'))
                    {
                        /* 没有找到对应的key,则在section末尾添加新的key/value */
                        //fseek(fpw, 0, SEEK_END);-((long)strlen(sLine))
                        fseek(fpw, 0, SEEK_CUR);
                        fprintf(fpw, "%s = %s\n", key, val);
                        flag = 0;
                    }
                }
            }
            else
            {
                // 找到section的位置
                if (0 == strncmp(sTitle, sLine, strlen(sTitle)))
                { // 长度依文件读取的为准
                    flag = 1; // 找到标题位置  
                }
            }

        }
        fputs(sLine, fpw); // 写入临时文件 
    }
    if (-1 == flag)
    {   /* 没有找到对应的section,则在文件末尾添加新的section/key/value */
        fseek(fpw, 0, SEEK_END);
        fprintf(fpw, "%s\n", sTitle);
        fprintf(fpw, "%s = %s\n\n", key, val);
    }

    fclose(fpr);
    fclose(fpw);
    sprintf(sLine, "%s.tmp", filename);
    rtn = rename(sLine, filename);// 将临时文件更新到原文件  
    if (rtn != 0)
    {
        if (errno == EEXIST)
        {
            // 如果目标文件已经存在,需要先删除,再重命名
            if (remove(filename) == 0)
            {
                if (rename(sLine, filename) == 0)
                {
                    return 0;
                }
                else
                {
                    return -1;
                }
            }
        }
    }
    return rtn;
}
  • 测试程序

头文件 ini.h

#pragma once

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

constexpr auto BUF_SIZE = 256;


int GetIniKeyString(char* filename, char* title, char* key, char* buf);


int PutIniKeyString2(char* filename, char* title, char* key, char* val);

主函数 main.c

#include "ini.h"

int main(int argc, char const* argv[])
{
    int ret;
    char buff[100];
    //readSpeed();
    //readExcel();

    int xishu_gain = 2 << 25;//滤波器系数放大倍数.


    *******************OK**************************
    char filename[] = "./test.ini";
    char title[] = "city";
    char key[] = "beijing";
    ret = GetIniKeyString(filename, title, key, buff);//读取ini文件key对应的vlaue
    printf("ret:%d,%s\n", ret, buff);

    char filename[] = "./test.ini";
    //char title2[] = "study";
    //char key2[] = "highschool";
    //ret = GetIniKeyString(filename, title2, key2, buff);//读取ini文件key对应的vlaue
    //printf("ret:%d,%s\n", ret, buff);

    char title3[] = "xinming";
    char key3[] = "name2";
    char value3[] = "xiao-hua";
    ret = PutIniKeyString2(filename, title3, key3, value3);//修改ini文件key对应的vlaue
    printf("put ret:%d,%s\n", ret, value3);

    //ret = GetIniKeyString(filename, title3, key3, buff);
    //printf("ret:%d,%s\n", ret, buff);
    //****************OK*****************************


    return 0;
}

测试结果ini文件:

/*test.ini*/
[city]
beijing =  hello-beijing
shanghai = hello-shanghai
wuhan = hello-wuhan
wuhan1 = hello-wu-han
wuhan2 = hello-wuhan

#information
[study]
highschool = huafuyi
university = guofangkeda
xiaoxue = huafucunxiao
xiaoxue1 = huafu-cunxiao1

[xinming]
name = lilei
name1 = xiao-ming1
name2 = xiao-hua

/*test.ini*/
[city]
beijing =  hello-beijing
shanghai = hello-shanghai
wuhan = hello-wuhan
wuhan1 = hello-wu-han
wuhan2 = hello-wuhan

#information
[study]
highschool = huafuyi
university = guofangkeda
xiaoxue = huafucunxiao
xiaoxue1 = huafu-cunxiao1

[xinming]
name = lilei
name1 = xiao-ming1
name2 = xiao-hua

[tizhi]
weight = 80kg
weight1 = 80kg

  • 打开或创建名为"config.ini"的文件

{
    FILE* file = fopen("config.ini", "w");//打开或创建名为"config.ini"的文件
    if (file == NULL)
    {
        printf("无法创建文件\n");
        return -1;
    }
    // 写入配置项到文件
    fprintf(file, "[Section]\n");
    fprintf(file, "key=value\n");
    fprintf(file, "\n[Another Section]\n");
    fprintf(file, "another_key=another_value\n");

    fclose(file); // 关闭文件
}

参考:

1、C语言读取写入 ini 配置文件_c读取ini配置文件-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022蓝帽杯取证初赛

检材&#xff1a;https://pan.baidu.com/s/1ibOdxyCWeC5x0DQKjwcz7w?pwdvg6g 目录 手机取证1、627604C2-C586-48C1-AA16-FF33C3022159.PNG图片的分辨率是&#xff1f;&#xff08;答案参考格式&#xff1a;19201080&#xff09;2、姜总的快递单号是多少&#xff1f;&#xff0…

【2024软件测试面试必会技能】Jmeter_性能测试(4):性能测试脚本的优化

性能测试脚本的优化 以PHP论坛为例&#xff1a;http://47.107.178.45/phpwind/ 根据上一篇的性能测试(3&#xff09;的脚本进行优化&#xff1b;见下图&#xff1a; 如上图中&#xff0c;把发帖和回帖的事务添加到随机控制器中&#xff0c;登录操作添加到仅一次控制器中&…

yolov5转换成TensorRT推理过程笔记

笔记内容来自 B站 手写AI 一、用硬代码实现 GitHub - wang-xinyu/tensorrtx: Implementation of popular deep learning networks with TensorRT network definition API 安装python、cuda11.2、cudnn对应cuda11.2软件 1、在yolov5-master下训练完成后生成best.pt文件(训练时…

Vue模版语法之属性绑定v-bind

双大括号不能在 HTML 属性中使用。想要响应式地绑定一个属性&#xff0c;应该使用 v-bind 指令 1. 使用v-bind绑定属性 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>新建页面</title><sc…

Vue3实现带动画效果的tab栏切换

效果图如下所示&#xff1a; 实现思路&#xff1a; 其实很简单 1、首先切换tab栏时tab标签激活下标与对应显示内容下标要一致。 2、其次点击tab栏切换时更新下标 3、最后就是css添加动画效果 这样就了&#xff01;&#xff01;&#xff01; 上全部代码 <template><…

有方机器人 STM32智能小车 项目学习笔记1

今天开始学习有方机器人--智能小车项目&#xff0c;正点原子部分的学习先放一放&#xff0c;还是小车更有吸引力哈哈。 新建工程及工程模板搭建 新建工程须知 目前常用的 STM32 的开发方式主要有基于寄存器编程、基于标准库函数编程、基于 HAL 库编程这三种。 寄存器版本--…

滤波电阻器:用于能源系统和工业的高精度解决方案(1)?

滤波电阻器用于防止能源系统中的电源反馈。铝厂或钢铁厂中的大型感应冶炼厂会产生与电源频率的谐波。必须不惜一切代价让这些远离电网。过滤器&#xff0c;通常以 T 或 L 元素的形式用于此目的。中压电源输入端的吸收电路由电容和电感的串联连接组成&#xff0c;对谐波进行负载…

【每日一题】106. 从中序与后序遍历序列构造二叉树-2024.2.21

题目: 106. 从中序与后序遍历序列构造二叉树 已解答 中等 相关标签 相关企业 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder = [9,3,15,20,7], pos…

Java Web(七)__Tomcat(二)

Tomcat工作模式 Tomcat作为Servlet容器&#xff0c;有以下三种工作模式。 1&#xff09;独立的Servlet容器&#xff0c;由Java虚拟机进程来运行 Tomcat作为独立的Web服务器来单独运行&#xff0c;Servlet容器组件作为Web服务器中的一部分而存在。这是Tomcat的默认工作模式。…

防御第六次作业-防火墙综合实验(av、url过滤、dns过滤)

目录 拓扑图&#xff1a; 要求&#xff1a; 8 9 10 11 拓扑图 要求 前7个要求在上一篇博客&#xff1b; 8.分公司内部的客户端可以通过域名访问到内部的服务器 9.假设内网用户需要通过外网的web服务器和pop3邮件服务器下载文件和邮件&#xff0c;内网的FTP服务器也需要…

【Vuforia+Unity】AR02-长方体物体识别

1.创建模型 选择多维长方体图&#xff0c;这个长方体是生活中的真实物体的拍摄图&#xff0c;提前把6个面拍摄好并裁剪干净。 官网创建模型https://developer.vuforia.com/targetmanager/project/targets?projectId0ddbb5c17e7f4bf090834650bbea4995&avfalse 设置长宽高…

Python开源项目周排行 2024年第4周

#2024年第4周2024年2月18日1Awesome-LLM一个精选的大型语言模型 (LLM) 资源列表&#xff0c;涵盖了以下内容&#xff1a; LLM 模型介绍 论文和代码 部署工具 应用场景 教程和示例 Awesome-LLM 的目标是帮助人们了解和使用 LLM 技术&#xff0c;并为 LLM 开发人员提供一个资源中…

从零开始学习PX4源码1(两个三维矢量如何转换成四元数)

目录 文章目录 目录摘要参考网址推导过程 摘要 本节主要记录px4如何从两个三维旋转矢量转换到四元数的过程&#xff0c;欢迎批评指正&#xff01;&#xff01;&#xff01; 参考网址 三维矢量转四元数 推导过程

【开源】JAVA+Vue.js实现高校学生管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生管理模块2.2 学院课程模块2.3 学生选课模块2.4 成绩管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学生表3.2.2 学院课程表3.2.3 学生选课表3.2.4 学生成绩表 四、系统展示五、核心代码5.1 查询课程5.2 新…

详解动态内存管理!

目录 ​编辑 1.为什么要用动态内存分配 2.malloc和free 2.1 malloc 2.2 free 3.calloc和realloc 3.1 calloc 3.2 realloc 4.常见的动态内存的错误 4.1 对NULL的解引用操作 4.2 对动态内存开辟空间的越界访问 4.3 对非动态内存开辟空间用free释放 4.4 使用free释放动…

unity打包apk运行于google手机

第一次打包apk运行于Pixel 7 Pro 一直提示安装包无法安装 untiy版本2020.1.0f1 有两点需要注意 第一 Scrpting Backend 需要选择 IL2CPP 勾选 ARM64 第二 勾选 Custom Main Mainfest 在Assets -> Plugins -> Android文件夹下 AndroidMainfest 中增加android:export…

软件实例分享,饭店餐饮会员卡管理系统怎么弄会员充值怎么记账

软件实例分享&#xff0c;饭店餐饮会员卡管理系统怎么弄会员充值怎么记账 一、前言 以下软件教程以 佳易王餐饮会员管理系统软件V16为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、会员可以登记电子会员卡或使用vip卡片 2、卡类型可以自由…

[云原生] 二进制安装K8S一部分

一、单机matser预部署设计 目前Kubernetes最新版本是v1.25&#xff0c;但大部分公司一般不会使用最新版本。 目前公司使用比较多的&#xff1a;老版本是v1.15&#xff0c;因为v1.16改变了很多API接口版本&#xff0c;国内目前使用比较多的是v1.18、v1.20。 组件部署&#xff…

【网络安全】电竞选手Faker遭受DDOS攻击,为什么它一直存在,我们遇到ddos攻击怎么办?

二十年前中国红客们就在用的DDOS攻击&#xff0c;直到现在还依然是黑客们最爱的攻击方法&#xff0c;为什么它一直存在&#xff1f; Faker各位小伙伴们自然是相当熟悉了&#xff0c;素有着英雄联盟第一人之称的Faker&#xff0c;其所拥有的荣誉让无数职业选手望其项背&#xf…

LabVIEW开发J-TEXT实时控制系统

LabVIEW开发J-TEXT实时控制系统 随着核聚变研究的不断深入&#xff0c;对实验装置的控制系统提出了更高的要求&#xff0c;尤其是在实时控制和数据处理方面。J-TEXT&#xff08;Joint Texas Experimental Tokamak&#xff09;&#xff0c;作为一种先进的托卡马克装置&#xff…