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

基于Ncurses(FORM)的表单验证:字符输入验证无法实现

ncurses表单数字输入验证失效问题解决

核心问题

你用TYPE_REGEXP设置的数字验证,默认只在字段失去焦点时才会触发,并非实时拦截非法输入。所以输入非数字字符时,字符会先显示在字段里,不会被即时阻止。后续添加的删除逻辑因时机不对,也没法彻底解决问题。

两种可行解决方案

方案1:实时拦截非法输入(推荐)

直接在获取输入后判断字符合法性,仅将数字和必要控制键传给表单驱动,从根源上阻止非法输入显示:

#include <form.h>
#include <ctype.h>

int main() {
    initscr();
    curs_set(1);
    WINDOW *win = newwin(5, 40, 10, 10);
    keypad(win, TRUE);
    box(win, 0, 0);
    wrefresh(win);

    FIELD *fields[2];
    fields[0] = new_field(1, 20, 2, 2, 0, 0);
    fields[1] = NULL;
    // 保留正则作为二次兜底验证
    set_field_type(fields[0], TYPE_REGEXP, "^[0-9]*$");
    set_field_opts(fields[0], O_VISIBLE | O_ACTIVE | O_EDIT);

    FORM *form = new_form(fields);
    set_form_win(form, win);
    set_form_sub(form, derwin(win, 3, 38, 1, 1));
    post_form(form);
    wrefresh(win);

    int ch;
    while ((ch = wgetch(win)) != KEY_F(1)) {
        // 仅允许数字、退格、删除、方向键、回车这些合法输入
        if (isdigit(ch) || ch == KEY_BACKSPACE || ch == KEY_DC || 
            ch == KEY_LEFT || ch == KEY_RIGHT || ch == '\n') {
            int status = form_driver(form, ch);
            if (status == E_OK) {
                wrefresh(win);
            }
        }
        // 非法字符直接忽略,不传给表单处理
    }

    unpost_form(form);
    free_form(form);
    free_field(fields[0]);
    endwin();

    return 0;
}

方案2:基于内置验证的实时修正

如果必须依赖正则验证,可以在每次输入后立刻触发验证,失败则回滚输入:

#include <form.h>

void revert_invalid(FORM *form) {
    // 删除刚输入的非法字符
    form_driver(form, REQ_DEL_PREV);
    // 刷新表单同步界面
    wrefresh(form_win(form));
}

int main() {
    initscr();
    curs_set(1);
    WINDOW *win = newwin(5, 40, 10, 10);
    keypad(win, TRUE);
    box(win, 0, 0);
    wrefresh(win);

    FIELD *fields[2];
    fields[0] = new_field(1, 20, 2, 2, 0, 0);
    fields[1] = NULL;
    set_field_type(fields[0], TYPE_REGEXP, "^[0-9]*$");
    set_field_opts(fields[0], O_VISIBLE | O_ACTIVE | O_EDIT);

    FORM *form = new_form(fields);
    set_form_win(form, win);
    set_form_sub(form, derwin(win, 3, 38, 1, 1));
    post_form(form);
    wrefresh(win);

    int ch;
    while ((ch = wgetch(win)) != KEY_F(1)) {
        int status = form_driver(form, ch);
        if (status == E_OK) {
            // 输入后立刻触发验证
            status = form_driver(form, REQ_VALIDATION);
            if (status == E_INVALID_FIELD) {
                revert_invalid(form);
            } else {
                wrefresh(win);
            }
        }
    }

    unpost_form(form);
    free_form(form);
    free_field(fields[0]);
    endwin();

    return 0;
}

额外说明

  • 方案1不会出现非法字符闪烁的问题,运行更流畅;方案2适合复杂正则规则场景,但可能存在短暂界面闪烁。
  • 编译时需链接ncurses和form库,命令示例:gcc your_code.c -o your_program -lncurses -lform

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:28:12