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. Maven目录结构, war目录结构

    Maven目录结构 src/main/java 存放java servlet类文件 src/main/webapp 存放jsp文件 war目录结构 Maven web项目目录结构

  2. ssh执行命令或者脚本里最好先加上 source /etc/profile

    记: 写一次shell脚本,发现总提示 找不到JAVA_HOME .明明已经配了环境变量,并且java -version也已经能输出信息,但就是提示. 后来在 脚本中加入第一句代码 source /e ...

  3. python文件操作glob_os_等对比

    Python标准库glob介绍 一. glob模块通配符 通配符 功能 * 匹配0或多个字符 ** 匹配所有文件,目录,子目录和子目录里面的文件 (3.5版本新增) ? 匹配一个字符,这里与正则表达式 ...

  4. jq获取不包含某些属性的元素

    最近写项目,有个功能实现checkbox全选,但是被禁用的checkbox不能选中 点击全选后发现禁用checkbox的也被选中了,不符合需求. 但是想了半天,属性选择器都是判断某个属性值的,没有判断 ...

  5. C++_Leecode20有效的括号

    一.题目介绍 1.题目描述 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正 ...

  6. RxJS中高阶操作符的全面讲解:switchMap,mergeMap,concatMap,exhaustMap

    RxJS中高阶映射操作符的全面讲解:switchMap, mergeMap, concatMap (and exhaustMap) 原文链接:https://blog.angular-universi ...

  7. 微服务7:通信之RPC

    ★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...

  8. [递归回溯] LeetCode 504七进制数(摸鱼版)

    LeetCode 七进制数 前言: 这个就没什么好说的了 题目:略 步入正题 进位制转换 10 -n 余数加倒叙 没什么好讲的直接上七进制代码 偷个懒 10进位制转7 class Solution { ...

  9. pycharm远程调试、开发(详细操作)

    如果仅是远程开发,新建 ssh Interpreter 并 apply tools -> deployment -> browser remote host 即可 1.服务器侧准备 准备调 ...

  10. 玩转OpenMLDB社区,四张角色卡待解锁

    关于OpenMLDB OpenMLDB 是一个开源机器学习数据库,提供企业级 FeatureOps 全栈解决方案.OpenMLDB 致力于闭环解决 AI 工程化落地的数据治理难题,并且已经在上百个企业 ...