IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Ajout élément par ordre alphabétique dans une liste chainée


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut Ajout élément par ordre alphabétique dans une liste chainée
    Bonjour,
    J'ai créé une structure étudiant afin de l'utiliser dans une liste chainée pour gérer une école et différente section.
    Ma fonction pour ajouter un étudiant par ordre alphabétique fonctionne quand il y a déjà des élément dans ma liste, par contre mon programme plante quand mon élément est le premier à devoir être inséré dans ma liste.
    J'ai passé la journée dessus et je bloque...

    Peut-être qu'un regard neuf et expert trouvera mon erreur?

    C'est ma fonction: Etudiant * ajoutAlpha(Etudiant * tete,char inom[]);
    qui ne fonctionne pas totalement, les autres fonctionnent.

    ma structure (enum.h)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    #ifndef ENUM_H
    #define ENUM_H
     
    typedef struct Etudiant Etudiant;
    struct Etudiant
    {
        char nom[25];
        Etudiant * next;//pointeur vers la structure Etudiant suivante
    };
     
    //creation de maillon
    Etudiant * creationMaillon(char nom[]);
     
    //insertion en tête
    Etudiant * insertionTete(Etudiant * tete, Etudiant * elt);
     
    //lire liste
    void lireList(Etudiant * tete);
     
    //libère mémoire
    void freeList(Etudiant * tete);
     
    //insertion dans l'ordre alphabétique
    Etudiant * ajoutAlpha(Etudiant * tete,char inom[]);
     
    #endif // ENUM_H
    mes fonctions (Fct.c)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "enum.h"
     
    //creation de maillon et hardcodage du nom
    Etudiant * creationMaillon(char nom[])
    {
        Etudiant *maillon = NULL;
        maillon = malloc(sizeof(Etudiant));
        if (maillon == NULL)
            {
                printf("Mémoire insuffisante");
                exit(99);
            }
            sprintf(maillon->nom, nom);
            maillon->next = NULL;
        return maillon;
    }
     
    //insertion en tête
    Etudiant * insertionTete(Etudiant * tete, Etudiant * elt)
    {
         if (tete == NULL)
            {
                tete = elt;
            }
            else
            {
                elt->next = tete;
                tete = elt;
            }
        return tete;
    }
     
    //lire liste
    void lireList(Etudiant * tete)
    {
        while (tete != NULL){
                printf("%s\n", tete->nom);
                tete = tete->next;
            }
            printf("---------------\n");
    }
     
    //libère la mémoire
    void freeList(Etudiant * tete)
        {
            Etudiant * temp = NULL;
            while (tete != NULL)
            {
                temp = tete;
                tete = tete->next;
                printf("free(%s)\n", temp->nom);
                free(temp);
            }
            printf("---------------\n");
        }
     
    //insertion dans l'ordre alphabétique
    Etudiant * ajoutAlpha(Etudiant * tete,char inom[])
    {
        Etudiant *temp = tete;
        Etudiant *elt = NULL;
        elt = malloc(sizeof(Etudiant));
        if (elt == NULL)//test si allocation a fonctionné
            {
                printf("Mémoire insuffisante");
                exit(99);
            }
        strcpy(elt->nom,inom);
        if (temp == NULL) // si la liste est vide on renvoie elt
            return elt;
        else if( strcmp(temp->nom,inom) > 0 ) // si l'élément est a insérer en premier
        {
            elt->next=tete;
            return elt;
        }
        else // si l'élément est a insérer au milieu ou a la fin
        {
            while ( temp->next != NULL && strcmp(temp->next->nom,inom) < 0 )  // on trouve l'endroit
            {
               temp = temp->next;
            }
            elt->next = temp->next;
            temp->next = elt;
        }
        return tete;
    }
    Et mon main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "enum.h"
     
     
     
    int main()
    {
        Etudiant *teteListe = NULL, *maillon = NULL;
     
        teteListe = ajoutAlpha(teteListe,"Fred");
     
        //maillon = creationMaillon("Fred");
     
        //teteListe = insertionTete(teteListe, maillon);
     
        lireList(teteListe);
     
        teteListe = ajoutAlpha(teteListe,"Zoe");
     
        lireList(teteListe);
     
        freeList(teteListe);
     
        return 0;
    }

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Quand on passe d'une liste vide à une liste à un unique élément, le champ elt->next n'est pas initialisé, il faut le mettre à NULL.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Bonjour,

    Quand on passe d'une liste vide à une liste à un unique élément, le champ elt->next n'est pas initialisé, il faut le mettre à NULL.
    Je vais passer pour un boulet...
    Je comprends le principe, mais je ne vois pas où le mettre?
    Avant le return elt;

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Cisman Voir le message
    Je comprends le principe, mais je ne vois pas où le mettre?
    Avant le return elt;
    Bonjour

    C'est quand tu crées ton maillon que tu remplis tous ses champs (donc y compris le next).
    Ensuite, tu places ton maillon dans la liste donc là le next peut changer... ou pas.

    Le problème, c'est que tu as une fonction "creationMaillon" qui crée le maillon, et une autre "ajouterAlpha" qui, elle aussi, crée un maillon. C'est pas bon. Tu ne dois avoir qu'une seule fonction qui effectue une seule tâche, et ensuite tu appelles les fonctions adéquates.
    Donc avec une fonction "creationMaillon", et une autre "insertionMaillon" ça doit suffire.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour



    Le problème, c'est que tu as une fonction "creationMaillon" qui crée le maillon, et une autre "ajouterAlpha" qui, elle aussi, crée un maillon. C'est pas bon. Tu ne dois avoir qu'une seule fonction qui effectue une seule tâche, et ensuite tu appelles les fonctions adéquates.
    J'avais fait la Fct crationMaillon avant. Mon but c'est de n'utiliser que la fonction ajouterAlpha(), pour créer et insérer directement au bon endroit. C'est là que je bloque quand je dois mettre mon maillon en premier dans la liste.

  6. #6
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    Etudiant * ajoutAlpha(Etudiant * tete,char inom[])
    {
        Etudiant *temp = tete;
        Etudiant *elt = NULL;
        elt = malloc(sizeof(Etudiant));
        if (elt == NULL)//test si allocation a fonctionné
            {
                printf("Mémoire insuffisante");
                exit(99);
            }
        strcpy(elt->nom,inom);
        if (temp == NULL) // si la liste est vide on renvoie elt
        {
            elt->next = NULL;
            return elt;
        }
     
        else if( stricmp(temp->nom,inom) > 0 ) // si l'élément est a insérer en premier
        {
            elt->next=tete;
            return elt;
        }
        else // si l'élément est a insérer au milieu ou a la fin
        {
            while ( temp->next != NULL && stricmp(temp->next->nom,inom) < 0 )  // on trouve l'endroit
            {
               temp = temp->next;
            }
            elt->next = temp->next;
            temp->next = elt;
        }
        return tete;
    }
    Trouvé et je fait srticmp plutôt que strcmp. ça règle le problème majuscule minuscule.
    Bon maintenant, je m'attaque à un tri pour pouvoir afficher mes étudiants par ordre de résultats.

    Merci pour le coup de main.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Cisman Voir le message
    Merci pour le coup de main.
    Mouais.
    Quand on te donne des conseils, c'est parce qu'on sait que ce sera mieux (plus élégant, plus simple à relire, plus modulaire) ainsi...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct Etudiant {
    	char nom[25];
    	struct Etudiant *next;//pointeur vers la structure Etudiant suivante
    } Etudiant;
     
    //creation de maillon
    Etudiant *creationMaillon(char[]);
     
    //lire liste
    void lireList(Etudiant*);
     
    //libère mémoire
    void freeList(Etudiant*);
     
    //insertion dans l'ordre alphabétique
    void ajoutAlpha(Etudiant**, Etudiant*);
     
    //creation de maillon et hardcodage du nom
    Etudiant *creationMaillon(char nom[]) {
    	Etudiant *maillon = NULL;
    	maillon = malloc(sizeof(Etudiant));
    	if (maillon == NULL) {
    		printf("Mémoire insuffisante");
    		return NULL;
    	}
    	strcpy(maillon->nom, nom);				// sprintf pff !!!
    	maillon->next = NULL;
    	return maillon;
    }
     
    //lire liste
    void lireList(Etudiant *tete) {
    	while (tete != NULL){
    		printf("0x%04x, %s (0x%04x)\n", tete, tete->nom, tete->next);
    		tete=tete->next;
    	}
    	printf("---------------\n");
    }
     
    //libère la mémoire
    void freeList(Etudiant *tete) {
    	Etudiant *temp = NULL;
    	while (tete != NULL) {
    		temp = tete;
    		tete = tete->next;
    		printf("free(0x%04x (%s))\n", temp, temp->nom);
    		free(temp);
    	}
    	printf("---------------\n");
    }
     
    void ajoutAlpha(Etudiant **tete, Etudiant *item)
    {
    	// Si liste vide
    	if (*tete == NULL) {
    		*tete=item;
    		return;
    	}
     
    	Etudiant *avant;
    	Etudiant *apres;
     
    	// Positionnement pointeurs avant et après
    	for (avant=NULL, apres=(*tete); apres != NULL && strcmp(apres->nom, item->nom) < 0; avant=apres, apres=apres->next);
     
    	// L'item à insérer vient forcément avant le "après" (y compris si "apres" est NULL donc en dernier)
    	item->next=apres;
     
    	// Si on a un "avant"
    	if (avant)
    		// Il vient alors juste avant l'item à insérer
    		avant->next=item;
    	else
    		// On est en début de liste
    		(*tete)=item;
    }
     
    int main(int argc, char *argv[]) {
    	Etudiant *teteListe = NULL;
    	char **pt;
     
    	for (pt=&argv[1]; *pt; pt++)
    		ajoutAlpha(&teteListe, creationMaillon(*pt));
    	lireList(teteListe);
    	freeList(teteListe);
     
    	return 0;
    }
    C'est pas plus simple ainsi plutôt que ton code où tu répètes chaque test à m'en faire saigner les yeux ???

    Tu lances ce programme en lui passant en paramètre tes noms à insérer. Quel que soit l'ordre de tes noms, ils réapparaitront par ordre alphabétique.

    Sinon bien entendu, tu peux utiliser ton jeu de tests "Fred" et "Zoe"...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
    	Etudiant *teteListe = NULL;
     
    	ajoutAlpha(&teteListe, creationMaillon("Fred"));
    	ajoutAlpha(&teteListe, creationMaillon("Zoe"));
    	lireList(teteListe);
    	freeList(teteListe);
     
    	return 0;
    }

    Maintenant, pour éviter ce double pointeur Etudiant **tete, ben tu pourrais rajouter une structure dédiée à la liste elle-même. Cette structure contiendrait donc forcément la tête au départ; mais pourrait ensuite évoluer et englober le nombre d'éléments, un pointeur sur l'élément en cours de traitement, bref plein de trucs auquel tu ne penses pas immédiatement mais qui peuvent s'avérer utiles...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct {
    	Etudiant *tete;
    } t_liste;			// Les types persos commencent par "t_" par convention
     
    void initListe(t_liste *l) {
    	l->tete=NULL;
    }

    Ainsi, ton code complet (avec rajout du nb d'éléments) devient ceci
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
     
    typedef struct s_etudiant {
    	char nom[25];
    	struct s_etudiant *next;//pointeur vers la structure Etudiant suivante
    } t_etudiant;
     
    typedef struct {
    	t_etudiant *tete;
    	size_t nb;
    } t_liste;
     
    void initListe(t_liste*);
     
    //creation de maillon
    t_etudiant *creationMaillon(char[]);
     
    //lire liste
    void lireList(t_liste*);
     
    //libère mémoire
    void freeList(t_liste*);
     
    //insertion dans l'ordre alphabétique
    void ajoutAlpha(t_liste*, t_etudiant*);
     
    // Initialisation de liste
    void initListe(t_liste *l) {
    	l->tete=NULL;
    	l->nb=0;
    }
     
    //creation de maillon et hardcodage du nom
    t_etudiant *creationMaillon(char nom[]) {
    	t_etudiant *maillon = NULL;
    	maillon = malloc(sizeof(t_etudiant));
    	if (maillon == NULL) {
    		printf("Mémoire insuffisante");
    		return NULL;
    	}
    	strcpy(maillon->nom, nom);
    	maillon->next=NULL;
    	return maillon;
    }
     
    //lire liste
    void lireList(t_liste *l) {
    	printf("Lecture 0x%04x (0x%04x) - nb=%u\n", l, l->tete, l->nb);
    	t_etudiant *pt;
    	for (pt=l->tete; pt != NULL; pt=pt->next)
    		printf("0x%04x, %s (0x%04x)\n", pt, pt->nom, pt->next);
    	printf("---------------\n");
    }
     
    //libère la mémoire
    void freeList(t_liste *l) {
    	t_etudiant *avant;
    	t_etudiant *apres;
    	apres=l->tete;
    	while (apres != NULL) {
    		avant=apres;
    		apres=apres->next;
    		printf("free(0x%04x (%s))\n", avant, avant->nom);
    		free(avant);
    	}
    	initListe(l);
    	printf("---------------\n");
    }
     
    void ajoutAlpha(t_liste *l, t_etudiant *item) {
    	// On a un élément de plus
    	l->nb++;
     
    	// Si liste vide
    	if (l->tete == NULL) {
    		l->tete=item;
    		return;
    	}
     
    	t_etudiant *avant;
    	t_etudiant *apres;
     
    	// Positionnement pointeurs avant et après
    	for (avant=NULL, apres=l->tete; apres != NULL && strcmp(apres->nom, item->nom) < 0; avant=apres, apres=apres->next);
     
    	// L'item à insérer vient forcément avant le "après"
    	item->next=apres;
     
    	// Si on a un "avant"
    	if (avant)
    		// Il vient alors juste avant l'item à insérer
    		avant->next=item;
    	else
    		// On est en début de liste
    		l->tete=item;
    }
     
    int main(int argc, char *argv[]) {
    	t_liste liste;
    	initListe(&liste);
    	char **pt;
     
    	for (pt=&argv[1]; *pt; pt++)
    		ajoutAlpha(&liste, creationMaillon(*pt));
    	lireList(&liste);
    	freeList(&liste);
     
     
    	lireList(&liste);			// Juste pour le fun (tu remarqueras que "freeList" réinitialise la liste à l'issue)...
     
    	return 0;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct Etudiant {
    	char nom[25];
    	struct Etudiant *next;//pointeur vers la structure Etudiant suivante
    } Etudiant;
     
    //creation de maillon
    Etudiant *creationMaillon(char[]);
     
    //lire liste
    void lireList(Etudiant*);
     
    //libère mémoire
    void freeList(Etudiant*);
     
    //insertion dans l'ordre alphabétique
    void ajoutAlpha(Etudiant**, Etudiant*);
     
    //creation de maillon et hardcodage du nom
    Etudiant *creationMaillon(char nom[]) {
    	Etudiant *maillon = NULL;
    	maillon = malloc(sizeof(Etudiant));
    	if (maillon == NULL) {
    		printf("Mémoire insuffisante");
    		return NULL;
    	}
    	strcpy(maillon->nom, nom);				// sprintf pff !!!
    	maillon->next = NULL;
    	return maillon;
    }
     
    //lire liste
    void lireList(Etudiant *tete) {
    	while (tete != NULL){
    		printf("0x%04x, %s (0x%04x)\n", tete, tete->nom, tete->next);
    		tete=tete->next;
    	}
    	printf("---------------\n");
    }
     
    //libère la mémoire
    void freeList(Etudiant *tete) {
    	Etudiant *temp = NULL;
    	while (tete != NULL) {
    		temp = tete;
    		tete = tete->next;
    		printf("free(0x%04x (%s))\n", temp, temp->nom);
    		free(temp);
    	}
    	printf("---------------\n");
    }
     
    void ajoutAlpha(Etudiant **tete, Etudiant *item)
    {
    	// Si liste vide
    	if (*tete == NULL) {
    		*tete=item;
    		return;
    	}
     
    	Etudiant *avant;
    	Etudiant *apres;
     
    	// Positionnement pointeurs avant et après
    	for (avant=NULL, apres=(*tete); apres != NULL && strcmp(apres->nom, item->nom) < 0; avant=apres, apres=apres->next);
     
    	// L'item à insérer vient forcément avant le "après" (y compris si "apres" est NULL donc en dernier)
    	item->next=apres;
     
    	// Si on a un "avant"
    	if (avant)
    		// Il vient alors juste avant l'item à insérer
    		avant->next=item;
    	else
    		// On est en début de liste
    		(*tete)=item;
    }
     
    int main(int argc, char *argv[]) {
    	Etudiant *teteListe = NULL;
    	char **pt;
     
    	for (pt=&argv[1]; *pt; pt++)
    		ajoutAlpha(&teteListe, creationMaillon(*pt));
    	lireList(teteListe);
    	freeList(teteListe);
     
    	return 0;
    }
    C'est pas plus simple ainsi plutôt que ton code où tu répètes chaque test à m'en faire saigner les yeux ???

    Désolé pour tes yeux, je ne suis qu'un jeune apprenti
    Mais je ne demande qu'à apprendre, et justement, j'ai quelques question sur ton code.

    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ajoutAlpha(Etudiant**, Etudiant*);
    le ** pour moi c'est un pointeur de pointeur correct? mais pq?

    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    maillon = malloc(sizeof(Etudiant));
    	if (maillon == NULL)
    	{
    		printf("Mémoire insuffisante");
    		return NULL;
    	}
    ça change quoi un return NULL; par rapport à un return 99; ?

    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //lire liste
    void lireList(Etudiant *tete)
    {
    	while (tete != NULL){
    		printf("0x%04x, %s (0x%04x)\n", tete, tete->nom, tete->next);
    		tete=tete->next;
    	}
    	printf("---------------\n");
    }
    à quoi ça sert: "0x%04x"?

    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char *argv[])
    argc: j'ai vu ça sur un IDE sur mac, de nouveau ça sert à quoi?

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Cisman Voir le message
    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ajoutAlpha(Etudiant**, Etudiant*);
    le ** pour moi c'est un pointeur de pointeur correct? mais pq?
    Parce que "liste" est un "Etudiant étoile".
    Ma fonction ajoutAlpha() est suceptible de modifier la liste reçue. Or, en C, toute fonction qui modifie quelque chose doit recevoir l'adresse de ce quelque chose (ce que je fais dans le main() quand je lui passe "&liste").
    Et l'adresse d'un "truc" c'est un "truc étoile". Donc "liste" étant un "Etudiant étoile", l'adresse de "liste" (l'adresse d'un "Etudiant étoile") c'est un "Etudiant étoile étoile".

    Citation Envoyé par Cisman Voir le message
    ça change quoi un return NULL; par rapport à un return 99; ?
    Tu n'avais pas écrit "return 99" mais "exit(99)" et là ce n'est pas pareil. On ne fait jamais quitter un programme sur une erreur. Il peut y avoir des trucs préalablement ouverts/alloués/connectés qu'il faut alors fermer/libérer/déconnecter. Donc la bonne attitude, c'est "si une fonction critique échoue dans une action, faire quitter la fonction (et non le programme) avec une valeur "spéciale échec". Et dans la manipulation de pointeurs, le "NULL" est une valeur "spéciale échec" (regarde le retour de malloc()). Charge à l'appelant de gérer ce retour s'il le souhaite.
    Normallement j'aurais même dû supprimer le printf("Pas assez de mémoire") selon la philisophie de la séparation des actions (d'un côté les ressources, de l'autre côté l'affichage) mais bon, pour ce petit TP je me suis dit que ça pouvait rester.

    Citation Envoyé par Cisman Voir le message
    à quoi ça sert: "0x%04x"?
    J'affiche toujours mes pointeurs au format hexadécimal sur 4 digits ("04x"). Déjà je trouve plus pratique de lire "ae0f" que "44559". Surtout que la valeur exacte je m'en fouts car ici je regarde juste si ne "next" de l'item1 correspond réellement à l'adresse de l'item2).
    De plus c'est encore plus élégant dans le cas de progressions binaires (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 par rapport à 1, 2, 4, 8, 16, 32, 64, 128).
    Et je fais précéder cet affichage d'un "0x" car c'est la convention usuelle des nombres hexa en C.

    Citation Envoyé par Cisman Voir le message
    code c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char *argv[])
    argc: j'ai vu ça sur un IDE sur mac, de nouveau ça sert à quoi?
    Ca te permet de prendre en considération les arguments de ton programme (des mots que tu places entre le nom du programme et le <return> ; mots que le programme peut ensuite utiliser s'il sait les récupérer). Exemple, ton programme se nomme "toto" ben tu peux très bien appeler "toto Pierre Paul Jacques" en ayant envie que le programme récupère ce "Pierre", "Paul" et "Jacques" pour les traiter (ici plus pratique par exemple que de coder "Fred" et "Zoe" en dur et recompiler chaque fois que tu veux changer).

    Ben quand tu appelles un programme avec (par exemple) 3 arguments, le premier paramètre de ton main() (conventionnellement nommé "argc" pour "arg count") contient le nombre d'arguments (ici 3). Ce nombre étant entier, il est alors stocké dans un "int".
    Et le second (arg values) contient les différents arguments. Chaque argument étant une chaine, et étant donné qu'il y a plusieurs chaines, ce paramètre est alors un "tableau de chaines" ou plus précisément un "tableau de pointeurs", chaque pointeur pointant vers le paramètre de son rang (le premier sur "Pierre", le second sur "Paul" et le 3° sur "Jacques"). Et le 4° contient toujours NULL (permet de savoir quand s'arrêter quand on les traite par une boucle).

    Ainsi, en écrivant char **pt; for (pt=&argv[1]; *pt; pt++) je définis un pointeur qui ira traiter chaque argv[x]. Je place le pointeur sur le premier argument (donc l'adresse de argv[1], qu'on peut aussi écrire argv + 1), puis je teste si son contenu n'est pas NULL (j'aurais pu écrire effectivement *pt != NULL mais c'est la force de l'habitude) puis j'incrémente pt qui passe alors sur l'argument suivant et etc.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Merci pour toutes ces explications

  11. #11
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2017
    Messages : 176
    Points : 99
    Points
    99
    Par défaut
    Bon ben maintenant, que j'avance sur d'autres fonctions et que je rajoute des étudiants, je me rend compte que s'ils ont le même nom, l'insertion en ordre Alpha ne fonctionne plus.

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Cisman Voir le message
    je me rend compte que s'ils ont le même nom, l'insertion en ordre Alpha ne fonctionne plus.
    Sois content

    Tu vas t'amuser à faire une liste chaînée de noms de famille triée et, pour chaque nom/ maillon avoir une liste chaînée de prénoms également triée

  13. #13
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Cisman Voir le message
    Bon ben maintenant, que j'avance sur d'autres fonctions et que je rajoute des étudiants, je me rend compte que s'ils ont le même nom, l'insertion en ordre Alpha ne fonctionne plus.
    Et t'as pas trouvé tout seul ??? C'est pourtant pas faute de t'avoir vanté les principes de la programmation modulaire. L'insertion ne se fait qu'à un endroit. C'est donc à cet endroit qu'il faut chercher !!!

    Faut rajouter un critère dans la fonction ajoutAlpha. Si deux noms identiques alors rajout d'un test sur le prénom...
    for (avant=NULL, apres=(*tete); apres != NULL && strcmp(apres->nom, item->nom) < 0 || (strcmp(apres->nom, item->nom) == 0 && strcmp(apres->prenom, item->prenom) < 0); avant=apres, apres=apres->next);.

    Ceci dit, le test commence à devenir un peu complexe. Et si demain tu t'aperçois que tu as aussi un souci sur des prénoms égaux et que tu veux rajouter un 3° critère ça deviendra illisible.

    Donc on peut le réécrire en plus explicite/modulaire...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (avant=NULL, apres=(*tete); apres != NULL; apres=apres->next) {
    	if (strcmp(apres->nom, item->nom) > 0) break;
    	if (strcmp(apres->nom, item->nom) == 0 && strcmp(apres->prenom, item->prenom) > 0) break;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ou mieux, faire une fonction ComparerEtudiants() qui teste un à un tous les champs permettant de l'identifier de manière unique tout en maintenant l'ordre alphabétique.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2013] Ordre alphabétique dans une liste déroulante
    Par maringot dans le forum IHM
    Réponses: 18
    Dernier message: 12/10/2017, 08h51
  2. [DATA] Classer les variables par ordre alphabétique dans une table
    Par alers dans le forum SAS Base
    Réponses: 5
    Dernier message: 11/03/2015, 14h40
  3. [AC-2007] Ordre alphabétique dans une requête qui calcule les E/S par mois
    Par Kisty10 dans le forum Requêtes et SQL.
    Réponses: 14
    Dernier message: 07/05/2011, 18h47
  4. Tie par ordre alphabétique d'une liste
    Par Freygolow dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 18/05/2007, 00h00
  5. Ordre alphabétique dans une liste déroulante
    Par Z[ee]k dans le forum Access
    Réponses: 2
    Dernier message: 30/05/2006, 15h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo