【问题标题】:Confused with interesting printf() statement对有趣的 printf() 语句感到困惑
【发布时间】:2014-11-30 15:07:06
【问题描述】:

通过阅读this code,我偶然发现了以下printf() 声明:

// reset, hide cursor and clear screen
printf("\e[0m\e[?25l\e[2J");

我必须承认我不是一个完全合格的 C 黑客并且不完全理解这一点。我调整了一下,删除了参数,我理解它的作用(嗯,评论实际上说明了一切),但我不知道它是如何完成的。此外,这在谷歌上有点难以搜索。

printf() 这个电话是如何工作的?

【问题讨论】:

  • man 5 termcapman 5 terminfo
  • printf() 的角度来看,它与任何其他printf() 语句一样工作:它将chars 的序列打印到标准输出。尝试将程序的输出重定向到一个文件,然后检查它的内容。
  • 你看到的是一个 CSI (Control Sequence Introducer),维基百科有一个很好的列表。您可以在控制台上获得文本颜色效果、清除屏幕、移动光标等。它们通常以\033[ 开头,例如要打印粗体,您将使用带有参数1 的SGR CSI (m) 通过打印"\033[1m"。 SGR 参数是here,非常有趣。维基百科在底部也提供了示例。

标签: c printf


【解决方案1】:

这与printf 没有任何关系。 C11 标准在 §5.2.2 中列出了转义序列,列表由\a\b\f\n\r\t\v 组成。作为扩展,GCC 认为 \e 是一个转义序列,它代表 ASCII 字符 Esc\E 也可以工作,或者您的编译器可能都不支持它们。请参阅编译器的文档)。以下是不可移植的control sequences。不能保证它们在所有终端中都能正常工作,甚至根本不能工作。最好的了解方法是查阅您系统的文档。

§6.4.4.4 还描述了八进制转义序列。例如,\033,其中033 是十进制的27,因此是ASCII 中的转义字符。同样,您可以使用\x1b,这是一个指定相同字符的十六进制转义序列。

如果我们用od -c检查程序的输出,它会显示033

(✿´‿`) ~/test> ./a.out | od -c
0000000 033   [   0   m 033   [   ?   2   5   l 033   [   2   J
0000016

ANSI 转义序列由终端仿真器解释。 C 会将八进制/十六进制转义序列转换为 ASCII Esc 字符。作为扩展,您的编译器也可能会转换\e\E。根据要求,简要说明控制序列的作用:

  • [0m:重置所有SGR属性
  • [?25l:隐藏光标
  • [2J: 来自维基百科:

    清除部分屏幕。如果n 为 0(或缺失),则从光标中清除 到屏幕结束。如果n 为 1,则从光标处清除 屏幕。如果n 为2,则清空整个屏幕...

【讨论】:

  • 您能否更详细地说明问题中的printf 命令究竟是做什么的?
【解决方案2】:

printf() 调用只是输出一系列特定的字节值。 “神奇”在于这些值在终端中是特殊的。

以 ASCII“转义”字符开头的特殊字节序列称为“转义序列”。这些是为串行数据终端发明的,与终端通信的唯一方式是通过串行连接发送字节值。普通字符只是简单地显示在终端上,但希望有一种方法来移动光标、清除屏幕等,并且大多数终端为此使用了转义序列。

http://en.wikipedia.org/wiki/Escape_sequence

有一个特别受欢迎的终端,称为“VT100”,如今大多数终端仿真器都使用 VT100 转义序列运行。

即使在今天,转义序列也很有用。你可以编写一个简单的 C 程序,它可以在 Linux、Mac、Windows、移动设备等终端仿真器上运行,基本上无处不在。当你需要做一些简单的事情比如清屏时,输出正确的转义序列是最简单的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多