printfの自作
Posted feedbacks - Scheme
場合わけが多くなるのでなかなかきれいにまとまりませんが、仕事ではこういうベタな仕様をえいやっと書くことも多い気がするので、書いとけば参考になるかなと。
さぼったところ:
- 浮動小数点数はeEfFgGを区別せず。いい加減です。
- 変換指定子 aApnはサポートせず。
- 長さ修飾子はSchemeはサポートせず(Schemeでは意味がないかな)
- n$による引数の並べかえはサポートせず。
後はそれなりにサポートしているつもりです。
gosh> (sprintf "|%d|" 123)
"|123|"
gosh> (sprintf "|%10d|" 123)
"| 123|"
gosh> (sprintf "|%-10d|" 123)
"|123 |"
gosh> (sprintf "|%10.5d|" 123)
"| 00123|"
gosh> (sprintf "|%+10.5d|" 123)
"| +00123|"
gosh> (sprintf "|%+10d|" 123)
"| +123|"
gosh> (sprintf "|%+10o|" 123)
"| +173|"
gosh> (sprintf "|%10o|" 123)
"| 173|"
gosh> (sprintf "|%#10o|" 123)
"| 0173|"
gosh> (sprintf "|%10x|" 123)
"| 7b|"
gosh> (sprintf "|%10X|" 123)
"| 7B|"
gosh> (sprintf "|%#10x|" 123)
"| 0x7b|"
gosh> (sprintf "|%f|" 3.14)
"|3.14|"
gosh> (sprintf "|%.6f|" (sqrt 2))
"|1.414214|"
gosh> (sprintf "|%10.6f|" (sqrt 2))
"| 1.414214|"
gosh> (sprintf "|%10.6f|" (- (sqrt 2)))
"| -1.414214|"
gosh> (sprintf "|%*.*f|" 10 6 (log 10))
"| 2.302585|"
gosh> (sprintf "|%f|" 10e100)
"|1.0e101|"
gosh> (sprintf "|%f|" 1e100)
"|1.0e100|"
gosh> (sprintf "|%.6f|" 1e100)
"|1.000000e100|"
gosh> (sprintf "|%s|" "abc")
"|abc|"
gosh> (sprintf "|%10s|" "abc")
"| abc|"
gosh> (sprintf "|%-10s|" "abc")
"|abc |"
gosh> (sprintf "|%*s|" 10 "abc")
"| abc|"
gosh> (sprintf "|%c|" #\z)
"|z|"
gosh> (sprintf "|%%|")
"|%|"
さぼったところ:
- 浮動小数点数はeEfFgGを区別せず。いい加減です。
- 変換指定子 aApnはサポートせず。
- 長さ修飾子はSchemeはサポートせず(Schemeでは意味がないかな)
- n$による引数の並べかえはサポートせず。
後はそれなりにサポートしているつもりです。
gosh> (sprintf "|%d|" 123)
"|123|"
gosh> (sprintf "|%10d|" 123)
"| 123|"
gosh> (sprintf "|%-10d|" 123)
"|123 |"
gosh> (sprintf "|%10.5d|" 123)
"| 00123|"
gosh> (sprintf "|%+10.5d|" 123)
"| +00123|"
gosh> (sprintf "|%+10d|" 123)
"| +123|"
gosh> (sprintf "|%+10o|" 123)
"| +173|"
gosh> (sprintf "|%10o|" 123)
"| 173|"
gosh> (sprintf "|%#10o|" 123)
"| 0173|"
gosh> (sprintf "|%10x|" 123)
"| 7b|"
gosh> (sprintf "|%10X|" 123)
"| 7B|"
gosh> (sprintf "|%#10x|" 123)
"| 0x7b|"
gosh> (sprintf "|%f|" 3.14)
"|3.14|"
gosh> (sprintf "|%.6f|" (sqrt 2))
"|1.414214|"
gosh> (sprintf "|%10.6f|" (sqrt 2))
"| 1.414214|"
gosh> (sprintf "|%10.6f|" (- (sqrt 2)))
"| -1.414214|"
gosh> (sprintf "|%*.*f|" 10 6 (log 10))
"| 2.302585|"
gosh> (sprintf "|%f|" 10e100)
"|1.0e101|"
gosh> (sprintf "|%f|" 1e100)
"|1.0e100|"
gosh> (sprintf "|%.6f|" 1e100)
"|1.000000e100|"
gosh> (sprintf "|%s|" "abc")
"|abc|"
gosh> (sprintf "|%10s|" "abc")
"| abc|"
gosh> (sprintf "|%-10s|" "abc")
"|abc |"
gosh> (sprintf "|%*s|" 10 "abc")
"| abc|"
gosh> (sprintf "|%c|" #\z)
"|z|"
gosh> (sprintf "|%%|")
"|%|"
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | (use gauche.sequence)
(use util.match)
(use text.tree)
(use srfi-1)
(define (sprintf fmt . args)
(define (get-var-arg name v args)
(if v
(cond [(string->number v) => (cut values <> args)]
[(equal? v "*") (values (car args) (cdr args))]
[else (error #`",name needs to be a number or '*', but got:" v)])
(values #f args)))
(define (pick-arg conv args)
(if (equal? conv "%") (values #f args) (car+cdr args)))
(define (rec fmt args)
(rxmatch-case fmt
[#/(.*)%([-+ #0]*)(\d+|\*)?(?:\.(\d*|\*))?([diouxXeEfFgGaAcspn%])(.*)/
(_ before flags width prec conv after)
(receive (width args) (get-var-arg 'width width args)
(receive (prec args) (get-var-arg 'prec prec args)
(receive (arg args) (pick-arg conv args)
`(,before
,(fill width flags (dispatch arg prec flags conv))
,(rec after args)))))]
[else fmt]))
(define (dispatch arg prec flags conv)
(case (ref conv 0)
[(#\d #\i #\u) (int arg prec flags 10 conv)]
[(#\o) (int arg prec flags 8 conv)]
[(#\x #\X) (int arg prec flags 16 conv)]
[(#\e #\E #\f #\F #\g #\G) (real arg prec flags conv)]
[(#\c) (if (char? arg)
(string arg)
(error "char required for %c conversion:" arg))]
[(#\s) (if (string? arg)
(if (and prec (< prec (string-length arg)))
(string-take arg prec)
arg)
(error "string required for %s conversion:" arg))]
[(#\%) "%"]
[else (error "unsupported conversion:" conv)]))
(define (fill w f s)
(or (and-let* ([ w ]
[len (string-length s)]
[(< len w)]
[pad (- w len)])
(if (string-index f #\-)
(cons s (make-string pad #\space))
(cons (make-string pad (if (string-index f #\0) #\0 #\space)) s)))
s))
(define (sign arg f s)
(define (pos-sign)
(cond [(string-index f #\+) "+"]
[(string-index f #\space) " "]
[else ""]))
(string-append (if (negative? arg) "-" (pos-sign)) s))
(define (minpad p s)
(if (and p (< (string-length s) p))
(string-append (make-string (- p (string-length s)) #\0) s)
s))
(define (prefix f c s)
(if (string-index f #\#)
(case (ref c 0)
[(#\o) (string-append "0" s)]
[(#\x) (string-append "0x" s)]
[(#\X) (string-append "0X" s)])
s))
(define (int arg p f r c)
(unless (and (exact? arg) (integer? arg))
(error "exact integer required for conversion:" c))
(sign arg f (prefix f c (minpad p (number->string (abs arg) r (equal? c "X"))))))
(define (maxprec p s)
(cond [(not p) s]
[else
(regexp-replace*
s #/\.(\d+)/
(lambda (m)
(cond [(zero? p) ""]
[else
(let1 oprec (string-length (m 1))
(cond [(< p oprec)
#`".,(round->exact (/. (string->number (m 1)) (expt 10 (- oprec p))))"]
[else
#`".,(m 1),(make-string (- p oprec) #\\0)"]))
])))
]))
(define (real arg p f c)
(unless (real? arg)
(error "real number required for conversion:" c))
(maxprec p (number->string arg)))
(tree->string (rec fmt args)))
|
前に作ったやつがあるので恥ずかしながら投げてみます。 shiroさんがきっと書いてくれると思ったのでshiroさんの投稿を待った事をここに告白します。 ライブラリにntというディレクトリを作ってその下に置き、 (use nt.printf) して使います。 Gauche 0.8.12で動きます。0.8.11以前では正規表現にmatchしなかった場合に#fではなく""が返るので一部修正が必要です。 なお、104行目の (d o x X) のところを (d b o x X) にすると、%bで2進表記をするオレオレ拡張が入ります。 テストコードも以下に付けておきます。 ;;; nt/test/printf.scm (use gauche.test) (test-start "nt.printf") (use nt.printf) (test-module 'nt.printf) (test-section "escaped symbols") (test* "\\t" "\t" (sprintf "\t")) (test* "\\n" "\n" (sprintf "\n")) (test* "\\\"" "\"" (sprintf "\"")) (test* "\\\\" "\\" (sprintf "\\")) (test* "%%" "%" (sprintf "%%")) (test-section "%d") (test* "%d 1" "1" (sprintf "%d" 1)) (test* "%3d 1" " 1" (sprintf "%3d" 1)) (test* "%3d 1111" "1111" (sprintf "%3d" 1111)) (test* "%03d 1" "001" (sprintf "%03d" 1)) (test* "%-3d" "1 " (sprintf "%-3d" 1)) (test* "%+d 1" "+1" (sprintf "%+d" 1)) (test* "%+3d 1" " +1" (sprintf "%+3d" 1)) (test* "%d zero" "0" (sprintf "%d" 0)) (test* "%d minusvalue" "-1" (sprintf "%d" -1)) (test* "%3d minusvalue" " -1" (sprintf "%3d" -1)) ;(test* "%03d minusvalue" "-01" (sprintf "%03d" -1)) (test* "%-d minusvalue" "-1" (sprintf "%-d" -1)) (test* "%+d minusvalue" "-1" (sprintf "%+d" -1)) (test* "%+3d minusvalue" " -1" (sprintf "%+3d" -1)) (test-section "%d with non-integer values") (test* "%d float 2.71828" "2" (sprintf "%d" 2.71828)) (test* "%d rational 3/2" "1" (sprintf "%d" 3/2)) (test* "%d string \"123\"" "123" (sprintf "%d" "123")) (test* "%d string \"abc\"" "0" (sprintf "%d" "abc")) (test* "%d symbol '1" "1" (sprintf "%d" '1)) (test* "%d symbol 'a" "0" (sprintf "%d" 'a)) (test-section "%i %u") (test* "%i" "999" (sprintf "%i" 999)) (test* "%u" "999" (sprintf "%u" 999)) (test-section "%x %X") (test* "%x 15" "f" (sprintf "%x" 15)) (test* "%3x 15" " f" (sprintf "%3x" 15)) (test* "%03x 15" "00f" (sprintf "%03x" 15)) (test* "%03x 65535" "ffff" (sprintf "%03x" 65535)) ;(test* "%-3x 15" "f " (sprintf "%-3x" 15)) (test* "%X 15" "F" (sprintf "%X" 15)) (test* "%3X 15" " F" (sprintf "%3X" 15)) (test* "%03X 15" "00F" (sprintf "%03X" 15)) (test* "%03X 65535" "FFFF" (sprintf "%03X" 65535)) ;(test* "%-3x 15" "f " (sprintf "%-3x" 15)) (test-section "%o") (test* "%o 9" "11" (sprintf "%o" 9)) (test* "%3o 9" " 11" (sprintf "%3o" 9)) (test* "%03o 9" "011" (sprintf "%03o" 9)) (test* "%3o 255" "377" (sprintf "%3o" 255)) (test* "%3o 511" "777" (sprintf "%3o" 511)) (test* "%3o 585" "1111" (sprintf "%3o" 585)) ;(test* "%-3o" "11 " (sprintf "%-3o" 9)) ;(test-section "%b") ; original feature ;(test* "%b 2" "10" (sprintf "%b" 2)) ;(test* "%3b 2" " 10" (sprintf "%3b" 2)) ;(test* "%03b 2" "010" (sprintf "%03b" 2)) ;(test* "%3b 15" "1111" (sprintf "%3b" 15)) ;;(test* "%-3b 2" "10 " (sprintf "%-3b" 3)) (test-section "%c") (test* "%c 9" "\t" (sprintf "%c" 9)) (test* "%c 13" "\r" (sprintf "%c" 13)) (test* "%c 32" " " (sprintf "%c" #x20)) ; 32 (test* "%c 55" "7" (sprintf "%c" #x37)) ; 55 (test* "%c 69" "E" (sprintf "%c" #x45)) ; 69 (test* "%c 12354" "あ" (sprintf "%c" #x3042)) ; = 12354 (test* "%c \"abc\"" "a" (sprintf "%c" "a")) (test* "%c \"いろは\"" "い" (sprintf "%c" "いろは")) (test-section "%s") (test* "%s" "\n" (sprintf "%s" "\n")) (test* "%s" "a" (sprintf "%s" "a")) (test* "%3s" " " (sprintf "%3s" "")) (test* "%3s" " a" (sprintf "%3s" "a")) (test* "%3s" " aa" (sprintf "%3s" "aa")) (test* "%3s" "aaa" (sprintf "%3s" "aaa")) (test* "%3s" "aaaa" (sprintf "%3s" "aaaa")) (test* "%-3s" " " (sprintf "%-3s" "")) (test* "%-3s" "a " (sprintf "%-3s" "a")) (test* "%-3s" "aa " (sprintf "%-3s" "aa")) (test* "%-3s" "aaa" (sprintf "%-3s" "aaa")) (test* "%-3s" "aaaa" (sprintf "%-3s" "aaaa")) (test-section "%s with non-string values") (test* "%s integer 5" "5" (sprintf "%s" 5)) (test* "%s float 3.14" "3.14" (sprintf "%s" 3.14)) (test* "%s rational 3/2" "3/2" (sprintf "%s" 3/2)) (test* "%s symbol 'abc" "abc" (sprintf "%s" 'abc)) (test* "%s list (1 2 3)" "(1 2 3)" (sprintf "%s" '(1 2 3))) (test* "%s empty list ()" "()" (sprintf "%s" '())) (test* "%s dotted list (1 . 2)" "(1 . 2)" (sprintf "%s" '(1 . 2))) (test* "%s #t" "#t" (sprintf "%s" #t)) (test* "%s #f" "#f" (sprintf "%s" #f)) (test-section "%f") (test* "%f" "3.140000" (sprintf "%f" 3.14)) (test* "%f" "3.141593" (sprintf "%f" 3.1415926)) (test* "%f" "-3.140000" (sprintf "%f" -3.14)) (test* "%f" "-3.141593" (sprintf "%f" -3.1415926)) (test* "%.0f" "3" (sprintf "%.0f" 3.14)) (test* "%.1f" "3.1" (sprintf "%.1f" 3.14)) (test* "%.2f" "3.14" (sprintf "%.2f" 3.14)) (test* "%.3f" "3.140" (sprintf "%.3f" 3.14)) (test* "%.4f" "3.1400" (sprintf "%.4f" 3.14)) (test* "%1.0f 3.14" "3" (sprintf "%1.0f" 3.14)) (test* "%1.1f 3.14" "3.1" (sprintf "%1.1f" 3.14)) (test* "%1.2f 3.14" "3.14" (sprintf "%1.2f" 3.14)) (test* "%1.0f 3.15" "3" (sprintf "%1.0f" 3.15)) (test* "%1.1f 3.15" "3.2" (sprintf "%1.1f" 3.15)) (test* "%1.2f 3.15" "3.15" (sprintf "%1.2f" 3.15)) (test* "%2.0f" " 3" (sprintf "%2.0f" 3.14)) (test* "%2.1f" "3.1" (sprintf "%2.1f" 3.14)) (test* "%2.2f" "3.14" (sprintf "%2.2f" 3.14)) (test* "%-2.0f" "3 " (sprintf "%-2.0f" 3.14)) (test* "%-2.1f" "3.1" (sprintf "%-2.1f" 3.14)) (test* "%-2.2f" "3.14" (sprintf "%-2.2f" 3.14)) (test* "%3.0f" " 3" (sprintf "%3.0f" 3.14)) (test* "%3.1f" "3.1" (sprintf "%3.1f" 3.14)) (test* "%3.2f" "3.14" (sprintf "%3.2f" 3.14)) (test* "%3.3f" "3.140" (sprintf "%3.3f" 3.14)) (test* "%-3.0f" "3 " (sprintf "%-3.0f" 3.14)) (test* "%-3.1f" "3.1" (sprintf "%-3.1f" 3.14)) (test* "%-3.2f" "3.14" (sprintf "%-3.2f" 3.14)) (test* "%-3.3f" "3.140" (sprintf "%-3.3f" 3.14)) (test* "%4.0f" " 3" (sprintf "%4.0f" 3.14)) (test* "%4.1f" " 3.1" (sprintf "%4.1f" 3.14)) (test* "%4.2f" "3.14" (sprintf "%4.2f" 3.14)) (test* "%4.3f" "3.140" (sprintf "%4.3f" 3.14)) (test* "%4.4f" "3.1400" (sprintf "%4.4f" 3.14)) (test* "%-4.0f" "3 " (sprintf "%-4.0f" 3.14)) (test* "%-4.1f" "3.1 " (sprintf "%-4.1f" 3.14)) (test* "%-4.2f" "3.14" (sprintf "%-4.2f" 3.14)) (test* "%-4.3f" "3.140" (sprintf "%-4.3f" 3.14)) (test* "%-4.4f" "3.1400" (sprintf "%-4.4f" 3.14)) (test* "%5.0f" " 3" (sprintf "%5.0f" 3.14)) (test* "%5.1f" " 3.1" (sprintf "%5.1f" 3.14)) (test* "%5.2f" " 3.14" (sprintf "%5.2f" 3.14)) (test* "%5.3f" "3.140" (sprintf "%5.3f" 3.14)) (test* "%5.4f" "3.1400" (sprintf "%5.4f" 3.14)) (test* "%5.5f" "3.14000" (sprintf "%5.5f" 3.14)) (test* "%-5.0f" "3 " (sprintf "%-5.0f" 3.14)) (test* "%-5.1f" "3.1 " (sprintf "%-5.1f" 3.14)) (test* "%-5.2f" "3.14 " (sprintf "%-5.2f" 3.14)) (test* "%-5.3f" "3.140" (sprintf "%-5.3f" 3.14)) (test* "%-5.4f" "3.1400" (sprintf "%-5.4f" 3.14)) (test* "%-5.5f" "3.14000" (sprintf "%-5.5f" 3.14)) (test-section "%e %E") (test* "%e 0.0000314" "3.140000e-05" (sprintf "%e" 0.0000314)) (test* "%e 0.000314" "3.140000e-04" (sprintf "%e" 0.000314)) (test* "%e 0.00314" "3.140000e-03" (sprintf "%e" 0.00314)) (test* "%e 0.0314" "3.140000e-02" (sprintf "%e" 0.0314)) (test* "%e 0.314" "3.140000e-01" (sprintf "%e" 0.314)) (test* "%e 3.14" "3.140000e+00" (sprintf "%e" 3.14)) (test* "%e 31.4" "3.140000e+01" (sprintf "%e" 31.4)) (test* "%e 314" "3.140000e+02" (sprintf "%e" 314)) (test* "%e 3140" "3.140000e+03" (sprintf "%e" 3140)) (test* "%e 31400" "3.140000e+04" (sprintf "%e" 31400)) (test* "%e 314000" "3.140000e+05" (sprintf "%e" 314000)) (test* "%.0e 31415926" "3e+07" (sprintf "%.0e" 31415926)) (test* "%.1e 31415926" "3.1e+07" (sprintf "%.1e" 31415926)) (test* "%.2e 31415926" "3.14e+07" (sprintf "%.2e" 31415926)) (test* "%.3e 31415926" "3.142e+07" (sprintf "%.3e" 31415926)) (test* "%.4e 31415926" "3.1416e+07" (sprintf "%.4e" 31415926)) (test* "%.5e 31415926" "3.14159e+07" (sprintf "%.5e" 31415926)) (test* "%E" "3.140000E+00" (sprintf "%E" 3.14)) (test-section "%g") (test* "%g" "3.14" (sprintf "%g" 3.14)) (test* "%g" "-3.14" (sprintf "%g" -3.14)) (test* "%g" "3.1415926" (sprintf "%g" 3.1415926)) (test-end)
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ;;; nt/printf.scm
(define-module nt.printf
(export
printf
sprintf
))
(select-module nt.printf)
(define (log10 x) (/ (log x) (log 10.0)))
(define (sprintf fmt . args)
(let ((out (open-output-string)))
(let loop ((fmt fmt) (args args))
(define (ret) (display fmt out) (get-output-string out))
(let ((match (#/%(?<flag>[-+# 0]*)(?<num>[1-9][0-9]*)?(\.(?<below>[0-9]+))?(?<type>[%diouxXfeEgGbcs])/ fmt)))
(if match
(let* ((flags (if (match 'flag) (string->list (match 'flag)) '()))
(num (match 'num)) ;str/指定がなければ#f. ※0.8.11までは#fではなく""が返る
(below (match 'below)) ;str/指定がなければ#f. ※0.8.11までは#fではなく""が返る
(type (string->symbol (match 'type)))
(consumes-an-arg? (not (eq? '% type)))
(flush-left? (memq #\- flags))
(signed? (memq #\+ flags))
(zero-pad? (memq #\0 flags))
)
(if (and consumes-an-arg? (null? args))
(ret) ;;; arguments-exhausted
(let ((arg (if consumes-an-arg? (car args) 'not-eaten)))
(define (format-int-value type)
(let ((%value (if (integer? arg) arg (x->integer (truncate (x->number arg))))))
(if flush-left?
(let ((%fmt (string-append "~" type)))
(format (string-append "~" (or num "") "a") (format %fmt %value)))
(let ((%fmt (string-append "~" (or num "") "," (if zero-pad? "'0" "")
(if signed? "@" "") type)))
(format %fmt %value)))))
(define (format-float-value); type)
(let* ((%value (if (real? arg) arg (x->number arg)))
(%e-offset (x->integer (floor (log10 (abs %value)))))
(%precision (case type
((f)
; (if (string=? "" below) 6 (x->integer below))) ; < 0.8.12
(if below (x->integer below) 6))
((e E)
(cond ((> %e-offset 0) ;;; sorry i'm using (set!)
(set! %value (/ %value (expt 10 %e-offset))))
((< %e-offset 0)
(set! %value (* %value (expt 10 (abs %e-offset)))))
(else #t))
; (if (string=? "" below) 6 (x->integer below))) ;< 0.8.12
(if below (x->integer below) 6))
; (else (if (string=? "" below) 12 (x->integer below))))) ;< 0.8.12
(else (if below (x->integer below) 12))))
)
(let* ((%int (x->integer (if (= 0 %precision)
(round %value)
(truncate %value))))
(%fract (abs (- %value %int)))
(%rounded (x->integer (round (+ (expt 0.1 (+ %precision 1))
(* (expt 10 %precision) %fract)))))
(%str (if (= 0 %precision)
(format "~d" %int)
(format (string-append "~d.~" (format "~d" %precision) ",'0d")
%int %rounded)))
(%f-fmt (string-append "~" (or num "") ;"," (if zero-pad? "'0" "")
(if flush-left? "" "@") "a"))
(%e-fmt (string-append %f-fmt
"~a" ; [eE]
(if (< %e-offset 0) "-" "+")
"~2,'0d"))
)
(case type
((f)
(format %f-fmt %str))
((g G)
(format %f-fmt (regexp-replace #/0+$/ %str "")))
((e E)
(format %e-fmt %str type (abs %e-offset))
)
))))
(display (match 'before) out)
;; warnings
; (case type
; ((d i)
; (when (not (integer? arg))
; (print "warning: %~a requires <integer>" type) ))
; ((b o u X x c)
; (when (not (and (integer? arg) (< 0 arg)))
; (print "warning: %~a requires <unsigned integer>" type) ))
; ((f e E g G)
; (when (not (real? arg))
; (print "warning: %~a requires <real>" type)))
;; ((b)) ; we use %b for unsigned binary
; ((s)
; (when (not (string? arg))
; (format "warning: %s requires <string>")))
; )
(display (case type
((d o x X) ;; %bを2進表記に使いたい場合は (d b o x X)
(format-int-value (match 'type)))
((i u) ; signed/unsigned decimal
(format-int-value "d"))
((f) ;float ; [-]ddd.ddd
(format-float-value))
((e E) ;'not-supported) ; [-]d.ddde+-dd
(format-float-value))
((g G) ; 'not-supported) ;
(format-float-value))
; ((b) 'not-supported) ; backslash-escape seq
((c) ; first-char
(cond ((integer? arg)
(string (integer->char arg)))
((string? arg)
(string-ref arg 0))
(else
(string (integer->char (truncate (x->number arg))))) ))
((s) ; 'str
(let1 %s-fmt (string-append "~"
(format "~a~a"
(or num "")
(if flush-left? "" "@")
)
"a")
(format %s-fmt arg)))
((%) "%")) out)
(loop (match 'after)
(if consumes-an-arg? (cdr args) args))
)))
(ret))))))
(define (printf fmt . args) (display (apply sprintf (cons fmt args))))
(provide "nt/printf")
;;EOF
|


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