Insert function does not work

Asked

Viewed 77 times

2

I am building a chained list to save a string with the following signature on the record:

typedef struct Lista *Noticia;

struct Lista {
    int hora; 
    char *Texto; 
    struct Lista *PN; 
};

And insert the following function:

void Insere_Noticia (Noticia p, int hora, char txt[]) {
    Noticia q, novo;
    q = p;
    novo = malloc(sizeof(Noticia));
    novo->hora = hora;
    novo->Texto = txt;
    while (q != NULL && q->hora < hora) 
        q = q->PN;
    novo->PN = q->PN;
    q->PN = novo;
}

However, it is not working, and indicates the line error novo->PN = q->PN I have in mind that the problem is very simple, but I have never worked with lists of this nature, with a pointer to char in the record, and I think this may be the problem, because I have always declared the string in the record allocating memory, e.g., char Text[100]. So I ask for help.

1 answer

3


The malloc should be done with the list type and not your pointer. So:

novo = malloc(sizeof(Noticia));

Must actually be:

novo = malloc(sizeof(struct Lista));

Because Noticia is actually a struct Lista *, and presenting the sizeof of each one we can see that does not correspond to what was intended:

  • sizeof(struct Lista) => 12
  • sizeof(Noticia) => 4, because it is a pointer

The function however will only work if it has at least one initial node, as it does not contemplate the fact that the list NULL. If she is NULL the code jumps over the while:

 void Insere_Noticia (Noticia p, int hora, char txt[]) {
 q = p;
 ...
 while (q != NULL && q->hora < hora) //salta se q nulo

And on the next line crashes because it tries to dereference a null pointer:

novo->PN = q->PN;

In which q points to NULL so we can’t do q->PN, because it would be trying to access the 0 memory address that is not possible. Here is also another problem, which is when the hora the insert is larger than all the ones on the list, which makes it go all the way and stay in the same null problem. For this case I suggest to review the logic you are trying to apply. If you want to apply a logic of if it is larger insert at the end can do the following:

//agora enquanto o próximo não for nulo, por isso para 1 antes do fim
while (q->PN != NULL && q->hora < hora){  
    q = q->PN;
}

Soon a main of this kind will work:

int main()
{
    Noticia lista = malloc(sizeof(struct Lista)); //primeiro elemento criado manualmente
    lista->hora = 10;
    lista->Texto = "algum texto";

    imprimirLista(lista);
    Insere_Noticia(lista, 5, "outro texto");
    imprimirLista(lista);

    return 0;
}

In which the imprimirLista could be something like:

void imprimirLista(Noticia n){
    printf("\nInicio");

    while (n != NULL){
        printf("\n->%d %s", n->hora, n->Texto);
        n = n->PN;
    }
}

To work with a list to null start it would be necessary to modify the function of the list to receive a pointer to list pointer:

void Insere_Noticia (Noticia *p, int hora, char txt[]) {

And adjustments within the function.

Or return the new start of the list when you are inserting the first:

Noticia Insere_Noticia (Noticia p, int hora, char txt[]) {

With their respective adjustments also.

Browser other questions tagged

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