📚 Capítulo do curso: 06 — Laços Indeterminados (while, do-while) e Sentinelas da Especialização em Sistemas com C. Leia o capítulo antes de começar.
Um caixa eletrônico de terminal que atende operações bancárias em loop até o usuário decidir sair.
🔒 Regra de Ouro: até o Capítulo 06, você só conhece os laços indeterminados
whileedo-while(contadores, acumuladores, parada por sentinela). Este projeto é resolvido sem o laçofor(isso só chega no Capítulo 07) e sem funções auxiliares (isso só chega no Capítulo 08) — tudo acontece dentro demain, com um únicodo-whilecontrolando o menu.
| ⏱️ Tempo estimado | 📦 Você vai entregar | ✅ Pronto quando |
|---|---|---|
| 45 min | main.c + entrada.txt |
o menu repete até a opção 4 e o saldo final do teste é R$ 120.00 |
do-while para um menu que precisa executar ao menos uma vez antes de checar a condição de parada.saldo) que persiste e é atualizada corretamente entre iterações do laço.if (já conhecido desde o Capítulo 05) para impedir saldo negativo.Construa um simulador de caixa eletrônico (main.c) que exibe repetidamente o menu:
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
O programa lê a opção escolhida com scanf, executa a operação correspondente e volta a mostrar o menu, repetindo esse ciclo até o usuário digitar 4 (a opção sentinela que encerra o laço). O saldo inicial é 100.0. Toda tentativa de saque com valor maior que o saldo disponível deve ser rejeitada, com uma mensagem de erro, sem jamais deixar o saldo negativo.
| ID | Requisito |
|---|---|
| RF01 | O programa deve compilar sem nenhum aviso com gcc -Wall -Wextra -Wpedantic -std=c17. |
| RF02 | Deve conter #include <stdio.h> e #include <stdlib.h>, usar int main(void) e terminar com return EXIT_SUCCESS;. |
| RF03 | O menu deve ser controlado por um único laço do-while. Não pode usar for nem declarar funções além de main. |
| RF04 | Deve oferecer as opções 1-Consultar Saldo, 2-Depositar, 3-Sacar e 4-Sair, lidas via scanf("%d", ...). |
| RF05 | O saldo é uma variável double iniciada em 100.0, atualizada corretamente a cada depósito ou saque válido. |
| RF06 | Uma tentativa de saque com valor > saldo deve ser rejeitada com mensagem de erro, sem alterar o saldo. |
| RF07 | O laço só deve terminar quando a opção 4 (sentinela) for digitada. |
graph TD
A["Inicio: saldo = 100.0"] --> B["do { ... } while (opcao != 4)"]
B --> C{"Menu: qual opcao?"}
C -->|1| D["Consultar Saldo"]
C -->|2| E["Depositar"]
C -->|3| F{"valor > saldo?"}
F -->|Sim| G["Rejeita saque (erro)"]
F -->|Nao| H["Saca e atualiza saldo"]
C -->|4| I["Sair (sentinela)"]
D --> B
E --> B
G --> B
H --> B
I --> J["return EXIT_SUCCESS"]
style B fill:#0284c7,stroke:#38bdf8,color:#ffffff
style I fill:#dc2626,stroke:#f87171,color:#ffffff
style J fill:#059669,stroke:#34d399,color:#ffffff
O mesmo do Miniprojeto 01: gcc 8 ou mais novo. No Windows, rode chcp 65001 se os emojis aparecerem quebrados.
🎯 Objetivo: partir de um código que compila e roda, antes de escrever qualquer linha.
⌨️ Faça: crie a pasta c_mini_06, salve o código abaixo como main.c e rode:
gcc -Wall -Wextra -Wpedantic -std=c17 main.c -o app
./app # Linux/macOS
.\app.exe # Windows (PowerShell)
📄 src/esqueleto.c
/*
* Miniprojeto 06: Simulador de Caixa Eletronico com Loops Indeterminados
* Regra: usa apenas while/do-while (Capitulo 06). Sem for, sem funcoes alem de main.
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double saldo = 100.0;
int opcao = 0;
// TODO 2: declare aqui "double valor = 0.0;" quando for ler valores
printf("====================================================\n");
printf(" 🏧 SIMULADOR DE CAIXA ELETRONICO\n");
printf("====================================================\n");
do {
printf("\n--- MENU ---\n");
printf("1 - Consultar Saldo\n");
printf("2 - Depositar\n");
printf("3 - Sacar\n");
printf("4 - Sair\n");
printf("Escolha uma opcao: ");
scanf("%d", &opcao);
// TODO 1: se opcao == 1, imprima o saldo atual com 2 casas decimais
// (dica: printf("Saldo atual: R$ %.2f\n", saldo);)
// TODO 2: se opcao == 2, leia "valor" com scanf("%lf", &valor)
// e some ao saldo (saldo = saldo + valor)
// TODO 3: se opcao == 3, leia "valor" e verifique com if
// se valor > saldo. Se for, imprima erro SEM alterar o saldo.
// Caso contrario, subtraia o valor do saldo.
// TODO 4: se opcao == 4, imprima uma mensagem de encerramento com o saldo final
// TODO 5: para qualquer outra opcao, imprima "Opcao invalida!"
} while (opcao != 4);
printf("Saldo ao sair: R$ %.2f\n", saldo);
printf("====================================================\n");
return EXIT_SUCCESS;
}
✅ Checkpoint: zero avisos do gcc, e a saída é:
🖥️ Saída esperada:
====================================================
🏧 SIMULADOR DE CAIXA ELETRONICO
====================================================
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Saldo ao sair: R$ 100.00
====================================================
Ao rodar, o menu aparece e espera uma opção: digite 4 e Enter. A saída acima é a do teste automático, que envia o 4 por redirecionamento; por isso o 4 não aparece depois de Escolha uma opcao:.
💡 Repare que o menu apareceu antes de qualquer teste da condição: é o
do-whileexecutando o corpo pelo menos uma vez.
🧯 Se der errado: se você digitar uma letra, o menu se repete sem parar. O scanf("%d") falha, não consome a letra e opcao nunca vira 4. Encerre com Ctrl+C. Tratar isso exige conferir o retorno do scanf, como no Desafio.
🎯 Objetivo: ver o acumulador saldo sobreviver de uma volta do laço para a outra.
⌨️ Faça: declare double valor = 0.0; ao lado de opcao e, dentro do do, comece a cadeia de decisão:
if (opcao == 1) imprime Saldo atual: R$ %.2f;else if (opcao == 2) lê valor com scanf("%lf", &valor), soma ao saldo e imprime o novo saldo.✅ Checkpoint: digite 2, depois 50, depois 1. O depósito mostra Novo saldo: R$ 150.00 e a consulta mostra Saldo atual: R$ 150.00. Saia com 4.
🧯 Se der errado: se o saldo vira um número absurdo, você leu valor com %f. Para double, o scanf exige %lf. Já no printf, %f serve para os dois.
🎯 Objetivo: aplicar uma regra de negócio com um if dentro do laço.
⌨️ Faça: else if (opcao == 3): leia o valor e, se valor > saldo, imprima ERRO: saldo insuficiente para este saque! sem mexer no saldo. Senão, subtraia e mostre o novo saldo.
✅ Checkpoint: com o saldo em 100, sacar 500 dá erro e o saldo continua 100.00. Sacar 30 deixa 70.00.
🎯 Objetivo: fechar a cadeia de decisão com a sentinela e um else final.
⌨️ Faça: else if (opcao == 4) imprime Encerrando... Saldo final: R$ %.2f, e o else imprime Opcao invalida!. Apague a linha Saldo ao sair do esqueleto, que agora ficou repetida.
✅ Checkpoint: digitar 9 mostra Opcao invalida! e o menu volta. Digitar 4 mostra o saldo final e o programa termina.
🎯 Objetivo: validar a saída completa e o código de retorno.
O arquivo de entrada faz, em ordem: consulta, depósito de 50, consulta, saque de 500 (recusado), saque de 30, opção inválida 9 e sai.
⌨️ Faça: crie entrada.txt na pasta do projeto, com o conteúdo abaixo, e rode o programa com a entrada redirecionada:
📄 tests/main.entrada.txt
1
2
50
1
3
500
3
30
9
4
./app < entrada.txt # Linux/macOS
Get-Content entrada.txt | .\app.exe # Windows (PowerShell)
✅ Checkpoint: com a entrada redirecionada o terminal não ecoa o que seria digitado, então as respostas não aparecem depois das perguntas. A saída tem que bater com esta, e o código de retorno é 0 (echo $? ou echo $LASTEXITCODE):
🖥️ Saída esperada:
====================================================
🏧 SIMULADOR DE CAIXA ELETRONICO
====================================================
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Saldo atual: R$ 100.00
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Valor a depositar: Deposito realizado. Novo saldo: R$ 150.00
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Saldo atual: R$ 150.00
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Valor a sacar: ERRO: saldo insuficiente para este saque!
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Valor a sacar: Saque realizado. Novo saldo: R$ 120.00
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Opcao invalida!
--- MENU ---
1 - Consultar Saldo
2 - Depositar
3 - Sacar
4 - Sair
Escolha uma opcao: Encerrando... Saldo final: R$ 120.00
====================================================
Só abra o gabarito depois de chegar até aqui:
src/main.c📄 src/main.c
/*
* Miniprojeto 06: Simulador de Caixa Eletronico com Loops Indeterminados
* Especializacao em Engenharia de Sistemas em C
* Regra: usa apenas while/do-while (Capitulo 06). Sem for, sem funcoes alem de main.
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double saldo = 100.0;
int opcao = 0;
double valor = 0.0;
printf("====================================================\n");
printf(" 🏧 SIMULADOR DE CAIXA ELETRONICO\n");
printf("====================================================\n");
do {
printf("\n--- MENU ---\n");
printf("1 - Consultar Saldo\n");
printf("2 - Depositar\n");
printf("3 - Sacar\n");
printf("4 - Sair\n");
printf("Escolha uma opcao: ");
scanf("%d", &opcao);
if (opcao == 1) {
printf("Saldo atual: R$ %.2f\n", saldo);
} else if (opcao == 2) {
printf("Valor a depositar: ");
scanf("%lf", &valor);
saldo = saldo + valor;
printf("Deposito realizado. Novo saldo: R$ %.2f\n", saldo);
} else if (opcao == 3) {
printf("Valor a sacar: ");
scanf("%lf", &valor);
// Regra de negocio: o saldo nunca pode ficar negativo.
if (valor > saldo) {
printf("ERRO: saldo insuficiente para este saque!\n");
} else {
saldo = saldo - valor;
printf("Saque realizado. Novo saldo: R$ %.2f\n", saldo);
}
} else if (opcao == 4) {
printf("Encerrando... Saldo final: R$ %.2f\n", saldo);
} else {
printf("Opcao invalida!\n");
}
} while (opcao != 4); // sentinela: a condicao so e testada DEPOIS do corpo
printf("====================================================\n");
return EXIT_SUCCESS;
}
Por que isso importa: repare que o do-while garante que o menu apareça pelo menos uma vez, mesmo antes de qualquer entrada do usuário — é exatamente esse detalhe que diferencia do-while de while puro. A condição de parada (opcao != 4) só é avaliada depois do corpo do laço executar, o que é natural para um menu interativo.
Adicione uma opção 5 - Ver Total de Operações, mantendo um contador (int total_operacoes = 0) que é incrementado a cada operação válida (depósito ou saque) dentro do próprio do-while — sem usar funções nem arrays. Esse é o mesmo padrão de acumulador que você vai usar depois, no Capítulo 08, quando aprender a mover esse contador para uma variável static dentro de uma função dedicada (veja o Miniprojeto 08).
✅ Checkpoint: depois de um depósito e um saque válidos, a opção 5 mostra Total de operacoes: 2. Um saque recusado não conta.
Extra: o scanf devolve quantos valores conseguiu ler. Use if (scanf("%d", &opcao) != 1) para detectar uma letra digitada e encerrar com uma mensagem, em vez de entrar no laço infinito do Passo 1.
📋 Projetos do curso de C | 📚 Teoria do Capítulo 06 | 🗂️ Hub de projetos