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 :

Jeu du plus ou moins


Sujet :

C

  1. #21
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut +/-
    Bonsoir, et désolé d'orienter le débat dans un autre sens, même-ci, il est très pertinent de mentionner les défauts de scanf .
    Ceci dit, pas mal de débutant n'ont pas été sensibilisé sur la chose et je pense qu'il est préférable, pour ma part de concevoir des exercices au débutant, qui non seulement incitent l'apprenti à poser des questions pas trop idiotes, mais à comprendre également le choix d'une fonction à défaut de l'autre et l'orienter à écrire du code plus ou moins robuste mais bon ce n'est qu'un avis
    Cordialement
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  2. #22
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ahah, Bktero t'a introduit en erreur
    En fait, %f pour un double est accepté au printf parce que printf sait faire la différence entre un float et un double (grace au codage interne de la valeur à afficher)
    Arf ! Craquage !

    Merci pour cette mise au point

  3. #23
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 677
    Points : 30 965
    Points
    30 965
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    Malheureusement non, sscanf ne sait pas le faire
    Citation Envoyé par Envoyé par ISO/IEC 9899:TC3, 7.19.6.2/10
    7.19.6.2 The fscanf function
    ...If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
    Zut, l'anglais et moi ça fait 30 donc je pige pas trop bien. Il me semble voir que si une conversion est impossible cela produit un comportement indéterminé. Mais peut-être que convertir une chaine en int ne fait pas partie des cas de "conversions non possibles"...

    Par ailleurs, la même norme possède quand-même un paragraphe sur sscanf()
    Citation Envoyé par Envoyé par ISO/IEC 9899:TC3, 7.19.6.2/10
    7.19.6.7 The sscanf function Synopsis
    ...
    The sscanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the sscanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure
    Ca indique bien noir sur blanc que sscanf renvoie le nombres d'items qu'il a réussi à récupérer, ou bien 0 s'il n'en récupère aucun.

    Vois-tu, ta remarque peut déboucher sur un problème grave parce que cette façon de saisir (fgets() + sscanf()) a été présentée moulte fois sur ce forum comme une façon efficace et robuste ; et par de bien plus grands que moi. S'il s'avérait qu'elle ne soit pas correcte, tout le monde peut se tromper mais cela porterait tout de même un rude coup à la crédibilité de tous les "pros" qui viennent ici aider/conseiller. Se pourrait-il (sans vouloir te vexer) que ta conclusion de ce qui est écrit dans la norme soit erronée ?

    Voici un petit code tapé à l'arrache
    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
    	char saisie[100];
    	int nb, x;
     
    	while (1)
    	{
    		fputs("saisie :", stdout);
    		fgets(saisie, 100, stdin);
    		x=sscanf(saisie, "%d", &nb);
    		printf("result: x=%d, nb=%d\n", x, nb);
    	}
    }

    Et son résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ ./x
    saisie :123
    result: x=1, nb=123
    saisie :aaa
    result: x=0, nb=123
    saisie :xxx
    result: x=0, nb=123
    saisie :456
    result: x=1, nb=456
    saisie :yyy
    result: x=0, nb=456
    saisie :^C
    Bien que cela ne prouve rien, il semblerait que toute saisie non numérique n'affecte pas la variable et fasse renvoyer 0 à sscanf...

    Citation Envoyé par sambia39 Voir le message
    Ceci dit, pas mal de débutant n'ont pas été sensibilisé sur la chose
    Ben oui, parce que pas mal de profs ne connaissent même pas la problématique de la chose, ou l'envisagent mal (voir le fflush(stdin) qu'ils n'hésitent pas à proposer comme solution)...

    Citation Envoyé par sambia39 Voir le message
    et je pense qu'il est préférable, pour ma part de concevoir des exercices au débutant, qui non seulement incitent l'apprenti à poser des questions pas trop idiotes, mais à comprendre également le choix d'une fonction à défaut de l'autre et l'orienter à écrire du code plus ou moins robuste
    Oui, mais pour écrire du code robuste il faut déjà avoir la connaissance du soucis, la connaissance des outils permettant de le régler (les fonctions fget/fput ne sont vues généralement qu'à partir du chapitre concernant les fichiers donc généralement à la fin) et une bonne habitude du langage et de ses subtilités. Et comme tu peux le voir, même parmis ceux qui ont une bonne habitude, il demeure toujours des manques, des oublis, voire des divergences quant à la façon dont on doit comprendre certains détails précis...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #24
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Zut, l'anglais et moi ça fait 30 donc je pige pas trop bien. Il me semble voir que si une conversion est impossible cela produit un comportement indéterminé. Mais peut-être que convertir une chaine en int ne fait pas partie des cas de "conversions non possibles"...
    "if the result of the conversion cannot be represented in the object, the behavior is undefined." ça signifie que si le résultat de la conversion (donc ça sous-entend que la conversion est réussie) ne peut pas être représenté (comment tu représentes 4 294 967 296 dans un int 32 bit (overflow) ?), et bien tu as un UB.

    Citation Envoyé par Sve@r Voir le message
    Par ailleurs, la même norme possède quand-même un paragraphe sur sscanf()
    Citation Envoyé par ISO/IEC 9899:TC3, 7.19.7
    7.19.6.7 The sscanf function Synopsis
    ...
    The sscanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the sscanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure
    Ca indique bien noir sur blanc que sscanf renvoie le nombres d'items qu'il a réussi à récupérer, ou bien 0 s'il n'en récupère aucun.
    Oui et non.
    Ça indique que sscanf renvoie le nombre d’éléments assignés (donc converti) avec succès.
    Bien, mais le problème que je pointe est une conversion réussie (format %d et la chaîne contient un entier) dont le résultat n’est pas représentable (entier trop grand) dans l’objet de destination.

    Citation Envoyé par Sve@r Voir le message
    Vois-tu, ta remarque peut déboucher sur un problème grave parce que cette façon de saisir (fgets() + sscanf()) a été présentée moulte fois sur ce forum comme une façon efficace et robuste ; et par de bien plus grands que moi. S'il s'avérait qu'elle ne soit pas correcte, tout le monde peut se tromper mais cela porterait tout de même un rude coup à la crédibilité de tous les "pros" qui viennent ici aider/conseiller.
    Je sais que c’est une approche fréquemment recommandée, mais je sais aussi que c’est une facette des *scanf méconnu donc ça ne m'étonne pas plus que ça que même des « grands » se trompent.
    Aucune remise en cause de crédibilité, on ne peut pas tout savoir.

    Citation Envoyé par Sve@r Voir le message
    Se pourrait-il (sans vouloir te vexer) que ta conclusion de ce qui est écrit dans la norme soit erronée ?
    Je ne pense pas (je ne me vexe pas pour si peu, ne t’inquiète pas ).
    Autant la norme peut parfois sembler ambigu, autant là je pense ne pas me tromper.
    De plus, il y a aussi l’annexe J.2 du même standard :
    Citation Envoyé par ISO/IEC 9899:TC3, Annex J
    J.2 Undefined behavior
    […]
    — The result of a conversion by one of the formatted input functions cannot be
    represented in the corresponding object, or the receiving object does not have an
    appropriate type (7.19.6.2, 7.24.2.2).
    (on notera le renvoi à la section 7.19.6.2, celle que j’ai cité précedemment)

    Enfin, il y a déjà eu des rapports de bug à ce sujet (ici et par exemple).

    Citation Envoyé par Sve@r Voir le message
    Voici un petit code tapé à l'arrache
    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
    	char saisie[100];
    	int nb, x;
     
    	while (1)
    	{
    		fputs("saisie :", stdout);
    		fgets(saisie, 100, stdin);
    		x=sscanf(saisie, "%d", &nb);
    		printf("result: x=%d, nb=%d\n", x, nb);
    	}
    }

    Et son résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ ./x
    saisie :123
    result: x=1, nb=123
    saisie :aaa
    result: x=0, nb=123
    saisie :xxx
    result: x=0, nb=123
    saisie :456
    result: x=1, nb=456
    saisie :yyy
    result: x=0, nb=456
    saisie :^C
    Bien que cela ne prouve rien, il semblerait que toute saisie non numérique n'affecte pas la variable et fasse renvoyer 0 à sscanf...
    Oui, tout saisie non numérique échoue.
    Encore une fois, ce n’est pas ce dont je parle.
    Je parle d’une conversion réussie mais dont le résultat ne peut pas être représenté.
    D’ailleurs, en reprenant ton code, voilà ce que j’obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [grim7reaper@coupable ~] % gcc -o Sve@r Sve@r.c    
    [grim7reaper@coupable ~] % ./Sve@r 
    saisie :1000000000000
    result: x=1, nb=-727379968
    saisie :^C
    [grim7reaper@coupable ~] % gcc -o Sve@r Sve@r.c -m32
    [grim7reaper@coupable ~] % ./Sve@r                  
    saisie :1000000000000             
    result: x=1, nb=2147483647
    saisie :^C
    [grim7reaper@coupable ~] %
    Tu remarqueras que pour un même code, même compilo’, même OS on a un comportement différent (mais un résultat faux dans les 2 cas) selon que l’on soit 32 ou 64 bits (au passage, c’est le second rapport de bug que j’ai linké).
    Et c’est tout a fait légal, un UB donne carte blanche au compilo’ (j’ai déjà vu un bool qui valait vrai ET faux simultanément en cas d’UB ). Il aurait aussi bien pu formater mon PC que me faire sortir des démons du nez.

  5. #25
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Personnellement, je ne vois pas de faille dans le raisonnement de grim7reaper.

    Unless assignment suppression was indicated by a *, the
    result of the conversion is placed in the object pointed to by the first argument following
    the format argument that has not already received a conversion result.
    Cela sous-entend que la conversion a réussi. Je me demande d'ailleurs comment on peut juger qu'elle est réussie si on ne peut pas faire rentrer le résultat dans la ""lvalue"".

  6. #26
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 677
    Points : 30 965
    Points
    30 965
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    Encore une fois, ce n’est pas ce dont je parle.
    Je parle d’une conversion réussie mais dont le résultat ne peut pas être représenté.
    +1. J'étais parti sur une conversion échouée sans regarder l'autre coté
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Jeu plus ou moins qui bug!
    Par Theinfrarougegp dans le forum Débuter
    Réponses: 7
    Dernier message: 28/11/2014, 19h13
  2. Jeu du plus ou moins avec une fonction récursive
    Par Pimousse22 dans le forum C
    Réponses: 6
    Dernier message: 29/10/2014, 21h26
  3. Jeu de plus ou moins à faire boucler
    Par stachys12 dans le forum Débuter
    Réponses: 7
    Dernier message: 28/08/2013, 21h10
  4. Jeu de plus ou moins avec images
    Par CloudyClad dans le forum Général JavaScript
    Réponses: 18
    Dernier message: 18/07/2013, 20h08

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