如何在Coq中将带空行的字符串解析为嵌套整数列表?
解决Coq中解析含空行的字符串为嵌套整数列表的问题
你的代码无法得到预期结果的核心原因是:Coq的记号解析器会将所有空白字符(包括单个换行和多个换行)视为相同分隔符,无法区分单换行和双换行来划分不同分组,因此原代码会把所有数字解析成一个扁平列表,而非嵌套列表。
针对可变长度分组(每组元素数量不固定)的场景,更合适的方案是先将字符串解析为包含可选数字的列表,再通过辅助函数将连续的有效数字分组为子列表。以下是完整实现:
From Coq Require Export String List NArith. From Coq Require Import Ascii. #[global] Open Scope string_scope. #[global] Open Scope N. Import ListNotations. (* 将字符串按换行符分割为行列表 *) Fixpoint split_lines (s : string) : list string := match s with | EmptyString => [EmptyString] | String c s' => if c = Ascii.ascii_of_nat 10 then (* 匹配换行符ASCII码 *) EmptyString :: split_lines s' else match split_lines s' with | [] => [String c EmptyString] | h :: t => (String c h) :: t end end. (* 将单行字符串转换为可选自然数(空行或无效数字返回None) *) Definition string_to_opt_N (s : string) : option N := N.of_string_opt s. (* 将行列表转换为可选自然数列表 *) Definition lines_to_opt_Ns (lines : list string) : list (option N) := map string_to_opt_N lines. (* 分割列表:提取满足条件的前缀和剩余部分 *) Fixpoint split_prefix {A} (P : A -> bool) (l : list A) : (list A) * (list A) := match l with | [] => ([], []) | h :: t => if P h then let (prefix, suffix) := split_prefix P t in (h :: prefix, suffix) else ([], l) end. (* 将可选自然数列表分组为嵌套列表:连续的有效数字组成子列表,空行分隔不同子列表 *) Fixpoint group_opt (l : list (option N)) : list (list N) := match l with | [] => [] | None :: t => group_opt t (* 跳过空行或无效数字 *) | Some n :: t => let (group, rest) := split_prefix (fun x => match x with Some _ => True | None => False end) t in let full_group := n :: map (fun x => match x with Some m => m end) group in full_group :: group_opt rest end. (* 主解析函数:从字符串得到嵌套整数列表 *) Definition parse_input (s : string) : list (list N) := group_opt (lines_to_opt_Ns (split_lines s)). (* 示例输入 *) Definition example_str := "1 2 3 4 5 ". (* 解析示例 *) Definition example := parse_input example_str. (* 查看结果 *) Print example.
代码说明
- split_lines: 将输入字符串按换行符分割为单个行的列表,保留空行。
- string_to_opt_N: 使用
N.of_string_opt将单行字符串转换为option N,空行或非数字字符串会返回None。 - group_opt: 遍历可选数字列表,将连续的
Some n元素组合为子列表,遇到None则切换到下一个分组。 - parse_input: 串联所有步骤,从原始字符串得到最终的嵌套列表。
运行Print example.后,你会得到预期的[[1; 2]; [3; 4; 5]]。
内容的提问来源于stack exchange,提问作者rex
相关产品推荐
相关产品推荐

