fgets 在遇到 space 时停止

fgets to stop when a space is encountered

我正在尝试用 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' 字节读入缓冲区,包括换行符、制表符 space 和 blankspace('')。但是我希望能够在遇到空白 space / tab space/ 换行符时中断,以便在进一步阅读其他行之前解析读取的字符。

请注意 fscanf() 可以与 strtok() 一起执行此操作 - 它会在每一行 space/new 处中断。但遗憾的是,它不允许缓冲区有界限。

我该怎么办?

更新编辑:

以下方法有效。在每个条件中,我需要调用 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(...))
{
}

...
}     

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

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='[=10=]'; 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= '[=10=]'; s= tokval; intok= FALSE; /* have token name now*/} else *s++ = ':'; break;
        case ',': if (!intok) {*s= '[=10=]'; 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");}
    }   
}