使用指针与malloc的C程序中scanf读取整数变量失效问题
C程序输入异常提前结束的原因与解决
问题描述
编写了一段使用指针和malloc分配内存的C程序,用于读取结构体evento的内容,但运行时输入n的值(例如1),再输入两个字符串后,程序直接输出"happy day"并结束,无法输入dia、mos、anos三个整数变量的值。
原代码
#include <stdio.h> #include <stdlib.h> struct evento{ char nome [100]; char local [100]; int dia; int mos; int anos; }; int main (){ int i,n; i=0; scanf ("%d",&n); struct evento *agenda; agenda =(struct evento*) malloc(n*sizeof(struct evento)); for (i=0;i<n;i++){ fgets (agenda[i].nome,100,stdin); fgets (agenda[i].local,100,stdin); scanf ("%d",&agenda[i].dia); scanf ("%d",&agenda[i].mos); scanf ("%d",&agenda[i].anos); } printf ("happy day"); free(agenda); return 0; }
原因分析
问题核心是输入缓冲区的残留换行符干扰了后续输入:
- 用
scanf("%d", &n)读取整数时,输入数字后按下的回车键会以\n字符的形式留在输入缓冲区中。 - 后续调用
fgets时,fgets会读取字符直到遇到\n或达到最大长度,此时它会直接把残留的\n读取到agenda[i].nome中,相当于读了一个空行。 - 第二个
fgets会读取你手动输入的第一个字符串,之后执行到scanf读取整数时,缓冲区里剩下的是输入第二个字符串后的换行符,scanf虽然会跳过空白字符,但此时输入逻辑已经混乱,导致循环提前结束,程序直接执行到printf语句。
解决办法
有三种简单有效的处理方式:
- 用
getchar()清除残留换行:在scanf("%d", &n)之后添加一行getchar();,直接吃掉输入n后留下的换行符,确保后续fgets读取的是手动输入的内容。 - 统一用
fgets读取后解析:避免混合使用scanf和fgets,先用fgets读取整行内容,再用sscanf解析整数,比如读取n的代码可以改成:char buf[100]; fgets(buf, sizeof(buf), stdin); sscanf(buf, "%d", &n); - 在
scanf格式串末尾加空格:修改读取n的语句为scanf("%d ", &n);,格式串末尾的空格会让scanf自动跳过缓冲区中所有空白字符(包括换行符),不过这种方式在部分场景下可能会等待额外输入,需要注意。
内容的提问来源于stack exchange,提问作者Gostodexadrez
相关产品推荐
相关产品推荐

