仿udhcpd配置文件读取的一段代码
前段时间看udhcpd的源代码,后来因为没直接应用,也就放弃了。网上有文章udhcpd详解(搜索一下有很多),其中在介绍udhcpd的配置相关代码时,有如下一句话,学习了这段代码后,以后用到需要读配置文件的地方可以直接使用。恰巧项目需要,就认真学习了下这段代码。不得不说,高人就是高人,写得代码简直是艺术品。我再做任何改动都毁了这件艺术品。我参看的源代码是udhcp-0.9.8。主要文件看的文件就是file.c,相关头文件就是file.h和dhcp.h。下面我贴我应用的代码,建议直接看源代码,我做一点注释。
下面是.c文件。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct general_config_t g_general_config; 2 3 static struct config_keyword keywords[] = { 4 /* keyword[14] handler variable address default[30] */ 5 {"server_ip", read_str, &(g_general_config.server_ip), "192.168.1.50"}, 6 {"my_id", read_str, &(g_general_config.my_id), "lt1000"}, 7 {"position",read_str,&(g_general_config.my_positon),"not set position"}, 8 {"", NULL, NULL, ""}, 9 }; 10 11 /*********************************************************************************************** 12 *函数名 :read_str 13 *函数功能描述:关键字对应的参数为字符串 14 *函数参数 : 输入参数字符串,存储输入参数的地址 15 *函数返回值 : 1 成功返回1 16 *作者 : nelson 17 *函数创建日期 : 2015.12.09 18 *函数修改日期 : 尚未修改 19 *修改人 :尚未修改 20 *修改原因 : 尚未修改 21 *版本 : 1.0 22 *历史版本 : 无 23 ***********************************************************************************************/ 24 int read_str(char *line, void *arg) 25 { 26 char *dest = (char *)arg; //arg是指向数组首地址的地址 27 28 strcpy(dest,line); 29 30 return 1; 31 } 32 33 /*********************************************************************************************** 34 *函数名 :read_config 35 *函数功能描述:读配置文件 36 *函数参数 :file 配置文件文件名 相对路径或者绝对路径都可以 37 *函数返回值 :成功返回1 失败返回0 38 *作者 : nelson 39 *函数创建日期 : 2015.12.09 40 *函数修改日期 : 尚未修改 41 *修改人 :尚未修改 42 *修改原因 : 尚未修改 43 *版本 : 1.0 44 *历史版本 : 无 45 ***********************************************************************************************/ 46 int read_config(char *file) 47 { 48 FILE *in; 49 char buffer[80], *token, *line; 50 int i; 51 52 for (i = 0; strlen(keywords[i].keyword); i++) 53 { 54 if (strlen(keywords[i].def)) 55 keywords[i].handler(keywords[i].def, keywords[i].var); 56 } 57 58 if (!(in = fopen(file, "r"))) 59 { 60 Important_Printf("config file not found,using the default value!"); 61 return 0; 62 } 63 64 while (fgets(buffer, 80, in)) 65 { 66 if (strchr(buffer, '\n')) 67 *(strchr(buffer, '\n')) = '\0'; 68 69 if (strchr(buffer, '#')) 70 *(strchr(buffer, '#')) = '\0'; 71 72 token = buffer + strspn(buffer, " \t"); 73 if (*token == '\0') 74 continue; 75 line = token + strcspn(token, " \t="); 76 if (*line == '\0') 77 continue; 78 *line = '\0'; 79 line++; 80 81 /* eat leading whitespace */ 82 line = line + strspn(line, " \t="); 83 /* eat trailing whitespace */ 84 for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--); 85 line[i] = '\0'; 86 87 for (i = 0; strlen(keywords[i].keyword); i++) 88 { 89 if(!strcmp(token, keywords[i].keyword)) 90 { 91 if (!keywords[i].handler(line, keywords[i].var)) 92 { 93 keywords[i].handler(keywords[i].def, keywords[i].var); 94 } 95 } 96 } 97 } 98 99 fclose(in); 100 101 return 1; 102 }
然后是.h文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #define SERVER_IP_LEN 16 2 #define MY_ID_LEN 12 3 #define POSITION_STRING_LEN 30 4 5 #pragma pack(1) 6 struct config_keyword 7 { 8 char keyword[14]; //关键字 9 int (*handler)(char *line, void *var); //关键字处理函数 10 void *var; //关键字对应的输入参数存储地址 11 char def[30]; //关键字对应的输入参数默认值 12 }; 13 #pragma pack() 14 15 #pragma pack(1) 16 struct general_config_t //全局配置参数结构体 17 { 18 char server_ip[SERVER_IP_LEN]; /*save tcp server's ip*/ 19 char my_id[MY_ID_LEN]; /*id of myself*/ 20 char my_positon[POSITION_STRING_LEN]; /*meachine's positon*/ 21 }; 22 #pragma pack() 23 24 extern struct general_config_t g_general_config; 25 26 int read_str(char *line, void *arg);
稍微需要讲的是config_keyword结构体,不得不说设计的真好。
然后就是strchr、strspn、strcspn、isspace这几个字符串操作函数。认真看,就会发现,使用strspn和strcspn可以从未知字符串中提取出自己想要的字符串,很方便。