C基础 一个可以改变linux的函数getch
引言 - 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 ;
}
运行结果

从上可以看出, _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 ;
}
来替代原先的 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(, &ots) < ) // 得到当前终端(0表示标准输入)的设置
return EOF; nts = ots;
cfmakeraw(&nts); // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理
if (tcsetattr(, TCSANOW, &nts) < ) // 设置上更改之后的设置
return EOF; cr = getchar();
if (tcsetattr(, TCSANOW, &ots) < ) // 设置还原成老的模式
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 ;
}
linux上演示结果
gcc -Wall -ggdb3 -o getch.out getch.c

一切正常.
到这里我们关闭getch跨平台实现细节都确定了. 那么我们实现一个跨平台的getch版本. 先看头文件声明部分(*.h 文件插入).
/*
* error => 以后再说
* 跨平台的丑陋从这里开始
* __GNUC => linux 平台特殊操作
* __MSC_VER => window 平台特殊操作
*/
#ifdef __GUNC__ // 下面是依赖GCC编译器实现 #include <termio.h> /*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int sh_getch(void); #elif _MSC_VER // 下面是依赖Visual Studio编译器实现 #include <conio.h> // window 上用_getch 替代了getch, 这里为了让其回来
#define sh_getch _getch #else
#error "error : Currently only supports the Visual Studio and GCC!"
#endif
再看实现部分 (*.c 文件中插入)
// 为linux扩展一些功能
#if defined(__GUNC__) /*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int
sh_getch(void) {
int cr;
struct termios nts, ots; if (tcgetattr(, &ots) < ) // 得到当前终端(0表示标准输入)的设置
return EOF; nts = ots;
cfmakeraw(&nts); // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理
if (tcsetattr(, TCSANOW, &nts) < ) // 设置上更改之后的设置
return EOF; cr = getchar();
if (tcsetattr(, TCSANOW, &ots) < ) // 设置还原成老的模式
return EOF; return cr;
} #endif
这就是getch跨平台实现的关键了. 从这里开始,你就可以构建自己喜欢的游戏了, 通过 sh_getch 入口开始.
预备下次重构C字符串,再下次采用simplec框架重写一个老的灭龙传说V2.0.0游戏, 让其支持跨平台, 并支持配置扩展.
后记 - 未来有 ∞ 次
Get Over http://music.163.com/#/song?id=22771653

C基础 一个可以改变linux的函数getch的更多相关文章
- 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字符不改变,给定函数,编写函数 void Stringchang(const char*input,char*output)其中input是输入字符串,output是输出字符串
import java.util.Scanner; /*** * 1. 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字 ...
- [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...
- Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...
- linux 线程函数大全
Technorati 标签: Linux thread 索引: 1.创建线程pthread_create 2.等待线程结束pthread_join 3.分离线程pthread_detach 4.创建线 ...
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...
- PHP基础入门(三)---PHP函数基础
PHP基础入门(三)---函数 今天来给大家分享一下PHP的函数基础.有了前两章的了解,想必大家对PHP有了一定的基础了解.想回顾前两章的朋友可以点击"PHP基础入门(一)"&qu ...
- linux API函数大全
获取当前执行路径:getcwd1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAdd ...
- linux select函数详解
linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...
- 【 MAKEFILE 编程基础之四】详解MAKEFILE 函数的语法与使用!
本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/gcc-makefile/771.html ...
随机推荐
- AD高级培训PPT总结
AD高级培训PPT总结 https://bbs.sangfor.com.cn/forum.php?mod=viewthread&tid=44905&highlight= 说明: ...
- 洛谷3800:Power收集——题解
https://www.luogu.org/problemnew/show/P3800 可以把游戏界面理解成一个N行M列的棋盘,有K个格子上有P点,其价值为val(i,j) 初始灵梦可以选择在第一行的 ...
- POJ.1003 Hangover ( 水 )
POJ.1003 Hangover ( 水 ) 代码总览 #include <cstdio> #include <cstring> #include <algorithm ...
- UVA.11384 Help is needed for Dexter (思维题)
UVA.11384 Help is needed for Dexter (思维题) 题意分析 同样水题一道,这回思路对了. 给出数字n,面对一个1,2,3,4--n的数字序列,你可以对他们的部分或者全 ...
- HDOJ(HDU).1114 Piggy-Bank (DP 完全背包)
HDOJ(HDU).1114 Piggy-Bank (DP 完全背包) 题意分析 裸的完全背包 代码总览 #include <iostream> #include <cstdio&g ...
- UIScrollView控件及其三个常用属性:contentSize、contentInset和contentOffset
如果您对UIScrollView控件感到难以理解,下面是本人自己对UIScrollView控件的理解方式,按照我的思路,理解UIScrollView控件非常容易! 我对UIScrollView的构成理 ...
- POJ 2289 最大流
Jamie's Contact Groups Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 7624 Accepted: ...
- vue-transition-animation
<!Doctype> <html> <head> <meta charset="utf-8"> <meta name=&quo ...
- Lucene6.6添加索引数据时字符个数超限,字符数不能超过BYTE_BLOCK_SIZE=32766
最近发现Lucene6.6版本添加索引数据字符数超过32766时,出现报错,而Lucene4.6版本中则未出现这一问题,原因如下: 概述: 添加索引数据时,对于分词字段,分词后的Ter ...
- 2017 济南综合班 Day 5
毕业考试 (exam.cpp/c/pas) (1s/256M) 问题描述 快毕业了,Barry希望能通过期末的N门考试来顺利毕业.如果他的N门考试平均分能够达到V分,则他能够成功毕业.现在已知每门的分 ...