Призначення триграфських послідовностей у С ++?


127

Відповідно до стандарту C ++ '03 2.3 / 1:

Перш ніж проводити будь-яку іншу обробку, кожне виникнення однієї з наступних послідовностей з трьох символів ("послідовності триграфа") замінюється одним символом, зазначеним у таблиці 1.

----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------

У реальному житті це означає, що код printf( "What??!\n" );призведе до друку, What|тому що ??!це триграфічна послідовність, яка замінюється |символом.

Моє запитання - яка мета використання триграфів? Чи є якась практична перевага використання триграфа?

UPD : У відповідях згадувалося, що деякі європейські клавіатури не мають усіх розділових знаків, тому програмістам, які не в США, доводиться використовувати триграфи в повсякденному житті?

UPD2 : Visual Studio 2010 має підтримку триграфа за замовчуванням вимкнено.


Деякі пунктуації важче дістати на європейських клавіатурах (до того, що деякі програмісти використовують американський макет для набору тексту швидше) Не бачив такого, де пунктуації повністю відсутні - можливо, для слов'янських мов?
peterchen

2
Може статися, що деякі термінали та / або віртуалізація не дозволяють легко отримати доступ до деяких символів. На мій досвід, головним правопорушником є ​​тильда.
Франческо

1
набравши це на моїй клавіатурі DE-deadkeys, # - це клавіша поруч із поверненням, \ є "AltGr" + "ß" (поруч із 0), ^ - "^" + "^" (через мертві клавіші; поруч із 1) , [є "AltGr" + "8",] є "AltGr" + "9", | є "AltGr" + "<", {є "AltGr" + "7",} є "AltGr" + "0", а ~ є "~" + "~" (через мертві клавіші, трохи вище #). так що насправді нічого великого. мої пальці наче набирають ці комбінації самостійно :-D
nonchip

1
Я подумав, що нормально мати два розкладки клавіатури та перемикати їх відповідно до роботи, яку я виконую на комп’ютері. Це загальний шлях у регіоні Центральної Європи. Користуватися цими триграфами досить моторошно. Я б проголосував за те, щоб зняти це зі стандарту.
VX

Відповіді:


97

На це запитання (про тісно пов’язані з ними графіки) є відповідь.

Це зводиться до того, що набір символів ISO 646 не має всіх символів синтаксису С, тому є деякі системи з клавіатурами та дисплеями, які не можуть мати справу з символами (хоча я думаю, що вони досить рідкісні нині).

Взагалі їх не потрібно використовувати, але вам потрібно знати про них саме для проблеми, з якою ви зіткнулися. Триграфи - це причина того, що ?символ ' ' має послідовність втечі:

'\?'

Отже, кілька способів уникнути вашої прикладної проблеми:

 printf( "What?\?!\n" ); 

 printf( "What?" "?!\n" ); 

Але ти повинен пам’ятати, коли ти пишеш два '?' символи, про які ти можеш починати триграф (і це, звичайно, ніколи не те, про що я думаю).

На практиці триграфи та диграфи - це те, про що я не переживаю взагалі щодня. Але вам слід знати про них, оскільки раз на пару років ви натрапляєте на помилку, пов’язану з ними (а ви будете витрачати решту дня, проклинаючи їх існування). Було б добре, якби компілятори могли бути налаштовані на попередження (або помилку), коли вони трапляються через триграф або диграф, тож я міг би знати, що у мене є щось, з чим слід свідомо мати справу.

І тільки для повноти, фотографії набагато менш небезпечні, оскільки вони обробляються як лексеми, тому диграф всередині рядкового літералу не трактуватиметься як диграф.

Для приємної освіти з різних розваг з пунктуаційними програмами в програмах C / C ++ (включаючи триграфну помилку, яка б напевно змусила мене витягати волосся), подивіться статтю GOTW № 86 Herb Sutter .


Додаток:

Схоже, GCC не буде обробляти (і попереджатиме про) триграфи за замовчуванням. Деякі інші компілятори мають можливість вимкнути підтримку триграфа (наприклад, IBM). Microsoft почала підтримувати попередження (C4837) у VS2008, яке має бути чітко ввімкнено (використовуючи -Wall або щось подібне).


Сумісність із C є єдиною причиною? Чи можливо їх зустріти в сучасних програмах C ++?
Кирило Васильович Лядвінський

Так, C ++ підтримує також триграфи та графіки.
Майкл Берр

4
Як я пам’ятаю, щонайменше для одного компілятора, який я використав (g ++?), Потрібен явний параметр командного рядка перед тим, як триграф і / або диграф буде переведені, інакше подається попередження, але не замінюється.
KTC

1
@ Jla3ep - В мене особисто ніколи не було потреби в триграфах, але, на жаль, компілятори будуть обробляти код з ними, тому вам потрібно знати про них (щоб уникнути випадкового використання). Крім того, якщо ви отримаєте код з іншого місця, ви можете зіткнутися з їх навмисним використанням, але це було б надзвичайно незвично. Я думаю, що я натрапив на навмисне використані триграфи один раз у 20+ років (це був якийсь код для мейнфрейму IBM).
Майкл Берр

1
Мені це справді стає на нерви, коли триграфи розширюються в коментарях, щоб робити дивовижні речі.
Джошуа

23

Діти сьогодні! :-)

Так, іноземне обладнання, наприклад, термінал IBM 3270. У 3270, якщо я пам’ятаю, немає фігурних брекетів! Якщо ви хотіли писати C на міні / мейнфреймах IBM, вам довелося використовувати жалюгідні триграфи для кожної межі блоку. На щастя, мені довелося лише писати програмне забезпечення на C, щоб імітувати деякі міні-комп'ютерні засоби IBM, а не писати програмне забезпечення C на System / 36.

Подивіться поруч із клавішею "P":

клавіатура

Хммм. Важко сказати. Поруч із "поверненням каретки" є додаткова кнопка, і я можу мати її назад: можливо, саме пара "[" / "]" відсутня. У будь-якому випадку ця клавіатура спричинить вам горе, якби вам довелося писати С.

Крім того, на цих терміналах відображається EBCDIC, "рідний" набір символів мейнфрейму IBM, а не ASCII (дякую Павлу Мінаєву за нагадування).

З іншого боку, як, наприклад, керівництво GNU C говорить: "Вам не потрібно це пошкодження мозку". Компілятор gcc залишає цю "функцію" відключеною за замовчуванням.


1
На клавіатурі є кнопка скидання. Це круто! Дивно, що спочатку привернуло мою увагу.
l46kok

10
Той, хто хоче використовувати C ++ 17 на апараті EBCDIC, повинен потрапити до в'язниці за некрофілію.
СФ.

Якщо платформа не має символів на всіх , крім тих , в ISO646, може не все , що може бути зроблено з тріграфамі бути зроблено, вимагаючи , щоб кожна реалізація визначає або зворотну косу риску або ще якийсь - або символ , який не в наборі C символів у вигляді "meta" символу, замініть всі посилання на косою косою рисою в стандарті на "meta" і додайте звороту косу рису / мета-скасування для будь-яких членів набору символів C, яких немає в ISO-646?
supercat

22

Із The C++ Programming LanguageСпеціального видання, сторінка 829

В ASCII спеціальні символи [, ], {, }, |, і \займають задані позиції символів , призначені в якості алфавітного ІСО. У більшості європейських національних наборів символів ISO-646 ці позиції займають літери, не знайдені в англійському алфавіті.

Набір триграфів надає можливість виражати національні символи портативно, використовуючи справді стандартний набір мінімальних символів. Це може бути корисно для обміну програмами, але людям не полегшує читання програм. Звичайно, довгострокове вирішення цієї проблеми полягає в тому, щоб програмісти на C ++ придбали обладнання, яке добре підтримує і рідну мову, і C ++. На жаль, це здається для деяких нездійсненним, і впровадження нового обладнання може бути неприємно повільним процесом.


7
"Впровадження нового обладнання може бути неприємно повільним процесом". Особливо порівняно з швидким і безболісним процесом стандартизації функцій мови програмування.
jforberg

4
Якщо це хитрість для розкладки клавіатури, то смішно, що немає триграфа, наприклад, для набору тексту `, якого немає в італійській та кількох інших розкладках клавіатури
badp

15

Вони призначені для використання в системах, у яких відсутні деякі символи в основному наборі символів C ++. Потрібно сказати, що такі системи надзвичайно рідкісні.


2
Це означає, що я ніколи не буду їх використовувати в реальному житті?
Кирило В. Лядвінський

1
У якій країні ви живете? Не всі клавіатури для всіх мов мають необхідні клавіші.
Девід Торнлі

2
Так, але, можливо, вам потрібно буде знати про існування, якщо хтось спричинить несподіваний результат, коли він підтримується, скажімо, рядковим буквалом.
CB Bailey

4
@David Thornley: Більшість сучасних систем підтримують усі основні символи C ++, навіть якщо вони не знаходяться в звичайному місці або потребують послідовності модифікаторів для введення. Триграфи потрібно підтримувати лише у вихідному коді в системах, де символ фактично не може бути представлений у наборі символів системи. Я все ще стверджую, що такі системи надзвичайно рідкісні.
CB Bailey

9

Триграфи були запропоновані для видалення в C ++ 0x. Зважаючи на це , все ще, мабуть, є вагомі аргументи на їхню підтримку - див. Документ комітету C ++ N2910, який обговорює це. Мабуть, EBCDIC є одним з головних твердинь, де вони потрібні.


Так, та "іноземна мова"! :-)
Робопрог

Вони насправді не говорять багато, крім "результатів внутрішнього опитування відгуків клієнтів", але ну добре. Я здивований, що EBCDIC все ще широко використовується, але (і ці системи очікують використання компіляторів C ++ 0x)
peterchen

5

Я бачив триграфі, які використовувались на початку 90-х, щоб допомогти конвертувати програми PL / 1 з мейнфрейму для запуску / компіляції / налагодження на ПК.

Вони намагалися редагувати PL / I на ПК за допомогою компілятора PL / I до C, і вони хотіли, щоб код працював, коли він переходив до мейнфрейму, який не підтримував фігурні дужки. Я припустив, що вони можуть використовувати макроси, як

#def BEGIN {    
#def END }  

або як дружніша альтернатива PL / I

#def BEGIN ??<
#def END ??>

і якщо вони дійсно хотіли пофантазувати, вони могли б спробувати

#ifdef MAINFRAME
    #def BEGIN ??<
    #def END ??>
#else
    #def BEGIN {    
    #def END }  
#endif

і тоді програма виглядала б так, як написана на Паскалі. Вони просто дивилися на мене смішно і не розмовляли зі мною протягом решти дня. Я не думаю, що я їх звинувачую. :)

Що вбило зусилля, а не триграфи, це було відмінності системи IO між платформами. Відкриття файлів на ПК настільки сильно відрізнялося від мейнфрейму, що це створило б занадто багато хитрощів, щоб тримати один і той же код на обох.


PL / 1 = версія IBM C (більше або менше). Дивіться мій коментар: у терміналів IBM немає клавіш '{' / '}' :-( Начебто важко написати C [++] на одній із них, в іншому випадку
Roboprog

3

Перш за все тому, що стандарт С запровадив їх ще в 1989 році, коли виникли проблеми із наявністю символів, на які триграфовані карти на деяких машинах. На той час, коли в 1998 році був опублікований стандарт C ++, потреба в триграфах була не великою. Вони - бородавка на С; вони так само, як бородавка на C ++. Виникла потреба в них - особливо поза англомовним світом - саме тому їх додали до С.


1
Я завжди підозрював, що IBM не розмовляє англійською мовою :-)
Roboprog

3

Деякі європейські клавіатури не мають (не?) Всіх пунктуаційних символів, які мали американські клавіатури, оскільки вони потребували клавіш для своїх незвичайних буквених символів. Так, наприклад (склавши це), шведська клавіатура мала б A-кільце там, де була фігурна дужка.

Для розміщення цих користувачів триграфи - це спосіб ввести розділові знаки, використовуючи лише найпоширеніші символи ASCII.


4
Триграфи насправді не стосуються введення даних (вони роблять код досить нечитабельним), вони більше стосуються систем, які насправді не мають потрібних символів. Якщо система може записувати та відображати символ - навіть якщо потрібно ввести триграмову послідовність клавіш - було б набагато простіше не зберігати послідовність триграфа у джерелі.
CB Bailey

2

Вони там здебільшого з історичних причин. Сьогодні більшість сучасних клавіатур для більшості мов дозволяють отримати доступ до всіх цих символів, але це колись було проблемою з деякими європейськими клавіатурами. Ось чому були винайдені триграфи.

Якщо ви не знаєте, для чого вони потрібні, не слід їх використовувати.

Однак все-таки добре знати про них, оскільки ви можете випадково і ненавмисно використовувати його у своєму коді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.