我解析了一个SCPI字符串,看起来像是:
HEADER:HEADER:HEADER:CMD NUMBER MULTIPLIER UNIT;
令牌NUMBER,MULTIPLIER和UNIT之间的空格不一定存在,也不是固定长度的令牌。到目前为止,我已经能够解析(从L到R)。但是,MULTIPLIER和UNIT标记都是可选的,并且可以包含相同的字符。
e.g。后缀可能是'P'(其中P可能意味着pico [mult]或poise [unit])
或'MA'(可能是兆[mult]或毫安[多单元])
有没有人有任何解析这种语法的经验,或者其他任何人都有任何关于如何将这些语法解析为正确的标记的想法。
编辑:对于学究者来说,我认为这比解析更有词汇分析。
答案 0 :(得分:1)
也许在你的简单例子中,使用几个嵌套的if
进行操作比尝试更强大的方法更容易,但如果你不想手动执行或者实际问题是更大,您可以尝试将您的输入与正则表达式(标准词法分析器)匹配。
在POSIX系统上,您可以使用regexec
。
修改:如何使用if
(和select
):
我认为您的输入位于text
,并且您已经阅读了NUMBER的结尾,因此您的索引i
显示了这一点!
// helper function: find next non-whitespace character
char get_prev(char *text, int *end, int i)
{
for (; *end > i; --*end)
if (text[*end] != ' ' && text[*end] != '\t'
&& text[*end] != '\n' && text[*end] != '\r')
// or `if (text[*end] > ' ')` if ASCII
break;
return text[(*end)--];
}
... your function...
// read up to i
int end = strlen(text);
int power_of_10 = 0; // for MULT
enum unit unit = UNKNOWN; // for UNIT
switch (get_prev(text, &end, i))
{
case 'P':
unit = POISE;
break;
case 'A':
unit = AMP;
break;
...
default: // unforeseen character
case '\0':
// neither UNIT nor MULT exist
break;
}
if (unit != UNKNOWN)
switch (get_prev(text, &end, i))
{
case 'M':
power_of_ten = -3; // milli
break;
case 'A':
switch (get_prev(text, &end, i))
{
case 'M':
power_of_ten = 6; // mega
break;
...
}
break;
...
default: // unforeseen character
case '\0':
// MULT doesn't exist
break;
}
注意,在这种情况下,我假设UNIT是强制性的。如果MULT和UNIT都是可选的,我不知道如何区分10MA中的mega和milliamp。但是,您可以向第一个switch
添加更多案例,这些案例对应MULT
的值,并将power_of_10
更改为。{例如,如果您在第一个switch
中看到k
,则可以理解UNIT
不存在且power_of_10
为3。