UNIX 中 printf 指定参数绑定顺序

UNIX 中的 printf

Single UNIX Specification 中允许 printf 使用 %m$*m$ 的形式来绑定第 m 个参数,其中 m 从 1 开始计数。如果使用了这种表达方式,则所有参数都要指定序号,而且不能遗漏参数。这样做的好处是:可以多次使用同一个参数。

请注意,参数是 %m$*m$ 这两个结构索取的。这意味着以下两行的含义相同:

printf("%*d", width, num);
printf("%2$*1$d", width, num);

首先 %2$ 索要了参数 num 用来表示输出的数字,然后 *m$ 索要了参数 width 来表示输出的宽度。这和我们看到的 %*d 的参数顺序有差异:%*d 中就好像输出数字这个参数是 d 索取的一样。相关链接:StackOverflow 的提问

C99 中没有规定这种指定序号绑定参数的方式。

对比:Java 中的 printf

在 Java 中,printfFormatter 类支持。这种多次使用一个参数的用法可以极大地方便日期的输出。比如:

Date date = new Date();
System.out.printf("%1$tH:%1$tM:%1$tS %1$tp %1$tL %1$tN %1$tz %n", date);

测试打印结果:

00:43:08 上午 280 280000000 +0800

不过,像 UNIX 那样用下标指定打印数和宽度没有成功后来发现 Java 的格式化器不支持 *。不只是 *m$,是 variable width / precision 这一整个功能都不支持!

public class Main {
    public static void main(String args[]) {
        int width = 4;
        int num = 7;
        System.out.printf("%2$*1$d", width, num);
    }
}

// Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = '2'

Java 的 printf 还有一些其他扩展,比如说可以用 ^ 居中。