【问题标题】:What do \t and \b do?\t 和 \b 做什么?
【发布时间】:2011-12-28 15:22:58
【问题描述】:

我期待这行简单的代码

printf("foo\b\tbar\n");

用“\t”替换“o”并产生以下输出

fo     bar

(假设制表位每 8 个字符出现一次)。 相反,我得到了

foo    bar

似乎我的 shell 将 \b 解释为“将光标向后移动一个位置”,并将 \t 解释为“将光标移动到下一个制表位”。这种行为是否特定于我在其中运行代码的 shell?我应该期望在不同的系统上有不同的行为吗?

【问题讨论】:

  • 不管怎样,我在 Powershell 的 Windows 7 上使用 Mingw GCC 得到了您的“预期”结果。

标签: c printf


【解决方案1】:

不,这或多或少是他们的本意。

在 C(和许多其他语言)中,您可以使用 \ 表示法插入难以看到/键入的字符:

  • \a 是警报/铃声
  • \b 是退格/擦掉
  • \n 是换行符
  • \r是回车(返回左边距)
  • \t 是标签

您还可以使用\0nnn 指定任何字符的八进制值,或使用\xnn 指定任何字符的十六进制值。

  • EG:_ 的 ASCII 值是八进制 137,十六进制 5f,因此如果您的键盘没有 _ 键或其他东西,也可以键入 \0137 或 \x5f。这对于 NUL (\0) 和 ESC (\033) 等控制字符更有用

正如某人发布的那样(然后在我 +1 之前删除了他们的答案),还有一些不常用的:

  • \f 是换页/新页面(从打印机弹出页面)
  • \v 是垂直制表符(下移一行,在同一列)

在屏幕上,\f 通常与\v 工作方式相同,但在某些打印机/电传打字机上,它会 一直到下一张表格/纸。

【讨论】:

  • 我应该注意到,有一种传统(许多终端都支持),就像在打字机上一样,通过交替退格和 _(下划线)字符来为文本加下划线,并通过键入 \ b 。这不再太流行了,但是您可以在 roff 之类的地方遇到它。在 Linux/Unix 中,ul 程序会将这些转换为可能 / 将 / 起作用的 ANSI 转义码:printf " • u\b_n\b_d\b_e\b_r\b_l\b_i\b_n\b_e\b_ B\bBO\bOL\bLD\bD \n" | ul
【解决方案2】:

Backspace 和 Tab 都移动光标位置。两者都不是真正的“可打印”字符。

你的代码说:

  1. 打印“富”
  2. 将光标后移一格
  3. 将光标向前移动到下一个制表位
  4. 输出“bar”。

要获得您期望的输出,您需要printf("foo\b \tbar")。注意额外的“空间”。那就是:

  1. 输出“foo”
  2. 将光标后移一格
  3. 输出一个“”(这会替换第二个“o”)。
  4. 将光标向前移动到下一个制表位
  5. 输出“bar”。

大多数情况下,使用制表符和退格键来格式化程序输出是不合适的。学习使用printf() 格式说明符。根据查看输出的方式,选项卡的呈现可能会有很大差异。

这个小脚本展示了一种改变终端标签呈现方式的方法。在 Ubuntu + gnome-terminal 上测试:

#!/bin/bash
tabs -8 
echo -e "\tnormal tabstop"
for x in `seq 2 10`; do
  tabs $x
  echo -e "\ttabstop=$x"
 done

tabs -8
echo -e "\tnormal tabstop"

另见man setterm 和regtabs。

如果您重定向输出或仅写入文件,选项卡通常会显示为少于标准的 8 个字符,尤其是在“编程”编辑器和 IDE 中。

换句话说:

printf("%-8s%s", "foo", "bar"); /* this will ALWAYS output "foo     bar" */
printf("foo\tbar"); /* who knows how this will be rendered */

恕我直言,标签通常很少适合任何东西。为需要制表符分隔值输入文件(类似于逗号分隔值)的程序生成输出时可能会出现异常。

Backspace '\b' 是另一回事......它永远不应该用于创建文本文件,因为它只会让文本编辑器吐出垃圾。但它在编写交互式命令行程序方面确实有许多应用程序,这些应用程序无法单独使用格式字符串来完成。如果您发现自己非常需要它,请查看“ncurses”,它可以让您更好地控制输出在终端屏幕上的位置。通常,由于是 2011 年而不是 1995 年,因此对于高度交互的程序,GUI 通常更容易处理。但同样,也有例外。就像为新的脚本语言编写 telnet 服务器或控制台一样。

【讨论】:

    【解决方案3】:

    C 标准(实际上是 C99,我不是最新的)说:

    表示执行字符集中非图形字符的字母转义序列旨在在显示设备上产生如下操作:

    \b (backspace) 将活动位置移动到当前行的前一个位置。 [...]

    \t (水平制表符) 将活动位置移动到当前行的下一个水平制表位置。 [...]

    两者都只是移动活动位置,都不应该在另一个字符上或上面写任何字符。要使用空格覆盖,您可以尝试:puts("foo\b \tbar");,但请注意,在某些显示设备(例如菊花轮打印机)上,o 将显示透明空间。

    【讨论】:

      【解决方案4】:

      此行为是特定于终端的,由您使用的终端仿真器(例如xterm)及其提供的终端语义指定。终端行为近 20 年来一直非常稳定,可以合理依赖\b 的语义。

      【讨论】:

      • 行为不应该是 that 终端特定的,因为 \b 和 \t 是终端行为的抽象,可能需要由 C 环境转换为终端具体代码。当然,实际上它们几乎总是直接映射到相应的BS 和TAB ASCII 码上。
      【解决方案5】:

      \t 是制表符,并且正在根据\b 的操作执行您所期望的操作 - 它转到下一个制表位,然后递减,然后转到下一个制表位 (在这种情况下,这是相同的制表位,因为 \b。

      【讨论】:

      • 我不确定我是否关注,只有一个 \t,因此只有一个明确移动到制表位。 \b 只是返回一个位置。在示例中,\b 没有(必然)从制表位开始或结束。
      猜你喜欢
      • 2019-08-08
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      • 2011-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多