Utop中Scanf.scanf首次正常二次输入报错:Stdlib.Scanf.Scan_failure咨询
OCaml Scanf 重复调用报错问题解决
问题重现
执行以下OCaml代码:
Scanf.scanf "%d %d" (fun a b -> Printf.printf "%d\n" (a - b));;
首次输入3 1时正常输出2 - : unit = (),但第二次输入相同内容时,触发报错:
Exception:
Stdlib.Scanf.Scan_failure
"scanf: bad input at char number 3: character '\n' is not a decimal digit".
问题原因
Scanf.scanf从标准输入缓冲区读取数据时,不会自动清理残留的换行符:
- 第一次输入
3 1并回车后,缓冲区实际内容是3 1\n - 第一次调用
scanf只读取了3和1,剩余的\n留在缓冲区中 - 第二次调用
scanf时,优先读取这个残留的换行符,但格式串%d %d要求整数输入,换行符不符合要求,因此抛出Scan_failure
解决方法
方法1:修改格式串,自动跳过换行符
在格式串末尾添加\n,让scanf处理完整数后自动跳过换行符:
Scanf.scanf "%d %d\n" (fun a b -> Printf.printf "%d\n" (a - b));;
方法2:手动清空缓冲区残留
每次调用scanf后,用额外的格式串跳过剩余的换行符:
Scanf.scanf "%d %d" (fun a b -> Printf.printf "%d\n" (a - b));; Scanf.scanf "%_" (fun () -> ());; (* 跳过缓冲区剩余的换行符 *)
方法3:改用整行读取+字符串解析
用read_line()读取完整输入行,再用Scanf.sscanf解析,彻底避免缓冲区残留问题:
let () = let line = read_line () in Scanf.sscanf line "%d %d" (fun a b -> Printf.printf "%d\n" (a - b))
内容的提问来源于stack exchange,提问作者Jeongseop Lee
相关产品推荐
相关产品推荐

