Domanda

Ho cercato un modo per ottenere la larghezza del terminale dal mio programma C. Quello che continuo a venire è qualcosa sulla falsariga di:

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

Ma ogni volta che provo che ottengo

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

È questo il modo migliore per farlo o esiste un modo migliore? In caso contrario, come posso farlo funzionare?

EDIT: il codice fisso è

#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;
}
È stato utile?

Soluzione

Hai pensato di utilizzare getenv () ? Ti permette di ottenere le variabili d'ambiente del sistema che contengono le colonne e le linee dei terminali.

In alternativa usando il tuo metodo, se vuoi vedere ciò che il kernel vede come dimensione del terminale (meglio se il terminale viene ridimensionato), dovresti usare TIOCGWINSZ, al contrario del tuo TIOCGSIZE, in questo modo:

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

e il codice 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
}

Altri suggerimenti

Questo esempio è un po 'lungo, ma credo che sia il modo più portatile di rilevare le dimensioni dei terminali. Questo gestisce anche gli eventi di ridimensionamento.

Come suggeriscono tim e rlbond, sto usando ncurses. Garantisce un notevole miglioramento della compatibilità dei terminali rispetto alla lettura diretta delle variabili di ambiente.

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

Deve essere compilato con -ltermcap . Ci sono molte altre informazioni utili che puoi ottenere usando termcap. Controlla il manuale di termcap usando info termcap per maggiori dettagli.

Se hai installato ncurses e lo stai usando, puoi usare getmaxyx () per trovare le dimensioni del terminale.

Supponendo che tu sia su Linux, penso che tu voglia usare la ncurses anziché. Sono abbastanza sicuro che le cose ttysize che hai non siano in stdlib.

Quindi non suggerire una risposta qui, ma:

linux-pc: ~ / scratch $ echo $ LINES

49

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

linux-pc: ~ / scratch $

Ok, e noto che se ridimensiono il terminale GNOME, le variabili LINES e COLUMNS lo seguono.

Kinda sembra che il terminale GNOME stia creando da solo queste variabili d'ambiente?

Ecco le chiamate di funzione per la cosa variabile ambientale già suggerita:

int lines = atoi(getenv("LINES"));
int columns = atoi(getenv("COLUMNS"));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top