Why do printf and sprintf behave differently when only given an array?
sub do_printf { printf @_ }
sub do_sprintf { print sprintf @_ }
do_printf("%s\n", "ok"); # prints ok
do_sprintf("%开发者_StackOverflow中文版s\n", "ok"); # prints 2
sprintf
has prototype $@
while printf
has prototype of @
From the perldoc on sprintf:
Unlike printf, sprintf does not do what you probably mean when you pass it an array as your first argument. The array is given scalar context, and instead of using the 0th element of the array as the format, Perl will use the count of elements in the array as the format, which is almost never useful.
See codeholic
's and Mark
's answers for the explanation as to why they behave differently.
As a workaround, simply do:
sub do_sprintf { print sprintf(shift, @_) }
Then,
sub do_printf { printf @_ }
sub do_sprintf { print sprintf(shift, @_) }
do_printf("%s\n", "ok"); # prints ok
do_sprintf("%s\n", "ok2"); # prints ok2
They do different things. For printf
the output is to a stream; for sprintf
you want the string constructed. It handles the formatting (the f) of the print command. The main purpose for printf
is to print out the value it constructs to a stream but with s(tring)printf(ormat) you're only trying to create the string, not print it.
printf
returns the number of characters printed to a stream as feedback. Once characters are printed to a stream they've passed out of the logical structure of the program. Meanwhile, sprintf
needs to hand you back a string. The most convenient way is as a return value--which because it is within the program structure can be inspected for length, or whether it contains any 'e's, or whatever you want.
Why shouldn't they behave differently?
sprintf evaluates the array in scalar context. Your array has two elements, so it evaluates as "2" (without a trailing \n).
精彩评论