List simply chained and not sorted

0

When running the code below, we have the following problem, when calling the imprime_lista function, when an element has already been allocated in the list, is giving segmentation fault . How do I resolve 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");
}
}
    
asked by anonymous 25.10.2017 / 05:12

1 answer

2

The main error that causes your program to fail is imprime_lista which tries to print the nodes 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 that you change this loop / loop to 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 your esvazia_lista you also have a small error where you use = to compare instead of == :

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

In 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 that the compiler gives you, as it allows you to catch these situations quickly.

Note : I do not advise, however, to read the values for 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 use in main and pass them to those functions.

    
25.10.2017 / 12:01