Ir ao conteúdo
  • Cadastre-se

C++ Verificar se existe duplicação de valor na minha lista


jottinha852

Posts recomendados

Boa noite! 

Iniciei a pouco tempo o curso de programação e resolvi fazer esse programa para fins acadêmicos,  eu gostaria que esse programa não cadastrar-se ninguém se o ID do cliente já estiver em uso, porém o programa ignora meu loop e não identifica isso, alguém consegue me ajudar? Desde já agradeço. Gostaria de verificar a parte do - Lista *cadastro_novosclientes(Lista *novo).

 

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
#include <stdbool.h>
#include <string.h>
#include <locale.h>

typedef struct Lista
{
    char pessoa[50];
    char cpf[15];
    int idade;
    unsigned long int iden;
    struct Lista *proximo;
}Lista;
//valores dos pratos    
float a = 25.00;
float b = 15.00;
float c = 65.80;
float comprado = 0;//para atualizar o valor que o cliente deve

//declaraçaõ de funções
Lista* cadastro_novosclientes(Lista* novo);
void imprima(Lista *novo);
void prato(Lista *novo, int x);

int main(void)
{
    setlocale(LC_ALL, "Portuguese"); //ACRESCENTANDO A LINGUA PORTUGUESA NO PROGRAMA
    Lista *novo = NULL; // Ponteiro para percorrer aos dados mais tarde
    
    int x; //receber o ID do cliente que comprou
    
    char resposta; //verificar se é um novo cliente ou não
    
    //Garante que só saia dessa pagina se for dado o comando de finalização
    while(resposta != 'S')
    {
    
        printf(" _________________________________________\n");
        printf("|                   MENU                  |\n");
        printf("|_________________________________________|\n");
        printf("|(N)        NOVO CADASTRO                 |\n");
        printf("|(P)        JA CADASTRADO                 |\n");
        printf("|(l)        LISTAR CLIENTES               |\n");
        printf("|(S)        FINALIZAR                     |\n");
        printf("|_________________________________________|\n");
        
        fflush(stdin);
        resposta = getch();
        resposta = toupper(getch()); // para não ter problema caso a resposta seja em maiusculo ou não
        
    
    
        switch(resposta) //começando o processamento
        {
            case 'N':
                system("cls"); // limpar a tela
                printf("------------------------------------------\n");
                printf("                 CADASTRO                 \n");
                printf("------------------------------------------\n");
                novo= cadastro_novosclientes(novo);
                getch();
                system("cls");
                break;
            
            case 'P':
                printf("Qual o ID: ");
                scanf("%i", &x);
                fflush(stdin);
                prato(novo, x);
                getch();
                system("cls");
                break;
            
            case 'L': 
                system("cls");
                printf("------------------------------------------\n");
                printf("          Clientes já cadastrados         \n");
                printf("------------------------------------------\n");
                imprima(novo);
                getch();
                system("cls");
                break;
        
            default:
                //se for dado um caractere invalido não retornar nada
                system("cls");
        }
    }
}


Lista *cadastro_novosclientes(Lista *novo)
{
    Lista dados;
    Lista *p = novo;
    bool identificar = false;
    
    printf("Nome:");
    fgets(dados.pessoa, 50, stdin);
    
    printf("Qual a idade: ");
    scanf("%i", &dados.idade);
    fflush(stdin);
        
    printf("Qual o CPF: ");
    fgets(dados.cpf, 15, stdin);
    
    printf("Qual a identificação: ");
    scanf("%u", &dados.iden);
    fflush(stdin);
    
    //verificar se meu número de identificação já existe
    for(p=novo; p!=NULL; p= p->proximo){
        if(p->iden==dados.iden){
            bool identificador= true; 
            break;
        }    
     }
    
    //salvando os novos dados
    if(!identificar)
    {
        Lista *novos_dados = (Lista*)malloc(sizeof(Lista));
    
        strcpy(novos_dados -> pessoa, dados.pessoa);
        novos_dados -> idade = dados.idade;
        strcpy(novos_dados -> cpf, dados.cpf);
        novos_dados -> iden = dados.iden;
        novos_dados -> proximo = novo;
    
        printf("------------------------------------------\n");
        printf("           Cadastro finalizado            \n");
        printf("------------------------------------------\n");
        printf("\n\n PRESSIONE QUALQUER TECLA PARA VOLTAR AO MENU\n");
        return novos_dados;
    }
    else
    {
        printf("Número de identificação já cadastrado");
        printf("\n\n PRESSIONE QUALQUER TECLA PARA VOLTAR AO MENU\n");
        return novo;
    }
}

void prato(Lista *novo, int x)
{
    char n; //identificar o input do usuario
    Lista *p;
    for(p = novo; p != NULL; p -> proximo)
    {
        if(p -> iden == x)
        {
            printf("Qual prato %s comprou? A, B ou  ", p -> pessoa);
            n = getch();
            n = toupper(getch());
        
            switch(n)
            {
                case 'A':
                    comprado += a;
                    printf("\n");
                    printf("%s tem que pagar %.2f\n", p -> pessoa, comprado);
                    comprado = 0;
                    break;
                case 'B':
                    comprado += b;
                    printf("\n");
                    printf("%s tem que pagar %.2f\n", p -> pessoa, comprado);
                    comprado = 0;
                    break;
                case 'C':
                    comprado += c;
                    printf("\n");
                    printf("%s tem que pagar %.2f\n", p -> pessoa, comprado);
                    comprado = 0;
                    break;
            }
            printf("\n\n PRESSIONE QUALQUER PLACA PARA VOLTAR AO MENU\n");
            return;
        }
    }
}

void imprima(Lista *novo)//imprime os nomes ja cadastrados
{
    Lista *p;
    for(p = novo; p != NULL; p = p -> proximo)
    {
        printf("                NOME: %s\n", p -> pessoa);
        printf("         ID: %i    Idade: %u", p -> iden, p -> idade);
        printf("      CPF: %s\n", p -> cpf);
        printf("------------------------------------------\n");
    }
    printf("\n\n PRESSIONE QUALQUER PLACA PARA VOLTAR AO MENU\n");
}

 

Link para o comentário
Compartilhar em outros sites

@jottinha852 Eu acho que você deveria separar o código da sua lista encadeada do seu programa.

Isso só vai atrapalhar, aprenda a fazer a lista encadeada primeiro para só depois você começar a fazer o programa.

 

Exemplo de lista encadeada.

Spoiler
/* Lista encadeada generica */
#include <stdio.h>
#include <stdlib.h>

struct no_t
{
    int valor;
    struct no_t *anterior, *proximo;
};

struct lista_t
{
    struct no_t *inicio, *fim;
};

void
apagaNo(struct no_t **no);
/*
 * Apaga apenas um nó
 */

struct no_t
*criaNo(int valor);
/*
 * Apaga um nó
 */

void
apagaLista(struct lista_t **lista);
/*
 * Apaga toda uma lista
 */

struct lista_t
*criaLista(void);
/*
 * Cria uma lista vazia
 */

struct no_t
*colocaNoInicio(struct lista_t *lista, int valor);
/*
 * Coloca um nó no inicio da lista e devolve o nó colocado
 */

struct no_t
*colocaNoFim(struct lista_t *lista, int valor);
/*
 * Coloca um nó no fim da lista e devolve o nó colocado
 */

int main(void)
{
    struct lista_t *lista = criaLista();
    struct no_t *no = NULL;

    colocaNoFim(lista, 10);
    colocaNoFim(lista, 11);
    colocaNoFim(lista, 12);
    colocaNoInicio(lista, 1);
    colocaNoInicio(lista, 2);
    colocaNoInicio(lista, 3);

    printf("Mostra a lista do comeco ao fim\n");
    no = lista->inicio;
    while (no != NULL) {
        printf("%d\n", no->valor);
        no = no->proximo;
    }

    printf("Mostra a lista do fim ao comeco\n");
    no = lista->fim;
    while (no != NULL) {
        printf("%d\n", no->valor);
        no = no->anterior;
    }

    apagaLista(&lista);
    return(0);
}

void
apagaNo(struct no_t **no)
{
    if (*no != NULL) {
        (*no)->anterior = (*no)->proximo = NULL;
        free(*no);
    }
    *no = NULL;
}

struct no_t
*criaNo(int valor)
{
    struct no_t *no = malloc(sizeof(*no));
    if (no != NULL) {
        no->anterior = no->proximo = NULL;
        no->valor = valor;
        return(no);
    }

    return(NULL);
}

void
apagaLista(struct lista_t **lista)
{
    if (*lista != NULL) {
        struct no_t *tmp = (*lista)->inicio;
        while (tmp != NULL) {
            struct no_t *aux = tmp->proximo;
            apagaNo(&tmp);
            tmp = aux;
        }
        (*lista)->inicio = (*lista)->fim = NULL;
        free(*lista);
    }

    (*lista) = NULL;
}

struct lista_t
*criaLista(void)
{
    struct lista_t *lista = malloc(sizeof(*lista));

    if (lista != NULL) {
        lista->inicio = lista->fim = NULL;
        return(lista);
    }
    return(NULL);
}


struct no_t
*colocaNoInicio(struct lista_t *lista, int valor)
{
    struct no_t *no = criaNo(valor);

    if (no != NULL) {
        if (lista->inicio == NULL) {
            lista->inicio = lista->fim = no;
        } else {
            lista->inicio->anterior = no;
            no->proximo = lista->inicio;
            lista->inicio = no;
        }
        return(no);
    }

    return(NULL);
}

struct no_t
*colocaNoFim(struct lista_t *lista, int valor)
{
    struct no_t *no = criaNo(valor);
    if (no != NULL) {
        if (lista->inicio == NULL) {
            lista->inicio = lista->fim = no;
        } else {
            lista->fim->proximo = no;
            no->anterior = lista->fim;
            lista->fim = no;
        }
        return(no);
    }

    return(NULL);
}

 

 

Não use system() nem fflush() para limpar a saída você só tera problemas usando isso.

Aprenda a pegar a linha inteira passada pelo usuário e interpretar o conteúdo contido na mesma.

Link para o comentário
Compartilhar em outros sites

Olá!

 

Meu palpite: seu programa está muito grande e complicado e talvez não precisasse. Vou listar alguns problemas e te mostrar um ou outro exemplo de como fazer. Pode ser vantagem fazer como vou te mostrar.

 

Postou um programa em C mas marcou o tópico como C++. São diferentes animais, assim como C#. Muito diferentes.

 

O caminho que usou para seguir a suposta lista de ID em uso é muito complicado. Podia usar apenas um vetor com as ID já em uso e olhar uma a uma. Num programa que sequer grava os dados em disco e sempre reinicia do zero não vai ter mais que uns poucos elementos nas listas afinal...

 

Antes de tentar pesquisar teste sua função de listar e veja se a lista ao menos existe com os dados que você espera que tenha lá dentro.

 

Escreva em torno dos dados. É muito mais simples. Muitos programas escritos assim rodam certo na primeira vez.

 

Sobre seu código

 

Um exemplo

 

        printf("------------------------------------------\n");
        printf("           Cadastro finalizado            \n");
        printf("------------------------------------------\n");
        printf("\n\n PRESSIONE QUALQUER TECLA PARA VOLTAR AO MENU\n");

 

É a mesma coisa que

 

        printf("\
------------------------------------------\n\
           Cadastro finalizado            \n\
------------------------------------------\n\n\n\
PRESSIONE QUALQUER TECLA PARA VOLTAR AO MENU\n"
        );

 

Isso aparece muitas vezes em seu programa. Já deve ter percebido que é muito chato fazer isso em C

e ter que ficar procurando palavras e espaços dentro de chamadas a printf(). E acho que sabe que

chamar 5 vezes uma função  para mostrar coisas na tela não é nada melhor que chamar UMA vez só.

 

E é mais fácil de ler e alterar se usar a segunda forma.

 

Evite esse tipo de comentário
 

//declaraçaõ de funções
Lista* cadastro_novosclientes(Lista* novo);
void imprima(Lista *novo);
void prato(Lista *novo, int x);

 

É bem conhecido o fato de protótipos serem declarações de funções. Documente o que está fazendo, como está fazendo. Por exemplo, comente seu algoritmo de procurar por uma ID pra saber se foi usada, explicando o que está fazendo.

 

  • Não use acentos. Em variáveis, em strings ou em comentários, a menos que o enunciado exija. Não vai aprender nada e só vai ter problemas. Se precisa deles use depois.
     
  • 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.
     
  • 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 de dados. E nesse registro um campo é a chave, que se usa para comparar dois registros e dar uma noção de ordenação.
     
  • evite retornar void de funções: em geral é um desperdício. Muitas vezes um erro. Use argumentos nas funções, e retorne algo delas
     
  • Não há razão para incluir conio.h. Essa é uma biblioteca dos anos 80 e nada acrescenta a um programa moderno. Mesmo nos anos '80 ela era usada em geral apenas para ler letrinhas do teclado sem mostrar na tela, limpar a tela e escrever letrinhas com cores --- getch(), kdhit(), clrscr() e textcolor(). A mesma coisa que estava disponível em C no Windows e no Unix depois Linux em poucas linhas.
     
  • Nunca use variáveis globais. Isso é um pesadelo e sempre vai cair na sua cabeça. Em geral é proibido em empresas e escolas. Não declare NADA fora de main().
     
  • Nunca leia valores do teclado para alimentar seu programa antes dele estar rodando. Só vai te atrasar e não acrescenta absolutamente nada. Use constantes, use funções que retornam a estrutura preenchida. Ao terminar os  testes aí sim incorpore a leitura. Um programa interativo é chato para testar. Durante o desenvolvimento ninguém quer interagir com o programa.
     
  • Se seu programa tem um menu, entenda que o menu() deve mostrar as opções e ler e retornar a opção. Um void menu() é um desperdício.
     
  • não use fflush(): isso só está definido para fluxos de saída. Em alguns compiladores pode até funcionar, mas é um sinal de fez algo errado
     
  • scanf() foi escrita para ler entrada formatada. Não use para ler do teclado, que claramente não é entrada formatada. Só vai dar mais trabalho. Muito mais trabalho.
     
  • Ao usar scanf() ou alguma função da família, como fscanf() entenda que ela retorna um valor. E teste. É ingênuo deixar o programa seguir sem testar. TESTE sempre. Para 5 especificadores --- aquelas coisas com % na frente e que não tem um asterisco, como "%d %d %f %f %d" scanf() pode ler de 0 1 5 itens ou dar erro e retornar -1. Então teste o retorno que vai estar entre -1 e 5...
     
  • Não existe "lixo de teclado": necessidades assim na entrada indicam apenas que não entendeu bem o que está lendo e o que é a entrada via teclado, free form: o usuário pode digitar qualquer coisa e é o seu programa que tem que se virar O teclado tem ao menos 105 teclas de liberdade e o usuário pode digitar qualquer coisa em qualquer ordem.
     
  • evite ler do teclado a menos que seja o objetivo do problema. Ler de arquivos é muito mais simples e seguro e fácil de reproduzir. Não há razão para ficar parado em frene a tela minutos inventando nomes de campos e coisas assim: o efeito é que vai acabar não testando direito porque é difícil controlar e repetir testes.
     
  • Não misture entrada de dados ou formatação com a apresentação dos dados ou a lógica do programa, Isso é um desastre para manutenção e desenvolvimento

Sobre os dados:
 

Entenda que lista é um container, e é uma ferramenta. Você não programa isso toda hora.

Você faz uma vez e usa sempre.

Se fizer direito.

 

Isso é o que está usando, e acho que deu pra ver que vai dar um trabalho infernal pra escrever e testar. E pouco vai servir em outro programa, aquele outro de livros, ou aquele da playlist, aqueles clássicos programas de listas ligada que vemos aqui a toda hora:

 

typedef struct Lista
{
    char              pessoa[50];
    char              cpf[15];
    int               idade;
    unsigned long int iden;
    struct Lista *    proximo;
} Lista;

 

Está usando ponteiros só para um lado e isso é muito mais complicado que usar ponteiros para os dois lados. É ilusão achar que ter só um ponteiro é mais fácil. Não é. Se seu exercício não exige um ponteiro só, use sempre  dois. 

 

De todo modo, entenda que
 

Citação

uma lista encadeada é uma coleção de registros chamados nós. E cada nó pode ter um dado. E os dados em geral tem um campo que é chamado chave, que é usado para ordenar ou localizar registros

 

Uma lista não é um nó, um nó não é uma lista. Um nó não tem nada a ver com os dados, pode apenas apontar para um. Um registro não é a chave, em geral. A chave não é o registro. Programas de exercício para iniciantes muitas vezes tem uma lista de inteiros, ou de letrinhas apenas, e os registros são colocados na ordem em que são inseridos, no fim ou no começo, mas em geral não é assim: sempre se espera os registros por ordem de chave.

 

A realidade dos seus dados:

 

Você quer um cadastro de clientes, representado em uma lista encadeada.

 

Seus dados:

 

typedef struct
{
    char              pessoa[50];
    char              cpf[15];
    int               idade;
    unsigned long int id;

} Cliente;

 

Isso é o seu registro de dado. Um cliente. Note que id é o preferido no planeta,

e como vai escrever isso toda hora é melhor um nome curto.

 

Um nó da sua lista:
 

um exemplo:

 

typedef struct st_node
{
    Cliente*         info;
    struct st_node*  ant;
    struct st_node*  prox;

}   Node;

 

Node precisa de um nome depois de struct porque tem esses ponteiros para Node dentro da estrutura.

Os dados e a lista não precisam e por isso podem ser estruturas anônimas. Compare.

 

Entenda que o nó não é uma lista. É só um link. Tem os ponteiros e aponta para UM único registro 

de dados. Percebe que se alterar de Cliente* para void* pode usar isso a vida toda? E 

mesmo que não use void* se no próximo programa for Livro ou Musica ou Espaconave a estrutura só

precisa mudar uma linha e as funções continuam funcionando?

 

Sua lista, qualquer lista:
 

typedef struct
{
    Node*    inicio;
    Node*    fim;
    unsigned size;
    unsigned limite;

} Lista;

 

Entenda que a lista começa por um nó, termina em um nó, tem um tamanho que no mundo inteiro tem esse nome,

e pode ter um limite apenas porque é bom se precaver...

 

unsigned faz com que você nunca precise se preocupar com um erro de lógica gerar um valor negativo e você não ver: o compilador garante.

 

E entenda que na Lista não tem nenhuma referência a Cliente

 

Compare com o que você escreveu: se revolver mudar Cliente para colocar o telefone por exemplo, vai ter que mudar as funções da Lista... Não programe assim.

 

E considere como pode ser usar várias listas no mesmo programa e pense em como faria isso no seu...

 

Nunca escreva um programa interativo. C nem é pra isso.

 

Use argumentos, gere dados, leia de arquivos. 

 

Quando o programa estiver pronto aí você coloca o infeliz do menu e as chamadas às funções, que já esarão todas terstadas a essa altura. Nunca misture desenvolvimento com essas coisas.

 

Considere seu programa com funções assim:
 

    int         inserir_cliente(Cliente* cl, Lista* l);
    int         remover_cliente(Cliente* cl, Lista* l);
    Lista*      cria_lista(unsigned limite);
    Lista*      apaga_lista(unsigned limite);
    int         mostra_lista(Lista* l);

 

Fica claro como testar isso. Inserir por exemplo um cliente é o simples: passa um cliente para a função que insere, junto com o que? O ponteiro para a lista. Sem menu, sem ficar parado em frente ao terminal inventado CPF e nome 3 vez para testar o programa que muitas vezes fecha na sua cara...

 

Um exemplo:

 

Se inserir retorna um erro quando estoura o limite, pode usar um loop e inserir clientes na lista com

nomes padrão tipo Cliente 001, CPF 123.456.001-56, id sequencial e idade igual ao id e ir testando o 

programa e as funções em minutos depois de começar o programa... 

 

O programa abaixo mostra isso
 

int main(void)
{ 
    Lista* teste = criar_lista(10); // limite
    Cliente um_cliente = {0}; // cliente zerado
    // agora insere clientes na lista, com id de 1 em diante e idade de 20 
    // em diante ate dar erro
    int id = 1;
    do {
        sprintf(um_cliente.pessoa, "Cliente %03d", id);
        sprintf(um_cliente.cpf, "123.456.%03d-56", id);
        um_cliente.idade = 20 + id;
        um_cliente.id    = id;
        id += 1;
        // cliente de teste pronto!
    } while (inserir_cliente(&um_cliente, teste) < 0);
}

 

Com 15 linhas já poderia estar testando. Use assim.

O teste, que pode compilar. Apenas com as funções em branco. Entenda a diferença de escrever assim:

 

Spoiler
#include <conio.h>
#include <ctype.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char              pessoa[50];
    char              cpf[15];
    int               idade;
    unsigned long int id;

} Cliente;

typedef struct st_node
{
    Cliente*        info;
    struct st_node* ant;
    struct st_node* prox;

} Node;

typedef struct
{
    Node*    inicio;
    Node*    fim;
    unsigned size;
    unsigned limite;

} Lista;

int         inserir_cliente(Cliente* cl, Lista* l);
int         remover_cliente(Cliente* cl, Lista* l);
Lista*      criar_lista(unsigned limite);
Lista*      apagar_lista(unsigned limite);
int         mostrar_lista(Lista* l);

int main(void)
{ 
    Lista* teste = criar_lista(10); // limite
    Cliente um_cliente = {0}; // cliente zerado
    // agora insere clientes na lista, com id de 1 em diante e idade de 20 
    // em diante ate dar erro
    int id = 1;
    do {
        sprintf(um_cliente.pessoa, "Cliente %03d", id);
        sprintf(um_cliente.cpf, "123.456.%03d-56", id);
        um_cliente.idade = 20 + id;
        um_cliente.id    = id;
        id += 1; // cliente de teste pronto!
    } while (inserir_cliente(&um_cliente, teste) < 0);
}

int    inserir_cliente(Cliente* cl, Lista* l) { return 0; };
int    remover_cliente(Cliente* cl, Lista* l) { return 0; };
Lista* criar_lista(unsigned limite) { return NULL; };
Lista* apagar_lista(unsigned limite) { return NULL; };
int    mostrar_lista(Lista* l){return 0; };

// fim

 

 

 

 

 

 

  • Obrigado 2
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...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!