如题,朋友领导的孩子大学作业是个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()的使用的更多相关文章

  1. sqlserver text类型字段错误 net.sourceforge.jtds.jdbc.ClobImpl@66fa192的解决方法

    1. SqlServer数据库中text/ntext字段,在用jtds1.2驱动时,会出现用getString()取不到值的问题,toString()也不行. 昨天查了下帮助可以通过简单的配置解决.即 ...

  2. Win7系统中提示:本地无法启动MySQL服务,报的错误:1067,进程意外终止的解决方法。

    Win7系统中提示:本地无法启动MySQL服务,报的错误:1067,进程意外终止的解决方法. 在本地计算机无法启动MYSQL服务错误1067进程意外终止.这种情况一般是my.ini文件配置出错了1.首 ...

  3. 关于错误Access Violation和too many consecutive exceptions 解决方法

    关于错误Access Violation和too many consecutive exceptions 解决方法 “如果DLL中用到了DELPHI的string类型,则DLL和主程序中都需要加上Sh ...

  4. 在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法

    在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法 在Eclipse中运行Jboss时,时间太长可能有时候会出现java ...

  5. 错误Name node is in safe mode的解决方法 (转)

    原文链接:错误Name node is in safe mode的解决方法 将本地文件拷贝到hdfs上去,结果上错误:Name node is in safe mode 这是因为在分布式文件系统启动的 ...

  6. ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法

    在IE9,或IE10中ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法   把弹出框嵌入到jquery dialog中.可以解决 I did: // javascript f ...

  7. linux中/etc/fstab文件删除或修改了,导致系统无法启动

    在linux中,/etc/fstab文件是磁盘挂载的问题,若该文件不小心给修改了,或者被删除了,那么就会导致系统无法重启.因为/etc/fstab文件是记录磁盘挂载的信息,若该文件出现了问题,那么对应 ...

  8. Emacs中编辑保存makefile文件时会错误地将TAB转成空格的解决方法

    问题描述 我的Emacs使用了Purcell的配置,在其配置中使用了whitespace-cleanup,且通过在.emacs.d/lisp/init-edit-utils.el中设定: (requi ...

  9. MVC中提示错误:从客户端中检测到有潜在危险的 Request.Form 值的详细解决方法

    今天往MVC中加入了一个富文本编辑框,在提交信息的时候报了如下的错误:从客户端(Content="<EM ><STRONG ><U >这是测试这...&q ...

  10. Linux网卡聚合时,其中一个网卡有两种配置的解决方法

    先来看看: ficonfig 其中第一网卡是ssh使用: 第二个网卡是在Linux 最小化安装后IP的配置(手动获取静态IP地址)这个文章中配置过ip是192.168.1.2:在Linux重命名网卡名 ...

随机推荐

  1. 🌟 简单理解 React 的 createContext 和 Provider 🚀

    在 React 应用中,我们经常需要在组件之间共享状态和数据.而 React 的 createContext 和 Provider 就是为了解决这个问题而诞生的. createContext:创建自定 ...

  2. CPU的一、二、三级缓存的区别

    引言 概念 缓存大小也是CPU的重要指标之一,而且缓存的结构和大小对CPU速度的影响非常大,CPU内缓存的运行频率极高,一般是和处理器同频 运作,工作效率远远大于系统内存和硬盘.实际工作时,CPU往往 ...

  3. python pika rabbitmq demo

    import pika import json # https://www.cnblogs.com/zhaohuaxishi/p/12107392.html # https://www.cnblogs ...

  4. 幻想领域图床系统V1.2正式版发布

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 幻想领域图床系统V1.2正式版发布 日期:2018-4-1 ...

  5. Fastjson基础环境配置与Java基础概念

    Preface 此篇系列文章将会从 Java 的基础语法开始,以 Fastjson 的各个反序列化漏洞分析为结尾,详细记录如何从一个具有基础面向对象编程但毫无 Java 基础的小白成长为了解 Fast ...

  6. kong网关部署

    软件版本: Postgresql:9.6 (不使用最新版,是因为 konga 不支持) Kong:3.4.2 konga:0.14.7 (UI管理界面) ### Postgresql部署 ## doc ...

  7. HDD成都站:HMS Core 6.0带来新可能,多元服务驱动产品价值提升

    9月10日,由华为开发者联盟主办的HDD(Huawei Developer Day)于成都举行.活动中,华为HMS Core各领域专家重点解读了HMS Core 6.0为开发者带来的多项全新能力,及生 ...

  8. 【AppStore】一文让你学会IOS应用上架Appstore

    前言 咱们国内现在手机分为两类,Android手机与苹果手机,现在用的各类APP,为了手机的使用安全,避免下载到病毒软件,官方都极力推荐使用手机自带的应用商城进行下载,但是国内Android手机品类众 ...

  9. Spring注解之参数校验@Validated和@Valid

    @Validated和@Valid的区别 Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303 规范,是标准 JSR-303 的一个变 ...

  10. 树莓派4B-高精度驱动步进电机

    树莓派4B-高精度驱动步进电机 项目介绍 利用4B树莓派控制步进电机转动,精度可达:0.0144度 (即360度/25000) 适用于非常精密的角度转动. 舵机的精度为1度,无法实现超高精度控制. 硬 ...