printfの自作
Posted feedbacks - Common Lisp
マクロ、クロージャ、高階関数を使って。わりと Lisp らしく書けたかも?
d,x,o,f,c,s,% に対応。フラグなどは実装してないし手抜き感はありますが。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | (defconstant *format-char-table* (make-hash-table))
(defmacro define-format-char (char lambda-list &body body)
`(setf (gethash ,char *format-char-table*)
(lambda ,lambda-list ,@body)))
(defun process-format-char (char args stream)
(let ((fn (gethash char *format-char-table*)))
(if fn (funcall fn args stream)
(error "Undefined format character: ~C" char))))
(defun sprintf (fmt &rest args)
(let ((rest args))
(flet ((getarg (&optional n) (if n (nth n args) (pop rest))))
(with-output-to-string (out)
(with-input-from-string (in fmt)
(do () ((null (peek-char nil in nil)))
(let ((c (read-char in)))
(if (char= c #\%)
(process-format-char (read-char in) #'getarg out)
(write-char c out)))))))))
(define-format-char #\f (fn stream) (write (funcall fn) :stream stream))
(define-format-char #\c (fn stream) (write-char (funcall fn) stream))
(define-format-char #\s (fn stream) (princ (funcall fn) stream))
(define-format-char #\% (fn stream) (write-char #\% stream))
(defun format-integer (n base stream)
(write n :base base :stream stream))
(defmacro define-integer-format-char (char base)
`(define-format-char ,char (fn stream)
(format-integer (funcall fn) ,base stream)))
(define-integer-format-char #\d 10)
(define-integer-format-char #\x 16)
(define-integer-format-char #\o 8)
;;; test
(sprintf (sprintf "%s/%%%c" "%x/%d/%o" #\f)
11259375 (* 9 3607 3803) 2054353 3.141592653589793d0)
;; => "ABCDEF/123456789/7654321/3.141592653589793d0"
|


yappy
#4119()
[
C
]
Rating-4/18=-0.22
Rating-4/18=-0.22-0+
[ reply ]