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 :

Bug lors de la saisie des données avec scanf()


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 7
    Par défaut Bug lors de la saisie des données avec scanf()
    Bonjour, je souhaite implémenter l'algorithme de Gale-Shapley. Dans un premier temps je comptais effectuer la saisie des données par l'utilisateur (le nombre d'hommes/femmes, la liste des préferences de chaque personne) pour enfin y appliquer l'algorithme de Gale-Shapley. Cependant, à l'éxécution du bout de code ci-dessus, la saisie du deuxième choix de la première personne n'aboutit pas et le programme ne m'affiche que le restant des printf sans la possibilité de saisie sachant que j'arrive à faire des saisies avec les deux premières boucles. J'ai essayé d'utiliser fgets mais celà me génère un segfault.. j'ai aussi essayer fflush(stdin) mais cela reste inefficace.

    Je prendrai volontière vos propositions, votre aide m'est indispensable (j'ai passé plus de 24h à essayer de trouver une solution )

    Merci par avance
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int N;
     
    struct person{
      char *name;
      int id;
      int *preference;
    };
     
    int search_for_person_with_id(struct person *tab, char *s){
      for(int i = 0; i < N; i++)
        if(tab[i].name == s)
          return tab[i].id;
      return -1;
    }
     
    void enter_information(struct person *tab){
     
      int i, j;
      char *c1 = NULL;
     
      for(i = 0; i < N; i++){
        printf("Enter the name of male number %d \n", i+1);
        scanf(" %s", tab[i].name); 
        tab[i].id = i;
      }
     
      for(j = 0; j < N; j++){
        printf("Enter the name of female number %d \n", j+1);
        scanf("\t%s", tab[j+N].name); 
        tab[j+N].id = j;
      }
     
     
       printf("Now enter the list of male preferences for each female \n ");
     
      for(i = 0; i < N; i++){
        printf("- For %s : \n", tab[i].name);
        for(j = 0; j < N; j++){
          printf(" %d choice \n", j + 1);
          //fflush(stdin); 
          scanf(" %s", c1);
          tab[i+N].preference[j] = search_for_person_with_id(tab, c1);
          c1 = NULL;
          //fflush(stdin); 
        }
      }
     
     
       printf("Now enter the list of female preferences for each male \n");
     
      for(i = 0; i < N; i++){
        printf("- For %s : \n", tab[i].name);
        for(j = 0; j < N; j++){
          printf(" %d choice \n", j + 1);
          scanf(" %s", c1);
          tab[i].preference[j] = search_for_person_with_id(tab, c1);
          c1 = NULL;
        }
      }
    }
     
    int main(){
      int i;
      printf("Enter the number of males and females: ");
      scanf("%d", &N);
     
      struct person *tab;
     
      tab = malloc(sizeof(struct person)* (2 * N));
      for(i = 0; i < 2*N; i++){
         tab[i].name = malloc(sizeof(char));
         tab[i].preference = malloc(sizeof(int)*N);
      }
     
      enter_information(tab);
     
      for(i = 0; i < 2*N; i++){
         free(tab[i].name) ;
         free(tab[i].preference) ;
       }
       free(tab);
      return 1;
    }
    P-S : voilà le résultat obtenu lors de l'éxecution Nom : Screenshot from 2015-07-07 16:47:43.png
Affichages : 697
Taille : 237,8 Ko

  2. #2
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 872
    Par défaut
    N'étant pas un grand connaisseur de scanf, je dirais que c'est cette ligne qui pose problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    scanf("\t%s", tab[j+N].name);
    Autre chose, fgets correspond bien mieux à ce que tu cherches à faire. Relis mieux le man.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Je plussoie Imperio ci-dessus.

    Pour allez un peu plus loin, la fonction fflush() ne doit jamais s'utiliser pour purger le flux d'entrée. Cette fonction a été créé dans le but de purger un flux, en particulier celui de sortie (le stdout). L'utilisation de cette fonction avec stdin est "Implementation Undefined" selon la norme, c'est à dire qu'elle est laissé à la libre appréciation du système de l'implémenter ou non.
    Si tu es sur un système type Unix, cela produit un comportement indéfinie.
    Pour purger le stdin, tu peux regarder ceci : FaqC -- Comment vider le buffer clavier

  4. #4
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Bonjour,

    Je pense que ton problème vient de la taille de la chaine de caractères allouée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab[i].name = malloc(sizeof(char));
    Telquel, tu as une chaine d'une taille de 1 octet.
    IMPORTANT: Il faut aussi tester le retour du malloc, car s'il est NULL, tu vas direct au segfault en tentant d'écrire dans ce tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #define MAXSIZESTR      100
    .
    .
    tab[i].name = malloc(MAXSIZESTR*sizeof(char));
    if(tab[i].name==NULL) {
        fprintf(stderr, "erreur d'allocation mémoire\n") ;
        /* Libérer toute la mémoire précédemment allouée */
        return 1 ;  /* Code de sortie d'erreur */
    }
    .
    .
    Pour éviter la "lourdeur" de l'allocation, tu peux redefinir ta structure comme ceci, qui limite à N-1 caractères le nom.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct person{
      char name[MAXSIZESTR];    /* Limite à N-1 caractères pour le nom (La fin de chaine étant représenté par \x0 */
      int id;
      int *preference;
    };
    Pour le scanf, le format "%s" ne permet que la saisie de chaine de caractères SANS espace. Comme imperio et archMqx t'ont précédemment dit, préfère l'utilisation de la fonction fgets.
    Pour exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      for(i = 0; i < N; i++){
        printf("Enter the name of male number %d \n", i+1);
        /* Limite la saisie à MAXSIZESTR-1 caractères, donc pas de risque de dépassement */
        fgets(tab[i].name, MAXSIZESTR, stdin) ;     /* Attention, fgets enregistre aussi le retour chariot '\n' */
        tab[i].id = i;
      }
    Voila pour le moment et bonne continuation

  5. #5
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 7
    Par défaut
    Merci pour vos réponses qui m'ont été d'une grande aide et qui m'ont permis d'apprendre de nouvelles choses (je suis un peu novice en C ). J'ai un peu près modifié mon code entièrement, laissant tombé l'allocation dynamique pour celle automatique dans la pile et cela tout en gardant la fonction de scanf (fgets bizarrement semble ne pas marcher.. ) J'ai aussi récupérer la fonction proposée par archMqx et qui purge le stdin et ça a ainsi résolu mon problème. Cependant les ennuies avec fgets semblent ne jamais terminer
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int N;
     
    void clean_stdin(){ 
      int c; 
      do { 
        c = getchar(); 
      } while (c != '\n' && c != EOF); 
    }
     
    void enter_information(char name[2*N][20],int pref[2*N][N]){
      int i, j;
      char *c1 = NULL;
      for(i = 0; i < N; i++){
        printf("Enter the name of male number %d (his id is %d) \n", i+1, i);
        scanf(" %s", name[i]);
        clean_stdin();  
      }
      for(j = 0; j < N; j++){
        printf("Enter the name of female number %d (her id is %d) \n", j+1, j+N);
        scanf(" %s", name[j+N]);
        clean_stdin(); 
      }
      printf("Now enter the list of id's of male preferences for each female \n ");
      for(i = 0; i < N; i++){
        printf("- For %s : \n", name[i]);
        for(j = 0; j < N; j++){
          printf(" %d choice \n", j + 1);
          scanf(" %d", &pref[i][j]);
          clean_stdin(); 
        }
      }
      printf("Now enter the list of id's of female preferences for each male \n");
      for(i = 0; i < N; i++){
        printf("- For %s : \n", name[i+N]);
        for(j = 0; j < N; j++){
          printf(" %d choice \n", j + 1);
          scanf(" %d", &pref[i][j]);
          clean_stdin();
        }
      } 
    //Boucle pour la vérification du contenu de pref[][]
     for(i = 0; i < 2*N; i++){
       printf("for %i tab de pref is \n", i);
      for(j = 0; j < N; j++){
        printf("%d   ", pref[i][j]);
      }
      printf("\n");
    }
      printf("enter info ok \n");  
    }
     
    /* MAIN FUNCTION */
     
    int main(){
     
      int i;
      printf("Enter the number of males and females: ");
      scanf("%d", &N);
      clean_stdin(); 
     
      char name[2*N][20];
      int pref[2*N][N];
     
      enter_information(name, pref);
     
      return 0;
    }
    En vérifiant si le tableau d'int pref à deux dimensions est bien rempli, je trouve que ces valeurs ne sont pas en concordance avec celles rentrées.. d'où le bug du à la fonction scanf
    Nom : Screenshot from 2015-07-14 18:55:52.png
Affichages : 634
Taille : 491,5 Ko

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Avec les lacunes que tu as, tu devrais faire une chose après l'autre, commence par une étape, contrôle que ça fonctionne et passe à l'étape suivante !

    J'ai vu des choses comme la comparaison de 2 chaînes de caractères avec l'opérateur == (ligne 15 de ton premier code), qui est impossible en C (utiliser la fonction strcmp ou créer sa propre fonction de comparaison)

    la liste des préferences de chaque personne
    Conceptuellement ça fonctionne comment ?

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

Discussions similaires

  1. [WD15] Erreur lors de saisie des données
    Par ellyam dans le forum WinDev
    Réponses: 12
    Dernier message: 18/05/2012, 17h20
  2. [MySQL] comment faire pour créer table et formulaire pour saisie des donnes GPS avec images
    Par kitcarson23 dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 07/09/2010, 10h09
  3. [format des données avec une procédure stockée]
    Par viny dans le forum PostgreSQL
    Réponses: 7
    Dernier message: 10/03/2005, 13h24
  4. Exporter seulement une partie des données avec pg_dump ?
    Par Philhz dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 31/07/2004, 09h50
  5. Réponses: 13
    Dernier message: 20/03/2003, 08h11

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