如何从ocaml中的文件中读取? [英] How to read from a file in ocaml?

查看:43
本文介绍了如何从ocaml中的文件中读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an input file in following format :

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 函数用分隔符分割字符串并返回一个列表.

Basically split function splits the string with delimiter and returns a list.

因此,我能够正确生成列表 a 和 b.

So, I am able to generate list a and b properly.

但是在列表 c 的情况下,我得到一个类型字符串列表.其实我想要一个类型为 ('string*'string) 的列表.

But in case of List c, I get a type string list. Actually I want a list with type ('string*'string).

我该怎么做?

推荐答案

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

File contents (notice comma-separations inside brackets)

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"]

Please, notice, that in last output we have to use lists for single string items in order to return same type from ocaml functions. If you want, you can write something similar to matlab squeeze function to change [["q0"]; ["q1"]] to ["q0"; "q1"]

这篇关于如何从ocaml中的文件中读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆