Leitura e escrita formatada
Slides
I/O formatado
O printf
e scanf
são 2 das funções mais usadas quando programamos em C.
Ambas as funções permitem escrever/ler um número arbitrário de valores:
int altura, idade;
float massa, imc;
printf("Insira a idade e massa separadas por um espaco:");
scanf("%d %f", &altura, &massa);
printf("altura: %d\nmassa:%f\n", altura, massa);
Quando usamos múltiplos descritores nestas funções, a correspondência com as variáveis/expressões é feita por ordem sequencial:
- linha 1: o primeiro
%d
corresponde à variávelaltura
,%f
corresponde àmassa
- linha 2: idem
Os compiladores de C não são obrigados a verificar que o número de descritores é coerente com o número de valores fornecidos.
Os compiladores de C não são obrigados a verificar que o descritor %
usado é o apropriado para o tipo da expressão/variável.
printf
Os descritores %d
, %f
, … também podem ser denominados por especificações de conversão.
Número de digitos
%d
escreve o número inteiro que recebe, mas podemos definir um número de ditigos mínimo.
// output no comentário após as linhas
// • significa um espaço
printf("%d\n", 42); // -> 42
printf("%5d\n", 42); // -> •••42 (3 espaços antes do 2)
printf("%05d\n", 422); // -> 00042 (3 zeros antes do 2)
// output no comentário após as linhas
// • significa um espaço
printf("%d\n", 42); // -> 42
printf("%5d\n", 42); // -> •••42 (3 espaços antes do 2)
printf("%05d\n", 42); // -> 00042 (3 zeros antes do 2)
Especifica que o que é escrito deve ter pelo menos 5 caracteres, se não tiver, são adicionados espaços antes do número até os perfazer;
// output no comentário após as linhas
// • significa um espaço
printf("%d\n", 42); // -> 42
printf("%5d\n", 42); // -> •••42 (3 espaços antes do 4)
printf("%05d\n", 422); // -> 00042 (3 zeros antes do 4)
Indica o mesmo, mas são usados 0s para preencher.
Casas decimais
Podemos fazer o mesmo com os números reais.
printf("%f\n", 3.14159); // -> 3.141590
printf("%.2f\n", 3.14159); // -> 3.14 (2 casas decimais)
printf("%.f\n", 3.14159); // -> 3 (0 casas decimais, arredonda)
//também podia ser %.0f
printf("%5.2f\n", 3.14159); // -> •3.14 (2 casas decimais,
// pelo menos 5 characteres no total,
// adiciona 1 espaço antes)
printf("%05.2f\n", 3.14159); // -> 03.14 (adiciona 0s)
printf("%-5.2f\n", 3.14159); // -> 3.14• (2 casas decimais,
// pelo menos 5 characteres no total,
// adiciona 1 espaço depois)
regra geral
Temos a fórmula %m.pX
ou %-m.pX
, onde m
e p
são números naturais positivos, mas opcionais. X
é uma letra válida para conversão, e.g. d
ou f
.
m
é o número de caracteres mínimo que devem ser escritos, sendo adicionados, à esquerda, espaços, ou zeros se designarmos 0m
.
p
é o número de casas decimais a usar.
Quando temos -m
, adicionamos os espaços à direita do número.
tabela de especificações de conversão
letras | descrição |
---|---|
d | inteiros, p não faz sentido, m é o número mínimo de caracteres a serem escritos |
e | reais em notação científica, p é o número de casas decimais |
f | reais em “decimal fixo”, sem expoente, p tem o mesmo significado |
símbolos especiais
Símbolo | descrição |
---|---|
\n |
nova linha |
\t |
tabulação |
\\ |
permite inserir um \ |
\a |
causa um alerta sonoro na maior parte dos computadores |
scanf
Como funciona?
Na sua essência, o scanf
faz correspondência de padrões.
Tenta fazer a correspondência entre grupos de input com especificações de conversão.
Para cada especificação de conversão, o scanf
tenta encontrar um item do tipo apropriado no input recebido, parando quando recebe um caracter incompatível com esse tipo.
Se algum item não for lido com sucesso, o scanf
retorna sem tentar fazer a correspondência entre as restantes especificações de conversão com o resto do input.
Ao procurar pelo início de um número, todos os espaços em branco são ignorados, e.g. espaços, novas linhas, tabulações, …
int i, j;
float x, y;
scanf("%d%d%f%f", &i, &j, &x, &y);
printf("i=%d, j=%d\nx=%f, y=%f\n", i, j, x, y);
Este programa irá ler os seguintes números de igual forma:
Porquê é que isto acontece?
O scanf lê todo o input como uma sequência de caracteres. Os espaços, enters, tabulações, etc. são todos caracteres.
é equivalente a
onde ¤
é uma nova linha e •
é um espaço.
O scanf
pára de ler quando encontra um enter (nova linha) após a correspondência da última especificação de conversão.
O último enter não é consumido do input e por isso será o primeiro caracter a ser lido na próxima chamada do scanf
.
Regras de correspondência para inteiros %d
:
- procura pelo primeiro digito ou sinal de + ou -
- lê digitos até encontrar o primeiro caracter não digito
Regras de correspondência para reais %f %e
:
- procura pelo sinal de + ou - (opcional)
- lê uma série de digitos, que podem conter 1
.
a indicar que depois vêm casas decimais - um expoente (opcional): consiste na letra e ou E seguida de um sinal e mais digitos, e.g.
1e-3
(=0.001),1E3
(=10000).
Quando o scanf lê um caracter que não encaixa na especificação de conversão que está a ser processada, é novamente colocado no input para ser processado
Ler apenas N digitos
int d1, d2;
printf("Numero inteiro:");
scanf("%1d%2d", &d1, &d2); // utilizador escreve 242
printf("d1=%d\n", d1); // d1=2
printf("d2=%d\n", d2); // d2=42
%Nd
permite ler N
digitos inteiros.
Exercício
Soma de frações.