基于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
相关产品推荐
相关产品推荐

