HOWTO · C

在 C 语言中的 printf 函数中对齐列

本文介绍了如何在 C 语言中的 printf 函数中对齐列。

本页内容

在 C 中,可以使用 printf 的字段宽度来对齐列。%10d 会将整数右对齐到至少 10 个字符宽的字段中;%*d 从参数中获取宽度,%0*d 则在整数前补零。要在表格中左对齐文本,可使用 %-*s 或 - 标志。

使用字段宽度对齐 C 语言输出

字段宽度规定了一个值所占字符数的最小值。对于整数,%10d 会将值右对齐;如果不足 10 个字符,就在左侧补空格。若值更宽,则会完整输出,因此字段宽度不会截断它。当一列的末尾需要对齐时,这种方式很有用;由于转换默认右对齐,较短的值会从更靠右的位置开始。

下面的完整示例展示了右对齐的值以及一个清晰可见的分隔符:

#include <stdio.h>

int main(void) {
  int values[] = {11011, 111, 11};

  for (int i = 0; i < 3; ++i) {
    printf("%10d | %d\n", values[i], values[i]);
  }

  return 0;
}
     11011 | 11011
       111 | 111
        11 | 11

第一个转换预留至少 10 个字符的宽度;第二个转换使用该值的自然宽度。| 字符使字段边界清晰可见。一般来说,像 %10d 这样的格式中的数字表示字段宽度的最小总长度,而不是要添加的空格数。

使用 %*d 指定动态字段宽度

如果只有在程序运行时才能确定字段宽度,可使用 %*d。转换中的每个 * 都会消耗一个 int 参数,该参数紧挨着对应值之前。例如,在 printf("%*d", width, value) 中,width 提供字段宽度,value 提供整数。

下面的完整示例在运行时设置宽度,并在每个整数值之前传入该宽度:

#include <stdio.h>

int main(void) {
  int width = 10;
  int values[] = {11011, 111, 11};

  for (int i = 0; i < 3; ++i) {
    printf("%*d | %d\n", width, values[i], values[i]);
  }

  return 0;
}
     11011 | 11011
       111 | 111
        11 | 11

第一个转换将 width 的值用作字段宽度下限,因此较短的整数前会补空格,较宽的值则保持完整。第二个转换以该整数的自然宽度输出同一个值。

- 标志会使值左对齐。它可以与动态宽度组合使用,例如 %-*d;宽度参数仍应放在值参数之前。例如,printf("%*d | %-*d\n", width, value, width, value) 会在每个对应的整数之前传入 width。第一个字段默认右对齐,第二个字段左对齐。如果每行的布局不同,可在相应的值之前传入不同的宽度。

组合字段宽度以对齐表格列

对于包含不同类型内容的表格,应为文本字段和数字字段设置适合目标列的宽度。- 标志会使标签左对齐;整数转换若不使用该标志,则会将数字右对齐。| 分隔符用于区分各列。使用 %*.*d 时,第一个 * 消耗宽度参数,第二个 * 消耗精度参数,最后一个参数是整数值。整数精度规定了数字位数的最小值,必要时会在前面补零。

下面的完整表格示例使用固定宽度的列来显示表头和示例行。由于代码块和输出块保持原样,其中可见的表格标签仍为英文:

#include <stdio.h>

int main(void) {
  int width = 12;

  printf("%-*s | %-*s | %*s\n", width, "Number", width,
         "Description", width, "Value");
  printf("%-*d | %-*s | %*.*d\n", width, 123, width, "First",
         width, 4, 4567);
  printf("%-*d | %-*s | %*.*d\n", width, 456, width, "Second",
         width, 4, 789);

  return 0;
}
Number       | Description  |        Value
123          | First        |         4567
456          | Second       |         0789

这里将数字列和描述列设为左对齐,以便快速浏览各行;从整数转换中移除 -,即可改为右对齐该数字。每个通过 * 提供的宽度或精度都必须按相同顺序对应一个 int 参数。包含多字节字符或宽字符的文本,其终端显示宽度可能有所不同,因此这些按字节处理的示例使用普通 ASCII 文本。

使用 %0*d 为整数补零

如果整数需要达到指定的最小宽度,并在前面补零,可使用 %0*d。其中的 * 会在整数之前消耗宽度参数。与 %*d 补空格不同,补零能让数字标识符和计数保持一致的位数。

下面的完整示例以至少五位数字的宽度输出两个整数:

#include <stdio.h>

int main(void) {
  int width = 5;

  printf("%0*d\n", width, 123);
  printf("%0*d\n", width, 7);

  return 0;
}
00123
00007

字段宽度是最小值,因此位数超过所选宽度的值仍会完整输出。对于表格,可为每一行应用相同的数字宽度;表头或文本则使用补空格的字段。

总结

布局已确定时,可选择 %10d 或其他固定字段宽度。宽度来自变量时,使用 %*d;字段需要左对齐时,添加 -。对于需要在前面补零的数字标识符或计数,使用 %0*d。这些格式选项能让普通 ASCII 控制台输出更易阅读;对于其他文本,终端显示宽度可能会影响对齐。