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. .net mvc项目本地调试:浏览器一直转圈无法访问

    原因: 通过 bundles.Add 方式給多个 js文件添加 匿名,再通过  @Scripts.Render 引入的时候, js 里面使用了 const 来定义变量,就会导致访问pending,具体 ...

  2. 60天shell脚本计划-7/12-渐入佳境

    --作者:飞翔的小胖猪 --创建时间:2021年2月26日 --修改时间:2021年3月2日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可在 ...

  3. Ubutun:镜像网站

    中科大镜像站(地址:安徽):http://mirrors.ustc.edu.cn清华大学镜像站:http://mirrors.tuna.tsinghua.edu.cn浙江大学镜像站:http://mi ...

  4. Linux的用户与用户组管理

    1.Linux用户与用户组 Linux 是多用户多任务操作系统,Linux 系统支持多个用户在同一时间内登陆,不同用户可以执行不同的任务,并且互不影响.不同用户具有不问的权限,毎个用户在权限允许的范围 ...

  5. Java序列化流的奇妙之旅

    Java序列化流有何奇妙之处呢?通过一个个案例逐一感受序列化流. !!!好戏在后头!!! 1.IO流读写文件 先从一个普通文件读写字符串开始讲起. 例子:输出字符串到文件,再从文件中读取字符串 在某一 ...

  6. JDK下载安装与环境变量配置【全网最新】

    1.下载安装JDK 下载地址:(https://www.oracle.com/java/technologies/downloads/) 最好选择解压版,解压即可(说删就删) 解压:例如我解压目录为 ...

  7. CSAPP-Lab04 Architecture Lab 深入解析

    穷且益坚,不坠青云之志. 实验概览 Arch Lab 实验分为三部分.在 A 部分中,需要我们写一些简单的Y86-64程序,从而熟悉Y86-64工具的使用:在 B 部分中,我们要用一个新的指令来扩展S ...

  8. think php 验证器及验证场景的使用

    1:在需要验证的模块名下建一个validate文件夹 ,文件夹下建议个验证的 名称   Goods.php 2:打开Goods.php <?php namespace app\api\valid ...

  9. ref属性

    ref属性 1.被用来给元素或组件注册引用信息(id的替代者) 2.应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc) 3.使用方式: 打标识:<h1 ref=& ...

  10. 【系列】关于NJUPT电赛自控方向第一次积分赛的总结

    本人是NJUPT电子科学与技术专业大一摸鱼狗一枚.本博客旨在总结与分享个人准备电赛所学知识,同时也是为了防止遗忘,锻炼写文章的能力.目前电赛方向为自控方向.主要研究方向为单片机.图像处理.自动控制相关 ...