【问题标题】:Parsing special character pattern using sscanf in C在 C 中使用 sscanf 解析特殊字符模式
【发布时间】:2013-12-13 14:24:32
【问题描述】:

我正在开发一个命令解析器,它应该接受以 \r\n 结尾的命令行并提取其参数

命令行结构如下:

()里面的参数都是强制的,[]里面的参数是可选的,spc 代表空白或空格。 \t 代表制表符

AP 是 1...4 之间的十进制整数 RT,WL 是十进制无符号整数 = 是等号 % 是百分比符号 以下是可接受的命令结构

[spc] MYCMD [spc] (\t) [spc] (AP) [spc ] (:) (WL)(=)(RT)spcspc(\n)

作为示例,以下命令正确:(整个命令不区分大小写)

MYCMD \t 1 : 540 = 21% \r\n

MYCMD \t 2 : 712= 25 % \r\n

MYCMD\t 3 : 200 =17%\r\n

和...

以下命令不正确:

MYCMD \t 5: 540 = 21% \r\n ---> 5 不在 1..4 范围内

MYCMD \t 2 : 712 25% \r\n --->没有等号

MYCMD 3 200 =17\r\n --->没有 : 3 到 200 之间,没有百分比符号

MYCMD 3 100 =1 ,,.\n ----> 1 后面有多余的符号,\r 不存在

MYCMD 2: 130 =17.1\r\n ----> sscanf 解析器不得将 17.1 浮点数转换为整数 7

我已经实现了 sscanf 控制格式,但是解析不正确!

int n_parsed=sscanf(cmd_str,"%*sMYCMD[*^\t]%*s%[1234]:%u%*s%[=]%u\r\n",&int_ap,&uint_wl,&uint_rt);

但这不适用于正确的命令(n_parsed 永远不会得到 3)。

任何有关修复解析问题的提示或 cmets 将不胜感激 谢谢

【问题讨论】:

    标签: regex parsing controls scanf


    【解决方案1】:

    不能单独使用sscanf()

    一个关键问题是格式字符串中的" " 以及"\r""\n"(除了"[ ]" 内部)将可选地扫描任何 number 0+ white-spaces 和 OP 有非常具体的要求。可选空格' ',但不是其他空格,在sscanf() 中很难做到。

    另一个问题是%d 等,可选地使用前导空格,我们需要阻止它或让它消失。

    格式与“%”位置的示例存在差异。我假设这个例子是正确的。

    格式与行尾\r\n\n 中的示例之间存在差异。我假设在最后的 \r\n 之前有任何尾随空格。

    格式与示例之间存在差异,数字前允许有空格。我认为空格是可以的。

    我看的越多,我发现规定的格式和正确的例子之间有很多差异。在这些情况下,我会选择最容易通过示例的方法。

    int sep[4] = { 0 };
    int int_ap;
    unsigned uint_wl, uint_rt;
    
    // [spc] MYCMD [spc] (\t) [spc] (AP) [spc] (:) (WL)(RT)(=)spcspc(\n)
    const char *format = " MYCMD%n %n%1d :%u =%u%n %n";
    
    int n_parsed = sscanf(cmd_str, format, 
        &sep[0], &sep[1], &int_ap, &uint_wl, &uint_rt, &sep[2], &sep[3]);
    
    if (sep[3] == 0) DidNotReadEnd();  
    if ((int_ap < 1) || (int_ap > 4)) RangeError();
    unsigned TabCount = 0;
    int n;
    for (n = sep[0]; n < sep[1]; n++) {
      if (cmd_str[n] == '\t')  TabCount++;
    }
    if (TabCount != 1) WrongTabCount;
    for (n = sep[2]; n < sep[3]; n++) {
      if (cmd_str[n] != ' ') break;
    }
    if (strcmp(&cmd_str[n], "\r\n") != 0) EOLError();
    

    注意:int_ap 可以使用%1[1-4] 扫描成字符串,然后转换为int

    我完全希望有人声称这一切都可以通过sscanf() 格式完成。我相信这样的方法是可以被打破的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多