Ir ao conteúdo
  • Cadastre-se

C Listas em C que utilize estrutura de dados


Vagabond1001

Posts recomendados

1 minuto atrás, Rafael Melo disse:

Eu usei, porém ficava dando conflito.

Não aparecia nada na tela, mas quando tirei o loop, voltou a funcionar.

 

Pois é. Errou em tirar o loop. Provavelmente é aí que está o problema de seu programa. Se a rotina funcionar o loop vai funcionar.

 

Não pode haver um erro em um loop até encher a lista a menos que....

  • a rotina que insere não está ok
  • a rotina que diz que está cheio não está ok

A solução não deve ser tirar o loop... ;) 

 

O que é conflito? Que significa?

 

Poste o código como est;a agora e vou olhar ok?

 

 

Link para o comentário
Compartilhar em outros sites

4 minutos atrás, arfneto disse:

 

Pois é. Errou em tirar o loop. Provavelmente é aí que está o problema de seu programa. Se a rotina funcionar o loop vai funcionar.

 

Não pode haver um erro em um loop até encher a lista a menos que....

  • a rotina que insere não está ok
  • a rotina que diz que está cheio não está ok

A solução não deve ser tirar o loop... ;) 

 

O que é conflito? Que significa?

 

Poste o código como est;a agora e vou olhar ok?

 

 

//Dado a estrutura básica para a construção de uma lista estática, pede-se que seja criada uma função responsável por inserir um elemento no final da lista.
//Essa função precisará receber como parâmetro a lista (ponteiro) e o elemento a ser inserido.
//Dentro da função main, será necessário chamar a função para inserir elemento ao final e, logo em seguida, mostrar o resultado da função que recupera o tamanho da lista.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LISTAS 20


struct aluno {

    int matricula;
    char nome[100];
    float n1;
    float n2;
    float n3;
};
//typedef só declara um
typedef struct aluno Aluno;

struct lista {

    int qtde;
    Aluno alunos[LISTAS];
};

typedef struct lista Lista;

struct lista* cria_lista(){

    struct lista *li;
    li=(struct lista *)malloc(sizeof(struct lista));

    if(li != NULL)
        li->qtde = 0;

    return li;
};
int lista_vazia(struct lista *li)
{
    if(li != NULL)
        return (li->qtde ==0);
    else
        return -1;
};

int lista_cheia(struct lista *li)
{
  if(li !=NULL)
        return (li->qtde == LISTAS);
  else
        return -1;
};

int tamanho_lista(Lista *li)
{
  if(li != NULL)
        return li->qtde;
  else
        return -1;
  };
  
int fim_lista(struct lista *li, struct aluno *al){
    if (!lista_cheia(li)){
        li->alunos[li->qtde] = *al;
        li->qtde++;
        return -1;
    } else {
        return 0;
    }
}

int main()
{
    Lista* li;
    Aluno al;
    al = (Aluno){ .matricula = 65464, .nome = "Maria" };
    al = (Aluno){ .matricula = 65567, .nome = "Marcos" };
    al = (Aluno){ .matricula = 68865, .nome = "Renan" };
    al = (Aluno){ .matricula = 78890, .nome = "Filipe" };
    al = (Aluno){ .matricula = 78900, .nome = "Rafael" };
    al = (Aluno){ .matricula = 78900, .nome = "João" };
    li = cria_lista();
    fim_lista(li, &al);

    li = cria_lista();

    printf("\nLista vazia: %d ", lista_vazia(li));
    printf("\nLista cheia: %d ", lista_cheia(li));
    printf("\nTamanho da lista: %d ", tamanho_lista(li));
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

0 é igual a falso, e qualquer valor diferente de 0 é verdadeiro.

 

Se a Lista Vazia e Cheia estão ambos retornando 0 significa que a lista não está vazia nem está cheia. Note que para estar vazia não deve ter nenhum elemento, e para estar cheia precisa ter MAX=100 elementos inseridos.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

3 minutos atrás, isrnick disse:

0 é igual a falso, e qualquer valor diferente de 0 é verdadeiro.

 

Se a Lista Vazia e Cheia estão ambos retornando 0 significa que a lista não está vazia nem está cheia. Note que para estar vazia não deve ter nenhum elemento, e para estar cheia precisa ter MAX=100 elementos inseridos.

 

E no seu programa você colocou a função para inserir no começo da lista, mas deveria ser para inserir no fim da lista.

Mas o retorno esta em LISTAS que eu defini em 20, agora buguei kkk

Pode apontar no codigo o valor a ser alterado?

Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

E sobre essa linha:


    li->a[li->qtde] = *al;

Isso não funciona.

 

Funciona sim. Não há necessidade de usar memcpy() para copiar o valores de apenas 1 struct. A struct já é entendida como uma variável e pode ser atribuída diretamente e será copiados todos os bits contidos na struct.

adicionado 1 minuto depois
10 minutos atrás, Rafael Melo disse:

Mas o retorno esta em LISTAS que eu defini em 20, agora buguei kkk

Pode apontar no codigo o valor a ser alterado?

 

Ignore minha mensagem, eu só tinha visto o seu post na primeira página do tópico, não tinha visto que tinha uma segunda página e que você já tinha alterado o código, no caso do seu último post seria 20 mesmo...

Link para o comentário
Compartilhar em outros sites

3 minutos atrás, isrnick disse:

 

Funciona sim. Não há necessidade de usar memcpy() para copiar o valores de apenas 1 struct. A struct já é entendida como uma variável e pode ser atribuída diretamente e será copiados todos os bits contidos na struct.

adicionado 1 minuto depois

 

Ignore minha mensagem, eu só tinha visto o seu post na primeira página do tópico, não tinha visto que tinha uma segunda página e que você já tinha alterado o código, no caso do seu último post seria 20 mesmo...

Pois é, e mesmo assim sempre imprime os mesmos valores:

 

Lista Vazia: 1

Lista cheia: 0

Tamanho da lista: 0

 

Nunca altera isso

 

Link para o comentário
Compartilhar em outros sites

1 minuto atrás, isrnick disse:

Tem dois li=cria_lista() no seu main exclua o segundo.

Meu Deus nem tinha visto kkkk

Agora ficou assim:

Lista Vazia: 0

Lista Cheia: 0

Tamanho da Lista: 1

 

Ainda assim não apresenta os resultados

adicionado 1 minuto depois
4 minutos atrás, isrnick disse:

Tem dois li=cria_lista() no seu main exclua o segundo.

Veja como esta o codigo:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LISTAS 5


struct aluno {

    int matricula;
    char nome[100];
    float n1;
    float n2;
    float n3;
};
//typedef só declara um
typedef struct aluno Aluno;

struct lista {

    int qtde;
    Aluno alunos[LISTAS];
};

typedef struct lista Lista;

struct lista* cria_lista(){

    struct lista *li;
    li=(struct lista *)malloc(sizeof(struct lista));

    if(li != NULL)
        li->qtde = 0;

    return li;
};
int lista_vazia(struct lista *li)
{
    if(li != NULL)
        return (li->qtde ==0);
    else
        return -1;
};

int lista_cheia(struct lista *li)
{
  if(li !=NULL)
        return (li->qtde == LISTAS);
  else
        return -1;
};

int tamanho_lista(Lista *li)
{
  if(li != NULL)
        return li->qtde;
  else
        return -1;
  };
  
int fim_lista(struct lista *li, struct aluno *al){
    if (!lista_cheia(li)){
        li->alunos[li->qtde] = *al;
        li->qtde++;
        return -1;
    } else {
        return 0;
    }
}

int main()
{
    Lista* li;
    Aluno al;
    al = (Aluno){ .matricula = 65464, .nome = "Maria" };
    al = (Aluno){ .matricula = 65567, .nome = "Marcos" };
    al = (Aluno){ .matricula = 68865, .nome = "Renan" };
    al = (Aluno){ .matricula = 78890, .nome = "Filipe" };
    al = (Aluno){ .matricula = 78900, .nome = "Rafael" };
    al = (Aluno){ .matricula = 78900, .nome = "João" };
    
    li = cria_lista();
    fim_lista(li, &al);


    printf("\nLista vazia: %d ", lista_vazia(li));
    printf("\nLista cheia: %d ", lista_cheia(li));
    printf("\nTamanho da lista: %d ", tamanho_lista(li));
}

 

Link para o comentário
Compartilhar em outros sites

9 minutos atrás, Rafael Melo disse:

Agora ficou assim:

Lista Vazia: 0

Lista Cheia: 0

Tamanho da Lista: 1

 

Ainda assim não apresenta os resultados

 

Representa exatamente o que o seu código fez, ou seja só incluiu 1 aluno na lista.

 

Para fazer o que você está pensando teria que chamar fim_lista(li, &al) toda vez após cada aluno criado.

 

Ou seja o main ficaria assim:

int main()
{
    Lista* li;
    Aluno al;
  
    li = cria_lista();
  
    al = (Aluno){ .matricula = 65464, .nome = "Maria" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 65567, .nome = "Marcos" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 68865, .nome = "Renan" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78890, .nome = "Filipe" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78900, .nome = "Rafael" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78900, .nome = "João" };
    fim_lista(li, &al);

    printf("\nLista vazia: %d ", lista_vazia(li));
    printf("\nLista cheia: %d ", lista_cheia(li));
    printf("\nTamanho da lista: %d ", tamanho_lista(li));
}

Note que eu tive que mover li=cria_lista) para o topo.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

9 minutos atrás, isrnick disse:

 

Representa exatamente o que o seu código fez, ou seja só incluiu 1 aluno na lista.

 

Para fazer o que você está pensando teria que chamar fim_lista(li, &al) toda vez após cada aluno criado.

 

Ou seja o main ficaria assim:


int main()
{
    Lista* li;
    Aluno al;
  
    li = cria_lista();
  
    al = (Aluno){ .matricula = 65464, .nome = "Maria" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 65567, .nome = "Marcos" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 68865, .nome = "Renan" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78890, .nome = "Filipe" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78900, .nome = "Rafael" };
    fim_lista(li, &al);

    al = (Aluno){ .matricula = 78900, .nome = "João" };
    fim_lista(li, &al);

    printf("\nLista vazia: %d ", lista_vazia(li));
    printf("\nLista cheia: %d ", lista_cheia(li));
    printf("\nTamanho da lista: %d ", tamanho_lista(li));
}

Note que eu tive que mover li=cria_lista) para o topo.

Amigo perfeito, era exatamente isso.

Estava embanando tudo nesse int main

Obrigado!

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Muito bem.

 

 

Depois do café, vamos ao seu programa. O maior problema acho que é sua noção de verdadeiro/falso:

Citação

em C zero é falso. Qualquer outra coisa é verdadeiro (inclusive -1) :) 

 

Você não devia ter tirado o loop. Como eu te disse, ele era o seu juiz.

 

lista_cheia()

int lista_cheia(struct lista *li)
{
  if(li !=NULL)
        return (li->qtde == LISTAS);
  else
        return -1;
};

Uma lista não iniciada não pode estar cheia, então lista_cheia(NULL) deveria retornar zero e não -1. Algo assim bem mais simples já serviria:

int lista_cheia(Lista* li)
{
    if (li != NULL) return (li->qtde == LISTAS);
    return 0;
};

Como lista_cheia() está errada o loop não terminaria :D 
 

lista_vazia()

int lista_vazia(struct lista *li)
{
    if(li != NULL)
        return (li->qtde ==0);
    else
        return -1;
};

uma lista que não foi iniciada pode ser considerada vazia e (-1) é verdadeiro. Mas não precisa de um else para um return. Só dificulta a leitura

Algo assim seria mais simples:

int lista_vazia(Lista* li)
{
    if (li == NULL) return 1;
    return (li->qtde == 0);
};

fim_lista()

int fim_lista(struct lista *li, struct aluno *al){
    if (!lista_cheia(li)){
        li->alunos[li->qtde] = *al;
        li->qtde++;
        return -1;
    } else {
        return 0;
    }
}

A condição final é definitiva então podia escrever antes. E a noção de inserir também é em geral de inserir o aluno na lista então podia ter escrito algo mais simples:

int insere_no_fim(Aluno* al, Lista* li)
{
    if (lista_cheia(li)) return 0;
    Aluno* um = & li->alunos[li->qtde];
    *um = *al;
    li->qtde += 1;
    return -1;
};

Ou algo parecido.

 

Há tantas maneiras de escrever um programa quanto autores, mas há uma certa convergência depois de algum tempo :) 

 

Abaixo está o seu código considerando essas sugestões. Estou postando porque sei que está trabalhando nisso e está quase lá

 

Não tem nada de especial no que eu escrevi, mas entenda que a medida em que seus programas passarem a ter dezenas e dezenas de funções vai agrupar em vários arquivos e ter no início os tais arquivos .h que declaram as funções como eu fiz aqui. Em ordem alfabética ajuda para quem não conhece seu código ou você mesmo em seis meses. main() deve ser a primeira função em especial se espera a ajuda de alguém e não quer forçar o cara a ficar procurando a função no meio de 500 linhas de código para começar a entender como funciona o seu programa...

 

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LISTAS 4


struct aluno
{
    int matricula;
    char nome[100];
    float n1;
    float n2;
    float n3;
};
typedef struct aluno Aluno;

struct lista
{
    int   qtde;
    Aluno alunos[LISTAS];
};
typedef struct lista Lista;

Lista*  cria_lista();
int     insere_no_fim(Aluno*, Lista*);
int     lista_vazia(Lista*);
int     lista_cheia(Lista*);
int     tamanho_lista(Lista*);

int main()
{
    int n = 0;
    Lista* li = cria_lista();
    printf("\nNo inicio: Lista Vazia?: %d (apenas 0 e falso)", lista_vazia(li));
    printf("\nNo inicio: Lista Cheia?: %d (apenas 0 e falso)", lista_cheia(li));
    printf("\nNo inicio: Tamanho da lista: %d ", tamanho_lista(li));

    int matricula = 65464;
    Aluno al = (Aluno){ .matricula = matricula, .nome = "Maria Silva" };
    do
    {  
        n = insere_no_fim( &al, li);
        al.matricula += 1;
    } while (!lista_cheia(li));

    printf("\nNo final: Lista Vazia?: %d (apenas 0 e falso)", lista_vazia(li));
    printf("\nNo final: Lista Cheia?: %d (apenas 0 e falso)", lista_cheia(li));
    printf("\nNo final: Tamanho da lista: %d ", tamanho_lista(li));
}

Lista* cria_lista()
{
    Lista* li = (Lista*)malloc(sizeof(struct lista));
    if (li != NULL) li->qtde = 0;
    return li;
};

int insere_no_fim(Aluno* al, Lista* li)
{
    if (lista_cheia(li)) return 0;
    Aluno* um = & li->alunos[li->qtde];
    *um = *al;
    li->qtde += 1;
    return -1;
};

int lista_cheia(Lista* li)
{
    if (li != NULL) return (li->qtde == LISTAS);
    return 0;
};

int lista_vazia(Lista* li)
{
    if (li == NULL) return 1;
    return (li->qtde == 0);
};

int tamanho_lista(Lista* li)
{
    if (li != NULL) return li->qtde;
    return -1;
};

 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

int lista_cheia(Lista* li)
{
	if (li != NULL) return (li->qtde == LISTAS);
	return 0;
};

 

Uma lista que não existe não é vazia, para está cheia tem que existir. Digo isso porque nos casos em que li é null a resposta também é 0, ou seja, conflitantemente diz que existe li e que é tem espaço.

 

 

Link para o comentário
Compartilhar em outros sites

5 minutos atrás, Mauro Britivaldo disse:

Uma lista que não existe não é vazia, para está vazia tem que existir. Digo isso porque nos casos em que li é null a resposta também é 0, ou seja, conflitantemente diz que existe li e que é vazia

 

Mauro, a programação não é filosófica. Trata-se nesse particular apenas de minimizar problemas e um pouco de álgebra. Algebra de Boole. A gente quer que lista_vazia() retorne verdadeiro ou falso. 

 

Do ponto de vista do programa me parece mais esperto retornar verdadeiro para lista_vazia(NULL). Na prática pode não valer a pena cancelar o programa por causa disso. E ao retornar do modo filosófico false para lista_vazia(NULL) vai fazer com que o infeliz que chamou faça coisas terrenas como partir para ler valores da lista, já que não está vazia.

 

Acha mesmo melhor? 

 

Não deveria ser chamada lista_vazia() com um NULL, mas se foi é melhor como estou dizendo. Ou claro, como você está dizendo claro.

Link para o comentário
Compartilhar em outros sites

@Mauro Britivaldo  Você indicou o trecho errado de código, queria dizer esse:

int lista_vazia(Lista* li)
{
    if (li == NULL) return -1;
    return (li->qtde == 0);
};

E quando li == NULL tem que retornar que está vazia, do contrário seria pior retornaria que ela existe e não está vazia, ou seja tem items inseridos.

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Mauro Britivaldo disse:

Exato, editei porque serve para as duas. No meu entender temos dois estados diferentes com a mesma sinalização.

 

A função não está perguntando "A lista foi criada?".

 

A pergunta "A lista está vazia?" só pode ser respondida com sim ou não, verdadeiro ou falso. Não dá para retornar 3 estados lógicos diferentes, só existe true e false. Então só dá para considerar que a li==NULL é vazia.

 

Do contrário deveria considerar um erro e assumir que a lista existe quando a função foi chamada e nem examinar o caso do NULL:

int lista_vazia(Lista* li)
{
    return (li->qtde == 0);
}

 

Mas ainda considero o caso de li==NULL é vazio descreve melhor, mas aí vira questão conceitual/interpretativa e depende de preferência de quem está programando.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

4 horas atrás, isrnick disse:

li==NULL é vazio

Esse é um estado arbitrário; trato radicalmente encerro o programa com notificação ao programador, pois a função não pode receber o ponteiro nulo e trato o fato profissionalmente na documentação. Entretanto, não precisa ser assim.

 

Neste caso uma mensagem de erro interno já é suficiente, pois li é null somente se algo não está certo.

 

 

 

adicionado 5 minutos depois
4 horas atrás, arfneto disse:

Mauro, a programação não é filosófica. Trata-se nesse particular apenas de minimizar problemas e um pouco de álgebra. Algebra de Boole. A gente quer que lista_vazia() retorne verdadeiro ou falso. 

 

Continua errado.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

21 minutos atrás, Mauro Britivaldo disse:

Continua errado

 

Você entendeu o argumento. O autor do tópico até tentou ir por um terceiro caminho retornando -1 que é uma solução em muitas rotinas de biblioteca, mas essas rotinas não tem a clara intenção de retornar verdadeiro/falso. @isrnick te deu um bom argumento também.

 

Encerrar o programa e "tratar profissionalmente" o problema pode ser uma postura arrogante e já te expliquei porque: quem chama sua rotina pode ver como inofensivo a lista estar "vazia" fora da sua concepção ternária: existe vazia/existe não vazia/ não existe para uma situação de dois estados apenas. E se você retornar falso para lista_vazia(NULL) porque a sua concepção de universo não abrange tal liberalidade, o infeliz que vai abrir uma rotina que grava todas as transações da lista no banco de dados vai sim cancelar um série de processos porque o ponteiro que ele recebeu era NULL e não havia nada a transmitir. E ninguém vai ser gentil quando você começar a explicar que a documentação claramente abrange os fatos necessários e tal e tal e tal...

 

Me lembra de sua discussão de tempos atrás sobre o que era um arquivo csv. Muito válida e filosófica até alguém te pagar para ler um ou escrever um. Não te pagar, na verdade. 

 

E pode não ser sua atribuição decidir isso. Abortar um programa a partir de uma rotina auxiliar por algo que você deixou claro na documentação não vai durar um dia e você vai ter que se entender com alguém. Mas você não trabalha para mim nem é meu aluno, claro. E respeito sua posição, apesar de achar folclórica.

 

Link para o comentário
Compartilhar em outros sites

Está defendendo um erro, mas o problema não é meu. Se eu, um aluno apresento essa função e essa justificativa é 0 na hora.

 

Eu não sou o professor. Só apresentei meu ponto e se fosse além do 0 perde ponto por plagiar e erradamente.

 
37 minutos atrás, arfneto disse:

retornando -1 que é uma solução em muitas rotinas de biblioteca

Pra ser tratado externamente, estava por um caminho certo, e não é à toa.

 
37 minutos atrás, arfneto disse:

não trabalha para mim nem é meu aluno

Meus professores não eram programadores de profissão, eram da ciência doutores em física e outro em química. Agradeço a Deus por saber que são melhores que muitos dá área.

Link para o comentário
Compartilhar em outros sites

agora, isrnick disse:

@Mauro Britivaldo De qualquer maneira nesse caso não é responsabilidade do aluno, essas funções de checagem já foram fornecidas (presumidamente pelo professor) e a única coisa que é pedido para o aluno fazer é a função para inserir no fim da lista.

Isso é novo.

adicionado 0 minutos depois

Para mim. O que pensei é que tudo fosse de autoria do grupo.

Link para o comentário
Compartilhar em outros sites

Em 26/04/2020 às 20:19, Rafael Melo disse:

 


int lista_vazia(struct lista *li)
{
  ifif(li != NULL){
    return (li->qtde == 0);
  } else{
    return -1;
  }
}

 

Está é a original do autor? Esse professor que fez essa função estudou comigo Observação com relação a estado -1 que gera a exceção. Está corretíssimo,

 

Ainda pode ficar um pouco mais elegante. Contudo, essa é a correta de sempre.

 

 

Link para o comentário
Compartilhar em outros sites

Que ridículo, não pode ser dessa maneira.

 

Isso pode gerar erros fatais. Mais fatais que finalizar o programa na careta dos tapados.

 

Enfim, vou concorda em discordar e fica a critério desse professor coitado que só deseja uma função de tudo isso.

 

Acredito que fez as pressas e deixou os detalhes por menores.

 
12 minutos atrás, isrnick disse:

para ser usada em um if desse tipo

Jamais, prefiro corre no asfalto descalço no verão que comenter outras burrices consiente.

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

 

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

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!