การปฏิบัติที่ดีที่สุดสำหรับการใช้งานการพิมพ์ / ความช่วยเหลือ (- ความช่วยเหลือ) คืออะไร?


13

เมื่อเขียนเครื่องมือสำหรับ CLI ของ UNIX ฉันจะทำให้โปรแกรมพิมพ์วิธีใช้และ / หรือการใช้งานได้อย่างไร

ฉันมักจะใช้fprintf(stderr, "help text here");แต่มีหลายปัญหาด้วยกัน

  • stderrครั้งแรกผมไม่แน่ใจว่าไม่ว่าฉันควรใช้ ตกลงหรือฉันควรใช้stdout?
  • อย่างที่คุณสามารถจินตนาการได้ข้อความช่วยเหลือค่อนข้างยาวขึ้นอยู่กับจำนวนตัวเลือกของเครื่องมือ ตอนนี้ฉันมักจะใส่หลาย ๆ อย่าง"strings like that\n"ในพารามิเตอร์ที่สอง อย่างไรก็ตามสิ่งนี้เติมรหัสต้นฉบับของฉันด้วยข้อความช่วยเหลือห้าสิบรายการขึ้นไป มันไม่สามารถจัดการได้ง่ายเลย ฉันควรทำอย่างไรดี
  • เมื่อเครื่องมือไม่ได้เขียนในภาษา C หรือภาษา C ฉันมักจะใช้ที่นี่ docsที่เป็นไปได้ (ส่วนใหญ่เด่นชัดด้วย Perl) ฉันไม่สามารถใช้สิ่งนั้นใน C แต่มีอะไรแบบนั้นที่ฉันสามารถใช้ได้หรือไม่?
  • ฉันกำลังพิจารณาที่จะวางมันไว้headerfile.hข้างใน a #define HELP "help text here"ฉันไม่เคยเห็นมันมาในป่าไม่รู้ว่าฉันควรใช้มันหรือไม่

เป็นการดีที่ฉันสามารถใส่ข้อความในไฟล์ภายนอกและรวมไว้ ใช้#includeสำหรับสิ่งที่ดูเหมือนว่าผิด ฉันควรทำอย่างไร

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


1
มีอะไรที่แย่ประมาณ 50 บรรทัดในซอร์สโค้ดของคุณ? เพียงวางไว้ที่ส่วนท้าย ไม่ใช่ว่าคุณจะต้องยุ่งกับมันเป็นประจำ
whatsisname

2
@whatsisname การใช้งานช่วยสำหรับปกติและ longopts ฉันมีสตริงประมาณ 200 บรรทัดในโค้ด นอกเหนือจากนั้นผมก็ไม่คิดว่านี่เป็นวิธีที่ดีที่สุด ฯลฯ นอกจากจะต้องเป็นวิธีที่มีประสิทธิภาพมากขึ้นของการวางความช่วยเหลือในตำรา ฯลฯ
Polemon

คำตอบ:


8

สร้างแรงบันดาลใจให้ตัวเองจากการทำงานภายในแพลตฟอร์มเป้าหมายของคุณ

ดูซอร์สโค้ดของ BSD ตัวอย่างเช่นนี่คือ:

  • usage(void)สำหรับ/usr/bin/unameเครื่องมือของ NetBSD [ แหล่งที่มา ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)สำหรับ NetBSD's /usr/bin/telnet[ แหล่งที่มา ]

  • usage(void)สำหรับ OpenBSD's /bin/ls[ source ]

ลองดูทางเลือกอื่น

และตัดสินใจด้วยตัวเองว่าพวกเขาจะดีขึ้นหรือแย่ลง คุณสามารถใช้ Google CodeSearch เพื่อค้นหาคนอื่น ๆ เช่น:

อย่างที่คุณเห็นสไตล์ที่แตกต่างระหว่างเครื่องมือเหล่านี้กับระบบที่รวมอยู่ในรายการ BSD ด้านบน มันไม่ได้หมายความว่าคุณต้องทำตามอย่างใดอย่างหนึ่ง แต่โดยปกติจะเป็นการดีที่จะมองไปรอบ ๆ และหาทางแก้ไขที่สอดคล้องกัน

โซลูชันที่ไม่ได้มาตรฐานสำหรับความช่วยเหลือ 50 บรรทัด ...

หากคุณไม่ต้องการหลีกเลี่ยงข้อความ 50 บรรทัดคุณสามารถอ่านความช่วยเหลือจากไฟล์ข้อความ (ในรูปแบบข้อความธรรมดาหรืออาจแยกวิเคราะห์manแหล่งข้อมูลโดยตรงหากคุณสร้างขึ้นมา) ฉันพบว่าวิธีที่ค่อนข้างหรูหรา (อย่างที่คุณสามารถค้นหาเอกสารข้อความ) แต่สำหรับโปรแกรมระบบหลักที่จะทำให้พวกเขาไม่ปลอดภัยโดยเนื้อแท้และแนะนำจุดของความล้มเหลว คนอื่น ๆ จะเถียงว่ามันหนักสำหรับข้อความusageหรือhelpแต่มันไม่เหมือนสิ่งเหล่านี้เรียกว่าในลูปแน่น ...

หากมีข้อสงสัยให้ติดตามยักษ์ใหญ่


9

ฉันใช้stdoutเพราะความช่วยเหลือไม่ใช่ข้อผิดพลาด

หากนี่เป็นความช่วยเหลือที่ยาวนานใน C ฉันพยายามเลียนแบบเอกสารที่นี่:

printf("This is the help for MyWonderfulApp\n"
       "Options are:\n"
       "    --help: display what you are reading now\n"
       "    --quiet: output nothing\n");

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


แต่ความช่วยเหลือไม่จำเป็นต้องเป็นมาตรฐานผลลัพธ์ที่พึงประสงค์ใช่ไหม แล้วไงstdlogล่ะ
greyfade

@greyfade: เป็นstdlogมาตรฐาน C หรือไม่
mouviciel

@mouviciel: ... ฉันคิดว่ามันเป็น ฉันเดาว่าไม่. C ++ มีกระแสมาตรฐานที่เกี่ยวข้องกัน ( cin, cout, cerrและclog) ดังนั้นผมคิดว่าผมคิดว่าstdlogอยู่ในมาตรฐานซี ความผิดฉันเอง.
greyfade

2

ถ้าฉันเป็นคุณฉันต้องการเพียงแค่เปิดแหล่งที่มาของgrep, tail, cat, your_other_favorite_unix_shell_commandเพื่อดูว่ามันทำมี ฉันค่อนข้างมั่นใจว่าวิธีการของพวกเขานั้นค่อนข้างที่จะคิดออกและสามารถรักษาไว้ได้โดยคนจำนวนมาก

เกี่ยวกับหรือstderr stdoutมันง่ายจริงๆถ้ามีข้อผิดพลาด - เขียนไปstderrถ้าเป็นข้อมูลเพียง stdout- ตัวอย่างเช่นหากฉันเรียกใช้เครื่องมือของคุณด้วยตัวเลือกที่ไม่ถูกต้องคุณอาจต้องการแสดงข้อผิดพลาดกล่าวว่าเครื่องมือUse --help for usageนี้อยู่ในstderrนั้น ถ้าฉันเรียกใช้เครื่องมือของคุณด้วยการเลือกที่ถูกต้อง--help, stdoutการใช้งานโปรด

หากการตั้งค่าของคุณไม่ให้มีสายช่วยเหลือยาวใกล้รหัสของคุณ #define ในไฟล์ส่วนหัวนั้นดีมาก แต่เป็นความชอบส่วนตัว หากฉันต้องอ่านรหัสของเครื่องมือบรรทัดคำสั่งฉันต้องการให้สตริงช่วยเหลืออยู่ในไฟล์ที่จัดการตัวเลือกที่ผู้ใช้จัดหา


2
ไม่ตอบคำถามของเขา
Mavrik

อืมเกิดอะไรขึ้นกับการลบ? เพื่ออะไร?
devmiles.com

@Mavrik: ย่อหน้าแรกทำ
haylem

1

ฉันใช้ไลบรารีgnu getopts ยกตัวอย่างเช่นด้วยความช่วยเหลือให้ดูนี้ตัวอย่างโครงการโดยเฉพาะวิธีการหลักที่ด้านล่างของparser.y

เนื่องจากมันถูกมัดด้วยเครื่องหมายปีกกาเครื่องมือแก้ไขเสียงเรียกเข้าที่ฉันใช้สามารถพับเส้นเข้าหากันได้และฉันไม่สังเกตแม้แต่ตอนที่ไม่ต้องการ


1

หากฉันใช้ C หรือไม่ต้องการที่จะขึ้นอยู่กับห้องสมุด Boost แล้วฉันติดกับ getoptGNU มิฉะนั้นฉันชอบตัวเลือก Boost Programที่พิมพ์ช่วยเหลือโดยอัตโนมัติ

ฉันยังพิจารณาการคาดเดาตัวเลือกที่ถูกต้องซึ่งเป็นหนึ่งในแนวปฏิบัติที่ดีที่สุดเมื่อพูดถึงการจัดการตัวเลือก ฉันเรียนรู้จาก Git และตอนนี้ใช้เหมือนกันในโครงการของฉัน โดยทั่วไปจะใช้ระยะทาง Damerau – Levenshtein เพื่อพิมพ์การจับคู่ที่ดีที่สุดหากผู้ใช้ป้อนตัวเลือกบรรทัดคำสั่งที่ไม่รู้จัก

ฉันเขียนบทความเล็กน้อยเกี่ยวกับเรื่องนี้ที่คุณสามารถใช้เป็นตัวอย่าง

หวังว่าจะช่วย :)


1

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

จากนั้นคุณสามารถใช้สคริปต์sedต่อไปนี้เพื่อแปลงไฟล์ข้อความนั้นเป็นไฟล์ส่วนหัว C ที่ถูกกฎหมาย:

s/\"/\\\"/g
s/$/\\n"/
s/^/"/
1i\
const char *helpStr = 
$a\
;

จากนั้นเมื่อ#include -ing ไฟล์ส่วนหัวของคุณลงในซอร์สโค้ดคุณสามารถเขียนข้อความโดยใช้

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