Pregunta

He estado buscando una forma de obtener el ancho del terminal desde mi programa C. Lo que se me ocurre es algo parecido a:

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

Pero cada vez que lo intento, obtengo

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.)

¿Es esta la mejor manera de hacer esto, o hay una mejor manera? Si no, ¿cómo puedo hacer que esto funcione?

EDITAR: el código fijo es

#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;
}
¿Fue útil?

Solución

¿Ha considerado usar getenv () ? Le permite obtener las variables de entorno del sistema que contienen las columnas y líneas de los terminales.

Alternativamente, utilizando su método, si desea ver lo que el núcleo ve como el tamaño del terminal (mejor en caso de que se cambie el tamaño del terminal), necesitaría usar TIOCGWINSZ, en lugar de su TIOCGSIZE, así:

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

y el código completo:

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

Otros consejos

Este ejemplo es un poco largo, pero creo que es la forma más portátil de detectar las dimensiones del terminal. Esto también maneja los eventos de cambio de tamaño.

Como lo sugieren tim y rlbond, estoy usando ncurses. Garantiza una gran mejora en la compatibilidad de terminales en comparación con las variables de entorno de lectura directamente.

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

Necesita compilarse con -ltermcap . Hay mucha otra información útil que puede obtener usando termcap. Consulte el manual de termcap con info termcap para obtener más detalles.

Si tiene ncurses instalado y lo está utilizando, puede usar getmaxyx () para encontrar las dimensiones del terminal.

Suponiendo que está en Linux, creo que desea utilizar la biblioteca ncurses en lugar. Estoy bastante seguro de que las cosas de ttysize que tienes no están en stdlib.

Entonces no sugiero una respuesta aquí, pero:

linux-pc: ~ / scratch $ echo $ LINES

49

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

linux-pc:~/scratch$

Ok, y me doy cuenta de que si cambio el tamaño del terminal GNOME, las variables LINES y COLUMNS lo siguen.

¿Parece que el terminal GNOME está creando estas variables de entorno por sí mismo?

Aquí están las llamadas a funciones para la variable ambiental ya sugerida:

int lines = atoi(getenv("LINES"));
int columns = atoi(getenv("COLUMNS"));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top