Entrada e Saída
Entrada e saída são como uma conversa entre você e o computador — printf é o computador falando com você, scanf é você falando com o computador. Acerte o formato, ou vocês vão falar um passando pelo outro.
Saída Formatada com printf
printf vem de "print formatted" (impressão formatada). Seu primeiro argumento é uma string de formato, seguida dos valores a serem exibidos.
Especificadores de Formato Básicos
| Especificador | Finalidade | Exemplo | Saída |
|---|---|---|---|
%d |
Inteiro decimal | printf("%d", 42) |
42 |
%f |
Ponto flutuante | printf("%f", 3.14) |
3.140000 |
%c |
Caractere único | printf("%c", 'A') |
A |
%s |
String | printf("%s", "oi") |
oi |
%x |
Hexadecimal | printf("%x", 255) |
ff |
%o |
Octal | printf("%o", 8) |
10 |
%p |
Endereço de ponteiro | printf("%p", &a) |
Valor do endereço |
%% |
Sinal de porcentagem literal | printf("100%%") |
100% |
#include <stdio.h>
int main(void) {
int idade = 25;
float altura = 175.5f;
char nota = 'A';
printf("Idade: %d, Altura: %.1f, Nota: %c\n", idade, altura, nota);
return 0;
}
Idade: 25, Altura: 175.5, Nota: A
Largura e Alinhamento
Você pode inserir números entre % e o especificador de formato para controlar a largura de saída:
%5d: Largura mínima de 5 caracteres, alinhado à direita%-5d: Largura mínima de 5 caracteres, alinhado à esquerda%05d: Preenche com zeros até 5 dígitos
#include <stdio.h>
int main(void) {
int num = 42;
printf("[%5d]\n", num);
printf("[%-5d]\n", num);
printf("[%05d]\n", num);
printf("[%+5d]\n", num);
return 0;
}
[ 42]
[42 ]
[00042]
[ +42]
Precisão de Ponto Flutuante
%.2f: 2 dígitos após o ponto decimal%8.2f: Largura total de pelo menos 8 caracteres, 2 dígitos após o ponto decimal%-8.2f: Versão alinhada à esquerda
#include <stdio.h>
int main(void) {
double pi = 3.14159265358979;
printf("Padrão: %f\n", pi);
printf("2 casas: %.2f\n", pi);
printf("6 casas: %.6f\n", pi);
printf("8.2: %8.2f\n", pi);
return 0;
}
Padrão: 3.141593
2 casas: 3.14
6 casas: 3.141593
8.2: 3.14
%f usa por padrão 6 casas decimais. Use %.0f para ocultar completamente a parte decimal.
Leitura de Entrada com scanf
scanf vem de "scan formatted" (leitura formatada). Ela lê dados da entrada padrão de acordo com a string de formato e os armazena em variáveis.
Uso Básico
#include <stdio.h>
int main(void) {
int idade;
float pontuacao;
printf("Digite sua idade: ");
scanf("%d", &idade);
printf("Digite sua pontuação: ");
scanf("%f", &pontuacao);
printf("Idade: %d, Pontuação: %.1f\n", idade, pontuacao);
return 0;
}
Digite sua idade: 20
Digite sua pontuação: 92.5
Idade: 20, Pontuação: 92.5
& (o operador de endereço), dizendo ao scanf "armazene o valor neste endereço." Esquecer o & é o erro mais comum de iniciante — o programa não vai dar erro mas vai travar.
Lendo Múltiplos Valores
#include <stdio.h>
int main(void) {
int a, b, c;
printf("Digite três inteiros (separados por espaços): ");
scanf("%d %d %d", &a, &b, &c);
printf("Você digitou: %d, %d, %d\n", a, b, c);
return 0;
}
Digite três inteiros (separados por espaços): 10 20 30
Você digitou: 10, 20, 30
Por padrão, scanf usa espaços em branco (espaços, novas linhas, tabs) para separar valores diferentes.
Lendo Caracteres e Strings
#include <stdio.h>
int main(void) {
char ch;
char nome[20];
printf("Digite um caractere: ");
scanf(" %c", &ch);
printf("Digite seu nome (sem espaços): ");
scanf("%s", nome);
printf("Caractere: %c, Nome: %s\n", ch, nome);
return 0;
}
%c (" %c") ignora caracteres de espaço em branco, caso contrário ele vai ler a nova linha residual da entrada anterior. %s lê uma string mas para no espaço em branco. nome é um nome de array, que já é um endereço, então não precisa de &.
O Valor de Retorno do scanf
scanf retorna o número de variáveis lidas com sucesso. Esse recurso pode ser usado para validar a entrada:
#include <stdio.h>
int main(void) {
int num;
printf("Digite um inteiro: ");
int resultado = scanf("%d", &num);
if (resultado == 1) {
printf("Lido com sucesso: %d\n", num);
} else {
printf("Entrada inválida!\n");
}
return 0;
}
Digite um inteiro: abc
Entrada inválida!
getchar e putchar
getchar() lê um único caractere do teclado, e putchar() exibe um único caractere na tela. São mais simples e eficientes que scanf("%c") e printf("%c").
#include <stdio.h>
int main(void) {
char ch;
printf("Digite um caractere: ");
ch = getchar();
printf("Você digitou: ");
putchar(ch);
putchar('\n');
return 0;
}
Digite um caractere: X
Você digitou: X
Lendo uma Linha Inteira
getchar() combinado com um loop pode ler uma linha inteira até encontrar uma nova linha:
#include <stdio.h>
int main(void) {
char ch;
printf("Digite uma linha de texto: ");
while ((ch = getchar()) != '\n') {
putchar(ch);
}
putchar('\n');
return 0;
}
Digite uma linha de texto: Olá Mundo!
Olá Mundo!
while ((ch = getchar()) != '\n') é um idioma clássico: primeiro lê um caractere em ch, depois verifica se é uma nova linha. Note que os parênteses externos ao redor da atribuição são obrigatórios.
Problemas de Buffer
A entrada padrão de C usa buffer de linha: a linha inteira de dados só é entregue ao buffer para o programa ler depois que o usuário pressiona Enter. Isso pode causar alguns problemas confusos.
Problema: scanf %c Lê uma Nova Linha Residual
#include <stdio.h>
int main(void) {
int num;
char ch;
printf("Digite um inteiro: ");
scanf("%d", &num);
printf("Digite um caractere: ");
scanf("%c", &ch);
printf("Inteiro=%d, Caractere=%d\n", num, ch);
return 0;
}
Digite um inteiro: 42
Digite um caractere: Inteiro=42, Caractere=10
Após digitar 42 e pressionar Enter, o buffer contém 42\n. scanf("%d") lê 42, e scanf("%c") imediatamente lê aquele \n residual (código ASCII 10), sem esperar você digitar um caractere.
Soluções
Solução 1: Adicionar um espaço antes de %c (recomendada)
scanf(" %c", &ch);
O espaço ignora todos os caracteres de espaço em branco (incluindo novas linhas, espaços e tabs).
Solução 2: Usar getchar() para absorver o residual
scanf("%d", &num);
getchar();
scanf("%c", &ch);
Solução 3: Limpar o buffer de entrada
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
fflush(stdin) para limpar o buffer de entrada — é comportamento indefinido em C padrão. Alguns compiladores suportam, mas não é portável.
Exemplo
Escreva um programa que leia tanto um inteiro quanto um caractere, tratando corretamente os resíduos do buffer:
#include <stdio.h>
int main(void) {
int idade;
char genero;
printf("Digite sua idade: ");
scanf("%d", &idade);
printf("Digite seu gênero (M/F): ");
scanf(" %c", &genero);
printf("Idade: %d, Gênero: %c\n", idade, genero);
return 0;
}
Digite sua idade: 25
Digite seu gênero (M/F): M
Idade: 25, Gênero: M
Exemplo
Use getchar() para ler caractere por caractere e contar o número de letras e dígitos em uma linha:
#include <stdio.h>
int main(void) {
char ch;
int letras = 0;
int digitos = 0;
printf("Digite uma linha de texto: ");
while ((ch = getchar()) != '\n') {
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
letras++;
} else if (ch >= '0' && ch <= '9') {
digitos++;
}
}
printf("Letras: %d, Dígitos: %d\n", letras, digitos);
return 0;
}
Digite uma linha de texto: Olá 2024!
Letras: 3, Dígitos: 4
puts e fputs
puts() exibe uma string e adiciona automaticamente uma nova linha. É mais simples que printf e ideal para saída de texto puro:
#include <stdio.h>
int main(void) {
puts("Olá, Mundo!");
puts("Nova linha automática, sem precisar de \\n");
return 0;
}
Olá, Mundo!
Nova linha automática, sem precisar de \n
puts() é mais eficiente que printf("%s\n", ...) porque não precisa analisar uma string de formato. Quando não precisa de formatação, prefira puts.
❓ Perguntas Frequentes
P: Por que as variáveis do scanf precisam de
&na frente? R: scanf precisa saber onde armazenar o valor, e&pega o endereço da variável. Só nomes de arrays não precisam, porque um nome de array já é o endereço do seu primeiro elemento.
P: scanf("%c") pulou minha entrada — o que aconteceu? R: Há uma nova linha residual no buffer de uma entrada anterior. Adicione um espaço antes de %c:
scanf(" %c", &ch)para ignorar espaços em branco.
P: Os especificadores de formato do printf e scanf podem ser maiúsculos? R: Alguns podem.
%dminúsculo corresponde a int;%Dmaiúsculo não é padrão. Mas%ximprime hex minúsculo (abcdef) enquanto%Ximprime maiúsculo (ABCDEF) — isso é válido.
P: Como leio uma string com espaços de forma segura? R:
scanf("%s")para no espaço em branco. Usefgets(nome, sizeof(nome), stdin)para ler uma linha inteira — suporta espaços e é mais seguro.
📖 Resumo
printfusa especificadores de formato para controlar a saída: largura, precisão, alinhamento, preenchimentoscanfexige&antes das variáveis; adicione um espaço antes de%cpara evitar ler novas linhas residuaisgetchar/putcharsão escolhas eficientes para E/S de caractere único- Buffer de linha causa problemas de dados residuais entre chamadas scanf e getchar
- O valor de retorno do scanf pode ser usado para validar se a entrada foi bem-sucedida
📝 Exercícios
- Escreva um programa que leia o raio de um círculo e exiba sua área e circunferência usando o formato
%.2fdo printf. - Escreva um programa que use
getchar()para ler uma linha de entrada e conte quantas letras maiúsculas e minúsculas ela contém. - Escreva um programa que leia um inteiro e o exiba nos formatos decimal (
%d), hexadecimal (%x) e octal (%o).



