List simply chained and unordered

Asked

Viewed 627 times

0

When running the code below, we have the following problem, when calling the function imprime_lista, when an element has already been allocated in the list, it is giving segmentation fault. How to solve this?

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

struct No{
int dado;
struct No *prox;
};
typedef struct No No;

struct lista{
struct No *inicio;
struct No *fim;
};
typedef struct lista lista;

//----------- FUNCOES ----------//

lista* cria_lista();
void insere_inicio_lista(lista *li);
void insere_fim_lista(lista *li);
void imprime_lista(lista *li);
void remover_elemento(lista *li);
void esvazia_lista(lista *li);

//---------- MAIN ----------//

int main(){
No *aux;
No *anterior;
lista *li = cria_lista();
imprime_lista(li);
insere_inicio_lista(li);
imprime_lista(li);


return 0;
}

//----------    FUNCOES     ----------//

lista* cria_lista(){
lista* li = (lista*) malloc(sizeof(lista));
if(li != NULL){
    li->fim = NULL;
    li->inicio = NULL;
}
return li;
}

void insere_inicio_lista(lista *li){
No *novo = (No*) malloc(sizeof(No));
scanf("%d", &novo->dado);
if(li->inicio == NULL){
    li->inicio = novo;
    novo->prox = NULL;
    li->fim = novo;
} else {
    novo->prox = li->inicio;
    li->inicio = novo;
}
}

void insere_fim_lista(lista *li){
No *novo = (No*)malloc(sizeof(No));
scanf("%d", &novo->dado);
if(li->inicio == NULL){
    li->inicio = novo;
    novo->prox = NULL;
    li->fim = novo;
} else {
li->fim->prox = novo;
li->fim = novo;
li->fim->prox = NULL;
}
}

void imprime_lista(lista *li){
No *aux;
No *anterior;
if(li->inicio == NULL){
    printf("Lista vazia!!\n");
} else{
    aux = li->inicio;
    do{
        printf((" %d ", aux->dado));
        aux = aux->prox;
    }while(aux != NULL);
}
}

void remover_elemento(lista *li){
No *aux;
No *anterior;
int numero;
int achou;
if(li->inicio == NULL){
    printf("Lista vazia!!\n");
} else {
    printf("Digite o numero a ser removido: ");
    scanf("%d", &numero);
    aux = li->inicio;
    anterior = NULL;
    achou = 0;
    while(aux != NULL){
        if(aux->dado == numero){
            achou++;
            if(aux == li->inicio){
                li->inicio = aux->prox;
                free(aux);
                aux = li->inicio;
            }else if (aux == li->fim){
                anterior->prox = NULL;
                li->fim = anterior;
                free(aux);
                aux == NULL;
            } else {
                anterior->prox = aux->prox;
                free(aux);
                aux = anterior->prox;
            }
        }else{
            anterior = aux;
            aux = aux->prox;
        }

    }
    if(achou == 0){
        printf("Numero nao encontrado\n");
    }else{
        printf("Numero removido %d vez(es)\n", achou);
    }
}
}

void esvazia_lista(lista *li){
No *aux;
No *anterior;
if(li->inicio = NULL){
    printf("Lista vazia!!\n");
}else{
    aux = li->inicio;
    while(aux != NULL){
        li->inicio = li->inicio->prox;
        free(aux);
        aux = li->inicio;
    }
printf("Lista esvaziada!\n");
}
}

1 answer

2


The main error that causes your program to fail is in imprime_lista who tries to print nodes by not being sure they are not null:

void imprime_lista(lista *li){
    ...
    aux = li->inicio; //pode apanhar NULL se a lista estiver vazia

    do{
        printf((" %d ", aux->dado)); //não pode fazer ->dado sobre NULL
        ...

I suggest you exchange this loop/loop for a while normal that already solves the problem:

void imprime_lista(lista *li) {
    if(li->inicio == NULL) {
        printf("Lista vazia!!\n");
    }
    else {
        No *aux = li->inicio;

        while(aux != NULL) { //while normal aqui garante que não usa o nó com NULL        
            printf(" %d ", aux->dado);
            aux = aux->prox;
        }
    }
}

In his esvazia_lista also has a small error where use = to compare instead of ==:

void esvazia_lista(lista *li){
    No *aux;
    No *anterior;
    if(li->inicio = NULL){
    //------------^ aqui

In the remover_elemento also has a problem with == that should be =:

void remover_elemento(lista *li){
    ...    
    while(aux != NULL){
        if(aux->dado == numero){
            achou++;
            if(aux == li->inicio){
                ...
            }else if (aux == li->fim){
                anterior->prox = NULL;
                li->fim = anterior;
                free(aux);
                aux == NULL;
                //---^ aqui devia ser = para atribuir em vez de comparar

Example working on Ideone

You should always be aware of the warnings the compiler gives, as it allows you to catch these situations quickly.


Note: However, I do not recommend reading the values to the list within the functions they add, as this mixes the logic of the data with that of the list. It is therefore more advisable to read the values to be used in main and pass them on to.

  • Thank you Isac! It was very helpful!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.