C语言如何限制scanf获取字符串的允许输出字符?
问题根因
- 条件判断语法错误:你写的
if (b[i] == '.','-')用到了C语言的逗号运算符,逗号运算符的规则是依次执行左侧所有表达式,最终返回最后一个表达式的值作为整体结果。这里最后一个表达式是字符常量'-',它的ASCII值非0,所以整个判断条件永远为真,所有字符都会被输出,自然失去了过滤效果。 - 循环逻辑错误:for循环已经自带
i++迭代逻辑,你在else分支又额外加了一次i++,会导致每次命中不合法字符时直接跳过下一个字符的校验,属于逻辑漏洞。 - 潜在安全问题:
scanf("%s", b)没有限制输入长度,你的字符数组b只有5字节容量,用户输入超过4个字符时会触发缓冲区溢出,存在安全风险。
修复方案
如果要自定义允许输出的字符,推荐用可配置的合法字符集合方案,后续新增/删除合法字符只需修改一处即可,不需要改判断逻辑。
修正后的完整代码如下:
#include <stdio.h> #include <string.h> // 在这里自定义所有允许输出的字符,新增删除只需要改这个字符串即可 #define ALLOWED_CHARS ".-" int main(int argc, char *argv[]) { // 多留1位存字符串结束符'\0' char b[6]; int i; printf("enter characters (only first 5 allowed characters will be shown):"); // 限制scanf最多读取5个字符,避免缓冲区溢出 scanf("%5s", b); for(i = 0; i < 5 && b[i] != '\0'; i++) { // 检查当前字符是否在允许的字符集合中 if (strchr(ALLOWED_CHARS, b[i]) != NULL) { printf("%c", b[i]); } } printf("\n"); return 0; }
方案说明
- 如果允许的字符较少,也可以直接用逻辑或写判断条件:
if (b[i] == '.' || b[i] == '-'),效果和上面的写法一致。 - 用
strchr的方案更适合合法字符数量多的场景,后续要新增允许的字符比如数字、字母,直接修改ALLOWED_CHARS的定义即可,比如要允许0-9的数字就改成#define ALLOWED_CHARS ".-0123456789"。 - 代码里已经修复了缓冲区溢出和循环跳字符的问题,同时增加了字符串结束符判断,避免读取到数组里的垃圾值。
内容的提问来源于stack exchange,提问作者questionC
相关产品推荐
相关产品推荐

