Dlaczego znak procentu (%) został wybrany jako specyfikator formatu dla rodziny funkcji printf?

27

Wszyscy wiedzą, że przynajmniej w C używa się printfrodziny funkcji do drukowania sformatowanego ciągu. I te funkcje używają znaku procentu ( %) do wskazania początku specyfikatora formatu. Na przykład %doznacza wydrukować inti %uoznacza wydrukować unsigned int. Jeśli nie wiesz, jak printfdziałają funkcje zastępcze funkcji i formatu, lub po prostu potrzebujesz odświeżenia, artykuł w Wikipedii jest dobrym miejscem na początek.

Moje pytanie brzmi: czy istnieje szczególnie przekonujący powód, dla którego został on pierwotnie lub powinien zostać wybrany w przyszłości jako specyfikator formatu?

Oczywiście decyzja została podjęta dawno temu (bardzo prawdopodobne dla poprzednika nawet języka C) i od tego czasu była mniej więcej „standardowa” (nie tylko w C, ale także w wielu innych językach, które dostosował swoją składnię w różnym stopniu), więc jest o wiele za późno, aby się zmienić. Ale nadal jestem ciekawy, czy ktokolwiek ma jakiś wgląd w to, dlaczego ten wybór mógł być dokonany w pierwszej kolejności i czy nadal ma sens jako wybór, jeśli projektuje się nowy język o podobnej funkcjonalności.

Na przykład w przypadku C # (i innej rodziny języków .NET) Microsoft podjął nieco inną decyzję dotyczącą działania funkcji formatowania łańcucha. Chociaż można tam zapewnić pewien stopień bezpieczeństwa typu (w przeciwieństwie do implementacji printfw C), a zatem nie jest konieczne dołączanie wskazania typu odpowiedniego parametru, zdecydowano się na użycie nawiasów parowych nawiasów klamrowych ( {}) jako specyfikatory formatu, takie jak:

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.

Dokumentacja String.Formatmetody zawiera więcej informacji, podobnie jak ten artykuł na temat formatowania złożonego , ale dokładne szczegóły są raczej nieistotne. Chodzi po prostu o to, że porzucili wieloletnią praktykę używania %do oznaczania początku specyfikatora formatu. Język C może po prostu być łatwo wykorzystane {d}i {u}, ale tak się nie stało. Czy ktoś ma jakieś przemyślenia na temat tego, czy ta decyzja ma sens z perspektywy czasu i czy powinny następować nowe wdrożenia?

Oczywiście nie ma żadnej postaci, która mogłaby zostać wybrana, która nie musiałaby być ucieczką, aby mogła być zawarta w samym łańcuchu, ale ten problem jest już całkiem dobrze rozwiązany przez użycie tylko dwóch z nich. Jakie inne uwagi są istotne?

Cody Gray
źródło
5
Problem ucieczki nie został rozwiązany za pomocą dwóch znaków. Oznacza to po prostu, że masz jeszcze jedną postać do ucieczki.
JJJ
2
Jestem ciekaw. Z pewnością byłoby możliwe użycie {u}zamiast, %uale czy miałoby to jakąś znaczącą zaletę? Wydaje się, że jest to w dużej mierze arbitralny wybór.
CB Bailey,
12
@JarrodRoberson, więc mówisz, że celowo wybrali {}składnię, aby ludzie uczący się języka C # nie zaczęli uczyć się niczego innego? Bardzo trudno mi uwierzyć, że była to ważna, jeśli w ogóle, część ich decyzji projektowej. Czy możesz w jakiś sposób wykonać kopię zapasową wyciągu?
stijn
6
Co ciekawe, Python porzucił (znacznie lepszą formę) %formatowanie na rzecz czegoś podobnego do {}formatowania .NET, ponieważ ta ostatnia oferuje większą elastyczność.
Konrad Rudolph,
3
Dlaczego niebo jest niebieskie i dlaczego słowo „niebieski” nazywa się niebieski? Musieli coś wybrać.

Odpowiedzi:

12

Jak zauważa @Secure, printffunkcja C jest inspirowana writeffunkcją BCPL . A jeśli spojrzysz na stronę wikipedii dla BCPL , ma przykład, który pokazuje, że BCPL writefrównież użył %do wprowadzenia specyfikatora formatu.

Możemy więc wywnioskować, że C użył %albo dlatego, że zrobił to BCPL, albo z tych samych powodów, które zrobił BCPL. Mam przeczucie, że to po prostu %jedna z najrzadziej używanych postaci ASCII ... a przynajmniej tak uważali autorzy. Jest również prawdopodobne, że nie spędzili dużo czasu na rozważaniu różnych alternatyw. W tym czasie zarówno BCPL, jak i C były nieznanymi językami, a autorzy najprawdopodobniej mieli ważniejsze sprawy do rozwiązania.

W pracach jest jednak niewielki klucz. Chociaż C został zainspirowany przez BCPL, nie jest całkowicie jasne, czy C pożyczył biblioteki we / wy BCPL, czy na odwrót. Przytomnie pamiętam, że biblioteki we / wy BCPL przeszły proces ewolucji mniej więcej w momencie dodania do języka operatora indeksowania bajtów infix. (Właściwie myślę, że wiem, kto by o tym wiedział.)

Stephen C.
źródło
3
„Właściwie myślę, że wiem, kto by o tym wiedział”… i? ... i? .. Nie zostawiaj nas tylko z wieszakiem na klify ...
Mawg
2
@Mawg - prawdopodobnie Brian Knight. Ian Wilson prawdopodobnie by to zrobił. Martin Richards na pewno by to zrobił. HTH.
Stephen C
6

Wpis w Wikipedii nie zawiera wielu informacji historycznych, nie jest specyficznych printf, ale ogólnie do znaków ucieczki.

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

Wczesne odniesienie do terminu „znak ucieczki” znajduje się w publikacjach technicznych Boba Bemera na temat IBM. Najwyraźniej to on wynalazł ten mechanizm podczas pracy nad zestawem znaków ASCII.

Domyślam się, że ukośnik odwrotny był już używany do literałów łańcuchowych i do formatowania ciągów potrzebny był inny znak. Najprawdopodobniej wybrali postać z założoną najmniejszą częstotliwością normalnego użytkowania i występowania.

BTW, kolejny powiązany artykuł jest tam powiązany z terminem, który słyszałem wcześniej w Nether:

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

Artykuł printfzawiera kilka dodatkowych fragmentów informacji, ale nie dotyczy to przyczyn.

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

Wariantowy printf C wywodzi się z funkcji writef BCPL.

Bezpieczne
źródło