You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用指针与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:30:10