#define _CRT_SECURE_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <Windows.h> #include <string.h>
#define MAX_VALUE 64 #define TRIM_LIFT 1 #define TRIM_RIGHT 2 #define TRIM_SPACE 3
typedef struct _option { char key[MAX_VALUE]; char value[MAX_VALUE]; struct _option* next; }Option;
typedef struct _data { char section[MAX_VALUE]; Option* option; struct _data* next; }Data;
typedef struct { char comment; char separator; char re_string[MAX_VALUE]; int re_int; bool re_bool; double re_double; Data* data; }Config;
bool str_empty(const char* string) { return NULL == string || '\0' == *string; }
bool cnf_add_option(Config* cnf, const char* section, const char* key, const char* value) { if (NULL == cnf || str_empty(section) || str_empty(key) || str_empty(value)) { return false; }
Data* p = cnf->data; while (NULL != p && 0 != strcmp(p->section, section)) { p = p->next; }
if (NULL == p) { Data* ps = (Data*)malloc(sizeof(Data)); if (NULL == ps) { exit(-1); } strcpy(ps->section, section); ps->option = NULL; ps->next = cnf->data; cnf->data = p = ps; }
Option* q = p->option; while (NULL != q && 0 != strcmp(q->key, key)) { q = q->next; }
if (NULL == q) { q = (Option*)malloc(sizeof(Option)); if (NULL == q) { exit(-1); } strcpy(q->key, key); q->next = p->option; p->option = q; } strcpy(q->value, value);
return true; }
char* trim_string(char* string, int mode) { char* left = string; if ((mode & 1) != 0) { for (; *left != '\0'; left++) { if (0 == isspace(*left)) { break; } } } if ((mode & 2) != 0) { char* right = string - 1 + strlen(string); for (; right >= left; right--) { if (0 == isspace(*right)) { *(right + 1) = '\0'; break; } } } return left; }
Config* cnf_read_config(const char* filename, char comment, char separator) { Config* cnf = (Config*)malloc(sizeof(Config)); if (NULL == cnf) { exit(-1); } cnf->comment = comment; cnf->separator = separator; cnf->data = NULL;
if (str_empty(filename)) { return cnf; }
FILE* fp = fopen(filename, "r"); if (NULL == fp) { exit(errno); }
char* s, * e, * pLine, sLine[MAX_VALUE];
char section[MAX_VALUE] = { '\0' }, key[MAX_VALUE], value[MAX_VALUE]; while (NULL != fgets(sLine, MAX_VALUE, fp)) { pLine = trim_string(sLine, TRIM_SPACE); if (*pLine == '\0' || *pLine == comment) { continue; } s = strchr(pLine, comment); if (s != NULL) { *s = '\0'; }
s = strchr(pLine, '['); if (s != NULL) { e = strchr(++s, ']'); if (e != NULL) { *e = '\0'; strcpy(section, s); } } else { s = strchr(pLine, separator);
if (s != NULL && *section != '\0') { *s = '\0'; strcpy(key, trim_string(pLine, TRIM_RIGHT)); strcpy(value, trim_string(s + 1, TRIM_LIFT)); cnf_add_option(cnf, section, key, value); } } } fclose(fp); return cnf; }
bool cnf_get_value(Config* cnf, const char* section, const char* key) { Data* p = cnf->data; while (NULL != p && 0 != strcmp(p->section, section)) { p = p->next; }
if (NULL == p) { return false; }
Option* q = p->option; while (NULL != q && 0 != strcmp(q->key, key)) { q = q->next; }
if (NULL == q) { return false; }
strcpy(cnf->re_string, q->value); cnf->re_int = atoi(cnf->re_string); cnf->re_bool = 0 == strcmp("true", cnf->re_string); cnf->re_double = atof(cnf->re_string);
return true; }
Data* cnf_has_section(Config* cnf, const char* section) { Data* p = cnf->data; while (NULL != p && 0 != strcmp(p->section, section)) { p = p->next; }
if (NULL == p) { return NULL; }
return p; }
Option* cnf_has_option(Config* cnf, const char* section, const char* key) { Data* p = cnf_has_section(cnf, section); if (NULL == p) { return NULL; }
Option* q = p->option; while (NULL != q && 0 != strcmp(q->key, key)) { q = q->next; } if (NULL == q) { return NULL; }
return q; }
bool cnf_write_file(Config* cnf, const char* filename, const char* header) { FILE* fp = fopen(filename, "w"); if (NULL == fp) { exit(errno); }
if (!str_empty(header)) { fprintf(fp, "%c %s\n\n", cnf->comment, header); }
Option* q; Data* p = cnf->data; while (NULL != p) { fprintf(fp, "[%s]\n", p->section); q = p->option; while (NULL != q) { fprintf(fp, "%s %c %s\n", q->key, cnf->separator, q->value); q = q->next; } p = p->next; } fclose(fp); return true; }
bool cnf_remove_option(Config* cnf, const char* section, const char* key) { Data* ps = cnf_has_section(cnf, section); if (NULL == ps) { return false; }
Option* p, * q; q = p = ps->option; while (NULL != p && 0 != strcmp(p->key, key)) { if (p != q) { q = q->next; } p = p->next; }
if (NULL == p) { return false; }
if (p == q) { ps->option = p->next; } else { q->next = p->next; }
free(p); q = p = NULL; return true; }
bool cnf_remove_section(Config* cnf, const char* section) { if (str_empty(section)) { return false; }
Data* p, * q;
q = p = cnf->data; while (NULL != p && 0 != strcmp(p->section, section)) { if (p != q) { q = q->next; } p = p->next; }
if (NULL == p) { return false; }
if (p == q) { cnf->data = p->next; } else { q->next = p->next; }
Option* ot, * o = p->option; while (NULL != o) { ot = o; o = o->next; free(ot); } p->option = NULL; free(p); q = p = NULL; return true; }
void destroy_config(Config** cnf) { if (NULL != *cnf) { if (NULL != (*cnf)->data) { Data* pt, * p = (*cnf)->data; Option* qt, * q; while (NULL != p) { q = p->option; while (NULL != q) { qt = q; q = q->next; free(qt); } pt = p; p = p->next; free(pt); } } free(*cnf); *cnf = NULL; } }
void print_config(Config* cnf) { Data* p = cnf->data; while (NULL != p) { printf("[%s]\n", p->section); Option* q = p->option; while (NULL != q) { printf("%s%c%s\n", q->key, cnf->separator, q->value); q = q->next; } p = p->next; } }
int main(int argc, char* argv[]) { Config* cnf = cnf_read_config("d://config.ini", '#', '='); if (NULL == cnf) { return -1; }
cnf_add_option(cnf, "Server", "Address", "192.168.1.1"); cnf_add_option(cnf, "Server", "Port", "99"); cnf_add_option(cnf, "Server", "Enabled", "True");
cnf_add_option(cnf, "Client", "ClientID", "10001"); cnf_add_option(cnf, "Client", "ClientName", "lyshark"); cnf_add_option(cnf, "Client", "ClientEnabled", "False");
cnf_get_value(cnf, "Server", "Address"); printf("读入IP地址: %s \n", cnf->re_string);
cnf_get_value(cnf, "Server", "Port"); printf("读入端口: %d \n", cnf->re_int);
cnf_get_value(cnf, "Client", "ClientEnabled"); printf("读入状态: %s \n", cnf->re_string);
cnf_add_option(cnf, "Server", "Address", "192.168.1.100");
cnf_remove_option(cnf, "Server", "Eanbled"); cnf_remove_section(cnf, "Client");
bool ref = cnf_write_file(cnf, "d://config_new.ini", "配置文件解析 Ver 1.0"); if (ref == 1) { std::cout << "已写出" << std::endl; destroy_config(&cnf); } return 0; }
|