在C中使用sscanf解析特殊字符模式

时间:2013-12-13 14:24:32

标签: regex parsing controls scanf

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

命令行结构如下:

inside()内的所有参数都是必需的,[]内的参数是可选的, spc 代表空白或空间。和\ t代表标签

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

[ spc ] MYCMD [ spc ](\ t)[ spc ](AP)[ spc ](:)(WL)(=)(RT) spc spc (\ 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 float转换为整数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)。

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

1 个答案:

答案 0 :(得分:0)

不能仅使用sscanf()完成。

一个关键问题是格式字符串中的" "以及"\r""\n"(除了"[ ]"内部)可选扫描任何数字0+空格,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()格式完成。我相信这样的方法可以被打破。