Error when printing chained list

2

Hello, I'm having an error in the function that prints a linked list.

I think the error is in the form's function prints, but I may also be saving the address of prox wrongly.

Follow the code:

/* 
 * File:   main.c
 * Author: pmargreff
 *
 * Created on 1 de Dezembro de 2014, 20:17
 */

/*
 * cria um struct que contém um nodo do tipo inteiro
 * e um ponteiro para uma celula do tipo do próprio struct
 */
struct cel {
    int nodo;
    struct cel *prox;
};
typedef struct cel celula;

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

celula *cria(void); //por que a função é um ponteiro ?
void insere(int x, celula *pont);
void imprime(celula *inicio);
/*
 * 
 */
int main(int argc, char** argv) {
    int i;
    celula *inicio;
    inicio = cria();

    for (i = 0; i < 10; i++) {
        insere(i, inicio);
    }
    imprime(inicio);

    return (EXIT_SUCCESS);
}

/*
 * cria uma função que recebe uma célula apontando para o ínicio 
 * e que aloca espaço para um tipo célula e passa a ser apontada pela 
 * célula inicio
 */
celula *cria(void) {
    celula *primeira;
    primeira = malloc(sizeof (struct cel));
    primeira->prox = NULL;
    return primeira; //perguntar para o andŕe o que isso significa
}

/*
 * cria uma nova váriavel do tipo célula chamada de "nova"
 * aloca espaço para ela, insere o valor no campo do seu conteúdo
 * o ponteiro da célula (ou seja) prox, recebe o valor que o ponteiro 
 * da célula anterior a ela tinha, o ponteiro da primeira aponta para 
 * nova
 */
void insere(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    nova -> prox = head -> prox;
    head -> prox = head;
}

void imprime(celula *inicio){
    celula *pont;
    for (pont = inicio -> prox; pont != NULL; pont = pont->prox)
        printf ("   %d\n", pont->nodo);
}

After a few more attempts, I have a new function used for insertion.

void *insere(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    nova -> prox = head -> prox;
    head -> prox = nova;
}
    
asked by anonymous 02.12.2014 / 00:03

1 answer

1

First of all:

void imprime(celula *inicio){
    celula *pont;
    for (pont = inicio -> prox; pont != NULL; pont = pont->prox)
        printf ("   %d\n", pont->nodo);
}

The correct would be pont = inicio; and not pont = inicio -> prox . The reason is inicio is the first element. Otherwise you would start from the second, and the program would crash if you receive a list with 1 or 0 elements.

There are more problems too:

void insere(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    nova -> prox = head -> prox;
    head -> prox = head;
}

Was the idea to insert at the beginning or at the end? Whatever is wrong for both of you. The head -> prox = head; line causes the cell to point as the next element to itself, causing a list with a loop. In addition, there is memory leak , since from head it is not possible to reach the nova that was allocated, but was lost in inaccessible memory.

To enter at the beginning:

celula *insere_no_inicio(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    nova -> prox = head;
    return nova;
}

To enter at the end:

celula *insere_no_final(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    if (head == NULL) {
        nova -> prox = NULL;
        return nova;
    }
    celula *ultima = head;
    while (ultima->prox != NULL) {
        ultima = ultima->prox;
    }
    ultima -> prox = nova;
    return head;
}

The idea of creating the list is to create the first element of it. This is what is returned by the cria function.

I would particularly modify the function cria to already fill in the created node element:

celula *cria(int x) {
    celula *primeira;
    primeira = malloc(sizeof (struct cel));
    primeira->prox = NULL;
    primeira->nodo = x;
    return primeira;
}

Or, just use the function insere_no_inicio passing as second parameter NULL , in this case the cria function can be either totally eliminated or reduced to this:

celula *cria(int x) {
    return insere_no_inicio(x, NULL);
}

EDIT:

Finally, to use these new creative functions:

celula *inicio = NULL;
for (i = 0; i < 10; i++) {
    inicio = insere_no_inicio(i, inicio);
}

// OU:

celula *inicio = NULL;
for (i = 0; i < 10; i++) {
    inicio = insere_no_final(i, inicio);
}

And you can not forget to destroy the list after finishing working with it:

void destroi(celula *inicio) {
    celula *proximo = inicio;
    while (proximo != NULL) {
        celula *destruir = proximo;
        proximo = proximo -> prox;
        free(destruir);
    }
}

You've suggested this new function:

void *insere(int x, celula *head) {
    celula *nova;
    nova = malloc(sizeof (struct cel));
    nova -> nodo = x;
    nova -> prox = head -> prox;
    head -> prox = nova;
}

Its new function is wrong, because if it receives a list [A, B, C], it changes the pointers making it [A, N, B, C], where N is the new cell. That is, it always enters the second position. If you get an empty list, it will crash.

Maybe it seems to work because its cria function started the list with a null element, and only from the second element did the values come. But in this case you will always be wasting the first element and whenever you want to use your list for anything, you should start with the second.

Finally, the return void * , which is not the same as void , is meaningless. Using void * means that the function returns a nondetermined type of pointer, but in fact it returns nothing.

    
02.12.2014 / 00:18