fgets在遇到空格时停止

时间:2015-07-19 16:26:43

标签: c parsing fgets scanf

我正在尝试用C解析输入JSON文件,文件内容如下:{"version":"0.1","type":"tracbuf:e", "userid":0, "method":"udpbuf:-paris", "src":"10.20.6.191"buf:, "dst":"8.8.8.8", "sport":41buf:687, "dport":33435, ...

输入文件非常大,我想读取每一行并解析读取行,即分别分离键值对,并且行和键值字段的长度是任意的。

我知道fscanf()可以正常使用。但我想使用一些带有边界保护的函数,例如fgets()。但我不太确定在这种情况下如何使用fgets(),因为它会读取' n'缓冲区中的字节,包括新行,制表符空间和blankspace('')。但是我希望能够在遇到空格/制表符空格/换行字符时解析读取字符,然后再读取其他行。

请注意,fscanf()可以与strtok()一起执行此操作 - 它会与每个空格/新行一起中断。但遗憾的是,它不允许在缓冲区上使用边界。

我该怎么办?

更新编辑:

以下方法有效。在每个条件中,我需要调用strtok并进行大约6次比较。但我想知道这是否可以做得更好。

while(fscanf(fp, "%100s", buf) != EOF)

{
token=strtok(buf,":-");

while(token!=NULL)

{

if(strcmp(token,"\"src\"")==0) 

{ 

head[trace_count]=(HEADER*) malloc(sizeof(HEADER));

token=strtok(NULL,":{,}])");

strcpy(head[trace_count]->src_ip,token);

}   
else if(strcmmp(...))
{
}

...
}     

1 个答案:

答案 0 :(得分:1)

由于行可以是任何长度,因此在将行读入缓冲区时总是会遇到问题。缓冲区可能永远不会足够大。唯一的方法是通过字符处理。以下是一个简单的基本语法分析器。根据需要进行调整:

void example(FILE *fin)
{
    char c, token[MAX_TOKEN], tokval[MAX_SVAL], *s= token;
    int instr= FALSE;   // track whether we are in a string
    int intok= TRUE;    // track whether we are in a token name or a value

    while ((c=fgetc(fin)) != EOF)
    {
        if (instr) {
            if (c=='"')
                 {*s='\0'; instr= FALSE;}
            else *s++ = c;
        }
        else switch (c) {
        case '"': instr= TRUE; break;
        case '{': /* open:  whatever you want to do*/ break;
        case '}': /* close: whatever you want to do*/ break;
        case ':': if (intok)  {*s= '\0'; s= tokval; intok= FALSE; /* have token name now*/} else *s++ = ':'; break;
        case ',': if (!intok) {*s= '\0'; s= token;  intok= TRUE;  /* have a pair now    */} else *s++ = ','; break;
        case ' ': case '\t': case '\n': case '\r': break;
        default: *s++ = c;
        }
        if (intok)
             {if (s > token+MAX_TOKEN-2) error("token name too long");}
        else {if (s > tokval+MAX_SVAL-2) error("token value too long");}
    }   
}