我期待这段简单的代码
printf("foo\b\tbar\n");
用“\ t”替换“o”并产生以下输出
fo bar
(假设每8个字符发生制表位)。 相反,我得到
foo bar
似乎我的shell将\ b解释为“将游标移回一个位置”并将\ t解释为“将光标移动到下一个制表位”。这种行为是否特定于我正在运行代码的shell?我应该期望在不同的系统上有不同的行为吗?
答案 0 :(得分:31)
不,这或多或少都是他们的目的。
在C(以及许多其他语言)中,您可以使用\
表示法插入难以查看/输入字符:
\a
是alert / bell \b
退格/退出\n
是换行符\r
是回车(返回左边距)\t
是标签您还可以使用\0
nnn 指定任何字符的八进制值,或使用\x
nn 指定任何字符的十六进制值。
_
的ASCII值是八进制137,十六进制5f,因此如果您的键盘没有{{1},它也可以键入\0137
或\x5f
键或什么的。这对于控制字符(如NUL(_
)和ESC(\0
)正如有人发布的那样(然后在我给它+1之前删除了他们的答案),还有一些不太常用的答案:
\033
是一个换页/新页面(从打印机弹出页面)\f
是一个垂直标签(向下移动一行,在同一列上)在屏幕上,\v
通常与\f
的工作方式相同,但在某些打印机/电视类型上,它会
一直走到下一张纸/纸上。
答案 1 :(得分:30)
Backspace和tab都移动光标位置。两者都不是真正的“可打印”角色。
您的代码说:
要获得您期望的输出,您需要printf("foo\b \tbar")
。注意额外的“空间”。那说:
大多数情况下,使用制表符和退格键来格式化程序输出是不合适的。学习使用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服务器或控制台一样。
答案 2 :(得分:2)
C标准(实际上是C99,我不是最新的)说:
表示执行字符集中非图形字符的字母转义序列旨在按如下方式在显示设备上产生操作:
\b
(退格)将活动位置移动到当前行的上一个位置。 [...]
\t
(水平标签)将活动位置移动到当前行的下一个水平制表位置。 [...]
两者都只是移动活动位置,也不应该在另一个角色上或上方写任何字符。要使用空格覆盖,您可以尝试:puts("foo\b \tbar");
但请注意,在某些显示设备上 - 例如菊花轮打印机 - o
将显示透明空间。
答案 3 :(得分:1)
此行为是终端特定的,由您使用的终端仿真器(例如xterm
)和它提供的终端的语义指定。终端行为在过去20年中一直非常稳定,您可以合理地依赖\b
的语义。
答案 4 :(得分:0)
\t
是制表符,并且正在根据\b
的操作执行您正在预期的操作 - 它会转到下一个制表位,然后递减,然后转到下一个制表位(在这种情况下,由于\b
而在同一个制表位上停止。