Найдите, сколько аргументов используется в выражении printf () - PullRequest
1 голос
/ 04 декабря 2009

Учитывая некоторые неизвестные входные данные, как определить, какие переменные подставляются в оператор (s)printf?

printf("%s %s", "a", "b");     // both used
printf("%s",    "a", "b");     // only the first one used
printf('%1$s %1$s', "a", "b"); //      "        "
printf('%s %1$s', "a", "b");    //     "        "
printf('%1$s %s %1$s', "a", "b");   // "        "
printf('%2$s', "a", "b");      // only the second one used.

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

В моей собственной ситуации есть только две переменные, которые можно заменить, и мне нужно знать, используется ли вторая или нет.

Ответы [ 3 ]

2 голосов
/ 04 декабря 2009

Разобрать строку формата самостоятельно и посмотреть, сколько аргументов она ожидает.

РЕДАКТИРОВАТЬ: пример psuedocode (без проверки ошибок):

bool arg1used = false;
bool arg2used = false;
int unspecifiedscount = 0;
for (int i = 0; i < s.length; i++) {
    if s[i] != '%' continue;
    switch s[i+1] {
        case '%':
            i++;
            break;
        case 's':
            if unspecifiedscount == 0 arg1used = true;
            if unspecifiedscount == 1 arg2used = true;
            break;
        case '1':
            if s[i+2] == '$' && s[i+3] == 's' {
                arg1used = true;
                i+=3;
                true;
            }
            break;
        case '2':
            if s[i+2] == '$' && s[i+3] == 's' {
                arg2used = true;
                i+=3;
                true;
            }
            break;
    }
}
1 голос
/ 04 декабря 2009

Вот немного хакерская функция для этого:

function printf_and_return_min_args_required(/* var args */) {
    $old_track = ini_set('track_errors', '1');
    $args = func_get_args();
    $args2 = array();
    $required = 100;    
    foreach ($args as $arg) {
        $args2[] = $arg;
        if (@call_user_func_array("printf", $args2)) {
            $required = count($args2) - 1;
            break;
        }
    }
    ini_set('track_errors', $old_track);
    return $required;
}

Для sprintf() вам, возможно, придется вместо этого вернуть array($result, $required), если вы не хотите, чтобы $result печатался функцией.

1 голос
/ 04 декабря 2009

Я придумал хитрый способ, который работает в этой ситуации, но мне было бы интересно услышать лучшие решения, которые являются более общими.

if (($result = @sprintf($input, "a")) === false) {
    // need two arguments
    $result = sprintf($input, "a", "b");
} else {
    // only needed one argument
}

По сути, он просто пробует это с одним аргументом, и если это не сработало, то вы знаете, что нужно два.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...