首页 > 代码库 > C语言ini格式配置文件的读写

C语言ini格式配置文件的读写

依赖的类

技术分享
 1 /*1 utils.h 2  *# A variety of utility functions. 3  *#  4  *# Some of the functions are duplicates of well known C functions that are not  5  *# standard. 6  *2 License 7  *[ 8  *# Author: Werner Stoop 9  *# This software is provided under the terms of the unlicense.10  *# See http://unlicense.org/ for more details.11  *]12  *2 API13  */14 #include "stdafx.h"15 /*@ MY_MIN(a,b)16  *# Macro that returns the smallest of its parameters.\n17  *# As with all macros, {{a}} and {{b}} should not have side effects.18  */19 #define MY_MIN(a,b) (((a)<(b))?(a):(b))20  21 /*@ MY_MAX(a,b)22  *# Macro that returns the largest of its parameters.\n23  *# As with all macros, {{a}} and {{b}} should not have side effects.24  */25 #define MY_MAX(a,b) (((a)>(b))?(a):(b))26 27 /*@ int my_stricmp(const char *p, const char *q)28  *# Compares two strings {{p}} and {{q}} case insensitively.29  *#30  *# It returns 0 if the strings are the same, a positive number if {{p}} comes after {{q}},31  *# and negative if {{p}} comes before {{q}}.32  */33 int my_stricmp(const char *p, const char *q);34 35 /*@ char *my_strdup(const char *s)36  *# Creates a duplicate of a string {{s}} in a dynamic memory buffer.\n37  *# The returned buffer needs to be {{free()}}d after use. It may return38  *# {{NULL}} if the memory allocation fails.39  */40 char *my_strdup(const char *s);41 42 /*@ char *my_strlower (char *p)43  *# Converts a string {{p}} to lowercase in place.44  *# It returns {{p}}.45  */46 char *my_strlower (char *p);47 48 /*@ char *my_strupper (char *p)49  *# Converts a string {{p}} to uppercase in place.50  *# It returns {{p}}.51  */52 char *my_strupper (char *p);53 54 /*@ char *my_strtok_r(char *str, const char *delim, char **saveptr)55  *# Works the same as {{strtok_r(3)}} for platforms which lack it.56  */57 char *my_strtok_r(char *str, const char *delim, char **saveptr);58 59 /*@ char *my_readfile (const char *fn)60  *# Reads an entire file identified by {{fn}} into a dynamically allocated memory buffer.\n61  *# The returned buffer needs to be {{free()}}d afterwards.\n62  *# It returns {{NULL}} if the file could not be read.63  */64 char *my_readfile (const char *fn);
utils.h

 

技术分享
 1 /* 2  * A variety of utility functions. 3  * 4  * See utils.h for more info 5  * 6  * This is free and unencumbered software released into the public domain. 7  * http://unlicense.org/ 8  */ 9 #include "stdafx.h"10 #include <stdlib.h>11 #include <string.h>12 #include <stdio.h>13 #include <ctype.h>14 15 /* Case insensitive strcmp()16  */ 17 int my_stricmp(const char *p, const char *q) { 18     for(;*p && tolower(*p) == tolower(*q); p++, q++);19     return tolower(*p) - tolower(*q);20 } 21 22 /* strdup() is not ANSI C */23 char *my_strdup(const char *s) {24     char *a;25     size_t len = strlen(s);26     a = (char*)malloc(len + 1);27     if(!a) return NULL;28     memcpy(a, s, len + 1);    29     return a;30 }31 32 /* converts a string to lowercase */33 char *my_strlower (char *p) {34   char *s;35   for (s = p; s[0]; s++)36     s[0] = tolower (s[0]);37 38   return p;39 }40 41 /* converts a string to lowercase */42 char *my_strupper (char *p)43 {44   char *s;45   for (s = p; s[0]; s++)46     s[0] = toupper (s[0]);47 48   return p;49 }50 51 char *my_strtok_r(char *str, const char *delim, char **saveptr) {52     if(!str)53         str = *saveptr;54     if(!str[0]) {55         *saveptr = str;56         return NULL;    57     }58     char *s = strpbrk(str, delim);59     if(s) {60         s[0] = \0;61         *saveptr = s + 1;62     } else 63         for(*saveptr = str; (*saveptr)[0]; (*saveptr)++);64     return str;65 }66 67 /* Reads an entire file into a dynamically allocated memory buffer.68  * The returned buffer needs to be free()d afterwards69  */70 char *my_readfile(const char *fname) {71     FILE *f;72     long len,r;73     char *str;74     75     if(!(f = fopen(fname, "rb")))    76         return NULL;77     78     fseek(f, 0, SEEK_END);79     len = ftell(f);80     rewind(f);81     82     if(!(str = (char*)malloc(len+2)))83         return NULL;    84     r = fread(str, 1, len, f);85     86     if(r != len) {87         free(str);88         return NULL;89     }90     91     fclose(f);    92     str[len] = \0;93     return str;94 }
utils.cpp

ini格式配置文件的读写

技术分享
  1 /*1 ini.h  2  *#    Header file for the {*INI*} parser.\n  3  *#   4  *#    This is a simple parser for {*.INI*} files.   5  *#    It is based around the syntax described in the Wikipedia entry at  6  *#    {_http://en.wikipedia.org/wiki/INI_file_}\n   7  *#  8  *# The API has these features:  9  *{ 10  ** Use {{~~ini_read()}} to read an INI file from the disc into an {{~~ini_file}}  11  *#   structure or create an empty {{~~ini_file}} structure. 12  ** Use {{~~ini_get()}} to retrieve values from the {{~~ini_file}} structure. 13  ** Use {{~~ini_put()}} and {{~~ini_putf()}} to set values in the {{~~ini_file}} structure. 14  ** Use {{~~ini_write()}} to write the contents of the {{~~ini_file}} structure back to disc. 15  ** Use {{~~ini_free()}} to deallocate the {{~~ini_file}} structure.  16  ** {{~~ini_errstr()}} is used for reporting errors. 17  *} 18  *2 License 19  *[ 20  *# Author: Werner Stoop 21  *# This software is provided under the terms of the unlicense. 22  *# See http://unlicense.org/ for more details. 23  *] 24  *2 API 25  */ 26 #ifndef INI_H 27 #define INI_H 28  29 #if defined(__cplusplus) 30 extern "C" { 31 #endif 32  33 /* 34  *    Encapsulates a parameter-value pair in an INI section. 35  *    Parameters are stored in a binary search tree, which attempts (but does not 36  *    guarantee) O(log(n)) behaviour. 37  */ 38 typedef struct INI_PAIR 39 { 40     char *param;        /* The parameter */ 41     char *value;        /* Its value */ 42      43     /* Nodes in the tree */ 44     struct INI_PAIR *left, *right;         45 } ini_pair; 46  47 /* 48  *    Encapsulates a section within a INI file. 49  *    Sections are stored in a binary search tree, which attempts (but does not 50  *    guarantee) O(log(n)) behaviour. 51  */ 52 typedef struct INI_SECTION 53 { 54     char *name;            /* Name of the section */ 55     ini_pair *fields;    /* Fields in the section */ 56      57     /* Nodes in the tree */ 58     struct INI_SECTION *left, *right; 59 } ini_section; 60  61 /*@ struct ##ini_file; 62  *#    Structure to encapsulate an INI file. 63  */ 64 struct ini_file 65 { 66     ini_pair     *globals; 67     ini_section *sections; 68 }; 69  70 /*@ ini_file *##ini_read(const char *filename, int *err, int *line); 71  *#    Reads an INI file named by {{filename}} and returns it as a {{~~ini_file}} object. 72  *#    If {{filename}} is {{NULL}}, an empty {{ini_file}} object is created and returned. 73  *#    Comments are discarded, so a later call to {{~~ini_write()}} will be 74  *#    commentless.\n 75  *# It returns {{NULL}} if the INI file couldn‘t be read, in which case {{err}} will contain the error code 76  *# (see {{~~ini_errstr()}}) and {{line}} will contain the line in the file where the error occured. 77  *# ({{err}} and {{line}} may be {{NULL}}). 78  */ 79 struct ini_file *ini_read(const char *filename, int *err, int *line); 80  81 /*@ ini_file *##ini_parse(const char *text, int *err, int *line); 82  *# Parses a null-terminated string {{text}} as an INI file.\n 83  *# It returns {{NULL}} if the INI file couldn‘t be read, in which case {{err}} will contain the error code 84  *# (see {{~~ini_errstr()}}) and {{line}} will contain the line in the file where the error occured. 85  *# ({{err}} and {{line}} may be {{NULL}}). 86  */ 87 struct ini_file *ini_parse(const char *text, int *err, int *line); 88  89 /*@ int ##ini_write(ini_file *ini, const char *fname); 90  *#    Saves all the sections and parameters in an {{ini_file}} to a file.\n 91  *#    {{fname}} is the file to which to save. If {{fname}} is {{NULL}}, it is written to  92  *#    {{stdout}}. 93  *# It returns 1 on success, an error code otherwise (see {{~~ini_errstr()}}). 94  */ 95 int ini_write(struct ini_file *ini, const char *fname); 96  97 /*@ void ##ini_free(ini_file *ini); 98  *#    Free‘s all the memory allocated to a {{ini_file}} object created in {{~~ini_read()}}.\n 99  *#    {{ini}} is the {{ini_file}} to free100  */101 void ini_free(struct ini_file *ini);102 103 /*@ int ini_has_section(struct ini_file *ini, const char *sec)104  *# Returns true if the ini file has a specific section.105  */106 int ini_has_section(struct ini_file *ini, const char *sec);107 108 /*@ const char *##ini_get(struct ini_file *ini, const char *sec, const char *par, const char *def);109  *#    Retrieves a parameter {{par}} from a section {{sec}} within the struct ini_file {{ini}}110  *#    and returns its value.\n111  *#    If {{sec}} is {{NULL}}, the global parameters in {{ini}} are searched.\n112  *#    If the value is not found, the default {{def}}, which may be {{NULL}}, is 113  *#    returned.114  */115 const char *ini_get(struct ini_file *ini, 116                     const char *sec, 117                     const char *par, 118                     const char *def);119 120 /*@ int ##ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val);121  *#    Sets a parameter {{par}} in section {{sec}}‘s value to {{val}}, replacing the 122  *#    current value if it already exists, or creates the section if it does not 123  *#    exist.\n124  *#    If {{sec}} is {{NULL}}, the parameter is added to {{ini}}‘s global parameters.\n125  *# It returns 1 on success, 0 on failure (which only happens if {{malloc()}} fails).126  */127 int ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val);128 129 /*@ int ##ini_putf(struct ini_file *ini, const char *sec, const char *par, const char *fmt, ...);130  *#    {{~~ini_putf()}} takes a {{printf()}} style format string and uses vsnprintf() to131  *#    pass a value to {{~~ini_put()}}. This function is intended for placing 132  *#    data types that are not strings into the {{ini_file}}133  *#    134  *#    The other parameters are the same as those of {{ini_put()}}.135  */136 int ini_putf(struct ini_file *ini, 137             const char *sec, 138             const char *par, 139             const char *fmt, 140             ...);141 142 /*@ const char *##ini_errstr(int err)143  *# Returns a textual description of an error code144  */145 const char *ini_errstr(int err);146             147 #if defined(__cplusplus)148 } /* extern "C" */149 #endif150 151 #endif /* INI_H */
ini.h

 

技术分享
  1 /*  2  *    This is a simple parser for .INI files.  3  *    It is based around the syntax described in the Wikipedia entry at  4  *    "http://en.wikipedia.org/wiki/INI_file"  5  *  6  * See ini.h for more info  7  *  8  * This is free and unencumbered software released into the public domain.  9  * http://unlicense.org/ 10  */ 11 #include "stdafx.h" 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <stdarg.h> 16 #include <ctype.h> 17 #include <setjmp.h> 18  19 #include <assert.h> /* Remember to define NDEBUG for release */ 20  21 #include "ini.h" 22 #include "utils.h" 23 #include <crtdbg.h> 24  25 /* Maximum number of characters expected on a line. 26 It is only used by the ini_putf() function. 27 */ 28 #define MAX_LINE        1024 29  30 /* Various error codes */ 31 #define SUCCESS                          1 32 #define FILE_CREATED                  0 33 #define NO_SUCH_FILE                  -1 34 #define OUT_OF_MEMORY                  -2 35 #define MISSING_END_BRACE             -3 36 #define EMPTY_SECTION                  -4 37 #define EXPECTED_EQUALS             -5 38 #define EXPECTED_END_OF_STRING         -6 39 #define ER_FOPEN                     -7 40 #define BAD_SYMBOL                     -8 41 #define EXPECTED_PARAMETER            -9 42 #define EXPECTED_VALUE                -10 43  44 const char *ini_errstr(int err) 45 { 46     switch(err) 47     { 48         case SUCCESS : return "Success"; 49         case FILE_CREATED: return "New INI object created"; 50         case NO_SUCH_FILE: return "Unable to open file"; 51         case OUT_OF_MEMORY: return "Out of memory"; 52         case MISSING_END_BRACE: return "Missing ‘]‘ at end of section"; 53         case EMPTY_SECTION: return "Empty [] for section"; 54         case EXPECTED_EQUALS : return "Expected an ‘=‘/‘:‘"; 55         case EXPECTED_END_OF_STRING : return "Expected an end of string"; 56         case ER_FOPEN : return "Unable to open file"; 57         case BAD_SYMBOL : return "Bad symbol"; 58         case EXPECTED_PARAMETER : return "Expected a parameter (or section)"; 59         case EXPECTED_VALUE : return "Expected a value"; 60     } 61     return "Unknown"; 62 } 63  64 /** Configurable parameters *************************************************/ 65  66 /* 67  *    Recursively adds sections to the tree of sections 68  */ 69 static void insert_section(ini_section *r, ini_section *n) { 70     assert(r); 71     assert(n); 72  73     if(my_stricmp(r->name, n->name) < 0) { 74         if(!r->left) 75             r->left = n; 76         else 77             insert_section(r->left, n); 78     } else { 79         if(!r->right) 80             r->right = n; 81         else 82             insert_section(r->right, n); 83     } 84 } 85  86 /* 87  *    Searches a tree of pairs for a specific parameter 88  */ 89 static ini_pair *find_pair(ini_pair *root, const char *name) { 90     int c; 91  92     if(!root) return NULL; 93  94     c = my_stricmp(root->param, name); 95     if(c == 0) 96         return root; 97     else if(c < 0) 98         return find_pair(root->left, name); 99     else100         return find_pair(root->right, name);101 }102 103 /*104  *    Searches for a specific section105  */106 static ini_section *find_section(ini_section *root, const char *name) {107     int c;108 109     if(!root) return NULL;110 111     c = my_stricmp(root->name, name);112     if(c == 0)113         return root;114     else if(c < 0)115         return find_section(root->left, name);116     else117         return find_section(root->right, name);118 }119 120 /*121  *    Creates a new section, and adds it to a tree of sections122  */123 static ini_section *add_section(ini_section **root, char *name) {124     ini_section *n;125 126     assert(root);127     assert(name);128 129     n = find_section(*root, name);130     if(n) {131         free(name);132         return n;133     }134 135     n = (ini_section*)malloc(sizeof *n);136     if(!n) return NULL;137 138     n->name = name;139 140     n->fields = NULL;141     n->left = n->right = NULL;142 143     if(*root)144         insert_section(*root, n);145     else146         *root = n;147 148     return n;149 }150 151 /*152  *    Inserts a new pair n into a pair tree p153  */154 static void insert_pair(ini_pair *p, ini_pair *n) {155     if(my_stricmp(p->param, n->param) < 0) {156         if(!p->left)157             p->left = n;158         else159             insert_pair(p->left, n);160     } else {161         if(!p->right)162             p->right = n;163         else164             insert_pair(p->right, n);165     }166 }167 168 /*169  *    Adds a parameter-value pair to section s170  */171 static ini_pair *add_pair(ini_section *s, char *p, char *v) {172     ini_pair *n;173 174     assert(s);175 176     n = (ini_pair*)malloc(sizeof *n);177     if(!n) return NULL;178 179     n->param = p;180     n->value =http://www.mamicode.com/ v;181 182     n->left = n->right = NULL;183 184     if(!s->fields)185         s->fields = n;186     else187         insert_pair(s->fields, n);188 189     return n;190 }191 192 /** Functions for memory deallocation ***************************************/193 194 /*195  *    Free‘s a tree of parameter-value pairs196  */197 static void free_pair(ini_pair *p) {198     if(!p) return;199 200     free_pair(p->left);201     free_pair(p->right);202 203     free(p->param);204     free(p->value);205     free(p);206 }207 208 /*209  *    Free‘s all the memory allocated to a ini_section s210  */211 static void free_section(ini_section *s) {212     if(!s) return;213 214     free_section(s->left);215     free_section(s->right);216 217     free(s->name);218     free_pair(s->fields);219     free(s);220 }221 222 /*223  *    Free‘s all the memory allocated to a ini_file object in ini_read()224  */225 void ini_free(struct ini_file *ini) {226     if(!ini) return;227     free_pair(ini->globals);228     free_section(ini->sections);229     free(ini);230 }231 232 /** Parsing functions *******************************************************/233 234 static struct ini_file *make_ini() 235 {236     struct ini_file *ini = (ini_file*)malloc(sizeof *ini);237     if(!ini) return NULL;238     ini->globals = NULL;239     ini->sections = NULL;240     return ini;241 }242 243 /*244  *    Reads an INI file and returns it as a ini_file object.245  *    If filename is NULL, an empty ini_file object is created and returned.246  */247 struct ini_file *ini_read(const char *filename, int *err, int *line) {248     if(line) *line = 0;249     if(!filename)250     {251         if(err) *err = FILE_CREATED;252         return make_ini();253     } 254     else 255     {256         char *text = my_readfile(filename);257         if(!text) {258             if(err) *err = NO_SUCH_FILE;259             return NULL;260         }261         struct ini_file * ini = ini_parse(text, err, line);262         free(text);263         return ini;264     }265 }266 267 #define T_END        0268 #define T_VALUE        1269 270 static int get_token(const char **tp, const char **tstart, const char **tend, int *line, jmp_buf err) {271     /* *tstart points to the start of the token, while *tend points one char past the end */272 273     const char *t = *tp;274     int tok = T_END;275 276     assert(tp && tstart && tend);277 278 whitespace:279     while(isspace(t[0])) {280         if(t[0] == \n && line)281             (*line)++;282         t++;283     }284     if(t[0] == ; || t[0] == #) {285         while(t[0] != \n && t[0] != \0)286             t++;287         goto whitespace;288     }289 290     *tstart = t;291     *tend = t;292     if(t[0]) {293         if(strchr("[]:=", t[0])) {294             tok = *t++;295         } else if(isgraph(t[0]) && !strchr("\"‘[];#", t[0])) {296             while(isgraph(t[0]) && !strchr("\"‘[];#", t[0])) {297                 t++;298             }299             *tend = t;300             tok = T_VALUE;301         } else if(t[0] == \" || t[0] == \‘) {302             char delim = t[0];303             if(t[1] == delim && t[2] == delim) {304                 /* """Python style long strings""" */305                 t += 3;306                 *tstart = t;307                 while(!(t[0] == delim && t[1] == delim && t[2] == delim)) {308                     if(t[0] == \0) {309                         longjmp(err, EXPECTED_END_OF_STRING);310                     } else if(t[0] == \\)311                         t++;312                     t++;313                 }314                 *tend = t;315                 t+=3;316             } else {317                 *tstart = ++t;318                 while(t[0] != delim) {319                     if(t[0] == \0 || t[0] == \n) {320                         longjmp(err, EXPECTED_END_OF_STRING);321                     } else if(t[0] == \\)322                         t++;323                     t++;324                 }325                 *tend = t++;326             }327             tok = T_VALUE;328         } else {329             /* Unrecognized token */330             longjmp(err, BAD_SYMBOL);331         }332     }333 334     *tp = t;335     return tok;336 }337 338 static char *get_string(const char *tstart, const char *tend, jmp_buf err) 339 {340     char *string, *s;341     const char *i;342 343     assert(tend > tstart);344     string = (char*)malloc(tend - tstart + 1);345     if(!string)346         longjmp(err, OUT_OF_MEMORY);347 348     for(i = tstart, s = string; i < tend; i++) {349         if(i[0] == \\) {350             switch(*++i) {351                 case \\:352                 case \‘:353                 case \": *s++ = i[0]; break;354                 case r: *s++ = \r; break;355                 case n: *s++ = \n; break;356                 case t: *s++ = \t; break;357                 case 0: *s++ = \0; break;358                 default: break;359             }360         } else {361             *s++ = i[0];362         }363     }364     assert(s - string <= tend - tstart);365     s[0] = \0;366     return string;367 }368 369 struct ini_file *ini_parse(const char *text, int *err, int *line) {370     jmp_buf on_error;371     int e_code;372 373     struct ini_file *ini = NULL;374     ini_section *cur_sec = NULL;375 376     const char *tstart, *tend;377 378     int t;379 380     if(err) *err = SUCCESS;381     if(line) *line = 1;382 383     ini = make_ini();384 385     if((e_code = setjmp(on_error)) != 0) {386         if(err) *err = e_code;387         ini_free(ini);388         return NULL;389     }390 391     while((t = get_token(&text, &tstart, &tend, line, on_error)) != T_END) {392         if(t == [) {393             char *section_name;394             if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {395                 longjmp(on_error, EMPTY_SECTION);396             }397 398             section_name = get_string(tstart, tend, on_error);399 400             cur_sec = add_section(&ini->sections, section_name);401             if(!cur_sec)402                 longjmp(on_error, OUT_OF_MEMORY);403 404             if(get_token(&text, &tstart, &tend, line, on_error) != ]) {405                 longjmp(on_error, MISSING_END_BRACE);406             }407 408         } else if (t == T_VALUE ) {409             char *par, *val;410             par = get_string(tstart, tend, on_error);411             t = get_token(&text, &tstart, &tend, line, on_error);412             if(t != = && t != :) {413                 longjmp(on_error, EXPECTED_EQUALS);414             }415             if(get_token(&text, &tstart, &tend, line, on_error) != T_VALUE) {416                 longjmp(on_error, EXPECTED_VALUE);417             }418             val = get_string(tstart, tend, on_error);419 420             if(cur_sec)421                 add_pair(cur_sec, par, val);422             else {423                 /* Add the parameter and value to the INI file‘s globals */424                 ini_pair *pair;425                 if(!(pair = (ini_pair*)malloc(sizeof *pair)))426                     longjmp(on_error, OUT_OF_MEMORY);427 428                 pair->param = par;429                 pair->value =http://www.mamicode.com/ val;430 431                 pair->left = pair->right = NULL;432 433                 if(!ini->globals)434                     ini->globals = pair;435                 else436                     insert_pair(ini->globals, pair);437             }438 439 440         } else441             longjmp(on_error, EXPECTED_PARAMETER);442     }443 444     return ini;445 }446 447 /** Printing functions ******************************************************/448 449 static void string_to_file(FILE *f, const char *s) {450     fputc(\", f);451     for(; s[0]; s++) {452         switch(s[0]) {453             case \n: fputs("\\n",f); break;454             case \r: fputs("\\r",f); break;455             case \t: fputs("\\t",f); break;456             case \": fputs("\\\"",f); break;457             case \‘: fputs("\\\‘",f); break;458             case \\: fputs("\\\\",f); break;459             default : fputc(s[0], f); break;460         }461     }462     fputc(\", f);463 }464 465 /*466  *    Recursively prints a tree of ini_pairs467  */468 static void write_pair(ini_pair *p, FILE *f) {469     if(!p) return;470 471     string_to_file(f, p->param);472     fputs(" = ", f);473     string_to_file(f, p->value);474     fputc(\n, f);475 476     write_pair(p->left, f);477     write_pair(p->right, f);478 }479 480 /*481  *    Recursively prints a tree of INI sections482  */483 static void write_section(ini_section *s, FILE *f) {484     if(!s) return;485 486     fputs("\n[", f);487     string_to_file(f, s->name);488     fputs("]\n", f);489 490     write_pair(s->fields, f);491 492     /* The akward sequence is to ensure that values are not written sorted */493 494     write_section(s->left, f);495     write_section(s->right, f);496 }497 498 /*499  *    Saves all the sections and parameters in an ini_file to a file.500  *    If fname is NULL, it is written to stdout.501  */502 int ini_write(struct ini_file *ini, const char *fname) {503     FILE *f;504 505     if(fname) {506         f = fopen(fname, "w");507         if(!f)508             return ER_FOPEN;509     } else510         f = stdout;511 512     write_pair(ini->globals, f);513     write_section(ini->sections, f);514 515     if(fname)516         fclose(f);517 518     return SUCCESS;519 }520 521 /****************************************************************************/522 523 int ini_has_section(struct ini_file *ini, const char *sec) {524     return find_section(ini->sections, sec) != NULL;525 }526 527 /*528  *    Finds a specific parameter-value pair in the configuration file529  */530 static ini_pair *find_param(const struct ini_file *ini,531                             const char *sec,532                             const char *par) {533     ini_section *s;534     ini_pair *p;535 536     if(!ini) return NULL;537 538     if(sec) {539         s = find_section(ini->sections, sec);540         if(!s) return NULL;541         p = s->fields;542     } else543         p = ini->globals;544 545     if(!p) return NULL;546 547     return find_pair(p, par);548 }549 550 /*551  *    Retrieves a parameter ‘par‘ from a section ‘sec‘ within the ini_file ‘ini‘552  *    and returns its value.553  *    If ‘sec‘ is NULL, the global parameters ini ‘ini‘ are searched.554  *    If the value is not found, ‘def‘ is returned.555  *    It returns a string. Functions like atoi(), atof(), strtol() and even556  *    sscanf() can be used to convert it to the relevant type.557  */558 const char *ini_get(struct ini_file *ini,559                     const char *sec,560                     const char *par,561                     const char *def) {562     ini_pair *p;563 564     p = find_param(ini, sec, par);565     if(!p) {566         if(def)567             ini_put(ini, sec, par, def);568         return def;569     }570 571     return p->value;572 }573 574 /*575  *    Sets a parameter ‘par‘ in section ‘sec‘s value to ‘val‘, replacing the576  *    current value if it already exists, or creates the section if it does not577  *    exist578  */579 int ini_put(struct ini_file *ini, const char *sec, const char *par, const char *val) {580     ini_section *s;581     ini_pair *p, **pp;582 583     if(!ini || !val) return 0;584 585     p = find_param(ini, sec, par);586     if(p) {587         /* Replace the existing value */588         char *t = p->value;589         if(!(p->value =http://www.mamicode.com/ my_strdup(val))) {590             p->value =http://www.mamicode.com/ t;591             return 0;592         }593 594         free(t);595         return 1;596     }597 598     if(sec) {599         s = find_section(ini->sections, sec);600         if(!s) {601             /* Create a new section */602             if(!(s = (ini_section*)malloc(sizeof *s))) return 0;603             if(!(s->name = my_strdup(sec))) {604                 free(s);605                 return 0;606             }607 608             s->fields = NULL;609             s->left = s->right = NULL;610 611             if(ini->sections)612                 insert_section(ini->sections, s);613             else614                 ini->sections = s;615         }616 617         pp = &s->fields;618     } else619         pp = &ini->globals;620 621     if(!(p = (ini_pair*)malloc(sizeof *p)))622         return 0;623 624     if(!(p->param = my_strdup(par)) || !(p->value =http://www.mamicode.com/ my_strdup(val))) {625         free(p);626         return 0;627     }628 629     p->left = p->right = NULL;630 631     if(!*pp)632         *pp = p;633     else634         insert_pair(*pp, p);635 636     return 1;637 }638 639 /*640  *    ini_putf() takes a printf() style format string and uses vsnprintf() to641  *    pass a value to ini_put(). This function is intended for placing642  *    data types that are not strings into the ini_file643  *644  *    The other parameters are the same as those of ini_put().645  */646 int ini_putf(struct ini_file *ini,647             const char *sec,648             const char *par,649             const char *fmt,650             ...) {651     char buffer[MAX_LINE];652     va_list arg;653 654     va_start(arg, fmt);655 656 #ifdef _MSC_VER /* Microsoft Visual C++? */657     /* VC++ messes around with _‘s before vsnprintf(): */658 #define    vsnprintf _vsnprintf659 #endif660 661 #if 1662     vsnprintf(buffer, MAX_LINE, fmt, arg);663 #else664     vsprintf(buffer, fmt, arg );665     assert(strlen(buffer) < MAX_LINE);666 #endif667     va_end(arg);668 669     return ini_put(ini, sec, par, buffer);670 }
ini.cpp

调用

  1 static struct ini_file *gamedb = NULL;  2 BOOL CRobomoduleTestDlg::ResetConfig()  3 {  4     ini_put(gamedb, "System", "Half", "0");  5     ini_put(gamedb, "InitialPose", "X", "0.0");  6     ini_put(gamedb, "InitialPose", "Y", "0.0");  7     ini_put(gamedb, "InitialPose", "theta", "0.0");  8   9     ini_put(gamedb, "TilingUnit_Pose", "XTrans", "0.0"); 10     ini_put(gamedb, "TilingUnit_Pose", "YTrans", "0.0"); 11     ini_put(gamedb, "TilingUnit_Pose", "Height", "1.10"); 12  13     ini_put(gamedb, "Laser_TilingUnitO", "RotateX", "0.0"); 14     ini_put(gamedb, "Laser_TilingUnitO", "RotateY", "0.0"); 15     ini_put(gamedb, "Laser_TilingUnitO", "RotateZ", "0.785398163"); 16  17     ini_put(gamedb, "Laser_TilingUnitO", "TransformX", "0.165"); 18     ini_put(gamedb, "Laser_TilingUnitO", "TransformY", "0.0"); 19     ini_put(gamedb, "Laser_TilingUnitO", "TransformZ", "0.0"); 20  21     ini_put(gamedb, "LaserO", "CalibRotateX", "-0.023289177"); 22     ini_put(gamedb, "LaserO", "CalibRotateY", "0.0"); 23     ini_put(gamedb, "LaserO", "CalibRotateZ", "-0.01573419"); 24  25     ini_put(gamedb, "LaserO", "CalibTransformX", "0.0"); 26     ini_put(gamedb, "LaserO", "CalibTransformY", "0.0"); 27     ini_put(gamedb, "LaserO", "CalibTransformZ", "0.0"); 28  29     char buffer[256]; 30     _snprintf(buffer, sizeof buffer, "%s/%s", "D:", "config.ini"); 31  32     int result = ini_write(gamedb,"config.ini"); 33     ini_free(gamedb); 34  35     gamedb=NULL    ; 36     return TRUE; 37 } 38  39 BOOL CRobomoduleTestDlg::OnInitDialog() 40 { 41     CDialog::OnInitDialog(); 42     ini_free(gamedb); 43     gamedb = ini_read(NULL, NULL, NULL); 44     int err, line; 45     ini_free(gamedb); 46     gamedb = ini_read("config.ini", &err, &line); 47     if(ini_get(gamedb,"InitialPose", "X", NULL) != NULL)  48     { 49         const char* a=ini_get(gamedb, "InitialPose", "X", NULL); 50         InitialPoseX= atof(a); 51     } 52     if(ini_get(gamedb,"InitialPose", "Y", NULL) != NULL)  53     { 54         const char* a=ini_get(gamedb, "InitialPose", "Y", NULL); 55         InitialPoseY= atof(a); 56     } 57     if(ini_get(gamedb,"InitialPose", "theta", NULL) != NULL)  58     { 59         const char* a=ini_get(gamedb, "InitialPose", "theta", NULL); 60         InitialPoseTheta= atof(a); 61     } 62     if(ini_get(gamedb,"TilingUnit_Pose", "XTrans", NULL) != NULL)  63     { 64         const char* a=ini_get(gamedb, "TilingUnit_Pose", "XTrans", NULL); 65         XTrans= atof(a); 66     } 67     if(ini_get(gamedb,"TilingUnit_Pose", "YTrans", NULL) != NULL)  68     { 69         const char* a=ini_get(gamedb, "TilingUnit_Pose", "YTrans", NULL); 70         YTrans= atof(a); 71     } 72     if(ini_get(gamedb,"TilingUnit_Pose", "Height", NULL) != NULL)  73     { 74         const char* a=ini_get(gamedb, "TilingUnit_Pose", "Height", NULL); 75         Height= atof(a); 76     } 77     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateX", NULL) != NULL)  78     { 79         const char* b=ini_get(gamedb, "Laser_TilingUnitO", "RotateX", NULL); 80         RotateX= atof(b); 81     } 82     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateY", NULL) != NULL)  83     { 84         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateY", NULL); 85         RotateY= atof(a); 86     } 87     if(ini_get(gamedb,"Laser_TilingUnitO", "RotateZ", NULL) != NULL)  88     { 89         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "RotateZ", NULL); 90         RotateZ= atof(a); 91     } 92     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformX", NULL) != NULL)  93     { 94         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformX", NULL); 95         TransformX= atof(a); 96     } 97     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformY", NULL) != NULL)  98     { 99         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformY", NULL);100         TransformY= atof(a);101     }102     if(ini_get(gamedb,"Laser_TilingUnitO", "TransformZ", NULL) != NULL) 103     {104         const char* a=ini_get(gamedb, "Laser_TilingUnitO", "TransformZ", NULL);105         TransformZ= atof(a);106     }107     if(ini_get(gamedb,"LaserO", "CalibRotateX", NULL) != NULL) 108     {109         const char* a=ini_get(gamedb, "LaserO", "CalibRotateX", NULL);110         CalibRotateX= atof(a);111     }112     if(ini_get(gamedb,"LaserO", "CalibRotateY", NULL) != NULL) 113     {114         const char* a=ini_get(gamedb, "LaserO", "CalibRotateY", NULL);115         CalibRotateY= atof(a);116     }117     if(ini_get(gamedb,"LaserO", "CalibRotateZ", NULL) != NULL) 118     {119         const char* a=ini_get(gamedb, "LaserO", "CalibRotateZ", NULL);120         CalibRotateZ= atof(a);121     }122     if(ini_get(gamedb,"LaserO", "CalibTransformX", NULL) != NULL) 123     {124         const char* a=ini_get(gamedb, "LaserO", "CalibTransformX", NULL);125         CalibTransformX= atof(a);126     }127     if(ini_get(gamedb,"LaserO", "CalibTransformY", NULL) != NULL) 128     {129         const char* a=ini_get(gamedb, "LaserO", "CalibTransformY", NULL);130         CalibTransformY= atof(a);131     }132     if(ini_get(gamedb,"LaserO", "CalibTransformZ", NULL) != NULL) 133     {134         const char* a=ini_get(gamedb, "LaserO", "CalibTransformZ", NULL);135         CalibTransformZ= atof(a);136     }137     if(ini_get(gamedb,"System", "Half", NULL) != NULL) 138     {139         const char* a=ini_get(gamedb, "System", "Half", NULL);140         useHalf= atof(a);141     }

 参考:https://github.com/wernsey/rengine/blob/master/src/ini.c

C语言ini格式配置文件的读写