sub do_printf { printf @_ }
sub do_sprintf { print sprintf @_ }
do_printf("%s\n", "ok"); # prints ok
do_sprintf("%s\n", "ok"); # prints 2
Из perldoc на sprintf :
В отличие от printf, sprintf не делает то, что вы, вероятно, имеете в виду, когда вы передаете ему массив в качестве первого аргумента. Массиву дается скалярный контекст, и вместо использования 0-го элемента массива в качестве формата , Perl будет использовать количество элементов в массиве как формат, который почти никогда не полезен.
Они делают разные вещи. Для printf
выводом является в поток; для sprintf
вы хотите построить строку. Он обрабатывает форматирование ( f ) команды печати. Основная цель printf
- распечатать созданное значение в поток, но с s (tring) printf (ormat) вы пытаетесь только создать строку, а не печатать Это.
printf
возвращает количество символов, напечатанных в потоке в качестве обратной связи. После того, как символы напечатаны в потоке, они вышли из логической структуры программы. Между тем sprintf
должен вернуть вам строку. Самый удобный способ - в виде возвращаемого значения, которое, поскольку оно находится в структуре программы, может быть проверено на предмет длины, наличия в нем каких-либо 'e' или чего угодно.
Почему не должны вести себя по-другому?
sprintf
имеет прототип $ @
в то время как printf
имеет прототип @
См. Ответы codeholic
и Марка
для объяснения того, почему они ведут себя по-разному.
В качестве обходного пути просто выполните:
sub do_sprintf { print sprintf(shift, @_) }
Затем
sub do_printf { printf @_ }
sub do_sprintf { print sprintf(shift, @_) }
do_printf("%s\n", "ok"); # prints ok
do_sprintf("%s\n", "ok2"); # prints ok2
sprintf оценивает массив в скалярном контексте. Ваш массив состоит из двух элементов, поэтому он оценивается как «2» (без завершающего \ n).