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

Index

Feed

Other

Link

Pathtraq

loading...