format

Common Lisp中,format相当复杂,它的功能不只是输出。format有4个输出的目的地:

~%,控制换行:

CL-USER> (format t "hello~%world")
hello
world
NIL

控制小数位数:

CL-USER> pi
3.141592653589793d0
CL-USER> (format nil "~$" pi)	; 默认是小数后两位
"3.14"
CL-USER> (format nil "~3$" pi)	; 前置参数(prefix parameter)控制打印浮点数的位数
"3.142"

~v,可以从参数列表中取值来做前置参数的值:

CL-USER> (format t "~v$" 3 pi) ; ~v从参数列表中取“3”作为前置参数
3.142

~#,字符串参数之后的剩余参数个数将作为~#的取值:

CL-USER> (format t "~#$" pi nil nil)
3.142

~:,让~D输出的十进制数字以逗号分割:

CL-USER> (format t "~:d" 1000)
1,000

~S和~A可将NIL输出成():

CL-USER> (format t "~:a" nil)
()
NIL
CL-USER> (format t "~:S" nil)
()

~c可将不可打印的字符按名字输出:

CL-USER> (format t "~:C" #\Tab)
Tab

~@,给数字加上正负号:

CL-USER> (format t "~@d" -1000)
-1000

还可以和~:结合:

CL-USER> (format t "~:@d" -1000)
-1,000

和~c可将字符按字面字符打印出来:

CL-USER> (format t "~@C" #\a)
#\a

~&、~%,都是产生新的行,和~%不同的是,~&只有在没有位于一行开始处才换行。

~d,打印数字,支持前缀参数,第一个参数为输出的最小宽度:

CL-USER> (format nil "~10d" 100)
"       100"

第二个参数指出数字之前的占位符号(默认是空格):

CL-USER> (format nil "~10,'0d" 100)
"0000000100"

第三个参数配合冒号,可以指定分割符:

CL-USER> (format nil "~,,'.:d" 1000)
"1.000"

第四个参数指定多少位才分割符:

CL-USER> (format nil "~,,'|,1:d" 1000)		; 每一位就分割,其他都好都是做占位

~x, ~o, ~b,分别指十六进制、八进制和二进制,和~d一样的使用方法

~r,控制2~36之间的进制,如二进制:

CL-USER> (format nil "~2r" 10)
"1010"

~r有趣的地方在于:不给参数可以打印数字的英文单词:

CL-USER> (format nil "~r" 1)
"one"
CL-USER> (format nil "~r" 100)
"one hundred"
CL-USER> (format nil "~r" 1000)
"one thousand"

如果加~:,可以让它成为序数:

CL-USER> (format nil "~:r" 1000)
"one thousandth"

加~@可以让它成为罗马字符:

CL-USER> (format nil "~@r" 1)
"I"

配合~:可以让它产生旧式的罗马字符:

"MCCXXXIIII"
CL-USER> (format nil "~@r" 1234)
"MCCXXXIV"

~p,如果参数不是1,将打印个字符“s“,用来解决复数问题:

CL-USER> (format nil "~p" 0)
"s"
CL-USER> (format nil "~p" 1)
""

~(,控制大小写:

CL-USER> (format nil "~(~A~)" "HELLO WORLD")	; 全部转成小写
"hello world"

配合~@,让首字符大写:

CL-USER> (format nil "~@(~A~)" "HELLO WORLD")
"Hello world"

配合~:,让单词首字母大写:

CL-USER> (format nil "~:(~A~)" "HELLO WORLD")
"Hello World"

~:结合~@,让所有字母大写:

CL-USER> (format nil "~:@(~A~)" "hello world")
"HELLO WORLD"

~[~],按数值索引取内容:

CL-USER> (format t "~[1~;2~;~]" 0)
1
NIL
CL-USER> (format t "~[1~;2~;~]" 1)
2

和~:配合在一起,True和False的条件选择:

CL-USER> (format t "~:[F~;T~]" 1)
T
NIL
CL-USER> (format t "~:[F~;T~]" nil)
F

和~@配合在一起,可以只支持一条子句:

CL-USER> (format t "~@[x=~a~]~@[y=~a~]" nil nil)
NIL
CL-USER> (format t "~@[x=~a~]~@[y=~a~]" nil 1)
y=1
NIL
CL-USER> (format t "~@[x=~a~]~@[y=~a~]" 1 2)
x=1y=2

{},迭代,需要接受一个列表:

CL-USER> (format t "~{~a~%~}" (list 1 2 3 4))
1
2
3
4
NIL
CL-USER> (format t "~{~a: ~a~%~}" (list 1 2 3 4))
1: 2
3: 4

这样看起来很讨厌,必须得让它在列表没元素的时候停止打印逗号:

CL-USER> (format t "~{~a,~}" (list 1 2 3 4 5))
1,2,3,4,5,

使用~^:

CL-USER> (format t "~{~a~^,~}" (list 1 2 3 4 5))
1,2,3,4,5

配合~@,可以把参数当作列表处理:

CL-USER> (format t "~@{~a~^,~}" 1 2 3 4 5)
1,2,3,4,5