Problem removing the first node from the double-chained list

0

Good evening,

I am trying to solve an issue that asked to remove students whose CR is less than 5. My biggest problem is to remove the first node (first student) from a double-chained list when there is only one node. I just gave free on the node containing the CR with value less than 5, and made the head of the list point to NULL, which would be the address of the successor node to which it will be deleted, nothing too much. The result is that at the time of printing the list, the node remained intact, but with random values after the free () call. Follow the print and source code for better analysis.

I'm counting on everyone's help!

#include<stdio.h>#include<stdlib.h>typedefstruct{longmatricula;charnome[51];floatCR;}DADOS_ALUNO;typedefstruct{DADOS_ALUNOdados;//Dadosdoalunovoid*pProximoAluno;//Ponteiroparaopróximoalunovoid*pAlunoAnterior;//Ponteiroparaalunoanterior}ELEMENTO;ELEMENTO*criaLista(){returnNULL;}ELEMENTO*cadastraAlunos(ELEMENTO*lista,DADOS_ALUNOnovo_aluno){ELEMENTO*novo=(ELEMENTO*)malloc(sizeof(ELEMENTO));//InicialmenteosponteirosiniefimapontamparaNULLELEMENTO*ini=lista;ELEMENTO*fim=lista;if(novo==NULL){printf("Memoria insuficiente\n");
        exit(1);

    } else if(lista == NULL){ //Se a lista estiver vazia, insere o primeiro nó

        novo->dados = novo_aluno;
        novo->pProximoAluno = fim;
        novo->pAlunoAnterior = ini;

        fim = ini = novo;

        return ini;

    } else { //Caso a lista tenha pelo menos um nó

        novo->dados = novo_aluno;
        novo->pProximoAluno = fim;
        novo->pAlunoAnterior = NULL;
        fim->pAlunoAnterior = novo;
        ini = novo;

        return ini;

    }

}

//a)Retornar a quantidade de alunos com coeficiente de rendimento maior ou igual a 7.
int numAlunosCrAlto(ELEMENTO* pLista){

    int quantidade = 0;

    ELEMENTO* p = pLista; //Ponteiro que aponta para o início da lista para percorrê-lo


    if(pLista == NULL){
        printf("Lista vazia\n");
        exit(1);

    } else {

        while(p != NULL){

            if(p->dados.CR >= 7){
                quantidade++;
            }

            p = p->pProximoAluno;
        }

        return quantidade;  
    }   
}

void imprimeAluno(ELEMENTO* lista){

    ELEMENTO* p = lista;

    if(lista == NULL){
        printf("Lista vazia\n");
        exit(1);

    } else {

    for(; p != NULL; p = p->pProximoAluno){
        printf("Matricula: %ld - Nome: %s - CR: %.2f\n", p->dados.matricula, p->dados.nome, p->dados.CR);
    }

    printf("\n\n");

    }
}


//b)Excluir da lista todos os alunos com coeficiente de rendimento menor que 5.
void excluirAlunosCrBaixo(ELEMENTO* pLista){

    ELEMENTO* p = pLista; //Ponteiro que aponta para o primeiro nó da lista para percorrê-la
    ELEMENTO* ant = NULL; //Ponteiro para guardar o nó antecessor ao que será excluído

    if(pLista == NULL){
        printf("Lista vazia\n");
        exit(1);

    } else {

        while(p != NULL){

            if(p->dados.CR < 5 && p->pAlunoAnterior == NULL){ //Se for primeiro da lista

            if(p->pProximoAluno == NULL){ //Se não houver mais elementos na lista, a mesma fica vazia

                ant = p; /*Usando o ponteiro ant para apontar ao p e chamar o free() sobre ele para 
                         não perder a referência de p, pois este será utilizado para percorrer a lista*/

                pLista = ant->pProximoAluno; //A cabeça da lista aponta para NULL, indicando que está vazia
                free(ant); 

            } else { //Caso ainda exista mais elementos na lista, o segundo elemento passa a ser o primeiro

                ant = p;
                p = p->pProximoAluno;
                free(ant);
                p->pAlunoAnterior = NULL;
            }


            } else if(p->dados.CR < 5 && p->pAlunoAnterior != NULL && p->pProximoAluno != NULL){ //Se o elemento estiver no meio da lista

                ELEMENTO* aux; //Ponteiro que irá apontar para o nó antecessor ao nó que será excluído
                ant = p;
                aux = ant->pAlunoAnterior;  
                p = p->pProximoAluno;
                p->pAlunoAnterior = aux;
                aux->pProximoAluno = p;
                free(ant);

            } else if(p->dados.CR < 5 && p->pProximoAluno == NULL){ //Se for o último da lista


                ant = p->pAlunoAnterior;
                ant->pProximoAluno = NULL;
                free(p);

            }

            p = p->pProximoAluno;       
        }
    }   
}


int main(int argc, char *argv[]) {


    ELEMENTO* Lista = (ELEMENTO*)malloc(sizeof(ELEMENTO));

    if(Lista == NULL){
        printf("Memoria insuficiente\n");
        exit(1);

    } else {

        Lista = criaLista();

//      DADOS_ALUNO a1 = {201311, "Teste 01", 8.5};
//      DADOS_ALUNO a2 = {201412, "Teste 02", 6.3};
//      DADOS_ALUNO a3 = {201211, "Teste 03", 6.2};
        DADOS_ALUNO a4 = {201511, "Teste 04", 1.0};

//      Lista = cadastraAlunos(Lista, a1);
//      Lista = cadastraAlunos(Lista, a2);
//      Lista = cadastraAlunos(Lista, a3);
        Lista = cadastraAlunos(Lista, a4);

        imprimeAluno(Lista);

        excluirAlunosCrBaixo(Lista);

        imprimeAluno(Lista);

        printf("Total de alunos com CR maior ou igual a 7: %d", numAlunosCrAlto(Lista));

    }

    return 0;
}
    
asked by anonymous 04.09.2017 / 01:50

1 answer

0

In line 132, make a call to your function to print the list, you will see that your code is actually deleting, however, it is not updating the pointer to NULL (this is very common in list implementations in C ).

What happens is that even though you are sending your parameters by memory address in C , you can not change the memory address within the scope of the function (in other words, it would be like if the address of the variable were passed by value). To illustrate best, an example follows:

#include <stdio.h>

void change(int *v ,int *b){
    v=b;
    printf("Dentro da fução\n");
    printf("%d\n", *v);
}

int main(){
    int *v1;

    int a=10;
    int b=5;
    *v1=a;

    change(v1,&b);
    printf("Fora da função\n");
    printf("%d\n", *v1);
 return 0;
}

Possible solutions you might be implementing are lists with headers (structures that hold the start position of your list and the end), so you could send pointers to your functions solving the problem or change their functions for the return type ELEMENT *

    
21.09.2017 / 07:48