2012-06-19 34 views
1

J'ai un fichier d'entrée au format suivant:Comment lire un fichier dans ocaml?

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

Je veux avoir trois listes comme suit:

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

Voici mon code:

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;; 

divise fonction Fondamentalement divisé la chaîne avec délimiteur et renvoie une liste. Donc, je suis capable de générer correctement les listes a et b.

Mais dans le cas de la liste c, j'obtiens une liste de chaînes de caractères. En fait je veux une liste avec type (chaîne 'string *').

Comment faire cela?

+1

Fonctions de base IO sont dans le [Pervasives] (http://caml.inria.fr/pub/docs/manual-ocaml /libref/Pervasives.html) module. Vous pouvez lire une ligne avec 'read_line', par exemple. Vous devrez montrer ce que vous avez déjà essayé d'obtenir de meilleurs conseils, je pense. –

Répondre

2

Contenu du fichier (séparations par des virgules préavis à l'intérieur entre parenthèses)

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

code 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;; 

et la sortie

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

S'il vous plaît, avis, qu'en dernière sortie nous avons utiliser des listes pour les éléments de chaîne unique afin de retourner le même type à partir des fonctions ocaml. Si vous voulez, vous pouvez écrire quelque chose de similaire à matlab pression fonction pour changer [["q0"]; ["q1"]] à ["q0"; "q1"]

+0

'(q0, x); (q1; x)' - vous avez tapé une fois ',' et autre fois ';' comme délimiteur dans votre exemple d'entrée entre parenthèses – Ribtoks

+0

@ user1280282 J'ai mis à jour une réponse – Ribtoks