引言 - getch简述
引用老的TC版本getch说明. (文章介绍点有点窄, 应用点都是一些恐龙游戏时代的开发细节)
#include <conio.h>
/*
* 立即从客户端得到输入的字符. 出错返回EOF
*/
int __cdecl getch(void);
记得三年之前看过一本书 <<C专家编程>> 有一章提到在立即从标准输入中得到输入字符(后面还介绍了一种linux实现, 对于现在linux版本不行了)。
那位作者评价就是, 由于linux对于''getch''支持的不友好, 导致了linux错失了很多游戏开发人员.
当然现在版本, window 上也没有这个函数了. 改成下面这个挫的样子
#include <conio.h> _Check_return_ _DCRTIMP int __cdecl _getch(void);
总得而言''立即交互'' 是游戏开发的入口. 很有必要.
前言 - 从实际例子中了解getch
现在Visual Studio 2015 Update3 中测试一段 getch 立即得到结果的代码 main.c
#include <stdio.h> #include <stdlib.h> #include <conio.h> /* * 制作等待, 函数 */ int main(int argc, char * argv[]) { printf("请输入任意字符结束程序......"); int rt = _getch(); printf("%d => %c\n", rt, rt); rt = _getch(); printf("%d => %c\n", rt, rt); system("pause"); return 0; }
运行结果
从上可以看出, _getch 名字变了, 但是功能和getch没有变化.
这里我们封装一下. 看新的文件, 一个演示小demo
#include <stdio.h>
#include <conio.h>
/*
* 定义统一接口 sh_getch 理解得到玩家输入
* : 返回 输入int值, 错误为EOF
*/
#define sh_getch _getch
/*
* 等待函数
*/
static void _pause(void) {
printf("请按任意键继续. . .");
rewind(stdin);
sh_getch();
}
/*
* 继续等待函数
*/
int main(int argc, char * argv[]) {
_pause();
return 0;
}
来替代原先的 window 上 的 system("pause"), linux 上 pause(). rewind 重置文件FILE * 流, 清除输入流保证当前流是干净的.
正文 - linux上实现一个getch, 立即接收
linux 需要借助 termio.h 终端控制头文件. 主要实现如下
#include <termio.h> /* * 得到用户输入的一个字符 * : 返回得到字符 */ int sh_getch(void) { int cr; struct termios nts, ots; if (tcgetattr(0, &ots) < 0) // 得到当前终端(0表示标准输入)的设置 return EOF; nts = ots; cfmakeraw(&nts); // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理 if (tcsetattr(0, TCSANOW, &nts) < 0) // 设置上更改之后的设置 return EOF; cr = getchar(); if (tcsetattr(0, TCSANOW, &ots) < 0) // 设置还原成老的模式 return EOF; return cr; }
主要是设置终端为原始接收字符模式, 可以接收立即返回, 随后还原老的环境设置. 终端缓冲, 也是出于效率考虑, 否则编程太复杂了.
同样测试 一个 getch.c
#include <stdio.h> #include <termio.h> /* * 得到用户输入的一个字符 * : 返回得到字符 */ int sh_getch(void); /* * 测试标准快速输入 */ int main(int argc, char * argv[]) { int ch; printf("请按任意键继续. . ."); ch = sh_getch(); printf("%d => %c\n", ch, ch); ch = sh_getch(); printf("%d => %c\n", ch, ch); return 0; }
linux上演示结果
gcc -Wall -ggdb3 -o getch.out getch.c
一切正常.
到这里我们关闭getch跨平台实现细节都确定了. 那么我们实现一个跨平台的getch版本. 先看头文件声明部分(*.h 文件插入).