printf-style string formatting
APL (73)
{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}
Some tests:
'a:%c b:%s c:%d'{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺} 65 'foo' 67
a:A b:foo c:67
printf←{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}
'1:%s 2:%s 3:%d 4:%c 5:%c' printf 'foo' 'bar' 100 110 'z'
1:foo 2:bar 3:100 4:n 5:z
'The %s brown %c%c%c jumps over the %s dog.' printf 'quick' 102 111 'x' 'lazy'
The quick brown fox jumps over the lazy dog.
Explanation:
G←'%!',⍺
: prefix a dummy specifier to the string (for easier processing)(Z←G='%')/⍳⍴G
: find the indices of all the%
characters in the string; also store a bitmask inZ
⌷∘G¨1↓1+
: select all the characters next to the%
s, and drop the dummy.⍵,⍪
: match up each specifier with its value from the right argument.{
...}/
: run the following function on each pair:'c'0≡⍵,∊⊃⍺
: if the argument is a number and the specifier isc
::⎕UCS⍺
: then return the unicode value of the argument,⋄⍕⍺
: otherwise, return the string representation of the argument.
⊂
: enclose⊂2∘↓¨Z⊂G
: split the string on the%
s and then remove the first two characters of each substring (this is where the dummy comes in), and enclose the result of that.↑
: make a matrix out of the two enclosed arrays, matching up each substring with the value that should follow it.,⌿
: join each substring with its value.⊃,/
: then join the resulting strings.
Lua 5.2, 115 bytes
-- Function definition, 115 chars
function f(f,...)n,t=0,{...}return(f:gsub('%%(%a)',function(s)n=n+1return(({c=s.char})[s]or tostring)(t[n])end))end
-- Usage example
print(f('Happy %cew %d %s %f',78,2014,'Year!',math.pi))
-- Output: Happy New 2014 Year! 3.1415926535898
Ruby: 102 characters
f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}
Sample run:
irb(main):001:0> f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}
=> #<Proc:0x96634ac@(irb):1 (lambda)>
irb(main):002:0> puts f["percent : %%\n char : %c or %c\n string : %s or %s or %s\ndecimal : %d or %d or %d\n float : %f or %f or %f\ninvalid : %x or %s or %d or %f", 65, 'B', 'format me', 42, Math::PI, 42, Math::PI, '2014', 42, Math::PI, '2014', 'more']
percent : %
char : A or B
string : format me or 42 or 3.141592653589793
decimal : 42 or 3 or 2014
float : 42.0 or 3.141592653589793 or 2014.0
invalid : %x or or 0 or 0.0
=> nil
Invalid format specifiers are kept in place. Format specifiers without argument value are replaced with the empty value of the given type.