Абстрагирующее выражение printf () - PullRequest
2 голосов
/ 01 декабря 2010

Читая какой-то случайный код, я сталкиваюсь с выражением printf(), которое мне немного странно, утверждение выглядит так

void PrintDiceFace(int n){
    printf("%d 0 %d\n%d %d %3$d\n%2$d 0 %1$d\n\n",n>50,51%n%2,n>53,n%2);
}

Это фактически запутанная версия сниппета, которая на самом деле печатает лицо электронной кости . Для пример .

Пожалуйста, объясните это printf() утверждение подробно.

http://en.wikipedia.org/wiki/Dice

Ответы [ 5 ]

5 голосов
/ 01 декабря 2010

POSIX / SUS printf() разрешает число, за которым следует $ после %, чтобы указать, что следует выбрать определенный аргумент из varargs.

printf("%2$s, %1$s!\n", "world", "Hello");
4 голосов
/ 01 декабря 2010

Формат результата:

<num1>    0   <num2>
<num3> <num4> <num3>
<num2>    0   <num1>

со всеми числами, равными 0 или 1, в зависимости от результата последующих операций. Единственная необычная вещь в этой строке формата - это использование %<N>$ - что говорит о том, что для этого параметра следует использовать arg<N> функции (вместо «следующий» в порядке). Пример, если вы укажете:

printf("%d %1$x\n", 10);

печатает «10 а».

1 голос
/ 01 декабря 2010

Этот код не соответствует и не работает.Если используются спецификаторы индекса аргумента %N$ -типа, они должны использоваться для всех аргументов, а не выборочно для одних и не для других.

Фиксированная версия:

printf("%1$d 0 %2$d\n%3$d %4$d %3$d\n%2$d 0 %1$d\n\n",n>50,51%n%2,n>53,n%2);

Здесь приведена соответствующая цитата: http://www.opengroup.org/onlinepubs/9699919799/functions/fprintf.html

Формат может содержать спецификации преобразования нумерованных аргументов (то есть "% n $" и "* m $") или ненумерованныеспецификации преобразования аргументов (то есть% и *), но не оба.Единственным исключением является то, что %% можно смешивать с формой «% n $».Результаты смешивания нумерованных и ненумерованных спецификаций аргументов в строке формата не определены.Когда используются спецификации нумерованных аргументов, для указания N-го аргумента необходимо, чтобы все ведущие аргументы, от первого до (N-1) -го, были указаны в строке формата.

Тот факт, что этоКод «сработал» является побочным эффектом конкретной реализации функции printf (вероятно, GNU).Нет никаких оснований ожидать, что он будет работать в других системах или даже в будущих версиях той же системы, если только это не задокументировано для работы в этой системе.

Даже с моим исправлением этот код все еще специфичен для POSIX;это не переносимо для реализаций C в не-POSIX системах.Вместо уродливых взломов автор должен был просто дублировать аргументы по мере необходимости:

printf("%d 0 %d\n%d %d %d\n%d 0 %d\n\n",n>50,51%n%2,n>53,n%2,n>53,51%n%2,n>50);
1 голос
/ 01 декабря 2010

Начнем с формата ("%d 0 %d\n%d %d %3$d\n%2$d 0 %1$d\n\n"):

  • % d означает числовой (десятичное число в виде целого числа) вывод
  • % 3d означает, что вы позволите по крайней мере 3 символа в качестве заполнителя для вывода (например, «2» будет дополнено «2». Вы можете использовать% 03d, чтобы сделать то же самое, но заполнение начальными нулями для получения «00» )
  • % 3 $ d фактически означает, что вместо использования элемента в списке в соответствующем порядке, вы непосредственно указываете элемент (так что здесь это будет n > 53)
  • и т.д ...

Для забавно выглядящих параметров:

  • n> 50 будет 1-м и 7-м% d
  • 51% n% 2 будет 2-м и 6-м% d
  • n> 53 будет 3-м и 5-м% d
  • n% 2 будет четвертым% d

См. man 3 printf

1 голос
/ 01 декабря 2010

Он печатает три строки целых чисел, как в более простом:

printf("%d %d %d\n%d %d %d\n%d %d %d\n", 0, 0, 0, 0, 1, 0, 0, 0, 0);

Что будет печатать

0 0 0
0 1 0
0 0 0

% 2 $ d означает «использовать 2-й аргумент вместоАргумент, соответствующий моему месту "

Теперь, каждый столбец в каждой строке имеет определенное условие, при котором" 0 "или" 1 "печатается в этом месте.Из-за симметричности игральных костей все, что вас действительно интересует, это следующие позиции (помеченные х):

x 0 x
x x -
- 0 -

Другие позиции могут быть получены из них (-) или всегда равны 0 (0).

Это пример «умного кодирования», который забавно делать, но разочаровывать читать.

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