【问题标题】:Read a file line per line and store every line read in a single list每行读取一个文件行并将读取的每一行存储在一个列表中
【发布时间】:2017-03-19 23:50:25
【问题描述】:

我是一名学生,我接受了一项我已经苦苦挣扎了大约一个月左右的练习。 我正在尝试在 Ocaml 中编写一个函数。该函数必须读取每行一个单词的文本文件,并且必须将所有单词存储在一个列表中。 但问题是这个程序必须是一个递归程序(这意味着没有循环,没有“while”)。

到目前为止,我所能做的就是创建一个读取文本文件的函数(很像 BASH 命令“cat”)

let dico filename =
  let f = open_in filename in
  let rec dico_rec () =
    try
      print_string (input_line f);
      print_newline ();
      dico_rec();
    with End_of_file -> close_in f
  in dico_rec() ;;

我只是不知道该怎么做。 Ocaml 几乎不是我最喜欢的语言。

【问题讨论】:

    标签: ocaml


    【解决方案1】:

    这是build_list 的另一种定义,它是尾递归的。如果您的输入可以有很多行,您可以使用它来代替 @MitchellGouzenko 的定义。

    let rec build_list l =
        match input_line ic with
        | line -> build_list (line :: l)
        | exception End_of_file -> close_in ic; List.rev l
    

    【讨论】:

    • 这个函数有什么作用?
    • 实际上我使用的文件大约有 500-600 行长,所以我认为在某些时候不会出现堆栈溢出
    • 这是我找到的最佳答案。我不明白为什么我在互联网搜索中找到的所有其他答案都以这些复杂的方式使用 try-with,而一个简单的匹配效果如此之好。
    【解决方案2】:
    open Printf
    
    let file = "example.dat"
    
    let () =
         let ic = open_in file in
         let rec build_list infile =
              try
                   let line = input_line infile in
                   line :: build_list(infile)
              with End_of_file ->
                   close_in infile;
                   [] in
         let rec print_list = function
              [] -> ()
              | e::l -> print_string e ; print_string " " ; print_list l in
         print_list(build_list(ic))
    

    编辑:我之前提出的算法过于复杂。试着理解这一点。

    为了理解这个递归,我们假设 build_list 工作正常。也就是说,假设 build_list 正确地将打开的文件作为参数并返回文件中的行列表。

    现在,让我们看看函数的主体。它从文件中读取一行并再次调用 build_list。如果文件中有 N 行,再次调用 build_list 应该会返回文件中剩余 N-1 行的列表(因为我们自己只是读取了第一行)。我们将刚刚读取的行追加到从 build_list 返回的列表中,并返回包含所有 N 行的结果列表。

    递归一直持续到达到基本情况为止。基本情况是存在 End_of_file 时。在这种情况下,我们返回一个空列表。

    【讨论】:

    • 这适用于小输入文件,但build_list 的这个定义不是尾递归的,并且会导致大输入的堆栈溢出。递归调用周围的try...with 可防止其成为尾调用。
    • 好电话...自从我使用 ocaml 以来已经有一段时间了 :) 你认为新的 build_list 更好,还是旧的更好(其中涉及传递一个空列表作为参数)?当然假设我修复了try...with 位。
    • 我不好意思向 OP 承认这一点,他显然不是 OCaml 的粉丝,但在编写 OCaml 代码时你必须学会​​识别尾调用。 try...with 是比较棘手的案例之一。
    • 有人可以向我解释一下“build_list”函数应该做什么吗?我不知道,但我尝试过编写它,但由于表达式“异常”而返回“语法错误”
    猜你喜欢
    • 1970-01-01
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 2012-10-25
    • 2014-08-03
    • 1970-01-01
    • 2013-05-15
    相关资源
    最近更新 更多