Lisp多次格式化一个字符

Pet*_*tko 10 lisp format common-lisp

我正在寻找一种使用格式多次输出字符的方法.这可能吗?有人可以填写_?_,以便该示例有效吗?

(let ((n 3))
  (format nil "_?_" _?_ #\* _?_ ))
Run Code Online (Sandbox Code Playgroud)

应该回来

=> "***"
Run Code Online (Sandbox Code Playgroud)

Lar*_*off 7

很高兴看到这么多解决方案:~A,〜<和〜{到目前为止.

〜@ {迭代结构提供了一个简洁的解决方案:

(format nil "~v@{~A~:*~}" 3 #\*)
Run Code Online (Sandbox Code Playgroud)


小智 5

(format nil "~a~:*~a~:*~a~:*" #\*)
"***"
Run Code Online (Sandbox Code Playgroud)

或者详细说明约书亚泰勒的回答:

(format nil "~v{~a~:*~}" 3 '(#\*))
Run Code Online (Sandbox Code Playgroud)

将是这样做的一种方式。不要被format指令中的星号混淆,它们是控制字符,而不是打印的字符。


然而,就效率而言,这是:

(make-string 3 :initial-element #\*)
Run Code Online (Sandbox Code Playgroud)

将是实现相同效果的首选方式。


Jos*_*lor 5

如果你使用该~A指令,你可以完全按照你建议的形式得到它,即

(let ((n 3))
  (format nil "_?_" _?_ #\* _?_ ))
Run Code Online (Sandbox Code Playgroud)

有三种格式参数.但是,如果您使用~<,您实际上只需使用两个格式参数即可.如果你不需要在已经生成的其他字符串中包含这个字符串format,你也可以使用该字符串make-string.

使用Tilde A(~A)

您可以打印字符并指定最小宽度和与填充字符相同的字符.例如,使用~v,,,vA和两个参数,您可以确保打印一定数量的字符,以及填充字符是什么.

CL-USER> (let ((n 3))
           (format nil "~v,,,vA"
                   n     ; number of characters that must be printed
                   #\*   ; character to use as padding
                   #\*)) ; character to print with ~A
"***"

CL-USER> (let ((n 3))
           (format nil "~v,,,vA" n #\* #\*)) 
"***"

CL-USER> (let ((n 10))
           (format nil "~v,,,vA" n #\* #\*))
"**********"
Run Code Online (Sandbox Code Playgroud)

这使用完整形式~A:

~mincol,colinc,minpad,padcharA是〜A的完整形式,它允许控制填充.字符串填充在右侧(如果使用@修饰符,则在左侧)至少填充padchar的minpad副本; 然后,填充字符一次插入colinc字符,直到总宽度至少为mincol.mincol和minpad的默认值为0,colinc的默认值为1,padchar的默认值为空格字符.

以及v:

代替指令的前缀参数,可以使用V(或v).在这种情况下,format将args中的参数作为指令的参数.参数应该是整数或字符.如果V参数使用的arg为nil,则效果就好像省略了参数一样.#可用于代替前缀参数; 它表示剩余要处理的args数.在递归格式中使用时,在〜?的上下文中?或〜{,#prefix参数表示递归调用中剩余的格式参数的数量.

使用Tilde小于(〜<)

还有一个不太常用的格式指令,波浪号小于,用于证​​明.它需要一个格式字符串并生成s

〜mincol,colinc,minpad,padchar <STR〜>

这证明了通过在至少mincol列宽的字段内处理str而产生的文本.str可以用〜;分成段,在这种情况下,间隔在文本段之间均匀分配.

我们可以(ab)通过传递一个空格式字符串并只指定宽度和填充字符来使用它:

CL-USER> (let ((n 3))
           (format nil "~v,,,v<~>"
                   n     ; width
                   #\*)) ; padding character
"***"

CL-USER> (let ((n 5))
           (format nil "~v,,,v<~>" n #\*))
"*****"
Run Code Online (Sandbox Code Playgroud)

只要做一个字符串

当然,除非你需要你已经格式化的其他字符串中使用这个特殊字符串,否则你应该按照wvxvw的建议做,并且只需使用make-string:

(make-string 3 :initial-element #\*)
Run Code Online (Sandbox Code Playgroud)

其他选择

format非常灵活,正如这个和其他答案所指出的那样,有很多方法可以做到这一点.我试图坚持那些应该在一次通过中做到这一点并且不进行显式迭代的那些,但这也可以通过format迭代来完成,正如Lars Brinkhoffwvxvw所指出的那样.


Rai*_*wig 5

就像 Lars 的回答一样,但我们写了字符 wih ~C,而不是使用带有~A以下内容的打印机:

(format nil "~v@{~C~:*~}" 3 #\*)
Run Code Online (Sandbox Code Playgroud)

用类似的东西写一个字符write-char是比打印 Lisp 对象更简单的操作。打印机有很多上下文需要观察,并且必须找到打印对象的正确方法。OTOH,类似于WRITE-CHAR将单个字符写入流。