วัตถุประสงค์ของลำดับ Trigraph ใน C ++?


128

ตามมาตรฐาน C ++ '03 2.3 / 1:

ก่อนที่การประมวลผลอื่น ๆ จะเกิดขึ้นการเกิดขึ้นของหนึ่งในลำดับต่อไปนี้ของอักขระสามตัวต่อไปนี้ ("ลำดับตรีโกณมิติ") จะถูกแทนที่ด้วยอักขระเดี่ยวที่ระบุในตารางที่ 1

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

ในชีวิตจริงนั่นหมายความว่ารหัสprintf( "What??!\n" );นั้นจะทำให้เกิดการพิมพ์What|เนื่องจาก??!เป็นลำดับตรีโกณมิติที่ถูกแทนที่ด้วย|อักขระ

คำถามของฉันคือจุดประสงค์ของการใช้ Trigraphs คืออะไร? มีประโยชน์ในทางปฏิบัติของการใช้ตรีโกณมิติหรือไม่?

UPD : ในคำตอบถูกกล่าวถึงว่าแป้นพิมพ์ในยุโรปบางตัวไม่มีอักขระเครื่องหมายวรรคตอนทั้งหมดดังนั้นโปรแกรมเมอร์ที่ไม่ใช่ชาวสหรัฐฯจึงต้องใช้ทริกเกอร์ในชีวิตประจำวัน?

UPD2 : Visual Studio 2010 ได้ปิดการสนับสนุนทริกเกอร์โดยค่าเริ่มต้น


เครื่องหมายวรรคตอนบางส่วนยากที่จะเข้าถึงบนแป้นพิมพ์ยุโรป (จนถึงจุดที่โปรแกรมเมอร์บางคนใช้เค้าโครงของสหรัฐอเมริกาเพื่อพิมพ์ได้เร็วขึ้น) ยังไม่เห็นเครื่องหมายวรรคตอนที่หายไปโดยสิ้นเชิง - อาจเป็นภาษาสลาฟ?
peterchen

2
อาจเกิดขึ้นที่เทอร์มินัลและ / หรือเวอร์ชวลไลเซชั่นบางตัวไม่อนุญาตให้คุณเข้าถึงอักขระบางตัวได้อย่างง่ายดาย จากประสบการณ์ของฉันผู้กระทำความผิดหลักคือหนอนตัวหนอน
Francesco

1
พิมพ์สิ่งนี้บนแป้นพิมพ์ DE-deadkeys ของฉัน # คือปุ่มที่อยู่ถัดจากการส่งคืน \ คือ "AltGr" + "ß" (ถัดจาก 0), ^ คือ "^" + "^" (เนื่องจากปุ่มปิดตายถัดจาก 1) , [คือ "AltGr" + "8",] คือ "AltGr" + "9", | คือ "AltGr" + "<", {คือ "AltGr" + "7",} คือ "AltGr" + "0" และ ~ คือ "~" + "~" (เนื่องจากมี deadkeys อยู่เหนือ #) จึงไม่ใช่เรื่องใหญ่จริงๆ นิ้วของฉันเหมือนพิมพ์ชุดค่าผสมเหล่านี้ด้วยตัวเอง :-D
nonchip

1
ฉันคิดว่าเป็นเรื่องปกติที่จะมีรูปแบบแป้นพิมพ์สองแบบและสลับไปตามงานที่ฉันทำบนคอมพิวเตอร์ เป็นวิธีที่ใช้กันทั่วไปในภูมิภาคยุโรปกลาง มันค่อนข้างน่าขนลุกที่จะใช้ทริกเกอร์เหล่านี้ ฉันจะลงคะแนนให้ลบสิ่งนี้ออกจากมาตรฐาน
VX

คำตอบ:


98

คำถามนี้ (เกี่ยวกับ digraphs ที่เกี่ยวข้องอย่างใกล้ชิด)มีคำตอบ

มันทำให้เกิดความจริงที่ว่าชุดอักขระ ISO 646 ไม่มีอักขระทั้งหมดของไวยากรณ์ C ดังนั้นจึงมีบางระบบที่มีคีย์บอร์ดและจอแสดงผลที่ไม่สามารถจัดการกับอักขระได้ (แม้ว่าฉันคิดว่าสิ่งเหล่านี้ค่อนข้างหายาก ในปัจจุบัน)

โดยทั่วไปคุณไม่จำเป็นต้องใช้ แต่คุณจำเป็นต้องรู้เกี่ยวกับปัญหาที่คุณพบ Trigraphs เป็นสาเหตุที่ทำให้?อักขระ "" มีลำดับ Escape:

'\?'

ดังนั้นสองสามวิธีที่คุณสามารถหลีกเลี่ยงปัญหาตัวอย่างของคุณคือ:

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

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

แต่คุณต้องจำไว้ว่าเมื่อคุณพิมพ์ "?" ทั้งสอง ตัวละครที่คุณอาจกำลังเริ่มทริกเกอร์ (และแน่นอนว่ามันไม่เคยเป็นอย่างที่ฉันคิด)

ในทางปฏิบัติ Trigraph และ Digraphs เป็นสิ่งที่ฉันไม่กังวลเลยในแต่ละวัน แต่คุณควรตระหนักถึงพวกเขาเพราะทุกๆสองปีคุณจะพบกับข้อบกพร่องที่เกี่ยวข้องกับพวกเขา (และคุณจะใช้เวลาที่เหลือทั้งวันเพื่อสาปแช่งการมีอยู่ของพวกเขา) คงจะดีไม่น้อยหากคอมไพเลอร์สามารถกำหนดค่าให้เตือน (หรือข้อผิดพลาด) เมื่อเจอทริกกราฟหรือไดกราฟดังนั้นฉันจะได้รู้ว่าฉันมีบางอย่างที่ควรจัดการอย่างรู้เท่าทัน

และเพื่อความสมบูรณ์ digraphs จะมีอันตรายน้อยกว่ามากเนื่องจากได้รับการประมวลผลเป็นโทเค็นดังนั้น digraph ภายในตัวอักษรสตริงจะไม่ถูกตีความว่าเป็น digraph

สำหรับการศึกษาที่ดีในความสนุกสนานต่างๆที่มีเครื่องหมายวรรคตอนใน C / C ++ โปรแกรม (รวมถึงข้อผิดพลาดที่จะ trigraph defintinely ได้ฉันดึงผมออก) จะดูที่สมุนไพรซัทเทอ GOTW # 86 บทความ


ภาคผนวก:

ดูเหมือนว่า GCC จะไม่ประมวลผล (และจะเตือนเกี่ยวกับ) ทริกเกอร์ตามค่าเริ่มต้น คอมไพเลอร์อื่น ๆ บางตัวมีตัวเลือกในการปิดการสนับสนุนทริกเกอร์ (เช่นของ IBM) Microsoft เริ่มสนับสนุนคำเตือน (C4837) ใน VS2008 ที่ต้องเปิดใช้งานอย่างชัดเจน (โดยใช้ -Wall หรือบางอย่าง)


ความเข้ากันได้กับ C เป็นเหตุผลเดียว? เป็นไปได้หรือไม่ที่จะตอบสนองพวกเขาในโปรแกรม C ++ สมัยใหม่
Kirill V. Lyadvinsky

ใช่ C ++ รองรับทริกกราฟและไดกราฟเช่นกัน
Michael Burr

4
อย่างที่ฉันจำได้ว่าคอมไพเลอร์อย่างน้อยหนึ่งตัวที่ฉันเคยใช้ (g ++?) ต้องการตัวเลือกบรรทัดคำสั่งที่ชัดเจนก่อนที่จะแปลทริกกราฟและหรือไดกราฟมิฉะนั้นจะได้รับคำเตือน แต่จะไม่มีการแทนที่
เคทีซี

1
@ Jla3ep - โดยส่วนตัวแล้วฉันไม่เคยมีความจำเป็นในการเรียกใช้ทริกเกอร์ แต่น่าเสียดายที่คอมไพเลอร์จะประมวลผลโค้ดกับพวกเขาดังนั้นคุณต้องระวังพวกเขา (เพื่อหลีกเลี่ยงการใช้โดยไม่ได้ตั้งใจ) นอกจากนี้หากคุณได้รับรหัสจากที่อื่นคุณอาจพบว่ามีการใช้งานโดยเจตนา แต่นั่นจะผิดปกติอย่างยิ่ง ฉันคิดว่าฉันพบว่ามีการใช้ทริกเกอร์โดยเจตนาหนึ่งครั้งในรอบ 20 ปีขึ้นไป (เป็นรหัสสำหรับเมนเฟรมของ IBM)
Michael Burr

1
มันทำให้ฉันหงุดหงิดเมื่อมีการขยายทริกเกอร์ในความคิดเห็นเพื่อทำสิ่งที่น่าประหลาดใจ
Joshua

23

เด็ก ๆ วันนี้! :-)

ใช่อุปกรณ์แปลกปลอมเช่นเทอร์มินัล IBM 3270 3270 มีถ้าจำไม่ผิดวงเล็บปีกกา! หากคุณต้องการเขียน C บนมินิ / เมนเฟรมของ IBM คุณต้องใช้ทริกเกอร์ที่เลวร้ายสำหรับทุกขอบเขตบล็อก โชคดีที่ฉันต้องเขียนซอฟต์แวร์ในภาษา C เพื่อเลียนแบบสิ่งอำนวยความสะดวกมินิคอมพิวเตอร์ของ IBM เท่านั้นไม่ใช่เขียนซอฟต์แวร์ C บน System / 36

ดูถัดจากคีย์ "P":

แป้นพิมพ์

อืมม ยากที่จะบอก มีปุ่มพิเศษถัดจาก "carriage return" และฉันอาจจะให้มันถอยหลังอาจจะเป็นคู่ "[" / "]" ที่หายไป ไม่ว่าในกรณีใดแป้นพิมพ์นี้จะทำให้คุณเศร้าถ้าคุณต้องเขียน C

นอกจากนี้เทอร์มินัลเหล่านี้ยังแสดง EBCDIC ซึ่งเป็นชุดอักขระเมนเฟรม "เนทีฟ" ของ IBM ไม่ใช่ ASCII (ขอบคุณ Pavel Minaev สำหรับการแจ้งเตือน)

ในทางกลับกันเช่นเดียวกับคู่มือ GNU C กล่าวว่า: "คุณไม่ต้องการความเสียหายของสมองนี้" คอมไพเลอร์ gcc ทำให้ "คุณลักษณะ" นี้ปิดใช้งานโดยค่าเริ่มต้น


1
มีปุ่มรีเซ็ตบนแป้นพิมพ์ ที่น่ากลัว! แปลกที่ดึงดูดความสนใจของฉันก่อน
l46kok

11
ใครก็ตามที่ต้องการใช้ C ++ 17 บนเครื่อง EBCDIC ควรติดคุกเนื่องจากเนโครฟิเลีย
SF.

เว้นแต่ว่าแพลตฟอร์มจะไม่มีอักขระใดเลยนอกจากใน ISO646 ไม่สามารถทำทุกอย่างที่สามารถทำได้ด้วยทริกเกอร์ทำได้โดยกำหนดให้ทุกการใช้งานกำหนดแบ็กสแลชหรืออักขระอื่นใดที่ไม่ได้อยู่ในชุดอักขระ C เป็น a อักขระ "meta" แทนที่การอ้างอิงแบ็กสแลชทั้งหมดในมาตรฐานด้วย "เมตา" และเพิ่มแบ็กสแลช / เมตาหนีสำหรับสมาชิกของชุดอักขระ C ที่ไม่อยู่ใน ISO-646?
supercat

22

จากThe C++ Programming LanguageSpecial Edition หน้า 829

อักขระ ASCII พิเศษ[, ], {, }, |และ\ครองตำแหน่งตัวละครชุดกำหนดให้เป็นตัวอักษรโดย ISO ในชุดอักขระ ISO-646 ประจำชาติของยุโรปตำแหน่งเหล่านี้ถูกครอบครองโดยตัวอักษรที่ไม่พบในตัวอักษรภาษาอังกฤษ

ชุดของทริกเกอร์มีไว้เพื่อให้สามารถแสดงอักขระประจำชาติได้ในแบบพกพาโดยใช้ชุดอักขระขั้นต่ำมาตรฐานอย่างแท้จริง สิ่งนี้มีประโยชน์สำหรับการแลกเปลี่ยนโปรแกรม แต่ไม่ได้ทำให้คนอ่านโปรแกรมง่ายขึ้น โดยธรรมชาติแล้ววิธีแก้ปัญหาในระยะยาวสำหรับโปรแกรมเมอร์ C ++ จะได้รับอุปกรณ์ที่รองรับทั้งภาษาแม่และ C ++ ได้ดี น่าเสียดายที่สิ่งนี้ดูเหมือนจะเป็นไปไม่ได้สำหรับบางคนและการเปิดตัวอุปกรณ์ใหม่อาจเป็นกระบวนการที่ช้าจนน่าหงุดหงิด


8
"การเปิดตัวอุปกรณ์ใหม่อาจเป็นกระบวนการที่ช้าจนน่าหงุดหงิด" โดยเฉพาะอย่างยิ่งเมื่อเทียบกับกระบวนการที่รวดเร็วและไม่เจ็บปวดในการกำหนดคุณสมบัติภาษาโปรแกรมมาตรฐาน
jforberg

4
หากนี่เป็น kludge สำหรับรูปแบบแป้นพิมพ์ก็น่าตลกที่ไม่มีท`
ริกเกอร์

15

ใช้สำหรับระบบที่ไม่มีอักขระบางตัวในชุดอักขระพื้นฐานของ C ++ ไม่จำเป็นต้องพูดว่าระบบดังกล่าวหายากเหลือเกิน


2
นั่นหมายความว่าฉันจะไม่ใช้มันในชีวิตจริงเหรอ?
Kirill V. Lyadvinsky

1
คุณอาศัยอยู่ในประเทศอะไร? แป้นพิมพ์บางตัวสำหรับบางภาษาอาจไม่มีคีย์ที่จำเป็น
David Thornley

2
ใช่ แต่คุณอาจต้องระวังว่ามีอยู่ในกรณีที่สิ่งหนึ่งทำให้เกิดผลลัพธ์ที่ไม่คาดคิดเมื่อใส่เข้าไปในตัวอักษรสตริง
CB Bailey

4
@David Thornley: ระบบที่ทันสมัยส่วนใหญ่รองรับอักขระพื้นฐานทั้งหมดของ C ++ แม้ว่าจะไม่ได้อยู่ในตำแหน่งเดิมหรือต้องการลำดับตัวปรับแต่งในการพิมพ์ ทริกเกอร์จำเป็นเท่านั้นที่จะคงไว้ในซอร์สโค้ดบนระบบที่ไม่สามารถแสดงอักขระในชุดอักขระของระบบได้ ฉันยังคงยืนยันว่าระบบดังกล่าวหายากเหลือเกิน
CB Bailey

9

มีการเสนอ Trigraphs สำหรับการลบใน C ++ 0x ที่กล่าวว่ายังคงมีข้อโต้แย้งที่ชัดเจนในการสนับสนุนพวกเขา - ดูเอกสาร C ++ N2910ซึ่งกล่าวถึงเรื่องนี้ เห็นได้ชัดว่า EBCDIC เป็นฐานที่มั่นสำคัญแห่งหนึ่งที่พวกเขาต้องการ


ใช่ว่า "ภาษาต่างดาว"! :-)
Roboprog

พวกเขาไม่ได้พูดอะไรมากนอกจาก "ผลจากการสำรวจความคิดเห็นของลูกค้าภายใน" แต่ก็โอเค ฉันแปลกใจที่ EBCDIC ยังคงมีการใช้อย่างแพร่หลาย (และระบบเหล่านี้คาดว่าจะใช้คอมไพเลอร์ C ++ 0x)
peterchen

5

ฉันเคยเห็นทริกเกอร์ที่ใช้ในช่วงต้นยุค 90 เพื่อช่วยแปลงโปรแกรม PL / 1 จากเมนเฟรมเพื่อเรียกใช้ / คอมไพล์ / ดีบักบนพีซี

พวกเขาขลุกอยู่กับการแก้ไข PL / I บนพีซีโดยใช้คอมไพเลอร์ PL / I to C และพวกเขาต้องการให้โค้ดทำงานเมื่อย้ายกลับไปที่เมนเฟรมซึ่งไม่รองรับเครื่องหมายปีกกา ฉันแนะนำว่าพวกเขาสามารถใช้มาโครเช่น

#def BEGIN {    
#def END }  

หรือเป็นทางเลือก PL / I ที่เป็นมิตรกว่า

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

และถ้าพวกเขาอยากจะแฟนซีจริงๆก็ลองดู

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

จากนั้นโปรแกรมจะดูเหมือนเขียนด้วยภาษาปาสคาล พวกเขามองฉันตลก ๆ และจะไม่พูดกับฉันตลอดทั้งวัน ฉันไม่คิดว่าฉันตำหนิพวกเขา :)

สิ่งที่ฆ่าความพยายามที่ไม่ใช่ไตรกราฟมันคือความแตกต่างของระบบ IO ระหว่างแพลตฟอร์ม การเปิดไฟล์บนพีซีนั้นแตกต่างจากเมนเฟรมมากซึ่งจะแนะนำวิธีการที่มี kludges มากเกินไปเพื่อให้โค้ดเดียวกันทำงานบนทั้งสองอย่าง


PL / 1 = เวอร์ชัน C ของ IBM (มากหรือน้อย) ดูความคิดเห็นของฉัน: เทอร์มินัล IBM ไม่มีคีย์ '{' / '}' :-( ยากที่จะเขียน C [++] ในหนึ่งในนั้นมิฉะนั้น
Roboprog

3

ส่วนใหญ่เป็นเพราะมาตรฐาน C นำพวกเขากลับมาในปี 1989 เมื่อมีปัญหาเกี่ยวกับการมีอยู่ของตัวละครที่ทริกเกอร์แผนที่ไปยังเครื่องบางเครื่อง เมื่อถึงเวลาที่เผยแพร่มาตรฐาน C ++ ในปี 1998 ความจำเป็นในการใช้ Trigraphs นั้นไม่มาก พวกเขาเป็นหูดที่ C; พวกเขาเป็นเพียงหูดใน C ++ มีความจำเป็นสำหรับพวกเขา - โดยเฉพาะนอกโลกที่พูดภาษาอังกฤษ - นั่นคือเหตุผลที่พวกเขาถูกเพิ่มเข้าไปใน C


1
ฉันสงสัยมาตลอดว่า IBM ไม่พูดภาษาอังกฤษ :-)
Roboprog

3

แป้นพิมพ์แบบยุโรปบางตัวไม่มี (ไม่มี?) มีอักขระเครื่องหมายวรรคตอนทั้งหมดที่แป้นพิมพ์ของสหรัฐฯมีเนื่องจากต้องการแป้นสำหรับอักขระที่เป็นตัวอักษรที่ผิดปกติ ตัวอย่างเช่น (สร้างสิ่งนี้ขึ้นมา) แป้นพิมพ์ภาษาสวีเดนจะมีวงแหวน A-ring ซึ่งเป็นวงเล็บปีกกา

เพื่อรองรับผู้ใช้เหล่านั้นทริกเกอร์เป็นวิธีป้อนเครื่องหมายวรรคตอนโดยใช้อักขระ ASCII ที่พบบ่อยที่สุดเท่านั้น


4
Trigraphs ไม่ได้เกี่ยวกับการป้อนข้อมูล (ทำให้โค้ดไม่สามารถอ่านได้) แต่เป็นข้อมูลเพิ่มเติมเกี่ยวกับระบบที่ไม่มีอักขระที่ต้องการ หากระบบสามารถบันทึกและแสดงอักขระได้แม้ว่าจะต้องพิมพ์ทริกกราฟเช่นลำดับคีย์ก็ตามจะเป็นการง่ายกว่ามากที่จะไม่เก็บลำดับทริกกราฟไว้ในแหล่งที่มา
CB Bailey

2

พวกเขาส่วนใหญ่มีเหตุผลทางประวัติศาสตร์ ปัจจุบันแป้นพิมพ์สมัยใหม่ส่วนใหญ่สำหรับภาษาส่วนใหญ่อนุญาตให้เข้าถึงอักขระเหล่านั้นได้ทั้งหมด แต่สิ่งนี้เคยเป็นปัญหากับแป้นพิมพ์ยุโรปบางรุ่น นี่คือเหตุผลที่มีการคิดค้นทริกกราฟ

หากคุณไม่รู้ว่ามีไว้เพื่ออะไรคุณไม่ควรใช้

อย่างไรก็ตามยังดีที่ต้องระวังเนื่องจากคุณอาจใช้รหัสในรหัสของคุณโดยบังเอิญและไม่ได้ตั้งใจ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.