我在C
中有一些字符串(char *)并使用sscanf
对其进行标记。
我正在生成C
源代码,使用sscanf
是最简单的解决方案,但是存在这个问题:
参数有正则表达式:
[$]([a-zA-Z0-9_-]{0,122})?[a-zA-Z0-9]
(从 $
开始,可以包含numbers
,letters
, '-'
和{{1} },但后来两个 不 位于参数名称的末尾。)
即。 :
'_'
$My_parameter1 //OK
$my-param-2 //OK
$_-this_-_is--my-_par //OK
$My_parameter2- //WRONG!
$My_parameter2_ //WRONG!
在char _param1 [125]; //string that matches parameter name
char _param2 [125]; //string that matches parameter name
if ( sscanf(str, " $%124[a-zA-Z0-9_-] - $%124[a-zA-Z0-9_-] ", _param1, _param2) != 2 )
DO_FAIL;
上使用时,(显然)。
" $parameter_one - $param-two "
显然存在问题,因为sscanf会将第一项标记为"$param1-$param2"
',然后无法找到'$param1-
。
有经验的'-'
程序员可以看到如何简单地解决这个问题吗?
即:
C
...谢谢
答案 0 :(得分:2)
简短回答:sscanf
无法解决此问题,因为sscanf
无法回溯。
至少只有一次sscanf
电话就无法做到这一点。尝试像
if (sscanf(str, " $%124[a-zA-Z0-9_-]", _param1) != 1) DO_FAIL;
size_t _param1_len = strlen(_param1);
if (_param1[_param1_len-1] == '-') {
_param[_param1_len-1] = '\0';
_param1_len -= 1;
}
// parse rest '- $param2'
if (sscanf(str+_param1_len, ...
想法是一次解析一个令牌。您可以实现标识符解析
作为自己的函数,所以你可以重用它,因为你可能想要解析
看起来像"$foo + $bar"
。
答案 1 :(得分:1)
您似乎熟悉正则表达式。如果您在POSIX平台上,为什么不使用regcomp()
/regexec()
/regfree()
?或PCRE哪个也可用作Windows的DLL?
我通常避免将sscanf()
用于比阅读数字或字符串更复杂的事情。否则,我要么编写一个迷你FSM(用char消耗字符串char),要么使用正则表达式。
答案 2 :(得分:0)
sscanf()
不支持正则表达式吗?
答案 3 :(得分:0)
我认为,使用sscanf没有简单的方法。 sscanf不是regexp的替代品。更短的应该是一个自制解决方案:
char *t,input[]="$my-param1-$my-param2";
if( (t=strstr(input,"-$")!=0 || (t=strstr(input,"_$")!=0 )
{
*t=0;
strcpy(param1,input);
strcpy(param2,t+1);
}
好的,在令牌之间有空格也很容易:
char *t,*t1,input[]=" $my-param1 - $my-param2 ";
if( (t=strchr(input,'$'))!=0 && (t1=strchr(t+2,'$'))!=0 )
{
*--t1=0;
while( t1>t+2 && strchr(" -_",*(t1-1)) )
*--t1=0;
while( !*t1 ) ++t1;
while( *t1 && strchr(" -_",t1[strlen(t1)-1]) )
t1[strlen(t1)-1]=0;
strcpy(param1,t);
strcpy(param2,t1);
}
答案 4 :(得分:0)
似乎使用sscanf不是最简单的解决方案,因为单独的sscanf无法处理这样的令牌。
但是,按字符解析这样的字符串非常简单。
您需要一个能够向前看并告知令牌结束位置的函数:
char *token_end(char *s)
{
int specials = 0;
for (; *s != '\0'; ++s) {
if (*s == '_' || *s == '-')
++specials;
else if (isalnum(*s))
specials = 0;
else
break;
}
return s - specials;
}
在找到'$'之后传递指向第一个字符的指针,并返回指向令牌后第一个字符的指针。
现在,逐个字符地解析字符串。如果它是'$',请使用token_end查找令牌结束的位置,并从结尾继续;否则,该角色不属于令牌:
/* str is a pointer to a NULL-terminated string */
char *p = str;
while (*p != '\0') {
if (*p == '$') {
char *beg = p;
char *end = token_end(p+1);
if (end - beg > 1) {
/* here, beg points to the '$' of the current token,
* and end to the character just after the token */
printf("token(%li,%li)", beg - str, end - str);
/* parse the token, save it, etc... */
p = end;
continue;
}
}
/* do something with a character which does not belong to a token... */
printf("%c", *p);
++p;
}