【问题标题】:How to manipulate the terminal output buffer directly如何直接操作终端输出缓冲区
【发布时间】:2015-02-20 08:21:36
【问题描述】:

我想在 Linux 终端(使用 C/C++)中编写一个游戏,所以首先我应该能够打印我想要的字符。我尝试使用“printf()”,但似乎有点不方便。我认为终端的输出字符应该有一个字符缓冲区。有没有办法直接操作缓冲区?

非常感谢。

【问题讨论】:

  • 不清楚你在问什么。为什么要直接操作缓冲区?您是否想立即将输出显示到屏幕上?
  • 您应该根据游戏需要查看 ncurses 以获得完整的终端控制。
  • 你好,我的意思是我认为终端的输出必须存储在某个缓冲区中,我想知道是否有办法直接修改它。例如,假设终端窗口的位置 (2, 3) 有一个字符 'c',我想将其更改为 'a'。这个“c”必须存储在缓冲区“buf”中的某个位置,比如“buf[2][3]”。我正在寻找一种直接操作此“buf”以将“buf [2] [3]”从“c”修改为“a”的方法。你清楚了吗?

标签: c++ c linux printing terminal


【解决方案1】:

它以不同的方式进行。 终端只是一个字符设备,这意味着它实际上是无缓冲的。尽管如此,您仍然可以使用适当的字符序列(称为“转义序列”)来操纵屏幕位置。例如,如果您发出 \e[A (0x1B 0x91 0x41) 序列,光标会向上移动一行,同时保持字符不变,而如果您发出 \e[10;10H, (0x1B 0x91 0x31 0x30 0x3B 0x31 0x30 0x48 ),您的光标将转到第 10 行的第 10 列(正是您想要的)。移动光标后,您写出的下一个字符将移至该位置。有关转义序列的更多信息,请查看this link

另一个需要了解的重要事项是终端的尺寸。 ioctl可以告知你终端窗口的大小:

#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int main ()
{
    struct winsize ws;
    ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws);
    printf ("Rows: %d, Cols: %d\n", ws.ws_row, ws.ws_col);
    return 0;
}

请注意,上述技术是一种将命令发送到连接到您的伪终端设备的终端仿真器的解决方案。也就是说,终端设备本身保持无缓冲,命令由终端仿真器解释。

【讨论】:

  • @Trams 你是什么意思?例如,不能通过 ioctl 更改终端窗口的大小
  • 比如在终端改变字体和字符大小?我能做到吗?
【解决方案2】:

您可能想要使用setbuf 函数,它允许您告诉 printf 要使用哪个缓冲区。您可以使用自己的缓冲区并控制内容。

但是,这是错误的方法,原因有两个。

第一,与 printf()、fwrite() 和 putchar() 相比,它不会为您节省工作量。

第二,更重要的是,即使这些功能也无济于事。从您的评论中可以清楚地看出您想在屏​​幕上操作一个字符,例如,替换一个“。” (空的地板)当那条龙接近时由一个D(龙)。您不能通过操纵 printf() 的输出缓冲区来做到这一点。一旦 '。'显示时,输出缓冲区已刷新到终端,如果您操作该缓冲区,则它没有效果。终端已收到该缓冲区的副本,并已显示缓冲区中的数据指示它显示的内容。为了改变显示的内容,你必须发送新的命令。

这正是ncurses 为您所做的。它跟踪终端的状态、当前内容、光标位置和所有令人讨厌的细节,例如如何使字符显示为粗体。

使用 printf 不会成功。那是没有希望的。您需要了解 ncurses 可以为您做什么,然后其他一切都很容易。

【讨论】:

  • 正如你上面所说的,'printf()' 的输出缓冲区最终会被刷新到终端显示。并且终端接收缓冲区的副本。那么,我可以在终端(接收副本)中找到该缓冲区并直接操作它吗?这就是 ncurses 的实际作用吗?
  • 不,您无法在终端中找到缓冲区。终端吃掉它接收到的数据,将数据解释为指令,然后数据就消失了。之后,你唯一能做的就是向终端发送更多数据,发送新指令。这就是 ncurses 为您做的事情。
猜你喜欢
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多