通过状态机实现的一个配置读取函数
完整代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
char IS_CHAR(char x)
{
return (x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z')? true:false;
}
char *strtrim(char *s)
{
char *p = NULL,*right = s,*left = s;
while(isspace(*left)) left++;
p = left;
while(*right != '\0') right++;
for(right--;isspace(*right);right--);
*(right+1) = '\0';
strcpy(s,p);
return s;
}
void parse_body(const char *s,
char *section,
char *key,
char *value)
{
typedef enum _body_state body_state;
enum _body_state
{
STATE_NONE = 0,
STATE_SECTION,
STATE_KEY,
STATE_SPLIT,
STATE_IN_SECTION,
STATE_VALUE,
STATE_COMMENT
};
char *p_section_start;
char *p_key_start;
char *p_value_start;
char *p = NULL;
body_state state = STATE_NONE;
char *tmp = (char*)malloc(strlen(s) + 1);
memset(tmp,'\0',strlen(s) + 1);
strncpy(tmp,s,strlen(s));
for(p = tmp;
*p != '\0';
p++)
{
switch(state)
{
case STATE_NONE:
if(IS_CHAR(*p))
{
state = STATE_SECTION;
p_section_start = p;
}
if((*p) == '#')
{
state = STATE_COMMENT;
}
break;
case STATE_COMMENT:
if(*p == '\n')
{
state = STATE_NONE;
}
break;
case STATE_SECTION:
if((*p) == '{')
{
*p = '\0';
state = STATE_IN_SECTION;
}
break;
case STATE_KEY:
if(*p == '=')
{
*p = '\0';
p_value_start = p+1;
state = STATE_VALUE;
}
break;
case STATE_VALUE:
if(*p == ';')
{
*p = '\0';
strtrim(p_section_start);
strtrim(p_key_start);
strtrim(p_value_start);
if(strcmp(p_section_start,section) == 0 &&
strcmp(p_key_start ,key) == 0)
{
strcpy(value,p_value_start);
}
state = STATE_IN_SECTION;
}
break;
case STATE_SPLIT:
if(IS_CHAR(*p))
{
state = STATE_VALUE;
}
break;
case STATE_IN_SECTION:
if(IS_CHAR(*p))
{
p_key_start = p;
state = STATE_KEY;
}
if((*p) == '}')
{
state = STATE_NONE;
}
break;
}
}
free(tmp);
}
int main()
{
char value[16] = {0};
FILE *f = NULL;
char *buff = NULL;
fpos_t pos = 0;
f = fopen("d:\\my.conf","r");
fseek(f,0,SEEK_END);
fgetpos(f,&pos);
buff = (char*)malloc(pos);
memset(buff,0,pos);
fseek(f,0,SEEK_SET);
fread(buff,pos,1,f);
parse_body(buff,"people","name",value);
printf("value:%s",value);
free(buff);
return 0;
}
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
char IS_CHAR(char x)
{
return (x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z')? true:false;
}
char *strtrim(char *s)
{
char *p = NULL,*right = s,*left = s;
while(isspace(*left)) left++;
p = left;
while(*right != '\0') right++;
for(right--;isspace(*right);right--);
*(right+1) = '\0';
strcpy(s,p);
return s;
}
void parse_body(const char *s,
char *section,
char *key,
char *value)
{
typedef enum _body_state body_state;
enum _body_state
{
STATE_NONE = 0,
STATE_SECTION,
STATE_KEY,
STATE_SPLIT,
STATE_IN_SECTION,
STATE_VALUE,
STATE_COMMENT
};
char *p_section_start;
char *p_key_start;
char *p_value_start;
char *p = NULL;
body_state state = STATE_NONE;
char *tmp = (char*)malloc(strlen(s) + 1);
memset(tmp,'\0',strlen(s) + 1);
strncpy(tmp,s,strlen(s));
for(p = tmp;
*p != '\0';
p++)
{
switch(state)
{
case STATE_NONE:
if(IS_CHAR(*p))
{
state = STATE_SECTION;
p_section_start = p;
}
if((*p) == '#')
{
state = STATE_COMMENT;
}
break;
case STATE_COMMENT:
if(*p == '\n')
{
state = STATE_NONE;
}
break;
case STATE_SECTION:
if((*p) == '{')
{
*p = '\0';
state = STATE_IN_SECTION;
}
break;
case STATE_KEY:
if(*p == '=')
{
*p = '\0';
p_value_start = p+1;
state = STATE_VALUE;
}
break;
case STATE_VALUE:
if(*p == ';')
{
*p = '\0';
strtrim(p_section_start);
strtrim(p_key_start);
strtrim(p_value_start);
if(strcmp(p_section_start,section) == 0 &&
strcmp(p_key_start ,key) == 0)
{
strcpy(value,p_value_start);
}
state = STATE_IN_SECTION;
}
break;
case STATE_SPLIT:
if(IS_CHAR(*p))
{
state = STATE_VALUE;
}
break;
case STATE_IN_SECTION:
if(IS_CHAR(*p))
{
p_key_start = p;
state = STATE_KEY;
}
if((*p) == '}')
{
state = STATE_NONE;
}
break;
}
}
free(tmp);
}
int main()
{
char value[16] = {0};
FILE *f = NULL;
char *buff = NULL;
fpos_t pos = 0;
f = fopen("d:\\my.conf","r");
fseek(f,0,SEEK_END);
fgetpos(f,&pos);
buff = (char*)malloc(pos);
memset(buff,0,pos);
fseek(f,0,SEEK_SET);
fread(buff,pos,1,f);
parse_body(buff,"people","name",value);
printf("value:%s",value);
free(buff);
return 0;
}
my.conf:
#test title
#this is a comment
#
people
{
name=ligang;
age=20;
sex=1;
}
box
{
widget=20;
height=30;
color=blue;
}
seller
{
n73 = 590;
N900 = 1500;
}
#this is a comment
#
people
{
name=ligang;
age=20;
sex=1;
}
box
{
widget=20;
height=30;
color=blue;
}
seller
{
n73 = 590;
N900 = 1500;
}
学习了李先静老师的系统程序员成长计划,自己实现了个简单的状态机,感觉真是威力无穷啊。。
配合词法树就可以实现词法解析处理了,嘿嘿,年底也可以写个简单的解释语言玩玩咯