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 in Z
⌷∘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 is c:
:⎕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.