saws #5265(2008/01/11 08:02 GMT) [ Ruby ] Rating2/2=1.00
Rubyのsprintfの仕様に従って実装しました. pフラグは仕様が不明瞭だったので実装しませんでした.
format系のメソッドは仕様不可ということで, 指数表示変換は自前で容易したのでバグが潜在している可能性が高いです.
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
#%[フラグ][最小フィールド幅][.精度][長さ修飾子]変換指定子 MATCH_STR = '%([\+\-\s#0\*]*)(\d*)((?:\.\d+)?)([hliztl]*)([\w%]*)' def mysprintf(*argv) def check_flag(str, flag, width, precision) str = str.to_s width = width.to_i pos = flag.include?('-') sign = (/\A([\-\+])\w+\z/ =~ str or flag.include?('+')) zero = flag.include?('0') w = (width.to_i > str.size ? width-str.size : 0) if sign s = (str.to_i.abs >= 0 ? '+' : '-') w = (w >= 1 ? w - 1 : 0) else s = '' end num = (/\.(\d+)/ =~ precision and $1.to_i <= w and $1.to_i > 0) ? $i.to_i+1 : 0 filler = (zero ? '0' : ' ')*(w-num) + '0'*num "#{pos ? '' : filler}#{s}#{str}#{pos ? filler : ''}" end def check_spec(str, spec, opt) def exp_expr(n) #有理数を指数表示に変換 i = 0 break if eval("10**#{n.abs > 1 ? '1' : '0'}*10**(i#{n.abs > 1 ? '+= 1) >' : '-= 1) <='}#{'-1*' if n < 0}n") while 1 "#{n.quo(10**(i+1))}e#{i+1}" end def e_flag(str) if str.include?('e') if str.include('.') str else "#{str.split('e')[0]}.e#{str.split('e')[1]}" end else exp_expr(str.to_f) end end def g_flag(str) str.to_f < 10e-3 ? e_flag(str) : str.to_f.to_s end if opt case spec when 'b': "0b#{str.to_i.to_s(2)}" when 'o': "0#{str.to_i.oct}" when 'x': "0x#{str.to_i.hex}" when 'X': "0x#{str.to_i.hex}".upcase when 'f': str.include('.') ? str : "#{str}." when 'F': (str.include('.') ? str : "#{str}.").upcase when 'e': e_flag(str) when 'E': e_flag(str).upcase when 'g': g_flag(str) when 'G': g_flag(str).upcase else end else case spec when 'd': str.to_i when 'i': str.to_i when 'u': (str.to_i < 0 ? 2**32 + str.to_i : str.to_i) when 'o': str.to_i.oct when 'x': str.to_i.hex when 'X': str.to_i.hex.to_s.upcase when 'e': e_flag(str) when 'E': e_flag(str).upcase when 'f': str.to_f when 'F': str.to_f.to_s.upcase when 'g': g_flag(str) when 'G': g_flag(str).upcase when 'c': str[0].chr when 's': str.to_s when '%': '%' else raise ArgumentError.new("malformed format string - #{spec}") end end end f = argv[0].match(/\A#{MATCH_STR}\z/)[1..-1] if f[0].include?('*') str = argv[2].to_s width = argv[1] else str = argv[1].to_s width = f[1] end if /\A[di]\z/ =~ f[4] and str.to_f != str.to_i raise ArgumentError.new("invalid value for Integer: #{str}") end flag = f[0] prec = f[2] spec = f[4] opt = f[0].include?('#') check_flag(check_spec(str, spec, opt), flag, width, prec) end p mysprintf("%%", "testtest") # => "%" p sprintf("%%", "testtest") # => "%" p mysprintf("%5.0u", '-1') # => "4294967295" p sprintf("%5.0u", '-1') # => "4294967295" p mysprintf("% 2d", "1", '2') # => " 1" p sprintf("% 2d", "1", '2') # => " 1"
Rating2/2=1.00-0+
[ reply ]
saws
#5265()
[
Ruby
]
Rating2/2=1.00
Rubyのsprintfの仕様に従って実装しました. pフラグは仕様が不明瞭だったので実装しませんでした.
format系のメソッドは仕様不可ということで, 指数表示変換は自前で容易したのでバグが潜在している可能性が高いです.
Rating2/2=1.00-0+
[ reply ]