C ++ 'da Trigraph dizilerinin amacı?


128

C ++ '03 Standardı 2.3 / 1'e göre:

Başka herhangi bir işlem gerçekleşmeden önce, aşağıdaki üç karakterlik dizilerden birinin ("trigraf dizileri") her bir oluşumu, Tablo 1'de belirtilen tek karakterle değiştirilir.

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

Gerçek hayatta bu, kodun printf( "What??!\n" );yazdırmayla sonuçlanacağı anlamına gelir, What|çünkü karakterle ??!değiştirilen bir trigraf dizisidir |.

Sorum şu, trigrafları kullanmanın amacı nedir? Trigraf kullanmanın herhangi bir pratik avantajı var mı?

UPD : Cevaplarda, bazı Avrupa klavyelerinin tüm noktalama karakterlerine sahip olmadığı, bu nedenle ABD dışındaki programcıların günlük yaşamda trigrafları kullanmak zorunda olduğu belirtildi.

UPD2 : Visual Studio 2010'da trigraph desteği varsayılan olarak kapalıdır.


Noktalama işaretlerinin bir kısmına avrupa klavyelerinde ulaşmak daha zor (bazı programcıların daha hızlı yazmak için ABD düzenini kullandıkları noktaya kadar) Noktalama işaretlerinin tamamen eksik olduğu bir tane görmediniz - belki Slav dilleri için?
peterchen

2
Bazı terminaller ve / veya sanallaştırma, bazı karakterlere kolayca erişmenize izin vermeyebilir. Tecrübelerime göre asıl suçlu tilde.
Francesco

1
bunu DE ölü tuşları klavyemde yazıyorum, # return öğesinin yanındaki bir tuş, \ "AltGr" + "ß" (0'ın yanında), ^ "^" + "^" (ölü tuşlar nedeniyle; 1'in yanında) , ["AltGr" + "8",] "AltGr" + "9", | "AltGr" + "<", {"AltGr" + "7",} "AltGr" + "0" ve ~, "~" + "~" (ölü tuşlar nedeniyle, # 'nin hemen üstünde). bu yüzden gerçekten önemli değil. parmaklarım bu kombinasyonları kendi başlarına yazmak gibi :-D
nonchip

1
İki klavye düzenine sahip olmanın ve bunları bilgisayarda yaptığım işe göre değiştirmenin normal olduğunu düşündüm. Orta Avrupa bölgesinde yaygın bir yoldur. Bu trigrafları kullanmak oldukça ürkütücü. Bunu standarttan çıkarmak için oy verirdim.
VX

1
@VX Dileklerin var!
graham.reeds

Yanıtlar:


98

Bu sorunun (yakından ilişkili digraflar hakkında) cevabı var.

ISO 646 karakter setinin C sözdiziminin tüm karakterlerine sahip olmadığı gerçeğine varıyor, bu nedenle karakterlerle başa çıkamayan klavyeli ve ekranlı bazı sistemler var (bunların oldukça nadir olduğunu hayal etsem de şu günlerde).

Genel olarak, bunları kullanmanıza gerek yoktur, ancak tam olarak karşılaştığınız sorun için onlar hakkında bilgi sahibi olmanız gerekir. Trigraflar, ' ?' karakterinin bir kaçış dizisine sahip olmasının nedenidir :

'\?'

Öyleyse örnek probleminizden kaçınmanın birkaç yolu:

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

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

Ama ikisini yazarken hatırlaman gerekiyor? bir trigraf başlatıyor olabileceğiniz karakterler (ve kesinlikle düşündüğüm bir şey değil).

Pratikte, trigraphs ve digraphs, günlük bazda hiç endişelenmediğim şeylerdir. Ancak bunların farkında olmalısınız çünkü her iki yılda bir onlarla ilgili bir hatayla karşılaşacaksınız (ve günün geri kalanını onların varlığını lanetleyerek geçireceksiniz). Derleyiciler bir trigraph veya digraph ile karşılaştığında uyaracak (veya hata yapacak) şekilde yapılandırılsaydı iyi olurdu, böylece bilerek uğraşmam gereken bir şey olduğunu anlayabilirdim.

Ve tamlık için, digraflar, simge olarak işlendikleri için çok daha az tehlikelidir, bu nedenle, bir dize değişmezinin içindeki bir digraph, bir digraph olarak yorumlanmayacaktır.

C / C ++ programlarında noktalama işaretleriyle çeşitli eğlenceler hakkında güzel bir eğitim için (kesinlikle saçımı çekmeme neden olacak bir trigraf hatası dahil), Herb Sutter'ın GOTW # 86 makalesine bir göz atın .


Zeyilname:

Görünüşe göre GCC, varsayılan olarak trigrafileri işlemeyecek (ve bunlar hakkında uyarıda bulunacak). Diğer bazı derleyiciler, trigraph desteğini kapatma seçeneklerine sahiptir (örneğin IBM'in). Microsoft, VS2008'de açıkça etkinleştirilmesi gereken (-Wall veya başka bir şey kullanılarak) bir uyarıyı (C4837) desteklemeye başladı.


C ile uyumluluk tek neden mi? Modern C ++ programlarında onlarla tanışmak mümkün mü?
Kirill V. Lyadvinsky

Evet, C ++ trigraphs ve digraphs da destekler.
Michael Burr

4
Hatırladığım kadarıyla, kullandığım en az bir derleyici (g ++?), Trigraph ve / veya digraph çevrilmeden önce açık bir komut satırı seçeneği gerektirir, aksi takdirde bir uyarı verilir ancak ikame olmaz.
KTC

1
@ Jla3ep - Şahsen trigraflara hiç ihtiyacım olmadı, ancak ne yazık ki derleyiciler onlarla birlikte kod işleyecek, bu yüzden bunlardan haberdar olmanız gerekiyor (yanlışlıkla kullanımı önlemek için). Ayrıca, başka bir yerden kod alırsanız, onların kasıtlı kullanımıyla karşılaşabilirsiniz, ancak bu son derece alışılmadık bir durum olacaktır. Sanırım 20+ yılda bir kasıtlı olarak kullanılan trigraphs ile karşılaştım (bu, bir IBM ana bilgisayarı için bir koddu).
Michael Burr

1
Trigraflar yorumlarda şaşırtıcı şeyler yapmak için genişletildiğinde gerçekten sinirlerimi bozuyor.
Joshua

23

Çocuklar bugün! :-)

Evet, IBM 3270 terminali gibi yabancı ekipman. 3270'de, hatırlıyorsam, küme telleri yok! Bir IBM mini / anabilgisayarına C yazmak istiyorsanız , her blok sınırı için sefil trigraphs kullanmak zorundaydınız . Neyse ki, bazı IBM mini bilgisayar olanaklarını taklit etmek için C dilinde yazılım yazmak zorunda kaldım , aslında Sistem / 36 üzerine C yazılımı yazmak değil .

"P" tuşunun yanına bakın:

tuş takımı

Hmmm. Söylemesi zor. "Satırbaşı" nın yanında fazladan bir düğme var ve bunu geriye doğru alabilirim: belki de eksik olan "[" / "]" çiftiydi. Her halükarda, bu klavye C yazmak zorunda kalırsan üzülmene neden olur.

Ayrıca, bu terminaller ASCII'yi değil, IBM'in "yerel" ana bilgisayar karakter seti olan EBCDIC'i gösterir (hatırlatma için teşekkürler, Pavel Minaev).

Öte yandan, GNU C kılavuzunun dediği gibi: "Bu beyin hasarına ihtiyacınız yok." Gcc derleyicisi bu "özelliği" varsayılan olarak devre dışı bırakır.


1
Klavyede bir sıfırlama düğmesi var. Bu harika! İlk önce dikkatimi çeken garip.
l46kok

11
EBCDIC makinesinde C ++ 17 kullanmak isteyenler nekrofili nedeniyle hapse atılmalıdır.
SF.

Platform hiçbir karakter olmadıkça hiç ISO646 dışındaki her uygulama bir şekilde C karakter kümesinde olmayan bir ters eğik çizgi veya başka herhangi bir karakter ya tanımlamak gerektiren yapılabilir, üç karakterli olan her canlı yapılabilir ki "meta" karakteri, Standart'taki ters eğik çizgiye yapılan tüm referansları "meta" ile değiştir ve ISO-646'da olmayan C karakter kümesinin herhangi bir üyesi için ters eğik çizgi / meta kaçışları eklensin mi?
supercat

22

Gönderen The C++ Programming LanguageSpecial Edition, sayfa 829

ASCII özel karakterler [, ], {, }, |, ve \ISO tarafından alfabetik olarak belirlenen karakter kümesi pozisyonlarını işgal eder. Çoğu Avrupa ulusal ISO-646 karakter setinde, bu pozisyonlar İngilizce alfabede bulunmayan harflerle doldurulur.

Ulusal karakterlerin gerçekten standart bir minimum karakter seti kullanılarak taşınabilir bir şekilde ifade edilmesine izin vermek için bir dizi trigraf sağlanmıştır. Bu, programların değişimi için yararlı olabilir, ancak insanların programları okumasını kolaylaştırmaz. Doğal olarak, bu sorunun uzun vadeli çözümü, C ++ programcılarının hem ana dillerini hem de C ++ 'yı iyi destekleyen ekipmanlara sahip olmalarıdır. Ne yazık ki, bu bazıları için uygun görünmüyor ve yeni ekipmanın piyasaya sürülmesi sinir bozucu derecede yavaş bir süreç olabilir.


8
"Yeni ekipmanın piyasaya sürülmesi sinir bozucu derecede yavaş bir süreç olabilir". Özellikle programlama dili özelliklerini standartlaştırmanın hızlı ve zahmetsiz süreciyle karşılaştırıldığında.
jforberg

4
Bu, klavye düzenleri için bir kludge ise, o zaman `İtalyanca ve diğer bazı klavye düzenlerinde eksik olan yazma için herhangi bir tetikleyici olmaması komik
badp

15

C ++ 'ın temel karakter kümesindeki bazı karakterlerden yoksun olan sistemlerde kullanım içindir. Söylemeye gerek yok, bu tür sistemler son derece nadirdir.


2
Bu, onları gerçek hayatta asla kullanmayacağım anlamına mı geliyor?
Kirill V. Lyadvinsky

1
hangi ülkede yaşıyorsun? Tüm diller için tüm klavyeler gerekli tuşlara sahip değildir.
David Thornley

2
Evet, ancak örneğin bir dize değişmezinde kodlandığında beklenmedik bir sonuca neden olması durumunda orada varolduğunun farkında olmanız gerekebilir.
CB Bailey

4
@David Thornley: Çoğu modern sistem, geleneksel yerde olmasalar veya yazmak için bir değiştirici dizisi gerektirseler bile C ++ 'nın tüm temel karakterlerini destekler. Trigrafların yalnızca, karakterin sistem karakter kümesinde gerçekten temsil edilemediği sistemlerde kaynak kodunda tutulması gerekir. Hala bu tür sistemlerin son derece nadir olduğunu düşünüyorum.
CB Bailey

9

C ++ 0x'de kaldırılmak üzere tetikleyiciler önerilmiştir. Bununla birlikte, onları destekleyen güçlü argümanlar var gibi görünüyor - bunu tartışan C ++ komite makalesi N2910'a bakın . Görünüşe göre, EBCDIC ihtiyaç duyulan önemli bir kaledir.


Evet, o "yabancı dil"! :-)
Roboprog

"Müşteri geri bildirimleriyle ilgili dahili bir anketin sonuçları" dışında pek bir şey söylemiyorlar, ama iyi.
EBCDIC'in

5

90'ların başlarında PL / 1 programlarını bir ana bilgisayardan bir bilgisayarda çalıştırılacak / derlenecek / hata ayıklanacak şekilde dönüştürmeye yardımcı olmak için kullanılan trigrafları gördüm.

Bir PL / I'den C'ye derleyici kullanarak PC'de PL / I düzenlemeyle uğraşıyorlardı ve küme parantezlerini desteklemeyen ana bilgisayara geri döndüklerinde kodun çalışmasını istediler. Gibi makro kullanabileceklerini önerdim

#def BEGIN {    
#def END }  

veya daha arkadaşça bir PL / I alternatifi olarak

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

ve gerçekten süslü olmak isterlerse deneyebilirlerdi

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

ve sonra program Pascal'da yazılmış gibi görünecektir. Bana sadece komik baktılar ve günün geri kalanında benimle konuşmadılar. Onları suçladığımı sanmıyorum. :)

Üç grafik değil, çabayı öldüren, platformlar arasındaki IO sistem farklılıklarıydı. Bilgisayarda dosya açmak ana bilgisayardan çok farklıydı ve aynı kodun her ikisinde de çalışmasını sağlamak için çok fazla kludges ortaya çıkarırdı.


PL / 1 = IBM'in C sürümü (aşağı yukarı). Yorumuma bakın: IBM terminallerinde '{' / '}' anahtarları yok :-( Aksi takdirde bunlardan birine C [++] yazmak zor.
Roboprog

3

Öncelikle, C standardı onları, bazı makinelerde tetikleyen karakterlerin varlığıyla ilgili sorunlar olduğunda, 1989'da tanıttığı için. C ++ standardı 1998'de yayınlandığında, trigrafilere olan ihtiyaç büyük değildi. C üzerinde bir siğildir; onlar da C ++ 'da bir siğildir. Onlara ihtiyaç vardı - özellikle İngilizce konuşulan dünyanın dışında - bu yüzden C'ye eklendiler.


1
IBM'in her zaman İngilizce konuşmadığından şüphelenmişimdir :-)
Roboprog

3

Bazı Avrupa klavyeleri, alışılmadık alfabetik karakterleri için tuşlara ihtiyaç duydukları için, ABD klavyelerinde bulunan tüm noktalama karakterlerine sahip değildir (yok mu?). Örneğin (bunu oluşturuyor), İsveç klavyesinde küme parantezinin olduğu yerde A halkası olacaktı.

Bu kullanıcıları barındırmak için, trigraphs, yalnızca en yaygın ASCII karakterlerini kullanarak noktalama işareti girmenin bir yoludur.


4
Trigraflar gerçekten veri girişi ile ilgili değildir (kodu oldukça okunamaz hale getirirler), daha çok gerekli karakterlere sahip olmayan sistemlerle ilgilidir. Bir sistem karakteri kaydedip görüntüleyebiliyorsa - trigraf benzeri bir tuş dizisinin yazılması gerekse bile - kaynakta trigraf dizisini korumamak çok daha kolay olacaktır.
CB Bailey

2

Çoğunlukla tarihsel nedenlerle oradalar. Günümüzde, çoğu dil için modern klavyelerin çoğu, tüm bu karakterlere erişime izin verir, ancak bu, bazı Avrupa klavyelerinde bir zamanlar bir sorundu. Trigrafların icat edilmesinin nedeni budur.

Ne için olduklarını bilmiyorsan, onları kullanmamalısın.

Yine de, yanlışlıkla ve istemeden kodunuzda bir tane kullanabileceğiniz için, bunların farkında olmak yine de iyidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.