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 :

Algo de tri


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut Algo de tri
    Bonjour
    J aimerais jsute que vous me disiez si mon prog est bien commente, si vous ne trouvez pas de bugs , si il y a moyen de l opimiser...enfin si vous pouviez prendre le role d inspecteur des travaux finis !

    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
    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
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct elem {
                          char valeur[11]; 
                          struct elem *suivant;
                        }element;
    typedef element* liste;
     
    /***********************Crée une nouvelle liste ou ajoute un element***************************/
     
    liste ajoutqueue(liste l,char valeur[]) 
    {  
        element *e; 			//Element servant a parcourir la liste
        element *nouv;			//Nouvel element
        nouv=(element*)malloc(sizeof(element)); //Allocation pour ce nouvel element 
        strcpy(nouv->valeur,valeur);//copie de la valeur entrée par user ds le nouvel element
        nouv ->suivant=NULL;	    //pas d'elements apres nouv
        if (l!=NULL)				//Si la liste existe, on ajoute le nouvel element a la fin
        {
            e=l;
            while (e->suivant != NULL)
                e=e->suivant;
                e->suivant =nouv;      
        }
        else					  //Si la liste n'existe pas,la liste commence avec nouv 
            l=nouv;
        return l; 				 //On retourne la liste
    }
     
    /**********************************Convertit un caractere en entier****************************/
     
    int convertir(char valeur)		
    {
        int entier;
     
        if (valeur=='0')
            entier=0;
        else if (valeur=='1')
            entier=1;
        else if (valeur=='2')
            entier=2;
        else if (valeur=='3')
            entier=3;
        else if (valeur=='4')
            entier=4;
        else if (valeur=='5')
            entier=5;
        else if (valeur=='6')
            entier=6;
        else if (valeur=='7')
            entier=7;
        else if (valeur=='8')
            entier=8;
        else if (valeur=='9')
            entier=9;
        else if ((valeur=='a')||(valeur=='A'))
            entier=10;
        else if ((valeur=='b')||(valeur=='B'))
            entier=11;
        else if ((valeur=='c')||(valeur=='C'))
            entier=12;
        else if ((valeur=='d')||(valeur=='D'))
            entier=13;
        else if ((valeur=='e')||(valeur=='E'))
            entier=14;
        else if ((valeur=='f')||(valeur=='F'))
            entier=15;
     
        return entier;
    }
     
    /*********************************Efface la liste**********************************************/
     
    liste init (liste l)
    {
        element *e;
        while ((l !=NULL)&&(l->suivant!=NULL))
        {
            e=l;
            while((e->suivant)->suivant != NULL)
                e=e->suivant;
            free(e->suivant);//Libere la memoire
            e->suivant=NULL;
        }
        if (l!=NULL)
        {
            free(l);        //Libere la memoire
            l=NULL;
        }
        return l;
    }
     
    /********************************Supprime le dernier élément***********************************/
     
    liste suppr(liste l)
    {
        element *e;
        if ((l !=NULL)&&(l->suivant!=NULL))
        {
            e=l;
            while((e->suivant)->suivant != NULL)
                e=e->suivant;
            free(e->suivant);
            e->suivant=NULL;
        }
        else if (l!=NULL)
        {
            free(l);
            l=NULL;
        }
        return l;
    }
     
    /****************************Memorise la longueur de la valeur la plus longue******************/
     
    int calcullongueur(liste e)		
    {
        int max;
        max =strlen(e->valeur);		//Enregistre la longueur de la chaine sous un entier
        e=e->suivant;
        while (e !=NULL)
        {
            if (max<strlen(e->valeur))
                max=strlen(e->valeur);
            e=e->suivant;
        }
        return max;
    }
     
    /******************************************Tri la liste****************************************/
     
    liste tri(liste l,int base)		
    {
        int i,j,k,max;  
        max=calcullongueur(l);		//Trouve la longueur de la valeur maximum
        liste A[base+1]; 			
        element *e,*f;    		//e parcours la liste l, f parcours la liste d une ligne du tableau 
     
        for (i=0;i<max;i=i+1)	
        {        
            for (j=0;j<=base;j=j+1)	//Initialisation du tableau a NULL
                A[j]=NULL;
     
            e=l;
            while (e !=NULL)		//On parcours la liste
            {
                k=strlen(e->valeur);//On memorise la longueur de la chaine de caracteres coutante
                if (k<max)       //Si la valeur est plus petite que la longueur de la plus grande
                {
                    if (k-i>0) //Si il existe une case k-i
                    {
                        j=convertir(e->valeur[k-1-i]);//Convertit le caractere en entier
                        A[j+1]=ajoutqueue(A[j+1],e->valeur);//"Range" la valeur dans le tableau 
                    }
                    else 
                        A[0]=ajoutqueue(A[0],e->valeur);//On range une "sous liste" deja triée   
                }
                else
                {
                    j=convertir(e->valeur[max-1-i]);//Convertit le caractere en entier
                    A[j+1]=ajoutqueue(A[j+1],e->valeur);//"Range" la valeur dans le tableau 
                }
                e=e->suivant;
            }
     
            e=l;				/*A partir d'ici, on ecrase les valeurs de la liste l*/ 
            j=0;			
            while (e!=NULL)			
            {
                while (A[j]==NULL)		//On saute les lignes du tableau ne contenant pas de liste
                    j=j+1;
                f=A[j];                 
                strcpy(e->valeur,f->valeur);//On ecrase la valeur d'un element dans la liste l
                while ((f->suivant!=NULL))  //On parcours la liste d'une ligne d'un tableau
                {
                    f=f->suivant;
                    e=e->suivant;
                    strcpy(e->valeur,f->valeur);//On ecrase la valeur d'un element dans la liste l
                } 
                j=j+1; 
                e=e->suivant;         
            }
        } 
        return l;
    } 
     
    /****************************************Menu**************************************************/
     
    int main()
    {   
        int choix,base,i,entier,drapeau,c,k;
        char valeur[11],sortie;
        element *l=NULL;
        element *e;
        do
        {
            system("clear");	
            printf("Choisir la base(entre 2 et 16) :\n");
            scanf("%d",&base);
        }while((base<2)||(base>16));	//L'utilisateur ne peut rentre qu'une base compris entre 2 et 16
     
        do 
        {	
            system("clear");
            printf("1. Ajout d'une nouvelle valeur\n");
            printf("2. Suppression de la derniere valeur\n");
            printf("3. Affichage des valeurs entrées ou triées\n");
            printf("4. Trier la liste\n");
            printf("5. Reinitialise la liste\n");
            printf("6. Quitter\n");
            printf("Entrez votre choix :\n");
            scanf("%d",&choix);
            switch(choix)
            {    
                case 1 :
                    do
                    {     
                        do
                        {
                            while ((c = getchar()) != '\n' && c != EOF);//Mange le tampon
                            system("clear");
                            printf("Entrez la valeur : \n");
                            scanf("%s",valeur);
                            i=0;
                            k=strlen(valeur);
                            //Dans cette boucle, on controle si la valeur est correct
                            do	
                            {
                                drapeau=0;
                                entier=convertir(valeur[i]);
                                if (entier>=base)
                                {
                                    drapeau=1;
                                    printf("Votre nombre n'appartient pas a la base choisie\n");
                                    printf("Entree pour continuer\n");
                                    getchar();
                                }
                                else if (k>10)
                                {
                                    drapeau=1;
                                    printf("Votre nombre est trop grand\n");
                                    printf("Entree pour continuer\n");
                                    getchar();
                                }
                                i=i+1;
                            }while ((drapeau==0)&&(valeur[i]!='\0'));
                            //Fin  de la boucle de verification
                        }while (drapeau==1);
                        l=ajoutqueue(l,valeur);//Ajout de la valeur a la liste
                        while ((c = getchar()) != '\n' && c != EOF);//Mange le tampon
                        printf("Entrez q pour quitter");
                        printf(",une autre touche pour entrer une nouvelle valeur\n");
                        sortie=getchar();
                    }while (sortie!='q');
                break;
     
                case 2 :
                    l=suppr(l);  //Supprime le dernier element
                break;
     
                case 3 :         //Affiche la liste
                    if (l!=NULL)
                    {
                        e=l;
                        system("clear");
                        while (e != NULL)
                        {
                            printf("%s\n",e->valeur);  
                            e=e->suivant;                                    
                        }
                    }
                    else
                    {
                        printf("Vous n'avez pas entrez de valeurs\n");
                    }
                    while ((c = getchar()) != '\n' && c != EOF);
                    printf("Entree pour continuer");
                    getchar();
                break;
     
                case 4 :              //tri la liste
                    if (l!=NULL)
                        l=tri(l,base);
                    else 
                    {
                        printf("Veuillez entrer des valeurs\n"); 
                        printf("Entree pour continuer");
                        while ((c = getchar()) != '\n' && c != EOF);
                        getchar();
                    }
                break;
     
                case 5 :              //Efface la liste
                    l=init(l);
                break;	 
            }
        }while (choix !=6);                    	
        return 0;
    }

  2. #2
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    J'ai pas tout regardé mais il y quelques petits trucs que je n'aime pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct elem { 
         char valeur[11]; 
         struct elem *suivant; 
    }element;
    J'ai l'habitude de ne jamais mettre de taille de tableau en dur, passe par un define, c'est plus propre ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     nouv=(element*)malloc(sizeof(element));
    Evite les casts.

    De plus, sur cette même ligne, teste la valeur de retour de ton malloc (si NULL tu fais quoi ?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     element *nouv;         //Nouvel element
    Trop de commentaire tue le commentaire ...

    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
    int convertir(char valeur)       
    { 
        int entier; 
     
        if (valeur=='0') 
            entier=0; 
        else if (valeur=='1') 
            entier=1; 
        else if (valeur=='2') 
            entier=2; 
        else if (valeur=='3') 
            entier=3; 
        else if (valeur=='4') 
            entier=4; 
        else if (valeur=='5') 
            entier=5; 
        else if (valeur=='6') 
            entier=6; 
        else if (valeur=='7') 
            entier=7; 
        else if (valeur=='8') 
            entier=8; 
        else if (valeur=='9') 
            entier=9;
    Tu trouves pas que c'est un peu répétitif ! Ca serait pas mieux de tester si tu teste si ton nombre est entre 0 et 9 alors tu fais entier = valeur.

    Je suis pas sur que ça fonctionne sous toutes les plateformes ...

    return EXIT_SUCCESS; est peut être mieux ...

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Un début de commentaire (car ton code est très long) sur la fonction main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        char valeur[11],sortie;
        ....
        switch(choix) 
            {    
                case 1 :
                           .....
                           scanf("%s",valeur); 
                            i=0; 
                            k=strlen(valeur);
                            ....
                                else if (k>10)
                                {
    Trop tard! si k >10, le tableau valeur était trop petit et le programme est DETRUIT. Le test est inutile et ne protège rien. Tourne toi vers fgets à la place de scanf pour l'éviter.

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par PRomu@ld
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct elem { 
         char valeur[11]; 
         struct elem *suivant; 
    }element;
    J'ai l'habitude de ne jamais mettre de taille de tableau en dur, passe par un define, c'est plus propre ...
    Pourquoi ? Au contraire, je trouve que le seul endroit logique pour définir une taille de tableau est le tableau lui-même. Après, il peut y avoir des dépendences entre certaines tailles, et dans ce cas, oui, une macro ou un enum peuvent être interessants.

    Ca devient des cas particuliers.

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par PRomu@ld
    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
    int convertir(char valeur)       
    { 
        int entier; 
     
        if (valeur=='0') 
            entier=0; 
        else if (valeur=='1') 
            entier=1; 
        else if (valeur=='2') 
            entier=2; 
        else if (valeur=='3') 
            entier=3; 
        else if (valeur=='4') 
            entier=4; 
        else if (valeur=='5') 
            entier=5; 
        else if (valeur=='6') 
            entier=6; 
        else if (valeur=='7') 
            entier=7; 
        else if (valeur=='8') 
            entier=8; 
        else if (valeur=='9') 
            entier=9;
    Tu trouves pas que c'est un peu répétitif ! Ca serait pas mieux de tester si tu teste si ton nombre est entre 0 et 9 alors tu fais entier = valeur.
    A condition de retirer '0' !
    return EXIT_SUCCESS; est peut être mieux ...
    Pas mieux, non.

  6. #6
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut
    Citation Envoyé par PRomu@ld
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     nouv=(element*)malloc(sizeof(element));
    Evite les casts.

    De plus, sur cette même ligne, teste la valeur de retour de ton malloc (si NULL tu fais quoi ?)
    Qu est-ce que tu veux dire ? les casts et la valeur du malloc ...j ai du mal la, tu peux m expliciter ca ?

    Citation Envoyé par PRomu@ld

    Tu trouves pas que c'est un peu répétitif ! Ca serait pas mieux de tester si tu teste si ton nombre est entre 0 et 9 alors tu fais entier = valeur.
    J ai essayer de faire ce que tu m'as dis mais le test qui suit la conversion de ce caractere m'affiche "Votre nombre n'appartient pas a la base choisie", j en deduit que la conversion n'a pas fonctionné correctement...

    Citation Envoyé par diogene
    Trop tard! si k >10, le tableau valeur était trop petit et le programme est DETRUIT. Le test est inutile et ne protège rien. Tourne toi vers fgets à la place de scanf pour l'éviter.
    Ce test marche très bien! Tu as un exemple qui le ferait bugguer ?

    En tt cas merci à vous tous , c'est un de mes premiers programmes en C et j'aimerais partir sur de bonnes bases

  7. #7
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    J ai essayer de faire ce que tu m'as dis mais le test qui suit la conversion de ce caractere m'affiche "Votre nombre n'appartient pas a la base choisie", j en deduit que la conversion n'a pas fonctionné correctement...
    Moi j'en déduit que tu n'a pas suivit le conseil suivant :

    A condition de retirer '0' !

    Code:
    return 0;

    return EXIT_SUCCESS; est peut être mieux ...

    Pas mieux, non.
    En effet pas mieux mais plus compréhesible ...

    Pourquoi ? Au contraire, je trouve que le seul endroit logique pour définir une taille de tableau est le tableau lui-même. Après, il peut y avoir des dépendences entre certaines tailles, et dans ce cas, oui, une macro ou un enum peuvent être interessant.
    On ne s'est pas compris, ce que j'ai dis c'est qu'il n'est pas propre de mettre 11 directement comme ça, d'un point de vue maintenance du code, je ne trouve pas ça beau, en fait que tu initialises ton tableau avec une constante dans le code OK mais une constante définie dans un define :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #define TAILLE_MAX 10
     
    ...
     
    int tab[TAILLE_MAX];
    je trouve celà plus propre, d'autant plus que dans le code, il me semble que ce n'est pas le seul tableau qui est déclaré de la sorte, si on a besoin de changer la taille du tableau, il faudra la changer à chaque fois, alors qu'avec ma méthode, il ne faut plus que la changer dans le define ...

    Qu est-ce que tu veux dire ? les casts et la valeur du malloc ...j ai du mal la, tu peux m expliciter ca ?
    Tu n'a pas à effectuer une conversion de type au retour de ta fonction malloc.

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par PRomu@ld
    Pourquoi ? Au contraire, je trouve que le seul endroit logique pour définir une taille de tableau est le tableau lui-même. Après, il peut y avoir des dépendences entre certaines tailles, et dans ce cas, oui, une macro ou un enum peuvent être interessants.
    On ne s'est pas compris, ce que j'ai dis c'est qu'il n'est pas propre de mettre 11 directement comme ça,
    C'est bien ce que j'avais compris.
    d'un point de vue maintenance du code, je ne trouve pas ça beau, en fait que tu initialises ton tableau avec une constante dans le code OK mais une constante définie dans un define :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #define TAILLE_MAX 10
     
    ...
     
    int tab[TAILLE_MAX];
    Pourquoi ajouter du code ?
    ca me va.

    Si je veux le nombre d'élements, je fais sizeof tab / sizeof *tab, ou j'utilise la macro 'canonique'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define NB_ELEM(a) (sizeof(a) / sizeof *(a))
    Le problème de la macro, c'est que, la flemmardise aidant, on va créer des dépendences externes qui font que le code ne sera pas souple. A la limite, une taille fixe se tableau définie par une macho placée dans un header public va se retrouver compilée dans une bibliothèque avec la mention 'ne pas modifier' dans le header. L'utilisateur perd donc en souplesse. C'est de la mauvaise conception.

    L'important est que la définition soit unique. Pour les tableaux, elle doit être la plus applicative possible, tout les code qui utilise des données dans un tableau devrait recevoir les informations "T *addr, size_t number".

    D'autre part, si on croit régler le problème de
    int a[123];
    char b[123][456];
    float c[123];
    en remplaçant 123 par une macro, on se met probablement le doigt dans l'oeil. La réponse est sans doute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct
    {
       int a;
       char b[456];
       float c;
    }
    mydata [123];

  9. #9
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut
    Citation Envoyé par Treuze
    J ai essayer de faire ce que tu m'as dis mais le test qui suit la conversion de ce caractere m'affiche "Votre nombre n'appartient pas a la base choisie", j en deduit que la conversion n'a pas fonctionné correctement...
    Citation Envoyé par PRomu@ld
    Moi j'en déduit que tu n'a pas suivit le conseil suivant :

    A condition de retirer '0' !
    Si si je l ai fait mais c'est peut etre le fait de mettre un caractere egale a un entier non ? (e->valeur :caractere , entier est un entier)

  10. #10
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    diogene a écrit:
    Trop tard! si k >10, le tableau valeur était trop petit et le programme est DETRUIT. Le test est inutile et ne protège rien. Tourne toi vers fgets à la place de scanf pour l'éviter.
    Ce test marche très bien! Tu as un exemple qui le ferait bugguer ?
    Il suffit que l'opérateur tape au clavier plus de 10 caractères pour avoir un débordement sur valeur et la zone mémoire derriere valeur est détruite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char valeur[11],
    ....
    scanf("%s",valeur);
    ....
    k=strlen(valeur);
    ....
     else if (k>10) ....
    Si il y avait à cet endroit des choses "importantes", c'est foutu. Ceci peut avoir des conséquences visibles ou non, immédiates ou différées, des plantages aléatoires, .... En tous cas, le programme doit être considéré dans ce cas comme détruit. Le test posterieur sur k ne peut plus rien réparer.
    fgets permet de limiter le nombre de caractères lus et d'éviter cet écrasement.
    Sur les problèmes et dangers liés à scanf et les précautions à prendre, il y a des choses dans la FAQ

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Petirte remarque : ce code n'est pas clair (mais pas faux)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    liste init (liste l) 
    { 
        element *e; 
        while ((l !=NULL)&&(l->suivant!=NULL)) 
        { 
            e=l; 
            while((e->suivant)->suivant != NULL) 
                e=e->suivant; 
            free(e->suivant);//Libere la memoire 
            e->suivant=NULL; 
        }.....
    A l'intérieur de la boucle while l n'est pas modifié explicitement ce qui rend la condition de sortie obscure.
    Pourquoi ne pas détruire par la tête plutôt que par la queue ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    liste init (liste l) 
    { 
        element *e;
        while(l!= NULL)
         {
           e = l->suivant;
          free(l);
          l = e;
        }
        return NULL;
    }

  12. #12
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Treuze
    Si si je l ai fait mais c'est peut etre le fait de mettre un caractere egale a un entier non ? (e->valeur :caractere , entier est un entier)
    Tu ne serais pas en train de confondre = et == ? Montre le code qui ne fonctionne pas.

  13. #13
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    Pourquoi ajouter du code ?
    Code:
    int tab[10];

    ca me va.
    Alors là pas du tout d'accord ! On ajoute du code pour la maintenance.

    De plus, le problème que je veux mettre en valeur, n'est pas la récupération du nombre d'élément, mais FIXER le nombre d'élément. Celà fait parti des constantes du code.

    D'autre part, si on croit régler le problème de
    Citation:
    int a[123];
    char b[123][456];
    float c[123];

    en remplaçant 123 par une macro, on se met probablement le doigt dans l'oeil. La réponse est sans doute :
    Code:
    struct
    {
    int a;
    char b[456];
    float c;
    }
    mydata [123];
    Et bien tu ne m'enlèveras pas l'indée qu'avec un Define, ça serait plus simple. En génie logiciel, c'est tout simplement mieux.

    Le but du jeu n'est pas de produire le code le plus concit possible mais le plus facile à maintenir.

  14. #14
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par PRomu@ld
    Alors là pas du tout d'accord ! On ajoute du code pour la maintenance.
    Contradiction. Moins de code = moins de maintenance. Tu raisonnes de façon dogmatique. Essaye le pragmatisme...
    De plus, le problème que je veux mettre en valeur, n'est pas la récupération du nombre d'élément, mais FIXER le nombre d'élément. Celà fait parti des constantes du code.
    En quoi le 10 n'est pas fixé ? En quoi il n'est pas une constante du code ?
    Et bien tu ne m'enlèveras pas l'indée qu'avec un Define, ça serait plus simple. En génie logiciel, c'est tout simplement mieux.

    Le but du jeu n'est pas de produire le code le plus concis possible mais le plus facile à maintenir.
    Jusqu'à preuve du contraire,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct mes_donnees
    {
       int tab[10];
    };
    n'est pas plus difficile à maintenir que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /* mes_donnees.h */
    #define TAILLE 10
     
    struct mes_donnees
    {
       int tab[TAILLE];
    };
    J'ai du mal à suivre ton raisonnement...

  15. #15
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    Tu prends des exemples ou la constante est utilisé seulement une fois.

    Imagine qu'il y ait une vingtaine de tableau de même taille dans tout son code, il est tout de même plus judicieux de mettre des define plutôt que de mettre les valeurs directement dans le code. Si tu es sur à 100 % que ton code ne subira pas de changement (en gros que tu ne toucheras pas à la taille des tableaux), alors peut être que ta solution est plus appropriée (quoique), mais si tu dois la taille des tableaux doit être changée, je crois (dis moi si je me trompe) que la solution des define facilite la maintenance...

    Contradiction. Moins de code = moins de maintenance. Tu raisonnes de façon dogmatique. Essaye le pragmatisme...
    Pas d'accord, ce n'est pas parce que tu as plus de code que tu as plus de maintenance, justement l'ajout de code comme cité précédement peut faciliter la maintenance.

  16. #16
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par PRomu@ld
    Tu prends des exemples ou la constante est utilisé seulement une fois.
    Oui, et c'est souvent le cas. On ne définit pas un tableau plusieurs fois, surtout si il est dans une structure...
    Imagine qu'il y ait une vingtaine de tableau de même taille dans tout son code,
    Leurs tailles sont elle liées ? Si c'est le cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    T tab [123];
    <...>
     
    T tab_b[NELEM (tab)];
    T tab_c[NELEM (tab) * 2];
    T tab_c[(NELEM (tab) * 5) / 4];
    Si elles sont indépendentes, il n'y a aune raison d'avoir une seule constante...
    il est tout de même plus judicieux de mettre des define plutôt que de mettre les valeurs directement dans le code.
    C'est pas 'dans le code'. C'est au moment où l'on définit le tableau... Soit il est strictement local et sa taille est aussi locale, dans ce cas, la definition 'en dur' suffit largement, soit elle dépend de conditions externes, et dans ce cas, il vaut largement mieux utiliser un paramètre, la mémoire dynamique... Le problèmes de constantes globales, est que le code généré n'est pas souple, et que ça peut provoquer de graves problèmes si il est placé en bibliothèque. (J'ai déjà expliqué tout ça...)
    Si tu es sur à 100 % que ton code ne subira pas de changement (en gros que tu ne toucheras pas à la taille des tableaux), alors peut être que ta solution est plus appropriée (quoique), mais si tu dois la taille des tableaux doit être changée, je crois (dis moi si je me trompe) que la solution des define facilite la maintenance...
    AMA, si le problème se pose, il y a un grave problème de conception.

  17. #17
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par PRomu@ld
    Imagine qu'il y ait une vingtaine de tableau de même taille dans tout son code, il est tout de même plus judicieux de mettre des define plutôt que de mettre les valeurs directement dans le code.
    Si la constante a une signification particuliere (autre que "c'est la taille de tel tableau") et que la taille des differents tableaux decoule directement de cette signification. Oui utiliser un define est envisageable (meme si il est possible d'utiliser la taille d'un tableau pour definir les autres et ne rien perdre en maintenabilite).
    Si cette taille est utilise a differentes reprises (taille de tableau, offset dans un tableau ou un fichier, etc.), dans differentes fonctions et fichiers ou si il est necessaire de la rendre disponible a un eventuel appelant dans le cas d'une bibliotheque (et a condition que dans tout ces cas elle corresponde a la meme signification bien precise), l'utilisation d'un define peut etre un choix judicieux (meme si ceci peut poser probleme, notamment dans le cas d'une bibliotheque).
    Par contre si la constante ne correspond a rien de concret ou si les differents tableaux ont la meme taille "par hasard" (c'est a dire si les tailles n'ont pas de rapport entre elles si ce n'est partagee leur valeur) il n'est pas utile, et j'aurais meme tendance qu'il est nuisible, de declarer une constante.

    Citation Envoyé par PRomu@ld
    Si tu es sur à 100 % que ton code ne subira pas de changement (en gros que tu ne toucheras pas à la taille des tableaux), alors peut être que ta solution est plus appropriée (quoique), mais si tu dois la taille des tableaux doit être changée, je crois (dis moi si je me trompe) que la solution des define facilite la maintenance...
    Idealement dans un code bien ecrit, la taille n'est exprime qu'une seule fois lors de la creation du tableau. Lors des autres utilisation elle soit recalcule (sizeof) soit lu dans une variable "taille" (allocation dynamique, parametre d'une fonction). Partant de la je ne vois pas en quoi l'utilisation d'un define facilite la maintenance. J'aurais meme tendance a penser le contraire car bien souvent les constante sont defini en debut de l'unite de compilation voir dans un header et il faut donc lorsque l'on souhaite modifier la taille d'un tableau rechercher le define correspond et le modifier plutot que de modifier la definition du tableau.

Discussions similaires

  1. Algo de tri par liste chainée
    Par Treuze dans le forum C
    Réponses: 3
    Dernier message: 30/12/2005, 14h05
  2. algo de tri gérant les exaequo
    Par tomy29 dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 13/10/2005, 13h54
  3. quel est le meilleur algo de tri de liste ?
    Par sony351 dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 24/07/2005, 02h00
  4. algo de tri
    Par el toro diablo dans le forum Algorithmes et structures de données
    Réponses: 16
    Dernier message: 05/11/2003, 08h43
  5. Algo de tri, extension
    Par Mouse dans le forum Langage SQL
    Réponses: 5
    Dernier message: 27/02/2003, 00h14

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