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 :

Probleme simple de boucle infinie.


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Par défaut Probleme simple de boucle infinie.
    Bonjour à tous, je debute en C (2 jour que je "programme"). J'ai un probleme sur un exo tout simple qui me demande de d'afficher une table de multiplication d'un entier compris entre 0 et 20 avec un test sur l'entier en question. Je suis sous windows et j'utilise Dev-C++, voila le programme que j'ai ecrit:

    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
    #include <stdio.h>
    int main(void)
    {
      int N, i=0, produit, Borne_Inf=0, Borne_Sup=20;
      do {
         printf ("Tapez l'entier compris entre 0 et 20 dont vous voulez la table de multiplication \n");
         scanf("%d",&N); // pas de test pour le caractere entier scanf(%d) prend seulement la partie entiere
         if (N < Borne_Inf || N > Borne_Sup)
            {printf ("L'entier choisit n'est pas compris entre 0 et 20!\n");
            }
         }
      while(N < Borne_Inf || N > Borne_Sup);
     
      for (i=Borne_Inf; i<=Borne_Sup; i++)
        {
       	produit = i * N;
    	printf ("%d x %d = %d\n", N, i, produit);
        }
     
      system("PAUSE");
      return 0;
    }
    Quand je compile pas de soucis et quand je l'éxecute avec un entier quelqu'il soit ou un réel lui entre 0 et 20 pas de soucis non plus mais si je lui donnes un réel non compris dans [0;20] il boucle a l'infini !
    Je ne comprend pas pourquoi...
    Je suis allez voir les tutoriel de devellopez à propos de scanf ou de Do while et je n'arrive pas a voir l'erreur.
    Merci d'avance pour vos reponse à mes questions!

  2. #2
    Membre confirmé
    Homme Profil pro
    Software engineer
    Inscrit en
    Août 2008
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Software engineer

    Informations forums :
    Inscription : Août 2008
    Messages : 139
    Par défaut
    j'ai essayé ton code et ca marche sans probleme ,je vois pas la boucle infinie !!
    relance ton dev-c++ ou redemarre le pc ,je ne sais pas ce que tu dois faire mais ca marche la ,avec xp et code::blocks .

  3. #3
    Membre éprouvé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    142
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 142
    Par défaut
    Bonjour,

    Pour oswalidos, as mon avis tu n'a pas testé completement sont programme, car effectivement pour un reel non compris dans les bornes, cela nous donne une belle boucle infini.

    Sinon concernant le probleme tu declare ton N comme étant un entier de type "int", alors que tu lui affecte un reel (float/double) .

    Met un float N, a la place d'un int N, sa devrait aller

  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 : 69
    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 elieto Voir le message
    Quand je compile pas de soucis et quand je l'éxecute avec un entier quelqu'il soit ou un réel lui entre 0 et 20 pas de soucis non plus mais si je lui donnes un réel non compris dans [0;20] il boucle a l'infini
    Ce n'est pas vrai. Déjà, c'est pas 'réel', mais 'entier'... Le défaut se produit si on entre une valeur invalide ('a', par exemple). C'est dû au fait que scanf() laisse trainer un \n dans le flux qui le rend non bloquant. La règle de bon usage est de systématiquement vider le flux stdin après usage si on est pas certain que le dernier caractère lu était un '\n'.
    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
     
    #include <stdio.h>
     
    static void fpurge (FILE * fp)
    {
       int c;
       while ((c = fgetc (fp)) != '\n' && c != EOF)
       {
       }
    }
     
    int main (void)
    {
       int N, i = 0, produit, Borne_Inf = 0, Borne_Sup = 20;
       do
       {
          N = -1;
          printf
             ("Tapez l'entier compris entre 0 et 20 dont vous voulez la table de multiplication \n");
    /* pas de test pour le caractere entier scanf(%d) prend seulement la partie entiere */
          scanf ("%d", &N);
          fpurge (stdin);
          if (N < Borne_Inf || N > Borne_Sup)
          {
             printf ("L'entier choisit n'est pas compris entre 0 et 20!\n");
          }
       }
       while (N < Borne_Inf || N > Borne_Sup);
     
       for (i = Borne_Inf; i <= Borne_Sup; i++)
       {
          produit = i * N;
          printf ("%d x %d = %d\n", N, i, produit);
       }
     
       return 0;
    }
    On peut aussi envisager de faire ses saisies avec fgets() et la conversion qui va bien...

  5. #5
    Membre expérimenté Avatar de jiddou
    Inscrit en
    Août 2007
    Messages
    247
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 247
    Par défaut
    Ton programme est syntaxiquement et algorithmiquement correct.Mais c'est langage C qui est comme ça.Quand tu valide pour la première fois à chaque fois qu'on repasse dans la boucle scanf trouve un \n dans le flux qui la valide donc c comme si cette instruction ne s'exécute plus.

    Alors La solution:
    après le scanf("%d",&N); mettre fflush(stdin);
    J'espère avoir régler ton problème.

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    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 jiddou Voir le message
    Alors La solution:
    après le scanf("%d",&N); mettre fflush(stdin);
    J'espère avoir régler ton problème.
    Non.

    http://c.developpez.com/faq/?page=cl...N_fflush_stdin

  7. #7
    Membre expérimenté Avatar de jiddou
    Inscrit en
    Août 2007
    Messages
    247
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 247
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Et pourtant j'insiste parce qu'il va tester et ça va marcher et c'est plus propre.Au lieu d'écrire tout une fonction pour lire un entier.
    Problème de portabilité mais je ne pense pas que c'est son soucis pour le moment :
    En tout cas ça marche aussi bien sous Linux que sous windows alors bonne chance

  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 : 69
    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 jiddou Voir le message
    Et pourtant j'insiste parce qu'il va tester et ça va marcher et c'est plus propre.Au lieu d'écrire tout une fonction pour lire un entier.
    Problème de portabilité mais je ne pense pas que c'est son soucis pour le moment :
    En tout cas ça marche aussi bien sous Linux que sous windows alors bonne chance
    Euh, non, ça ne marche pas du tout sous Linux (comportement indéfini). Des cas de plantages ont été signalés...

  9. #9
    Membre expérimenté Avatar de jiddou
    Inscrit en
    Août 2007
    Messages
    247
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 247
    Par défaut
    En tt cas aucun cas de plantage signalé de mon côté.
    Bon une instruction que j'utilisais avant de connaître le fflush marche aussi.

    while( (c=getchar())!='\n' && c!=EOF );

  10. #10
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    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 jiddou Voir le message
    En tt cas aucun cas de plantage signalé de mon côté.
    Bon une instruction que j'utilisais avant de connaître le fflush marche aussi.

    while( (c=getchar())!='\n' && c!=EOF );
    Et c'est quoi la différence avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    static void fpurge (FILE * fp)
    {
       int c;
       while ((c = fgetc (fp)) != '\n' && c != EOF)
       {
       }
    }
    déjà indiqué ?

    Franchement, oublie fflush(stdin), c'est un bug.

  11. #11
    Membre éclairé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Août 2007
    Messages
    509
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Août 2007
    Messages : 509
    Par défaut
    ET si on met un \n dans le scanf.
    Comme ça :
    scanf("%d\n",&N);

  12. #12
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Par défaut
    Merci pour toutes ces réponses!
    Je me demandai de mon côté si on pouvait déclarer N comme réel et ensuite utiliser la fonction floor() de la bibliotheque math.h qui renvoie la partie entière de l'argument et travailler avec cette dernière?
    Je pose la question d'un point de vue un peut comportementaliste, la on "impose" à l'utilisateur cette partie entière. Pour ce programme ce n'est pas trés grave mais pour plus tard est ce que cette philosophie d'imposer a l'utilisateur est à bannir? Ou cela depend-t-il juste du programmeur?
    En esperant avoir été clair...

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par jiddou Voir le message
    Bon une instruction que j'utilisais avant de connaître le fflush marche aussi.

    while( (c=getchar())!='\n' && c!=EOF );
    Et surtout que tu devrais continuer d'utiliser plutôt que de mettre des fflush(stdin) qui invoque un comportement indéfini (au passage, je suis fort surpris que cela fonction chez toi sur Linux).

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par publicStaticVoidMain Voir le message
    ET si on met un \n dans le scanf.
    Comme ça :
    scanf("%d\n",&N);
    Ca ne permet au mieux que de traiter le '\n' trainant dans le flux d'entrée, pas une saisie incorrect de la part de l'utilisateur.

  15. #15
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    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 publicStaticVoidMain Voir le message
    ET si on met un \n dans le scanf.
    Comme ça :
    scanf("%d\n",&N);
    Il faut cesser de coder au hasard. La doc est là : http://xrenault.developpez.com/tutoriels/c/scanf/

  16. #16
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 982
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 982
    Par défaut
    Beo,
    Citation Envoyé par elieto Voir le message
    Merci pour toutes ces réponses!
    Je me demandai de mon côté si on pouvait déclarer N comme réel et ensuite utiliser la fonction floor() de la bibliotheque math.h qui renvoie la partie entière de l'argument et travailler avec cette dernière?
    Je pose la question d'un point de vue un peut comportementaliste, la on "impose" à l'utilisateur cette partie entière. Pour ce programme ce n'est pas trés grave mais pour plus tard est ce que cette philosophie d'imposer a l'utilisateur est à bannir? Ou cela depend-t-il juste du programmeur?
    En esperant avoir été clair...
    La bonne pratique est de sécuriser l'entrée.

    Un moyen est de lire l'entrée dans une chaîne, puis de contrôler le contenu de cette chaîne (dans ton cas : est-ce une valeur numérique entière ?).

Discussions similaires

  1. probleme avec une boucle infinie
    Par hunter99 dans le forum C++
    Réponses: 3
    Dernier message: 26/12/2007, 23h37
  2. Probleme de boucle infini
    Par Premium dans le forum C++
    Réponses: 4
    Dernier message: 29/03/2007, 22h10
  3. probleme de gestion de boucle infinie
    Par masterix59 dans le forum C
    Réponses: 8
    Dernier message: 27/12/2006, 16h34
  4. Probleme Boucle infinie Recordset.movenext "muet"?
    Par shub dans le forum VBA Access
    Réponses: 7
    Dernier message: 14/06/2006, 13h22

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