如题,朋友领导的孩子大学作业是个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. ClickHouse + ClickVisual 构建日志平台

    越来越多的互联网公司开始尝试 ClickHouse 存储日志,比如映客.快手.携程.唯品会.石墨文档,但是 ClickHouse 存储日志缺少对应的可视化方案,石墨文档开源了 ClickVisual ...

  2. koishi常用插件推荐

    今天给大家做一个常用插件的推荐 以下将插件归为几个大类,按类型推荐 1. 日常相关 点歌 插件名:koishi-plugin-music-downloadvoice-api 功能介绍: 语音点歌 - ...

  3. 判断一个数n是不是快乐数

    引言 题目:编写一个算法来判断一个数n是不是快乐数 来源:网友分享的面试算法题 题目描述 [快乐数定义] 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和. 然后重复这个过程直到这个数变为 ...

  4. 第二届算法、图像处理与机器视觉国际学术会议(AIPMV2024)

    第二届算法.图像处理与机器视觉国际学术会议(AIPMV2024) 2024 2nd International Conference on Algorithm, Image Processing an ...

  5. 【FAQ】HarmonyOS SDK 闭源开放能力 —Asset Store Kit

    1.问题描述 使用关键资产API需要配置SystemCapability.Security.Asset,但不知道syscap.json文件应该配置在哪里,文档也没找到. 解决方案 新增关键资产等API ...

  6. Ubuntu禁止和启动内核更新

    ubuntu禁止和启动内核更新 https://www.cnblogs.com/passedbylove/p/13091002.html https://www.cnblogs.com/sparkde ...

  7. FFmpeg新旧接口对照使用一览

    背景 根据例程学习调用ffmpeg 库方法的时候,发现了一堆警告. main.cpp:81:37: warning: 'AVStream::codec' is deprecated [-Wdeprec ...

  8. 题解:洛谷 P1165 日志分析

    标签:栈,模拟 题意 对于一个栈,给定三种操作: 0 x,将 \(x\) 入栈: 1,出栈,栈空时忽略: 2,查询当前栈内最大值. 思路 前两个都是栈的基本操作,关键在于查最大值. 每次询问暴力找肯定 ...

  9. 【点云检测】OpenPCDet 教程系列 [1] 安装 与 ROS运行

    前言与参考 主要是介绍库的使用,做笔记区 首先搜索的时候有个问题 一直在我脑子里 hhh 就是MMlab其实还有一个叫mmdetection3d 的库,然后搜的时候发现 hhh 有网友和我一样的疑惑: ...

  10. vue2.x版本升级2.7版本

    2022年7月1日,vue正式迎来2.7版本,代号:"Naruto".支持 Composition API + <script setup> .原文链接 也就是说,你可 ...