如何使用 printf 格式化输出

了解 printf,一个神秘、灵活且功能丰富的 echo、print 和 cout 的替代方案。
53 位读者喜欢这篇文章。

当我开始学习 Unix 时,我很早就接触了 echo 命令。同样,我的第一堂 Python 课程涉及 print 函数。学习 C++ 和 Java 后,我了解了 coutsystemout。似乎每种语言都自豪地拥有一种方便的单行输出方法,并像过时一样宣传它。

但是,一旦我翻到中级课程的第一页,我就遇到了 printf,一个神秘、令人费解且出奇灵活的函数。本文旨在打破向初学者隐藏 printf 的令人困惑的传统,向世界介绍不起眼的 printf 函数,并解释如何在几乎任何语言中使用它。

printf 的简史

术语 printf 代表“print formatted”(格式化打印),可能最早出现在 Algol 68 编程语言中。自从包含在 C 语言中以来,printf 已经在 C++、Java、Bash、PHP 中重新实现,并且很可能在您最喜欢的(后 C 语言)语言中也实现了。

它显然很受欢迎,但许多人似乎认为它的语法很复杂,特别是与 echoprintcout 等替代方案相比。例如,这是一个 Bash 中简单的 echo 语句

$ echo hello
hello
$

这是在 Bash 中使用 printf 的相同结果

$ printf "%s\n" hello
hello
$

但是,您为增加的复杂性获得了许多功能,这正是 printf 非常值得学习的原因。

printf 输出

printf 背后的主要概念是它能够根据与内容分离的样式信息来格式化其输出。例如,printf 识别为特殊字符的特殊序列集合。您最喜欢的语言可能具有更多或更少的序列,但常见的序列包括

  • \n:换行符
  • \r:回车符
  • \t:水平制表符
  • \NNN:具有八进制值(包含一到三位数字)的特定字节

例如

$ printf "\t\123\105\124\110\n"
     SETH
$

在这个 Bash 示例中,printf 呈现一个制表符,后跟分配给四个八进制值字符串的 ASCII 字符。这以控制序列结尾以产生新行 (\n)。

尝试使用 echo 执行相同的操作会产生更字面的结果

$ echo "\t\123\105\124\110\n"
\t\123\105\124\110\n
$

对同一任务使用 Python 的 print 函数,揭示了 Python 的 print 命令比您可能预期的要多

>>> print("\t\123\n")
        S

>>>

显然,Python 的 print 结合了传统的 printf 功能以及简单的 echocout 的功能。

但是,这些示例仅包含文字字符,虽然它们在某些情况下很有用,但它们可能是关于 printf 最不重要的东西。printf 的真正威力在于格式规范。

使用 printf 格式化输出

格式说明符是以百分号 (%) 开头的字符。

常见的包括

  • %s:字符串
  • %d:数字
  • %f:浮点数
  • %o:八进制数

这些是 printf 语句中的占位符,您可以将它们替换为您在 printf 语句中其他位置提供的值。这些值的提供位置取决于您使用的语言及其语法,但这是一个 Java 中的简单示例

string var="hello\n";
system.out.printf("%s", var);

这段代码在适当的样板代码中包装并执行后,会呈现

$ ./example
hello
$

当变量的内容发生变化时,事情会变得更有趣。假设您想根据不断增加的数字更新输出

#include <stdio.h>

int main() {
  int var=0;
  while ( var < 100) {
    var++;
  printf("Processing is %d%% finished.\n", var);
  }
  return 0;
}

编译并运行

Processing is 1% finished.
[...]
Processing is 100% finished.

请注意,代码中的双 %% 解析为单个打印的 % 符号。

使用 printf 限制小数位数

数字可能会变得复杂,printf 提供了许多格式化选项。您可以使用 %f(用于浮点数)来限制打印的小数位数。通过在百分号和 f 之间放置一个点 (.) 以及一个限制数字,您可以告诉 printf 要呈现多少位小数。这是一个用 Bash 编写的简单示例,为了简洁起见

$ printf "%.2f\n" 3.141519
3.14
$

类似的语法适用于其他语言。这是 C 语言中的一个示例

#include <math.h>
#include <stdio.h>

int main() {
  fprintf(stdout, "%.2f\n", 4 * atan(1.0));
  return 0;
}

对于三位小数,请使用 .3f,依此类推。

使用 printf 在数字中添加逗号

由于大数字可能难以解析,因此通常用逗号分隔它们。您可以通过在百分号和 d 之间放置一个撇号 (') 来让 printf 根据需要添加逗号

$ printf "%'d\n" 1024
1,024
$ printf "%'d\n" 1024601
1,024,601
$

使用 printf 添加前导零

printf 的另一个常见用途是在文件名上强制执行特定格式。例如,如果您的计算机上有 10 个顺序文件,则计算机可能会在 1.jpg 之前对 10.jpg 进行排序,这可能不是您的本意。以编程方式写入文件时,可以使用 printf 来形成带有前导零字符的文件名。这是一个 Bash 中的示例,为了简洁起见

$ printf "%03d.jpg\n" {1..10}
001.jpg
002.jpg
[...]
010.jpg

请注意,每个数字最多使用 3 位。

使用 printf

从这些 printf 示例中可以看出,包括控制字符,尤其是 \n,可能很乏味,并且语法相对复杂。这就是开发 echocout 等快捷方式的原因。但是,如果您偶尔使用 printf,您将习惯该语法,并且它将成为第二天性。我不认为 printf 应该是您日常活动中打印语句的首选,但它是一个很棒的工具,足够熟悉它,以至于在您需要它时不会拖慢您的速度。

花一些时间学习您选择的语言中的 printf,并在您需要时使用它。这是一个强大的工具,您不会后悔拥有它。

接下来阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,并且经常同时工作。

2 条评论

您使用 000%d 左填充文件名的做法是完全错误的。您的格式字符串应该是 %03d

您完全正确。我已在文章中更正,以供后人参考。

回复 ,作者:Chris Elvidge (未验证)

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.