C Entrada com scanf
Até agora, todos os valores dos seus programas estavam escritos no próprio código: int idade = 29;. Para mudar a idade, só editando e compilando de novo. Um programa de verdade pergunta: qual é a sua idade? Quanto custa o produto? Nesta aula você vai aprender o scanf, a função do C que lê o que a pessoa digita no teclado e guarda numa variável, e as armadilhas que fazem dele a função mais perguntada nos fóruns de C: o & esquecido, o %lf do double e o Enter que sobra.
- Como ler um número digitado com
scanf("%d", &idade), e para que serve o&. - Como ler vários valores de uma vez, e o que o
scanffaz com espaços, Enters e outros caracteres. - As letras de cada tipo:
%d,%lf(double),%f(float),%c,%se%i, e onde elas são diferentes das doprintf. - O valor de retorno: como saber se a pessoa digitou mesmo um número.
- O espaço mágico do
" %c"e a largura do"%19s". - Os erros reais:
Falha de segmentaçãosem o&, oR$ 0.00do%fcomdoublee ostack smashing detected.
Todos os programas desta aula foram compilados com o gcc 15.2 na máquina fictícia da Ana (usuária ana, computador notebook), na pasta ~/c, com o comando padrão do guia: gcc -std=c23 -Wall -Wextra arquivo.c -o programa. Nos terminais, o que vem logo depois de uma pergunta do programa (como o 29 em Quantos anos você tem? 29) foi digitado pela Ana, seguido de Enter.
A ideia: o formulário de papel
Lembra do printf? Ele é um formulário já preenchido: o texto tem lacunas (%d) e o programa coloca os valores nelas para mostrar na tela.
O scanf é o caminho contrário. Ele é um formulário em branco que você entrega para a pessoa. O %d diz "aqui vai um número inteiro". A pessoa escreve, e o scanf lê o que foi escrito e guarda na gaveta que você indicou, a variável. Para isso ele precisa saber onde fica a gaveta, e é por isso que aparece o &.
O nome vem de scan formatted, "ler formatado" (o printf é print formatted, "imprimir formatado"). Ele mora no mesmo <stdio.h> do printf.
1. A primeira leitura
#include <stdio.h>
int main(void) {
int idade = 0;
printf("Quantos anos você tem? ");
scanf("%d", &idade);
printf("Daqui a 10 anos você terá %d anos.\n", idade + 10);
return 0;
}
$ gcc -std=c23 -Wall -Wextra idade.c -o idade $ ./idade Quantos anos você tem? 29 « o programa parou e esperou; a Ana digitou 29 e apertou Enter Daqui a 10 anos você terá 39 anos.
- int idade = 0;
- A gaveta que vai receber o número. Começa com 0 para nunca ter lixo (aula Variáveis): logo abaixo você vai ver por que isso importa.
- printf("Quantos anos você tem? ");
- A pergunta, o prompt. Sem
\nno fim, de propósito: assim o que a pessoa digita aparece na mesma linha da pergunta. Oscanfnão mostra nada sozinho; sem esseprintf, o programa ficaria parado numa tela vazia, e a pessoa nem saberia que ele está esperando. - scanf(
- Chama a função. O programa para aqui e espera a pessoa digitar e apertar Enter.
- "%d"
- O formato: "leia um número inteiro". É a mesma letra do
printf. - &idade
- O endereço da variável
idade: o lugar da memória onde ela mora. O&se lê "endereço de". Oprintfsó precisa do valor para mostrar (idade); oscanfprecisa saber onde guardar (&idade). - idade + 10
- Depois do
scanf,idadevale o que foi digitado e pode ser usada como qualquer variável.
&? Uma prévia
Quando você chama uma função, o C entrega a ela uma cópia do valor. Se o scanf recebesse idade, receberia uma cópia do 0, e não teria como mudar a variável de verdade. Com &idade, ele recebe o endereço e escreve direto na gaveta. Isso tem nome, ponteiro, e aulas inteiras: Memória e Endereços, Ponteiros e Passar por Ponteiro. Por enquanto, guarde a regra: no scanf, número e caractere levam &.
E se a pessoa digitar outra coisa?
$ ./idade Quantos anos você tem? abc Daqui a 10 anos você terá 10 anos. « "abc" não é número: o scanf não guardou nada, e idade continuou 0 $ ./idade Quantos anos você tem? 29 anos Daqui a 10 anos você terá 39 anos. « leu o 29 e parou no espaço; o " anos" ficou sem ler
O %d lê algarismos (com um sinal - ou + na frente, se tiver) e para no primeiro caractere que não serve para um número. Com abc, ele para logo no a, sem ter lido nada, e a variável fica como estava. Foi por isso que ela começou com 0: sem o = 0, o programa mostraria um valor qualquer que estivesse na memória. A seção 4 mostra como o programa descobre que a leitura falhou.
Experimente: clique em Rodar. O programa vai parar na pergunta: clique no terminal da caixa, digite a sua idade e aperte Enter. Rode de novo e digite abc, depois -5 e depois 42 (com espaços antes). Depois troque a pergunta e a conta: pergunte quantas horas a pessoa dorme por noite e mostre quantas horas ela dorme por semana (horas * 7).
#include <stdio.h>
int main(void) {
int idade = 0;
printf("Quantos anos você tem? ");
scanf("%d", &idade);
printf("Daqui a 10 anos você terá %d anos.\n", idade + 10);
return 0;
}
2. Esqueci o &
É o erro número 1 de quem começa. Sem o &, o scanf recebe o valor da variável (0) e acha que ele é um endereço:
#include <stdio.h>
int main(void) {
int idade = 0;
printf("Quantos anos você tem? ");
scanf("%d", idade);
printf("Você tem %d anos.\n", idade);
return 0;
}
$ gcc -std=c23 -Wall -Wextra semE.c -o semE
semE.c: In function ‘main’:
semE.c:6:13: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
6 | scanf("%d", idade);
| ~^ ~~~~~
| | |
| | int
| int *
$ ./semE
Quantos anos você tem? 29
Falha de segmentação (imagem do núcleo gravada) ./semE
- O aviso diz: "o formato
%despera um argumento do tipoint *, mas o argumento 2 é do tipoint". O*emint *quer dizer "endereço de umint". O desenho embaixo do código aponta as duas partes que não combinam: o%de oidade. - Ele compilou mesmo assim: é só um aviso. Mas o programa tentou escrever o 29 no "endereço 0", que não pertence a ele, e o sistema o derrubou:
Falha de segmentação(segmentation fault), código de saída 139. - Conserto:
scanf("%d", &idade);.
O -Wall confere cada % do formato contra a variável que você passou. Um aviso -Wformat num scanf quase sempre é um programa que vai ler errado ou cair. No editor do guia, o Clang avisa com outras palavras (format specifies type 'int *' but the argument has type 'int'), e o programa não cai: mostra Você tem 0 anos., porque a memória do WebAssembly é organizada de outro jeito (aula O Editor do Guia). Não confie nisso: no Linux, cai.
3. Vários valores de uma vez
Um formato pode ter várias lacunas. Cada uma precisa da sua variável, na mesma ordem, cada uma com o seu &:
#include <stdio.h>
int main(void) {
int a = 0;
int b = 0;
printf("Digite dois números: ");
scanf("%d %d", &a, &b);
printf("%d + %d = %d\n", a, b, a + b);
return 0;
}
$ gcc -std=c23 -Wall -Wextra soma.c -o soma $ ./soma Digite dois números: 3 4 3 + 4 = 7 $ ./soma Digite dois números: 3 « a Ana apertou Enter depois do 3… 4 « …e o scanf continuou esperando o segundo número 3 + 4 = 7 $ ./soma Digite dois números: 3,4 3 + 0 = 3 « a vírgula não é espaço: o segundo %d não leu nada
Três regras explicam essas saídas:
%dpula os brancos antes do número. "Brancos" são espaços, tabulações e Enters. Por isso tanto faz digitar3 4,3Enter4ou3 4: o resultado é o mesmo.- Um espaço no formato (o de
"%d %d") quer dizer "pule quantos brancos houver, inclusive nenhum". Como o%djá pula brancos sozinho, aqui ele não muda nada; na seção 5 ele vai fazer toda a diferença. - O
scanfpara no primeiro problema. Em3,4, o primeiro%dleu o 3 e parou na vírgula. O segundo%dencontrou a vírgula, que não é número nem branco, e desistiu. Obcontinuou 0.
Outros caracteres no formato
Qualquer outro caractere no formato precisa aparecer igualzinho na entrada. Isso serve para ler uma data com barras:
#include <stdio.h>
int main(void) {
int dia = 0;
int mes = 0;
int ano = 0;
printf("Data (dia/mês/ano): ");
int lidos = scanf("%d/%d/%d", &dia, &mes, &ano);
printf("Li %d valores: dia %d, mês %d, ano %d\n", lidos, dia, mes, ano);
return 0;
}
$ gcc -std=c23 -Wall -Wextra data.c -o data $ ./data Data (dia/mês/ano): 17/10/2026 Li 3 valores: dia 17, mês 10, ano 2026 $ ./data Data (dia/mês/ano): 17-10-2026 Li 1 valores: dia 17, mês 0, ano 0 « esperava "/" e veio "-": parou depois do dia
O int lidos = scanf(…) é novidade: o scanf devolve um número, e esse número é o assunto da próxima seção. Um detalhe: com "%d/%d/%d", a entrada 17 / 10 / 2026 (com espaços) também lê só o dia, porque a barra do formato tem de vir logo depois do número. Para aceitar espaços, ponha espaços no formato: "%d /%d /%d".
4. O valor de retorno: deu certo?
O scanf devolve quantas lacunas conseguiu preencher. Este programa mostra esse número:
#include <stdio.h>
int main(void) {
int a = 0;
int b = 0;
int lidos = scanf("%d %d", &a, &b);
printf("scanf devolveu %d (a = %d, b = %d)\n", lidos, a, b);
return 0;
}
$ gcc -std=c23 -Wall -Wextra retorno.c -o retorno $ ./retorno 3 4 scanf devolveu 2 (a = 3, b = 4) « as duas lacunas preenchidas $ ./retorno 3 x scanf devolveu 1 (a = 3, b = 0) « só a primeira $ ./retorno x 4 scanf devolveu 0 (a = 0, b = 0) « nenhuma: parou logo no x $ ./retorno scanf devolveu -1 (a = 0, b = 0) « a Ana apertou Ctrl+D sem digitar nada: fim da entrada
O scanf devolveu | Significa |
|---|---|
| o número de lacunas (aqui, 2) | Tudo lido. |
| um número menor (1, 0) | Parou no meio: veio algo que não combina com o formato. As variáveis que faltaram ficaram como estavam. |
EOF (vale -1) | End of file, "fim do arquivo": a entrada acabou antes de ler qualquer coisa. No teclado do Linux, é o Ctrl+D; quando a entrada vem de um arquivo, é o fim dele. |
A receita de segurança
Um programa de verdade confere esse número antes de usar a variável. A forma mais comum usa um if ("se"), que tem aula própria (if e else). Por enquanto, leia como uma frase: "se o scanf não leu 1 valor, avise e termine o programa".
#include <stdio.h>
int main(void) {
int idade = 0;
printf("Quantos anos você tem? ");
if (scanf("%d", &idade) != 1) {
printf("Isso não é um número.\n");
return 1;
}
printf("Daqui a 10 anos você terá %d anos.\n", idade + 10);
return 0;
}
$ gcc -std=c23 -Wall -Wextra checada.c -o checada $ ./checada Quantos anos você tem? abc Isso não é um número. $ echo $? 1 « o código de saída: 1 avisa que deu errado $ ./checada Quantos anos você tem? 17 Daqui a 10 anos você terá 27 anos.
- if (scanf("%d", &idade) != 1)
- Primeiro o
scanfroda e lê. Depois o número que ele devolveu é comparado com 1 (!=é "diferente de"; aula Operadores de Comparação). Se for diferente, o bloco entre{ }roda. - return 1;
- Termina o
mainali mesmo, com código de saída 1. Por costume, 0 é "deu certo" e qualquer outro número é "deu errado". O resto do programa não roda. - != 1
- Compare com o número de lacunas: com
"%d %d", o certo é!= 2. Não use== 0: ele deixaria passar oEOF(-1) e as leituras pela metade.
Com otimização (-O2), o gcc do Ubuntu liga proteções extras da biblioteca C e reclama quando o retorno do scanf é jogado fora:
$ gcc -std=c23 -Wall -Wextra -O2 idade.c -o idade
idade.c: In function ‘main’:
idade.c:6:5: warning: ignoring return value of ‘scanf’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
6 | scanf("%d", &idade);
| ^~~~~~~~~~~~~~~~~~~
"Ignorando o valor de retorno do scanf, declarado com o atributo warn_unused_result" (avise se o resultado não for usado). Sem -O2, e no editor do guia, esse aviso não aparece: o hábito de conferir tem de ser seu.
5. Letras e números com vírgula: %c, %lf, %f
double é %lf
Aqui o scanf é diferente do printf. No printf, %f serve para double e para float (aula Formatos do printf). No scanf, não: %f é só para float, e double exige %lf (de long float). A Ana errou isso na lojinha:
#include <stdio.h>
int main(void) {
double preco = 0.0;
printf("Preço do produto: ");
scanf("%f", &preco);
printf("Com desconto: R$ %.2f\n", preco * 0.9);
return 0;
}
$ gcc -std=c23 -Wall -Wextra preco.c -o preco
preco.c: In function ‘main’:
preco.c:6:13: warning: format ‘%f’ expects argument of type ‘float *’, but argument 2 has type ‘double *’ [-Wformat=]
6 | scanf("%f", &preco);
| ~^ ~~~~~~
| | |
| | double *
| float *
| %lf
$ ./preco
Preço do produto: 25.50
Com desconto: R$ 0.00 « 25.50 com 10% de desconto deveria dar 22.95
O %f mandou o scanf gravar um float (4 bytes) numa gaveta de double (8 bytes), no formato do float. Lido como double, aquele padrão de bits vira um número minúsculo, praticamente 0. O gcc avisou e até mostrou o conserto embaixo do código: %lf. O editor do guia dá o mesmo R$ 0.00.
Repare também que a entrada usa ponto: 25.50. O scanf segue o formato americano, como o printf (aula float e double). Com 25,50, ele lê o 25 e para na vírgula.
Missão: conserte o programa da Ana para ele mostrar o desconto certo, sem nenhum aviso. A entrada preparada é 25.50, e a saída esperada é:
Preço do produto: 25.50 Com desconto: R$ 22.95
#include <stdio.h>
int main(void) {
double preco = 0.0;
printf("Preço do produto: ");
scanf("%f", &preco);
printf("Com desconto: R$ %.2f\n", preco * 0.9);
return 0;
}
#include <stdio.h>
int main(void) {
double preco = 0.0;
printf("Preço do produto: ");
scanf("%lf", &preco);
printf("Com desconto: R$ %.2f\n", preco * 0.9);
return 0;
}
Com float, o %f é o certo. Os dois juntos:
#include <stdio.h>
int main(void) {
double preco = 0.0;
float peso = 0.0f;
printf("Preço do quilo e peso: ");
scanf("%lf %f", &preco, &peso);
printf("Total: R$ %.2f\n", preco * peso);
return 0;
}
$ gcc -std=c23 -Wall -Wextra preco2.c -o preco2 $ ./preco2 Preço do quilo e peso: 25.50 1.5 Total: R$ 38.25
%c e o Enter que sobra
O %c lê um caractere (aula Caracteres). Mas, diferente do %d, ele não pula brancos: um espaço ou um Enter também é um caractere. Veja o que acontece com o pedido de camisetas:
#include <stdio.h>
int main(void) {
int quantidade = 0;
char tamanho = '?';
printf("Quantas camisetas? ");
scanf("%d", &quantidade);
printf("Tamanho (P, M ou G)? ");
scanf("%c", &tamanho);
printf("Pedido: %d camiseta(s) tamanho [%c]\n", quantidade, tamanho);
return 0;
}
$ gcc -std=c23 -Wall -Wextra pedido.c -o pedido $ ./pedido Quantas camisetas? 3 Tamanho (P, M ou G)? Pedido: 3 camiseta(s) tamanho [ « nem deu tempo de digitar o tamanho! ]
- A Ana digitou
3e apertou Enter. Na entrada ficou:3\n(o Enter é o caractere\n; aula Escapes). - O
%dleu o3e parou antes do\n, que não faz parte do número. O\nsobrou na entrada. - O
%cpegou o primeiro caractere que encontrou: o\nque sobrou. Por isso o programa nem esperou, e os colchetes mostram uma quebra de linha.
O conserto é um espaço antes do %c: " %c". Lembra da regra da seção 3? O espaço no formato pula todos os brancos, inclusive o Enter que sobrou:
$ grep '%c"' pedido.c
scanf(" %c", &tamanho); « o espaço entre a aspa e o %
$ gcc -std=c23 -Wall -Wextra pedido.c -o pedido
$ ./pedido
Quantas camisetas? 3
Tamanho (P, M ou G)? M
Pedido: 3 camiseta(s) tamanho [M]
Regra prática: quase sempre que for ler um caractere com scanf, escreva " %c". O mesmo Enter que sobra atrapalha o fgets, que lê uma linha inteira; a aula Ler uma Linha mostra o problema e dois consertos.
Missão: a entrada preparada é 3, Enter, M. Conserte o formato do segundo scanf para o pedido sair com o tamanho certo:
Pedido: 3 camiseta(s) tamanho [M]
#include <stdio.h>
int main(void) {
int quantidade = 0;
char tamanho = '?';
printf("Quantas camisetas? ");
scanf("%d", &quantidade);
printf("Tamanho (P, M ou G)? ");
scanf("%c", &tamanho);
printf("Pedido: %d camiseta(s) tamanho [%c]\n", quantidade, tamanho);
return 0;
}
#include <stdio.h>
int main(void) {
int quantidade = 0;
char tamanho = '?';
printf("Quantas camisetas? ");
scanf("%d", &quantidade);
printf("Tamanho (P, M ou G)? ");
scanf(" %c", &tamanho);
printf("Pedido: %d camiseta(s) tamanho [%c]\n", quantidade, tamanho);
return 0;
}
6. Textos: %s lê uma palavra
Para ler um texto, a variável é um array de char, uma fileira de gavetas de letras (aula Strings). O %s lê uma palavra: pula os brancos do começo e para no primeiro espaço ou Enter.
#include <stdio.h>
int main(void) {
char nome[20];
printf("Seu nome: ");
scanf("%19s", nome);
printf("Olá, %s!\n", nome);
return 0;
}
$ gcc -std=c23 -Wall -Wextra nome.c -o nome $ ./nome Seu nome: Ana Maria Olá, Ana! « parou no espaço: o "Maria" ficou sem ler $ ./nome Seu nome: Bartolomeu_de_Gusmao_Albuquerque Olá, Bartolomeu_de_Gusma! « só os 19 primeiros caracteres
- char nome[20];
- Espaço para 20 caracteres. Um deles fica reservado para o
'\0', a marca de fim do texto que o C coloca sozinho. Sobram 19 para as letras. - %19s
- A largura: "leia no máximo 19 caracteres". Ela protege o array: o que passar disso fica na entrada, sem ler.
- nome, sem &
- A exceção da regra do
&. O nome de um array já é o endereço do começo dele (aula Ponteiros e Arrays). Número echarlevam&; array dechar, não.
Sem a largura: o estouro
Sem o 19, o %s escreve quantas letras vierem, mesmo que não caibam. Com char nome[8]; e scanf("%s", nome);:
$ gcc -std=c23 -Wall -Wextra estouro.c -o estouro $ ./estouro Seu nome: Maximiliano_Bartolomeu_de_Gusmao Olá, Maximiliano_Bartolomeu_de_Gusmao! *** stack smashing detected ***: terminated Abortado (imagem do núcleo gravada) ./estouro
Nenhum aviso na compilação. O nome de 32 letras não cabia nas 8 gavetas e o scanf escreveu por cima da memória vizinha. O Ubuntu compila os programas com uma proteção (o stack protector) que percebeu o estrago no fim do main e derrubou o programa: "esmagamento da pilha detectado". Nem sempre há essa sorte: um estouro desse tipo é a origem de muitas falhas de segurança, porque quem digita escolhe o que vai parar na memória. No editor do guia não há essa proteção, e o programa termina normalmente, com a memória estragada sem ninguém ver.
%s sempre com largura
A largura é o tamanho do array menos 1: char nome[20] → "%19s"; char cidade[50] → "%49s". Para ler um nome com espaços (Ana Maria), use o fgets.
7. %d ou %i?
No printf, %d e %i são iguais. No scanf, o %i entende a base pelo jeito como o número começa, como no código C (aula Inteiros): 0x é hexadecimal e um 0 na frente é octal (base 8).
#include <stdio.h>
int main(void) {
int d = 0;
int i = 0;
scanf("%d %i", &d, &i);
printf("%%d leu %d e %%i leu %d\n", d, i);
return 0;
}
$ gcc -std=c23 -Wall -Wextra inteiro.c -o inteiro $ ./inteiro 010 010 %d leu 10 e %i leu 8 « para o %i, 010 é octal: 1×8 + 0 = 8 $ ./inteiro 25 0x19 %d leu 25 e %i leu 25 « 0x19 em hexadecimal: 1×16 + 9 = 25
Para a idade, o mês ou a quantidade, ninguém quer que 08 dê problema. Use %d; o %i só quando você quer mesmo aceitar 0x….
Letras do scanf × do printf
| Tipo da variável | printf | scanf | Leva &? |
|---|---|---|---|
int | %d | %d | sim |
unsigned int | %u | %u | sim |
long / long long | %ld / %lld | %ld / %lld | sim |
float | %f | %f | sim |
double | %f (ou %lf) | %lf (%f lê errado) | sim |
char | %c | " %c" (com espaço antes) | sim |
char nome[20] | %s | %19s (largura = tamanho − 1) | não |
Formas diferentes de ler: qual usar
| Forma | Exemplo | Quando usar |
|---|---|---|
scanf sem conferir | scanf("%d", &n); | Só em testes rápidos. Se a pessoa digitar letras, o programa segue com um valor que ninguém digitou. |
scanf conferindo o retorno | if (scanf("%d", &n) != 1) { … } | O padrão deste guia para ler números nos exercícios. |
| Uma pergunta por vez | dois scanf("%d", …) | Mais claro para quem usa o programa: cada pergunta tem o seu prompt. |
| Vários valores numa linha | scanf("%d %lf", &q, &p) | Quando os valores andam juntos (quantidade e preço, dia/mês/ano). Confira com != 2, != 3… |
| Linha inteira | fgets(linha, sizeof linha, stdin) | Textos com espaços e programas que precisam ser à prova de qualquer entrada: aulas Ler uma Linha e Texto ↔ Número. |
gets | gets(nome) | Nunca. Não tem limite de tamanho; foi removido da linguagem no C11 (aula Ler uma Linha). |
Quando dá errado
warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’
O que significa: faltou o &: o scanf recebeu o valor da variável em vez do endereço. Rodando, o programa cai com Falha de segmentação. No editor (Clang): format specifies type 'int *' but the argument has type 'int'.
Como consertar: scanf("%d", &idade);.
warning: format ‘%f’ expects argument of type ‘float *’, but argument 2 has type ‘double *’
O que significa: a variável é double e o formato é o do float. O valor lido sai errado (no exemplo, 0.00).
Como consertar: %lf para double. O gcc mostra o conserto na última linha do aviso.
O que significa: um %c depois de outra leitura pegou o Enter que sobrou da anterior.
Como consertar: espaço antes do %c: scanf(" %c", &letra);.
O que significa: a entrada não combinou com o formato (letras no lugar de número, vírgula no lugar de ponto, um - no lugar da /) e o scanf desistiu sem guardar nada. A variável ficou com o valor de antes.
Como consertar: confira o retorno (if (scanf(…) != 1)) e avise a pessoa. Inicialize a variável, para o "valor de antes" nunca ser lixo.
*** stack smashing detected ***: terminated + Abortado
O que significa: um %s sem largura escreveu mais letras do que o array tinha de espaço. O gcc não avisa na compilação.
Como consertar: largura sempre: char nome[20] → scanf("%19s", nome).
O que significa: o %s para no primeiro espaço. Não é defeito: é a regra dele.
Como consertar: para ler a linha inteira, use fgets.
Referência rápida
| Escrita | O que faz |
|---|---|
scanf("%d", &n) | Lê um int, pulando os brancos antes dele. |
scanf("%d %d", &a, &b) | Lê dois inteiros, separados por espaços ou Enters. |
scanf("%d/%d/%d", …) | A / precisa aparecer igualzinha na entrada. |
scanf("%lf", &x) | Lê um double (com ponto: 25.50). |
scanf(" %c", &c) | Lê um caractere, pulando os brancos (e o Enter que sobrou). |
scanf("%19s", nome) | Lê uma palavra de até 19 letras, sem &. |
| retorno | Quantas lacunas foram preenchidas; EOF (-1) se a entrada acabou. |
| Ctrl+D | No terminal do Linux, encerra a entrada (o scanf devolve EOF). |
A tabela completa de formatos está em Referência: printf e scanf.
Exercícios
1. O endereço
Complete para ler um número inteiro na variável pontos:
2. O formato do double
Complete o formato para ler a variável double altura:
3. A letra depois do número
Complete com o formato inteiro, com as aspas, para ler a resposta s/n depois de um scanf("%d", …), sem pegar o Enter que sobrou:
4. Com int a = 0, b = 0; e a entrada 8 x, quanto scanf("%d %d", &a, &b) devolve?
5. Qual leitura está certa para char cidade[30];?
6. A Ana digitou Ana Maria para um scanf("%19s", nome). O que fica em nome?
Missão final: o caixa da lojinha
Missão: o caixa da lojinha da Ana lê, numa linha só, a quantidade (um int) e o preço de cada item (um double), e mostra o total. A entrada preparada é 3 12.50. Escreva o scanf que lê os dois valores e confira o retorno: se ele não for 2, mostre Entrada inválida. e termine com return 1;. Sem avisos. A saída deve terminar com:
Total: R$ 37.50
#include <stdio.h>
int main(void) {
int quantidade = 0;
double preco = 0.0;
printf("Quantidade e preço: ");
// leia a quantidade e o preço aqui, conferindo o retorno
printf("Total: R$ %.2f\n", quantidade * preco);
return 0;
}
#include <stdio.h>
int main(void) {
int quantidade = 0;
double preco = 0.0;
printf("Quantidade e preço: ");
if (scanf("%d %lf", &quantidade, &preco) != 2) {
printf("Entrada inválida.\n");
return 1;
}
printf("Total: R$ %.2f\n", quantidade * preco);
return 0;
}
Depois, troque o que está no campo Entrada da caixa e rode de novo. Com abc, o seu != 2 mostra Entrada inválida.. Com 3 12,50, porém, o total sai R$ 36.00, sem reclamação: o %lf leu o 12, parou na vírgula, e as duas lacunas foram preenchidas. O retorno do scanf pega a entrada errada, mas não a entrada pela metade. Para conferir a linha inteira, existe o caminho do fgets com strtol e strtod.
Resumo
scanf("%d", &n)para o programa, espera a pessoa digitar e apertar Enter, e guarda o número emn. Mostre antes uma pergunta comprintf.- O
&entrega o endereço da variável. Sem ele: aviso-WformateFalha de segmentação. Arrays dechar(%s) não levam&. %d,%lfe%spulam os brancos antes do valor; o%cnão pula, por isso use" %c".- No
scanf,doubleé%lf;%fé só parafloat. Números com ponto:25.50. - O
scanfdevolve quantas lacunas preencheu (ouEOF, -1). Confira sempre:if (scanf(…) != 1). %slê uma palavra; sempre com largura ("%19s"parachar nome[20]). Para linhas com espaços, fgets.- Próximo passo: Operadores Aritméticos, para fazer contas com os valores que você leu.