解析ini文件,对外接口增删改查

一、头文件的设置

a、对外接口提供时需要提供明确的成功和失败的返回值,让人判断成功和失败,

b、需要提供明确的参数描述信息,让人知道这是输入参数还是输出参数

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <pthread.h>
#include <iconv.h>

#ifndef INI_PARSER_H
#define INI_PARSER_H

#define LEN 1000
#define INI_SUCCESS 0
#define FAIL_TO_WRITE_TO_FILE -1
#define FAIL_TO_OPEN_FILE -2
#define LINE_EXCEEDS_LENGTH -3
#define InI_FILE_IS_EMPTY -4
#define RWLOCK_INITIALIZATION_FAILED -5
#define MEMORY_ALLOCATION_FAILED -6
#define NO_SPACES_ALLOWED_FOR_KEY -7
#define KEY_CANNOT_BE_EMPTY -8
#define PARAMETER_ERROR -9
#define SECTION_NOT_FOUND -10
#define ENTRIES_NOT_FOUND -11
#define FAILED_TO_ADD -12
#define FAILED_TO_DELETE -13
#define FAILED_TO_MODIFY -14
#define FAILED_TO_QUERY -15
#define INPUT_EXCEED_LENGTH -16
#define NO_COMMENT_FOR_KRY -17
#define INI_FAILURE -19

typedef enum
{
    ENTRY_TYPE_KEY_VALUE,
    ENTRY_TYPE_COMMENT,
    ENTRY_TYPE_EMPTY_LINE
} EntryType_t;

typedef struct
{
    EntryType_t type;
    char *p_key;
    char *p_value;
    char *content; // 用于存储注释或空行内容
} Entry_t;

typedef struct
{
    char *p_name;
    Entry_t *p_entries;
    int entry_count;
} Section_t;

typedef struct
{
    Section_t *p_sections;
    int section_count;
    pthread_rwlock_t lock; // 读写锁
} INIFile_t;

int init(INIFile_t **p_ini_file);
/**
 * @brief 初始化INI文件结构体
 *
 * 该函数用于初始化INI文件结构体,包括分配内存、初始化变量和互斥锁。
 *
 * @param p_file 用于保存初始化后的INI文件结构体指针的指针
 * @return 成功时返回INI_SUCCESS
 *         分配内存失败时返回MEMORY_ALLOCATION_FAILED
 *         初始化互斥锁失败时返回MUTEX_LOCK_INITIALIZATION_FAILED
 */

int destroy_ini_file(INIFile_t *p_ini_file);
/**
 * @brief 销毁INI文件结构体及其资源
 *
 * 该函数用于销毁INI文件结构体,并释放相关资源,包括互斥锁、各个部分的名称和条目,以及INI文件结构体本身。
 *
 * @param p_file 要销毁的INI文件结构体指针
 * @return 成功时返回INI_SUCCESS
 *         文件为空时返回InI_FILE_IS_EMPTY
 */

int parse_ini_file(char *p_filename, INIFile_t **p_ini_file_ptr);
/**
 * @brief 解析INI文件
 *
 * 该函数用于解析INI文件,读取文件中的内容并构建相应的数据结构。line最大为1000,超出返回INI_FAILURE
 *
 * @param p_filename 要解析的INI文件名
 * @param p_ini_filename 用于保存解析后的INI文件结构体指针的指针
 * @return 成功时返回INI_SUCCESS
 *         文件为空时返回InI_FILE_IS_EMPTY
 *         行超出1000时返回LINE_EXCEEDS_LENGTH
 *         内存分配失败时返回MEMORY_ALLOCATION_FAILED
 */

int write_ini_file(char *p_filename, INIFile_t *p_ini_file);
/**
 * @brief 写入INI文件
 *
 * 该函数用于将已解析的INI文件数据结构写入到文件中。
 *
 * @param p_filename 要写入的INI文件名
 * @param p_ini_file 已解析的INI文件数据结构指针
 * @return 成功时返回INI_SUCCESS
 *         打开文件失败时返回FAIL_TO_OPEN_FILE
 *         key值为空时返回KEY_CANNOT_BE_EMPTY
 *         写入文件失败时返回FAIL_TO_WRITE_TO_FILE。
 */

int add_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key, const char *p_value);
/**
 * @brief 添加
 *
 * 该函数用于添加操作
 *
 * @param p_ini_file:指向INI文件结构的指针
 * @param p_section:要添加的节名称
 * @param p_key:要添加的条目的键
 * @param p_value:要添加的条目的值
 * @return 成功时返回INI_SUCCESS
 *         参数p_ini_file、p_section、p_key、p_value为空时返回PARAMETER_ERROR
 *         key含有空格时返回NO_SPACES_ALLOWED_FOR_KEY
 *         key为#或者;时返回INI_FAILURE
 *         输入行超出长度时返回INPUT_EXCEED_LENGTH
 *         内存分配失败时返回MEMORY_ALLOCATION_FAILED
 */

int delete_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key);
/**
 * @brief 删除
 *
 * 该函数用于删除操作
 *
 * @param p_ini_file:指向INI文件结构的指针
 * @param p_section:要删除的节名称
 * @param p_key:要删除的条目的键
 * @param p_value:要删除的条目的值
 * @return 成功时返回INI_SUCCESS
 *         参数p_ini_file、p_section、p_key为空时返回PARAMETER_ERROR
 *         key含有空格时返回NO_SPACES_ALLOWED_FOR_KEY
 *         没有找到节返回SECTION_NOT_FOUND
 *         没有条目时返回ENTRIES_NOT_FOUND
 */

int modify_entry(INIFile_t *p_ni_file, const char *p_section, const char *p_key, const char *p_value);
/**
 * @brief 修改
 *
 * 该函数用于修改操作
 *
 * @param p_ini_file:指向INI文件结构的指针
 * @param p_section:要修改的节名称
 * @param p_key:要修改的条目的键
 * @param p_value:要修改的条目的新的值
 * @return 成功时返回INI_SUCCESS
 *         参数p_ini_file、p_section、p_key、p_value为空时返回PARAMETER_ERROR
 *         key含有空格时返回NO_SPACES_ALLOWED_FOR_KEY
 *         没有找到节返回SECTION_NOT_FOUND
 *         没有条目时返回ENTRIES_NOT_FOUND
 */

const char *query_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key, int *return_code);
/**
 * @brief 查找
 *
 * 该函数用于查找value操作
 *
 * @param p_ini_file:指向INI文件结构的指针
 * @param p_section:要查找的节名称
 * @param p_key:要查找的条目的键
 * @param error_code:存放错误码的
 * @return 成功时返回查找到的value值,且返回码设为INI_SUCCESS
 *         参数p_ini_file、p_section、p_key为空时返回PARAMETER_ERROR
 *         key含有空格时返回NO_SPACES_ALLOWED_FOR_KEY
 *         没有找到节返回SECTION_NOT_FOUND
 *         没有条目时返回ENTRIES_NOT_FOUND
 */

#endif // INI_PARSER_H

二、初始化结构体

// 初始化
int init(INIFile_t **p_file)
{
    *p_file = malloc(sizeof(INIFile_t));
    if (*p_file == NULL)
    {
        return MEMORY_ALLOCATION_FAILED; // 内存分配失败
    }

    (*p_file)->p_sections = NULL;
    (*p_file)->section_count = 0;

    // 初始化读写锁
    if (pthread_rwlock_init(&(*p_file)->lock, NULL) != 0)
    {
        free(*p_file);
        return RWLOCK_INITIALIZATION_FAILED; // 读写锁初始化失败
    }
    return INI_SUCCESS;
}

三、解析ini文件

// 解析
int parse_ini_file(char *p_filename, INIFile_t **p_ini_filename)
{
    FILE *p_file = fopen(p_filename, "r");
    if (p_file == NULL)
    {
        return InI_FILE_IS_EMPTY;
    }

    INIFile_t *p_ini_file = *p_ini_filename;
    pthread_rwlock_wrlock(&p_ini_file->lock);

    char line[LEN];
    Section_t *p_current_section = NULL;
    while (fgets(line, sizeof(line), p_file) != NULL)
    {
        if (strlen(line) >= sizeof(line) - 1)
        {
            fclose(p_file);
            pthread_rwlock_unlock(&p_ini_file->lock);
            return LINE_EXCEEDS_LENGTH;
        }

        line[strcspn(line, "\r\n")] = '\0'; // 找\r\n下标 遇到\r就会返回

        char *p_trimmed_line = line;
        while (isspace(*p_trimmed_line))
        {
            p_trimmed_line++;
        }
        char *p_end = p_trimmed_line + strlen(p_trimmed_line) - 1;
        while (p_end > p_trimmed_line && isspace(*p_end))
        {
            *p_end = '\0';
            p_end--;
        }

        if (*p_trimmed_line == '#' || *p_trimmed_line == ';' || *p_trimmed_line == '\0') // 遇到注释或者空行
        {
            Entry_t entry = {0};
            entry.type = (*p_trimmed_line == '\0') ? ENTRY_TYPE_EMPTY_LINE : ENTRY_TYPE_COMMENT; // 判断是空行还是注释
            entry.content = strdup(line);
            entry.p_key = NULL;
            entry.p_value = NULL;

            if (!entry.content)
            {
                fclose(p_file);
                pthread_rwlock_unlock(&p_ini_file->lock);
                return MEMORY_ALLOCATION_FAILED;
            }

            if (p_current_section == NULL)
            {
                p_ini_file->p_sections = realloc(p_ini_file->p_sections, (p_ini_file->section_count + 1) * sizeof(Section_t));
                if (!p_ini_file->p_sections)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock);
                    return MEMORY_ALLOCATION_FAILED;
                }
                memset(&p_ini_file->p_sections[p_ini_file->section_count], 0, sizeof(Section_t)); // Initialize the new section
                p_current_section = &p_ini_file->p_sections[p_ini_file->section_count++];
                p_current_section->p_name = strdup("DEFAULT_SECTION");
                if (!p_current_section->p_name)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock);
                    return MEMORY_ALLOCATION_FAILED;
                }
            }

            Entry_t *p_temp_entries = realloc(p_current_section->p_entries, (p_current_section->entry_count + 1) * sizeof(Entry_t));
            if (!p_temp_entries)
            {
                fclose(p_file);
                pthread_rwlock_unlock(&p_ini_file->lock);
                return MEMORY_ALLOCATION_FAILED;
            }
            p_current_section->p_entries = p_temp_entries;
            memset(&p_current_section->p_entries[p_current_section->entry_count], 0, sizeof(Entry_t)); // Initialize the new entry
            p_current_section->p_entries[p_current_section->entry_count] = entry;
            p_current_section->entry_count++;
            continue;
        }

        if (*p_trimmed_line == '[' && *p_end == ']') // section
        {
            char *p_section_name = p_trimmed_line + 1;
            *p_end = '\0';

            Section_t *p_temp_sections = realloc(p_ini_file->p_sections, (p_ini_file->section_count + 1) * sizeof(Section_t));
            if (!p_temp_sections)
            {
                fclose(p_file);
                pthread_rwlock_unlock(&p_ini_file->lock);
                return MEMORY_ALLOCATION_FAILED;
            }
            p_ini_file->p_sections = p_temp_sections;
            memset(&p_ini_file->p_sections[p_ini_file->section_count], 0, sizeof(Section_t)); // Initialize the new section

            p_current_section = &p_ini_file->p_sections[p_ini_file->section_count++];
            p_current_section->p_name = strdup(p_section_name);
            if (!p_current_section->p_name)
            {
                fclose(p_file);
                pthread_rwlock_unlock(&p_ini_file->lock);
                return MEMORY_ALLOCATION_FAILED;
            }

            continue;
        }

        char *p_equal = strchr(p_trimmed_line, '=');
        if (p_equal == NULL)
        {
            continue;
        }

        char *p_key = p_trimmed_line;
        char *p_value = p_equal + 1;
        *p_equal = '\0';

        if (p_current_section == NULL)
        {
            continue;
        }

        Entry_t entry = {0};
        entry.type = ENTRY_TYPE_KEY_VALUE;
        entry.p_key = strdup(p_key);
        if (!entry.p_key)
        {
            fclose(p_file);
            pthread_rwlock_unlock(&p_ini_file->lock);
            return MEMORY_ALLOCATION_FAILED;
        }

        entry.p_value = strdup(p_value);
        if (!entry.p_value)
        {
            fclose(p_file);
            pthread_rwlock_unlock(&p_ini_file->lock);
            return MEMORY_ALLOCATION_FAILED;
        }

        Entry_t *p_temp_entries = realloc(p_current_section->p_entries, (p_current_section->entry_count + 1) * sizeof(Entry_t));
        if (!p_temp_entries)
        {
            fclose(p_file);
            pthread_rwlock_unlock(&p_ini_file->lock);
            return MEMORY_ALLOCATION_FAILED;
        }
        p_current_section->p_entries = p_temp_entries;
        memset(&p_current_section->p_entries[p_current_section->entry_count], 0, sizeof(Entry_t)); // Initialize the new entry
        p_current_section->p_entries[p_current_section->entry_count] = entry;
        p_current_section->entry_count++;
    }

    fclose(p_file);
    pthread_rwlock_unlock(&p_ini_file->lock);
    *p_ini_filename = p_ini_file;
    return INI_SUCCESS;
}

四、增、删、改、查、各个函数接口

1、增加

// 添加
int add_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key, const char *p_value)
{
    if (p_ini_file == NULL || p_section == NULL || p_key == NULL || p_value == NULL)
    {
        return PARAMETER_ERROR; // 参数错误
    }

    if (strchr(p_key, ' ') != NULL)
    {
        printf("No spaces allowed for key \n");
        return NO_SPACES_ALLOWED_FOR_KEY;
    }

    if (strchr(p_key, '#') != NULL || strchr(p_key, ';') != NULL)
    {
        printf("No (# or ;) allowed for key \n");
        return NO_COMMENT_FOR_KRY;
    }

    if (strlen(p_section) > LEN || strlen(p_key) + strlen(p_value) > LEN - 1)
    {
        printf("Input exceeds length\n");
        return INPUT_EXCEED_LENGTH;
    }

    pthread_rwlock_wrlock(&p_ini_file->lock);

    // 查找或创建节
    Section_t *p_sec = NULL;
    int i;
    for (i = 0; i < p_ini_file->section_count; i++)
    {
        if (p_ini_file->p_sections[i].p_name && strcmp(p_ini_file->p_sections[i].p_name, p_section) == 0)
        {
            p_sec = &p_ini_file->p_sections[i];
            break;
        }
    }

    if (p_sec == NULL)
    {
        // 创建新节
        p_ini_file->p_sections = realloc(p_ini_file->p_sections, (p_ini_file->section_count + 1) * sizeof(Section_t));
        if (p_ini_file->p_sections == NULL)
        {
            pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
            return MEMORY_ALLOCATION_FAILED;
        }

        p_sec = &p_ini_file->p_sections[p_ini_file->section_count++];
        p_sec->p_name = strdup(p_section);
        if (p_sec->p_name == NULL)
        {
            pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
            return MEMORY_ALLOCATION_FAILED;
        }

        p_sec->p_entries = NULL;
        p_sec->entry_count = 0;
    }
    for (i = 0; i < p_sec->entry_count; i++)
    {
        if (p_sec->p_entries[i].p_key && strcmp(p_sec->p_entries[i].p_key, p_key) == 0)
        {
            char *new_value = strdup(p_value);
            if (!new_value)
            {
                pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
                return MEMORY_ALLOCATION_FAILED;
            }
            free(p_sec->p_entries[i].p_value); // 释放旧的value的内存
            p_sec->p_entries[i].p_value = new_value;

            pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
            return INI_SUCCESS;                       // key已存在并已被更新,直接返回
        }
    }

    // 如果key在这个section中不存在,就添加新的key-value对
    p_sec->p_entries = realloc(p_sec->p_entries, (p_sec->entry_count + 1) * sizeof(Entry_t));
    if (p_sec->p_entries == NULL)
    {
        pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
        return MEMORY_ALLOCATION_FAILED;
    }

    Entry_t *p_entry = &p_sec->p_entries[p_sec->entry_count++];
    p_entry->type = ENTRY_TYPE_KEY_VALUE;
    p_entry->p_key = strdup(p_key);
    p_entry->p_value = strdup(p_value);
    p_entry->content = NULL;

    if (p_entry->p_key == NULL)
    {
        if (p_entry->p_key)
        {
            free(p_entry->p_key);
            p_entry->p_key = NULL;
        }
        if (p_entry->p_value)
        {
            free(p_entry->p_value);
            p_entry->p_value = NULL;
        }

        pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
        return KEY_CANNOT_BE_EMPTY;
    }

    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
    return INI_SUCCESS;
}

2、删除

// 删除
int delete_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key)
{
    if (p_ini_file == NULL || p_section == NULL || p_key == NULL)
    {
        return PARAMETER_ERROR; // 参数错误
    }

    if (strchr(p_key, ' ') != NULL)
    {
        return NO_SPACES_ALLOWED_FOR_KEY;
    }

    pthread_rwlock_wrlock(&p_ini_file->lock);

    // 查找节
    Section_t *p_sec = NULL;
    int i, j;
    for (i = 0; i < p_ini_file->section_count; i++)
    {
        if (p_ini_file->p_sections[i].p_name && strcmp(p_ini_file->p_sections[i].p_name, p_section) == 0)
        {
            p_sec = &p_ini_file->p_sections[i];
            break;
        }
    }

    if (p_sec == NULL)
    {
        pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
        return SECTION_NOT_FOUND;                 // 没有找到节
    }

    // 在找到的节中查找条目
    for (i = 0; i < p_sec->entry_count; i++)
    {
        if (p_sec->p_entries[i].p_key && strcmp(p_sec->p_entries[i].p_key, p_key) == 0)
        {
            // 找到条目,释放条目的key和value
            free(p_sec->p_entries[i].p_key);
            free(p_sec->p_entries[i].p_value);

            // 将后面的条目向前移动,覆盖当前条目
            for (j = i; j < p_sec->entry_count - 1; j++)
            {
                p_sec->p_entries[j] = p_sec->p_entries[j + 1];
            }

            // 缩小条目数组的大小
            p_sec->p_entries = realloc(p_sec->p_entries, (p_sec->entry_count - 1) * sizeof(Entry_t));
            p_sec->entry_count--;

            pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
            return INI_SUCCESS;                       // 成功
        }
    }

    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
    return ENTRIES_NOT_FOUND;                 // 没有找到条目
}

3、修改

// 修改
int modify_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key, const char *p_value)
{
    if (p_ini_file == NULL || p_section == NULL || p_key == NULL || p_value == NULL)
    {
        return PARAMETER_ERROR; // 参数错误
    }
    if (strchr(p_key, ' ') != NULL)
    {
        return NO_SPACES_ALLOWED_FOR_KEY;
    }
    pthread_rwlock_wrlock(&p_ini_file->lock);

    // 查找节
    Section_t *p_sec = NULL;
    int i;
    for (i = 0; i < p_ini_file->section_count; i++)
    {
        if (p_ini_file->p_sections[i].p_name && strcmp(p_ini_file->p_sections[i].p_name, p_section) == 0)
        {
            p_sec = &p_ini_file->p_sections[i];
            break;
        }
    }

    if (p_sec == NULL)
    {
        pthread_rwlock_unlock(&p_ini_file->lock);
        return SECTION_NOT_FOUND; // 没有找到节
    }

    // 在找到的节中查找条目
    for (i = 0; i < p_sec->entry_count; i++)
    {
        if (p_sec->p_entries[i].p_key && strcmp(p_sec->p_entries[i].p_key, p_key) == 0)
        {
            // 找到条目,释放旧的value
            free(p_sec->p_entries[i].p_value);

            // 设置新的value
            p_sec->p_entries[i].p_value = strdup(p_value);
            if (p_sec->p_entries[i].p_value == NULL)
            {
                pthread_rwlock_unlock(&p_ini_file->lock);
                return MEMORY_ALLOCATION_FAILED;
            }

            pthread_rwlock_unlock(&p_ini_file->lock);
            return INI_SUCCESS; // 成功
        }
    }

    pthread_rwlock_unlock(&p_ini_file->lock);
    return ENTRIES_NOT_FOUND; // 没有找到条目
}

4、查找

// 查找
const char *query_entry(INIFile_t *p_ini_file, const char *p_section, const char *p_key, int *return_code)
{
    if (p_ini_file == NULL || p_section == NULL || p_key == NULL)
    {
        *return_code = PARAMETER_ERROR;
        return NULL;
    }
    if (strchr(p_key, ' ') != NULL)
    {
        *return_code = NO_SPACES_ALLOWED_FOR_KEY;
        return NULL;
    }
    pthread_rwlock_rdlock(&p_ini_file->lock);

    // 查找节
    Section_t *p_sec = NULL;

    int i;
    for (i = 0; i < p_ini_file->section_count; i++)
    {
        if (p_ini_file->p_sections[i].p_name && strcmp(p_ini_file->p_sections[i].p_name, p_section) == 0)
        {
            p_sec = &p_ini_file->p_sections[i];
            break;
        }
    }

    if (p_sec == NULL)
    {
        pthread_rwlock_unlock(&p_ini_file->lock);
        *return_code = SECTION_NOT_FOUND;
        return NULL;
    }

    // 在找到的节中查找条目
    for (i = 0; i < p_sec->entry_count; i++)
    {
        if (p_sec->p_entries[i].p_key && strcmp(p_sec->p_entries[i].p_key, p_key) == 0)
        {
            // 找到条目,返回value
            pthread_rwlock_unlock(&p_ini_file->lock);
            *return_code = INI_SUCCESS;
            return p_sec->p_entries[i].p_value; // 成功
        }
    }

    pthread_rwlock_unlock(&p_ini_file->lock);
    *return_code = ENTRIES_NOT_FOUND;
    return NULL;
}

五、写文件

// 写文件
int write_ini_file(char *p_filename, INIFile_t *p_ini_file)
{
    pthread_rwlock_wrlock(&p_ini_file->lock);
    FILE *p_file = fopen(p_filename, "w");
    if (p_file == NULL)
    {
        pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
        return FAIL_TO_OPEN_FILE;
    }
    int i, j;
    for (i = 0; i < p_ini_file->section_count; i++)
    {
        Section_t *p_section = &p_ini_file->p_sections[i];

        if (strcmp(p_section->p_name, "DEFAULT_SECTION") != 0)
        {
            fprintf(p_file, "[%s]\n", p_section->p_name);
        }

        for (j = 0; j < p_section->entry_count; j++)
        {
            Entry_t *p_entry = &p_section->p_entries[j];

            switch (p_entry->type)
            {
            case ENTRY_TYPE_KEY_VALUE:
                if (p_entry->p_key == NULL)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
                    return KEY_CANNOT_BE_EMPTY;
                }
                char *format_str = "%s=%s\n";

                if (fprintf(p_file, format_str, p_entry->p_key, p_entry->p_value) < 0)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
                    return FAIL_TO_WRITE_TO_FILE;
                }
                break;

            case ENTRY_TYPE_COMMENT:
                if (fprintf(p_file, "%s\n", p_entry->content) < 0)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
                    return FAIL_TO_WRITE_TO_FILE;
                }
                break;

            case ENTRY_TYPE_EMPTY_LINE:
                if (fprintf(p_file, "\n") < 0)
                {
                    fclose(p_file);
                    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
                    return FAIL_TO_WRITE_TO_FILE;
                }
                break;
            }
        }
    }

    fclose(p_file);
    pthread_rwlock_unlock(&p_ini_file->lock); // 解锁
    return INI_SUCCESS;
}

别的程序可以直接引用这个静态库,用这个库的各个函数进行操作

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值