2009-06-21 10 views
75

मैं अपने सी प्रोग्राम के भीतर से टर्मिनल चौड़ाई प्राप्त करने का एक तरीका ढूंढ रहा हूं। की तर्ज पर कुछ क्या मैं के साथ आते रहते है:सी में टर्मिनल चौड़ाई प्राप्त करना?

#include <sys/ioctl.h> 
#include <stdio.h> 

int main (void) 
{ 
    struct ttysize ts; 
    ioctl(0, TIOCGSIZE, &ts); 

    printf ("lines %d\n", ts.ts_lines); 
    printf ("columns %d\n", ts.ts_cols); 
} 

लेकिन हर मैं कोशिश मुझे मिलता है कि

[email protected]:~$ gcc test.c -o test 
test.c: In function ‘main’: 
test.c:6: error: storage size of ‘ts’ isn’t known 
test.c:7: error: ‘TIOCGSIZE’ undeclared (first use in this function) 
test.c:7: error: (Each undeclared identifier is reported only once 
test.c:7: error: for each function it appears in.) 

इस यह करने के लिए सबसे अच्छा तरीका है, या वहाँ एक बेहतर तरीका है? यदि नहीं, तो मैं इसे काम करने के लिए कैसे प्राप्त कर सकता हूं?

संपादित करें: निर्धारित कोड

#include <sys/ioctl.h> 
#include <stdio.h> 

int main (void) 
{ 
    struct winsize w; 
    ioctl(0, TIOCGWINSZ, &w); 

    printf ("lines %d\n", w.ws_row); 
    printf ("columns %d\n", w.ws_col); 
    return 0; 
} 

उत्तर

101

आप getenv() का उपयोग कर विचार किया है? यह आपको सिस्टम के पर्यावरण चर प्राप्त करने की अनुमति देता है जिसमें टर्मिनल कॉलम और रेखाएं होती हैं।

वैकल्पिक रूप से अपने विधि का उपयोग कर, अगर आप क्या गिरी टर्मिनल आकार के रूप में देखता है देखना चाहता हूँ (मामले टर्मिनल में बेहतर आकार दिया जाता है), तो आप TIOCGWINSZ उपयोग करने के लिए, के रूप में अपने TIOCGSIZE करने का विरोध किया, तो तरह की आवश्यकता होगी:

struct winsize w; 
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); 

और पूर्ण कोड:

#include <sys/ioctl.h> 
#include <stdio.h> 
#include <unistd.h> 

int main (int argc, char **argv) 
{ 
    struct winsize w; 
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); 

    printf ("lines %d\n", w.ws_row); 
    printf ("columns %d\n", w.ws_col); 
    return 0; // make sure your main returns int 
} 
+4

हाँ लेकिन शब्द चौड़ाई एक पर्यावरणीय चर नहीं है, यह शब्द के लिए स्थिर है। – austin

+4

यह आपको _current_ टर्मिनल आकार प्रदान नहीं करता है, अगर कोई प्रोग्राम के निष्पादन के दौरान टर्मिनल का आकार बदलता है। –

+0

हाँ, जोड़ने की गई कि :) –

0

मान लिया जाये कि आप लिनक्स पर कर रहे हैं, मुझे लगता है कि आप के बजाय ncurses पुस्तकालय उपयोग करना चाहते हैं। मुझे पूरा यकीन है कि आपके पास ttysize सामान stdlib में नहीं है।

+0

अच्छी तरह से, मैं जो कर रहा हूं वह – austin

+0

ncurses के लिए ncurses सेट करने के लिए वास्तव में लायक नहीं है या तो stdlib में नहीं है। दोनों POSIX में मानकीकृत हैं, लेकिन 'ioctl' तरह से, सरल और क्लीनर है, क्योंकि आप शाप प्रारंभ करने, आदि नहीं है – Gandaro

2

आप स्थापित ncurses है और इसे का उपयोग कर रहे हैं, तो आप getmaxyx() का उपयोग टर्मिनल के आयामों को खोजने के लिए कर सकते हैं।

+1

हाँ, और ध्यान दें कि वाई पहले आता है और फिर X – Daniel

-1

यहाँ समारोह पहले से ही सुझाव दिया पर्यावरण चर बात के लिए कहता है कर रहे हैं:

int lines = atoi(getenv("LINES")); 
int columns = atoi(getenv("COLUMNS")); 
+8

पर्यावरण चर नहीं हैं विश्वसनीय।ये मान खोल द्वारा निर्धारित किए जाते हैं, इसलिए वे मौजूद होने की गारंटी नहीं देते हैं। साथ ही, यदि उपयोगकर्ता टर्मिनल आकार बदलता है तो वे अद्यतित नहीं होंगे। – Juliano

+0

कई गोले 'सिग्विन' सिग्नल के लिए हैंडलर स्थापित करते हैं, इसलिए वे चर को अद्यतित रख सकते हैं (उन्हें इसकी भी आवश्यकता है ताकि वे इनपुट एडिटर में उचित लाइन रैपिंग कर सकें)। – Barmar

+1

वे ऐसा कर सकते हैं, लेकिन एक प्रोग्राम का वातावरण अपडेट होने के बाद अपडेट नहीं किया जाएगा। – Functino

10
#include <stdio.h> 
#include <stdlib.h> 
#include <termcap.h> 
#include <error.h> 

static char termbuf[2048]; 

int main(void) 
{ 
    char *termtype = getenv("TERM"); 

    if (tgetent(termbuf, termtype) < 0) { 
     error(EXIT_FAILURE, 0, "Could not access the termcap data base.\n"); 
    } 

    int lines = tgetnum("li"); 
    int columns = tgetnum("co"); 
    printf("lines = %d; columns = %d.\n", lines, columns); 
    return 0; 
} 

जरूरत -ltermcap साथ संकलित की। टर्मकैप का उपयोग करके आप कई अन्य उपयोगी जानकारी प्राप्त कर सकते हैं। अधिक जानकारी के लिए info termcap का उपयोग कर टर्मकैप मैन्युअल देखें।

+0

आप इसे भी -ccurses के साथ संकलित कर सकते हैं। – Kambus

+0

मैं उबंटू 14.04 में टर्म कैप शामिल नहीं कर सकता और इसे भंडार में नहीं ढूंढ सकता। :/ –

+1

मुझे पता है कि यह टिप्पणी तथ्य के 6 साल बाद आती है, लेकिन कृपया 2048 के अपने जादू संख्या को समझाएं ... – einpoklum

15

यह उदाहरण लंबा तरफ एक सा है, लेकिन मेरा मानना ​​है कि यह टर्मिनल आयामों का पता लगाने का सबसे पोर्टेबल तरीका है। यह आकार बदलने का आयोजन भी करता है।

के रूप में टिम और rlbond पता चलता है, मैं ncurses उपयोग कर रहा हूँ। यह पर्यावरण परिवेश पढ़ने के बजाय टर्मिनल संगतता में एक महान सुधार की गारंटी देता है।

#include <ncurses.h> 
#include <string.h> 
#include <signal.h> 

// SIGWINCH is called when the window is resized. 
void handle_winch(int sig){ 
    signal(SIGWINCH, SIG_IGN); 

    // Reinitialize the window to update data structures. 
    endwin(); 
    initscr(); 
    refresh(); 
    clear(); 

    char tmp[128]; 
    sprintf(tmp, "%dx%d", COLS, LINES); 

    // Approximate the center 
    int x = COLS/2 - strlen(tmp)/2; 
    int y = LINES/2 - 1; 

    mvaddstr(y, x, tmp); 
    refresh(); 

    signal(SIGWINCH, handle_winch); 
} 

int main(int argc, char *argv[]){ 
    initscr(); 
    // COLS/LINES are now set 

    signal(SIGWINCH, handle_winch); 

    while(getch() != 27){ 
    /* Nada */ 
    } 

    endwin(); 

    return(0); 
} 
+2

लेकिन क्या यह वास्तव में सिग्नल हैंडलर से initscr और endwin को कॉल करना सुरक्षित है? वे कम से कम 'मैन 7 सिग्नल' – nav

+1

में एसिंक-सिग्नल-सुरक्षित एपीआई के बीच सूचीबद्ध नहीं हैं, यह एक अच्छा बिंदु @nav है, मैंने कभी नहीं सोचा है! क्या बेहतर समाधान शायद सिग्नल हैंडलर ध्वज उठाएगा, और उसके बाद बाकी लूप को मुख्य लूप में निष्पादित करेगा? – gamen

+1

@gamen, हाँ, यह बेहतर होगा;) - संकेत के बजाय सिग्नेशन का भी उपयोग करना बेहतर होगा। –

संबंधित मुद्दे