/*
* EXPLICAÇÃO DETALHADA DO PROGRAMA
* Este programa é um Gerenciador de Lista de Compras que mantém os itens
* organizados em ordem alfabética. Ele utiliza um array estático para armazenar
* os produtos e simula operações de banco de dados simples.
*
* 1. ESTRUTURA DE DADOS:
* - TList (Lista): Contém um array de 'Item', um contador total ('count')
* e um contador de itens já comprados ('boughtCount').
* - Item (Produto): Possui nome, quantidade (float) e status de compra (int/bool).
*
* 2. FUNCIONALIDADES PRINCIPAIS:
* - **I (Insert)**: Insere um novo produto. O algoritmo encontra a posição
* correta e desloca os outros itens para manter a lista sempre ordenada
* alfabeticamente.
* - **P (Print)**: Imprime a lista.
* - Argumento "F": Imprime do início ao fim.
* - Argumento "R": Imprime do fim ao início.
* - **A (Atualizar/Comprar)**: Marca um item como comprado. Se já estiver
* comprado, avisa. Incrementa o contador de comprados.
* - **X (Excluir)**: Remove um item da lista e rearranja os espaços.
*
* 3. CONTROLE DE ESTADO:
* - O programa impede a inserção de um item se o limite (MAX_ITEMS) for atingido.
* - Ao final (comando '*'), exibe quantos itens restam sem comprar.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MEMORY_ERROR 2
#define EXEC_SUCCESS 0
#define MAX_ITEMS 50
#define MAX_NAME_LENGTH 26
// Estrutura que representa um item individual da lista de compras
typedef struct {
char name[MAX_NAME_LENGTH]; // Nome do produto
float quantity; // Quantidade do item
int isBought; // Flag (0=não, 1=sim) indicando se foi comprado
} Item;
// Estrutura que representa a lista de compras completa
typedef struct {
Item items[MAX_ITEMS]; // Array estático para armazenar os itens
int count; // Contador total de itens na lista
int boughtCount; // Contador de itens marcados como comprados
} TList;
// Protótipos das funções
int MarkAsBought(TList *, char []);
int DeleteItem(TList *, char []);
int InsertItem(TList *, char [], float );
void PrintListForward(TList *);
void PrintListReverse(TList *);
void InitializeList(TList *);
int main(void)
{
TList list;
char operation = '.';
char productName[MAX_NAME_LENGTH];
float productQuantity;
// Inicializa a lista vazia
InitializeList(&list);
// Loop principal que processa comandos até encontrar o caractere '*'
while(operation != '*') {
scanf(" %c", &operation);
if(operation != '*') {
scanf("%24s", productName);
// Se a operação for Inserção (I), lê também a quantidade
if(operation == 'I')
scanf("%f", &productQuantity);
}
switch(operation) {
case 'I':
// Tenta inserir o item na lista
if (InsertItem(&list, productName, productQuantity))
printf("Incluiu %s \n", productName);
productQuantity = 0;
break;
case 'P':
// Verifica o argumento para decidir o tipo de impressão
if(strcmp("R", productName) == 0)
PrintListReverse(&list);
else if(strcmp("F", productName) == 0)
PrintListForward(&list);
break;
case 'A':
// Marca o item como comprado
if(MarkAsBought(&list, productName))
printf("Comprou %s \n", productName);
break;
case 'X':
// Remove o item da lista
if (DeleteItem(&list, productName))
printf("Excluiu %s\n", productName);
break;
case '*':
// Exibe o resumo final antes de encerrar
printf("Fim do programa ( %d itens sem comprar)\n", list.count - list.boughtCount);
break;
default:
printf("Operacao invalida.\n");
}
}
return EXEC_SUCCESS;
}
// Inicializa os contadores da lista
void InitializeList(TList *list) {
list->count = 0;
list->boughtCount = 0;
}
// Função para incluir um novo item mantendo a ordem alfabética
int InsertItem(TList *list, char productName[], float quantity)
{
int i, j;
int insertIndex = -1;
// Verifica se a lista está cheia
if (list->count >= MAX_ITEMS) {
puts("Quantidade maxima de itens");
return MEMORY_ERROR;
}
// Percorre a lista para encontrar a posição correta (ordem alfabética)
for (i = 0; i < list->count; i++) {
// strcmp retorna positivo se o item atual é "maior" (vem depois) que o novo
if (strcmp(list->items[i].name, productName) > 0) {
insertIndex = i;
break;
}
}
// Se não encontrou nenhum item "maior", insere no final da lista
if (insertIndex == -1)
insertIndex = list->count;
// Desloca os itens uma posição para a direita para abrir espaço para o novo
for (j = list->count; j > insertIndex; j--) {
strcpy(list->items[j].name, list->items[j-1].name);
list->items[j].quantity = list->items[j-1].quantity;
list->items[j].isBought = list->items[j-1].isBought;
}
// Insere os dados na posição encontrada
strcpy(list->items[insertIndex].name, productName);
list->items[insertIndex].quantity = quantity;
list->items[insertIndex].isBought = 0;
list->count++;
return TRUE;
}
// Imprime a lista do início ao fim (Ordem Alfabética)
void PrintListForward(TList *list)
{
int i;
if (list->count == 0)
puts("Lista vazia");
else
{
printf("\n Lista de compras (do inicio) \n");
for(i = 0; i < list->count; i++)
// Corrigido para %.1f para exibir corretamente o float
printf("%s %.1f %d \n", list->items[i].name, list->items[i].quantity, list->items[i].isBought);
printf("Total itens: %d Itens comprados: %d\n\n", list->count, list->boughtCount);
}
}
// Imprime a lista do fim para o início (Ordem Reversa)
void PrintListReverse(TList *list)
{
int i;
if (list->count == 0)
puts("Lista vazia");
else
{
printf("\n Lista de compras (do final) \n");
// Percorre do último índice até o 0
for(i = list->count; i > 0; i--)
printf("%s %.1f %d \n", list->items[i-1].name, list->items[i-1].quantity, list->items[i-1].isBought);
printf("Total itens: %d Itens comprados: %d\n\n", list->count, list->boughtCount);
}
}
// Marca um item específico como comprado
int MarkAsBought(TList *list, char productName[])
{
int i;
// Busca linear pelo nome do produto
for (i = 0; i < list->count; i++) {
if (strcmp(list->items[i].name, productName) == 0) {
// Se já foi comprado, não faz nada e avisa
if (list->items[i].isBought == 1) {
printf(" %s ja foi comprado \n ", productName);
return FALSE;
} else {
// Marca como comprado e incrementa o contador
list->items[i].isBought = 1;
list->boughtCount++;
return TRUE;
}
}
}
printf("Produto '%s' nao encontrado\n", productName);
return FALSE;
}
// Exclui um item da lista pelo nome
int DeleteItem(TList *list, char productName[])
{
int i, j;
// Busca o item
for (i = 0; i < list->count; i++) {
if (strcmp(list->items[i].name, productName) == 0) {
// Se estava marcado como comprado, decrementa o contador de comprados
if (list->items[i].isBought == 1) {
list->boughtCount--;
}
// Desloca os itens seguintes uma posição para a esquerda (sobrescrevendo o excluído)
for (j = i; j < list->count - 1; j++) {
strcpy(list->items[j].name, list->items[j+1].name);
list->items[j].quantity = list->items[j+1].quantity;
list->items[j].isBought = list->items[j+1].isBought;
}
list->count--;
return TRUE;
}
}
printf("Valor informado nao existe na lista\n");
return FALSE;
}