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 :

Passage d'un parametre problematique


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Par défaut Passage d'un parametre problematique
    Bonsoir,

    J'ai un probleme dans le (mon) code suivant avec la fonction
    void affiche_caracteristiques(char *name,int *code) qui prends en paramètre dans le main deux champs (name et codePostal) de la structure user1 (de type personne).


    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
     struct personne {
     
    char  *name;
    int codePostal;
     
     
    };
     
    int SaisieCode(void);   // demande de saisir un code postal
     
    int format_alphabetique(char *nom);   // utilisée par la fonction SaisieNom ci-dessous
     
    char * SaisieNom (void)       //demande de saisir un nom
    {
      char Nom[41];     
      do
      {
           printf("Entrez le nom\n");
           fgets(Nom, sizeof Nom, stdin);             // Lire Nom au clavier
           if(!(format_alphabetique(Nom)))            // Emettre un message d'erreur ?
           {
               printf("Merci d'utiliser des lettres Majuscules ou minuscules\n");
           }
      }
     
      while (!(format_alphabetique(Nom)));    // Tant que le Nom n'est pas de format alphabetique
     
     return Nom;
     
    }
     
     
     
    void affiche_caracteristiques(char *name,int *code)   // NE FONCTIONNE PAS
    {
     
      printf("Le nom est: %c\n",name);                    // cette ligne ne fonctionne pas : 8 est affiché quelque soit la chaine que je veux passer en parametre
      printf("Votre code postal est le :%i",*code);       // Cette ligne fonctionne correctement et affiche bien la valeur du code postal
    }
     
     
     
     
    int main()  
    {
        char fin=0;
        char choix;
        struct personne user1;      // Création d'un objet personne de nom user1
        user1.name = "NON SAISI";   // Initialisation des données de la personne user1
        user1.codePostal = -1;      // conformément au cahier des charges
     
        // AFFICHAGE DU MENU :
    while(!fin)                    // Tant que fin est faux, le programme boucle sur le menu principal :
    {
        printf("\n\n");
        printf("1.Saisie du nom\n2.Saisie du code postal\n3.Affichage des caracteristiques de la personne\n4.Fin \n");
        choix = getchar();
        fflush(stdin);
     
    switch (choix)                // Aiguillage en fonction du choix
     {
     
    case '1' :
     
      user1.name = SaisieNom();   // Appel pour saisir le premier champs (le nom)
     
        printf("La 3eme lettre de ton nom est: %c\n",user1.name[2]);  // Debug
    	break;
     
    case '2' :
     
    	user1.codePostal = SaisieCode();    // Appel pour saisir le code postal 
     
    	break;
     
    case '3' :
     
    	affiche_caracteristiques(&user1.name,&user1.codePostal);    // Je passe en parametre les adresses des champs de ma srtucture user1 à la fonction d'affichage
    	break;
     
    default:  fin=1;     // Si on choisit 4 on met fin à 1 (true) ce qui provoque la sortie de la boucle while et le retour du programme
     
        break;
     
      }
     
    }
    return 0;
    }
    Je veux afficher à l'écran name et codePostal. Ce qui ne fonctionne pas du tout pour name. Avez-vous une idée d'où ça peut bloquer ? (définition de la structure ? parametre d'afficher_caractéristiques ? dans le printf ? ...)

    Guillaume

    ps : Je n'ai pas fait apparaitre certaines fonctions, en mettant simplement leurs définitions

  2. #2
    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
    Bonjour et bienvenue sur le forum

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char * SaisieNom (void)       //demande de saisir un nom
    {
      char Nom[41];     
    ....
     
     return Nom;
     
    }
    Tu retournes l'adresse d'une variable locale ( Dans return Nom, Nom est l'adresse du premier élément du tableau). Or les variables locales sont détruites en sortie de fonction et on a alors l'adresse d'une variable qui n'existe plus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void affiche_caracteristiques(char *name,int *code)   // NE FONCTIONNE PAS
    {
     
      printf("Le nom est: %c\n",name);                    // cette ligne ne fonctionne pas : 8 est affiché quelque soit la chaine que je veux passer en parametre
      printf("Votre code postal est le :%i",*code);       // Cette ligne fonctionne correctement et affiche bien la valeur du code postal
    }
    Le format %c est pour l'affichage d'un char, pas d'une chaîne de char. Le format devrait être %s

    a un comportement indéfini : sur certaines plateformes, ça ne fonctionne pas. fflush() ne devrait être utilisé que sur des flux de sortie (comme stdout)

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Par défaut
    Bonsoir diogene et merci pour ton acceuil

    Merci pour l'explication je comprends ce qui se passe maintenant.

    Je fais essayer de solutionner ça en passant en paramètre le champs de la structure que je veux modifier, dans la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SaisieNom(&user1.name);
    C'est comme cela que l'on fait en C, apparemment.


    Cependant, une chose étrange est que ce morceau fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    user1.name = SaisieNom();   // Appel pour saisir le premier champs (le nom)
     
        printf("La 3eme lettre de ton nom est: %c\n",user1.name[2]);
    => le printf m'affiche bien la 3eme lettre du nom que je saisie. La fonction SaisieNom() fonctionne donc.

    Bref, je modifie mon code et je reposte une fois les tests effectués. Le C est vraiment déroutant pour moi qui vient de java !

  4. #4
    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
    Cependant, une chose étrange est que ce morceau fonctionne :
    C'est uniquement un hasard : la mémoire n'a pas encore été récupérée pour y mettre autre chose. C'est d'ailleurs une malchance, parce que au lieu de planter là où il y a l'erreur, ça va planter plus tard ailleurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SaisieNom(&user1.name);
    Là aussi, ça va planter si tu ne fais pas attention : le champ name est un pointeur et toi, il te faut un tableau pour placer tes caractères.
    Donc :
    - Soit tu gardes name comme un pointeur et tu dois faire de l'allocation dynamique dans ta fonction pour allouer de quoi stocker la chaîne et placer l'adresse dans name,
    - Soit tu changes name pour un tableau de caractères (assez grand pour les mettre tous + le zéro terminal). Dans ce cas & ne doit pas figurer dans l'appel

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Par défaut
    Arf, malgré ton aide, je n'y arrive pas !

    J'ai réussi à afficher "Gu" mais Guillaume ne veut pas sortir. J'ai adopté la stratégie tableau name sur ton conseil, et ne me sentant pas du tout à l'aise avec les malloc...

    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
    struct personne {
     
    char name[41];
    int codePostal;
     
    };
     
    void SaisieNom (char Nom[41]){
    fgets(Nom, sizeof Nom, stdin);
    }
     
    void affiche_caracteristiques(char name[41],int *code)   
    {
         // Je ne vois pas quoi mettre ici
    }
    J'ai essayé d'afficher avec un unique printf("%s",name); ou de balayer sur chaque caractère de name jusqu'à rencontrer \0, mais je n'accede pas correctement aux caractère... Peux-tu me donner les 2 syntaxes à utiliser ?

    Main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int main(){
     
    struct personne user1;           // Création d'un objet personne de nom user1
     
    SaisieNom(user1.name);   
    fflush(stdin);
     
    affiche_caracteristiques(user1.name,59000);
    return 0;
    }
    En tappant SaisieNom(user1.name) comme tu le suggère, user1.name ne sera pas modifié par la fonction, mais juste recopié localement, non ?

    Donc je ne vois pas comment ca marche. J'ai peut être mal interprété ta proposition.

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    En tappant SaisieNom(user1.name) comme tu le suggère, user1.name ne sera pas modifié par la fonction, mais juste recopié localement, non ?
    Oui, comme pour tout tranfert de paramètres.
    MAIS, user1.name désigne un tableau donc c'est l'adresse du premier élément qui est passé. Si la fonction connait l'adresse du premier élément et la taille d'un élément (donné par le type de user1.name) elle peut accéder à tous les éléments du tableau (ce qu'elle ne connait pas à priori, c'est le nombre d'éléments du tableau).
    Donc si la fonction écrit à l'adresse user1.name, on écrit dans le tableau et SaisieNom(user1.name) permet de charger le tableau.

    Par contre, il y a un problème ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void SaisieNom (char Nom[41]){
    fgets(Nom, sizeof Nom, stdin);
    }
    Dans le paramètre char Nom[41] , le 41 ne sert à rien et est ignoré par le compilateur. C'est équivalent à écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SaisieNom (char Nom[]){
    et ceci est interprété par le compilateur (dans une liste de paramètres) comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SaisieNom (char *Nom){
    Cette dernière forme montre qu'en fait Nom est un pointeur et lorsque tu écris sizeof Nom tu obtiens la taille d'un pointeur (probablement 4), pas la taille du tableau ! Comme je te le disais plus haut, la fonction ne connait pas le nombre d'éléments du tableau. Si elle en a besoin, il faut le lui passer en paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void SaisieNom (char Nom[], size_t dim){
    fgets(Nom, dim , stdin);
    }
    int main(){
    struct personne user1;           // Création d'un objet personne de nom user1 
    SaisieNom(user1.name, 41);   
    affiche_caracteristiques(user1.name,59000);
    return 0;
    }
    Dans la fonction affiche_caracteristiques(), pourquoi le paramètre code est-il un pointeur sur int et pas un int ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void affiche_caracteristiques(char name[], int code)   
    {
         printf( "nom =%s ; code = %d \n",name,code);
    }

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

Discussions similaires

  1. [C#]Passage d'un parametre date a une procédure stocké
    Par frans2111 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 28/08/2006, 23h07
  2. Probleme de passage d un parametre
    Par micanti dans le forum Struts 1
    Réponses: 6
    Dernier message: 07/07/2006, 17h03
  3. Passage de plusieurs parametre
    Par el_quincho dans le forum Access
    Réponses: 2
    Dernier message: 30/03/2006, 14h26
  4. Réponses: 7
    Dernier message: 27/03/2006, 16h18
  5. Réponses: 7
    Dernier message: 04/01/2005, 18h45

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