[英]sscanf - varying number of format arguments?
在我的程序中,我使用sscanf
检查字符串是否为给定格式。 为此,我提供格式字符串中的参数数量,并检查sscanf
在解析输入时是否返回相同的数字。
作为原始解析器的一部分,我想检查一个字符串是否匹配多种格式之一。 sscanf
函数是可变参数,那么如何处理我需要传递的不同数量的参数?
目前,我只是将大量的参数(例如50)传递给函数,并希望格式字符串不包含更多参数。
有没有更好的方法来做到这一点?
你真的需要比scanf
更重的东西。 您必须告诉 scanf
您的输入是什么格式; 它本身无法解决任何问题。
如果您可以访问POSIX,请查看regex.h
它可能是您需要的一切。
否则,你就会陷入困境。 如果格式相当复杂, lex
和yacc
很好,但是否则strtok
或( getchar
+ switch
)可能是要走的路。
编辑:由于您可以使用POSIX,这里有一个如何从c中的正则表达式中提取数据的简单示例。 (为简洁起见,排除了错误检查。)
char txt[] = "232343341235898dfsfgs/.f";
regex_t reg;
regmatch_t refs[MAX_REFS]; //as in, the maximum number of data you want to extract
regcomp(®, "3433\\([0-5]*\\).*", 0); //replace 0 with REG_EXTENDED if desired
regexec(®, txt, MAX_REFS, refs, 0);
regfree(®);
txt[refs[0].rm_eo+1] = '\0';
int n = atoi(txt+refs[0].rm_so);
printf("%d\n", n);
打印
41235
你应该使用lex / yacc来构建一个合适的解析器。 或者,首先用strtok
标记字符串可能会简化您的问题。 (注意:正确使用strtok
非常棘手 - 请仔细阅读其文档。)
我不确定它是否回答了你的问题,但你在C中使用varargs
来允许函数的可变数量的参数。
void myscanf(const char *fmt, ...)
{
}
无益的答案是“不要这样做,正确编写解析器,可能使用lex
和/或yacc
或bison
”。
你问的问题的答案是“是的,你可以做到”。 我不相信有任何理由为什么没有比格式要求更多的可变参数,尽管很少会是一件坏事。 我假设你有一个数组或列表可能的格式,你在循环中调用sscanf。
您可以使用stdarg.h
提供的宏使用变长参数编写验证函数。
例如,
int my_validation_func(const char *format, ...) {
va_list ap;
char *p, *sval;
int ival;
float fval;
va_start(ap, format);
for(p=format; *p ; p++) {
if (*p != '%') {
continue;
}
switch(*++p) {
case 'd':
ival = va_arg(ap, int);
break;
case 'f':
fval = va_arg(ap, float);
break;
case 's':
for (sval = va_arg(ap, char *); *sval; sval++);
break;
default:
break;
}
}
va_end(ap);
}
希望这可以帮助!
如果您不知道何时编写参数的数量和类型, sscanf()
就无法安全地执行您要执行的操作。
将50个参数传递给sscanf()
是正常的(格式字符串不会消耗的参数会被计算,但会被忽略),但是对应格式字符串的参数必须是促销后的预期类型; 否则,行为未定义。 因此,如果要检测是否可以使用"%d"
或"%f"
扫描字符串,则无法通过单个sscanf()
调用来安全地执行此操作。 (很可能你可以通过传递一个指向足够大的缓冲区的void*
来逃避,但行为仍未定义。)
sscanf()
另一个令人讨厌的问题是它不处理数字溢出。 这个:
char *s = "9999999999999999999999999";
int n;
int result = sscanf(s, "%d", &n);
printf("result = %d, n = %d\n", result, n);
具有未定义的行为(假设9999999999999999999999999太大而无法存储在int
)。
您可以做的事情是找到一个开源的sscanf
实现并修改它,以便它只是根据格式验证字符串,而不存储任何内容。 (处理实现的许可证留待练习。)如果您发现sscanf
样式的格式字符串对您的问题特别方便,这是有道理的。 否则,正则表达式可能是要走的路(不是在C标准中,但是很容易找到实现)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.