HOWTO · C

Alinhar colunas na função printf em C

Este artigo apresenta como alinhar colunas na função printf em C

Nesta página

Use a largura de campo de printf para alinhar colunas em C. %10d alinha um inteiro à direita em um campo com pelo menos 10 caracteres; %*d recebe essa largura como argumento, e %0*d preenche o inteiro com zeros à esquerda. Use %-*s ou a flag - para alinhar texto à esquerda em uma tabela.

Use uma largura de campo para alinhar a saída em C

A largura de campo define o número mínimo de caracteres usados para exibir um valor. Para um inteiro, %10d alinha o valor à direita e preenche o espaço à esquerda com espaços quando ele ocupa menos de 10 caracteres. Um valor mais longo é exibido por completo, pois a largura não o trunca. Isso é útil quando você quer alinhar os últimos caracteres de uma coluna: valores menores começam mais à direita porque a conversão é alinhada à direita.

Este exemplo completo mostra os valores alinhados à direita ao lado de um separador visível:

#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

A primeira conversão reserva uma largura mínima de 10; a segunda usa a largura natural do valor. O caractere | deixa visível o limite do campo. Em geral, o número em um formato como %10d indica a largura mínima total do campo, e não a quantidade de espaços a acrescentar.

Use %*d para uma largura de campo dinâmica

Use %*d quando a largura do campo só for conhecida durante a execução do programa. Cada * em uma conversão consome um argumento do tipo int imediatamente antes do valor correspondente. Por exemplo, em printf("%*d", width, value), width define a largura do campo e value fornece o inteiro.

Este exemplo completo define a largura durante a execução e a passa imediatamente antes de cada valor inteiro:

#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

A primeira conversão usa o valor de width como largura mínima do campo: por isso, inteiros menores recebem espaços à esquerda, enquanto valores maiores permanecem intactos. A segunda conversão exibe o mesmo inteiro com sua largura natural.

A flag - alinha o valor à esquerda. Ela pode ser combinada com uma largura dinâmica como em %-*d; o argumento da largura continua vindo antes do argumento do valor. Por exemplo, printf("%*d | %-*d\n", width, value, width, value) usa width antes de cada inteiro correspondente. O primeiro campo é alinhado à direita por padrão, e o segundo, à esquerda. Passe uma largura diferente antes de um valor quando o layout variar entre as linhas.

Combine larguras de campo para alinhar colunas de uma tabela

Em uma tabela com tipos mistos, defina larguras para os campos de texto e numéricos que se ajustem às colunas desejadas. A flag - alinha rótulos à esquerda, enquanto conversões de inteiros sem essa flag alinham os números à direita. Um separador | distingue as colunas. Em %*.*d, o primeiro * consome a largura, o segundo consome a precisão e o argumento final é o valor inteiro. A precisão de um inteiro define uma quantidade mínima de dígitos e acrescenta zeros à esquerda quando necessário.

Este exemplo completo de tabela usa colunas de largura fixa para os cabeçalhos e as linhas de exemplo. Os rótulos visíveis permanecem em inglês, pois os blocos de código e de saída são mantidos idênticos ao original:

#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

As colunas de número e descrição estão alinhadas à esquerda para facilitar a leitura das linhas; remova - de uma conversão de inteiro para alinhar esse número à direita. Cada largura ou precisão indicada com * precisa ter um argumento int correspondente, na mesma ordem. A largura visual no terminal pode variar para textos com caracteres multibyte ou de largura dupla, por isso estes exemplos orientados a bytes usam texto ASCII comum.

Use %0*d para inteiros preenchidos com zeros

Use %0*d quando um inteiro precisar de uma largura mínima preenchida com zeros à esquerda. O * consome o argumento da largura antes do inteiro. Diferentemente do preenchimento com espaços de %*d, o preenchimento com zeros mantém identificadores numéricos e contagens com uma quantidade consistente de dígitos.

Este exemplo completo exibe dois inteiros com uma largura mínima de cinco dígitos:

#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

A largura é mínima, portanto um valor com mais dígitos do que o limite escolhido continua sendo exibido por completo. Em uma tabela, aplique a mesma largura numérica a cada linha e use campos preenchidos com espaços para cabeçalhos ou texto.

Conclusão

Escolha %10d ou outra largura de campo fixa quando o layout for conhecido. Use %*d quando a largura vier de uma variável e acrescente - quando um campo precisar ficar alinhado à esquerda. Use %0*d para identificadores numéricos ou contagens que precisem de zeros à esquerda. Essas opções de formato facilitam a leitura de saídas de console com texto ASCII comum, embora a largura visual de outros textos possa afetar o alinhamento.