getch()函数依赖于头文件 conio.h .会在windows平台下从控制台无回显地取一个字符,并且返回读取到的字符。

然而,我在实际用这个函数才发现getch()这个函数并不简单。

getch函数从控制台读取单个字符而不回显,函数不能去读取CTRL+C,当读取一个功能键或方向键,函数必须调用两次(这就说明可以用这个函数去监控功能键和方向键),第一次调用返回0或0xe0,第二次返回实际的键代码

例如:

#include <stdio.h>
#include <conio.h>
int main()
{
while (true)
{
int tmp = _getch();
printf(" ……\n"); //测试每键入一次,打印几次
}
return 0;
}

在这个简单的小程序中,我测试了几个键盘的按键。

  • 在a~z的英文字母、数字键、以及Tab、space、ESC、Backspace、Enter等几个常用键上,printf()只会打印一次,也就是说,getch()会立即返回真实的键码值,并且被tmp变量接收。
  • 在键盘上输入上下左右的方向键,F1~F9、Delete等功能键时,printf()会打印两次。

为了探究getch()的真相,我改写了以上函数。

int main()
{
while (true)
{
int tmp = _getch();
int tmp2 = _getch();
printf(" tmp=%d\n tmp2=%d\n",tmp,tmp2);
}
return 0;
}

在键盘上依次输入上下左右得到如下键值:

  • 上     tmp=224     tmp2=72
  • 下     tmp=224     tmp2=80
  • 左     tmp=224     tmp2=75
  • 右     tmp=224     tmp2=77

上下左右方向键,getch()第一次返回 224(0xe0),第二次返回真实键值

在键盘上依次输入F1~F10、F11、F12、Delete得到如下键值:

  • F1        tmp=0    tmp2=59
  • F2        tmp=0    tmp2=60
  • F3        tmp=0    tmp2=61
  • F10      tmp=0    tmp2=68

F1~F10,getch()第一次返回 0 ,第二次返回该键的真实键值(59~68)

  • F11         tmp=224    tmp2=133
  • F12         tmp=224    tmp2=134
  • Delete     tmp=224    tmp2=83

那么问题就来了,getch()一会返回一个值,一会返回两个值,究竟要怎样写才不会出错呢?

我这里提供一种方法,仅供参考

#include <conio.h>
int main()
{
char tmp; //读取键值,或过滤功能键的第一个返回值
char tmp2; //接受功能键
while (true)
{
tmp = _getch(); if (tmp == 0 || tmp == -32)//表示读取的是功能键或者方向键,丢掉第一个返回值,读取第二个返回值
{
switch (tmp2 = _getch()) //接収功能键返回值
{
case 72://上
printf("This is ↑\n");
break;
case 59://F1
printf("This is F1\n");
break;
default:
break;
}
}
else //普通按键,如字母、数字、space,Esc等按键
{
switch (tmp)
{
case 32://空格
printf("This is Space\n");
break;
case 27://Esc
printf("This is Esc\n");
break;
default:
break;
}
} }
return 0;
}

注意1:在以上代码中 tmp 为char类型,可接受的值为 -128~127之间,所以原本 0xe0的返回值(10进制为224) 会被转换为 -32。

转换原理为 超出char范围的(即127以后的数字),把差值从 char类型的另一侧极限值重新开始计算(即-128往后排)

例如:224——> 超出97(224-127)——> -128+97-1=-32

详见char的越界赋值即其原理剖析

解决办法:

  1. 可以把tmp定义 unsigned char类型
  2. 通过计算、或者测试,得到可用的键值。

注意2:用getch()函数时,编译器可能会给出如下错误

严重性    代码    说明    项目    文件    行    禁止显示状态

错误    C4996     'getch': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _getch. See online help for details.

解决办法:把getch()换成编译器要求的_getch()函数即可

getch()函数的使用方法及其返回值问题的更多相关文章

  1. 一个方法中的ajax在success中renturn一个值,但是方法的返回值是undefind?

    https://segmentfault.com/q/1010000003762379 A页面 console.log(handleData("search_list", &quo ...

  2. C#多线程函数如何传参数和返回值

          详见网站:http://WWW.MOVIH.COM就是一个多线程爬虫系统.   C#多线程函数如何传参数和返回值 提起多线程,不得不提起 委托(delegates)这个概念. 我理解的委托 ...

  3. 关于ajax中return并不能作为方法的返回值

    接下来关于ajax中的return值最后没有办法是方法的最终返回值问题 login(username,password) { console.log("进入方法"); $.ajax ...

  4. STL—— 容器(vector)数据插入insert()方法 的返回值

    vector 容器下的 insert() 方法拥有返回值,由于insert() 方法拥有4种重载函数,他的返回值不尽相同. 第一种,插入单个元素后的返回值: 1 #include <iostre ...

  5. PHP方法的返回值

    不仅是PHP,大部分编程语言的函数或者叫方法,都可以用return来定义方法的返回值.从函数这个叫法来看,本身它就是一个计算操作,因此,计算总会有个结果,如果你在方法体中处理了结果,比如进行了持久化保 ...

  6. Controller方法的返回值

    方法的返回值1.ModelAndView这个就不多说,这是最基础的,前面定义一个ModelAndView,中途使用addObject方法添加属性,再返回.视图解析器会自动扫描到的.2.String这个 ...

  7. java中Arrays类中,binarySearch()方法的返回值问题

    最近在复习Java知识,发现果然不经常使用忘得非常快... 看到binarySearch()方法的使用时,发现书上有点错误,于是就自己上机实验了一下,最后总结一下该方法的返回值. 总结:binaryS ...

  8. SSM-SpringMVC-21:SpringMVC中处理器方法之返回值Object篇

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 今天要记录的是处理方法,返回值为Object的那种,我给它分了一下类: 1.返回值为Object数值(例如1) ...

  9. Java反射机制二 获取方法的返回值或参数的泛型信息

    在使用反射机制时,我们经常需要知道方法的参数和返回值类型,很简单  ,下面上示例,示例中的两个方法非常相似 package deadLockThread; import java.lang.refle ...

随机推荐

  1. pyqt(二)

    二.文本和图片 1. 文本控件 文本控件是QLabel from PyQt5.QtWidgets import QWidget,QApplication,QLabel from PyQt5.QtCor ...

  2. Jmeter计数器实现自增功能

    如果需要引用的数据量较大,且要求不能重复或者需要自增,那么可以使用计数器来实现 如:新增功能,要求名称不能重复 1,新增计数器 计数器:允许用户创建一个在线程组之内都可以被引用的计数器. 计数器允许用 ...

  3. Spring Cloud Gateway 不小心换了个 Web 容器就不能用了,我 TM 人傻了

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  4. 2022年官网下安装RedisDesktopManager最全版与官网查阅方法

    目录 安装部署RedisDesktopManager 一.下载安装 1.浏览器输入网址:https://github.com/ ,输入搜索条件,找到如图,双击 2.滑动浏览器找到如图位置,双击 3.滑 ...

  5. laravel7 webuploader上传图片

    webuploader上传 前提工作: 1>了解 代码如下:1.app_path() app_path函数返回app目录的绝对路径: $path = app_path(); 你还可以使用app_ ...

  6. php 23种设计模型 - 工厂模式

    工厂模式(Factory) 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建 ...

  7. 实践2:github管理代码仓库,包含用webpack打包项目

    此篇介绍用github仓库管理代码,github是大型的项目代码管理,存储平台:简单说帮助一个团队共享,修改同一个项目,配合着gitHub Desktop非常方便: 可以做到多人删除.修改.增加同一项 ...

  8. 【工程应用五】 opencv中linemod模板匹配算法诸多疑惑和自我解读。

    研究这个前前后后也有快两三个月了,因为之前也一直在弄模板匹配方面的东西,所以偶尔还是有不少朋友咨询或者问你有没有研究过linemod这个算法啊,那个效率啥的还不错啊,有段时间一直不以为然,觉得我现在用 ...

  9. SpringCloud-Consul

    1. Consul 简介 Consul是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其它分布式服 务注册与发现的方案,Consul 的方案更"一站式&qu ...

  10. JavaWeb——Http

    4.1.什么是http http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上. 文本:无链接 超文本:利用超链接将普通文本的信息组织在一起的超级文本 4.2.http两个时代的 ...