getch 是一个在 C 语言编程中常用的函数,用于从键盘读取一个字符,但不回显到屏幕上。

在 Windows 环境下,getch 实现通常包含在 <conio.h> 头文件中。需要注意的是,getch 这个符号并非标准,标准的符号是 _getch,虽然 getch 一般会被指向 _getch,但你应当使用 _getch 而非 getch

在 Unix/Linux 环境下,没有系统提供的 getch 实现,我们可以通过以下方法实现:

#include <termio.h>

int getch(void) {
struct termios tm, tm_old;
int fd = 0, ch; if (tcgetattr(fd, &tm) < 0) { // 保存现在的终端设置
return -1;
} tm_old = tm;
cfmakeraw(&tm); // 更改终端为原始模式,该模式下所有的输入数据以字节处理
if (tcsetattr(fd, TCSANOW, &tm) < 0) { // 设置上更改之后的设置
return -1;
} ch = getchar();
if (tcsetattr(fd, TCSANOW, &tm_old) < 0) { // 更改设置为最初的样子
return -1;
} return ch;
}

其中 struct termiostcgetattrtcsetattrcfmakeraw 以及 getchar 的定义为:

typedef unsigned char	cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios{
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
}; int tcgetattr(int __fd, struct termios *__termios_p);
void cfmakeraw(struct termios *__termios_p);
int tcsetattr(int __fd, int __optional_actions, const struct termios *__termios_p);
int getchar(void);

据此,我们可以通过 Rust 的 FFI 为 rust 实现一个 getch

#[cfg(target_os = "windows")]
mod conio {
use std::os::raw::c_int; extern "C" {
pub fn _getch() -> c_int;
}
} #[cfg(target_os = "linux")]
#[allow(non_camel_case_types)]
mod conio {
use std::os::raw::c_int;
type tcflag_t = ::std::os::raw::c_uint;
type speed_t = ::std::os::raw::c_uint;
type cc_t = ::std::os::raw::c_uchar; const NCCS: usize = 32;
const TCSANOW: i32 = 0; #[repr(C)]
#[derive(Default, Copy, Clone)]
struct termios {
c_iflag: tcflag_t,
c_oflag: tcflag_t,
c_cflag: tcflag_t,
c_lflag: tcflag_t,
c_line: cc_t,
c_cc: [cc_t; NCCS],
c_ispeed: speed_t,
c_ospeed: speed_t,
} extern "C" {
fn tcgetattr(__fd: c_int, __termios_p: *mut termios) -> c_int;
fn tcsetattr(__fd: c_int, __optional_actions: c_int, __termios_p: *const termios) -> c_int;
fn cfmakeraw(__termios_p: *mut termios);
fn getchar() -> c_int;
} #[allow(unused_mut, unused_assignments)]
pub fn _getch() -> c_int {
unsafe {
let mut tm: termios = Default::default();
let mut tm_old: termios = Default::default();
let fd = 0;
let mut ch: c_int;
if tcgetattr(fd, &mut tm) < 0 {
return -1;
} tm_old = tm;
cfmakeraw(&mut tm);
if tcsetattr(fd, TCSANOW, &mut tm) < 0 {
return -1;
} ch = getchar();
if tcsetattr(fd, TCSANOW, &mut tm_old) < 0 {
return -1;
} ch
}
}
} #[allow(unused_unsafe)]
fn getch() -> char {
unsafe { conio::_getch() as u8 as char }
}

C/C++ 以及 Rust 中的 getch() 实现的更多相关文章

  1. Rust 中的继承与代码复用

    在学习Rust过程中突然想到怎么实现继承,特别是用于代码复用的继承,于是在网上查了查,发现不是那么简单的. C++的继承 首先看看c++中是如何做的. 例如要做一个场景结点的Node类和一个Sprit ...

  2. Rust 中的类型转换

    1. as 运算符 as 运算符有点像 C 中的强制类型转换,区别在于,它只能用于原始类型(i32 .i64 .f32 . f64 . u8 . u32 . char 等类型),并且它是安全的. 例 ...

  3. Rust中的RefCell和内部可变性

    RefCell Rust在编译阶段会进行严格的借用规则检查,规则如下: 在任意给定时间,要么只能有一个可变引用,要么只能有多个不可变引用. 引用必须总是有效. 即在编译阶段,当有一个不可变值时,不能可 ...

  4. Rust中的Slices

    这个slice切片,python中有,go中有, 但确实,Rust中最严格. 精彩见如下URL: Rust 程序设计语言(第二版) 简体中文版 · GitBook (Legacy) https://k ...

  5. 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?

    我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...

  6. 【译】Rust中的array、vector和slice

    原文链接:https://hashrust.com/blog/arrays-vectors-and-slices-in-rust/ 原文标题:Arrays, vectors and slices in ...

  7. 【译】理解Rust中的闭包

    原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...

  8. 【译】理解Rust中的局部移动

    原文标题:Understanding Partial Moves in Rust 原文链接:https://whileydave.com/2020/11/30/understanding-partia ...

  9. 【译】理解Rust中的Futures (一)

    原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...

  10. 【译】理解Rust中的Futures(二)

    原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...

随机推荐

  1. confd+Nacos实现nginx配置文件管理

    场景: 由于公司内部站点保护的需求, 将部分的站点添加白名单, 这边的操作是在nginx配置文件中添加如下代码 allow 127.0.0.1: deny all; 但随之问题也出现了, 需要添加一个 ...

  2. c++动态库详解

    dmjcb个人博客 原文地址 概念 动态库, 又称动态链接库(\(Dynamic\) \(Link\) \(Library\), \(DLL\)), 是包含程序代码和数据的可执行文件, 在运行时被程序 ...

  3. 纯JS+CSS实现羊了个羊

    前言 省流 gitee上扒的,感觉还不错,拿下来玩玩. https://gitee.com/kenxq/ylgy.git 技术说明 纯JS+CSS实现羊了个羊,包含部分特效,响应式手机.电脑.ipad ...

  4. 高效文件处理:Python pathlib实战指南

    在使用Python处理文件路径时,强烈建议使用pathlib. pathlib以面向对象的方式处理文件路径,既避免了很多陷阱,也能使执行许多路径的相关操作变得更容易. 本篇总结了常用的使用pathli ...

  5. Fuzz技术综述与文件Fuzz

    文章一开始发表在微信公众号 https://mp.weixin.qq.com/s?__biz=MzUyNzc4Mzk3MQ==&mid=2247486189&idx=1&sn= ...

  6. Microsoft Build 2022 专家对话

    Microsoft Build 2022 专家对话 Build 2022 专家对话地址:https://mybuild.microsoft.com/en-US/sessions/81056450-6f ...

  7. 简单软件架构的一些好处zz

    简单软件架构的一些好处_大数据_Dan Luu_InfoQ精选文章 Wave 是一家价值 17 亿美元的公司,拥有 70 名工程师,该公司的产品是一款加减数字的 CRUD 应用程序.为了与此保持一致, ...

  8. forms组件与源码分析、modelform组件

    目录 一.forms组件 forms组件介绍 Form定义 二.forms组件渲染标签 三.forms组件展示信息 四.forms组件校验补充 五.forms组件参数补充 六.forms组件源码剖析 ...

  9. KTL 用C++14写公式的K线工具 - 0.9.3版

    K,K线,Candle蜡烛图. T,技术分析,工具平台 L,公式Language语言使用c++14,Lite小巧简易. 项目仓库:https://github.com/bbqz007/KTL 国内仓库 ...

  10. Spring注解之-@ConditionalOnExpression表达式

    @ConditionalOnExpression("'true") 当括号中的内容为true时,使用该注解的类被实例化,支持语法如下: @ConditionalOnExpressi ...