如何使用OCaml中的字符串格式从文件中读取数字列表

时间:2019-03-16 18:39:50

标签: ocaml

我想获取文件中以特定格式显示的数字列表。但是我没有任何格式的数字(例如%s%d)。

我的文件包含以下文本:

[1;2] [2] 5
[45;37] [9] 33
[3] [2;4] 1000

我尝试了以下

value split_input str fmt =  Scanf.sscanf str fmt (fun x y z -> (x,y,z));

value rec read_file chin acc fmt =
      try let line = input_line chin in
      let (a,b,c) = split_input line fmt in 
      let acc = List.append acc [(a,b,c)] in
            read_file chin acc fmt
      with 
      [ End_of_file -> do { close_in chin; acc}
      ];

value read_list = 
      let chin = open_in "filepath/filename" in
      read_file chin [] "%s %s %d";

问题在于在结尾处指定的格式。我使用了相同的代码从其他文件中获取数据,其中数据的格式为(字符串*字符串*整数)。

要重用相同的代码,我必须以字符串形式接收上述文本,然后根据需要进行拆分。我的问题是:是否存在像%s%d这样的整数列表格式,以便我直接从文件中获取列表,而不用编写其他代码将字符串转换为列表。

1 个答案:

答案 0 :(得分:1)

Scanf中没有列表的内置说明符。可以使用%r说明符将解析委派给自定义扫描程序,但是Scanf并非真正用于解析复杂格式:

let int_list b = Scanf.bscanf b "[%s@]" (fun s ->
  List.map int_of_string @@ String.split_on_char ';' s
)

然后使用这个int_list解析器,我们可以编写

let test = Scanf.sscanf "[1;2]@[3;4]" "%r@%r" int_list int_list (@)

并获取

  val test:int list = [1; 2; 3; 4]

符合预期。但是同时,使用String.split_on_char进行拆分更容易。通常,解析复杂的格式最好用 regexp库,解析器组合器库或解析器生成器。

P.S:您可能应该避免使用经过修订的语法,因为它已被废弃。