Linux 在 C 中获取终端宽度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1022957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting terminal width in C?
提问by austin
I've been looking for a way to get the terminal width from within my C program. What I keep coming up with is something along the lines of:
我一直在寻找一种从 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);
}
But everytime I try that I get
但每次我尝试我都得到
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.)
Is this the best way to do this, or is there a better way? If not how can I get this to work?
这是最好的方法,还是有更好的方法?如果不是,我怎样才能让它发挥作用?
EDIT: fixed code is
编辑:固定代码是
#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;
}
采纳答案by John T
Have you considered using getenv()? It allows you to get the system's environment variables which contain the terminals columns and lines.
您是否考虑过使用getenv()?它允许您获取包含终端列和行的系统环境变量。
Alternatively using your method, if you want to see what the kernel sees as the terminal size (better in case terminal is resized), you would need to use TIOCGWINSZ, as opposed to your TIOCGSIZE, like so:
或者使用您的方法,如果您想查看内核看到的终端大小(在调整终端大小的情况下更好),您需要使用 TIOCGWINSZ,而不是您的 TIOCGSIZE,如下所示:
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
and the full code:
和完整代码:
#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
}
回答by tim
回答by rlbond
If you have ncurses installed and are using it, you can use getmaxyx()
to find the dimensions of the terminal.
如果您安装了 ncurses 并正在使用它,您可以使用它getmaxyx()
来查找终端的尺寸。
回答by merkuro
Here are the function calls for the already suggested environmental variable thing:
以下是对已经建议的环境变量事物的函数调用:
int lines = atoi(getenv("LINES"));
int columns = atoi(getenv("COLUMNS"));
回答by Juliano
#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;
}
Needs to be compiled with -ltermcap
. There is a lot of other useful information you can get using termcap. Check the termcap manual using info termcap
for more details.
需要编译-ltermcap
。您可以使用 termcap 获得许多其他有用的信息。查看 termcap 手册 usinginfo termcap
了解更多详细信息。
回答by gamen
This example is a bit on the lengthy side, but I believe it's the most portable way of detecting the terminal dimensions. This also handles resize events.
这个例子有点冗长,但我相信这是检测终端尺寸的最便携的方式。这也处理调整大小事件。
As tim and rlbond suggests, I'm using ncurses. It guarantees a great improvement in terminal compatability as compared to reading environment variables directly.
正如 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);
}
回答by Scott Franco
So not suggesting an answer here, but:
所以不是在这里建议答案,而是:
linux-pc:~/scratch$ echo $LINES
linux-pc:~/scratch$ echo $LINES
49
49
linux-pc:~/scratch$ printenv | grep LINES
linux-pc:~/scratch$ printenv | grep LINES
linux-pc:~/scratch$
linux-pc:~/scratch$
Ok, and I notice that if I resize the GNOME terminal, the LINES and COLUMNS variables follow that.
好的,我注意到如果我调整 GNOME 终端的大小,LINES 和 COLUMNS 变量会跟随它。
Kinda seems like GNOME terminal is creating these environment variables itself?
有点像 GNOME 终端自己创建这些环境变量?
回答by iggy12345
To add a more complete answer, what I've found to work for me is to use @John_T's solution with some bits added in from Rosetta Code, along with some troubleshooting figuring out dependencies. It might be a bit inefficient, but with smart programming you can make it work and not be opening your terminal file all the time.
为了添加更完整的答案,我发现对我有用的是使用@John_T 的解决方案,其中添加了一些从Rosetta Code 中添加的位,以及一些解决依赖关系的故障排除。这可能有点低效,但通过智能编程,您可以使其工作,而不必一直打开终端文件。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h> // ioctl, TIOCGWINSZ
#include <err.h> // err
#include <fcntl.h> // open
#include <unistd.h> // close
#include <termios.h> // don't remember, but it's needed
size_t* get_screen_size()
{
size_t* result = malloc(sizeof(size_t) * 2);
if(!result) err(1, "Memory Error");
struct winsize ws;
int fd;
fd = open("/dev/tty", 0_RDWR);
if(fd < 0 || ioctl(fd, TIOCGWINSZ, &ws) < 0) err(8, "/dev/tty");
result[0] = ws.ws_row;
result[1] = ws.ws_col;
close(fd);
return result;
}
If you make sure not to call it all but maybe every once in awhile you should be fine, it should even update when the user resizes the terminal window (because you're opening the file and reading it everytime).
如果您确保不全部调用它,但可能每隔一段时间调用一次应该没问题,它甚至应该在用户调整终端窗口大小时更新(因为您每次都打开文件并阅读它)。
If you aren't using TIOCGWINSZ
see the first answer on this form https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/.
如果您不使用,TIOCGWINSZ
请参阅此表单https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/上的第一个答案。
Oh, and don't forget to free()
the result
.
哦,别忘free()
了result
.