【问题标题】:Get size of terminal window (rows/columns)获取终端窗口的大小(行/列)
【发布时间】:2014-06-15 16:14:33
【问题描述】:

有没有可靠的方法来获取当前输出终端窗口的列/行数?

我想在 C/C++ 程序中检索这些数字。

我主要在寻找 GNU/Linux 解决方案,但也需要 Windows 解决方案。

【问题讨论】:

标签: c++ c shell terminal


【解决方案1】:

这是一个适用于 Windows 和 Linux 的解决方案:

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <Windows.h>
#elif defined(__linux__)
#include <sys/ioctl.h>
#endif // Windows/Linux

void get_terminal_size(int& width, int& height) {
#if defined(_WIN32)
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    width = (int)(csbi.srWindow.Right-csbi.srWindow.Left+1);
    height = (int)(csbi.srWindow.Bottom-csbi.srWindow.Top+1);
#elif defined(__linux__)
    struct winsize w;
    ioctl(fileno(stdout), TIOCGWINSZ, &w);
    width = (int)(w.ws_col);
    height = (int)(w.ws_row);
#endif // Windows/Linux
}

#include <iostream>
using namespace std;
int main() {
    int width=0, height=0;
    get_terminal_size(width, height);
    cout << "width=" << width << ", height=" << height << endl;
    cin.get();
    return 0;
}

【讨论】:

  • 1. linux 中没有 iostream 或 iostream.h。我不知道那是什么或是否需要它。因为如果是这样……这不再是跨平台的了。 2. 没有int&这样的东西。如果你的意思是: ` void get_terminal_size(int &width, int &height) ` 会抛出错误。如果你的意思是` void get_terminal_size(int *width, int *height) `,你会得到一堆警告,它返回0,0。这将是伟大的......如果它工作:/
  • @Eric Sebasta 当然在 Linux C++ 中有 标准库。对于get_terminal_size(...) 调用,您不需要它,它只是用于演示它的使用并在控制台中打印结果。你用的是什么编译器?尝试使用 g++ 编译。 int&amp; 是传递引用,这是 C++ 中的标准内容。如果由于某种原因这对您不起作用,请尝试使用指针:get_terminal_size(int* width, int* height) 并将每个 width = height = 替换为 *width = *height =
【解决方案2】:

悲痛欲绝:

  auto const w(WEXITSTATUS(std::system("exit `tput cols`")));
  auto const h(WEXITSTATUS(std::system("exit `tput lines`")));

【讨论】:

    【解决方案3】:

    对于 Unix(基于),使用 ioctl(2)TIOCGWINSZ

    
    #include <sys/ioctl.h> //ioctl() and TIOCGWINSZ
    #include <unistd.h> // for STDOUT_FILENO
    // ...
    
    struct winsize size;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);
    
    /* size.ws_row is the number of rows, size.ws_col is the number of columns. */
    
    // ...
    
    

    另外,虽然我在过去五年没有接触过 Windows,但 GetConsoleScreenBufferInfo() 应该可以帮助您了解控制台窗口的大小。

    【讨论】:

    • 我读过这不是标准的 POSIX - 是否有任何定义可以告诉我代码是否可以在当前机器上运行?
    • 请加回#includes,因为这不是一个完整的答案。见:stackoverflow.com/questions/1022957/getting-terminal-width-in-c
    • @DanielCheung 花了我一点时间,但添加了所需的包括:-)
    【解决方案4】:

    在 Windows 上,使用以下代码打印控制台窗口的大小(借用自 here):

    #include <windows.h>
    
    int main(int argc, char *argv[]) 
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        int columns, rows;
    
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
        rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
    
        printf("columns: %d\n", columns);
        printf("rows: %d\n", rows);
        return 0;
    }
    

    在 Linux 上,请改用以下代码(借用自 here):

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

    【讨论】:

    • 有跨平台解决方案的机会吗?
    【解决方案5】:

    为 Windows 扩展 @herohuyongtao 答案。 .srWindow 属性给出了控制台窗口大小的答案,即可见的行和列。这并没有说明实际可用的屏幕缓冲区宽度和高度是多少,如果窗口包含滚动条,它可能会更大。如果是这种情况,请使用 .dwSize:

    CONSOLE_SCREEN_BUFFER_INFO sbInfo;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbInfo);
    int availableColumns = sbInfo.dwSize.X;
    int availableRows = sbInfo.dwSize.Y;
    

    【讨论】:

      【解决方案6】:

      在 GNU/Linux 上使用 libtermcap (https://www.gnu.org/software/termutils/manual/termcap-1.3/html_mono/termcap.html) 创建 demo.c:

      #include <stdio.h>
      #include <stdlib.h>
      #include <curses.h>
      #include <term.h>
      
      static char term_buffer[2048];
      
      void
      init_terminal_data (void)
      {
      
        char *termtype = getenv ("TERM");
        int success;
      
        if (termtype == NULL)
          fprintf (stderr, "Specify a terminal type with `setenv TERM <yourtype>'.\n");
      
        success = tgetent (term_buffer, termtype);
        if (success < 0)
          fprintf (stderr, "Could not access the termcap data base.\n");
        if (success == 0)
          fprintf (stderr, "Terminal type `%s' is not defined.\n", termtype);
      }
      
      int
      main ()
      {
        init_terminal_data ();
        printf ("Got: Lines: %d, Columns: %d\n", tgetnum ("li"), tgetnum ("co"));
        return 0;
      }
      

      然后用gcc -o demo.x demo.c -ltermcap编译并运行给出:

      $ ./demo.x
      Got: Lines: 24, Columns: 80
      

      我怀疑这对 Windows 有多大帮助,但我不知道那个平台。

      (其中部分代码直接从 termcap 文档中复制而来。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-19
        • 1970-01-01
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-22
        • 2012-07-31
        相关资源
        最近更新 更多