OCaml中使用input_byte stdin即时读取标准输入的方法
问题描述
我尝试用input_byte stdin读取标准输入,写了这段递归循环代码:
let rec loop () = Format.eprintf "in the loop@."; (match input_byte stdin with | 0x0D -> print_newline () | b -> Format.eprintf "saw %i@." b); loop () let () = loop ()
当输入aaa时,我预期的输出是:
in the loop a in the loop saw 97 a in the loop saw 97 a in the loop saw 97
但实际必须按下回车才会输出内容,得到的结果是:
in the loop aaa saw 97 in the loop saw 97 in the loop saw 97 in the loop saw 10 in the loop
请问有没有无需等待刷新就能从通道读取字符的方法?
解决方法
这是因为默认情况下终端处于行缓冲模式——只有输入换行符时,系统才会把输入内容传递给程序。要实现逐字符即时读取,需要修改终端输入模式,关闭行缓冲。
在OCaml中可以借助Unix模块修改终端属性:
open Unix let () = (* 获取当前终端属性 *) let term_attr = tcgetattr stdin in (* 关闭行缓冲,保留回显(若不需要回显可设为false) *) let new_attr = { term_attr with c_icanon = false } in tcsetattr stdin TCSANOW new_attr; (* 程序退出时恢复终端原始属性,避免终端状态异常 *) at_exit (fun () -> tcsetattr stdin TCSANOW term_attr) let rec loop () = Format.eprintf "in the loop@."; match input_byte stdin with | 0x0A -> (* 处理换行符 *) print_newline (); loop () | b -> Format.eprintf "saw %i@." b; loop () let () = loop ()
关键说明:
tcgetattr stdin:获取当前终端的配置参数c_icanon = false:关闭行缓冲,让输入的每个字符立即被程序读取at_exit:注册回调函数,确保程序退出时恢复终端原始设置,防止终端陷入异常状态
修改后,输入每个字符时程序会立即响应,无需等待回车即可读取并输出结果。
内容的提问来源于stack exchange,提问作者Lhooq
相关产品推荐
相关产品推荐

