为何不能用%s替代%c?scanf格式符致程序异常问题咨询
为啥用
scanf("%s", &wasd)会导致数组里的1重复出现? 嘿,这个问题我之前写控制台小游戏的时候也踩过一模一样的坑,咱们来一步步拆解清楚原因和解决办法:
核心问题:内存缓冲区溢出
首先我猜你的wasd是单个char类型的变量对吧?那问题就出在%s这个格式符的工作逻辑上:
%s是scanf专门用来读取字符串的格式符,它读取输入字符后,会自动在末尾加上一个字符串终止符\0(占1个字节的内存空间)。- 但单个
char变量只有1个字节的存储空间,当scanf尝试把输入字符+\0一起写入时,就会超出变量的内存范围,发生缓冲区溢出——溢出的字节会覆盖相邻内存区域的数据。
而这个被覆盖的内存,大概率就是你用来记录数组中1的原位置的变量,甚至是二维数组本身的某个元素。结果就是程序“误以为”原位置的1还存在,同时又在新位置写入了新的1,看起来就像1没被删除还重复出现了。
对比你之前用的%c:它只会读取单个字符,不会额外添加\0,刚好匹配单个char变量的空间,所以不会有溢出问题,程序就能正常执行删除原位置、写入新位置的逻辑。
解决办法
办法1:老老实实用%c(最推荐)
既然只需要单个输入字符,%c才是最适配的选择,但要注意一个小细节:
当你输入w然后按回车时,回车符\n会留在输入缓冲区里,下次调用scanf("%c", &wasd)时会直接读取这个换行符,导致程序出现“假死”或者误操作。解决办法是在%c前面加一个空格:
scanf(" %c", &wasd);
这个空格会自动跳过所有空白字符(包括换行、空格、制表符),确保每次读取的都是你真正输入的w/a/s/d。
办法2:如果非要用%s(不推荐)
把wasd定义成一个至少2字节的字符数组,给\0留出存储空间:
char wasd[2]; scanf("%s", wasd); // 之后用wasd[0]来获取输入的字符
但这种方式完全没必要,因为你只需要单个字符,反而增加了不必要的复杂度。
小调试技巧
如果想直观看到溢出的影响,可以打印wasd变量的内存地址,以及二维数组相关变量的地址,就能清楚看到溢出时到底覆盖了哪些内存数据,帮你更深刻理解问题本质~
内容的提问来源于stack exchange,提问作者Gottaquest
相关产品推荐
相关产品推荐

