使用scanf读取整数后读取含空格字符串异常,求解决方法
问题分析与解决方案
原代码的核心问题出在第一个scanf的格式串%d\n:
scanf中格式串的空白字符(包括\n、空格、制表符)会匹配输入中任意数量的空白字符,直到遇到非空白字符才停止。输入30回车后,scanf("%d\n", &age)会读取整数30,然后持续等待输入非空白字符,导致printf("name\t: ")还未输出就要求用户输入内容。- 后续第二个
scanf读取的是你提前输入的hotpotcookie,而你看到name :后输入的loremipsum被格式串中的%*s(丢弃读取的字符串)吃掉了。
修正方案1:修正scanf格式串并处理缓冲区换行符
直接去掉第一个scanf的\n,并在读取字符串时跳过缓冲区残留的换行符:
#include <stdio.h> int main() { int age; char name_user[35]; printf("age\t: "); scanf("%d", &age); // 去掉多余的\n printf("name\t: "); scanf(" %[^\n]", name_user); // 前置空格自动跳过缓冲区的换行/空白字符 printf("result\t: %s is %d years old\n", name_user, age); return 0; }
说明:
scanf(" %[^\n]", name_user)中的前置空格会自动匹配并跳过输入缓冲区中所有空白字符(包括之前输入30后残留的换行符),然后%[^\n]会读取所有字符直到遇到换行符,完美支持带空格的用户名输入。
修正方案2:用getchar()清理缓冲区换行
如果更倾向于显式清理缓冲区,可以在读取整数后调用getchar()吃掉残留的换行符:
#include <stdio.h> int main() { int age; char name_user[35]; printf("age\t: "); scanf("%d", &age); getchar(); // 吃掉输入30后留下的换行符 printf("name\t: "); scanf("%[^\n]", name_user); printf("result\t: %s is %d years old\n", name_user, age); return 0; }
注意:
- 该方案仅适用于用户输入整数后直接回车的场景,如果用户输入
30(多个空格后回车),getchar()只能吃掉一个换行符,剩余的空格会被%[^\n]读取,导致用户名开头出现空格。此时方案1的前置空格更可靠。
修正方案3:用fgets读取字符串(推荐)
fgets可以安全读取包含空格的字符串,同时避免缓冲区溢出风险,需要注意处理fgets读取到的换行符:
#include <stdio.h> #include <string.h> int main() { int age; char name_user[35]; printf("age\t: "); scanf("%d", &age); getchar(); // 清理换行符 printf("name\t: "); fgets(name_user, sizeof(name_user), stdin); // 去掉fgets读取到的换行符 if (name_user[strcspn(name_user, "\n")] == '\n') { name_user[strcspn(name_user, "\n")] = '\0'; } printf("result\t: %s is %d years old\n", name_user, age); return 0; }
说明:
strcspn(name_user, "\n")会返回换行符在字符串中的位置,将其替换为\0可避免输出时多一个换行。fgets会限制读取的字符数为sizeof(name_user)-1,自动添加终止符\0,比scanf("%[^\n]")更安全(后者如果输入超过数组长度会导致缓冲区溢出)。
内容的提问来源于stack exchange,提问作者hotpotcookie
相关产品推荐
相关产品推荐

