我正在开发一个命令解析器,它应该接受以\ 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)。
任何有关修复解析问题的提示或意见将不胜感激 感谢
答案 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()
格式完成。我相信这样的方法可以被打破。