欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > C语言实现INI配置文件读取和写入

C语言实现INI配置文件读取和写入

2025/5/17 21:27:41 来源:https://blog.csdn.net/xieliru/article/details/148016837  浏览:    关键词:C语言实现INI配置文件读取和写入

一.INI文件介绍

INI配置文件是一种简单的文本文件,用于存储配置信息,通常由一个或多个节(section)组成,每个节包含多个键值对(Key-Value)格式。INI文件易于阅读和编辑,广泛应用于多种程序和应用中。

二.基本格式

INI文件由若干个节(section)组成,每个节由方括号包围的标题表示,例如 [SectionName]。每个节可以包含多个键值对,格式为 key=value。注释用分号(;)表示,放在注释之前的行被视为注释。例如:

[network]

host = 127.0.0.1

port = 8081

[database]

user = admin

三.C代码实现

1.编译环境:VS2022

2.代码

#define _CRT_SECURE_NO_WARNINGS  // 禁用安全警告  //防止fopen告警

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#define MAX_LINE_LENGTH 256    //一行字符串最大长度

#define MAX_SECTION_LENGTH 64  //section字符串最大长度

#define MAX_KEY_LENGTH 64      //key字符串最大长度

typedef struct KeyValue {

    char key[MAX_KEY_LENGTH];

    char* value;

    struct KeyValue* next;

} KeyValue;

typedef struct Section {

    char name[MAX_SECTION_LENGTH];

    KeyValue* pairs;

    struct Section* next;

} Section;

typedef struct IniFile {

    Section* sections;

} IniFile;

// 辅助函数:去除字符串首尾空白

char* trim(char* str) {

    while (isspace((unsigned char)*str)) str++;

    if (*str == 0) return str;

    char* end = str + strlen(str) - 1;

    while (end > str && isspace((unsigned char)*end)) end--;

    *(end + 1) = '\0';

    return str;

}

// 加载INI文件

IniFile* ini_load(const char* filename) {

    FILE* file = fopen(filename, "r");

    if (!file) return NULL;

    IniFile* ini = (IniFile*)calloc(1, sizeof(IniFile));

    Section* current_section = NULL;

    char line[MAX_LINE_LENGTH];

    while (fgets(line, sizeof(line), file)) {

        char* trimmed = trim(line);

        // 跳过空行和注释

        if (*trimmed == '\0' || *trimmed == ';' || *trimmed == '#') continue;

        // 处理节

        if (*trimmed == '[') {

            char* end = strchr(trimmed, ']');

            if (end) {

                *end = '\0';

                char* section_name = trim(trimmed + 1);

                Section* section = (Section*)calloc(1, sizeof(Section));

                strncpy(section->name, section_name, sizeof(section->name) - 1);

                // 添加到链表

                if (!ini->sections) {

                    ini->sections = section;

                }

                else {

                    Section* last = ini->sections;

                    while (last->next) last = last->next;

                    last->next = section;

                }

                current_section = section;

            }

            continue;

        }

        // 处理键值对

        if (current_section) {

            char* sep = strchr(trimmed, '=');

            if (sep) {

                *sep = '\0';

                char* key = trim(trimmed);

                char* value = trim(sep + 1);

                KeyValue* pair = (KeyValue*)calloc(1, sizeof(KeyValue));

                strncpy(pair->key, key, sizeof(pair->key) - 1);

                pair->value = _strdup(value); // VS中使用安全版本

                // 添加到链表

                if (!current_section->pairs) {

                    current_section->pairs = pair;

                }

                else {

                    KeyValue* last = current_section->pairs;

                    while (last->next) last = last->next;

                    last->next = pair;

                }

            }

        }

    }

    fclose(file);

    return ini;

}

// 获取值

const char* ini_get(IniFile* ini, const char* section, const char* key) {

    Section* s = ini->sections;

    while (s) {

        if (strcmp(s->name, section) == 0) {

            KeyValue* p = s->pairs;

            while (p) {

                if (strcmp(p->key, key) == 0) {

                    return p->value;

                }

                p = p->next;

            }

            return NULL;

        }

        s = s->next;

    }

    return NULL;

}

// 设置值

void ini_set(IniFile* ini, const char* section, const char* key, const char* value) {

    Section* s = ini->sections;

    Section* prev_section = NULL;

    // 查找或创建section

    while (s) {

        if (strcmp(s->name, section) == 0) break;

        prev_section = s;

        s = s->next;

    }

    if (!s) {

        s = (Section*)calloc(1, sizeof(Section));

        strncpy(s->name, section, sizeof(s->name) - 1);

        if (prev_section) {

            prev_section->next = s;

        }

        else {

            ini->sections = s;

        }

    }

    // 查找或创建key

    KeyValue* p = s->pairs;

    KeyValue* prev_pair = NULL;

    while (p) {

        if (strcmp(p->key, key) == 0) {

            free(p->value);

            p->value = _strdup(value); // VS中使用安全版本

            return;

        }

        prev_pair = p;

        p = p->next;

    }

    KeyValue* new_pair = (KeyValue*)calloc(1, sizeof(KeyValue));

    strncpy(new_pair->key, key, sizeof(new_pair->key) - 1);

    new_pair->value = _strdup(value); // VS中使用安全版本

    if (prev_pair) {

        prev_pair->next = new_pair;

    }

    else {

        s->pairs = new_pair;

    }

}

// 保存INI文件

int ini_save(IniFile* ini, const char* filename) {

    FILE* file = fopen(filename, "w");

    if (!file) return -1;

    Section* s = ini->sections;

    while (s) {

        fprintf(file, "[%s]\n", s->name);

        KeyValue* p = s->pairs;

        while (p) {

            fprintf(file, "%s = %s\n", p->key, p->value);

            p = p->next;

        }

        fprintf(file, "\n");

        s = s->next;

    }

    fclose(file);

    return 0;

}

// 释放内存

void ini_free(IniFile* ini) {

    Section* s = ini->sections;

    while (s) {

        Section* next_s = s->next;

        KeyValue* p = s->pairs;

        while (p) {

            KeyValue* next_p = p->next;

            free(p->value);

            free(p);

            p = next_p;

        }

        free(s);

        s = next_s;

    }

    free(ini);

}

// 示例用法

int main()

{

    #define FILE_NAME "d:/30.VS/12.c配置文件/config.ini" 

    // 写入测试

    IniFile* ini = ini_load(FILE_NAME);

    if (!ini) ini = (IniFile*)calloc(1, sizeof(IniFile));

    ini_set(ini, "network", "host", "127.0.0.1");

    ini_set(ini, "network", "port", "8080");

    ini_set(ini, "database", "user", "admin");

    ini_set(ini, "network", "port", "8081");  //修改值

    ini_save(ini, FILE_NAME);

    // 读取测试

    IniFile* read_ini = ini_load(FILE_NAME);

    const char* host = ini_get(read_ini, "network", "host");

    printf("Host: %s\n", host);

    ini_free(ini);

    ini_free(read_ini);

    system("pause"); // 防止控制台窗口关闭

    return 0;

}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词