Entrada e saída com printf e scanf
1. Introdução às Funções de E/S Padrão
A linguagem C oferece funções poderosas para entrada e saída de dados através da biblioteca padrão <stdio.h>. Esta biblioteca fornece as funções printf (saída formatada) e scanf (entrada formatada), que são essenciais para a comunicação entre o programa e o usuário.
Os fluxos padrão em C são:
- stdin — fluxo de entrada padrão (geralmente o teclado)
- stdout — fluxo de saída padrão (geralmente o monitor)
- stderr — fluxo de saída de erro padrão
A principal diferença entre E/S formatada e não formatada está no controle sobre a apresentação dos dados. Enquanto funções como putchar e getchar trabalham caractere por caractere, printf e scanf permitem formatar e interpretar dados de maneira estruturada.
2. A Função printf: Saída Formatada
A sintaxe básica do printf é:
printf("string de formato", argumentos);
Os especificadores de formato mais comuns são:
| Especificador | Tipo de dado |
|---|---|
%d |
inteiro (int) |
%f |
ponto flutuante (float/double) |
%c |
caractere (char) |
%s |
string (char[]) |
Exemplo básico:
#include <stdio.h>
int main() {
int idade = 25;
float altura = 1.75;
char inicial = 'A';
char nome[] = "Maria";
printf("Idade: %d anos\n", idade);
printf("Altura: %.2f metros\n", altura);
printf("Inicial: %c\n", inicial);
printf("Nome: %s\n", nome);
return 0;
}
Modificadores de largura e precisão:
printf("%10d\n", 42); // largura mínima de 10 caracteres (alinhado à direita)
printf("%-10d\n", 42); // alinhado à esquerda
printf("%.2f\n", 3.14159); // duas casas decimais
printf("%10.3f\n", 3.14159);// largura 10, precisão 3
3. Especificadores Avançados em printf
Para inteiros, existem variações úteis:
int valor = 255;
printf("Decimal: %d\n", valor); // 255
printf("Sem sinal: %u\n", valor); // 255
printf("Hexadecimal: %x\n", valor); // ff
printf("Octal: %o\n", valor); // 377
printf("Longo: %ld\n", 123456L); // para long int
Para ponto flutuante:
double pi = 3.1415926535;
printf("Notação científica: %e\n", pi); // 3.141593e+00
printf("Formato compacto: %g\n", pi); // 3.14159
Caracteres especiais:
printf("Nova linha: \n");
printf("Tabulação: \tTexto tabulado\n");
printf("Barra invertida: \\\n");
printf("Porcentagem: %%\n");
4. A Função scanf: Entrada Formatada
O scanf lê dados do teclado conforme uma string de formato. É crucial usar o operador & (endereço) para variáveis que não são arrays.
#include <stdio.h>
int main() {
int numero;
float real;
char letra;
printf("Digite um inteiro: ");
scanf("%d", &numero);
printf("Digite um float: ");
scanf("%f", &real);
printf("Digite um caractere: ");
scanf(" %c", &letra); // espaço antes de %c ignora whitespace
printf("Você digitou: %d, %.2f, %c\n", numero, real, letra);
return 0;
}
Captura de múltiplos valores:
int dia, mes, ano;
printf("Digite a data (dd/mm/aaaa): ");
scanf("%d/%d/%d", &dia, &mes, &ano);
printf("Data: %02d/%02d/%04d\n", dia, mes, ano);
5. Tratamento de Erros e Validação em scanf
O scanf retorna o número de itens lidos com sucesso. Isso é fundamental para validação:
#include <stdio.h>
int main() {
int idade;
int resultado;
printf("Digite sua idade: ");
resultado = scanf("%d", &idade);
if (resultado == 1) {
printf("Idade válida: %d\n", idade);
} else {
printf("Entrada inválida!\n");
}
return 0;
}
Problema do buffer residual: Quando o usuário digita algo que não corresponde ao formato esperado, os caracteres permanecem no buffer, causando loops infinitos em leituras subsequentes.
Solução: limpeza do buffer
void limpar_buffer() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
Exemplo prático com validação:
#include <stdio.h>
int main() {
int numero;
int resultado;
do {
printf("Digite um número inteiro: ");
resultado = scanf("%d", &numero);
if (resultado != 1) {
printf("Erro! Digite apenas números.\n");
// Limpa o buffer
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
} while (resultado != 1);
printf("Número lido: %d\n", numero);
return 0;
}
6. Leitura de Strings com scanf e Alternativas
O scanf com %s lê apenas até o primeiro espaço em branco:
char nome[50];
printf("Digite seu nome completo: ");
scanf("%s", nome); // Lê apenas o primeiro nome!
printf("Nome: %s\n", nome); // Exibe apenas "Maria" se digitou "Maria Silva"
Solução com fgets:
char nome_completo[100];
printf("Digite seu nome completo: ");
fgets(nome_completo, sizeof(nome_completo), stdin);
printf("Nome: %s", nome_completo);
Combinação fgets + sscanf para validação:
#include <stdio.h>
#include <string.h>
int main() {
char entrada[100];
int idade;
float altura;
printf("Digite idade e altura (ex: 25 1.75): ");
fgets(entrada, sizeof(entrada), stdin);
// Remove o \n do final
entrada[strcspn(entrada, "\n")] = 0;
if (sscanf(entrada, "%d %f", &idade, &altura) == 2) {
printf("Idade: %d, Altura: %.2f\n", idade, altura);
} else {
printf("Formato inválido!\n");
}
return 0;
}
7. Exemplos Práticos e Boas Práticas
Calculadora simples:
#include <stdio.h>
int main() {
float a, b, resultado;
char operador;
int items_lidos;
printf("Digite: numero1 operador numero2 (ex: 10 + 5): ");
items_lidos = scanf("%f %c %f", &a, &operador, &b);
if (items_lidos != 3) {
printf("Entrada inválida!\n");
return 1;
}
switch (operador) {
case '+': resultado = a + b; break;
case '-': resultado = a - b; break;
case '*': resultado = a * b; break;
case '/':
if (b == 0) {
printf("Divisão por zero!\n");
return 1;
}
resultado = a / b;
break;
default:
printf("Operador inválido!\n");
return 1;
}
printf("%.2f %c %.2f = %.2f\n", a, operador, b, resultado);
return 0;
}
Leitura de data formatada:
#include <stdio.h>
int main() {
int dia, mes, ano;
char entrada[20];
printf("Digite a data (DD/MM/AAAA): ");
fgets(entrada, sizeof(entrada), stdin);
if (sscanf(entrada, "%d/%d/%d", &dia, &mes, &ano) == 3) {
if (dia >= 1 && dia <= 31 && mes >= 1 && mes <= 12 && ano >= 1900) {
printf("Data válida: %02d/%02d/%04d\n", dia, mes, ano);
} else {
printf("Data inválida!\n");
}
} else {
printf("Formato inválido!\n");
}
return 0;
}
Boas práticas resumidas:
- Sempre verifique o retorno de
scanf - Limpe o buffer após leituras com falha
- Prefira
fgets+sscanfpara entradas complexas - Use tamanhos máximos em arrays de caracteres
- Evite
scanf("%s", ...)sem limite de tamanho - Utilize modificadores de formato para evitar estouro de buffer
Referências
- Documentação oficial do printf (cppreference.com) — Referência completa da função printf com todos os especificadores e modificadores
- Documentação oficial do scanf (cppreference.com) — Referência completa da função scanf com exemplos de uso
- Tutorial de printf e scanf (GeeksforGeeks) — Explicação detalhada com exemplos práticos das funções de E/S formatada
- Guia de formatação de strings em C (TutorialsPoint) — Tutorial abrangente sobre formatação com printf
- Tratamento de buffer e validação com scanf (Programiz) — Guia prático sobre entrada e saída em C com dicas de boas práticas
- Documentação da biblioteca stdio.h (IBM) — Documentação técnica da biblioteca padrão de entrada e saída