Usando todo o seu conhecimento adquirido na disciplina, faça um programa em Linguagem C para controlar o estoque de uma loja com até 10 produtos. O programa deve:
a) Definir um registro (struct) para armazenar: nome do produto (até 30 caracteres), código (inteiro), quantidade em estoque (inteiro) e preço unitário (float).
b) Utilizar um vetor de registros para representar o estoque de produtos.
c) Implementar funções para:
i) Cadastrar um novo produto no estoque.
ii) Atualizar a quantidade de um produto vendido (baixa no estoque por código).
iii) Consultar e exibir todos os produtos com suas quantidades e preços.
iv) Calcular e informar o valor total em estoque da loja.
v) Buscar produto pelo código.
d) Considere tratar os seguintes erros:
i) Validação de entrada do usuário: garantir que campos como quantidade e preço não recebam valores negativos ou zero;
ii) Verificação de código duplicado: antes de cadastrar um novo produto, conferir se o código já existe no vetor, evitando duplicidades;
iii) Busca por código inexistente: ao atualizar estoque ou buscar produto, exibir mensagem informando que o produto não existe se o código não for localizado;
iv) Controle de limites de vetor: impedir cadastro de produto se o número máximo de produtos já foi atingido; avisar o usuário;
v) Atualização de Estoque: evitar baixa que exceda a quantidade em estoque, mostrar mensagem de erro e não permitir a operação;
vi) Mensagens de erro claras: sempre informar o motivo do erro ao usuário e como proceder corretamente.

Passo 1

O enunciado pede um programa em Linguagem C para controlar o estoque de uma loja com as seguintes exigências e informações fornecidas:
  • Capacidade máxima de produtos: ... \,10 produtos.
  • Cada produto deve armazenar: nome (até ... \,30 caracteres), código (inteiro), quantidade em estoque (inteiro) e preço unitário (float).
  • Deve-se usar um vetor de registros (array de structs) para representar o estoque.
  • Funções a implementar:
    1. Cadastrar um novo produto no estoque.
    2. Atualizar a quantidade de um produto vendido (baixa por código).
    3. Consultar e exibir todos os produtos com quantidades e preços.
    4. Calcular e informar o valor total em estoque da loja.
    5. Buscar produto pelo código.
  • Tratamento de erros exigidos:
    1. Validar entradas: quantidade e preço não podem ser negativos nem zero.
    2. Evitar códigos duplicados no cadastro.
    3. Ao buscar ou atualizar por código inexistente, informar que o produto não existe.
    4. Impedir cadastro quando vetor já estiver cheio e avisar o usuário.
    5. Evitar baixa que exceda a quantidade em estoque; informar erro e não permitir a operação.
    6. Mensagens de erro claras, explicando o motivo e como proceder.
Não vou resolver nada ainda; a partir do próximo passo eu mostro o projeto e a implementação passo a passo.

Passo 2

Definição do registro (struct) e do vetor. Aqui explico por que cada escolha e como isso é usado no programa.
  • Vamos criar uma struct chamada Product com os campos:
    • char name[31]; — espaço para até ... \,30 caracteres mais o caractere nulo '\0'. Sempre lembramos de reservar +1 para terminar a string.
    • int code; — código inteiro do produto. Vou exigir que seja positivo.
    • int quantity; — quantidade em estoque (inteiro não negativo).
    • float price; — preço unitário (float, maior que zero).
  • Por que char name[31]? Em C as strings ficam armazenadas como arrays de char terminados por '\0'. Se o enunciado pede até ... \,30 caracteres, precisamos ... \,31 células para guardar o terminador.
  • Definimos uma constante #define MAX_PRODUCTS 10 para o limite ... \,10. Isso facilita trocar o limite depois, se necessário.
Explicação didática rápida: uma struct é um “pacote” de variáveis relacionadas; aqui cada produto é um pacote com nome, código, quantidade e preço. O vetor de structs é só uma lista desses pacotes.

Passo 3

Como representar o estoque na memória e variáveis de controle:
  • Vamos declarar:
    • Product inventory[MAX_PRODUCTS]; — o vetor que armazena até ... \,10 produtos.
    • int numProducts = 0; — contador de quantos produtos já estão cadastrados atualmente no vetor.
  • Por que preciso do numProducts? Em C arrays têm tamanho fixo, mas nem todas as posições estarão ocupadas. numProducts indica até onde existem dados válidos no vetor.
Conceito importante: para inserir, verificamos if (numProducts >= MAX_PRODUCTS) — se verdadeiro, o estoque está cheio e devemos impedir novo cadastro. Para percorrer produtos válidos usamos índices de 0 até numProducts - 1.

Passo 4

Funções que vamos implementar — assinatura, finalidade e comportamento esperado (contrato):
  • int findProductIndexByCode(Product inv[], int n, int code);
    • Busca produto pelo código code no vetor inv com n itens.
    • Retorna índice >= 0 se encontrado, ou -1 se não existe.
    • Por que retornar índice? É eficiente para depois atualizar ou exibir.
  • int addProduct(Product inv[], int *n);
    • Tenta cadastrar novo produto no vetor inv, atualizando *n.
    • Valida entradas: código positivo, não duplicado; quantidade maior que ... \,0; preço maior que ... \,0.
    • Verifica limite do vetor: recusa cadastro se *n >= MAX_PRODUCTS.
    • Retorna 0 em sucesso, e códigos negativos para erros (ex.: -1 para vetor cheio, -2 para código duplicado, -3 para entrada inválida).
  • int sellProduct(Product inv[], int n);
    • Faz baixa de estoque por código.
    • Pergunta o código, verifica que existe; pede quantidade vendida (deve ser > ... \,0 e <= quantidade em estoque).
    • Se válido, subtrai e retorna 0. Se erro (produto não existe, quantidade inválida, insuficiente) retorna código de erro e imprime mensagem apropriada.
  • void listProducts(const Product inv[], int n);
    • Exibe todos os produtos com código, nome, quantidade e preço formatado.
    • Se n == 0, informa que o estoque está vazio.
  • float calculateTotalValue(const Product inv[], int n);
    • Percorre os n produtos e soma quantity * price.
    • Retorna o valor total (float). Explico como calcular sem complicar: é uma simples soma acumulada.
  • void searchProduct(const Product inv[], int n);
    • Pergunta código, usa findProductIndexByCode e exibe o produto se encontrado, ou mensagem clara se não existir.
Para cada função vou imprimir mensagens claras de sucesso/erro, conforme exigido pelo enunciado.

Passo 5

Validações de entrada e como implementá-las (com exemplos de fluxo de leitura e tratamento de erros):
  • Ler strings com segurança:
    • Para o nome usamos fgets(buffer, sizeof(buffer), stdin); e removemos o '\n' final (se presente). Isso evita overflow e problemas com espaços no nome.
  • Ler números com scanf e verificar retorno:
    • Ao usar scanf("%d", &x), sempre verificamos se o retorno é 1 (entrada válida). Se não, limpamos buffer e re-pedimos.
    • Para floats usamos scanf("%f", &f) e verificamos retorno 1.
  • Garantir valores positivos:
    • Quantidade: exigir quantity > 0. Não aceitamos 0 ou negativo.
    • Preço: exigir price > 0.0f.
    • Código: exigir code > 0.
  • Evitar duplicidade de código:
    • Antes de aceitar um cadastro, chamamos findProductIndexByCode. Se retorno >= 0, mostramos: “Código já cadastrado — se quiser, use outro código”.
  • Impedir cadastro quando vetor cheio:
    • Se numProducts >= MAX_PRODUCTS mostramos: “Limite atingido (máx. ... \,10) — exclua um produto ou aumente o limite.” (mensagem clara).
  • Evitar baixas maiores que estoque:
    • Ao vender, se sellAmount > product.quantity, mostramos “Erro: quantidade solicitada maior que estoque atual ( ... \,X). Operação cancelada.”
  • Mensagens de erro:
    • Sempre dizer o que aconteceu e o que fazer: ex.: “Entrada inválida: preço deve ser um número real maior que 0. Tente novamente.”
Dica prática: para limpar o buffer após scanf com falha ou para descartar o '\n' residual, usamos uma função auxiliar void clearInputBuffer(void) que consome int c; while ((c = getchar()) != '\n' && c != EOF);.

Passo 6

Implementação passo a passo das funções principais — explicando cada trecho importante (mas sem colar o programa final aqui):
  1. findProductIndexByCode:
    • Percorre for (int i = 0; i < n; ++i) e compara inv[i].code == code.
    • Retorna i quando encontra; se terminar loop retorna -1.
    • Conceito: busca linear. Para ... \,10 itens é eficiente e simples.
  2. addProduct (fluxo):
    • Verifica limite: if (*n >= MAX_PRODUCTS) return -1;
    • Lê código em loop até obter um int válido e > 0. Checa duplicidade:
      • if (findProductIndexByCode(inv, *n, code) != -1) informar erro e pedir outro código.
    • Lê nome com fgets, remove '\n'.
    • quantity em loop até obter int válido e > 0.
    • price em loop até obter float válido e > 0.
    • Preenche inv[*n] e incrementa (*n)++; imprime mensagem de sucesso e retorna 0.
  3. sellProduct (fluxo):
    • Lê código; usa findProductIndexByCode; se -1 imprime “produto não existe”.
    • Se existe, mostra estoque atual inv[idx].quantity. Pede qtdVendida.
    • Valida qtdVendida > 0 e qtdVendida <= inv[idx].quantity. Se inválido, imprime motivo.
    • Se válido, faz inv[idx].quantity -= qtdVendida; e imprime resumo da operação.
  4. listProducts:
    • Se n == 0, imprime “estoque vazio”.
    • Senão, imprime cabeçalho e loop mostrando cada produto com printf("%d\t%-30s\t%d\tR$ %.2f\n", ...).
    • Explico formatação: %d inteiro, %-30s string alinhada à esquerda com largura ... \,30, %.2f mostra preço com ... \,2 casas decimais.
  5. calculateTotalValue:
    • Inicializa float total = 0.0f; e para cada produto adiciona total += inv[i].quantity * inv[i].price;.
    • Retorna total. Explico que multiplicamos quantidade (inteiro) por preço (float) e somamos — operação elementar.
  6. searchProduct:
    • Lê código, usa findProductIndexByCode. Se encontrado exibe os campos do produto; senão, mensagem clara.
  7. Menu e loop principal:
    • Repetimos até o usuário escolher sair.
    • Opções (ex.: 1 Cadastrar, 2 Vender, 3 Listar, 4 Valor total, 5 Buscar, 6 Sair).
    • Toda entrada do menu validada: se escolha inválida, mostrar instrução.

Passo 7

Boas práticas e dicas para usar/compilar o programa:
  • Compilação típica: gcc -std=c99 -Wall -Wextra -o estoque estoque.c
  • Testes que você deve fazer manualmente:
    1. Tentar cadastrar produto com código repetido — ver mensagem e impedir duplicata.
    2. Tentar cadastrar com quantidade ... \,0 ou negativa — ver mensagem e pedir novo valor.
    3. Tentar vender quantidade maior que estoque — ver mensagem e operação não realizada.
    4. Preencher até o limite de ... \,10 produtos e tentar cadastrar mais — ver mensagem que limite foi atingido.
    5. Verificar listagem e cálculo do valor total para conferir somas.
  • Mensagens no programa são construídas para explicar o erro e indicar como proceder (por exemplo: “Digite um preço maior que 0.0”).
Agora, no próximo campo eu te entrego o programa completo em C que implementa tudo explicado acima.

Resposta

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_PRODUCTS 10

typedef struct {
    char name[31]; /* até 30 caracteres + terminador */
    int code;
    int quantity;
    float price;
} Product;

/* Limpa buffer de entrada até '\n' ou EOF */
void clearInputBuffer(void) {
    int c;
    while ((c = getchar()) != '\n' && c != EOF) { }
}

/* Busca linear: retorna índice do produto com código igual a code, ou -1 se não achar */
int findProductIndexByCode(Product inv[], int n, int code) {
    for (int i = 0; i < n; ++i) {
        if (inv[i].code == code) return i;
    }
    return -1;
}

/* Lista todos os produtos */
void listProducts(const Product inv[], int n) {
    if (n == 0) {
        printf("Estoque vazio.\n");
        return;
    }
    printf("Código\tNome                            \tQuantidade\tPreço (R$)\n");
    printf("---------------------------------------------------------------------\n");
    for (int i = 0; i < n; ++i) {
        printf("%6d\t%-30s\t%9d\tR$ %8.2f\n",
               inv[i].code,
               inv[i].name,
               inv[i].quantity,
               inv[i].price);
    }
}

/* Calcula valor total em estoque */
float calculateTotalValue(const Product inv[], int n) {
    float total = 0.0f;
    for (int i = 0; i < n; ++i) {
        total += inv[i].quantity * inv[i].price;
    }
    return total;
}

/* Buscar produto pelo código e exibir */
void searchProduct(const Product inv[], int n) {
    int code;
    printf("Digite o código do produto a buscar: ");
    if (scanf("%d", &code) != 1) {
        printf("Entrada inválida. O código deve ser um número inteiro positivo.\n");
        clearInputBuffer();
        return;
    }
    clearInputBuffer();
    int idx = findProductIndexByCode((Product*)inv, n, code);
    if (idx == -1) {
        printf("Produto com código %d não encontrado.\n", code);
    } else {
        printf("Produto encontrado:\n");
        printf("Código: %d\n", inv[idx].code);
        printf("Nome  : %s\n", inv[idx].name);
        printf("Qtd   : %d\n", inv[idx].quantity);
        printf("Preço : R$ %.2f\n", inv[idx].price);
    }
}

/* Cadastra um novo produto; retorna 0 em sucesso, negativo em erro */
int addProduct(Product inv[], int *n) {
    if (*n >= MAX_PRODUCTS) {
        printf("Erro: limite de produtos atingido (máx. %d). Não é possível cadastrar.\n", MAX_PRODUCTS);
        return -1;
    }

    int code;
    while (1) {
        printf("Digite o código do produto (inteiro positivo): ");
        if (scanf("%d", &code) != 1) {
            printf("Entrada inválida. Digite um número inteiro positivo para o código.\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();
        if (code <= 0) {
            printf("Código deve ser maior que 0. Tente novamente.\n");
            continue;
        }
        if (findProductIndexByCode(inv, *n, code) != -1) {
            printf("Código já cadastrado. Use outro código.\n");
            continue;
        }
        break;
    }

    char nameBuf[256];
    while (1) {
        printf("Digite o nome do produto (até 30 caracteres): ");
        if (fgets(nameBuf, sizeof(nameBuf), stdin) == NULL) {
            printf("Erro ao ler o nome. Tente novamente.\n");
            clearInputBuffer();
            continue;
        }
        /* Remove newline se presente */
        size_t len = strlen(nameBuf);
        if (len > 0 && nameBuf[len - 1] == '\n') nameBuf[len - 1] = '\0';

        if (strlen(nameBuf) == 0) {
            printf("Nome não pode ser vazio. Tente novamente.\n");
            continue;
        }
        if (strlen(nameBuf) > 30) {
            printf("Nome muito longo (máx. 30 caracteres). Tente novamente.\n");
            continue;
        }
        break;
    }

    int quantity;
    while (1) {
        printf("Digite a quantidade inicial em estoque (inteiro > 0): ");
        if (scanf("%d", &quantity) != 1) {
            printf("Entrada inválida. A quantidade deve ser um número inteiro maior que 0.\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();
        if (quantity <= 0) {
            printf("Quantidade deve ser maior que 0. Tente novamente.\n");
            continue;
        }
        break;
    }

    float price;
    while (1) {
        printf("Digite o preço unitário (maior que 0, ex: 19.90): ");
        if (scanf("%f", &price) != 1) {
            printf("Entrada inválida. O preço deve ser um número (use ponto para decimal).\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();
        if (price <= 0.0f) {
            printf("Preço deve ser maior que 0. Tente novamente.\n");
            continue;
        }
        break;
    }

    /* Preenche produto */
    inv[*n].code = code;
    strncpy(inv[*n].name, nameBuf, 30);
    inv[*n].name[30] = '\0'; /* garantia */
    inv[*n].quantity = quantity;
    inv[*n].price = price;

    (*n)++;
    printf("Produto cadastrado com sucesso!\n");
    return 0;
}

/* Faz baixa no estoque por código (venda). Retorna 0 em sucesso, negativo em erro */
int sellProduct(Product inv[], int n) {
    if (n == 0) {
        printf("Estoque vazio. Não há produtos para vender.\n");
        return -1;
    }

    int code;
    printf("Digite o código do produto a vender: ");
    if (scanf("%d", &code) != 1) {
        printf("Entrada inválida. Código deve ser inteiro.\n");
        clearInputBuffer();
        return -2;
    }
    clearInputBuffer();
    int idx = findProductIndexByCode(inv, n, code);
    if (idx == -1) {
        printf("Produto com código %d não encontrado.\n", code);
        return -3;
    }

    printf("Produto: %s | Estoque atual: %d | Preço unitário: R$ %.2f\n",
           inv[idx].name, inv[idx].quantity, inv[idx].price);

    int qtd;
    while (1) {
        printf("Digite a quantidade a vender (inteiro > 0): ");
        if (scanf("%d", &qtd) != 1) {
            printf("Entrada inválida. A quantidade deve ser um número inteiro maior que 0.\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();
        if (qtd <= 0) {
            printf("Quantidade deve ser maior que 0. Tente novamente.\n");
            continue;
        }
        if (qtd > inv[idx].quantity) {
            printf("Erro: quantidade solicitada (%d) maior que estoque atual (%d). Operação cancelada.\n",
                   qtd, inv[idx].quantity);
            return -4;
        }
        break;
    }

    inv[idx].quantity -= qtd;
    printf("Venda registrada: %d unidade(s) de '%s' vendida(s). Estoque agora: %d\n",
           qtd, inv[idx].name, inv[idx].quantity);
    return 0;
}

/* Menu principal */
int main(void) {
    Product inventory[MAX_PRODUCTS];
    int numProducts = 0;
    int option;

    printf("=== Sistema de Controle de Estoque (até %d produtos) ===\n", MAX_PRODUCTS);

    while (1) {
        printf("\nEscolha uma opção:\n");
        printf("1 - Cadastrar novo produto\n");
        printf("2 - Registrar venda (baixa no estoque por código)\n");
        printf("3 - Listar produtos\n");
        printf("4 - Calcular valor total em estoque\n");
        printf("5 - Buscar produto por código\n");
        printf("6 - Sair\n");
        printf("Opção: ");

        if (scanf("%d", &option) != 1) {
            printf("Entrada inválida. Digite o número da opção.\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();

        switch (option) {
            case 1:
                addProduct(inventory, &numProducts);
                break;
            case 2:
                sellProduct(inventory, numProducts);
                break;
            case 3:
                listProducts(inventory, numProducts);
                break;
            case 4: {
                float total = calculateTotalValue(inventory, numProducts);
                printf("Valor total em estoque: R$ %.2f\n", total);
                break;
            }
            case 5:
                searchProduct(inventory, numProducts);
                break;
            case 6:
                printf("Encerrando programa. Até mais!\n");
                return 0;
            default:
                printf("Opção inválida. Escolha uma das opções entre 1 e 6.\n");
        }
    }

    return 0;
}

Exercícios relacionados