O
printf, velho "amigo" dos programadores C, é esquisito a primeira vista. Principalmente ao pessoal que está aprendendo lógica, acostumado com algoritmos, demora um pouco para entender seu jeito de ser.
Basicamente o printf do C é dividido em duas partes bem distintas, sendo que pelo menos a primeira delas deve existir.
A primeira parte é chamada de string de formato ou, do inglês, format string. Ela nada mais é do que dizer ao printf que faça alguma coisa.
Exemplo:
printf("Ola");
Isto pode ser interpretado como uma ordem ao printf:
- imprima a letra 'O';
- imprima a letra 'l';
- imprima a letra 'a'.
Dentro da string de formato, algumas sequências especiais de caracteres são comandos, como o '\n' por exemplo:
printf("Ola\n");
Isto pode ser interpretado como uma ordem ao printf:
- imprima a letra 'O';
- imprima a letra 'l';
- imprima a letra 'a'.
- imprima uma quebra de linha ('\n')
Na verdade sempre que na string de formato for encontrada uma contra barra ('\') ou um porcento ('%') será um comando. Alguns comandos mais usados:
- \t - imprima uma tabulação
- \\ - imprima uma contra barra
- %d - imprima um valor em formato decimal (e como tem gente que confunde o 'd' de double. Para double use %lf)
- %c - imprima um caractere
- %i - imprima um valor no formato inteiro
- %f - imprima um valor no formato ponto flutuante
- %lf - imprima um valor no formato ponto flutuante long (long float), ou seja, double
- %% - imprima o caractere %
Se a string de formato tiver um comando que mande imprimir alguma coisa, esta "alguma coisa" deverá ser fornecida. Assim, a segunda parte do printf são os parâmetros que satisfazem a string de formato. Exemplo:
printf ("Val=%d\n", 345);
- imprima o 'V';
- imprima o 'a';
- imprima o 'l';
- imprima o '=';
- imprima um número em formato decimal ('%d');
- imprima uma quebra de linha ('\n')
A segunda parte possui apenas um valor, o 345, que será usado pelo único %d existente.
Para cada comando que necessite de um parâmetro, um valor a mais deve estar na segunda parte. Coisas "estranhas" ocorrem quando se passa parâmetros de menos ou de mais.
Mas o objetivo deste artigo não é explicar o printf. Ele tem muitas outras opções além destas. O objetivo é tratar alguns parâmetros interessantes, pouco explorados pela maioria dos programadores. Começando pelo retorno da função, que praticamente ninguém usa.
O printf retorna um número inteiro, que é justamente a quantidade de caracteres que foram impressos.
tot = printf("Ola %d", 300);
No trecho de código anterior, tot acabará tendo o valor 7, pois será impresso na tela "Ola 300" (sem quebra de linha) e isto totalizaram sete caracteres.
Mas é no quesito "formatação" que o printf mostra do que é capaz.
É possível colocar o número de casas reservadas para a impressão, junto com o printf. Exemplo:
printf("Valor = %5d\n", 3);
printf("Valor = %5d\n", 30);
printf("Valor = %5d\n", 300);
printf("Valor = %5d\n", 3000);
printf("Valor = %5d\n", 30000);
O %5d indica que será impresso um decimal usando cinco casas decimais. As casas não usadas serão preenchidas com espaço em branco. A sequência de comandos anterior irá gerar a seguinte saída:
Valor = 3
Valor = 30
Valor = 300
Valor = 3000
Valor = 30000
Observe que os números ficaram à direita. Caso seja do interesse que o número fique à esquerda, basta colocar um sinal de menos antes:
printf("a=[%5d]\n", 3);
printf("a=[%-5d]\n", 3);
Observe como o número 3 foi ajustado entre os colchetes nas duas versões do printf.
Em se tratando de números, é ainda possível usar o ZERO para preencher os espaços não usados:
printf("a = %05d\n", 3);
printf("a = %05d\n", 30);
printf("a = %05d\n", 300);
Estes parâmetros são até bem conhecidos. Mas o que poucos sabem é que o 5, número de casas, pode ser também uma variável!
Considere este exemplo:
char frases[4][200];
int i;
for (i = 0; i < 4; i++){
/* lendo 4 frases */
scanf("%s", frases[i]);
}
for (i = 0; i < 4; i++){
/* imprimindo formatado as 4 frases */
printf("%-10s %d\n", frases[i], i);
}
Se o usuário digitar as seguintes frases:
Apenas_Um_Teste
lixo
Vol
hehehe
Será impresso na tela:
Apenas_Um_Teste 0
lixo 1
Vol 2
hehehe 3
Veja que o "Apenas_um_teste" foi maior do que o tamanho 10 inicialmente pensado, por isto ele ficou desformatado.
No entanto, o seguinte código tem um aspecto bem melhor:
char frases[4][200];
int i, m=-1,x;
for (i = 0; i < 4; i++){
/* lendo 4 frases */
scanf("%s", frases[i]);
x = strlen(frases[i]);
if (x > m)
m = x;
}
m = m + 1;
for (i = 0; i < 4; i++){
/* imprimindo formatado as 4 frases */
printf("%-*s %d\n", m, frases[i], i);
}
Agora o tamanho da maior string digitada é armazenado na variável m. Quando elas foram impressas, usou-se o comando:
printf("%-*s %d\n", m, frases[i], i);
Veja que tem um asterisco no lugar de onde estaria o valor 10. Isto indica ao printf para usar um dos parâmetros no lugar do *.