引用别人的博文: http://www.open-open.com/lib/view/open1402278076447.html
可以解析 INI 格式的字符串、解析文件、保存到文件。
下面是头文件:
1 #ifndef INI_PARSER_H 2 #define INI_PARSER_H 3 #ifdef __cplusplus 4 extern "C" { 5 #endif 6 struct tag_value_list; 7 8 struct ini_parser { 9 struct tag_value_list * keyvalues; 10 int (*parse_file)(struct ini_parser *, const char * file); 11 int (*parse_string)(struct ini_parser *, const char *text); 12 char * (*value)(struct ini_parser *, const char * key); 13 void (*set_value)(struct ini_parser *, const char * key, const char * value); 14 void (*remove)(struct ini_parser *, const char *key); 15 int (*save_to_file)(struct ini_parser *, const char * file); 16 }; 17 18 struct ini_parser * new_ini_parser(); 19 void delete_ini_parser(struct ini_parser *); 20 21 #ifdef __cplusplus 22 } 23 #endif 24 #endif // INI_PARSER_H 25 下面是源文件: 26 #include "ini_parser.h" 27 #include <stdio.h> 28 #include <string.h> 29 #include "tag_value.h" 30 31 static struct tag_value_pair * parse_line(char *line, int len) 32 { 33 struct tag_value_pair * pair = 0; 34 int count = 0; 35 char * p = line; 36 char * end = 0; 37 char * start = line; 38 if(!p) return 0; 39 while(*p == ' ') p++; 40 41 42 /*blank line*/ 43 if(p - line == len || 44 *p == '\r' || 45 *p == '\n' || 46 *p == '\0') return 0; 47 48 /*do not support group*/ 49 if(*p == '[') return 0; 50 /*comments*/ 51 if(*p == '#') return 0; 52 53 /* extract key */ 54 start = p; 55 end = line + len; 56 while(*p != '=' && p!= end) p++; 57 if(p == end) 58 { 59 /* none '=' , invalid line */ 60 return 0; 61 } 62 end = p - 1; 63 while(*end == ' ') end--; /* skip blank at the end */ 64 count = end - start + 1; 65 66 pair = new_tag_value_pair(); 67 pair->szTag = malloc(count + 1); 68 strncpy(pair->szTag, start, count); 69 pair->szTag[count] = 0; 70 71 /* extract value */ 72 p++; 73 end = line + len; /* next pos of the last char */ 74 while( *p == ' ' && p != end) p++; 75 if(p == end) 76 { 77 delete_tag_value_pair(pair); 78 return 0; 79 } 80 start = p; 81 end--; /* to the last char */ 82 if(*end == '\n') { *end = 0; end--; } 83 if(*end == '\r') { *end = 0; end--; } 84 count = end - start + 1; 85 if(count > 0) 86 { 87 pair->szValue = malloc(count + 1); 88 strncpy(pair->szValue, start, count); 89 pair->szValue[count] = 0; 90 } 91 92 /* release empty key-value pair */ 93 if(!pair->szValue) 94 { 95 delete_tag_value_pair(pair); 96 return 0; 97 } 98 99 return pair; 100 } 101 102 static int _parse_file(struct ini_parser * ini, const char *file){ 103 FILE * fp = fopen(file, "r"); 104 if(fp) 105 { 106 struct tag_value_pair * pair = 0; 107 char buf[1024] = {0}; 108 while(fgets(buf, 1024, fp)) 109 { 110 pair = parse_line(buf, strlen(buf)); 111 if(pair) 112 { 113 ini->keyvalues->add(ini->keyvalues, pair); 114 } 115 } 116 fclose(fp); 117 return ini->keyvalues->size; 118 } 119 return -1; 120 } 121 122 static int _parse_text(struct ini_parser * ini, const char * text){ 123 char *p = text; 124 char * start = 0; 125 struct tag_value_pair * pair = 0; 126 if(!text) return -1; 127 128 while(1) 129 { 130 start = p; 131 while(*p != '\n' && *p != '\0' )p++; 132 if(*p == '\0') break; 133 134 pair = parse_line(start, p - start); 135 if(pair) ini->keyvalues->add(ini->keyvalues, pair); 136 137 p++; 138 } 139 140 return ini->keyvalues->size; 141 } 142 143 static char * _value(struct ini_parser * ini, const char * key){ 144 struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key); 145 if(pair) return pair->szValue; 146 return 0; 147 } 148 149 static void _set_value(struct ini_parser * ini, const char * key, const char *value){ 150 struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key); 151 if(pair) 152 { 153 if(pair->szValue) free(pair->szValue); 154 pair->szValue = strdup(value); 155 } 156 else 157 { 158 ini->keyvalues->add(ini->keyvalues, make_tag_value_pair(key, value)); 159 } 160 } 161 162 static void _remove(struct ini_parser * ini, const char * key){ 163 struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key); 164 if(pair)ini->keyvalues->remove(ini->keyvalues, pair); 165 } 166 167 static void write_keyvalue(struct tag_value_pair * pair, FILE *fp) 168 { 169 fputs(pair->szTag, fp); 170 fputc('=', fp); 171 fputs(pair->szValue, fp); 172 fputc('\n', fp); 173 } 174 175 static int _save_to_file(struct ini_parser * ini, const char * file){ 176 if(ini->keyvalues->size > 0) 177 { 178 FILE * fp = fopen(file, "w"); 179 if(fp) 180 { 181 struct tag_value_pair * pair = ini->keyvalues->head; 182 while(pair != ini->keyvalues->tail) 183 { 184 write_keyvalue(pair, fp); 185 pair = pair->next; 186 } 187 188 if(pair)write_keyvalue(pair, fp); 189 190 fclose(fp); 191 return 0; 192 } 193 } 194 return -1; 195 } 196 197 struct ini_parser * new_ini_parser(){ 198 struct ini_parser * ini = (struct ini_parser*)malloc(sizeof(struct ini_parser)); 199 ini->keyvalues = new_tag_value_list(); 200 ini->parse_file = _parse_file; 201 ini->parse_string = _parse_text; 202 ini->value = _value; 203 ini->set_value = _set_value; 204 ini->remove = _remove; 205 ini->save_to_file = _save_to_file; 206 return ini; 207 } 208 209 void delete_ini_parser(struct ini_parser *ini){ 210 if(ini) 211 { 212 delete_tag_value_list(ini->keyvalues); 213 free(ini); 214 } 215 } 216 测试代码: 217 #include "util/ini_parser.h" 218 #include "ini_test.h" 219 #include <stdio.h> 220 #include <assert.h> 221 222 static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli zhang \n"; 223 224 static void ini_parser_test_string() 225 { 226 struct ini_parser * ini = new_ini_parser(); 227 int size = ini->parse_string(ini, g_szIniString); 228 229 assert( size > 0); 230 assert( ini->value(ini, "second") == 0 ); 231 assert( ini->value(ini, "abc") == 0); 232 assert( ini->value(ini, "name") != NULL ); 233 assert( ini->value(ini, "first") != NULL); 234 235 printf("ini string: %s\n", g_szIniString); 236 printf("key-value pairs count = %d\n", size); 237 printf("key \'name\'', value = %s\n", ini->value(ini, "name")); 238 printf("key \'first\'', value = %s\n", ini->value(ini, "first")); 239 240 ini->set_value(ini, "baidu", "hahaha"); 241 ini->save_to_file(ini, "write.conf"); 242 243 ini->remove(ini, "first"); 244 ini->save_to_file(ini, "write2.conf"); 245 246 delete_ini_parser(ini); 247 } 248 249 static void ini_parser_test_file() 250 { 251 struct ini_parser * ini = new_ini_parser(); 252 int size = ini->parse_file(ini, "test.conf"); 253 254 assert( size > 0); 255 assert( ini->value(ini, "second") == 0 ); 256 assert( ini->value(ini, "abc") == 0); 257 assert( ini->value(ini, "name") != NULL ); 258 assert( ini->value(ini, "first") != NULL); 259 260 printf("ini string: %s\n", g_szIniString); 261 printf("key-value pairs count = %d\n", size); 262 printf("key \'name\'', value = %s\n", ini->value(ini, "name")); 263 printf("key \'first\'', value = %s\n", ini->value(ini, "first")); 264 printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu")); 265 266 delete_ini_parser(ini); 267 } 268 269 void ini_parser_test() 270 { 271 ini_parser_test_string(); 272 ini_parser_test_file(); 273 }