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 :

problème d'affectation de tableau ...


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut problème d'affectation de tableau ...
    Je vais encore me faire tirer les oreilles (n'est-ce pas Emmanuel )

    Je déclare ceci dans une fonction (peu importe) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *menu1[]=
    	 {" MENU GENERAL",
    	  "-============-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [E]ncodage (Competition / Concurent)",
    	  "- [S]uppression (Competition / Concurent)","",
    	  "- [Q]uitter","",
    	  "//"};

    Je déclare aussi ceci dans cette même fonction :


    Par la suite, je fais ceci :

    Je sais que normalement c'est non-autorisé en C d'affecter des tableaux de cette manière... Mais pourtant je n'ai pas d'erreur à la compilation.
    Par contre, j'ai des comportements assez bizarres lors de lexécution (mais je ne dis pas que ça vient de là ...).

    Ma question : Vaudrait-il mieux que je passe par qqch du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy(menu,menu1,sizeof(menu1));

    Merci d''avance !

  2. #2
    Membre habitué Avatar de .:morgoth:.
    Profil pro
    Inscrit en
    Février 2005
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 124
    Points : 132
    Points
    132
    Par défaut
    Tu peux aussi copier a la main par une iteration (for ou while) toutes les chaines contenues dans Menu1 vers Menu.

    Ca coutera pas plus de 2 lignes

  3. #3
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Pourquoi tu dis que ce n'est pas autorisé ? Si ça l'est.
    Ce n'est pas autorisé avec les tableaux qui ont une place reservée en mémoire lors de leur déclaration. Mais là, menu est un pointeur (sur pointeur) et non un tableau. Il peut recevoir n'importe quelle adresse du même type.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * ptr ;
    char chaine[20];
    strcpy(chaine,"Bonjour");
    ptr=chaine ;
    printf("%s\n",ptr);
    va afficher "Bonjour".
    T'as le droit d'affecter des adresses à un pointeur (c'est même leur but). Mais le problème (si on peut appeler ça un problème) c'est que si tu modifies ta chaine 'chaine' (dans l'exemple précédent), 'ptr' pointe vers la zone modifiée et est donc modifié lui aussi. Si tu fais un 'strcpy', tu copies la chaine à un autre endroit et donc une modification de l'originale n'affecte pas la copie.

    Nas'

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: problème d'affectation de tableau ...
    Citation Envoyé par Mike888
    Je vais encore me faire tirer les oreilles (n'est-ce pas Emmanuel )

    Je déclare ceci dans une fonction (peu importe) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *menu1[]=
    	 {" MENU GENERAL",
    	  "-============-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [E]ncodage (Competition / Concurent)",
    	  "- [S]uppression (Competition / Concurent)","",
    	  "- [Q]uitter","",
    	  "//"};

    Je déclare aussi ceci dans cette même fonction :


    Par la suite, je fais ceci :

    Jusque là, ça va.
    Je sais que normalement c'est non-autorisé en C d'affecter des tableaux de cette manière...
    Pas du tout. 'menu' est un pointeur, tu as parfaitement le droit de mettre l'adresse d'un tableau dans un pointeur du moment que le type est compatible, et c'est le cas.
    Par contre, j'ai des comportements assez bizarres lors de lexécution (mais je ne dis pas que ça vient de là ...).

    Ma question : Vaudrait-il mieux que je passe par qqch du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy(menu,menu1,sizeof(menu1));
    NON! C'est inutile (et dangereux si menu n'a pas été correctement initialisé). Montre la suite du code, c'est là qu'est le bug.

    Remarque sur la conception. Je crois deviner ce que tu veux faire. Ce n'est pas une bonne idée de mélanger les données fixes d'un menu et les données 'variables' (selections...) de celui-ci...

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par .:morgoth:.
    Tu peux aussi copier a la main par une iteration (for ou while) toutes les chaines contenues dans Menu1 vers Menu.
    Pourquoi faire ?

  6. #6
    Membre habitué Avatar de .:morgoth:.
    Profil pro
    Inscrit en
    Février 2005
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 124
    Points : 132
    Points
    132
    Par défaut
    Ben la on cherche bien a faire de la recopie d'un tableau vers un autre non ?
    Donc on peut tres bien copier une a une les chaines du tableau source vers le tableau cible meme si ce n'est pas tres propre ni optimisé.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par .:morgoth:.
    Ben la on cherche bien a faire de la recopie d'un tableau vers un autre non ?
    La demande du P.O. n'est pas claire !

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut Re: problème d'affectation de tableau ...
    Citation Envoyé par Mike888
    Par contre, j'ai des comportements assez bizarres lors de lexécution (mais je ne dis pas que ça vient de là ...).
    Quel est le comportement bizzard dont tu parle ?

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Merci de vous intéresser à mon problème !

    Je ne vais remettre ici l'entiereté du code (le projet contient pour le moment 6 fichiers .c et 5 .h et plus de 800 lignes de code ...).

    Par contre, voici l'exécutable : http://users.skynet.be/mickcauw/patinage.exe

    Voici également le fichier menu.c (celui qui cause problème) :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #include <ctype.h>
    #include <dos.h>
     
    #ifndef LIST_H
    #include "LIST.H"
    #endif
    #ifndef COMPET_H
    #include "COMPET.H"
    #endif
    #ifndef MENU_H
    #include "MENU.H"
    #endif
    #ifndef CONCUR_H
    #include "CONCUR.H"
    #endif
    #ifndef COMMUN_H
    #include "COMMUN.H"
    #endif
    void crecarval(char **men,char *chval,char csel)
    { int x=0,i=0;
      char *ptr;      
      do { if ((ptr=strchr(men[x],csel))!=NULL) {chval[i]=ptr[1];i++;}
           x++;
         }
      while (strcmp(men[x],"//"));
      chval[i]='\0';
    };
     
    void affich(char **men)
    { int i=0;
      clrscr();
      do { printf("%s\n",men[i]);i++;}
      while (strcmp(men[i],"//"));
      printf("\n");
      printf("Votre choix : ");
    };
     
    char choix(char *chval)
    { char c;
      int j,x,y,test;
      x=wherex();y=wherey();
      do
       { fflush(stdin);
         gotoxy(x,y);
         clreol();
         test=0;
         c=toupper(getche());
         for (j=0;j<strlen(chval);j++) if (c==chval[j]) test=1;
       }
      while (!test);
      return (c);
    };
     
    void fonctions(int nummenu1,char ch1,int *msuiv1,list *listcompet2,list *listconcur2)
    { switch(nummenu1)
       { case 1 : { switch(ch1)
    		 { case 'E' : *msuiv1=2;break;
    		   case 'S' : *msuiv1=3;break;
    		 };
    		break;
    	      }
         case 2 : { switch(ch1)
    		 { case 'C' : encodecompet(listcompet2);*msuiv1=2;break;
    		   case 'N' : encodeconcur(listconcur2);*msuiv1=2;break;
    		 };
    		break;
    	      }
         case 3 : { switch(ch1)
    		 { case 'C' : enlevecompet(listcompet2);*msuiv1=3;break;
    		   case 'N' : enleveconcur(listconcur2);*msuiv1=3;break;
    		 };
    		break;
    	      }
       }
    };
     
    void appelmenu(list *listcompet1,list *listconcur1)
    { int j,mprec=0,msuiv=1,nummenu=1;
      char ch,cs='[',*chvalide,**menu;
      char *menu1[]=
    	 {" MENU GENERAL",
    	  "-============-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [E]ncodage (Competition / Concurent)",
    	  "- [S]uppression (Competition / Concurent)","",
    	  "- [Q]uitter","",
    	  "//"};
      char *menu2[]=
    	 {" Encodage",
    	  "-========-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [C]ompetition",
    	  "- Co[N]curent","",
    	  "- [Q]uitter","",
    	  "//"};
      char *menu3[]=
    	 {" Suppression",
    	  "-===========-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [C]ompetition",
    	  "- Co[N]curent","",
    	  "- [Q]uitter","",
    	  "//"};
      clrscr();
      do
       { switch (nummenu)
          { case 0 : break;
             case 1 : menu=menu1;mprec=0;msuiv=1;break;
             case 2 : menu=menu2;mprec=1;msuiv=2;break;
             case 3 : menu=menu3;mprec=1;msuiv=3;break;
          }    
         if (nummenu)
          { for (j=0;j<3;j++) chvalide[j]=' ';
            crecarval(menu,chvalide,cs);
            affich(menu);
            ch=choix(chvalide);
            if (ch!='Q')
             { fonctions(nummenu,ch,&msuiv,listcompet1,listconcur1);
                nummenu=msuiv;
             }
            else nummenu=mprec;
          }              
       }
      while (ch!='Q' || mprec!=0);
    };

    Comme vous pouvez le voir, 4 fonctions différentes sont appellables ( encodage et suppression de compétition/concurent). Lorsque je les fais tourner seule (sans passer par menu.c), tout fonctionne bien. En passant par menu.c, et bien, je vous laisse découvrir ... (problèmes divers : changement de valeur de certaines variables, bugs en sortie de programme,...)
    Je suis persuadé que le problème se situe au niveau de cette affection de tableau de char. Mais pourquoi ???...

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Mike888
    Je ne vais remettre ici l'entiereté du code (le projet contient pour le moment 6 fichiers .c et 5 .h et plus de 800 lignes de code ...).
    Donne une url. Les plus courageux iront peut être voir...
    Par contre, voici l'exécutable : http://users.skynet.be/mickcauw/patinage.exe
    Certainement pas! Jamais d'exécutable. (Et puis exécutable sur quoi ?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #ifndef LIST_H
    #include "LIST.H"
    #endif
    L'interet de la protection est de la placer dans le header. Ca allège l'écriture :
    Des variables sont utilisées sans avoir été initialisées...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    main.c: In function `appelmenu':
    main.c:143: warning: `ch' might be used uninitialized in this function
    main.c:143: warning: `chvalide' might be used uninitialized in this function
    main.c:143: warning: `menu' might be used uninitialized in this function
    Notamment le pointeur 'chvalide' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     char *chvalide;
    <...>
          { for (j=0;j<3;j++) chvalide[j]=' ';
    Ca ne pardonne pas (comportement indéfini)

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Par rapport à tes deux dernières remarques (initialisation) :

    - Sachant que ch devra stocker un et un seul caractère, je suppose que je dois le déclarer ainsi :

    - Concernant menu et chvalide, je sais bien que je dois les initialiser; mais, étant donné que ces variables vont devoir etre réutilisées à maintes reprises, je dois également les réinitilaliser à "zéro" à chaque recommencement de la boucle ...
    Est-ce qu'une écriture de ce genre conviendrait ?


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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Mike888
    Par rapport à tes deux dernières remarques (initialisation) :

    - Sachant que ch devra stocker un et un seul caractère, je suppose que je dois le déclarer ainsi :
    Ca ne peut donc pas être une chaine (autre que vide). Pourquoi pas... J'espère que tu sais ce que tu fais...
    - Concernant menu et chvalide, je sais bien que je dois les initialiser; mais, étant donné que ces variables vont devoir etre réutilisées à maintes reprises,
    Peut importe. Il faut que la valeur initiale soit correcte, sinon, la première lecture invoque un comportement indéfini.
    je dois également les réinitilaliser à "zéro" à chaque recommencement de la boucle ...
    Est-ce qu'une écriture de ce genre conviendrait ?
    Non. Tu n'as toujours pas compris qu'un pointeur n'est pas un tableau. Quand tu définis
    c'est un pointeur non initialisé. IL EST INTERDIT DE L'UTILSER.
    On ne peut ni le passer à une fonction, ni le déréférencer. La seule chose autorisée est sa mise à jour :
    • par le retour de malloc()
    • par l'adresse d'un char (ou d'un tableau de char)
    • par la valeur d'un pointeur valide du même type.
    • par la valeur constante NULL (mais dans ce cas le pointeur ne peut pas être déréférencer. Certaines fonctions acceptent cette valeur sans broncher...

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Bon, j'ai modifié mon code, mais j'ai toujours des bugs ... Pourtant, je ne pense pas avoir laissé de comportements indé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
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #include <ctype.h>
    #include <dos.h>
     
    #ifndef LIST_H
    #include "LIST.H"
    #endif
    #ifndef COMPET_H
    #include "COMPET.H"
    #endif
    #ifndef MENU_H
    #include "MENU.H"
    #endif
    #ifndef CONCUR_H
    #include "CONCUR.H"
    #endif
    #ifndef COMMUN_H
    #include "COMMUN.H"
    #endif
    void crecarval(char **men,char *chval,char csel)
    { int x=0,i=0;
      char *ptr;      
      do { if ((ptr=strchr(men[x],csel))!=NULL) {chval[i]=ptr[1];i++;}
           x++;
         }
      while (strcmp(men[x],"//"));
      chval[i]='\0';
    };
     
    void affich(char **men)
    { int i=0;
      clrscr();
      do { printf("%s\n",men[i]);i++;}
      while (strcmp(men[i],"//"));
      printf("\n");
      printf("Votre choix : ");
    };
     
    void choix(char *chval,char *ch1)
    { int j,x,y,test;
      x=wherex();y=wherey();
      do
       { fflush(stdin);
         gotoxy(x,y);
         clreol();
         test=0;
         *ch1=toupper(getche());
         for (j=0;j<strlen(chval);j++) if (*ch1==chval[j]) test=1;
       }
      while (!test);  
    };
     
    void fonctions(int nummenu1,char ch1,int *msuiv1,list *listcompet2,list *listconcur2)
    { switch(nummenu1)
       { case 1 : { switch(ch1)
                         { case 'E' : *msuiv1=2;break;
                            case 'S' : *msuiv1=3;break;
                         };
                        break;
                      }
         case 2 : { switch(ch1)
                         { case 'C' : encodecompet(listcompet2);*msuiv1=2;break;
                            case 'N' : encodeconcur(listconcur2);*msuiv1=2;break;
                         };
                        break;
                      }
         case 3 : { switch(ch1)
                         { case 'C' : enlevecompet(listcompet2);*msuiv1=3;break;
                            case 'N' : enleveconcur(listconcur2);*msuiv1=3;break;
                         };
                        break;
                      }
       }
    };
     
    void appelmenu(list *listcompet1,list *listconcur1)
    { int j,mprec=0,msuiv=1,nummenu=1;
      char ch,cs='[',chvalide[3],**menu;
      char *menu1[]=
    	 {" MENU GENERAL",
    	  "-============-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [E]ncodage (Competition / Concurent)",
    	  "- [S]uppression (Competition / Concurent)","",
    	  "- [Q]uitter","",
    	  "//"};
      char *menu2[]=
    	 {" Encodage",
    	  "-========-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [C]ompetition",
    	  "- Co[N]curent","",
    	  "- [Q]uitter","",
    	  "//"};
      char *menu3[]=
    	 {" Suppression",
    	  "-===========-\n",
    	  "Choisissez parmi les options suivantes :","",
    	  "- [C]ompetition",
    	  "- Co[N]curent","",
    	  "- [Q]uitter","",
    	  "//"};
      clrscr();
      do
       { ch=' ';
         strcpy(chvalide,NULL);
         menu=NULL;
         switch (nummenu)
          { case 0 : break;
             case 1 : menu=menu1;mprec=0;msuiv=1;break;
             case 2 : menu=menu2;mprec=1;msuiv=2;break;
             case 3 : menu=menu3;mprec=1;msuiv=3;break;
          }    
         if (nummenu)
          { crecarval(menu,chvalide,cs);
             affich(menu);
             choix(chvalide,&ch);
             if (ch!='Q')
              { fonctions(nummenu,ch,&msuiv,listcompet1,listconcur1);
                 nummenu=msuiv;
              }
             else nummenu=mprec;
          }         
       }
      while (ch!='Q' || mprec!=0);
    };

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Mike888
    Bon, j'ai modifié mon code, mais j'ai toujours des bugs ... Pourtant, je ne pense pas avoir laissé de comportements indéfinis ...
    • Est-ce qu'on a pas déjà expliqué 3000 fois que fflush(stdin) invoquait un comportement indéfini ?
    • Je t'ai déjà dit que la place des gardes anti-inclusion multiples était dans les .h... Si tu ne tiens pas compte des remarques, pourquoi continuer à t'aider ? Si tu ne les comprends pas, pose des questions...
    • en principe, on ne met pas un strlen() dans la condition de test d'un boucle, à moins que celle-ci modifie la chaine. Ce n'est pas le cas ici (choix()).
    • Code : Sélectionner tout - Visualiser dans une fenêtre à part
            strcpy (chvalide, NULL);
      Je croyais pourtant avoir été clair... Puisque tu ne prends pas la peine d'ouvrir ton livre de C, je mets les points sur les i. Passer NULL à strcpy() invoque un comportement indéfini.

      Le code correct est

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Ecoute, faut pas croire que je ne lis pas tes remarques, elles sont tjs très instructives !...

    - A propos du fflush(stdin); ce sont mes profs qui recommandent de l'employer, alors moi, je ne sais plus ce que je dois faire ???... Qu'est-ce qu'il faudrait mettre à la place ?

    - A propos des #ifndef, j'ai galéré pendant des jours (et je suis loin d'avoir été le seul aux cours) là-dessus avant de plus ou moins obetnir qqch de correct. Effectivement, ca s'apparente bcp à du tatonnement ce que je fais, mais si tu voyais la pédagogie employée dans notre établissement, tu comprendrais vite ! Notre prof a vaguement évoqué le #ifndef lors d'un cours mais n'a pas expliqué son fonctionnement. Je te renvoie d'ailleurs sur notre forum à ce sujet : http://www.opensupport.be/phpBB2/vie...r=asc&&start=0

    - Pour le Strlen dans la condition de test, je ne savais pas; je vais modifier vite fait.

    - Et concernant le NULL, je pensais que ce que tu disais s'appliquait pour **menu et non chvalide[]. Je vais donc modifier aussi !

    Voilà

  16. #16
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Bon, encore une question :

    Lorsque j'attends de l'utilisateur qu'il tape au clavier (via un gets) une chaine de caractere (qui doit faire 5 caractères pour etre validée )

    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
     
    void enlevecompet(list *listcompet3)
    { int cpt,i,test,x,y;
      char *chaine;
      clrscr();
      printf("Il y a actuellement %d competitions enregistrees.",listcompet3->nbcell);
      printf("\nVous allez a present supprimer une competition.");
      printf("\n\nProcedure :");
      printf("\n-----------");
      printf("\n\n* Veuillez simplement rentrer le matricule");
      printf("\n  de la competition que vous desirez supprimer.");
      printf("\n\n\n Le matricule => ");
      x=wherex();y=wherey();
      do
       { gotoxy(x,y);
         clreol();
         //fflush(stdin);
         gets(chaine);
         cpt=strlen(chaine);
       }
      while (cpt!=5);
      for (i=0;i<cpt;i++) chaine[i]=toupper(chaine[i]);
      test=delet(listcompet3,placecp(listcompet3,chaine));
      clrscr();
      if (!test) printf ("Le matricule n'a pas ete trouve; aucune suppression effectuee...");
      else printf("Suppression de la competition (matricule %s) effectuee !",chaine);
      waiting();
    };
    J'ai un problème lorsque l'on rentre plus de 5 caractères ... Bug !
    Je suppose que cela vient de la déclaration de ma chaine en tant que pointeur sur char.
    Devrais-je plutôt faire

    Dans ce cas, 5 espaces seront réservés; mais que se passera-t-il en mémoire pour les caractères supplémentaires (si mon utilisateur en rentre 6 ou plus ) ?

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Mike888
    Lorsque j'attends de l'utilisateur qu'il tape au clavier (via un gets) une chaine de caractere (qui doit faire 5 caractères pour etre validée )
    Et on a pas dit 3000 fois que gets() était un bug qu'il ne fallait pas utiliser ? Si tu me réponds que c'est ton prof qui le demande, alors c'est simple. Change d'école, et vite.

    Tu l'a pas lu mon article sur les saisies ? Il y a quelque chose que tu ne comprends pas ? Pourquoi t'obstines tu à faire des saisies incorrectes ? C'est lassant...
    J'ai un problème lorsque l'on rentre plus de 5 caractères ... Bug !
    Je suppose que cela vient de la déclaration de ma chaine en tant que pointeur sur char.
    Ben oui, on en a déjà parlé non ? Passer la valeur d'un pointeur non intialisé à une fonction invoque un comportement indéfini. C'est si dur que ça à comprendre?
    Devrais-je plutôt faire
    Ok pour 4 caractères max. Mais par pitié vire moi ce gets(). Les solutions alternatives ont été évoquées maintes fois...
    Dans ce cas, 5 espaces seront réservés; mais que se passera-t-il en mémoire pour les caractères supplémentaires (si mon utilisateur en rentre 6 ou plus ) ?
    Un comportement indéfini. C'est pour ça qu'il ne faut pas utiliser gets().

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    Bon alors, concrètement :

    1°) je déclare :

    Je réserve donc un emplacement pour 5 caractères dans ma future chaine.

    2°) je fais une lecture sur le clavier :

    fgets arretera de lire au clavier après le 5ème caractère.

    On sait que la fonction strlen() ne prend pas en compte le /0 final;

    => Alors pourquoi chez moi, strlen m'indique un caractère de plus que ce qu'il n'y a vraiment dans ma chaine (ex: je rentre 3 caractères, strlen me dit qu'il y en a 4 ...) ?

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Mike888
    Bon alors, concrètement :
    Tu ouvres ton livre de C, et tu apprends à utiliser correctement fgets(). A savoir que cette fonction place tout ce qu'elle eput dans le buffer en fonction de la taille indiquée en reservant toujours une place pour le 0 final.

    Et aussi qu'elle place les caractères lus, y compris le '\n'. Il faut donc de la place pour celui-ci.

    1°) je déclare :

    Je réserve donc un emplacement pour 5 caractères dans ma future chaine.
    6, c'est pingre. Pourquoi pas 8 ou 16...
    2°) je fais une lecture sur le clavier :

    Profitons des automatismes du C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fgets (chaine, sizeof chaine, stdin);
    fgets arretera de lire au clavier après le 5ème caractère.

    Cepedant, la fonction strlen() ne prend pas en compte le /0 final;

    => alors pourquoi chez moi, strlen m'indique un caractère de plus que ce qu'il n'y a vraiment dans ma chaine (ex: je rentre 3 caractères, strlen me dit qu'il y en a 4 ...) ?
    Le '\n' final...

  20. #20
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 463
    Points : 114
    Points
    114
    Par défaut
    oui pardon... c'est \n final que je voulais dire (je fatigue) !

    J'ai mis 5, car le matricule que je veux lire fait 5 caractères.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [XL-2007] Problème de "Range" avec tableau XL2007 (en réalité affectation objet)
    Par ESVBA dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 30/08/2010, 22h17
  2. Réponses: 0
    Dernier message: 20/04/2009, 11h09
  3. Réponses: 5
    Dernier message: 06/10/2007, 11h33
  4. Problème d'affectation tableau
    Par splouf dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 14/12/2006, 14h31
  5. Entier 64 bits sous linux, problème d'affectation
    Par Steki-kun dans le forum Linux
    Réponses: 2
    Dernier message: 13/01/2005, 21h10

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