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 ...
随机推荐
- BZOJ4868 Shoi2017期末考试(三分+贪心)
容易想到枚举最晚发布成绩的课哪天发布,这样与ti和C有关的贡献固定.每门课要么贡献一些调节次数,要么需要一些调节次数,剩下的算贡献也非常显然.这样就能做到平方级别了. 然后大胆猜想这是一个凸函数三分就 ...
- Vika and Segments - CF610D
Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-d ...
- POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16742 Accepted: 7390 Ca ...
- [洛谷P4111][HEOI2015]小Z的房间
题目大意:有一个$n\times m$的房间,一些位置是房间,另一些位置是柱子,相邻两个房间之间有墙,问有多少种方案可以打通一些墙把所有房间连成一棵树,柱子不可以打通 题解:矩阵树定理,把房间当点,墙 ...
- [NOIP2015 TG D2T3]运输计划
题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去.m 个计划, 这 m 个计划会同时开始.当这 m 个任务都完成时,工作完成. 现在可以把任意一个边的边权变为 ...
- [bzoj] 1068 压缩 || 区间dp
原题 f[i][j][0/1]表示i-1处有一个M,i到j压缩后的长度,0/1表示i到j中有没有m. 初始为j-i+1 f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k ...
- bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)
题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...
- bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)
题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符. 前几天刚学了hash+二分求lcp,就看到这题. 原来splay还能这么用?!原来splay模板这么好写?我以前写的s ...
- 将Visual Studio项目转换为Dot Net Core项目 csproj to xproj
删除csproj文件. 将 package.config 重命名为 project.json . 转换文件,将xml转换为json格式. <?xml version="1.0" ...
- Tree and Permutation dfs hdu 6446
Problem Description There are N vertices connected by N−1 edges, each edge has its own length.The se ...