在研究这个问题时,我在 comments 中发现有人提到了ANSI转义代码来获取端子大小.因为我将使用ANSI转义序列,所以我认为这将是一种比ioctl()getenv()更优雅的获得终端大小的方法.

这里有一个关于ioctl()的很好的帖子,这是激起我兴趣的comment:

只是偶然发现了这个答案,当我意识到getenv("列")在运行时非常完美时,我大吃一惊(1).因此,现在我有了一组后备,所有这些都是从TIOCWINSZ ioctl到getenv(如果不是tty的话),再到classic 的ANSI转义"将游标移动到9999,9999和查询游标pos.最后一个可以在嵌入式系统的串行控制台上运行:)

现在,我确实找到了一些关于ANSI的帖子(1,2),但没有一个回答我的具体问题-如何真正做到这一点?

使用this图表,我推断为了将光标移动到最右边和最下面的位置,我需要CUP(CSI n ; m H)"光标位置"命令,它可能会翻译成类似\x1b[9999;9999H的东西.这是最简单的部分,因为它是一个命令.

第二部分是我有大问题的地方.即使我可以推断出我需要DSR(CSI 6n)"设备状态报告"命令,并且它是\x1b[6n,那么这个查询是如何工作的,即,我如何获取数据并将其存储在变量中,最好不中断终端上正在显示的其他数据?

推荐答案

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <ctype.h>

#define SIZE 100

int main ( void) {
    char in[SIZE] = "";
    int each = 0;
    int ch = 0;
    int rows = 0;
    int cols = 0;
    struct termios original, changed;

    // change terminal settings
    tcgetattr( STDIN_FILENO, &original);
    changed = original;
    changed.c_lflag &= ~( ICANON | ECHO);
    changed.c_cc[VMIN] = 1;
    changed.c_cc[VTIME] = 0;
    tcsetattr( STDIN_FILENO, TCSANOW, &changed);

    printf ( "\033[2J"); //clear screen

    printf ( "\033[9999;9999H"); // cursor should move as far as it can

    printf ( "\033[6n"); // ask for cursor position
    while ( ( ch = getchar ()) != 'R') { // R terminates the response
        if ( EOF == ch) {
            break;
        }
        if ( isprint ( ch)) {
            if ( each + 1 < SIZE) {
                in[each] = ch;
                each++;
                in[each] = '\0';
            }
        }
    }

    printf ( "\033[1;1H"); // move to upper left corner
    if ( 2 == sscanf ( in, "[%d;%d", &rows, &cols)) {
        printf ( "%d rows\n", rows);
        printf ( "%d cols\n", cols);
    }

    // restore terminal settings
    tcsetattr( STDIN_FILENO, TCSANOW, &original);

    return 0;
}

C++相关问答推荐

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

数据包未从DPDK端口传输到内核端口

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

这是一个合法的C Strdup函数吗?

如何在C宏中确定 struct 中元素的类型?

ESP32在vTaskDelay上崩溃

在C语言中,在数学运算过程中,为什么浮点数在变量中的行为不同

C++中矢量类型定义和数据保护的高效解决方案

如何在C中使printf不刷新标准输出?

为什么我不能只在内存地址中添加一个int来寻址任何数组?

如何使用指向 struct 数组的指针并访问数组中特定索引处的 struct

链接器脚本和C程序使用相同的头文件,这可能吗?

如何将两个uint32_t值交织成一个uint64_t?

如何编写postgresql支持函数

哪些C++功能可以在外部C块中使用

在分配内存后使用指针是未定义的行为吗?

共享内存未授予父进程权限

比 * 更快的乘法

如何在 C 中编辑 struct 体中的多个变量

将字节/字符序列写入标准输出的最简单形式