Почему знак процента (%) был выбран в качестве спецификатора формата для семейства функций printf?

27

Всем известно, что, по крайней мере в C, вы используете printfсемейство функций для печати форматированной строки. И эти функции используют знак процента ( %), чтобы указать начало спецификатора формата. Например, %dозначает, чтобы напечатать int, и %uозначает, чтобы напечатать unsigned int. Если вы не знакомы с тем, как printfработают заполнители функций и форматов, или просто нуждаетесь в обновлении, статья Википедии - хорошее место для начала.

У меня вопрос, есть ли особенно веская причина, по которой это было изначально или должно быть выбрано в будущем в качестве спецификатора формата?

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

Например, с C # (и другим семейством языков .NET) Microsoft приняла несколько иное решение относительно работы функций форматирования строк. Хотя некоторая степень безопасности типов может быть обеспечена там (в отличие от реализации printfв C), и поэтому нет необходимости включать указание типа соответствующего параметра, они решили использовать пары фигурных скобок с нулевым индексом ( {}) как спецификаторы формата, вот так:

string output = String.Format("In {0}, the temperature is {1} degrees Celsius.",
                              "Texas", 37);
Console.WriteLine(output);

// Output:
//     In Texas, the temperature is 37 degrees Celsius.

Документация по String.Formatметоду содержит больше информации, как и эта статья о составном форматировании в целом , но точные детали довольно не важны. Дело в том, что они просто отказались от давней практики использования %для указания начала спецификатора формата. Язык C мог бы просто использоваться {d}и {u}, но это не так. У кого-нибудь есть мысли о том, почему, имеет ли это решение смысл в ретроспективе, и должны ли новые реализации следовать ему?

Очевидно, что нельзя выбрать символ, который не должен был бы быть экранируемым, чтобы его можно было включить в саму строку, но эта проблема уже достаточно хорошо решена, если использовать только два из них. Какие еще соображения актуальны?

Коди Грей
источник
5
Проблема побега не решается с помощью двух символов. Это просто означает, что вам нужно убежать еще от одного персонажа.
JJJ
2
Мне интересно. Конечно, можно было бы использовать {u}вместо, %uно будет ли это иметь какое-либо существенное преимущество? Это кажется в значительной степени произвольным выбором.
CB Bailey
12
@JarrodRoberson, так вы говорите, что они сознательно выбрали {}синтаксис, чтобы люди, изучающие C #, не начали изучать что-нибудь еще? Мне очень трудно поверить, что это была главная, если вообще вообще, часть их дизайнерского решения. Можете ли вы сделать резервную копию своего заявления как-нибудь?
Стейн
6
Интересно, что Python отказался от (намного более совершенной формы) %форматирования в пользу чего-то похожего на {}форматирование .NET, поскольку последний предлагает большую гибкость.
Конрад Рудольф
3
Почему небо голубое, и почему слово «синий» называется синим? Они должны были что-то выбрать.

Ответы:

12

Как отмечает @Secure, printfфункция C основана на writefфункции BCPL . И если вы посмотрите на страницу Википедии для BCPL , у нее есть пример, который показывает, что BCPL writefтакже используется %для введения спецификатора формата.

Таким образом, мы можем сделать вывод, что C использовал %либо потому, что это сделал BCPL, либо по тем же причинам, что и BCPL. Мне кажется, что это просто %один из наименее часто используемых символов ASCII ... или так думали авторы. Также вероятно, что они не тратили много времени на взвешивание различных альтернатив. В то время и BCPL, и C были малоизвестными языками, и авторам, скорее всего, приходилось иметь дело с более важными вещами.

Однако в работах есть небольшой гаечный ключ. Хотя C был вдохновлен BCPL, не совсем понятно, заимствовал ли C библиотеки ввода-вывода BCPL или наоборот. Я смутно вспоминаю, что библиотеки ввода / вывода BCPL пережили процесс эволюции примерно в то время, когда в язык был добавлен инфиксный оператор индексации байтов. (На самом деле, я думаю, что знаю, кто бы знал об этом.)

Стивен С
источник
3
«На самом деле, я думаю, я знаю, кто бы знал об этом» ... а? ... и? .. Не просто оставьте нас с вешалкой скалы ...
Mawg
2
@ Mawg - вероятно, Брайан Найт. Ян Уилсон, вероятно, будет. Мартин Ричардс определенно будет. НТН.
Стивен К
6

Запись в Википедии не содержит много исторической информации, не относящейся к конкретным printfперсонажам, но вообще не содержит символов.

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

Ранние ссылки на термин «экранирующий символ» можно найти в технических публикациях Боба Бемера в IBM. По-видимому, именно он изобрел этот механизм во время своей работы над набором символов ASCII.

Мое предположение: обратная косая черта уже использовалась для строковых литералов, а для строк формата требовался другой символ. Скорее всего, они выбрали персонажа с предполагаемой наименьшей частотой нормального использования и появления.

Кстати, другая связанная статья связана там с термином, который я раньше не слышал:

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

В статье printfесть еще несколько информационных фрагментов, но не о причинах.

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

C variadic printf происходит из функции writef в BCPL.

Безопасный
источник