如何确保sscanf()/fscanf()的格式串与输入完全匹配?
如何让scanf系列函数实现完全匹配输入
问题背景
scanf系列函数的返回值是成功匹配并赋值的输入项(转换说明)数量,而非格式串的整体匹配完成度。比如示例中的代码:
// 读取CSI 14 t请求的响应 int r = sscanf(input, "\033[4;%d;%dt", &resp_y, &resp_x);
四种输入场景下返回值均为2,但只有输入"\033[4;100;200t"是完全有效的:
- 输入1:完全匹配格式串 → 有效
- 输入2:缺少末尾的
t→ 无效 - 输入3:缺少末尾的
t且有多余字符 → 无效 - 输入4:匹配完格式串后有多余字符 → 无效
我们需要一种简洁方法,同时覆盖sscanf()和fscanf(),区分完全匹配与上述部分匹配/多余内容的情况。
通用解决方案:利用%n记录匹配位置 + 检查输入结束
%n是scanf的转换说明之一,它不消耗输入,仅将当前已匹配的字符总数存入指定的整型变量中。通过它可以确认格式串是否完全匹配,以及输入是否无多余内容。
1. 针对sscanf()的实现
修改格式串,在末尾添加%n,然后检查两个条件:
- 成功匹配所有输入项(返回值等于预期数量,这里是2)
- 匹配完成后,输入字符串已到达末尾(即
%n记录的位置对应的字符为\0)
代码示例:
int resp_y, resp_x; int matched_len; int r = sscanf(input, "\033[4;%d;%dt%n", &resp_y, &resp_x, &matched_len); // 判断完全匹配的条件 if (r == 2 && input[matched_len] == '\0') { // 输入有效,完全匹配格式串 } else { // 输入无效:要么部分匹配,要么有多余内容 }
2. 针对fscanf()的实现
对于文件流,%n依然可以记录已读取的字符数,结合流结束检查实现完全匹配:
- 先通过
fscanf()匹配格式串,确保返回值等于预期输入项数 - 尝试读取下一个字符,若读取到
EOF,说明流已到末尾,完全匹配;若读取到任意字符,说明有多余内容
代码示例:
int resp_y, resp_x; int matched_len; int r = fscanf(fp, "\033[4;%d;%dt%n", &resp_y, &resp_x, &matched_len); if (r != 2) { // 输入项匹配失败,直接判定无效 } else { int c = fgetc(fp); if (c == EOF) { // 完全匹配,输入有效 } else { // 有多余字符,输入无效 // 若需继续使用流,需把字符放回流中 ungetc(c, fp); } }
补充说明
%n不会影响scanf的返回值,仅用于记录位置,是实现完全匹配的核心- 对于
fscanf(),若允许末尾存在空白字符(换行、空格等),可在格式串末尾添加%*[ \t\n]跳过所有空白后,再执行上述检查逻辑
内容的提问来源于stack exchange,提问作者intelfx
相关产品推荐
相关产品推荐

