Obtendo a largura do terminal em C?

Eu tenho procurado uma maneira de obter a largura do terminal de dentro do meu programa em C. O que eu continuo chegando é algo nos moldes de:

#include  #include  int main (void) { struct ttysize ts; ioctl(0, TIOCGSIZE, &ts); printf ("lines %d\n", ts.ts_lines); printf ("columns %d\n", ts.ts_cols); } 

Mas toda vez que eu tento, fico

 austin@:~$ 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.) 

Esta é a melhor maneira de fazer isso, ou existe uma maneira melhor? Se não como posso fazer isso funcionar?

EDIT: código fixo é

 #include  #include  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; } 

Você já pensou em usar getenv () ? Ele permite que você obtenha as variables ​​de ambiente do sistema que contêm as colunas e linhas dos terminais.

Alternativamente, usando seu método, se você quiser ver o que o kernel vê como o tamanho do terminal (melhor caso o terminal seja redimensionado), você precisaria usar o TIOCGWINSZ, ao contrário do seu TIOCGSIZE, da seguinte forma:

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

e o código completo:

 #include  #include  #include  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 } 

Este exemplo é um pouco longo, mas acredito que seja a forma mais portátil de detectar as dimensões dos terminais. Isso também lida com events de redimensionamento.

Como tim e rlbond sugerem, estou usando ncurses. Ele garante uma grande melhoria na compatibilidade do terminal em comparação com as variables ​​de ambiente de leitura diretamente.

 #include  #include  #include  // 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); } 
 #include  #include  #include  #include  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; } 

Precisa ser compilado com -ltermcap . Há muitas outras informações úteis que você pode obter usando o termcap. Verifique o manual termcap usando info termcap para mais detalhes.

Se você tiver ncurses instaladas e estiver usando, você pode usar getmaxyx() para encontrar as dimensões do terminal.

Supondo que você esteja no Linux, eu acho que você quer usar a biblioteca ncurses . Tenho certeza que o material ttysize que você tem não está no stdlib.

Aqui estão as chamadas de function para a variável de ambiente já sugerida:

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