getch()函数的使用方法及其返回值问题
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
解决办法:
- 可以把tmp定义 unsigned char类型
- 通过计算、或者测试,得到可用的键值。
注意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()函数的使用方法及其返回值问题的更多相关文章
- 一个方法中的ajax在success中renturn一个值,但是方法的返回值是undefind?
https://segmentfault.com/q/1010000003762379 A页面 console.log(handleData("search_list", &quo ...
- C#多线程函数如何传参数和返回值
详见网站:http://WWW.MOVIH.COM就是一个多线程爬虫系统. C#多线程函数如何传参数和返回值 提起多线程,不得不提起 委托(delegates)这个概念. 我理解的委托 ...
- 关于ajax中return并不能作为方法的返回值
接下来关于ajax中的return值最后没有办法是方法的最终返回值问题 login(username,password) { console.log("进入方法"); $.ajax ...
- STL—— 容器(vector)数据插入insert()方法 的返回值
vector 容器下的 insert() 方法拥有返回值,由于insert() 方法拥有4种重载函数,他的返回值不尽相同. 第一种,插入单个元素后的返回值: 1 #include <iostre ...
- PHP方法的返回值
不仅是PHP,大部分编程语言的函数或者叫方法,都可以用return来定义方法的返回值.从函数这个叫法来看,本身它就是一个计算操作,因此,计算总会有个结果,如果你在方法体中处理了结果,比如进行了持久化保 ...
- Controller方法的返回值
方法的返回值1.ModelAndView这个就不多说,这是最基础的,前面定义一个ModelAndView,中途使用addObject方法添加属性,再返回.视图解析器会自动扫描到的.2.String这个 ...
- java中Arrays类中,binarySearch()方法的返回值问题
最近在复习Java知识,发现果然不经常使用忘得非常快... 看到binarySearch()方法的使用时,发现书上有点错误,于是就自己上机实验了一下,最后总结一下该方法的返回值. 总结:binaryS ...
- SSM-SpringMVC-21:SpringMVC中处理器方法之返回值Object篇
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 今天要记录的是处理方法,返回值为Object的那种,我给它分了一下类: 1.返回值为Object数值(例如1) ...
- Java反射机制二 获取方法的返回值或参数的泛型信息
在使用反射机制时,我们经常需要知道方法的参数和返回值类型,很简单 ,下面上示例,示例中的两个方法非常相似 package deadLockThread; import java.lang.refle ...
随机推荐
- c++ cgi执行shell命令l发送qq邮件mailx
#include <cstdlib> //随机数 #include <iostream> #include <cstdio> //popen函数调用的需要 #inc ...
- VS常用的快捷键
整理代码 Ctrl+k+f 注释 Ctrl+k+c 取消注释 Ctrl+k+u 帮助文档 F1 无调试启动 ...
- 分页PHP
<?php//1.连接数据库$link = mysqli_connect('127.0.0.1','root','root','1906');//2.设置字符集mysqli_set_charse ...
- mysql5.7.35数据库迁移
最近开发使用的测试环境的服务器使用的一台惠普E7300CPU\4G内存\160G西数硬盘配置,数据量近达20G!虽然作为测试数据库但也算是重要角色,一旦出现将严重影响工作.计划迁移至另一台做有RAID ...
- mysql全量备份与增量备份
mysql全量备份与增量备份 1.全量备份 全量备份就是把数据库中所有的数据进行备份. 备份所有库: mysqldump -uroot -p456 -S /data/3306/mysql.sock ...
- Clickhouse 与 Kafka 的数据同步
作者: LemonNan 原文地址: https://mp.weixin.qq.com/s/SUUHF9R_FKg-3vq7Q3cwBQ 注: 转载需注明作者及原文地址 介绍 Clickhouse 本 ...
- 使用vscode Container开发调试envoy
由于我最近在研究 envoy 这个项目,这是个cpp的项目,对于我这种cpp新人来说还是比较有压力的,感觉处处都是坑,开个引导文章记录一下. 如果要研究 envoy 项目源码,那肯定是需要代码跳转的, ...
- m3u8文件合并处理
m3u8文件合并处理 简介 M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码."M3U" 和 "M3U8" 文件都是苹果公司使用的 HTTP ...
- Spring Boot 进行优雅的字段校验
Controller层 VS Service层 一般推荐与业务无关的放在Controller层中进行校验,而与业务有关的放在Service层中进行校验. 那么如何将参数校验写的优雅美观呢,如果都是if ...
- k8s学习笔记一(搭建&部署helloworld应用)
kubernetes 目录 kubernetes 虚拟机创建三个节点 k8s install 部署hello world 应用 issue 汇总 node 一直处理NotReady状态 重启系统后虚拟 ...