📚 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.

🏧 Miniprojeto C 06 — Caixa Eletrônico com Laço Indeterminado

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 while e do-while (contadores, acumuladores, parada por sentinela). Este projeto é resolvido sem o laço for (isso só chega no Capítulo 07) e sem funções auxiliares (isso só chega no Capítulo 08) — tudo acontece dentro de main, com um único do-while controlando 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

Diagrama do 🏧 Miniprojeto C 06 — Caixa Eletrônico com Laço Indeterminado

🎯 Objetivos

📋 O problema

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

🧰 Ambiente

O mesmo do Miniprojeto 01: gcc 8 ou mais novo. No Windows, rode chcp 65001 se os emojis aparecerem quebrados.


Passo 1 — Compilar o esqueleto

🎯 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-while executando 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.


Passo 2 — Consultar e depositar (TODO 1 e 2)

🎯 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:

✅ 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.


Passo 3 — Sacar sem deixar o saldo negativo (TODO 3)

🎯 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.


Passo 4 — Sair e opção inválida (TODO 4 e 5)

🎯 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.


Passo final — Conferir com o gabarito

🎯 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:

🔑 Ver gabarito: 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.


🏆 Desafio

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.


🧭 Navegação

📋 Projetos do curso de C | 📚 Teoria do Capítulo 06 | 🗂️ Hub de projetos