Получение ширины терминала в C?
Я искал способ получить ширину терминала из моей программы на 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);
}
Но каждый раз, когда я пытаюсь, я получаю
[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.)
Это лучший способ сделать это, или есть лучший способ? Если нет, то как я могу заставить это работать?
EDIT: фиксированный код
#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;
}
Ответы
Ответ 1
Считаете ли вы использование 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
}
Ответ 2
Этот пример немного длинный, но я считаю его самым переносимым способом определения размеров терминала. Это также обрабатывает события изменения размера.
Как показывает tim и 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);
}
Ответ 3
#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
.
Ответ 4
Если у вас установлены ncurses и вы используете его, вы можете использовать getmaxyx()
для определения размеров терминала.
Ответ 5
Предполагая, что вы работаете в Linux, я думаю, вы хотите использовать библиотеку ncurses
вместо. Я уверен, что у ttysize, который у вас есть, нет в stdlib.
Ответ 6
Так что не предлагая ответ здесь, но:
linux-pc:~/scratch$ echo $LINES
49
linux-pc:~/scratch$ printenv | grep LINES
linux-pc:~/scratch$
Хорошо, и я заметил, что если я изменю размер терминала GNOME, переменные LINES и COLUMNS будут следовать за этим.
Вроде как терминал GNOME сам создает эти переменные окружения?
Ответ 7
Вот вызов функций для уже предложенной переменной среды:
int lines = atoi(getenv("LINES"));
int columns = atoi(getenv("COLUMNS"));