You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vlang中实现getch功能?适配Brainfuck解释器需求

在Vlang中实现无回车获取键盘输入(含扫描码)用于Brainfuck解释器

方案1:直接嵌入C代码(跨平台兼容,修复你之前的嵌入失败问题)

Vlang支持直接在代码中嵌入C片段,不需要依赖C2V工具。下面是一个跨平台实现,能获取字符(无需回车),并处理特殊键的扫描码:

module main

// 嵌入C代码实现跨平台的无回车输入与扫描码获取
#flag linux -ltermios
#flag darwin -ltermios
#include <stdio.h>
#ifdef _WIN32
#include <conio.h>
int get_key_scancode() {
    int ch = _getch();
    // 特殊键(方向键、功能键等)会先返回0或0xE0,再返回扫描码
    if (ch == 0 || ch == 0xE0) {
        return _getch();
    }
    // 普通字符返回ASCII码(可根据需求调整为对应的扫描码映射)
    return ch;
}
#else
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

int get_key_scancode() {
    struct termios old_attr, new_attr;
    int ch;
    // 保存终端原有属性
    tcgetattr(STDIN_FILENO, &old_attr);
    // 设置终端为非规范模式,关闭回显
    new_attr = old_attr;
    new_attr.c_lflag &= ~(ICANON | ECHO);
    new_attr.c_cc[VMIN] = 1;
    new_attr.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSANOW, &new_attr);
    
    // 获取字符
    ch = getchar();
    
    // 恢复终端原有属性
    tcsetattr(STDIN_FILENO, TCSANOW, &old_attr);
    // Linux/macOS下普通字符返回ASCII,特殊键需要额外处理(如需扫描码需读取/dev/input,需权限)
    return ch;
}
#endif

// 声明C函数供V调用
fn c.get_key_scancode() int

// 封装为V的公共函数
fn get_key() int {
    return c.get_key_scancode()
}

// 测试:Brainfuck的,指令调用示例
fn main() {
    println("Brainfuck ,指令测试 - 按下任意键(无需回车):")
    key_code := get_key()
    println("获取到的键值/扫描码:${key_code}")
    // 若要转为字符(仅普通ASCII键有效)
    if key_code >= 32 && key_code <= 126 {
        println("对应字符:${u8(key_code)}")
    }
}

代码说明:

  • Windows平台:直接使用conio.h的_getch(),自动处理特殊键的扫描码返回逻辑
  • Linux/macOS平台:通过修改终端属性关闭行缓冲与回显,实现无回车输入;普通字符返回ASCII码,如需特殊键扫描码,需通过读取/dev/input设备实现(需要root权限,适合特定场景)
  • 编译时自动链接所需库(Linux/macOS链接termios),无需额外配置

方案2:使用Vlang的term模块(轻量可选)

如果你的Vlang环境安装了term模块(部分版本默认包含),可以直接调用终端控制函数:

import term

fn get_key() int {
    // 设置终端为原始模式
    term.set_raw_mode(true)
    // 确保程序退出时恢复终端模式
    defer { term.set_raw_mode(false) }
    // 获取字符,失败则panic
    ch := term.get_char() or { panic("无法获取输入") }
    return int(ch)
}

注意:term模块默认返回ASCII字符,如需扫描码仍需结合方案1的逻辑扩展。

关键注意事项

  • 终端状态恢复:Linux/macOS下必须恢复终端原有属性,否则程序退出后终端会出现输入不回显等异常问题,代码中用tcsetattr确保恢复
  • 扫描码兼容性:不同平台的扫描码定义不同,如果Brainfuck仅需ASCII输入,返回ASCII码即可满足需求;如需处理特殊键,需针对各平台单独映射扫描码

内容的提问来源于stack exchange,提问作者JYL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:30:11