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 主控台輸出更容易閱讀;其他文字的對齊則可能受到終端機顯示寬度影響。