Function inserts does not work

2

I am building a linked list to store a string with the following signature in the registry:

typedef struct Lista *Noticia;

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

And the following function insert:

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;
}

But it is not working, and it indicates the error in line 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 registry, and I think it can be the problem, because I have always declared the string in the record by allocating memory, eg, char Text [100]. So I ask for help.

    
asked by anonymous 19.07.2017 / 21:42

1 answer

3

The malloc must be done with the type of list and not its pointer. Therefore:

novo = malloc(sizeof(Noticia));

Should actually be:

novo = malloc(sizeof(struct Lista));

Because Noticia is actually a struct Lista * , and displaying sizeof of each we can see that it does not match 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 start node, as it does not contemplate the fact that the list is NULL . If it is NULL the code jumps over while :

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

And in the following line crashes because it attempts to dereference a null pointer:

novo->PN = q->PN;

Where q points to NULL soon we can not q->PN , because it would try to access address 0 from memory that is not possible. Here is another problem, which is when the hora to insert is greater than all the ones that are in the list, which causes it to go to the end and stay in the same null problem. In this case I suggest reviewing the logic you are trying to apply. If you want to apply a logic if it is greater to insert at the end you 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 genre 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;
}

Where 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 null-list 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 their settings within the function.

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

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

With their respective settings as well.

    
19.07.2017 / 22:43