【问题标题】:SML/NJ: Extracting a number's digits into an int listSML/NJ:将数字的数字提取到 int 列表中
【发布时间】:2016-08-30 09:24:08
【问题描述】:

输入:仅包含 1 行的文本文件,其中包含一个整数

输出:带数字位数的 int 列表

这是我的代码:

fun parse file =
  let
    val input = TextIO.openIn file

    fun read_digits (NONE,acc) = rev acc
      | read_digits (SOME e,acc) =
        let
          val c = Option.valOf (e)
          val str = Char.toString c
          val digit = Option.valOf (Int.fromString str)
        in
          read_digits (TextIO.input1 input,digit::acc)
        end
  in
    read_digits (TextIO.input1 input,nil: int list)
  end

这是我收到的错误消息:

test.sml:14.11-14.55 Error: operator and operand don't agree [tycon mismatch]
  operator domain: char option option * int list
  operand:         TextIO.elem option * int list
  in expression:
    read_digits (TextIO.input1 input,digit :: acc)
test.sml:17.5-17.52 Error: operator and operand don't agree [tycon mismatch]
  operator domain: char option option * int list
  operand:         TextIO.elem option * int list
  in expression:
    read_digits (TextIO.input1 input,nil: int list)

uncaught exception Error
  raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:292.17-292.20

关于如何处理这个问题有什么建议吗?

否则,有没有人有更好的办法将文本文件中的数字提取到 int 列表中?

【问题讨论】:

    标签: file parsing char integer ml


    【解决方案1】:

    这里的第一个问题是SOME e中的e已经是char,你不必用valOf“解包”它。

    第二个问题是,即使您删除了 valOf(并且您的程序将进行类型检查),尝试从文件中读取数字也会导致运行时错误,如下所示:

    $ cat digits.txt
    12345
    $ smlnj read_digits_from_file.sml
    ...
    - parse "digits.txt";
    
    uncaught exception Option
      raised at: Basis/Implementation/option.sml:17.25-17.31
    

    这是由于行尾字符造成的。要解决此问题,您可以执行以下操作:

    fun parse file =
      let
        val input = TextIO.openIn file
    
        fun read_digits (NONE, acc) = acc (* end of stream *)
          | read_digits (SOME ch, acc) =
            let
              val str = Char.toString ch
            in
              case (Int.fromString str) of
                  SOME digit => read_digits (TextIO.input1 input, digit::acc)
                | NONE => acc (* return on first non-digit *)
            end
      in
        rev (read_digits (TextIO.input1 input, []))  (* rev moved here *)
    

    一个简单的测试:

    - parse "digits.txt";
    val it = [1,2,3,4,5] : int list
    

    【讨论】:

    • 非常感谢! :D 另外,你是对的,我应该检查换行符。我没有这样做的唯一原因是因为我知道该文件只包含一行,因此读取 '\n' 字符没有任何风险。但安全总比后悔好。谢谢!
    • @Orion (1) 例如echo "12345" > digits.txt 将插入它(可以使用-n 选项来避免); (2) 在不再需要文件后,还应该关闭文件描述符
    • (1) 你说得对,我用编辑器创建了文件,在这种情况下没有添加任何不必要的'\n'。 (2) 注明。再次感谢! :)
    猜你喜欢
    • 2013-09-18
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 1970-01-01
    • 2012-03-12
    • 2018-03-19
    • 2021-03-23
    相关资源
    最近更新 更多