我们在写C程序时,经常使用scanf函数,让用户输入数据,可是有时候会出现一些很奇怪的问题。例如,下面的程序是一个简单的四则运算:

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. char ope = '\0';//操作符+ - * /
  6. int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果
  7.  
  8. printf("请输入第一个运算参数\n");
  9. scanf("%d"1);
  10. printf("请输入运算符 '+ - * /'\n");
  11. scanf("%c",&ope);
  12. printf("请输入第二个运算参数\n");
  13. scanf("%d"2);
  14. switch(ope)
  15. {
  16. case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
  17. break;
  18. case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
  19. break;
  20. case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
  21. break;
  22. case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
  23. break;
  24. default: printf("运算符输入错误\n");//
  25. break;
  26. }
  27. printf("运算结果是: %d\n", result);
  28. return 0;
  29. }

此程序不管从语法,还是逻辑上,都没有问题,且编译也能通过。实际运行时,却是如下结果:

在用户输入第一个运算参数后,按照程序的设定,应该让用户输入运算符,可是直接让用户输入第二个运算参数了。你能看出这是为什么吗? 

我们修改下程序,如下:

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. char ope = '\0';//操作符+ - * /
  6. int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果
  7.  
  8. printf("请输入第一个运算参数\n");
  9. scanf("%d"1);
  10. printf("请输入运算符 '+ - * /'\n");
  11. scanf("%c",&ope);
  12.  
  13. printf("运算符是: %d\n", ope);
  14. printf("请输入第二个运算参数\n");
  15. scanf("%d"2);//加入这两行代码
  16. switch(ope)
  17. {
  18. case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
  19. break;
  20. case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
  21. break;
  22. case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
  23. break;
  24. case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
  25. break;
  26. default: printf("运算符输入错误\n");//
  27. break;
  28. }
  29. printf("运算结果是: %d\n", result);
  30. return 0;
  31. }

我们加入两行代码,输出字符参数ope的ASCII码值,结果如下:

可以看到,ope的ASCII码值是10,正是换行符的ASCII码值。我们什么时候把换行符给了ope?

其实,在我们给运算参数para1赋值1的时候,我们按下了回车键,准备输入运算符,可是系统不懂啊,系统把回车键理解为换行符赋值给了ope,所以接下来会跳过让用户输入运算符而直接让用户输入运算参数2了,问题就在这里。

知道了问题所在,那么就好解决了。
请看:

  1. #include <stdio.h>
  2. #include <conio.h>
  3.  
  4. int main()
  5. {
  6. char ope = '\0';//操作符+ - * /
  7. int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果
  8.  
  9. printf("请输入第一个运算参数\n");
  10. scanf("%d"1);
  11. getchar();
  12.  
  13. printf("请输入运算符 '+ - * /'\n");
  14. scanf("%c",&ope);
  15. getchar();
  16. printf("运算符是: %d\n", ope);
  17. printf("请输入第二个运算参数\n");
  18. scanf("%d"2);
  19. switch(ope)
  20. {
  21. case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
  22. break;
  23. case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
  24. break;
  25. case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
  26. break;
  27. case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
  28. break;
  29. default: printf("运算符输入错误\n");//
  30. break;
  31. }
  32. printf("运算结果是: %d\n", result);
  33. return 0;
  34. }

在每次scanf结束后,加入getchar函数,即可。getchar函数从输入流中读取一个字符,因此可以接收我们每次按下的回车键,也就是换行符。运行结果如下:

调用scanf函数的一个陷阱的更多相关文章

  1. Android中调用C++函数的一个简单Demo

    这里我不想多解释什么,对于什么JNI和NDK的相关内容大家自己去百度或谷歌.我对Android的学习也只是个新手.废话少说直接进入正题. 一.在Eclipse中创建一个Android Applicat ...

  2. Delphi中返回类型为string的函数的一个陷阱(不是很懂)

    如果类的一个成员函数的返回值是string类型,需要注意一个问题 其返回值可能是错误的 例如函数的实现如下 function GetString( s: string ): string;begin  ...

  3. C语言scanf函数详细解释

    原文链接 函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准 ...

  4. scanf函数

    一. 变量的内存分析 1. 字节和地址 为了更好地理解变量在内存中的存储细节,先来认识一下内存中的“字节”和“地址”. 1> 内存以“字节为单位” 0x表示的是十六进制,不用过于纠结,能看懂这些 ...

  5. 【C语言】05-printf和scanf函数

    一.printf函数 这是在stdio.h中声明的一个函数,因此使用前必须加入#include <stdio.h>,使用它可以向标准输出设备(比如屏幕)输出数据 1.用法 1> pr ...

  6. 黑马程序员——C语言基础 scanf函数 基本运算 三目运算符

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (一下内容是对黑马苹果入学视频的个人知识点总结) (一)scanf函数 1>  简单介绍一下scanf函数   这是在 ...

  7. 【学习笔记】【C语言】scanf函数

    1. 简介 这也是在stdio.h中声明的一个函数,因此使用前必须加入#include <stdio.h>.调用scanf函数时,需要传入变量的地址作为参数,scanf函数会等待标准输入设 ...

  8. C语言第五节scanf函数

    变量的内存分析 字节和地址 为了更好地理解变量在内存中的存储细节,先来认识一下内存中的"字节"和"地址". 内存以"字节为单位" 0x表示的 ...

  9. 【C语言】03-printf和scanf函数

    一.printf函数 这是在stdio.h中声明的一个函数,因此使用前必须加入#include <stdio.h>,使用它可以向标准输出设备(比如屏幕)输出数据 1.用法 1> pr ...

随机推荐

  1. HTTP协议解析(格式和举例十分清楚)

    掌握HTTP虽然不是必须的,但是如果你知道它的工作原理,那么在学习JSP开发中的某些知识就可以易如反掌了. 一,HTTP协议详解之URL篇 http(超文本传输协议)是一个基于请求与响应模式的.无状态 ...

  2. Win10《芒果TV - Preview》更新至v3.1.57.0:热门节目和电视台直播回归

    Win10<芒果TV - Preview>是Win10<芒果TV>官方唯一指定内测预览版,最新的改进和功能更新将会在此版本优先体验. 为了想让大家能在12月31日看到<湖 ...

  3. ORACLE 11.2.0.4 RAC安装在rhel6上

    . 关闭ipv4防火墙(两个节点): [root@RAC01 ~]# service iptables stop [root@RAC01 ~]# service iptables status ipt ...

  4. 改善C#程序的建议1:非用ICloneable不可的理由

    原文:改善C#程序的建议1:非用ICloneable不可的理由 好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由.事实上,接口ICloneable还会带来误解 ...

  5. Gradle添加外部项目代码

    为了测试一些功能,我想在公司的项目中引进外部项目的子模块代码进来调试,试验了好半天终于成功了... 原来不需要导入代码,只要在settings.gradle中这样就好了: 然后就可以和原项目中的代码一 ...

  6. 搜索栏+collectionView实现

      效果图如下:   1.h文件声明方法:   @interface IDSGameRoomSearchPage : UIView @property (nonatomic,weak) BaseVie ...

  7. Linux用户和权限

    用户和用户组管理 linux使用用户和组来限制资源的使用. 在linux上运行任何程序或命令都要以一个具体的用户来运行,这个用户的权限决定了相应的程序能访问的资源和能执行的操作. 用户相关命令 组是用 ...

  8. C#抓取远程Web网页信息的代码

    来自:http://www.jb51.net/article/9499.htm 通过程序自动的读取其它网站网页显示的信息,类似于爬虫程序.比方说我们有一个系统,要提取BaiDu网站上歌曲搜索排名.分析 ...

  9. React躬行记(2)——JSX

    JSX既不是字符串,也不是HTML,而是一种类似XML,用于描述用户界面的JavaScript扩展语法,如下代码所示.在使用JSX时,为了避免自动插入分号时出现问题,推荐在其最外层用圆括号包裹,并且必 ...

  10. Git项目迁移

    代码项目迁移步骤 1.将原有项目重命名,old 2.新建一个项目,名字为原本的项目名称,new 3.使用特殊方式克隆代码 # old.git为原项目重命名后的git链接 git clone --mir ...