รับความกว้างของขั้วใน C?


96

ฉันกำลังมองหาวิธีรับความกว้างเทอร์มินัลจากภายในโปรแกรม C ของฉัน สิ่งที่ฉันคิดต่อไปคือบางสิ่งตามแนวของ:

แต่ทุกครั้งที่ฉันพยายามที่จะได้รับ

วิธีนี้เป็นวิธีที่ดีที่สุดหรือมีวิธีที่ดีกว่านี้ ถ้าไม่ฉันจะทำงานนี้ได้อย่างไร

แก้ไข: รหัสคงที่คือ


1
ไม่มีคำตอบใดที่แนะนำถูกต้องเกินครึ่ง
Thomas Dickey

2
@ThomasDickey คำตอบของคุณอยู่ไหนแล้ว?
Alexis Wilke

คำตอบ:


132

คุณได้พิจารณาใช้getenv ()หรือไม่? ช่วยให้คุณได้รับตัวแปรสภาพแวดล้อมของระบบซึ่งมีคอลัมน์และเส้นเทอร์มินัล

หรือใช้วิธีการของคุณหากคุณต้องการดูว่าเคอร์เนลเห็นว่าเป็นขนาดเทอร์มินัล (ดีกว่าในกรณีที่มีการปรับขนาดเทอร์มินัล) คุณจะต้องใช้ TIOCGWINSZ ซึ่งตรงข้ามกับ TIOCGSIZE ของคุณดังนี้:

และรหัสเต็ม:


7
ใช่ แต่ความกว้างของคำไม่ได้เป็นตัวแปรด้านสิ่งแวดล้อมมันคงที่กับคำนั้น
austin

4
ไม่ได้ให้ขนาดเทอร์มินัลปัจจุบันแก่คุณหากมีคนปรับขนาดเทอร์มินัลระหว่างการทำงานของโปรแกรม
Chris Jester-Young

วิธีรับขนาดเป็นพิกเซล? ฉันใช้ws_xpixelและws_ypixelแต่มันพิมพ์แค่เลขศูนย์!
Debashish

1
@Debashish ขึ้นอยู่กับ. เช่น Linux ไม่รองรับฟิลด์เหล่านั้นเลย
melpomene

แม้ว่าเราจะเห็นตัวแปรLINESและCOLUMNSตัวแปรในสภาพแวดล้อม แต่ดูเหมือนจะไม่ถูกส่งออก จึงไม่สามารถเข้าถึงได้จากโปรแกรม C ของคุณ
Alexis Wilke

16

ตัวอย่างนี้มีความยาวเล็กน้อย แต่ฉันเชื่อว่าเป็นวิธีตรวจจับขนาดเทอร์มินัลแบบพกพามากที่สุด นอกจากนี้ยังจัดการปรับขนาดเหตุการณ์

ตามที่ tim และ rlbond แนะนำฉันใช้ ncurses รับประกันความเข้ากันได้ของเทอร์มินัลที่ดีขึ้นเมื่อเทียบกับการอ่านตัวแปรสภาพแวดล้อมโดยตรง


3
แต่การเรียกใช้ initscr และ endwin จากตัวจัดการสัญญาณนั้นปลอดภัยจริงหรือ? อย่างน้อยก็ไม่ได้อยู่ในรายการ API ที่ปลอดภัยของสัญญาณ async ในman 7 signal
nav

1
นั่นเป็นจุดที่ดี @nav ฉันไม่เคยคิดแบบนั้นมาก่อน! วิธีแก้ปัญหาที่ดีกว่าคือให้ตัวจัดการสัญญาณตั้งค่าสถานะแล้วดำเนินการที่เหลือในลูปหลักหรือไม่?
gamen

1
@gamen ใช่ว่าจะดีกว่า;) - การใช้ sigaction แทนสัญญาณก็จะดีกว่าเช่นกัน
Bodo Thiesen

ตัวแปรส่วนกลางของ COLS และ LINES เป็นอย่างไร
einpoklum

1
@AlexisWilke: รวมถึงOKและERR. "ใจดี" ของพวกเขาแค่ไหนที่ช่วยเติมเต็มช่องว่างในชีวิตของเรา :-(
einpoklum

12

จำเป็นต้องคอมไพล์ด้วย-ltermcap. มีข้อมูลที่เป็นประโยชน์อื่น ๆ อีกมากมายที่คุณสามารถหาได้จากการใช้ termcap ตรวจสอบคู่มือการใช้งาน termcap info termcapสำหรับรายละเอียดเพิ่มเติม


คุณสามารถรวบรวมด้วย -lcurses ได้เช่นกัน
Kambus

2
ฉันรู้ว่าความคิดเห็นนี้เกิดขึ้น 6 ปีหลังจากความจริง แต่โปรดอธิบายหมายเลขมหัศจรรย์ของคุณที่ 2048 ...
einpoklum

1
@einpoklum นี่ก็เกือบสามปีแล้ว แต่ยังไม่ชัดเจนว่าปี 2048 เป็นเพียงขนาดที่กำหนดเองสำหรับบัฟเฟอร์ที่ "น่าจะใหญ่พอ" สำหรับสตริงอินพุตใด ๆ ที่จะไปที่นั่น?
Roflcopter4

2
ที่จริงคำตอบนี้ทำให้สมมติฐานถูกต้องมากเกินไป
Thomas Dickey

1
สำหรับใครที่อยากรู้อยากเห็นขนาดบัฟเฟอร์ 2048 มีอธิบายไว้ในเอกสารTermcapของGNU ที่นี่: gnu.org/software/termutils/manual/termcap-1.3/html_mono/…นอกจากนี้ยังมีสิ่งอื่น ๆ อีกมากมายในนั้นผู้ที่อ่านโพสต์นี้อาจพบว่ามีประโยชน์ .

3

หากคุณติดตั้ง ncurses และกำลังใช้งานอยู่คุณสามารถใช้getmaxyx()เพื่อค้นหาขนาดของเทอร์มินัล


2
ใช่และโปรดทราบว่า Y มาก่อนแล้ว X
ดาเนียล

1

เพื่อเพิ่มคำตอบที่สมบูรณ์ยิ่งขึ้นสิ่งที่ฉันพบว่าใช้ได้ผลสำหรับฉันคือการใช้โซลูชันของ @John_T กับบิตบางส่วนที่เพิ่มเข้ามาจากRosetta Codeพร้อมกับการแก้ไขปัญหาบางอย่างเพื่อหาการอ้างอิง อาจไม่มีประสิทธิภาพเล็กน้อย แต่ด้วยการเขียนโปรแกรมอัจฉริยะคุณสามารถทำให้มันใช้งานได้และไม่ต้องเปิดไฟล์เทอร์มินัลตลอดเวลา

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

หากคุณไม่ได้ใช้TIOCGWINSZโปรดดูคำตอบแรกในแบบฟอร์มนี้https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/ https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/

Oh, และไม่ลืมที่จะfree()result


0

สมมติว่าคุณใช้ Linux ฉันคิดว่าคุณต้องการใช้ไลบรารีncursesแทน ฉันค่อนข้างมั่นใจว่าสิ่งของ ttysize ที่คุณมีไม่ได้อยู่ใน stdlib


ดีสิ่งที่ฉันทำไม่คุ้มค่าที่จะตั้งค่า ncurses สำหรับ
austin

1
ncurses ไม่ได้อยู่ใน stdlib เช่นกัน ทั้งสองแบบเป็นมาตรฐานใน POSIX แต่ioctlวิธีนี้ง่ายกว่าและสะอาดกว่าเพราะคุณไม่ต้องเริ่มต้นคำสาป ฯลฯ
Gandaro

0

ดังนั้นไม่แนะนำคำตอบที่นี่ แต่:

linux-pc:~/scratch$ echo $LINES

49

linux-pc:~/scratch$ printenv | grep LINES

linux-pc:~/scratch$

โอเคและฉันสังเกตว่าถ้าฉันปรับขนาดเทอร์มินัล GNOME ตัวแปร LINES และ COLUMNS จะเป็นไปตามนั้น

ดูเหมือนว่าเทอร์มินัล GNOME กำลังสร้างตัวแปรสภาพแวดล้อมเหล่านี้เอง?


2
และแน่นอนว่ามันไม่ได้ส่งผ่านไปยังรหัส C getenv ("LINES") คืนค่า NULL
Scott Franco

ตัวแปรเป็นสิ่งที่มีเปลือกไม่ใช่สิ่งปลายทาง
melpomene

-1

นี่คือฟังก์ชั่นที่เรียกใช้สิ่งตัวแปรสภาพแวดล้อมที่แนะนำแล้ว:


12
ตัวแปรสภาพแวดล้อมไม่น่าเชื่อถือ ค่าเหล่านี้ถูกกำหนดโดยเชลล์ดังนั้นจึงไม่รับประกันว่าจะมีอยู่จริง นอกจากนี้จะไม่อัปเดตหากผู้ใช้เปลี่ยนขนาดเทอร์มินัล
Juliano

1
เชลล์จำนวนมากสร้างตัวจัดการสำหรับSIGWINCHสัญญาณดังนั้นจึงสามารถอัปเดตตัวแปรให้ทันสมัยอยู่เสมอ (จำเป็นต้องใช้ดังนั้นจึงจะทำการตัดบรรทัดที่เหมาะสมในตัวแก้ไขอินพุต)
Barmar

5
พวกเขาอาจทำได้ดี แต่สภาพแวดล้อมของโปรแกรมจะไม่ได้รับการอัปเดตเมื่อทำงานอยู่
Functino

แน่นอนว่าโค้ดนั้นมีแนวโน้มที่จะผิดพลาดอย่างมากเนื่องจากคุณไม่ได้ทดสอบว่าgetenv()ส่งคืนค่า NULL หรือไม่และทำในเทอร์มินัล Linux ของฉัน (เนื่องจากตัวแปรเหล่านั้นไม่ได้ถูกส่งออก) แม้ว่าเชลล์จะอัปเดตตัวแปรเหล่านั้นคุณจะไม่เห็น เปลี่ยนแปลงในขณะที่โปรแกรมของคุณกำลังทำงาน (ไม่ใช่โดยที่คุณไม่มีตัวSIGWINCHจัดการของคุณเอง)
Alexis Wilke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.