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

#include <stdio.h>

int main()
{
char ope = '\0';//操作符+ - * /
int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果 printf("请输入第一个运算参数\n");
scanf("%d",¶1);
printf("请输入运算符 '+ - * /'\n");
scanf("%c",&ope);
printf("请输入第二个运算参数\n");
scanf("%d",¶2);
switch(ope)
{
case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
break;
case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
break;
case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
break;
case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
break;
default: printf("运算符输入错误\n");//
break;
}
printf("运算结果是: %d\n", result);
return 0;
}

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

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

我们修改下程序,如下:

#include <stdio.h>

int main()
{
char ope = '\0';//操作符+ - * /
int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果 printf("请输入第一个运算参数\n");
scanf("%d",¶1);
printf("请输入运算符 '+ - * /'\n");
scanf("%c",&ope); printf("运算符是: %d\n", ope);
printf("请输入第二个运算参数\n");
scanf("%d",¶2);//加入这两行代码
switch(ope)
{
case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
break;
case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
break;
case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
break;
case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
break;
default: printf("运算符输入错误\n");//
break;
}
printf("运算结果是: %d\n", result);
return 0;
}

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

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

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

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

#include <stdio.h>
#include <conio.h> int main()
{
char ope = '\0';//操作符+ - * /
int para1 = 0, para2 = 0, result = 0;//para1是运算参数1,para2是运算参数2,result是运算结果 printf("请输入第一个运算参数\n");
scanf("%d",¶1);
getchar(); printf("请输入运算符 '+ - * /'\n");
scanf("%c",&ope);
getchar();
printf("运算符是: %d\n", ope);
printf("请输入第二个运算参数\n");
scanf("%d",¶2);
switch(ope)
{
case '+': result = para1 + para2;//如果运算符是+,就执行加法运算
break;
case '-': result = para1 - para2;//如果运算符是-,就执行减法运算
break;
case '*': result = para1 * para2;//如果运算符是*,就执行乘法运算
break;
case '/': result = para1 / para2;//如果运算符是/,就执行除法运算
break;
default: printf("运算符输入错误\n");//
break;
}
printf("运算结果是: %d\n", result);
return 0;
}

在每次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. 图像滤镜艺术---ZPhotoEngine超级算法库

    原文:图像滤镜艺术---ZPhotoEngine超级算法库 一直以来,都有个想法,想要做一个属于自己的图像算法库,这个想法,在经过了几个月的努力之后,终于诞生了,这就是ZPhotoEngine算法库. ...

  2. 图像Stride求取

    原文:图像Stride求取 做这个日志也许你会觉得多余,但是,如果只给你了图像的流文件,和图像的Width,让你还原原始图像,那么你会发现一个问题,就是Stride未知的问题,这时就需要根据图像的Wi ...

  3. sql语句查询重复值

    select * from user where name in (select name from user group by name having count(*)>1)

  4. OWIN 托管服务器问题:StartOptions WebApp.Start TargetInvocationException

    我有一个与OWIN托管的服务器有一个小问题.我试图让它可以访问本地网络,这意味着我不得不添加一些额外的选择: // Start OWIN host StartOptions options = new ...

  5. C#最基本的数据库增删改查

    namespace access { public partial class Form1 : Form { //定义数据库的连接路径 string txtConn ="Provider=M ...

  6. AndroidStudio问题汇总

    1.Error:Execution failed for task ':app:preDebugAndroidTestBuild'.> Conflict with dependency 'com ...

  7. c++类运算符重载遇到的函数形参问题

    class A { public: A(int arg1, int arg2); ~A(); A &operator = ( A &other); A operator + ( A & ...

  8. SYN012型B码时统

       SYN012型B码时统 产品概述 SYN012型B码时统是由西安同步电子科技有限公司精心设计.自行研发生产的一款通用性时统终端,内置高精度恒温晶振,接收GPS北斗双模卫星信号,10MHz外部参考 ...

  9. SpringCloud-分布式配置中心【加密-对称加密】

      前面我们介绍了SpringCloud的分布式配置中心,我们将项目中的配置信息保存在git或者码云的仓库中,但是这样一些敏感信息就暴露出来了,比如数据库连接的账号密码等信息,这时我们最好能够对这些信 ...

  10. windows下nginx的安装和使用

    LNMP的安装与配置 windows下的nginx安装和使用 1.1 去官网下载相应的安装包:http://nginx.org/en/download.html 1.2 解压后进入PowerShell ...