Ir ao conteúdo

C++ Como colocar em ordem alfabetica a listagem de produtos


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

Olá bom dia , to com um trabalho da faculdade que é criar um programa que faça o controle do estoque , está tudo ok , porém o professor colocou uma condição na listagem , que é colocar em ordem alfabética , e eu não to conseguindo enxergar como eu posso está fazendo isso , se alguém poder me ajudar com isso , vou agradecer muito , abaixo vai estar o codigo para ser possível analisar melhor :

 

#include <iostream>
#include <stdlib.h>
#include <string.h>
#define MAX 1000 //Maximo de Produtos
#define lli long long int // fazendo long long int ser escrito como lli
using namespace std;

int op,ind = 0,cont; // variavel op (Operação que vai ser realizada) , ind (Indíce do Produto) , 
                     //cont para ser contadora/auxiliar em certas operações de funções

void removeprod(); // Funções
void remocao();     // Que
void listagem();   // Foram
void busca();      // Criada

struct produto{
    char nome[100];
    char tipo[50];
    double preco;
    char localdisp[50];
    char identificador[10];
    lli quantidadedisp;
}; //struct com as variaveis e valores que o programa precisa

struct produto p[MAX]; //struct que vai ser responsavel pelos produtos

struct produto dadoproduto(){ // vai ler os dados do produto

    char quantidade[19],precoprod[10];// vai ler 19 caracteres , ja que, logo a quantidade de produtos esta como long long int
                                  // e suporta até 19 numeros , e o preço do produto que vai até 10 digitos

    cout << "-Opção : Adição de Produto, Selecionada com Sucesso-" << endl << endl;
    repetecad:
    cout << "-Digite o nome do produto-" << endl;
    cin >> p[ind].nome;
    cout << "-Digite qual vai ser o tipo do produto-" << endl;
    cin >> p[ind].tipo ;
    repetepreco:
    cout << "-Digite o preço do produto(Preco maximo ate 10 digitos)-" << endl;
    cin >> precoprod;

    bool vefpreco = true;

    for(int i = 0 ; i < strlen(precoprod) ; i++)
        if(!isdigit(precoprod[i]) && precoprod[i] != '.'){
            vefpreco = false;
            break;
        }

    if(vefpreco) p[ind].preco = atof(precoprod);
    else{
        cout << "-Digite um preco valido-" << endl << endl;
        goto repetepreco;
    }

    cout << "-Digite o local onde o produto se encontra disponivel-" << endl;
    cin >> p[ind].localdisp;
    cout << "-Digite o identificador do produto , pode ser composto por letras e numeros-" << endl;
    cin >> p[ind].identificador;
    repetequant:
    cout << "-Digite a quantidade disponivel do produto no estoque-" << endl;
    cin >> quantidade;

    bool vefquant = true;

    for(int i = 0 ; i < strlen(quantidade) ; i++)
        if(!isdigit(quantidade[i])){
            vefquant = false;
            break;
        }

    if(vefquant) p[ind].quantidadedisp = atoi(quantidade);
    else{
        cout << "-Digite uma quantidade disponível no estoque valida-" << endl << endl;
        goto repetequant;
    }
    ind++;
    cout << "-Deseja adicionar outro produto sim ou não ? Digite 1 para sim ou 2 para não- " << endl;
    repetecadfim:
    cin >> op;
    switch(op){
        case 1:
            system("clear||cls");
            goto repetecad;
        case 2:
            cout << "Produto(s) Adicionado com Sucesso ! " << endl << endl;
            system("clear||cls");
            break;
        default:
            cout << "Opção invalida , tente novamente " ;
            goto repetecadfim;
    }
} // struct para o cadastro do produto

int main (){

    //struct produto novo;
    cout << "Bem vindo ao programa de Controle de Estoque" << endl << endl ; 

    inicio:

    cout << "Digite um numero de 1 até 5 para as seguintes operações : " << endl << 
            "1. Adição de Produto" << endl <<
            "2. Remoção de Produto" << endl <<
            "3. Busca de Produto" << endl <<
            "4. Listagem dos Produtos" << endl <<
            "5. Sair do Programa"<< endl << endl;

    cin >> op ;
    cout << endl;

    switch(op){
        case 1:
            system("clear||cls");
            dadoproduto();
            goto inicio;
        case 2:
            system("clear||cls");
            remocao();
            getchar();
            system("clear||cls");
            goto inicio;
        case 3:
            system("clear||cls");
            busca();
            getchar();
            system("clear||cls");
            goto inicio;
        case 4:
            system("clear||cls");
            cout << "-Opção : Listagem dos Produtos, Selecionada com Sucesso-" << endl << endl;
            listagem();
            cout << "-Aperte a tecla ENTER para voltar ao menu principal-" << endl;
            getchar();
            getchar();
            system("clear||cls");
            goto inicio;
        case 5:
            cout << "-Saindo do Programa !-" << endl;
            return 0;
        default:
            cout << "!Opção invalida , tente novamente selecionando uma opção válida!" << endl << endl;
            goto inicio;
    }

    return 0;
}

void listagem(){

    cout << "-A seguir , a listagem de todos os produtos cadastrado até o momento-" << endl << endl;

    for(int i = 0 ; i < ind ; i++){
        cout << "-------PRODUTO " << i+1 << "--------" << endl;
        cout << "Nome do Produto : " << p[i].nome << endl;
        cout << "Tipo do Produto : " << p[i].tipo << endl;
        cout << "Preco do Produto : " << p[i].preco << endl;
        cout << "Local com Disponibilidade : " << p[i].localdisp << endl;
        cout << "Identificador : " << p[i].identificador << endl;
        cout << "Quantidade Disponivel : " << p[i].quantidadedisp << endl;
        cout << "-----------------------" << endl;
    }
}

void busca(){

    cout << "-Opção : Busca de Produto, Selecionada com Sucesso-" << endl << endl;

    char busca[100];

    cout << "-Por favor , digite o nome do produto ou o identificador que deseja buscar-" << endl << endl;

    cin >> busca;

    for(int i = 0 ; i < ind ; i++){
        if((strcmp(busca,p[i].nome) == 0) || (strcmp(busca,p[i].identificador) == 0)){
            cout << "-Produto encontrado com sucesso !-" << endl << endl;

            cout << "-------PRODUTO " << i+1 << "--------" << endl;
            cout << "Nome do Produto : " << p[i].nome << endl;
            cout << "Tipo do Produto : " << p[i].tipo << endl;
            cout << "Preco do Produto : " << p[i].preco << endl;
            cout << "Local com Disponibilidade : " << p[i].localdisp << endl;
            cout << "Identificador : " << p[i].identificador << endl;
            cout << "Quantidade Disponivel : " << p[i].quantidadedisp << endl;
            cout << "-----------------------" << endl << endl;
        }
    }
    cout << "-Aperte a tecla ENTER para continuar" << endl;
    getchar();
}

void remocao(){

    cout << "-Opção : Remoção de Produto, Selecionada com Sucesso-" << endl;

    cont = 0;

    char codiden[10];

    cout << "Por favor , verifique qual produto voce deseja realmente remover de acordo" << endl <<
             "o identificador com a listagem a seguir : " << endl << endl; 

    listagem();

    cout << "Digite o identificador do produto que deseja remover : " ;

    cin >> codiden ;

    for(int i = 0 ; i < ind ; i++){
        if(strcmp(codiden,p[i].identificador) == 0) {
            for(int j = i ; j < ind ; j++){
                p[j]=p[j+1];
            }
            ind--;
            cont++;
            break;
        }
    }

    if(cont > 0){
        cout << "Produto excluido com sucesso" << endl;
        cout << "Pressione a tecla ENTER para continuar" << endl;
        getchar();
    } else{
        cout << "Identificador Invalido !" << endl;
        cout << "Pressione a tecla ENTER para continuar" << endl;
        getchar();
    }
}

 

ele está funcionando corretamente , so to tendo dificuldade nessa parte

  • Solução
Postado
1 minuto atrás, Pedro Ulisses Maia disse:
void removeprod(); // Funções
void remocao();     // Que
void listagem();   // Foram
void busca();      // Criada


nunca use void(void).  Isso só vai te dar muito mais trabalho.

 

Escreveu um programa C. Não precisa se limitar ao dialeto C se está programando em C++ que é muito mais expressiva.

 

Comente o que está fazendo e porque está fazendo. Sugiro evitar esses comentários óbvios tipo "variáveis aqui", "op" é a opção....

 

3 minutos atrás, Pedro Ulisses Maia disse:
struct produto{
    char nome[100];
    char tipo[50];
    double preco;
    char localdisp[50];
    char identificador[10];
    lli quantidadedisp;
}; //struct com as variaveis e valores que o programa precisa

struct produto p[MAX]; //struct que vai ser responsavel pelos produtos

 

Em C++ não há razão para escrever assim. Está claro que tem um cadastro de produtos. Só que no programa não tem. Apenas um vetor de struct. E sem nenhum método? Não se escreve assim em C++ porque só fica mais difícil...

C++ tem sort. Basta escrever uma função que compara dois produtos. Pode ter uma linha só....

  • Amei 1
Postado

@arfneto caraca vei , mt obrigado mesmo , me ajudou mt

tinha esquecido total do sort kkkk

sobre eu ta me limitando ao C , é porque o professor que passou o trabalho pediu pra gente ser assim , so usar a iostream do C++ 😕  , ele limitou o uso das biblitoecas , se ele n tivesse feito isso , eu taria era usando as bibliotecas do C++ e esse codigo estaria bem menor ksks

mesmo assim , obrigado de coração , me ajudou mt !

Postado
10 minutos atrás, Pedro Ulisses Maia disse:

ele limitou o uso das biblitoecas , se ele n tivesse feito isso , eu taria era usando as bibliotecas do C++ e esse codigo estaria bem menor

Não é bem o caso de bibliotecas. É o lance de void funcao(void) e o fato de ter funções que claramente atuam na struct. Essa é a razão de C++ ter sido escrita nos anos 80: colocar as funções na struct. Seu professor não explicou isso?

Postado

vou te mostrar um exemplo curto quando der

 

4 horas atrás, Pedro Ulisses Maia disse:

é porque o professor que passou o trabalho pediu pra gente ser assim , so usar a iostream do C++ 😕  , ele limitou o uso das biblitoecas

 

:) você não usou as bibliotecas C++ mas usou stdlib.h a biblioteca padrão do C. Qual o propósito então? 

 

Sobre o programa como postou

 

O programa tem muitos dos erros --- ou "quase erros" --- comuns de se ver em programas de iniciantes, provavelmente porque tem algo errado com o modo como se ensina ou se escreve sobre isso hoje em dia.

 

Escrevendo desse modo:

  • vai levar uma eternidade para terminar e testar
  • vai aprender pouco ou nada de C++ porque tem um programa ruim. E em C.

Eis alguns problemas:

  • não misture interatividade com a lógica do programa. Isso é um desastre.
        case 4:
            system("clear||cls");
            cout << "-Opção : Listagem dos Produtos, Selecionada com "
                    "Sucesso-"
                 << endl
                 << endl;
            listagem();
            cout << "-Aperte a tecla ENTER para voltar ao menu "
                    "principal-"
                 << endl;
            getchar();
            getchar();
            system("clear||cls");
            goto inicio;

 

2 chamadas a system(), 2 chamadas a getchar(), 2 cout, uma função void que retorna void. Isso tudo é problemático. NUNCA escreva assim.

 

A começar pelo case em si.

 

  • nunca escreva um programa interativo. Só vai perder tempo
  • listagem() vai listar o que? Tudo global, Só serve para um cadastro uma única vez. Então pra que um programa e uma função?
  • Não use system() para nada. Não estará fazendo nada. Não há praticamente nada que possa fazer com system() que não possa fazer em C ou C++. system() foi escrita em C e o sistema quase todo também. E em geral é proibido em empresas e escolas afinal: é um risco grande de segurança. E se tem algo que você não possa inicialmente fazer em C ou C++ talvez não deva mesmo fazer.
  • duas chamadas a getchar? Não use nenhuma
  • goto inicio? Não, não use isso. Não há nada especial em usar um goto, desde que tenha uma razão sólida. E é difícil isso. 
  • Ao usar uma estrutura de dados, como uma lista encadeada, entenda que uma estrutura é um container. Até tem esse nome em C++. Em java são chamadas coleções. Se programar uma estrutura dessas como se fosse um elemento com um ponteiro dentro só vai trabalhar mais e à toa. Em geral uma estrutura tem nós e cada nó tem uma referência a um dado. Por exemplo uma lista não é um nó, um nó não é uma lista. E os nós em geral tem uma referência a UM registro d dados. E nesse registro um campo é a chave, que se usa para comparar dois registros e dar uma noção de ordenação.

Se você quer listar um cadastro e essa é a opção não fique escrevendo na tela e lendo no meio das coisas. Simplesmente escreva:

 

    int listagem(Cadastro* produtos);


E passe o endereço de um cadastro. E retorne ZERO de deu certo ou um valor negativo em caso de erro. Só isso.

 

Escreva em torno dos dados

 

Seu dado é um cadastro de produtos.

 

Produto é

 

struct produto
{
    char   nome[100];
    char   tipo[50];
    double preco;
    char   localdisp[50];
    char   identificador[10];
    lli    quantidadedisp;
};  // struct com as variaveis e valores que o programa precisa

 

Mas não é seu dado. Seu dado é o cadastro

 

void removeprod();  // Funções
void remocao();     // Que
void listagem();    // Foram
void busca();       // Criada

 

Essas funções que listou se referem ao CADASTRO, todas. Mas onde está o tal cadastro? Nem tem no seu programa.

 

Não pode ser só um vetorzinho. Se fizer assim, como fez, vai ter que ficar controlando quantos tem, se passou de MAX, e só vai ter um cadastro para o programa todo.  Isso não serve para nada. Vai ter um trabalho do inferno.

 

Compare com esse programa, que já até compila, escrito em torno dos dados

 

#define MAXPRD 10 
#include <iostream>
using namespace std;

struct Produto
{
    char   nome[100];
    char   tipo[50];
    double preco;
    char   localdisp[50];
    char   identificador[10];
    long   quantidadedisp;
};

struct Cadastro
{
    unsigned limite; // quanto cabe
    unsigned N; // quantos tem agora
    Produto* p[MAXPRD];        
    int remove(const char* ident){};  // a partir do identificador
    int listagem(const char* titulo){};
    int busca(const char* chave){};  // identificador ou nome
};

int main(void)
{
    Cadastro unico;
    Cadastro prod;
    Cadastro filial[30];
    return 0;
}

 

O programa não faz nada, mas deve te mostrar a diferença. Ele declara 32 Cadastros. Já tem as funções de seu programa original...

 

 

 

 

 

  • Amei 1
Postado

Escrevendo a partir dos dados um exemplo em C++

 

Eu nada disse sobre sort() ou bibliotecas em C ou C++. Trata-se da maneira de escrever e da total ausência no programa da razão de se ter criado C++: classes. E do risco de escrever tudo misturado, dados, lógica, loops e tal.

 

Vou te mostrar um exemplo. A partir de seu produto. Faz boa parte do que precisa fazer, mas isso não importa. Espero que eu consiga mostrar o princípio dessas coisas. Se não entender sugiro perguntar aqui mesmo, justificando assim o meu tempo e ajudando a outros com questões parecidas. 

 

TODOS esses programas para iniciantes gravitam em torno de containers, a lista de produtos, a playlist, a lista de livros, as matrizes e as médias e tal. E os programas para não iniciantes também ;) 

 

C++ é uma linguagem enorme, complicada, enjoada mas sensacional para compor coisas e escrever protótipos. Mas muito da filosofia pode ser usada em C, COBOL, Assembler ou na lista de compras.

 

De volta ao exemplo

 

O programa que segue foi escrito em torno dos dados, copiado de seu código. E rodou certinho da primeira vez, como é comum nesses casos.

 

Ele cria um Cadastro e insere produtos até dar erro, o que deve acontecer por exemplo quando não couberem mais produtos. Aí o programa lista o cadastro e encerra, apagando tudo.

 

O Produto

 

struct Produto
{
    char   nome[100];
    char   tipo[50];
    double preco;
    char   localdisp[50];
    char   identificador[10];
    lli    quantidadedisp;
    Produto() // construtor padrão
        : nome("nome"),          tipo("tipo"),
          preco(0.0),          localdisp("local"),
          identificador("ident"),          quantidadedisp(0){};  // padrão

    friend Produto* fab_prd(int control);  // 'fabrica' um produto
    int             lista();               // lista esse produto
};

 

Claro que poderia usar strings e escrever de outros modos, criar outras funções e tal. Mas o que importa aqui é ver que em uma uma função de lista um produto. E ela faz parte do produto. Isso é o que deveria ser discutido nas primeiras aulas dos cursos de C++: a noção de classe, de objeto, de struct. E nada tem a ver com C.

 

E tem uma função que constrói um produto: Produto(). E cria um produto com tudo zerado porque não é importante quando se está desenvolvendo inicialmente a coisa:

 

    cout << "Produto 'vazio'\n";
    Produto teste;
    teste.lista();

 

teste aqui é um Produto desses. E se chamar lista() vai listar exatamente esse. Eis uma implementação de lista():

 

int Produto::lista()
{
    cout << setw(15) << nome << setw(15) << identificador << setw(10)
         << tipo << " R$ " << preco << " disp = " << quantidadedisp
         << "  " << localdisp << "\n";
    return 0;
}

 

Só um cout. Eis o que mostra
 

Produto 'vazio'
           nome          ident      tipo R$ 0 disp = 0  local

 

E não importa.

 

fab_prd()

 

E essa função é a que importa no início. Declarada assim

 

    Produto* fab_prd(int control);  // fabrica um produto

 

Isso é uma função factory. Ela cria um produto e retorna o endereço dele. Sem perguntas, sem teclar ENTER, sem nada. E você passa a testar o programa em minutos. Isso é o que importa.

 

Eis uma implementação:
 

Produto* fab_prd(int control)
{
    static unsigned id = 1000;
    Produto*        nv = new Produto;
    if (control <= 0)
    {  // marca o reinicio
        id = -control;
        srand(211217);
        return nullptr;
    }
    sprintf(nv->nome, "nome %04d", id);
    sprintf(nv->tipo, "tipo %04d", id);
    nv->preco = rand() % 10'000 + (rand() % 100 / 100.);
    sprintf(nv->localdisp, "local %04d", id);
    sprintf(nv->identificador, "ident %04d", id);
    nv->quantidadedisp = 1 + rand() % 10'000;
    id += 1;
    return nv;
}

 

Nada demais. Se chamar com algo negativo a função marca o reinício de um contador. A partir daí retorna Produtos preenchidos e arrumadinhos, mas numerados para poder usar nos testes. 10 produtos ou 10.000 deles. Na hora, sem stress. Com valores razoáveis mas aleatórios e reproduzíveis.

 

Acho que já entendeu: se tiver um Cadastro para 1.000 produtos pode chamar fab_prd() 1.000 vezes e inserir os caras no cadastro. 

 

Um exemplo dos primeiros 10, usando claro a função lista() para cada produto e começando em 100

 


      nome 0100     ident 0100 tipo 0100 R$ 1656.95 disp = 2743  local 0100
      nome 0101     ident 0101 tipo 0101 R$ 4430.71 disp = 3054  local 0101
      nome 0102     ident 0102 tipo 0102 R$ 9313.89 disp = 8009  local 0102
      nome 0103     ident 0103 tipo 0103 R$ 7261.27 disp = 5390  local 0103
      nome 0104     ident 0104 tipo 0104 R$ 6144.61 disp = 8414  local 0104
      nome 0105     ident 0105 tipo 0105 R$ 9309.45 disp = 2487  local 0105
      nome 0106     ident 0106 tipo 0106 R$ 9638.93 disp = 1970  local 0106
      nome 0107     ident 0107 tipo 0107 R$ 5963.22 disp = 2960  local 0107
      nome 0108     ident 0108 tipo 0108 R$ 8529.04 disp = 6114  local 0108
      nome 0109     ident 0109 tipo 0109 R$ 8028.23 disp = 2189  local 0109

 

Então tem os nomes e preços e tudo mais. Para 2 ou 200.000 produtos. E se rodar de novo vai ver de novo os mesmos valores. Não adianta ser aleatório se não for reproduzível nos testes.

 

O Cadastro

 

struct Cadastro
{
    unsigned limite;  // quanto cabe
    unsigned N;       // quantos tem agora
    Produto* p[MAXPRD];
    int      remove(const char* ident){};  // a partir do identificador
    int      listagem(const char* titulo);
    int      busca(const char* chave){};  // identificador ou nome
    int      insere(Produto* p);
    Cadastro(); // cria o cara
    ~Cadastro(); // destroi
};

 

Então agora existe um cadastro. É um vetor de ponteiros. E tem um limite. E tem uma função que lista. Lista o que? Produtos? Não. O cadastro. Esse é o conceito de encapsulamento.

 

E tem uma função que insere um produto. E para remover e para buscar. E elas não dependem de NADA global ou externo. 

 

Cadastro() cria um Cadastro e ~Cadastro() destrói um Cadastro. É o construtor e o destrutor da struct em C++. Pode ter várias dessas coisas.

 

Criando um Cadastro
 

Cadastro::Cadastro()
{
    limite = MAXPRD;
    N      = 0;  // vazio;
    p[0]   = nullptr;
}

 

Basta isso. Salvar o limite DENTRO do cadastro, e o contador. E os dados.

 

A saída do exemplo

 

Produto 'vazio'
           nome          ident      tipo R$ 0 disp = 0  local

Cadastro criado...
 Cadastro VAZIO!


        Teste: deve estar cheio agora

10 produtos no cadastro:

      nome 0100     ident 0100 tipo 0100 R$ 1656.95 disp = 2743  local 0100
      nome 0101     ident 0101 tipo 0101 R$ 4430.71 disp = 3054  local 0101
      nome 0102     ident 0102 tipo 0102 R$ 9313.89 disp = 8009  local 0102
      nome 0103     ident 0103 tipo 0103 R$ 7261.27 disp = 5390  local 0103
      nome 0104     ident 0104 tipo 0104 R$ 6144.61 disp = 8414  local 0104
      nome 0105     ident 0105 tipo 0105 R$ 9309.45 disp = 2487  local 0105
      nome 0106     ident 0106 tipo 0106 R$ 9638.93 disp = 1970  local 0106
      nome 0107     ident 0107 tipo 0107 R$ 5963.22 disp = 2960  local 0107
      nome 0108     ident 0108 tipo 0108 R$ 8529.04 disp = 6114  local 0108
      nome 0109     ident 0109 tipo 0109 R$ 8028.23 disp = 2189  local 0109

Apagando o Cadastro

 

main() para o exemplo

 

int main(void)
{
    cout << "Produto 'vazio'\n";
    Produto teste;
    teste.lista();

    Cadastro unico;
    unico.listagem("\nCadastro criado...");
    fab_prd(-100);  // reinicia a partir de 100
    Produto* um = fab_prd(1);
    while (unico.insere(um) == 0) delete um, um = fab_prd(1);
    // inseriu ate dar erro: o cadastro deve estar cheio
    delete um;  // apaga o ultimo
    unico.listagem("\n\tTeste: deve estar cheio agora\n");
    return 0;
}

 

As 3 primeiras linhas apenas mostram que o produto é criado por enquanto com valores fixos, só para explicar o mecanismo.

 

O Cadastro unico é criado ao ser declarado. E está vazio claro. E isso é confirmado na linha de baixo, onde ele é listado. A função que lista aceita um título opcional só para conveniência e acho que dá pra entender porque.

 

A primeira chamada a fab_prd() com um valor negativo sinaliza para a função que é para reiniciar a numeração dos campos a partir de 100.

 

Como insere() retorna 0 se der tudo certo esse simples loop enche o cadastro com MAXPRD produtos para poder testar as funções e os recursos do programa:

 

    Produto* um = fab_prd(1);
    while (unico.insere(um) == 0) delete um, um = fab_prd(1);
    // inseriu ate dar erro: o cadastro deve estar cheio
    delete um;  // apaga o ultimo

 

Então quando insere() der pau deve ser porque atingiu o limite. E então chama a listagem() para mostrar os caras na tela e termina o programa:

 

    unico.listagem("\n\tTeste: deve estar cheio agora\n");
    return 0;

 

Compare isso com o que você precisaria fazer com o seu menu e parado em frente a tela inventando campos para 10 produtos e vai entender porque estou insistindo nisso.

 

Inserindo um produto

 

int Cadastro::insere(Produto* novo)
{
    if (N >= limite) return -1;  // cheio
    p[N] = new Produto(*novo);
    N += 1;  // conta esse
    return 0;
}

 

Simples: não aceita nada de fora: o que vier em novo vai ser copiado para uma variável novinha e o ponteiro apenas vai para o cadastro. O contador é incrementado e a vida segue. Sem perguntas, sem interatividade.

 

Listando o cadastro inteiro

 

int Cadastro::listagem(const char* titulo)
{
    if (titulo != NULL) cout << titulo << "\n";
    if (N == 0)
    {
        cout << " Cadastro VAZIO!\n\n";
        return 0;
    }
    cout << N << " produtos no cadastro:\n\n";
    for (unsigned i = 0; i < N; i += 1) p[i]->lista();
    cout << endl;
    return 0;
}

 

Pois é: se o cadastro tem produtos e tem uma função que lista o produto é claro que é só chamar essa função com os produtos que estão no Cadastro. E não precisa de nada global ou externo. DENTRO do Cadastro tem o limite, a capacidade e os ponteiros para os produtos:
 

        for (unsigned i = 0; i < N; i += 1) p[i]->lista();

 

E o resto do código é só para tratar erros e mostrar o título e tratar o lance do cadastro vazio. 10 linhas.

 

O programa todo

 

#define MAXPRD 10
#include <iomanip>
#include <iostream>
using namespace std;
using lli = long long int;

struct Produto
{
    char   nome[100];
    char   tipo[50];
    double preco;
    char   localdisp[50];
    char   identificador[10];
    lli    quantidadedisp;
    Produto() // construtor padrão
        : nome("nome"),          tipo("tipo"),
          preco(0.0),          localdisp("local"),
          identificador("ident"),          quantidadedisp(0){};  // padrão

    friend Produto* fab_prd(int control);  // 'fabrica' um produto
    int             lista();               // lista esse produto
};

struct Cadastro
{
    unsigned limite;  // quanto cabe
    unsigned N;       // quantos tem agora
    Produto* p[MAXPRD];
    int      remove(const char* ident){};  // a partir do identificador
    int      listagem(const char* titulo);
    int      busca(const char* chave){};  // identificador ou nome
    int      insere(Produto* p);
    Cadastro(); // cria o cara
    ~Cadastro(); // destroi
};

Produto* fab_prd(int control);  // fabrica um produto

int main(void)
{
    cout << "Produto 'vazio'\n";
    Produto teste;
    teste.lista();

    Cadastro unico;
    unico.listagem("\nCadastro criado...");
    fab_prd(-100);  // reinicia a partir de 100
    Produto* um = fab_prd(1);
    while (unico.insere(um) == 0) delete um, um = fab_prd(1);
    // inseriu ate dar erro: o cadastro deve estar cheio
    delete um;  // apaga o ultimo
    unico.listagem("\n\tTeste: deve estar cheio agora\n");
    return 0;
}

// produto

Produto* fab_prd(int control)
{
    static unsigned id = 1000;
    Produto*        nv = new Produto;
    if (control <= 0)
    {  // marca o reinicio
        id = -control;
        srand(211217);
        return nullptr;
    }
    sprintf(nv->nome, "nome %04d", id);
    sprintf(nv->tipo, "tipo %04d", id);
    nv->preco = rand() % 10'000 + (rand() % 100 / 100.);
    sprintf(nv->localdisp, "local %04d", id);
    sprintf(nv->identificador, "ident %04d", id);
    nv->quantidadedisp = 1 + rand() % 10'000;
    id += 1;
    return nv;
}

int Produto::lista()
{
    cout << setw(15) << nome << setw(15) << identificador << setw(10)
         << tipo << " R$ " << preco << " disp = " << quantidadedisp
         << "  " << localdisp << "\n";
    return 0;
}

// Cadastro

Cadastro::Cadastro()
{
    limite = MAXPRD;
    N      = 0;  // vazio;
    p[0]   = nullptr;
}

Cadastro::~Cadastro()
{  // apaga todo mundo
    cout << "Apagando o Cadastro\n";
    for (auto um : p) delete um;
}

int Cadastro::insere(Produto* novo)
{
    if (N >= limite) return -1;  // cheio
    p[N] = new Produto(*novo);
    N += 1;  // conta esse
    return 0;
}

int Cadastro::listagem(const char* titulo)
{
    if (titulo != NULL) cout << titulo << "\n";
    if (N == 0)
    {
        cout << " Cadastro VAZIO!\n\n";
        return 0;
    }
    cout << N << " produtos no cadastro:\n\n";
    for (unsigned i = 0; i < N; i += 1) p[i]->lista();
    cout << endl;
    return 0;
}

 

Isso é só um exemplo da filosofia de construção. Nem vou dizer que é uma boa maneira e não importa muito aqui. O que importa é que

  • roda certinho desde a primeira vez.
  • Implementa de fato um container. 
  • usa os conceitos de encapsulamento para não ficar repetindo código
  • não usa memória externa à classe Cadastro. Tudo é copiado
  • nada interativo por enquanto

 

Outra hora escrevo uma função para classificar esse cadastro. Seguindo a mesma filosofia, claro que bastaria classificar os ponteiros e não os dados. Pense nisso. 

 

:) 

 

  • Curtir 1
  • Amei 1
Postado

Fase 2 :) Classifica o cadastro por um critério qualquer

 

Classificar o cadastro é bem simples. Vou manter o modo meio C que usei acima e mudar umas poucas linhas.

 

Classificar envolve antes de tudo a função de ordem. Claro que C++ tem sort e mais de uma centena de algoritmos em std mas vou mudar o mínimo no exemplo acima.

 

Uma opção é inserir já na ordem. Outra seria classificar a qualquer momento usando uma função. Vou fazer as duas coisas.

 

Inserindo em alguma ordem

 

Uma ordem óbvia seria a ordem de identificador. Para ficar mais evidente vou mudar a função fábrica e retornar um identificador aleatório da forma "ident abcd".

 

Basta alterar 
 

    sprintf(nv->identificador, "ident %04d", id);

 

 por

 

    char ident[5] = {0};
    ident[0]      = 'a' + rand() % 26;
    ident[1]      = 'a' + rand() % 26;
    ident[2]      = 'a' + rand() % 26;
    ident[3]      = 'a' + rand() % 26;
    sprintf(nv->identificador, "ident %s", ident );

 

O critério de classificação

 

Abaixo os dois que vamos usar: por nome e por identificador. Sim, apenas uma linha porque são montados como string e strcmp() compara strings e retorna -1,0 ou 1 conforme o resultado da comparação. É só disso que precisamos.

 

int cmp_ident(Produto* um, Produto* outro)
{
    return strcmp(um->identificador, outro->identificador);
};

int cmp_nome(Produto* um, Produto* outro)
{
    return strcmp(um->nome, outro->nome);
};

 

E como inserir na ordem?

 

Basta mudar insere e passar o nome da função que compara: ao invés de inserir sempre no final vai inserir na ordem certa.

 

Antes em insere() com 4 linhas

 

int Cadastro::insere(Produto* novo)
{
    if (N >= limite) return -1;  // cheio
    p[N] = new Produto(*novo);
    N += 1;  // conta esse
    return 0;
}

 

Depois, inserindo na ordem, agora com 7 linhas

 

int Cadastro::insere(Produto* novo, int (*cmp)(Produto*,Produto*) )
{
    if (N >= limite) return -1;  // cheio
    p[N] = new Produto(*novo); // coloca no fim
    for (int j = N; j > 0; j -= 1)
        if (cmp(p[j - 1], p[j]) > 0)
            swap(p[j - 1], p[j]);
    N += 1;  // conta esse
    return 0;
}

 

A lógica é simples: coloca o novo no final e depois usa insertion sort e põe na posição. Como o cadastro só tem os ponteiros basta inverter os dois.

 

No exemplo

 

      nome 0106     ident avuh tipo 0106 R$ 4340.90 disp =  7319  local 0106
      nome 0103     ident bhid tipo 0103 R$ 5963.22 disp =  8029  local 0103
      nome 0105     ident kipv tipo 0105 R$ 3561.21 disp =  5932  local 0105
      nome 0100     ident mkxb tipo 0100 R$ 1656.95 disp =  9314  local 0100
      nome 0107     ident oqne tipo 0107 R$ 7536.07 disp =  2676  local 0107
      nome 0109     ident pigh tipo 0109 R$ 8582.24 disp =  3226  local 0109
      nome 0108     ident utvl tipo 0108 R$ 2827.96 disp =  4226  local 0108
      nome 0104     ident vqfb tipo 0104 R$ 8123.88 disp =   265  local 0104
      nome 0101     ident xtny tipo 0101 R$ 8689.08 disp =  7362  local 0101
      nome 0102     ident zwij tipo 0102 R$ 8413.09 disp =  1970  local 0102

 

 

E como classificar por algum critério depois de inserir por alguma ordem?

 

Pode ser só criar um método sort() em Cadastro e passar para ele o nome da função de comparação e fazer a mesma coisa...

 

Não estamos em busca de nenhuma medalha de sort. Usando o trivial bubble sort por exemplo:

 

int Cadastro::sort(int (*cmp)(Produto*, Produto*))
{   // classifica o cadastro de acordo
    // com um criterio dado por cmp
    if (N == 0) return 0;  // ok, vazio
    int mudou_algo = 0;
    for (unsigned i = 0; i < N - 1; i++)
    {
        mudou_algo = 0;
        for (unsigned j = 0; j < N - i - 1; j++)
            if ( cmp(p[j],p[j+1]) > 0)
            {
                swap(p[j], p[j + 1]);
                mudou_algo = 1;
            }
        // se não mudou nenhum ja esta em ordem
        if (mudou_algo == 0) break;
    };
    return 0;
};

 

Isso faz o esperado. Sem variáveis externas, sem globais, sem interatividade,  sem escrever na tela

 

Como usar?

 

Eis  main() para um programa que insere por ordem de identificador e classifica por ordem de nome e depois de novo por ordem de identificador e mostra na tela

 

int main(void)
{
    Cadastro unico;
    unico.listagem("\nCadastro criado...");
    fab_prd(-100);  // reinicia a partir de 100
    Produto* um = fab_prd(1);
    while (unico.insere(um, cmp_ident ) == 0) delete um, um = fab_prd(1);
    // inseriu ate dar erro: o cadastro deve estar cheio
    delete um;  // apaga o ultimo
    unico.listagem("\n\tTeste: deve estar cheio agora\n");
    // sort 1
    unico.sort(cmp_nome);
    unico.listagem("\n\tEm ordem de nome:\n");
    // sort 2
    unico.sort(cmp_ident);
    unico.listagem("\n\tAgora em ordem de identificador:\n");
    return 0;
}

 

4 linhas a mais apenas. Como listagem() já aceita um título e sort só depende do critério fica tudo bem legível

 

Saída do exemplo
 

Cadastro criado...
 Cadastro VAZIO!


        Teste: deve estar cheio agora

10 produtos no cadastro:

      nome 0106     ident avuh tipo 0106 R$ 4340.90 disp =  7319  local 0106
      nome 0103     ident bhid tipo 0103 R$ 5963.22 disp =  8029  local 0103
      nome 0105     ident kipv tipo 0105 R$ 3561.21 disp =  5932  local 0105
      nome 0100     ident mkxb tipo 0100 R$ 1656.95 disp =  9314  local 0100
      nome 0107     ident oqne tipo 0107 R$ 7536.07 disp =  2676  local 0107
      nome 0109     ident pigh tipo 0109 R$ 8582.24 disp =  3226  local 0109
      nome 0108     ident utvl tipo 0108 R$ 2827.96 disp =  4226  local 0108
      nome 0104     ident vqfb tipo 0104 R$ 8123.88 disp =   265  local 0104
      nome 0101     ident xtny tipo 0101 R$ 8689.08 disp =  7362  local 0101
      nome 0102     ident zwij tipo 0102 R$ 8413.09 disp =  1970  local 0102


        Em ordem de nome:

10 produtos no cadastro:

      nome 0100     ident mkxb tipo 0100 R$ 1656.95 disp =  9314  local 0100
      nome 0101     ident xtny tipo 0101 R$ 8689.08 disp =  7362  local 0101
      nome 0102     ident zwij tipo 0102 R$ 8413.09 disp =  1970  local 0102
      nome 0103     ident bhid tipo 0103 R$ 5963.22 disp =  8029  local 0103
      nome 0104     ident vqfb tipo 0104 R$ 8123.88 disp =   265  local 0104
      nome 0105     ident kipv tipo 0105 R$ 3561.21 disp =  5932  local 0105
      nome 0106     ident avuh tipo 0106 R$ 4340.90 disp =  7319  local 0106
      nome 0107     ident oqne tipo 0107 R$ 7536.07 disp =  2676  local 0107
      nome 0108     ident utvl tipo 0108 R$ 2827.96 disp =  4226  local 0108
      nome 0109     ident pigh tipo 0109 R$ 8582.24 disp =  3226  local 0109


        Agora em ordem de identificador:

10 produtos no cadastro:

      nome 0106     ident avuh tipo 0106 R$ 4340.90 disp =  7319  local 0106
      nome 0103     ident bhid tipo 0103 R$ 5963.22 disp =  8029  local 0103
      nome 0105     ident kipv tipo 0105 R$ 3561.21 disp =  5932  local 0105
      nome 0100     ident mkxb tipo 0100 R$ 1656.95 disp =  9314  local 0100
      nome 0107     ident oqne tipo 0107 R$ 7536.07 disp =  2676  local 0107
      nome 0109     ident pigh tipo 0109 R$ 8582.24 disp =  3226  local 0109
      nome 0108     ident utvl tipo 0108 R$ 2827.96 disp =  4226  local 0108
      nome 0104     ident vqfb tipo 0104 R$ 8123.88 disp =   265  local 0104
      nome 0101     ident xtny tipo 0101 R$ 8689.08 disp =  7362  local 0101
      nome 0102     ident zwij tipo 0102 R$ 8413.09 disp =  1970  local 0102

Apagando o Cadastro

 

Como o cadastro é preenchido por uma função até encher basta mudar o tamanho e vai funcionar igualzinho para 100.000 ao invés de 10 produtos.

 

O código completo

 

#define MAXPRD 10
#include <iomanip>
#include <iostream>
using namespace std;
using lli = long long int;

struct Produto
{
    char   nome[100];
    char   tipo[50];
    double preco;
    char   localdisp[50];
    char   identificador[10];
    lli    quantidadedisp;
    Produto() // construtor padrão
        : nome("nome"),          tipo("tipo"),
          preco(0.0),          localdisp("local"),
          identificador("ident"),          quantidadedisp(0){};  // padrão

    friend Produto* fab_prd(int control);  // 'fabrica' um produto
    int             lista();               // lista esse produto
    friend int      cmp_ident(Produto&, Produto&);
    friend int      cmp_nome(Produto&, Produto&);
};

struct Cadastro
{
    unsigned limite;  // quanto cabe
    unsigned N;       // quantos tem agora
    Produto* p[MAXPRD];
    int      busca(const char* chave){};  // identificador ou nome
    int      insere(Produto*, int (*cmp)(Produto*, Produto*));
    int      listagem(const char* titulo);
    int      remove(const char* ident){};  // a partir do identificador
    int      sort(int (*cmp)(Produto*, Produto*));
    Cadastro(); // cria o cara
    ~Cadastro(); // destroi
};

Produto* fab_prd(int control);  // fabrica um produto
int      cmp_ident(Produto*, Produto*);
int      cmp_nome (Produto*, Produto*);

int main(void)
{
    Cadastro unico;
    unico.listagem("\nCadastro criado...");
    fab_prd(-100);  // reinicia a partir de 100
    Produto* um = fab_prd(1);
    while (unico.insere(um, cmp_ident ) == 0) delete um, um = fab_prd(1);
    // inseriu ate dar erro: o cadastro deve estar cheio
    delete um;  // apaga o ultimo
    unico.listagem("\n\tTeste: deve estar cheio agora\n");
    // sort 1
    unico.sort(cmp_nome);
    unico.listagem("\n\tEm ordem de nome:\n");
    // sort 2
    unico.sort(cmp_ident);
    unico.listagem("\n\tAgora em ordem de identificador:\n");
    return 0;
}

// produto 

Produto* fab_prd(int control)
{
    static unsigned id = 1000;
    Produto*        nv = new Produto;
    if (control <= 0)
    {  // marca o reinicio
        id = -control;
        srand(211217);
        return nullptr;
    }
    sprintf(nv->nome, "nome %04d", id);
    sprintf(nv->tipo, "tipo %04d", id);
    nv->preco = rand() % 10'000 + (rand() % 100 / 100.);
    sprintf(nv->localdisp, "local %04d", id);
    // cria ident alfabetico
    char ident[5] = {0};
    ident[0]      = 'a' + rand() % 26;
    ident[1]      = 'a' + rand() % 26;
    ident[2]      = 'a' + rand() % 26;
    ident[3]      = 'a' + rand() % 26;
    sprintf(nv->identificador, "ident %s", ident );
    nv->quantidadedisp = 1 + rand() % 10'000;
    id += 1;
    return nv;
}

int Produto::lista()
{
    cout << setw(15) << nome << setw(15) << identificador << setw(10)
         << tipo << " R$ " << fixed << 
        setprecision(2) << preco <<
        " disp = " << setw(5) << quantidadedisp
         << "  " << localdisp << "\n";
    return 0;
}


// Cadastro

Cadastro::Cadastro()
{
    limite = MAXPRD;
    N      = 0;  // vazio;
    p[0]   = nullptr;
}

Cadastro::~Cadastro()
{  // apaga todo mundo
    cout << "Apagando o Cadastro\n";
    for (auto um : p) delete um;
};

int Cadastro::insere(Produto* novo, int (*cmp)(Produto*,Produto*) )
{
    if (N >= limite) return -1;  // cheio
    p[N] = new Produto(*novo); // coloca no fim
    for (int j = N; j > 0; j -= 1)
        if (cmp(p[j - 1], p[j]) > 0)
            swap(p[j - 1], p[j]);
    N += 1;  // conta esse
    return 0;
}

int Cadastro::listagem(const char* titulo)
{
    if (titulo != NULL) cout << titulo << "\n";
    if (N == 0)
    {
        cout << " Cadastro VAZIO!\n\n";
        return 0;
    }
    cout << N << " produtos no cadastro:\n\n";
    for (unsigned i = 0; i < N; i += 1) p[i]->lista();
    cout << endl;
    return 0;
}

int Cadastro::sort(int (*cmp)(Produto*, Produto*))
{   // classifica o cadastro de acordo
    // com um criterio dado por cmp
    if (N == 0) return 0;  // ok, vazio
    int mudou_algo = 0;
    for (unsigned i = 0; i < N - 1; i++)
    {
        mudou_algo = 0;
        for (unsigned j = 0; j < N - i - 1; j++)
            if ( cmp(p[j],p[j+1]) > 0)
            {
                swap(p[j], p[j + 1]);
                mudou_algo = 1;
            }
        // se não mudou nenhum ja esta em ordem
        if (mudou_algo == 0) break;
    };
    return 0;
};

// helpers

int cmp_ident(Produto* um, Produto* outro)
{
    return strcmp(um->identificador, outro->identificador);
};

int cmp_nome(Produto* um, Produto* outro)
{
    return strcmp(um->nome, outro->nome);
};

 

Considerando o quanto dos programas propostos nessas listas envolvem percorrer e classificar containers de estruturas recomendo testar e rodar em sua máquina até entender porque pode usar no futuro  muitas vezes@Pedro Ulisses Maia  :) 

 

  • Amei 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!