如何从ocaml中的文件中读取? [英] How to read from a file in 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屋!