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 :

Erreur : Atribuer une valeur scanf à une variable d'une structure


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Octobre 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut Erreur : Atribuer une valeur scanf à une variable d'une structure
    Bonjour à toute la communauté Developpez.
    J'ai souhaité revoir un peu les listes chainées que je n'ai jamais réellement maîtrisé. Donc rien de mieux qu'un petit programme pour tester... enfin si ça marche >_<
    Ce que j'essaye de faire c'est un programme console assez basique dans lequel on peut rentrer des informations (nom, prenom, etc...) qui seront stockées dans une liste chainée.

    Un problème se pose lorsque je veux assigner la valeur scanf rentrée par l'utilisateur à la variable "nom" de la structure "contact".

    Voici la partie du code qui foire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         scanf ("%s", &vNom);
         contact *sel;
         sel->nom = (char*) malloc ((strlen (vNom) + 1) * sizeof (sel));
         strcpy(sel->nom,vNom);

    Et voici le code complet :
    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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
     
    int jid=0;
     
    typedef struct contact {
            int id;
            char *nom;
            struct contact *next;
    };
     
    contact* add_contact (contact *nouv, contact *tete) {    // fct qui ajoute une maille à la liste chainée
         contact * pCourant;
     
         if (tete != NULL) {
            pCourant = tete;
            while (pCourant->next != NULL) 
                  pCourant = pCourant->next;
         }
     
         nouv = (contact*)malloc(sizeof(struct contact));
         if (tete!= NULL ) pCourant->next = nouv;
         nouv->next = NULL;
         nouv->nom = NULL;
     
         return nouv;
    }
     
    contact* mod_contact (contact *sel, char *vNom) { // associe des valeurs aux variables de la liste chainée
         sel->id = jid;
         jid++;
         sel->nom = (char*) malloc ((strlen (vNom) + 1) * sizeof (sel));
         strcpy(sel->nom,vNom);
     
         return sel;
    }
     
     
     
    int main ()
    {
        /* Valeurs entrées par l'utilisateur */
        int choix;     // choix d'action (ajouter un contact/lire la liste de contacts/quitter)
        char *vNom; // variable nom
        /* Initialisation des pointeurs pour la liste chainée */
        contact *nouv;  // maille temporaire de la liste
        contact *tete;  // tete le la liste chainée
        contact *sel;   // maille selectionnee localement (sur laquelle on veut travailler)
        tete = NULL;
        sel = NULL;
     
        while (1) {
              choix=0;
              printf ("Que voulez-vous faire?\n  1)Ajouter un contact\n  2)Visualiser la liste de contacts\n  3)Quitter\n\n");
              scanf ("%s", &choix);
     
              if (choix == '1') {
                 sel = add_contact (nouv, tete); //creer une nouvelle maille
                 if (tete == NULL)
                    tete=sel;         // si c'est la premiere maille, c'est la tete
                 printf ("\nNom :");
                 scanf ("%s", &vNom);
                 sel = mod_contact (sel, vNom); // rentrer vNom dans la liste chainée
                 printf ("Operation terminee\n\n");  // inutile mais j'ai trouvé ça joli
     
              }
     
              else if (choix == '2') {
                       printf ("Carnet vide\n\n"); // pour le moment je mets ça
              }
     
              else if (choix == '3') {
                   break; // quitter
              }
     
              else
                  printf ("Saisie incorrecte\n\n");
     
        }
     
        return 0;
    }
    Ah oui et l'erreur est une exception win32 non-gérée.

    Merci d'avance pour votre aide!

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Cela commence mal déjà avec la saisie du nom
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *vNom; // variable nom
    scanf ("%s", &vNom);
    dans ton cas, scanf lit une chaine de caractères (%s) et le stocke dans un buffer.
    Toi, tu n'as pas de buffer alloué (vNom pointe sur rien, c'est un pointeur fou.
    et en plus, tu passes l'adresse du pointeur au lieu de passer le pointeur

    Code corrigé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char vNom[256]; // variable nom
    scanf ("%s", vNom);
    Attention, si le nom saisi fait plus de 255 caractères, cela part en cacahuètes.

    Autre chose, scanf n'est pas la meilleure fonction pour faire des saisies au clavier (trop de subtilités). Je préfère fgets()

  3. #3
    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 : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Plusieurs remarques en vrac:

    * Il manque les tests sur la valeur de retour des malloc.
    * A la line sel->nom = (char*) malloc ((strlen (vNom) + 1) * sizeof (sel)); que vient faire le sizeof(sel) ? Tu cherches a allouer un tableau de char par un tableau de contact*.
    * Il manque les tests sur le retour de scanf.
    * choix est un int, la ligne scanf ("%s", &choix); est donc fausse. C'est %d pour lire un entier et %c pour un caractère.
    * La ligne scanf ("%s", &vNom); est fausse. Tout d'abord ce n'est pas &vNom mais vNom. Ensuite vNom n'est pas une adresse valide. Enfin scanf("%s...) est une mauvaise utilisation de scanf(), en effet la taille de la saisie n'est pas contrôlée, préfère fgets() à scanf() pour de telle saisie.

    Il y a probablement d'autres soucis, mais ce sont ceux qui m'ont sauté aux yeux.

  4. #4
    Candidat au Club
    Inscrit en
    Octobre 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup, ça marche nickel =)
    Et moi qui pensais qu'on faisais toujours l'adresse de la variable avec scanf

    EDIT @gl :
    -serais-ce possible de m'expliquer comment tester la valeur de retour des malloc?
    -je vais enlever "sizeof(sel)" ^^
    -je vais faire les tests sur le scanf tout de suite
    -pour ce qui est du scanf du "choix", j'ai voulu restreindre la saisie à des caractères numériques (1 et 2). En faisant un %i, lors de saisies de lettres, le programme part en boucle infinie. J'ai donc essayé avec %s et ça a marché donc j'ai laissé comme ça sans vraiment savoir pourquoi c'était bon ^^" Si vous avez une meilleure solution je suis preneur.
    -je vais aller jeter un coup d'oeil à la fonction fgets

    EDIT 2 :
    En fait je vois pas ce que je dois mettre comme test sur le scanf du nom saisi, vu que ça attend une chaine de caractères, et que le fait que l'utilisateur rentre des chiffres ne va pas poser de problèmes au programme.

  5. #5
    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 : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par NewelZ Voir le message
    -serais-ce possible de m'expliquer comment tester la valeur de retour des malloc?
    En cas d'erreur, malloc() retourne NULL.

    Citation Envoyé par NewelZ Voir le message
    -pour ce qui est du scanf du "choix", j'ai voulu restreindre la saisie à des caractères numériques (1 et 2). En faisant un %i, lors de saisies de lettres, le programme part en boucle infinie. J'ai donc essayé avec %s et ça a marché donc j'ai laissé comme ça sans vraiment savoir pourquoi c'était bon ^^" Si vous avez une meilleure solution je suis preneur.
    Comme indiqué dans mon message précédent, pour récupérer un caractère c'est %c (et non %s) qui récupère une chaîne de caractères).

    Il faut en outre bien entendu après chaque lecture nettoyer le flux d'entrée afin d'éliminer les caractères surnuméraires qui trainent (je te renvoie à la FAQ pour plus de détails.

    Citation Envoyé par NewelZ Voir le message
    En fait je vois pas ce que je dois mettre comme test sur le scanf du nom saisi, vu que ça attend une chaine de caractères, et que le fait que l'utilisateur rentre des chiffres ne va pas poser de problèmes au programme.
    scanf() renvoie le nombre de conversions réussies. Ce test aurait permis de détecter le problème de boucle infinie évoqué ci-dessus.

    Pour plus de détails sur comment utiliser scanf(), je te conseille la lecture de Scanf démythifiée.

  6. #6
    Candidat au Club
    Inscrit en
    Octobre 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Merci, je vais reprendre tout ça =)

Discussions similaires

  1. Réponses: 21
    Dernier message: 05/02/2015, 11h26
  2. [XL-2000] Remplir une valeur dans cellule à partir d'une valeur precise d'un fichier texte
    Par cactus666 dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 26/01/2010, 10h31
  3. Réponses: 2
    Dernier message: 23/11/2007, 11h33
  4. Couleur de cellule variable suivant une valeur
    Par repié dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 14/03/2006, 08h04
  5. Valeur d'e variable d'une fct dans autre fonction
    Par Torpedox dans le forum Langage
    Réponses: 3
    Dernier message: 11/11/2005, 08h48

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