ocaml - 如何在ocaml中读取文件?

标签 ocaml

我有一个以下格式的输入文件:

q0;q1
a;b
(q0,x);(q1;x)

我想要三个列表,如下所示:

a = ["q0";"q1"];
b = ["a";"b"];
c = [("q0","x");("q1","y")];

这是我的代码:

let buf = Queue.create ();;

let catfile filename =
let rec print_all_lines in_chan =
    Queue.add (input_line in_chan) buf;
    print_all_lines in_chan
in
let in_file = open_in filename in
try
    print_all_lines in_file
with End_of_file -> close_in in_file;;

catfile "test.txt";;

let rec pvt_rec_split skipf rv str c i limit =
if (List.length rv < (limit - 1)) && (i < String.length str) then (
    if String.contains_from str i c then
        let o = String.index_from str i c in
        pvt_rec_split skipf
            (rv @ [ String.sub str i (o - i)])
            str c
            (skipf str c o)
            limit;
    else
        rv @ [ String.sub str i ((String.length str) - i) ]
) else (
    if i < String.length str then
        rv @ [ String.sub str i ((String.length str) - i) ]
    else
        rv
);;

let split s c limit =
let rec pvt_skip_char s c i =
    if (i >= String.length s ) then (
        String.length s
    ) else (
        if ((String.get s i) == c) then (
            pvt_skip_char s c (i +1)
        ) else (
            i
        )
    )
in
pvt_rec_split pvt_skip_char [] s c 0 limit ;;

let a = split (Queue.take buf) ';' 100;;

let b = split (Queue.take buf) ';' 100;;

let c = split (Queue.take buf) ';' 100;;

基本上 split 函数用分隔符分割字符串并返回一个列表。

所以,我能够正确生成列表 a 和 b。

但是对于列表 c,我得到一个类型字符串列表。实际上我想要一个类型为 ('string*'string) 的列表。

我该怎么做?

最佳答案

文件内容(注意括号内的逗号分隔)

q0;q1
a;b
(q0,x);(q1,x)

Ocaml代码

let split_str separator s =
  let list = ref [] in
  let start = ref 0 in
  let () = try
    while true do
      let index = String.index_from s !start separator in
      list := (String.sub s !start (index - !start)) :: !list;
      start := index + 1
    done
  with Not_found -> list := (String.sub s !start ((String.length s) - !start)) :: !list
  in List.rev !list;;

let maybe_input_line stdin =
  try Some (input_line stdin) with
    End_of_file -> None;;

let input_lines stdin =
  let rec input lines =
    match maybe_input_line stdin with
      Some line -> input (line :: lines)
    | None -> List.rev lines
  in
  input [];;

let rec parse_list_line delim line =
  if (String.length line) > 0 then
    let parts = split_str delim line in
    parse_tokens parts
  else
    []

and parse_tokens tokens =
  let rec inner_parse_tokens buffer = function
      [] -> List.rev buffer
    | h :: t ->
        let parsed = parse_line h in
        inner_parse_tokens (parsed :: buffer) t
  in
  inner_parse_tokens [] tokens

and parse_line str =
  if (String.length str) > 1 then
    if str.[0] = '(' && str.[(String.length str) - 1] = ')' then
      let substr = String.sub str 1 ((String.length str) - 2) in
      split_str ',' substr
    else
      str :: []
  else
    str :: []

and parse_lines lines =
  let rec inner_parse chunks = function
      [] -> List.rev chunks
    | head :: rest ->
        let parsed = parse_list_line ';' head in
        inner_parse (parsed :: chunks) rest
  in
  inner_parse [] lines;;

let file_channel = open_in("read_file2");;
let all_lines = input_lines file_channel;;
let chunks = parse_lines all_lines;;
let () = close_in file_channel;;

和输出

# val file_channel : in_channel = <abstr>
# val all_lines : string list = ["q0;q1"; "a;b"; "(q0,x);(q1,x)"]
# val chunks : string list list list =
  [[["q0"]; ["q1"]]; [["a"]; ["b"]]; [["q0"; "x"]; ["q1"; "x"]]]

请注意,在最后的输出中,我们必须使用单个字符串项的列表,以便从 ocaml 函数返回相同的类型。如果需要,您可以编写类似于 matlab squeeze 函数的内容来更改 [["q0"]; [“q1”]][“q0”; “q1”]

关于ocaml - 如何在ocaml中读取文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11095770/

相关文章:

匹配中的 OCaml 类型错误

curl - js_of_ocaml : missing primitive when calling ocurl and str

parsing - 在Menhir/Ocamlyacc中为运算符(operator)指定动态优先级和优先级

merge - 自定义目录/文件夹合并工具

recursion - 计算列表中元素的出现次数 - OCaml

erlang - 为什么 OCaml 的模式匹配比 Erlang 的弱?

parsing - 使用 ocamllex/ocamlyacc 解析部分语法

ocaml - 如何在 OCaml 中定义 int64?

c - 是否可以在没有包装类型的情况下从 OCaml 调用 C 函数?

ocaml - 唱片公司必须是全局唯一的吗?