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

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.mfbz.cn/a/399924.html

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

相关文章

人工智能|深度学习——基于数字图像处理和深度学习的车牌定位

1.研究背景及研究目的和意义 车牌识别Vehicle License Plate Recognition VLPR) 是从一张或一系列数字图片中自动定位车牌区域并提取车牌信息的图像识别技术。车牌识别 以数字图像处理、模式识别、计算机视觉等技术为基础&#xff0c;是现代智能交通系统的重要组成部分&#xf…

ABAQUS中创建主视图命令菜单和工具条

在ABAQUS中操作模型时&#xff0c;经常需要选择边界上的元素&#xff0c;如果使用框选则需要将模型摆正&#xff08;处于一个主视图角度&#xff09;&#xff0c;虽然ABAQUS提供了6个主视图工具按键&#xff0c;但实际使用中还有有一些不便的&#xff1a; ABAQUS提供的视角只是…

复高斯分布的随机变量的模方的分布

文章目录 服从复高斯分布的随机向量的模方的分布问题的源头矩阵服从复高斯分布向量服从复高斯分布杂记需要与上面向量的分布区别开的是&#xff1a;服从复高斯分布的随机变量的和的平方的分布 服从复高斯分布的随机向量的模方的分布 已知 x ∈ C L 1 \mathbf{x} \in \mathbb{…

【CVE-2024-21626】容器逃逸漏洞修复

哈喽大家好&#xff0c;我是咸鱼。 好久不见&#xff0c;最近有一个很火的 CVE——runc 容器逃逸漏洞。年前的时候我们已经在测试环境进行了相关操作打算年后线上进行修复。 因为今天咸鱼才开工&#xff0c;所以文章也就拖到了现在 &#x1f603; 漏洞介绍 简单来讲&#xf…

怿星科技测试实验室(EPT LABS)服务介绍

据中国汽车工业协会数据&#xff0c;2023年我国汽车产销量分别达3016.1万辆和3009.4万辆&#xff0c;年产销量双双创历史新高&#xff0c;汽车行业进入了新时代。新汽车时代下的OEM竞争更激烈&#xff0c;汽车电子架构更复杂&#xff0c;研发周期更短&#xff0c;软件迭代更快&…

汽车线束中的螺栓拧紧有哪些要求——SunTorque智能扭矩系统

在现代汽车的电气系统中&#xff0c;线束是连接各个电器元件的桥梁&#xff0c;承担着传输电能、信号以及实现控制功能的重要任务。而在线束的装配过程中&#xff0c;螺栓的拧紧技术是确保线束固定、连接可靠的关键环节。SunTorque智能扭矩系统和大家一起探讨汽车线束中的螺栓拧…

Java中的关键字

✨✨ 所属专栏&#xff1a; Java基石&#xff1a;深入探索Java核心基础✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; Java中的关键字是一些具有特殊含义的单词&#xff0c;它们在语法中有特定的用途&#xff0c;不能用作标识符&am…

响应式编程上下文

标题响应式编程代码示例 代码示例 多个消费者订阅了同一个生产者 package com.yaeher.infrastructure.userinfovault.user; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import reactor.core.scheduler.Scheduler; import reactor.core.schedul…

基于ImageSharp实现趣味横生的点选验证

引言 随着安全需求的不断提升&#xff0c;传统的文本验证码已经无法满足防止机器自动识别和攻击的要求。点选式验证码作为一种交互式的验证手段&#xff0c;因其更难被自动化脚本破解而逐渐受到欢迎。利用开源图像处理库SixLabors.ImageSharp来实现点选式验证码功能。 ImageS…

APP 有漏洞被测要下架,怎么处理?

事情的经过是这样的&#xff1a; 1&#xff1a;学员公司测试的 APP 发现有漏洞&#xff0c;被要求下架 2&#xff1a;他被公司要求去查询 APP 哪里有漏洞 3&#xff1a;他来寻求帮助&#xff0c;推荐几款安全测试扫描漏洞的问题。 事情的梳理&#xff1a; 1:我们看了他的 …

UE5 C++ UENUM 和 USTRUCT

一.首先在APawn里声明 UENUM 和 USTRUCT。UENUM 有两种定义方式 一种是使用命名空间&#xff1a; 还有是继承uint8&#xff1a; 通过申明class类 别名来替代 USTRUCT的定义 上面的第二种有类似但仍然有很多的差异&#xff1a; 首先要有GENERATED_USTRUCT_BODY()这个函数 并且…

fastApi笔记04-查询参数和字符串校验

额外校验 使用Query可以对查询参数添加校验 from typing import Unionfrom fastapi import FastAPI, Queryapp FastAPI()app.get("/items/") async def read_items(q: Union[str, None] Query(defaultNone, max_length50)):results {"items": [{"…

春招面试准备笔记——过拟合和欠拟合

介绍 过拟合&#xff1a;过拟合是指模型在训练过程中过于复杂&#xff0c;拥有过多的参数&#xff0c;以至于在训练数据集上表现良好&#xff0c;但在未见过的测试数据上表现很差的现象。这种情况下&#xff0c;模型可能只是“死记硬背”了训练数据的特征和噪声&#xff0c;而…

SpringBoot中使用PageHelper插件实现Mybatis分页

场景 SpringBoot中整合Mybatis时一般添加的依赖为 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.1</version></dependency> 如果要实现分页查…

解锁ThreadLocal的问题集:如何规避多线程中的坑

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 解锁ThreadLocal的问题集&#xff1a;如何规避多线程中的坑 前言内存泄露问题内存泄漏原因&#xff1a;检测和避免内存泄漏的实用建议&#xff1a; 线程池带来的数据混乱最佳实践&#xff1a;注意事项…

CVE-2024-0918 TEW-800MB RCE漏洞分析

漏洞描述 固件版本为1.0.1.0的TEW-800MB路由器存在命令注入漏洞。如果攻击者获得了web管理权限&#xff0c;他们可以将命令注入到httpd未知函数中的post请求参数DeviceURL中&#xff0c;从而获得shell权限。。 参考链接 TEW-800MB (notion.site)https://warp-desk-89d.notio…

从宏观到微观——泽攸科技ZEM系列台式扫描电子显微镜在岩石分析中的应用

岩石作为地球地壳的主要构成物质之一&#xff0c;其微观结构对于了解地质过程、资源勘探以及工程建设具有重要意义。按照岩石的成因&#xff0c;可以把它们分为三类&#xff1a;岩浆岩、沉积岩和变质岩。在地球表面&#xff0c;沉积岩占据75%的份额&#xff0c;而在地壳深度&am…

Family Day/园区参观路径(C语言)

题目描述 园区某部门举办了Family Day&#xff0c;邀请员工及其家属参加&#xff1b; 将公司园区视为一个矩形&#xff0c;起始园区设置在左上角&#xff0c;终点园区设置在右下角&#xff1b; 家属参观园区时&#xff0c;只能向右和向下园区前进&#xff0c;求从起始园区到终…

低代码中的工作流:简化开发流程,提升效率

低代码开发平台近年来在软件开发领域引起了广泛的关注和应用。它以提高开发效率、降低开发成本为目标&#xff0c;通过简化开发过程&#xff0c;使非专业开发者也能快速构建高品质的应用程序。其中&#xff0c;工作流引擎作为低代码开发平台的重要组成部分&#xff0c;对于提升…

使用C# Net6连接国产达梦数据库记录

达梦官网&#xff1a;http://www.dameng.com/ 1 下载达梦并进行安装 下载地址&#xff1a;官网首页——服务与合作——下载中心&#xff08;https://www.dameng.com/list_103.html&#xff09; 根据需要自行下载需要的版本&#xff0c;测试版本为&#xff1a;x86 win64 DM8版…
最新文章