scanf()读取字符数量不符合预期的问题求助
哈哈,这个问题简直是C语言初学者绕不开的经典坑!核心就是scanf对输入缓冲区里的空白字符(尤其是换行)的处理逻辑在搞怪,咱们把两种情况拆开说:
问题根源:scanf对%c和空白字符的处理逻辑
为什么用scanf("%c\n", &arr[i])会读10个字母?
你可能以为格式串里的\n是匹配输入的回车,但实际上scanf里的任何空白字符(包括\n、空格、制表符)都表示“跳过所有连续的空白字符,直到遇到非空白字符”。
具体到你的循环:
- 第一次调用
scanf("%c\n", ...):你输入字母a+回车,scanf先读走a,然后开始“跳过空白”——也就是那个回车,但这时候输入缓冲区空了,程序会卡住等待你输入下一个非空白字符。直到你输入第二个字母b,scanf才会认为“空白跳过完成”,结束第一次scanf调用。 - 后面的8次循环也是同理:每次输入字母+回车后,scanf都要等下一个字母来触发“空白结束”。直到第9次循环,你输入第9个字母+回车,程序还在等非空白字符,你不得不输入第10个字母,scanf才会完成最后一次调用。
- 这就导致你明明循环9次,却需要输入10个字母。
为什么去掉\n用scanf("%c", &arr[i])只能读5个字母?
这是因为输入缓冲区里的换行符被当成有效字符读走了!
当你输入一个字母+回车时,输入缓冲区里实际存的是[字母, \n]:
- 第1次
scanf("%c"):读走字母,缓冲区剩下\n; - 第2次
scanf("%c"):直接读走缓冲区里的\n,根本不会等待你输入新的字母; - 第3次
scanf("%c"):读走你输入的下一个字母,缓冲区又剩下\n; - 以此类推,9次循环下来,你实际只读到了第1、3、5、7、9次的字母(共5个),剩下4次读的都是换行符——所以你感觉程序“只读取了5个字母”。
解决办法(推荐第一种)
1. 在%c前加一个空格(最省心)
修改格式串为scanf(" %c", &arr[i]),这里的空格会让scanf自动跳过所有前置的空白字符(包括换行、空格),然后只读取下一个非空白的字符。完美适配你“输入字母+回车”的场景。
示例代码:
#include <stdio.h> int main() { char arr[9]; int i; printf("请输入9个字母,每个字母后按回车:\n"); for (i = 0; i < 9; i++) { scanf(" %c", &arr[i]); // %c前的空格是关键 } // 3×3格式输出 printf("\n3×3格式输出:\n"); for (i = 0; i < 9; i++) { printf("%c ", arr[i]); if ((i + 1) % 3 == 0) { printf("\n"); } } return 0; }
2. 手动吃掉换行符
每次用scanf("%c", &arr[i])后,调用getchar()来读取缓冲区里的换行符。但要注意如果输入时不小心多打了空格,这种方式可能漏处理,不如第一种可靠:
scanf("%c", &arr[i]); getchar(); // 吃掉回车
3. 用fgets读取整行(更健壮)
如果想彻底避开缓冲区问题,可以用fgets读取每一行输入,然后提取行首的字母(因为你每次只输入一个字母+回车):
char line[10]; for (i = 0; i < 9; i++) { fgets(line, sizeof(line), stdin); arr[i] = line[0]; // 取每行第一个字符 }
内容的提问来源于stack exchange,提问作者Ania
相关产品推荐
相关产品推荐

