Ir ao conteúdo

C lista estática criar uma função


Ir à solução Resolvido por isrnick,

Posts recomendados

Postado

Preciso  criar 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, é 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. Alguém pode me ajudar.

#include <stdlib.h>
#include <stdio.h>
#define TAMANHOLISTA 100


struct aluno {

    int matricula;
    char nome[100];
    float n1, n2,n3;
};

struct lista {

    int qtde;
    struct aluno lAlunos[TAMANHOLISTA];
};

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 == TAMANHOLISTA);
  else
        return -1;
};

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

void main()
{
    struct lista *li;

    li = cria_lista();

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

( Segue o código)

 

Postado

 

struct lista
{
    int qtde;
    struct aluno lAlunos[TAMANHOLISTA];
};

Sua estrutura de lista tem um problema, digamos, estrutural...

 

Sua lista termina em si mesma já que não há um ponteiro para o próximo elemento, ou para o anterior, ou para qualquer coisa.

Só um int, qtde e uma outra estrutura...

 

Pense nisso: Se isso fosse um elemento de usa lista a quantidade não seria sempre um? Se tem 20 na lista ao mudar a quantidade iria alterar todos? Como iria encontrá-los?

 

Como percorrer uma lista assim?

 

Compare com o exemplo abaixo, de uma implementação comum:


struct no
{
    void*      item;
    struct no* proxima;
    struct no* anterior;
};  // no
typedef struct no Node;

struct a_propria_lista
{
    char*     nome;
    unsigned  quantos;
    unsigned  maximo;
    Node*     inicio;
    Node*     fim;
};
typedef struct a_propria_lista Lista;

Tem dois elementos aqui: Node e Lista. A lista dá pra imaginar é uma lista de Node

 

A lista

  • tem um nome
  • uma quantidade
  • um limite
  • um ponteiro para o inicio
  • um ponteiro para o fim

O tal Node, o nó

  • tem um ponteiro para algum conteúdo
  • tem um ponteiro para o próximo nó
  • tem um ponteiro para o nó anterior

E a conta fecha:

  • Se você não precisa apontar para o anterior, não usa
  • Se você não precisa apontar para o próximo não usa
  • Se não precisa dar um nome, por exemplo porque só vai ter uma lista no seu programa, não usa o nome
  • Se não tem um limite não precisa do tal maximo
  • item é um ponteiro e você pode apontar cada um para um Aluno, no seu caso

Pense nisso.

 

  • Curtir 1
  • Amei 1
Postado

Uma estruturação simples poderia ser feita assim:

#include <stdio.h>
#include <stdlib.h>

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

typedef struct no {
    Aluno *aluno;
    struct no *proximo;
} No;

typedef struct lista {
    int quantidade;
    No *primeiro;
} Lista;

Lista *criarLista();

void adicionar(Lista *lista, Aluno *aluno);

void listar(Lista *lista);

int main() {
    Lista *lista = criarLista();
    
    // ----- Poupa tempo
    Aluno aluno1= (Aluno) {1, "A", 1.0, 1.0, 1.0};
    Aluno aluno2= (Aluno) {2, "B", 2.0, 2.0, 2.0};
    Aluno aluno3= (Aluno) {3, "C", 3.0, 3.0, 3.0};
    // ----- Poupa tempo
    
    adicionar(lista, &aluno1);
    adicionar(lista, &aluno2);
    adicionar(lista, &aluno3);

    listar(lista);
    return EXIT_SUCCESS;
}

Obs.: A implementação das funções fica por sua conta. 😉

  • Confuso 1
Postado

A função seria algo assim:

#include <string.h>
  
/*...*/

int insere_no_fim_da_lista(struct lista *li, int matricula, char *nome){
    if (!lista_cheia(li)){
        li->lAlunos[li->qtde].matricula = matricula;
        strcpy(li->lAlunos[li->qtde].nome, nome);
        /*
        li->lAlunos[li->qtde].n1 = -1.0;
        li->lAlunos[li->qtde].n2 = -1.0;
        li->lAlunos[li->qtde].n3 = -1.0;
        */
        li->qtde++;
        return -1;
    } else {
        return 0;
    }
}

E usaria assim:

insere_no_fim_da_lista(li, 53563, "Joao Santos");

 

Note que eu não incluí as notas do aluno na inserção do aluno.

 

Se for para criar o aluno e colocar as notas ao mesmo tempo, tem que adicionar as variáveis ao protótipo da função e implementar dentro, mas eu imaginei que seria melhor colocar as notas separadamente.

 

Opcionalmente também coloquei no trecho comentado as notas com valor negativo que poderiam servir para indicar que ainda não recebeu o valor da respectiva nota.

  • Curtir 1
  • Membro VIP
Postado

@arfneto e @AdrianoSiqueira, o exercício é para uma lista estática...

 

Provavelmente a lista foi entregue pronta... daí faltando implementar o que foi solicitado.

 

adicionado 4 minutos depois

@isrnick, não daria simplesmente para passar o aluno por parâmetro? em C não sei exatamente como faria... mas creio que faria mais sentido passar todo o objeto.

 

Sobre:

1 hora atrás, isrnick disse:

        /*
        li->lAlunos[li->qtde].n1 = -1.0;
        li->lAlunos[li->qtde].n2 = -1.0;
        li->lAlunos[li->qtde].n3 = -1.0;
        */

 

Essas atribuições não faria sentido ficar dentro da função... pois o objetivo dela seria simplesmente adicionar à fila.

adicionado 7 minutos depois

Algo assim:

nsere_no_fim_da_lista(listaAlunos, novoAluno);

 

  • Curtir 1
Postado
Em 26/04/2020 às 17:12, Rafael LXP disse:

Preciso  criar 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, é 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. Alguém pode me ajudar

 

Parecem estar todos de acordo que uma lista estática é apenas um array de struct e um contador que passa a ser chamado de ponteiro. E assim inserir no fim da lista é simplesmente somar um ao total e copiar o conteúdo da struct para lá.

 

A estrutura dos dados

 

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

struct lista
{
    int qtde;
    struct aluno lAlunos[TAMANHOLISTA];
};

é uma lista? Ou apenas um array de structs e um contador de capacidade.

 

Mas qual o propósito de chamar isso de lista estática e não de um vetor de struct ou um array de structs aluno afinal?

 

Eu já implementei listas estáticas para um bom número de situações, mas não me lembro da última vez que fiz isso em um exercício de programação. E o conceito de eu conheci sempre foi de que "lista estática" era uma lista ligada estática,

 

Vou tentar explicar melhor

 

Uma lista ligada estática é --- ou é em alguns casos --- um tipo de lista ligada em que a gente aloca uma quantia fixa de memória, como aqui. Mas é uma lista ligada e não um simples e óbvio array. Sério que para inserir em um array e aumentar um contador alguém ia criar um exercício e pedir uma função? Qual a utilidade disso?

 

Ainda explicando:
 

Numa lista ligada convencional a memória é alocada a cada nó. Mostrei uma declaração disso aqui acima. Algo assim

struct no
{
    void*      item;
    struct no* proxima;
    struct no* anterior;
};  // no
typedef struct no Node;

struct a_propria_lista
{
    char*     nome;
    unsigned  quantos;
    unsigned  maximo;
    Node*     inicio;
    Node*     fim;
};
typedef struct a_propria_lista Lista;

Cada Node tem um ponteiro para os dados e um ponteiro para frente e outro para trás. Os tais Links da Linked List.

Numa lista ligada estática seria algo assim

struct no
{
    Item       item;
    int        proxima;
    int        anterior;
};  // no
typedef struct no Node;

struct a_propria_lista
{
    char*     nome;
    unsigned  quantos;
    unsigned  maximo;
    Node*     dados;
};
typedef struct a_propria_lista Lista;

Qual a diferença afinal?

 

Numa lista estática você aloca a lista toda uma única vez quando cria. Por isso era dita estática. Na verdade em geral não se aloca assim estaticamente porque há limites pequenos do que se pode alocar no stack, e em geral isso é alocado no heap, via alocação dinâmica mas uma única na criação da lista. Se não entende essa diferença não se importe. Não tem a ver com esse problema a menos que use um número muito grande de itens e o compilador vai te dizer que excedeu...

 

Repare que os Nodes tem apontadores do tipo int que são os índices do array que é a lista. Os links da static linked list são índices de um array. Fora isso funciona igual.

 

E porque a gente usaria isso?

  • Performance: é muito muito mais rápido que alocar um por um.
  • Fragmentação de memória, que acaba em redução de performance se o programa roda por horas ou dias.

E qual a diferença para a lista ligada comum?

  

Não tem os atrasos associados a alocação de memória. Então você pode criar coisas como 5.000 buffers de transmissão e deixar no jeito para atender a consultas. E assim que vem um pedido você já despacha um endereço, que é só um índice no vetor. Não precisa alocar memória, seguir ponteiros e tal.

 

E qual a diferença em relação ao que está escrito aqui?

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

struct lista
{
    int qtde;
    struct aluno lAlunos[TAMANHOLISTA];
};

Simples: isso aqui é só um array. Então você só coloca os caras lá. O mais importante: não pode apagar sem mover todo mundo. Não pode reaproveitar. Não faz sentido dar um outro nome para um simples array. Ou hoje em dia faz :D 

 

Mas desse jeito é inútil: só um array com outro nome. No entanto uma lista ligada estática, como eu expliquei, é super útil: tem as mesmas funções de uma lista ligada comum mas é dezenas de vezes mais rápida. A limitação é que usa sempre uma quantia fixa de memória, como 100 conexões a bancos de dados prontinhas para uso, 3000 buffers de comunicação, coisas assim. É muito rápido. Muito mais rápido que a linked list convencional. E estática.

 

Onde está descrito esse conceito de lista estática que não é um array? Você tem um livro-texto? Uma apostila? Alguma descrição mais elaborada?

 

Até onde eu sei e como eu expliquei, static linked lists são listas ligadas indexadas por um índice num vetor alocado na criação e não por ponteiros. Só isso. E expliquei para que servem.

 

  • Solução
Postado
41 minutos atrás, Simon Viegas disse:

@isrnick, não daria simplesmente para passar o aluno por parâmetro? em C não sei exatamente como faria... mas creio que faria mais sentido passar todo o objeto.

 

Dá sim, o @AdrianoSiqueira até fez um exemplo no programa dele:

 

Em 26/04/2020 às 18:56, AdrianoSiqueira disse:

// ----- Poupa tempo
    Aluno aluno1= (Aluno) {1, "A", 1.0, 1.0, 1.0};
    Aluno aluno2= (Aluno) {2, "B", 2.0, 2.0, 2.0};
    Aluno aluno3= (Aluno) {3, "C", 3.0, 3.0, 3.0}; 
// ----- Poupa tempo

 

 

Minha função alterada ficaria assim:

#include <string.h>
  
/*...*/

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

E chamaria a função assim:

    struct aluno al;
    al.matricula = 53563;
    strcpy(al.nome, "Joao Santos");

    insere_no_fim_da_lista(li, &al);
    
    //Ou Assim:
    al = (struct aluno){.matricula=65464, .nome="Maria Silva"};

    insere_no_fim_da_lista(li, &al);
    
    //Ou Então assim:
    insere_no_fim_da_lista(li, &(struct aluno){.matricula=15436, .nome="Jose Souza"});

 

adicionado 32 minutos depois

@arfneto O conceito de lista é genérico, não há regra de como deve ser implementado, é possível fazer uma lista com todas as funcionalidades conceituais da estrutura de dados usando um vetor comum, claro essa implementação ficaria longe do ideal com sérios impactos de desempenho quando forem feitas inserções ou remoções que não esteja no fim da lista, devido a necessidade de copiar vários nós da lista toda vez que isso acontecer, mas ainda assim atenderia a definição de uma lista.

 

Mas concordo que se o intuito era introduzir a estrutura de dados Lista seria melhor utilizar um código adequado para não confundir o aluno. E se esse é o caso o professor cometeu uma grave falha.

 

Entretanto a lista neste exercício me parece apenas se referir ao termo lista de chamada relacionada a uma classe de aula, e é mais um exercício de linguagem de programação do que de estrutura de dados. E embora essa lista de chamada pudesse ser melhor modelada utilizando a estrutura de dados lista, um vetor é adequado suficiente visto a pequena quantidade de alunos, e não há requisitos fortes de inserção intermediária ou remoção de alunos frequentes, de fato isso aconteceria só excepcionalmente.

Postado
1 minuto atrás, Rafael LXP disse:

E para mostrar o resultado da função que recupera o tamanho da lista???

 

Não precisa fazer nada já está no seu código original:

 

Em 26/04/2020 às 17:12, Rafael LXP disse:

printf("\nTamanho da lista? %d ", recupera_tamanho_lista(li));

 

Postado
struct aluno al; al.matricula = 53563; strcpy(al.nome, "Joao Santos"); insere_no_fim_da_lista(li, &al);

Então já esta inserindo ao fina da lista! coloquei pra executar aqui 

 

Antes o resultado era:l

lista vazia: 1
lista cheia:0
tamanho da lista:0

 

Depois de implementar a funçao o resultado é:

lista vazia: 0
lista cheia:0
tamanho da lista:1

 

Então quer dizer que o elemento foi inserido ao final da lista??

Postado
2 horas atrás, isrnick disse:

Entretanto a lista neste exercício me parece apenas se referir ao termo lista de chamada relacionada a uma classe de aula, e é mais um exercício de linguagem de programação do que de estrutura de dados. E embora essa lista de chamada pudesse ser melhor modelada utilizando a estrutura de dados lista, um vetor é adequado suficiente visto a pequena quantidade de alunos, e não há requisitos fortes de inserção intermediária ou remoção de alunos frequentes, de fato isso aconteceria só excepcionalmente

 

Claro que você percebeu que isso é só um vetor de struct, a tal struct Aluno e com um contador? E inserir no final é só somar um.
 

Por mais liberal que seja a definição de "lista estática" como escreveu o autor no tópico não poderia ser a mesma que um vetor e um contador. E para piorar existe a tal lista estática mesmo, como eu expliquei. E é muito útil porque é MUITO rápida.

 

Veja que o enunciado fala em uma função que recupera o tamanho da lista. Sério que precisa de uma função só para escrever na tela o valor de um contador? 

 

Tem algo errado. Por isso perguntei se tinha um livro ou apostila ou algo...
 

3 horas atrás, isrnick disse:

não há regra de como deve ser implementado, é possível fazer uma lista com todas as funcionalidades conceituais da estrutura de dados usando um vetor comum, claro essa implementação ficaria longe do ideal com sérios impactos de desempenho quando forem feitas inserções ou remoções que não esteja no fim da lista, devido a necessidade de copiar vários nós da lista toda vez que isso acontecer, mas ainda assim atenderia a definição de uma lista

 

Não. Pelo contrário. Não há "sério impacto de desempenho". É muito mais rápido que a lista convencional e por isso a gente implementa quando a velocidade é fundamental. Talvez não tenha lido o que eu expliquei: numa "lista ligada estática" os links entre os nós são os índices do vetor. Quando você remove apenas marca o slot como disponível. Sem overhead. Quando vai inserir começa a busca por um slot livre logo depois do último usado. Este pode não estar mais livre se seu programa está rodando há dias por exemplo.
Localizar o próximo slot livre é trivial porque os nós da lista tem um indicador de disponibilidade. Não há overhead de chamada de função, de alocar memória, nada. 
Quando cada fração de segundo é importante se mantem até uma lista auxiliar de slots livres: um array de índices alimentado pelas próprias funções que apagam valores: ao apagar você insere no array de espaço livre, uma espécie de GC --- garbage collector --- e assim pode reusar os de lá como índices antes de sequer pesquisar o vetor. Os sistemas operacionais fazem isso com a memória alocada pelo processos e liberada via free() ou delete ou delete[] em C ou C++ por exemplo.

 

Só que você usa sempre memória suficiente para conter a lista toda. Fora isso é a mesma estrutura de dados. Só que muito mais rápida. 

 

E é um pouco mais caro de implementar porque não pode ser totalmente genérica, já que o ganho de performance vem do fato dela ser estática e então os dados de cada nó contem os próprios dados e não ponteiros.

 

Exemplo de uma estrutura assim que funciona:

struct no
{
    Aluno      aluno;
    int        anterior;
    int        proxima;
    char       status;
};  // no
typedef struct no Node;

struct a_propria_lista
{
    Node*     dados;
    int       fim;
    int       inicio;
    char*     nome;
    unsigned  quantos;
    unsigned  maximo;
};
typedef struct a_propria_lista Lista;

É uma lista ligada dupla, estática. Note que ao invés de um void* apontando para os dados você usa diretamente uma estrutura estática. Até coloquei a desse exemplo: Aluno.

 

E na criação da lista você aloca a lista toda, uma única vez. Quando o sistema entra está tudo certinho. A lista está cheia. De slots vazios.

 

Exemplo de como criar uma lista ligada estática

Lista* criar_lista(const char* nome, int N)
{
    Lista* nova = (Lista*)malloc(sizeof(Lista));
    nova->nome = (char*)malloc(1 + strlen(nome));
    strcpy(nova->nome, nome);
    nova->quantos = 0;
    nova->maximo = N;
    nova->dados = (Node*)malloc(N * sizeof(Node));
    nova->inicio = -1;
    nova->fim = -1;
    for (int i = 0; i < N; i = i + 1)
        nova->dados[i].status = 0; // 0 = livre
    printf(
        "Criada lista \"%s\" com %d alunos\n",
        nova->nome, nova->maximo);
    return nova;
};  // criar()

Para criar usaria algo assim

    Lista* lista1 = criar_lista("Lista 001", 500);

E se inserir estivesse declarado assim

int     inserir_no_final(Aluno*, Lista*);

retornando o índice ou (-1) em caso de erro

 

E se listar() estivesse declarado assim

int     listar(Lista*);

E se existisse uma função fábrica() --- data factory --- declarada assim

    Aluno* fabrica()

E que devolvesse um aluno a cada vez que você chama, com nome, matrícula e notas, um programa assim

int main(int argc, char** argv)
{
	int n = 0;
	Lista* lista1 = criar_lista("Lista 001", 30);
	listar(lista1);
	do
	{	// enche a lista
		Aluno* a = fabrica();
		n = inserir_no_final(a, lista1);
		free(a);
	} while (n >= 0); // nao conseguiu mais inserir
	listar(lista1);
	if (cheia(lista1))
	{
		printf("\"%s\" cheia: %d elementos\n",
			lista1->nome, lista1->quantos);
	}
	else
	{
		printf("\"%s\" nao cheia: %d elementos\n",
			lista1->nome, lista1->quantos);
	};	// if()
	return 0;
}

Mostra


Lista 'Lista 001' com 0 de 12 elementos MAX

Lista 'Lista 001' com 12 de 12 elementos MAX

    Primeiro: 10000
      Ultimo: 10011

Alunos

10000 Jhonny Cash 10000 Notas 41.67 34.00 69.24
10001 Jhonny Cash 10001 Notas 78.58 62.64 5.45
10002 Jhonny Cash 10002 Notas 81.27 61.91 95.42
10003 Jhonny Cash 10003 Notas 27.36 91.04 2.53
10004 Jhonny Cash 10004 Notas 92.82 21.16 18.95
10005 Jhonny Cash 10005 Notas 47.26 71.38 69.12
10006 Jhonny Cash 10006 Notas 67.99 35.94 3.11
10007 Jhonny Cash 10007 Notas 22.33 73.64 41.11
10008 Jhonny Cash 10008 Notas 53.68 47.44 62.57
10009 Jhonny Cash 10009 Notas 37.59 23.41 29.78
10010 Jhonny Cash 10010 Notas 16.35 90.42 88.06
10011 Jhonny Cash 10011 Notas 40.42 64.48 46.05

Fim da lista

"Lista 001" cheia: 12 elementos

Para essa versão de fabrica()

Aluno* fabrica()
{
	static int matricula = 10000;
	Aluno* a = (Aluno*)malloc(sizeof(Aluno));
	sprintf(a->nome, "Jhonny Cash %04d", matricula);
	a->matricula = matricula;
	a->n1 = rand() % 100 + rand() % 100 / 100.f;
	a->n2 = rand() % 100 + rand() % 100 / 100.f;
	a->n3 = rand() % 100 + rand() % 100 / 100.f;
	matricula += 1;
	return a;
};  // fabrica()

Claro que inserir no final não é assim o máximo de útil. Em geral eu escreveria as 3:

int     inserir_no_inicio(void*, Lista*);
int     inserir_no_final(Aluno*, Lista*);
int     inserir_na_ordem(void*, Lista*, int(*)(void*, void*));

 Mas isso tudo é muito rápido e a versão mais útil é claro a que insere na ordem, e que funciona igualzinho: você passa uma rotina que compara dois itens --- alunos aqui --- e devolve -1,0 ou 1 conforme o seu critério de ordem, e o código chama a rotina e assim insere por exemplo por ordem de matrícula de aluno, ou CEP de entrega, ou número da caixa, coisas assim. Sim, uma rotina de CallBack como o qsort(0 usa. Basta isso.

 

Cansei de escrever :D 

Vou copiar uma versão da rotina que insere no fim. Inseri esse código em um programa antigo, não de produção. Pode ter algum erro...mas acho que não.

int inserir_no_final(Aluno* aluno, Lista* l)
{
    if (l == NULL) return -1;
    if ((l->maximo > 0) && (l->quantos == l->maximo)) return -1; // nao cabe
    // cabe: arruma onde
    int p = 0;
    if (l->quantos == 0)
    {   // esta vazia
        l->inicio = p;
        l->fim = p;
        l->dados[p].anterior = -1;
        l->dados[p].proxima = -1;
    }
    else
    {
        p = (l->fim + 1) % (l->maximo);
        while (l->dados[p].status != 0) p = (p + 1) % l->maximo;
    };  // if()
    // vai inserir em p
    memcpy(&(l->dados[p].aluno), aluno, sizeof(Aluno));
    l->dados[p].status = 1; // ocupado
    l->dados[p].anterior = l->fim; // o ultimo de antes
    l->dados[p].proxima = -1; // depois nao tem ninguem
    if(l->fim >= 0) l->dados[l->fim].proxima = p; // o que era ultimo aponta para esse
    l->fim = p; // novo fim em p
    l->quantos = l->quantos + 1;
    return p;
};  // inserir_no_final()

Note que a rotina de inserção não aloca memória e só tem uma chamada de função. Para memcpy() porque como a estrutura é estática você pode copiar a struct toda de uma vez e isso em C é ultra rápido.

  • Membro VIP
Postado
12 horas atrás, Rafael LXP disse:

struct aluno al; al.matricula = 53563; strcpy(al.nome, "Joao Santos"); insere_no_fim_da_lista(li, &al);

Então já esta inserindo ao fina da lista! coloquei pra executar aqui 

 

Antes o resultado era:l


lista vazia: 1
lista cheia:0
tamanho da lista:0

 

Depois de implementar a funçao o resultado é:


lista vazia: 0
lista cheia:0
tamanho da lista:1

 

Então quer dizer que o elemento foi inserido ao final da lista??

 

Essa mudança apenas, nos resultados em tela, indica que algo foi inserido, mas não diz onde!

 

Cada função tem um propósito. A primeira apenas dizer se está vazia, a segunda se já enchu e a última o seu tamanho. Se quer saber se inseriu no fim, uma boa forma seria imprimir a lista completa. Ou cria uma função que exibe a posição do elemento que está inserido etc.

 

 

adicionado 48 minutos depois

@arfneto, para este contexto, creio que estaria criando pelo em ovo... o cerne da questão é simplesmente implementar novas funções para o algoritmo que já foi fornecido. Não importa o nome dado a estrutura... o autor do enunciado OU o autor da postagem chamou de "lista estática". Poderia ter chamado de "bicicleta de rodinha", entende?, ou seja: no final, o que deve ser feito é o que solicitado. A foco da questão aqui não é o que é correto ou não, ou o que poderia ser melhorado etc. Vide:

 

Em 26/04/2020 às 17:12, Rafael LXP disse:

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

 

Que lista? a lista que está lá no código.

 

 

Ainda essa questão... De qualquer modo, quando se disse, "lista estática", ficou implícito, pelo menos de algum modo para mim, que está se tratando de um vetor (ou array, não sei o nome em C técnico... mas aquilo que usam os "[]"). Já ao propor algo como, por exemplo:
 

Em 26/04/2020 às 17:54, arfneto disse:

O tal Node, o nó

  • tem um ponteiro para algum conteúdo
  • tem um ponteiro para o próximo nó
  • tem um ponteiro para o nó anterior

 

Você está sugerindo a mudança do algoritmo atual (que é um ponteiro de struct que tem um vetor de outra struct... ou o que seja, rs) para uma coisa diferente (uma estrutura de encadeamento de ponteiro, ou algo do tipo). Lá, ele já tem uma estrutura (e quer, e deve ser, assim). Veja... o cerne do termo "estático" está na estrutura do armazenamento (estrutura estático, representado por uso de um vetor), e não no tamanho (algo qualquer que não mude de tamanho), ou seja: no máximo, com a nova estrutura, você iria está criando uma "estrutura dinâmica" com "tamanho estático", sacou? E mesmo que um vetor com [] venha também a não ser estático, no sentido do tamanho (que dê para redimensionar ou não), a questão é que ele tem um sentido de ser (estático)... pelo menos para o contexto. 

 

 

Resumindo:

 

Entendi que o @Rafael LXP teria que fazer isso:

 

Em 26/04/2020 às 17:12, Rafael LXP disse:

Essa função precisará receber como parâmetro a lista (ponteiro) e o elemento a ser inserido

 

Que seria mais ou menos isso:

 

13 horas atrás, isrnick disse:

int insere_no_fim_da_lista(struct lista *li, struct aluno *al){
  
}

 

 

  • Curtir 1
Postado
Citação

lista estática criar uma função

 

Em 26/04/2020 às 17:12, Rafael LXP disse:

Preciso  criar 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, é 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


É o que temos para o tópico. E isso é o que se imagina que seja a tal lista estática:

struct lista
{
    int qtde;
    struct aluno lAlunos[TAMANHOLISTA];
};

Apenas um vetor e um contador. Não estou sugerindo mudar nada. Mas dizer que há um algoritmo implementado por parte do exemplo ou do autor seria um exagero. A estrutura de dados seria um vetor e um contador. O Algoritmo seria copiar o valor da estrutura que veio como argumento na função para o tal vetor de estruturas e somar um ao contador? Então está bem. Deve ensinar algum conceito novo.

 

59 minutos atrás, Simon Viegas disse:

Você está sugerindo a mudança do algoritmo atual (que é um ponteiro de struct que tem um vetor de outra struct... ou o que seja, rs) para uma coisa diferente (uma estrutura de encadeamento de ponteiro, ou algo do tipo). Lá, ele já tem uma estrutura (e quer, e deve ser, assim). Veja... o cerne do termo "estático" está na estrutura do armazenamento (estrutura estático, representado por uso de um vetor), e não no tamanho (algo qualquer que não mude de tamanho), ou seja: no máximo, com a nova estrutura, você iria está criando uma "estrutura dinâmica" com "tamanho estático", sacou? E mesmo que um vetor com [] venha também a não ser estático, no sentido do tamanho (que dê para redimensionar ou não), a questão é que ele tem um sentido de ser (estático)... pelo menos para o contexto


Não estou sugerindo mudar nada. O que eu expliquei e dei um exemplo é que existe a tal lista (ligada) estática e poderia ser esse o objetivo do exercício. E o que torna a lista estática é o que eu também mostrei, o fato óbvio de a lista ser estática. alocada inicialmente, inteira. No stack via

    Lista    lista[Tamanho];

ou no heap no momento da criação alocando

    Lista* lista = (Lista*) malloc(sizeof(Node)*Tamanho);

Esse é o 'cerne do termo "estático"' @Simon Viegas a lista é manipulada através de índices na memória estática. Não há alocação de memória.

 

E esse sim é um algoritmo sim, importante, porque tem alta performance, pela razão que eu também expliquei. E isso pode ser medido.

 

Agora se o "exercício" é isso que o autor entendeu e com esse nome o autor do enunciado criou um termo estiloso para um vetor e um contador: lista estática. E não vai ensinar nada. Ou vai: somar um.

 

adicionado 7 minutos depois

Em resumo 

 

Eu achei que o autor tivesse "esquecido" o termo "ligada" e simplificado o título do tópico e o próprio exercício... Se aparentemente ele não fez isso o exercício é uma coisa inútil tanto nomes chiques a um simples vetor com um contador...

  • Curtir 1
  • Membro VIP
Postado

@arfneto, o que eu quero dizer é que precisaria fazer o que é foi solicitado. Existe um código pré-fornecido, daí, se quer que insira uma nova função (de acordo com a estrutura atual).

 

Concordo que o nome utilizado para definir algo tem sim a sua importância! sou defensor disso também, rs (tanto acho interessante, que estamos debatendo)... mas não é o cerne do contexto em si (mais mesmo assim relevante, é claro). Veja:

 

2 horas atrás, Simon Viegas disse:

Poderia ter chamado de "bicicleta de rodinha"

 

Tanto faz nome! Sacou? seria basicamente dizer:

 

Fulano, essa função aqui pode servir para o que foi pedido:

15 horas atrás, isrnick disse:

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

 

Mas oh! o código não está utilizando "bicicleta de rodinha". Esse nome não tem algo a ver!!! Muito estranho! Isso aí tá mais para um xxxxxxxx.

 

Entende? se eu vou no restaurante e peço: "Por favor: um x-egg, mas com apenas pão e ovo". Entendo que o cara tem que me trazer um "pão e ovo"... e não um "pão, carne, ovo e queijo" (eventualmente também presunto) por que disse "x-egg".

 

Ele poderia até dizer:
- "Senhor, no caso o senhor quer um Americano?".

- Hum! É isso mesmo. Desculpe, não lembrava do nomePor favor, apenas pão e ovo!!

 

O garçom, dando uma de maldoso, poderia até cobrar como um x-egg (quer supostamente é mais caro) e trazer o tal do "pão com ovo"... mas o que importa que vou comer meu "pão com ovo". rs

 

Sobre a "lista estática" do contexto penso assim: o termo "estático" seria uma alusão ao uso de vetores (termo errado ou não). Usar ponteiros já seria como dizer algo como: "lista encadeada"... no caso, podendo até chamar de "lista estática encadeada"?. Para mim, não é o caso. O exercício serve essencialmente para "treinar manipulação de vetores (com os [])" (e não manipulação de ponteiros (encadeamentos)).

 

De um modo geral, entendo como nesse documento, por exemplo:

http://wiki.icmc.usp.br/images/a/ac/Lista_Sequencial_Estatica_09.pdf

 

  • Curtir 1
Postado

Toda lista desse algoritmo tem: mesmo tamanho, mesmo tipo e poucas das operações elementares e reduzida aos interesses do examinador com sua didática. 

 

Esta é mesmo uma resposta à sua pergunta.

17 horas atrás, isrnick disse:

#include <string.h>
  /*...*/
int insere_no_fim_da_lista(struct lista *li, struct aluno *al)
{
	if (!lista_cheia(li)){
		li->lAlunos[li->qtde] = *al;
		li->qtde++;
		return -1;
	}
	else {
		return 0;
    }
}

 

 

16 horas atrás, Rafael LXP disse:

Então quer dizer que o elemento foi inserido ao final da lista??

E você não vê isso ainda por quê? Observe mais um vez o campo qtde; Ele é o índice do último (Aluno) e a magnitude real da lista, ou seja, o número de elementos na lista nos conduz ao seu último elemento.

 

Bons estudos.

 

Postado
2 horas atrás, Simon Viegas disse:

De um modo geral, entendo como nesse documento, por exemplo:

http://wiki.icmc.usp.br/images/a/ac/Lista_Sequencial_Estatica_09.pdf

 

Então baseado nisso, acredito que a lista proposta nesse exercício poderia ser classificada como uma Lista Sequencial Estática, enquanto o tipo de lista que o  @arfneto está apontando seria classificada como uma Lista Ligada Estática.

 

Concordam com essa nomenclatura para diferenciar um do outro?

  • Curtir 1

Crie uma conta ou entre para comentar

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

Criar uma conta

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

Crie uma nova conta

Entrar

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

Entrar agora

Sobre o Clube do Hardware

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

Direitos autorais

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

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!