问题描述
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”函数的情况下执行此操作。那可能吗?编写此函数是一种明智的方法吗?
解决方法
我希望标题
"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
恒定查找,避免了列表递归。太好了。