Linux中scanf类型匹配错误,特指scanf("%d", &c ) ,导致死循环的解决方法 —— fflush(stdin)和getchar()的使用
如题,朋友领导的孩子大学作业是个C语言编写的管理信息系统发来要我给改改,原代码的配置环境是Windows的C环境,由于10多年没有搞过Windows下的C语言了于是换上了Ubuntu18.04的系统上,本以为都是C语言的标准函数在哪个系统上区别不大,不过正是这个想法要自己调到了坑里,其中最大的一个坑就是scanf的输入问题,代码如下:
#include <stdio.h>
#include <stdlib.h> void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
} /* return 1 means yes, return 0 means no */
int check_input(char content [])
{
char c[5]; fflush(stdin);
int r = scanf("%s",&c);
/*
int r = scanf("%d %d", &c1, &c2);
如果数据类型不匹配就会输入失败 !!! %d整型数据输入了字符型%c
r=0表示全部没有输入成功, r=1表示成功输入1个数值, r=2表示成功输入2个数值
*/
c[4] = '\0'; while(!(r==1&&(strcmp(c, "Y")==0||strcmp(c, "y")==0||strcmp(c, "yes")==0||strcmp(c, "N")==0||strcmp(c, "n")==0||strcmp(c, "no")==0)))
{
// printf("输入有误,请重新输入!!!\n若是请回复Y/y/yes,若退出程序请回复N/n/no\n");
printf("%s", content); if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
clean_stdin(); fflush(stdin);
r = scanf("%s",&c);
} if(strcmp(c, "Y")==0||strcmp(c, "y")==0||strcmp(c, "yes")==0)
{
return 1;
}
return 0;
} int main()
{
char content[] = "输入有误,请重新输入!!!\n确认操作请输入Y/y/yes,退回主菜单请输入N/n/no\n"; printf("确认操作请输入Y/y/yes,退回主菜单请输入N/n/no\n"); int res = check_input(content);
if(res==0) // return 1 means yes, return 0 means no
{
printf("退回操作!!!\n");
}
else
{
printf("继续操作!!!\n");
} }
这个代码本身也刷新了我很多的知识点,以前都没有想过 scanf 这个函数还有返回值,毕竟当年用的时候也是在上大学本科的时候,而且这个返回值还挺有用。
(毕竟上学时候重来不会考虑输入检测这事情)
/*
int r = scanf("%d %d", &c1, &c2);
如果数据类型不匹配就会输入失败 !!! %d整型数据输入了字符型%c
r=0表示全部没有输入成功, r=1表示成功输入1个数值, r=2表示成功输入2个数值
*/
==============================================
需要注意的是如果scanf中是字符输入是永远不会出现类型匹配错误的,因为所有输入都可以看做是字符输入,如:
scanf("%c", &c );
scanf("%s", &c );
会出现scanf匹配错误的是这种:
scanf("%d", &c );
在Windows系统下 scanf 因为类型不匹配是不太会引起太多问题的,即使出现问题使用fflush(stdin)然后一个循环输入就解决了,而在linux系统下发现这个是不好用的。
在linux中如果 scanf 输入类型不匹配这时fflush(stdin)是不起作用的,输入缓冲中的值会一直存在的(不清空),然后就会造成死循环然后一直循环输入。
例子:
#include <stdio.h>
#include <stdlib.h> void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
} /* return 1 means yes, return 0 means no */
int check_input(char content [])
{
int c; fflush(stdin);
int r = scanf("%d",&c);
/*
int r = scanf("%d %d", &c1, &c2);
如果数据类型不匹配就会输入失败 !!! %d整型数据输入了字符型%c
r=0表示全部没有输入成功, r=1表示成功输入1个数值, r=2表示成功输入2个数值
*/ while(!(r==1&&(c==1||c==2)))
{
printf("%s", content); // if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
// clean_stdin(); fflush(stdin);
r = scanf("%d",&c);
} if(c==1)
{
return 1;
}
return 0;
} int main()
{
char content[] = "输入有误,请重新输入!!!\n确认操作请输入 1,退回主菜单请输入 2\n"; printf("确认操作请输入 1,退回主菜单请输入 2\n"); int res = check_input(content);
if(res==0) // return 1 means yes, return 0 means no
{
printf("退回操作!!!\n");
}
else
{
printf("继续操作!!!\n");
} }
该代码运行时如果输入字符,如“a”回车后就会死循环:

同时使用 fflush(stdin)和getchar()的使用:
#include <stdio.h>
#include <stdlib.h> void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
} /* return 1 means yes, return 0 means no */
int check_input(char content [])
{
int c; fflush(stdin);
int r = scanf("%d",&c);
/*
int r = scanf("%d %d", &c1, &c2);
如果数据类型不匹配就会输入失败 !!! %d整型数据输入了字符型%c
r=0表示全部没有输入成功, r=1表示成功输入1个数值, r=2表示成功输入2个数值
*/ while(!(r==1&&(c==1||c==2)))
{
printf("%s", content); if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
clean_stdin(); fflush(stdin);
r = scanf("%d",&c);
} if(c==1)
{
return 1;
}
return 0;
} int main()
{
char content[] = "输入有误,请重新输入!!!\n确认操作请输入 1,退回主菜单请输入 2\n"; printf("确认操作请输入 1,退回主菜单请输入 2\n"); int res = check_input(content);
if(res==0) // return 1 means yes, return 0 means no
{
printf("退回操作!!!\n");
}
else
{
printf("继续操作!!!\n");
} }

重要部分代码:
if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
clean_stdin();
需要注意的是只有在scanf匹配错误的时候才好使用getchar函数,否则多需要输入一次回车才可以,因为getchar是阻塞操作如果缓冲区空间中没有结束符会一直等待输入。
更稳妥的方式可以写为:
if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
clean_stdin();
else
fflush(stdin);
整体代码:
#include <stdio.h>
#include <stdlib.h> void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
} /* return 1 means yes, return 0 means no */
int check_input(char content [])
{
int c; fflush(stdin);
int r = scanf("%d",&c);
/*
int r = scanf("%d %d", &c1, &c2);
如果数据类型不匹配就会输入失败 !!! %d整型数据输入了字符型%c
r=0表示全部没有输入成功, r=1表示成功输入1个数值, r=2表示成功输入2个数值
*/ while(!(r==1&&(c==1||c==2)))
{
printf("%s", content); if(r==0) // linux系统中scanf数据类型匹配错误情况下fflush(stdin)无效
clean_stdin();
else
fflush(stdin); r = scanf("%d",&c);
} if(c==1)
{
return 1;
}
return 0;
} int main()
{
char content[] = "输入有误,请重新输入!!!\n确认操作请输入 1,退回主菜单请输入 2\n"; printf("确认操作请输入 1,退回主菜单请输入 2\n"); int res = check_input(content);
if(res==0) // return 1 means yes, return 0 means no
{
printf("退回操作!!!\n");
}
else
{
printf("继续操作!!!\n");
} }
==========================================
引用: https://www.shuzhiduo.com/A/E35poObJvX/
在Windows中不匹配的问题:

==========================================
附加说明:
在linux系统中本文所写的函数 clean_stdin 中利用getchar函数对EOF进行判断是无意义的,因为在linux系统中是无法从键盘输入这个字符的。
(具体也不是很理解)
详细见:https://www.codenong.com/9796054/

==========================================
参考:
https://blog.csdn.net/chunqiu_lfq/article/details/21841217
https://blog.csdn.net/weixin_30883777/article/details/97901491
https://www.shuzhiduo.com/A/E35poObJvX/
Linux中scanf类型匹配错误,特指scanf("%d", &c ) ,导致死循环的解决方法 —— fflush(stdin)和getchar()的使用的更多相关文章
- sqlserver text类型字段错误 net.sourceforge.jtds.jdbc.ClobImpl@66fa192的解决方法
1. SqlServer数据库中text/ntext字段,在用jtds1.2驱动时,会出现用getString()取不到值的问题,toString()也不行. 昨天查了下帮助可以通过简单的配置解决.即 ...
- Win7系统中提示:本地无法启动MySQL服务,报的错误:1067,进程意外终止的解决方法。
Win7系统中提示:本地无法启动MySQL服务,报的错误:1067,进程意外终止的解决方法. 在本地计算机无法启动MYSQL服务错误1067进程意外终止.这种情况一般是my.ini文件配置出错了1.首 ...
- 关于错误Access Violation和too many consecutive exceptions 解决方法
关于错误Access Violation和too many consecutive exceptions 解决方法 “如果DLL中用到了DELPHI的string类型,则DLL和主程序中都需要加上Sh ...
- 在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法
在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法 在Eclipse中运行Jboss时,时间太长可能有时候会出现java ...
- 错误Name node is in safe mode的解决方法 (转)
原文链接:错误Name node is in safe mode的解决方法 将本地文件拷贝到hdfs上去,结果上错误:Name node is in safe mode 这是因为在分布式文件系统启动的 ...
- ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法
在IE9,或IE10中ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法 把弹出框嵌入到jquery dialog中.可以解决 I did: // javascript f ...
- linux中/etc/fstab文件删除或修改了,导致系统无法启动
在linux中,/etc/fstab文件是磁盘挂载的问题,若该文件不小心给修改了,或者被删除了,那么就会导致系统无法重启.因为/etc/fstab文件是记录磁盘挂载的信息,若该文件出现了问题,那么对应 ...
- Emacs中编辑保存makefile文件时会错误地将TAB转成空格的解决方法
问题描述 我的Emacs使用了Purcell的配置,在其配置中使用了whitespace-cleanup,且通过在.emacs.d/lisp/init-edit-utils.el中设定: (requi ...
- MVC中提示错误:从客户端中检测到有潜在危险的 Request.Form 值的详细解决方法
今天往MVC中加入了一个富文本编辑框,在提交信息的时候报了如下的错误:从客户端(Content="<EM ><STRONG ><U >这是测试这...&q ...
- Linux网卡聚合时,其中一个网卡有两种配置的解决方法
先来看看: ficonfig 其中第一网卡是ssh使用: 第二个网卡是在Linux 最小化安装后IP的配置(手动获取静态IP地址)这个文章中配置过ip是192.168.1.2:在Linux重命名网卡名 ...
随机推荐
- 如何解决系统报错:nf_conntrack: table full, dropping packets
问题 在系统日志中(/var/log/messages),有时会看到大面积的下面的报错: nf_conntrack: table full, dropping packet 这说明系统接到了大量的连接 ...
- SRE Google 运维解密读书笔记一:SRE 方法论概述
SRE Google 运维解密,是 SRE 领域的启蒙之作,讲述了 Google 的 SRE 实践,SRE 就是从 Google 流传出来的.本文是读书笔记,第一篇,概述 SRE 方法论.帮大家把书读 ...
- SonarQube代码质量扫描工具
1.什么是SonarQube 既然是学习devops 运维流水线构建 开发 ↓ 测试 ↓ 运维 华为devops软件开发流水线文档 https://support.huaweicloud.com/re ...
- OAuth + Security - 错误收集
Could not decode JSON for additional information: BaseClientDetails 完整的错误输出如下: 2019-12-03 22:18:37.2 ...
- Excel表格Vlookup跨sheet取值,ISNA函数处理匹配不到的空字符串
Excel表格Vlookup跨sheet取值 =VLOOKUP($A2,Sheet2!$A$2:$D$15,2,FALSE) $A2 代表当前的Sheet1的单元格,数据类型需要与查找的单元格字段类型 ...
- windows离线部署VSCode在Centos7上的远程开发环境
前言 公司一直使用的是ssh+vim的远程开发方式,习惯了vim之后已经非常方便了.但是还是想尝试一下VSCode的开发方式.就我而言,原因如下 漂亮的语法高亮,并且有补全 基于语法解析的引用查找(尽 ...
- 03-Python数据类型
None类型 Python3中没有NULL,取而代之的是空类型None.空列表.空字典等. None是一个特殊的Python对象,表示无. None的类型是NoneType. 如果只想声明变量,而不想 ...
- uniapp+thinkphp5实现微信支付(JSAPI支付)
前言 统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返回预支付订单号的接口,目前微信支付所有场景均使用这一接口.下面介绍的是其中JSAPI的支付实现流程与uniapp唤起微信支 ...
- 【简单总结】SLAM 算法的 Benchmark 及相关数据集的结果对比
前言与参考 主要是copy一下总结,方便自己后续找方案特定使用,所有的出处均在标题处和原链接跳转,此处仅做各个benchmark收集使用,如果有原作者觉得侵权,请联系我 将全力配合相关内容和链接删除 ...
- 我对《RAG/大模型/非结构化数据知识库类产品》技术架构的思考、杂谈
1.前言 在6.28/29的稀土掘金开发者大会RAG专场上,我们公司CEO员外代表TorchV分享了我们在<RAG在企业应用中落地的难点与创新> 其中最后分享了两个观点: AI在应用场景落 ...