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

如何让C语言scanf()函数忽略无效字符并避免程序异常运行?

问题原因

你遇到的重复打印问题本质是输入缓冲区残留+scanf类型匹配失败共同导致的:

  • 当你给%d格式的scanf输入字符时,scanf会匹配失败,返回0,且输入的错误字符不会被从输入缓冲区取走,一直留在缓冲区里
  • 下次循环走到scanf的时候,会直接读取缓冲区里残留的错误字符,再次匹配失败,进入无限循环,反复执行前面的printf语句
修复方案

1. 新增输入缓冲区清空函数

先在代码开头加一个清空输入缓冲区的工具函数,每次scanf调用后都执行清空,避免残留:

void limpiarBuffer() {
    while (getchar() != '\n');
}

2. 给数字类scanf增加读取成功校验

所有用%d的scanf都不要直接调用,要判断返回值是否为1(表示成功读取1个int值),如果失败就提示重新输入,同时清空缓冲区:
比如你原来读取产品ID的代码修改为:

do{
    printf("Escriba la ID del producto: ");
    if(scanf("%d", &idprompt) != 1){
        printf("输入错误,请输入数字!\n");
        idprompt = 0; // 赋值为0触发范围校验不通过,继续循环
        limpiarBuffer(); // 清空缓冲区残留的错误字符
    }
}while(0==rangoValido(1,1000,idprompt));

同理,后面读取收款金额的scanf("%d", &monto);也做同样的校验修改。

3. 字符类scanf的残留处理

你现在的%c前面加了空格已经可以跳过换行符,但是如果用户输入多个字符(比如输了yes而不是Y),还是会有残留,所以每次读取完字符之后也调用一次limpiarBuffer()清空多余的输入即可。

补充:你代码里另外3个隐藏bug

  • 你定义的二维数组int productoid[1000][1]和int listacompra[100][1]第二维长度是1,合法下标只能是0,但是你代码里写了productoid[idprompt][1]、listacompra[colector][1],属于数组越界,会导致内存篡改,把第二维长度改成2就行:int productoid[1000][2];、int listacompra[100][2];
  • 变量total定义的时候没有初始化,累加的时候会用垃圾值作为初始值,定义的时候改成int total = 0;
  • 你的折扣函数有整数除法问题:descuento / 100两个都是int,比如25/100会得到0,最终折扣后价格是0,改成num * descuento / 100就行,先乘再除避免整数除法误差。

内容的提问来源于stack exchange,提问作者Groxil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 23:45:10