J'ai des difficultés avec cette fonction. La fonction est censée rechercher un étudiant dans une liste liée et supprimer ce nœud ou imprimer un message d'erreur si l'élève n'a pas été trouvé. Le code suivant ne fonctionne pas correctement, il supprime le nœud suivant après le nœud recherché.

void vymazstudenta(STUDENT **head,const char *priezvisko)
{
    STUDENT *traverse = *head;
    while(traverse!=NULL)
    {
        if(!strcmp(traverse->priezvisko,priezvisko))
        {
        STUDENT *hladany = traverse->next;
        traverse->next = hladany->next;
        free(hladany);
        return;
        }
        traverse = traverse->next;
    }
        fprintf(stderr,"Student %s sa nenasiel.\n",priezvisko);
        return;
}
1
Babs91 20 avril 2017 à 19:47

3 réponses

Meilleure réponse

Lorsque vous parcourez la liste, vous devez stocker le nœud qui précède celui que vous vérifiez (j'ai utilisé le pointeur nommé previous dans l'extrait de code ci-dessous).

Lorsque vous trouvez le nœud correspondant que vous venez de définir next sur le nœud précédent sur next du nœud actuel, de cette façon la liste ignore le nœud à supprimer. Ensuite, vous pouvez free() le nœud correspondant.

Notez que vous devez gérer le cas particulier où le nœud à supprimer est le premier (le head)

Dans l'extrait de code ci-dessous, vous voyez cela dans le bloc if( previous == NULL ) - c'est assez explicite.

void vymazstudenta(STUDENT **head,const char *priezvisko)
{
    STUDENT *traverse = *head;
    STUDENT *previous = NULL;
    while( traverse != NULL )
    {
        if( strcmp(traverse->priezvisko,priezvisko) == 0 )
        {
            if( previous == NULL )
            {
                *head = traverse->next;
            }
            else
            {
                previous->next = traverse->next;
            }
            free( traverse );
            return;
        }
        else
        {
            previous = traverse;
            traverse = traverse->next; 
        }
    }

    fprintf(stderr,"Student %s sa nenasiel.\n",priezvisko);
    return;
}
3
Paolo 21 avril 2017 à 15:16

La fonction est erronée au moins parce qu'elle ignore le cas où l'en-tête satisfait à la condition.

Vous devez également conserver le nœud avant le nœud supprimé.

La fonction peut avoir l'aspect suivant

void vymazstudenta( STUDENT **head, const char *priezvisko )
{
    STUDENT *tmp = NULL;

    if ( *head != NULL )
    {
        if ( strcmp( head->priezvisko, priezvisko ) == 0 )
        {
            tmp = *head;
            *head = ( *head )->next;
        }
        else
        {        
            STUDENT *traverse = *head;
            while( traverse->next != NULL && strcmp( traverse->next->priezvisko, priezvisko ) != 0 )
            {
                traverse = traverse->next;
            }

            if ( traverse->next != NULL )
            {
                tmp = traverse->next;
                traverse->next = traverse->next->next;
            }
        }
    }

    if ( tmp != NULL )
    {
        free( tmp );
    }
    else
    {
        fprintf( stderr, "Student %s sa nenasiel.\n", priezvisko );
    }
}
1
Vlad from Moscow 20 avril 2017 à 17:42

Vous devez garder une trace de l'élément avant traverse afin de pouvoir modifier le pointeur suivant de cet élément pour qu'il pointe vers l'élément après traverse . Après cela, vous pouvez free(traverse)

De plus, vous devez gérer un cas particulier. C'est alors que la correspondance est sur l'élément *head. Dans ce cas, vous devez mettre à jour *head pour obtenir une nouvelle tête de liste.

Quelque chose comme:

void vymazstudenta(STUDENT **head,const char *priezvisko)
{
    if (*head == NULL)
    {
        // empty list
        return;
    }

    if(!strcmp(*head->priezvisko,priezvisko))
    {
        // Special case:
        // Remove the *head element

        STUDENT *hladany = *head;  // Save a pointer to current head
        *head = *head->next;       // Update head
        free(hladany);             // Free the previous head
        return;
    }

    STUDENT *traverse = *head->next;
    STUDENT *previous = *head;

    while(traverse!=NULL)
    {
        if(!strcmp(traverse->priezvisko,priezvisko))
        {
            previous->next = traverse->next;  // Update previous to point
                                              // to element after traverse.

            free(traverse);                   // Now free traverse
            return;
        }

        previous = traverse;                  // Move previous to next element
        traverse = traverse->next;            // Move traverse to next element
    }

    fprintf(stderr,"Student %s sa nenasiel.\n",priezvisko);
    return;
}
2
4386427 20 avril 2017 à 17:31