Bonjour je suis en train d'apprendre le C et j'éssaie de comprendre le principe de liste chainé pour le moment, j'éssaie de faire le premier exercice pour l'insertion en milieu de liste mais pour le moment ça se termine en une fonction insertionMilieu avec une condition if en infini mais avec mon chiffre en milieu et la consigne dis de prendre en paramètre l'adresse précedent je ne comprend pas après comment la traité voilà mon code avec la fonction insertionMilieu qui permet de rajouter le chiffre à tel position.
Merci pour votre aide.
#include <stdio.h>
#include <stdlib.h>
typedef struct Element Element;
struct Element
{
int nombre;
Element* suivant;
};
typedef struct Liste Liste;
struct Liste
{
Element* premier;
};
Liste* initialisation();
void insertion(Liste* liste, int nvNombre);
void suppression(Liste* liste);
void afficherListe(Liste* liste);
void insertionMilieu(Liste* liste, int nvNombre, Element* premier);
int main(int argc, char* argv[])
{
Liste* maListe = initialisation();
Element* premier = initialisation();
insertion(maListe, 8);
insertion(maListe, 15);
insertion(maListe,77);
insertion(maListe, 7);
insertionMilieu(maListe, 7777,premier);
afficherListe(maListe);
return 0;
}
Liste* initialisation()
{
Liste* liste = malloc(sizeof(*liste));
Element* element = malloc(sizeof(*element));
if (liste == NULL || element == NULL)
{
exit(EXIT_FAILURE);
}
element->nombre = 0;
element->suivant = NULL;
liste->premier = element;
return liste;
}
void insertion(Liste* liste, int nvNombre)
{
/* Création du nouvel élément */
Element* nouveau = malloc(sizeof(*nouveau));
if (liste == NULL || nouveau == NULL)
{
exit(EXIT_FAILURE);
}
nouveau->nombre = nvNombre;
/* Insertion de l'élément au début de la liste */
nouveau->suivant = liste->premier;
liste->premier = nouveau;
}
void insertionMilieu(Liste* liste, int nvNombre, Element* premier)
{
/* Création du nouvel élément */
Element* nouveau = malloc(sizeof(*nouveau));
if (liste->premier->suivant->suivant && premier->nombre ) {
nouveau->nombre = nvNombre;
/* Insertion de l'élément au début de la liste */
nouveau->suivant = liste->premier;
liste->premier->suivant->suivant = nouveau;
}
}
void suppression(Liste* liste)
{
if (liste == NULL)
{
exit(EXIT_FAILURE);
}
if (liste->premier != NULL)
{
Element* aSupprimer = liste->premier;
liste->premier = liste->premier->suivant;
free(aSupprimer);
}
}
void afficherListe(Liste* liste)
{
if (liste == NULL)
{
exit(EXIT_FAILURE);
}
Element* actuel = liste->premier;
while (actuel != NULL)
{
printf("%d -> ", actuel->nombre);
actuel = actuel->suivant;
}
printf("NULL\n");
}
- Edité par françois-jordan quenard 1 novembre 2022 à 15:47:33
Deuxième question: tu n'as pas de warning pour la ligne 27 ? Car initialisation() renvoie un Liste *, pas un Element *. Ne devrais-tu pas écrire deux fonctions différentes ?
Edit: il me semble que tu n'as pmême pas besoin de cette ligne 27
- Edité par edgarjacobs 1 novembre 2022 à 18:20:08
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Deux posts sur le même sujet ... Troisième question: comment obtenir cette fameuse adresse? Quatrième question: pourquoi toujours placer un élément lors de l'initialisation? Une liste vide, ça n'existe pas? Et pas de bon cours sur le sujet? Je n'en ai pas trouvé sur ZDS.
Le Tout est souvent plus grand que la somme de ses parties.
Première question que l'on se pose, c'est quoi insérer au milieu ? (A mi chemin entre le début et la fin ou bien d'autres critères ? ...)
Entre le debut et la fin et s'il y avait d'autre critère ece serait que le premier serait pas vide et le suivant aussi par la même occasion.
Mais ok je pose d'abord cette question et je trouverai les réponse pour les mettre en condition Merci.
edgarjacobs a écrit:
Deuxième question: tu n'as pas de warning pour la ligne 27 ? Car initialisation() renvoie un Liste *, pas un Element *. Ne devrais-tu pas écrire deux fonctions différentes ?
Edit: il me semble que tu n'as pmême pas besoin de cette ligne 27
- Edité par edgarjacobs 1 novembre 2022 à 18:20:08
Nan l'avertissement c'est plutôt aux nouveau->nombre = nvNombre; ligne 75 quand je le met au mauvais endroit
il me semble que tu n'as même pas besoin de cette ligne 27-> pour l'initialisation à voir t'as raison je vais voir ça
- Edité par françois-jordan quenard 3 novembre 2022 à 23:33:38
Deuxième question: tu n'as pas de warning pour la ligne 27 ? Car initialisation() renvoie un Liste *, pas un Element *. Ne devrais-tu pas écrire deux fonctions différentes ?
Nan l'avertissement c'est plutôt aux nouveau->nombre = nvNombre; ligne 75 quand je le met au mauvais endroit
Ah bon ?
xxx.c: In function 'main':
xxx.c:27:24: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
Element* premier = initialisation();
^~~~~~~~~~~~~~
- Edité par edgarjacobs 3 novembre 2022 à 23:42:36
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Première question que l'on se pose, c'est quoi insérer au milieu ? (A mi chemin entre le début et la fin ou bien d'autres critères ? ...)
Entre le debut et la fin ...
On s'en doute, mais c'est pas assez précis. Parce que avant de coder, il faut savoir exactement ce que l'on doit faire, sinon chacun l'interpète comme bon lui semble.
Tu n'as toujours pas répondu à ma question: comment obtiens-tu l'adresse où tu veux insérer. OK. Elle peut être n'importe où dans la liste, mais encore? C'est avant (ou après) une valeur? Ou bien c'est N positions après le début? Et que fais-tu si tu ne trouves pas cette adresse?
Le Tout est souvent plus grand que la somme de ses parties.
Tu n'as toujours pas répondu à ma question: comment obtiens-tu l'adresse où tu veux insérer. OK. Elle peut être n'importe où dans la liste, mais encore? C'est avant (ou après) une valeur? Ou bien c'est N positions après le début? Et que fais-tu si tu ne trouves pas cette adresse?
Salut PierrotLeFou désolé je pensais que je devais réfléchir à ces questions moi même, alors l'adresse c'est à la liste->premier que je l'obtiens et je l’Intègre ou je veux en rajoutant liste->premier->suivant->suivant. Elle peut être juste deux cran après la première. C'est toujours après une valeur qu'elle se rajoute, j'ai pas mis de valeur précédent pour éviter une liste double chaine. SI je trouve pas d'adresse eh bien on met une valeur Null ou elle s’interrompt direct
> C'est toujours après une valeur qu'elle se rajoute Donc tu cherches une valeur et ensuite tu en obtiens l'adresse. Je ne sais pas comment tu veux le faire, mais de la façon dont je comprend, tu vas parcourir ta liste (sans doute en partie), deux fois. Tu pourrais ne parcourir la liste qu'une seule fois et chercher la valeur plutôt qu'une adresse.
Tu auras l'adresse en même temps que la valeur, et effectivement, tu insères après cette adresse.
- Edité par PierrotLeFou 5 novembre 2022 à 0:57:06
Le Tout est souvent plus grand que la somme de ses parties.
> C'est toujours après une valeur qu'elle se rajoute Donc tu cherches une valeur et ensuite tu en obtiens l'adresse. Je ne sais pas comment tu veux le faire, mais de la façon dont je comprend, tu vas parcourir ta liste (sans doute en partie), deux fois. Tu pourrais ne parcourir la liste qu'une seule fois et chercher la valeur plutôt qu'une adresse.
Tu auras l'adresse en même temps que la valeur, et effectivement, tu insères après cette adresse.
- Edité par PierrotLeFou il y a environ 11 heures
Alors pour l'insertion au milieu, j'ai modifier la fonction insertionMilieu.
void insertionMilieu(Liste* liste, int nvNombre)
{
Element* nouveau = malloc(sizeof(*nouveau));
if (nouveau)
{
nouveau->nombre = nvNombre;
liste->premier->suivant->suivant->nombre = nouveau->nombre;
}
}
qui change la valeur de l'addresse indiqué mais écrase l'ancienne, je vais chercher pour qu'elle me le fasse après l'addresse indiquer je voulais voir si c'était la bonne voie pour réussir
- Edité par françois-jordan quenard 5 novembre 2022 à 19:44:27
> C'est toujours après une valeur qu'elle se rajoute Donc tu cherches une valeur et ensuite tu en obtiens l'adresse. Je ne sais pas comment tu veux le faire, mais de la façon dont je comprend, tu vas parcourir ta liste (sans doute en partie), deux fois. Tu pourrais ne parcourir la liste qu'une seule fois et chercher la valeur plutôt qu'une adresse.
Tu auras l'adresse en même temps que la valeur, et effectivement, tu insères après cette adresse.
- Edité par PierrotLeFou hier à 0:57
Excuse moi je ne sais pas si tu as lu le commentaire précédent c'était pour signaler que j'ai modifier la fonction tout est dans le commentaire précédent.
Que se passe-t-il si ma liste contient 25 éléments et que je veux insérer après le 22 ième? Vas-tu faire des ...->suivant->... 21 fois? On doit faire une boucle.
Il faut retenir le précédent de celui qu'on vient de visiter.
De plus, si on veut insérer après une valeur ou une position, il faut fournir cette information à la fonction.
- Edité par PierrotLeFou 6 novembre 2022 à 14:44:39
Le Tout est souvent plus grand que la somme de ses parties.
Que se passe-t-il si ma liste contient 25 éléments et que je veux insérer après le 22 ième? Vas-tu faire des ...->suivant->... 21 fois? On doit faire une boucle.
Il faut retenir le précédent de celui qu'on vient de visiter.
De plus, si on veut insérer après une valeur ou une position, il faut fournir cette information à la fonction.
- Edité par PierrotLeFou 6 novembre 2022 à 14:44:39
J'ai fait une boucle pour le moment j'ajoute un élémént à la fin mais elle éfface les autre élémént pour l'ajouter à la fin, pour le je cherche à faire un autre pointeur ou à moins qu'il y est une autre solution
void insertionMilieu(Liste* liste, int nvNombre)
{
Element* nouveau = malloc(sizeof(*nouveau));
if (liste->premier != NULL)
{
if (nouveau)
{
nouveau->nombre = nvNombre;
while (liste->premier->suivant != NULL) {
liste->premier = liste->premier->suivant;
liste->premier->suivant = nouveau;
nouveau->suivant = NULL;
}
}
}
}
- Edité par françois-jordan quenard 11 novembre 2022 à 21:11:41
A chaque tour de boucle tu décides de changer ta liste, le premier élément est remplacé par le second. A la fin ta liste ne sera donc constituée que du dernier. Il ne faut pas modifier ta liste!
Pour insérer avant une valeur (si on ne trouve pas, on insère à la fin) - void insertionMilieu(Liste *liste, int valeur, int nouvelle) { Element *courant = liste->premier; Element *precedent = NULL; while(courant && courant->valeur != valeur) { precedent = courant; courant = courant->suivant; } // if(courant == NULL) return; // On peut choisir de ne rien faire si on ne trouve pas. Element *nouveau = malloc(sizeof(Element)); nouveau->valeur = nouvelle; nouveau->suivant = courant; if(precedent == NULL) liste->premier = nouveau; else precedent->suivant = nouveau; }
Le Tout est souvent plus grand que la somme de ses parties.
Dans tous les cas il s'agira de raccorder le nouveau maillon
Soit en modifiant le champ suivant du maillon précédent
Soit en modifiant le champ premier de la liste.
Dans la solution traditionnelle, les deux cas sont séparés (voir code de @pierrot) mais il est possible de les unifier. Pour ça on utilise un pointeur qui indique l'adresse du pointeur à modifier.
Au début : l'adresse du champ premier, ensuite l'adresse du champ suivant.
C'est un pointeur de pointeur de maillon.
On se retrouve avec du code plus court, mais plus difficile à décoder, avec des trucs inhabituels comme p = &( (*p)-> suivant);
- Edité par michelbillaud 12 novembre 2022 à 8:01:45
Bonsoir j'ai trouvé une solution mais elle me semble pas parfait je crois que ça résout le problême merci à tous de m'avoir aider n'hésiter à me dire si il y a une meilleur solution, je vous présente ma solution.
Il me semble que tu n'insères pas en milieu de liste, mais toujours à la fin, puisque tu ne sors de ta boucle while ligne 14 que si tu pointes sur le dernier élément.
Il faudrait un critère de recherche pour insérer "en milieu de liste"
- Edité par edgarjacobs 19 novembre 2022 à 20:48:34
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Avec 3 if imbriqués, c'est sûrement trop compliqué.
Et on ne peut pas dire si c'est correct, parce que tu ne veux toujours pas définir ce que tu entends par "insérer au milieu". On ne joue pas aux devinettes.
Et par consequent une "meilleure solution", si on ne sait pas quel est le problème...
- Edité par michelbillaud 19 novembre 2022 à 22:17:25
Je suppose que mon code était trop simple ... Pourquoi faire simple quand on peut faire compliqué. Un seul while sans cette collection de if suffit. Et ça demande vraiment un minimum de modifications pour insérer à une position ou de façon ordonnée.
Le Tout est souvent plus grand que la somme de ses parties.
Dans la condition de la boucle while, on accède à item->suivant. Ça n'a de sens que si item n'est pas NULL.
Item n'est jamais NULL à partir de la ligne 8 (garanti au départ par la ligne 6).
La ligne 14 affecte à item une valeur qui ne peut pas être NULL (condition de la boucle).
Donc pas NULL après la boucle. Item pointe sur le dernier maillon.
Programmer des boucles, c'est faire des raisonnements par récurrence...
A part ça, le code présenté ajoute une valeur À LA FIN de la liste si elle n'est pas vide, pas "au milieu", quoi que ça puisse vouloir dire.
**Note pour l'OP** : tout le monde aime penser que "mon code à l'air correct". L'autosatisfaction, c'est pas désagréable, ça coûte pas cher, mais là on est dans le cas où c'est la même personne qui écrit le code et qui l’évalue. Et fait donc exactement les mêmes erreurs de raisonnement au même endroit, pour les mêmes raisons.
Donc il faut toujours tester. Sérieusement. En n'oubliant pas que, pour un exercice, c'est malheureusement encore la même personne qui écrit le code + fait les tests, avec le même biais : ne pas tester les cas particuliers qu'on a négligés en écrivant le code, et qu'on ne voit pas non plus en se relisant.
C'est une raison pour préparer les tests avant, calmement, avant d'avoir la cervelle farcie par les détails de programmation, boucle par ci, allocation dynamique par là. Réfléchir d'abord à ce que ça doit faire, et après chercher comment on va s'y prendre pour que ça marche.
Au fait : si ma liste contient 3 valeurs 12, 56, 34, ça veut dire quoi insérer 45 au milieu ?
- Edité par michelbillaud 20 novembre 2022 à 18:17:43
Dans la condition de la boucle while, on accède à item->suivant. Ça n'a de sens que si item n'est pas NULL.
Item n'est jamais NULL à partir de la ligne 8 (garanti au départ par la ligne 6).
La ligne 14 affecte à item une valeur qui ne peut pas être NULL (condition de la boucle).
Donc pas NULL après la boucle. Item pointe sur le dernier maillon.
Programmer des boucles, c'est faire des raisonnements par récurrence...
A part ça, le code présenté ajoute une valeur À LA FIN de la liste si elle n'est pas vide, pas "au milieu", quoi que ça puisse vouloir dire.
**Note pour l'OP** : tout le monde aime penser que "mon code à l'air correct". L'autosatisfaction, c'est pas désagréable, ça coûte pas cher, mais là on est dans le cas où c'est la même personne qui écrit le code et qui l’évalue. Et fait donc exactement les mêmes erreurs de raisonnement au même endroit, pour les mêmes raisons.
Donc il faut toujours tester. Sérieusement. En n'oubliant pas que, pour un exercice, c'est malheureusement encore la même personne qui écrit le code + fait les tests, avec le même biais : ne pas tester les cas particuliers qu'on a négligés en écrivant le code, et qu'on ne voit pas non plus en se relisant.
C'est une raison pour préparer les tests avant, calmement, avant d'avoir la cervelle farcie par les détails de programmation, boucle par ci, allocation dynamique par là. Réfléchir d'abord à ce que ça doit faire, et après chercher comment on va s'y prendre pour que ça marche.
Au fait : si ma liste contient 3 valeurs 12, 56, 34, ça veut dire quoi insérer 45 au milieu ?
- Edité par michelbillaud 20 novembre 2022 à 18:17:43
Merci Michelbilla ça va résoudre mon problême je vais m'y mettre et mettre le sujet résolu
listes chaînées : Insertion d'un élément en milieu
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
En recherche d'emploi.
Le Tout est souvent plus grand que la somme de ses parties.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.