有没有办法只显示一次?

时间:2020-11-02 22:06:41

标签: recursion iteration sml converters radix

我编写了此sml函数,使我可以显示Ascii表的前5列。

fun radix (n, base) =
    let
        val b = size base
        val digit = fn n => str (String.sub (base, n))
        val radix' =
            fn (true, n) => digit n
            | (false, n) => radix (n div b, base) ^ digit (n mod b)
    in
        radix' (n < b, n)
    end;

val n = 255;
val charList = List.tabulate(n+1, 
  fn x => print(
      "DEC"^"\t"^"OCT"^"\t"^"HEX"^"\t"^"BIN"^"\t"^"Symbol"^"\n"^
      Int.toString(x)^"\t"^
      radix (x, "01234567")^"\t"^
      radix (x, "0123456789abcdef")^"\t"^
      radix (x, "01")^"\t"^
      Char.toCString(chr(x))^"\t"
  )
);

但是我希望标题"DEC"^"\t"^"OCT"^"\t"^"HEX"^"\t"^"BIN"^"\t"^"Symbol"仅在开始时显示一次,但是我不能这样做。有人知道这样做的方法吗?

另一方面,我想在不重新调用“ radix”函数的情况下执行此操作。那可能吗?编写此函数是一种明智的方法吗?

1 个答案:

答案 0 :(得分:1)

我希望标题"DEC"...仅在开头显示一次

当前,标题显示多次,因为它是在print函数内部List.tabulate中使用的,对于表中的每个数字一次。因此,您可以将打印标题移出此函数,然后移入父函数。

为清楚起见,我还可以将单个字符的打印移到单独的功能中。 (我认为您已经很好地缩进了charList中的代码,但是如果一个函数执行的功能不只一项,那么它的作用就太多了。)

例如

fun printChar (i : int) =
    print (Int.toString i ^ ...)

fun printTable () =
    ( print "DEC\tOCT\tHEX\tBIN\tSymbol\n"
    ; List.tabulate (256, printChar)
    ; ()  (* why this? *)
    )

您发现Char.toCString非常酷,与仅打印任何字符相比,它是安全的。它似乎为例如\t\n,但几乎没有所有功能。因此,如果您真的想为桌子增添趣味,可以添加一个辅助函数,

fun prettyName character =
    if Char.isPrint character
    then ...
    else case ord character of
         0 => "NUL (null)"
       | 1 => "SOH (start of heading)"
       | 2 => "STX (start of text)"
       | ...

并使用它代替Char.toCString

仅打印字符本身还是对其进行某些描述可能取决于Char.isPrint

我希望在没有递归调用“基数”函数的情况下这样做。

有可能吗?

编写此函数是否明智?

无论哪种方式,您都需要与radix函数等效的东西。

当然可以。您可以稍微缩短一点,但是一般的方法是好的。

通过进行String.sub恒定查找,避免了列表递归。太好了。

相关问题