正如其他人向您指出的那样,使用sscanf
不建议出于此目的。它无法捕获的情况是“可选”(
之间可能出现也可能不出现"
和X
. With scanf
,如果有一个可选字段没有任何类型的分隔符来指示它丢失,那么确定它丢失的唯一方法是尝试解析它,注意到它不存在,然后尝试使用以下命令再次解析它不同的扫描格式字符串。
parsed = sscanf( formula, " \" %*[(] X%*[^>]>> %u %*[)] %c %n", &s, &del, &pos );
if (parsed != 2) {
parsed = sscanf( formula, " \" X%*[^>]>> %u %c %n", &s, &del, &pos );
}
该解决方案的其余部分描述了如何使用 POSIX<regex.h>
解析它的基本正则表达式。
首先,您需要定义正则表达式并编译它。
const char *re =
"[ \t]*\"" /* match up to '"' */
"[ \t]*(\\{0,1\\}[ \t]*" /* match '(' if present */
"X[ \t]*>>[ \t]*" /* match 'X >>' */
"\\([0-9][0-9]*\\)" /* match number as subexpression */
"[ \t]*)\\{0,1\\}[ \t]*" /* match ')' if present */
"\\(.\\)" /* match final delimiter as subexpression */
"[ \t\r\n]*"; /* match trailing whitespace */
regex_t reg;
int r = regcomp(®, re, 0);
if (r != 0) {
char buf[256];
regerror(r, ®, buf, sizeof(buf));
fprintf(stderr, "regcomp: %s\n", buf);
/*...*/
}
现在,您需要针对要匹配的字符串执行表达式。编译器将跟踪正则表达式中子表达式的数量,并将该数字放入reg.re_nsub
。但是,有一个隐式子表达式不包含在该计数中。这是与所提供的表达式匹配的完整字符串。这总是在第一场比赛中出现。因此,当您创建匹配数组时,请考虑到这一点。这就是为什么matches
数组比里面多了一个reg.re_nsub
.
unsigned match(const regex_t *preg, const char * formula){
/*...*/
int r;
const int NSUB = preg->re_nsub + 1;
regmatch_t matches[NSUB];
r = regexec(preg, formula, NSUB, matches, 0);
if (r == 0) {
/* success */
parsed = preg->re_nsub;
s = atoi(formula + matches[1].rm_so);
del = formula[matches[2].rm_so];
pos = matches[0].rm_eo;
} else {
parsed = 0;
}
/*...*/
当您完成正则表达式后,您应该释放它(如果它已成功编译)。
regfree(®);