|  | 
 
| 来自:http://topic.csdn.net/u/20111128/14/d701ae5b-b6a3-45ff-a199-d068d77ecb5d.html 问题:
 [{"iconNo":"1","seq":"1","devStatus":"1","devdescribe":"asd"}]
 
 [{"iconNo":"2","seq":"2","devStatus":"2","devdescribe":"asasdsasdas师大d"}]
 
 解析出各个字段,得到key-value。
 
 我看Lighttpd解析http那一块代码大约1000行,不过它里边包括了http协议的处理,这里特意为了模仿它,写了一个基本类似的函数。
 
 说说我为什么要写这么长吧, 因为我假设用户的输入是任意风格的, 也就是会有很多地方敲一些空格或者TAB, 格式也比较乱, 这里我还没有处理折叠格式,写时候忘了搞了,无非就是特殊对待一下\n。
 
 http里的"\r\n" 对应这里的','。
 另外,这里由于这里的key,value都被""包裹,我假定""内不允许存在空白字符,对于http,需要特殊判断key中间是否有空白字符。
 
 这个办法靓点在哪里呢? 就是一趟扫描,不需要回溯再去检查合法性,那么复杂的情况为何可以做到呢? 就是用了state这个变量, 将解析过程划分成了不同的阶段, 0阶段是解析一行第一次进入的状态,以后都不会再进入了, 1是解析key,2是解析:并且过度到3阶段,3阶段是解析val,4阶段是解析,或者行结尾。 通过state,保证每一个case里我们完全把精力集中在一部分,简化了逻辑复杂性,希望大家有所体会。
 
 
 复制代码#include <stdio.h>#include <stdlib.h>#include <string.h>static const char* parse_test[] = {    "[{"iconNo":"1","seq":"1","devStatus":"1","devdescribe":"asd"}]",    "[{"iconNo":"2","seq":"2","devStatus":"2","devdescribe":"asasdsasdas师大d"}]"};int parse_key_value(const char *line){    // 主要检查以下不合法性:    //1, key或者value没有被'"'包裹    //2, ""内没有空白字符    //3, key : value 形式不合法    int key_start, dot, key_end, val_start, val_end;    int line_len;    int state = 0;    //0:初始化,1:解析key,2:解析',',3:解析val,4:解析',' or '\0'                    //or }]序列    int left_over = 0;    char key[20], value[30];    key_start = dot = key_end = val_start = val_end = -1;    line_len = strlen(line);        for (int i = 0; i <= line_len; /*<=line_len目的: 对','和'\0'同等对待*/)    {        switch (state)        {            case 0:            {                switch (line[i])                {                    case ' ':                    case '\t':                    {                        ++i;                    }break;                    case '[':                    {                        // 多余的[                        if (left_over != 0)                        {                            return -1;                        }                        if (line[i+1] != '{')                        {                            return -1;                        }                        left_over++; //左侧"[{"序列合法                        i+=2;                    }break;                    case '{':    //不应该单独出现,此分支可以不写,被default处理                    {                        return -1;                    }break;                    case '"':                    {                        if (left_over == 0)                        {                            //还没遇到[{序列                            return -1;                        }                        // key的左'"',记录key_start                        key_start = ++ i;                        ++ state; //进入解析key状态                    }break;                    default:                    {                            // 非空白字符 or 非[{序列 or 非'"' or '\0'                         return -1;                    };                }            }break;            case 1:            {                switch (line[i])                {                    case ' ':                    case '\t':                    case '{':                    case '[':                    case ',':                    case ':':                    case '\0':                    {                        // key不应该包含非字母,这里只列举一些                        return -1;                    }break;                    case '"':                    {                        //key结束,记录key_end                        key_end = i-1;                        if (key_end < key_start)    //key为空                        {                            return -1;                        }                        ++ i;                        state ++; // 进入解析':'状态                    }break;                    default:                    {                        // 任意合法字母                        ++ i;                    }break;                }            }break;            case 2:            {                switch (line[i])                {                    case '\t':                    case ' ':                    {                        // 空白字符掠过                        ++ i;                    }break;                    case ':':                    {                        //找到':'                        dot = i++;                        state++;                        //向后掠过所有的空白,检测"val的'"'                        while (line[i] != '\0')                        {                            if (line[i] != ' ' && line[i] != '\t')                            {                                if (line[i] != '"')                                {                                    return -1;    //遇到非空白非"字符                                }                                val_start = ++ i;                                break;                            }                                                        ++ i;                        }                        if (val_start == -1)                        {                            return -1;                        }                    }break;                    default:                    {                        //非合法,出错                        return -1;                    }break;                }            }break;            case 3:    //开始解析value            {                switch (line[i])                {                    //val内不应该有非字母字符                    case '\t':                    case ' ':                    case ',':                    case '\0':                    case '[':                    case '}':                    case ']':                    case '{':                    {                        return -1;                    }break;                    case '"':                    {                        val_end = i - 1;                                                 if (val_end < val_start)                        {                            return -1;                        }                        ++ i;                        state++;                    }break;                    default:                    {                        ++ i;    //正常字母                    }break;                }            }break;            case 4:    //最后阶段:如果是line末尾需要检测}]                    //不是line末尾需要检测',',并且重新进入state = 1            {                // 直接快速的处理过去                while (line[i] == ' ' || line[i] == '\t')                {                    ++ i;                }                if (line[i] == '\0')                {                    return -1; // line末尾,却没有}]                }                if (line[i] == ',')                {                    // 一个字段结束,打印key,value                    strncpy(key, line + key_start, key_end - key_start + 1);                    key[key_end - key_start + 1] = '\0';                    strncpy(value, line + val_start, val_end - val_start + 1);                    value[val_end - val_start + 1] = '\0';                    printf("%s:%s\n", key, value);                    key_start = key_end = val_start = val_end = -1;                                        // 向后找到value的"                    while (line[++i] != '\0' && (line[i] == ' ' || line[i] == '\t'));                                        if (line[i] != '"')                    {                        return -1;     // , 之后非",错误                    }                    key_start = ++ i;                    state = 1;    //直接进入解析value状态                }                else if (line[i] == '}')                {                    if (line[i+1] != ']')                    {                        return -1;    //}]不完整                    }                                        strncpy(key, line + key_start, key_end - key_start + 1);                    key[key_end - key_start + 1] = '\0';                    strncpy(value, line + val_start, val_end - val_start + 1);                    value[val_end - val_start + 1] = '\0';                    printf("%s:%s\n", key, value);                    return 0;    //解析完毕,}]之后再有字符也不理会了                }                else                {                    // 意外的字符                    return -1;                }            }break;            default:            {                fprintf(stderr, "unknown state %d \n", state);                return -1;            }break;        }    }}int main(){    char test_buffer[1000];    while (scanf("%s", test_buffer) == 1)    {        parse_key_value(test_buffer);    }    for (int i = 0; i < 2; ++ i)    {        parse_key_value(parse_test[i]);    }    return 0;}owenliang@linux-7lsl:~/csdn/src> ./mainiconNo:1seq:1devStatus:1devdescribe:asdiconNo:2seq:2devStatus:2devdescribe:asasdsasdas师大d
 | 
 |