Ir ao conteúdo
  • Cadastre-se

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


Ir à solução Resolvido por arfneto,

Posts recomendados

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

Link para o comentário
Compartilhar em outros sites

  • Solução
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
Link para o comentário
Compartilhar em outros sites

@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 !

Link para o comentário
Compartilhar em outros sites

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?

Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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