challenge printfの自作

printf関数を自作してください。
printfの説明は不要だと思います。とりあえずWikiPediaのリンクをはっておきます。

実際にはsprintf関数を作ってください。
注意事項
  • 標準でついているprintf系関数の使用禁止
  • 標準でついているライブラリ以外の使用禁止
  • 引数・返り値等の仕様はできるだけ似せればよい

可変長引数など、言語によっては難しい/不可能な仕様もありますが、いろいろ工夫して本物に近づくようにしてみてください。
1
2
3
4
5
6
7
#include <string.h>

// なにもフォーマットしてない
int mysprintf(char *str, const char *format, ... ){
    strcpy(str, format);
    return strlen(str);
}

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 "|%%|")
"|%|"
 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

Index

Feed

Other

Link

Pathtraq

loading...