Используйте переменные аргументы в качестве аргументов для sprintf - PullRequest
1 голос
/ 31 марта 2012

Я бы хотел запрограммировать оболочку вокруг printf(...).

Моя первая попытка была:

sub printf2 {
    my $test = sprintf(@_);
    print $test;
}

Поскольку массив (в скалярном контексте) не является строкой формата, это не работает (как и ожидалось).

Кто-нибудь знает решение?Вероятно, без использования каких-либо специальных пакетов?

РЕДАКТИРОВАТЬ: В реальном контексте я хотел бы использовать sprintf.Очевидно, есть разница между printf и sprintf.

Ответы [ 3 ]

7 голосов
/ 01 апреля 2012

Функция sprintf имеет прототип ($@) , поэтому первый аргумент sprintf всегда оценивается в скалярном контексте, даже если это массив.

$x = sprintf(@a);      # same as  sprintf(scalar @a)

Поэтому перед вызовом sprintf необходимо отделить шаблон от остальных аргументов. Вот краткий способ:

sub printf2 {
    my $test = sprintf(shift, @_);
    print $test;
}

Любопытно, что printf не имеет прототипа и делает то, что вы ожидаете.

printf(@a);            # same as  printf($a[0], @a[1..$#a])
2 голосов
/ 31 марта 2012

Как насчет этого

sub pf { printf $_[0],@_[1..$#_] }
0 голосов
/ 01 апреля 2012

Многие из именованных операторов (например, sprintf) имеют специальные синтаксисы. Синтаксис sprintf определен как

sprintf FORMAT, LIST

Это часто (но не всегда) можно увидеть, используя prototype.

>perl -wE"say prototype 'CORE::sprintf'"
$@

Проблема в том, что вы использовали один из следующих синтаксисов вместо документированного синтаксиса.

sprintf ARRAY
sprintf LIST

Просто переключитесь на документированный синтаксис, чтобы решить вашу проблему.

sub printf2 {
   my ($format, @args) = @_;
   print sprintf($format, @args);
}

Или, если вы хотите избежать копирования,

sub printf2 {
   print sprintf($_[0], @_[ 1..$#_ ]);
}
...