Ir ao conteúdo

Posts recomendados

Postado

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");
}

 

Postado

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

Postado

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

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

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!