Получение ширины терминала в C? - PullRequest
82 голосов
/ 21 июня 2009

Я искал способ получить ширину терминала из моей C-программы. Я продолжаю придумывать что-то вроде:

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

Но каждый раз, когда я пытаюсь это получить, я получаю

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

Это лучший способ сделать это, или есть лучший способ? Если нет, то как я могу заставить это работать?

РЕДАКТИРОВАТЬ: фиксированный код

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

Ответы [ 7 ]

112 голосов
/ 21 июня 2009

Рассматривали ли вы использование 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
}
16 голосов
/ 13 августа 2010

Этот пример немного длинноват, но я считаю, что это самый портативный способ определения размеров терминала. Это также обрабатывает события изменения размера.

Как подсказывают Тим ​​и Рлбонд, я использую 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);
}
12 голосов
/ 21 июня 2009
#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. Существует много другой полезной информации, которую вы можете получить с помощью termcap. Обратитесь к руководству termcap, используя info termcap для более подробной информации.

2 голосов
/ 21 июня 2009

Если у вас установлена ​​ncurses и вы ее используете, вы можете использовать getmaxyx(), чтобы найти размеры терминала.

0 голосов
/ 18 апреля 2019

Так что здесь не предлагается ответ, но:

linux-pc:~/scratch$ echo $LINES

49

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

linux-pc:~/scratch$

Хорошо, и я замечаю, что если я изменяю размер терминала GNOME, переменные LINES и COLUMNS следуют за этим.

Кажется, что терминал GNOME сам создает эти переменные окружения?

0 голосов
/ 21 июня 2009

Вот вызовы функций для уже предложенной переменной среды:

int lines = atoi(getenv("LINES"));
int columns = atoi(getenv("COLUMNS"));
0 голосов
/ 21 июня 2009

Если вы работаете в Linux, я думаю, вы хотите использовать библиотеку ncurses вместо. Я почти уверен, что у вас есть ttize, которого нет в stdlib.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...