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 :

"if" mêlant des "&&" et des "||"


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    Points : 22
    Points
    22
    Par défaut "if" mêlant des "&&" et des "||"
    Bonjour à tous !

    Je débute dans la prog en C et je suis confronté à un petit souci. Plutôt que de longs discours, voici la ligne qui me pose problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     else if ( j == 1 && (i != 0 || i != ii) )
    Que j'ai aussi essayé de mettre sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     else if ( (j == 1 && i != 0) || (j == 1 && i != ii) )
    Si quelqu'un à la solution à ce petit problème qui j'imagine est tout bête... je le remercie par avance !


    EDIT : Correction du code

  2. #2
    Membre régulier
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    Je ne comprends pas bien, que veux-tu faire ? Les deux propositions contenues dans tes if ne sont pas équivalentes !

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Bonjour,

    Oui, dsl j'ai mal recopier mes parenthèses pour le premier exemple.
    Le principe est d'effectuer certains calculs pour certaines "cases" d'un tableau. Dans mon cas, je veux effectuer ce calcul précis pour toutes les cases de la ligne j = 1 sauf pour les cases des colonnes i = 0 et i = ii; c'est-à-dire les deux cases aux extrémités de cette ligne.

    C'est plus clair ?

  4. #4
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    toujours mettre les parenthèses complètes....

    Pour 2 touches à taper en plus, quelle simplification et sûreté !!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    else if ( (j == 1) && ( (i != 0) || (i != ii) ) )
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si ii est différent de zéro, ce test est toujours vrai. Tu devrais remplacer || par &&.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Médinoc
    Si ii est différent de zéro, ce test est toujours vrai. Tu devrais remplacer || par &&.
    j'avais même pas fais gaffe
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Ah oui exact...

    Bon j'ai corrigé et ça marche. Merci bien
    Sinon je vais suivre ton conseil pour les parenthèses Souviron

    Merci pour vos réponses rapides

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    @ j0o0 : désolé de te contredire mais ces deux tests sont strictement équivalent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    else if ( j == 1 && (i != 0 || i != ii) )
    else if ( (j == 1 && i != 0) || (j == 1 && i != ii) )
    Voici un petit code que tu peux t'amuser à tester :

    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
    int main(int argc, char *argv[])
    {
        printf("1 == 1 && (1 == 2 || 2 == 1) = %d\n"
               "(1 == 1 && 1 == 2) ||(1 == 1 && 2 == 1) = %d\n"
               "1 == 2 && (2 == 2 || 2 == 1) = %d\n"
               "(1 == 2 && 2 == 2) || (1== 2 && 2 == 1) = %d\n",
     
               1 == 1 && (1 == 2 || 2 == 1),
               (1 == 1 && 1 == 2) ||(1 == 1 && 2 == 1),
               1 == 2 && (2 == 2 || 2 == 1),
               (1 == 2 && 2 == 2) || (1== 2 && 2 == 1));
        printf("----------------------------------------\n");
        printf("1 == 1 && (2 == 2 || 2 == 1) = %d\n"
               "(1 == 1 && 2 == 2) ||(1 == 1 && 2 == 1) = %d\n"
               "1 == 2 && (2 == 2 || 2 == 2) = %d\n"
               "(1 == 2 && 2 == 2) || (1== 2 && 2 == 2) = %d\n",
     
               1 == 1 && (2 == 2 || 2 == 1),
               (1 == 1 && 2 == 2) ||(1 == 1 && 2 == 1),
               1 == 2 && (2 == 2 || 2 == 2),
               (1 == 2 && 2 == 2) || (1== 2 && 2 == 2));
     
        return 0;
    }
    Résultat :

    1 == 1 && (1 == 2 || 2 == 1) = 0
    (1 == 1 && 1 == 2) ||(1 == 1 && 2 == 1) = 0
    1 == 2 && (2 == 2 || 2 == 1) = 0
    (1 == 2 && 2 == 2) || (1== 2 && 2 == 1) = 0
    ----------------------------------------
    1 == 1 && (2 == 2 || 2 == 1) = 1
    (1 == 1 && 2 == 2) ||(1 == 1 && 2 == 1) = 1
    1 == 2 && (2 == 2 || 2 == 2) = 0
    (1 == 2 && 2 == 2) || (1== 2 && 2 == 2) = 0
    L'opérateur && est distributif par rapport à || mais || est aussi distributif par rapport à &&, en revanche && est prioritaire sur ||, ce qui fait que :
    a == b && a == c || a == b && c == d

    équivaut à :
    a== b && (a == c || c == d)

    Et complètement différent de :
    a == b && a == c || c == d

    qui est en revanche équivalent à :
    (a == b && a == c) || (a == b && c == d)

    En outre :
    @ souviron34 :

    == et != sont prioritaires sur && et ||...

    Mettre des parenthèses partout ne sert à rien, aussi bien tu peux écrire ça :

    a = (c + (b * (d * 3)));

    En tout cas, c'est ce que tu conseilles de faire en vertue de la "sûreté"...

  9. #9
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par PsychoH13
    En outre :
    @ souviron34 :

    == et != sont prioritaires sur && et ||...

    Mettre des parenthèses partout ne sert à rien, aussi bien tu peux écrire ça :

    a = (c + (b * (d * 3)));

    En tout cas, c'est ce que tu conseilles de faire en vertue de la "sûreté"...
    Non c'est ce qe je conseille de faire au nom de la lisibilité et des mathématiques.

    Tu devrais pouvoir lire du code "mathématique" comme une équation écrite à la main.

    Et par conséquent l'ordre de précédence des opérateurs (qui par ailleurs n'est pas forcément standard, ni par langage, ni par compilateur) n'a rien à voir avec l'écriture.

    Une écriture lisible ne fait pas d'hypothèses.. Elle se lit...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    La précédence des opérateurs est standard... Et respecte la précédence des opérateurs mathématiques, et ajouter des parenthèses lorsqu'elles ne sont pas nécessaires réduit à mon sens la lisibilité d'une expression mathématique :
    Ces deux expression sont strictement équivalentes : (3 + (5 * 2)) et 3 + 5 * 2, que ce soit en programmation ou en mathématique, ajouter des parenthèses n'enlève en rien une quelconque ambiguïté et rend une simple expression illisible.

  11. #11
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par PsychoH13
    La précédence des opérateurs est standard... Et respecte la précédence des opérateurs mathématiques, et ajouter des parenthèses lorsqu'elles ne sont pas nécessaires réduit à mon sens la lisibilité d'une expression mathématique :
    Ces deux expression sont strictement équivalentes : (3 + (5 * 2)) et 3 + 5 * 2, que ce soit en programmation ou en mathématique, ajouter des parenthèses n'enlève en rien une quelconque ambiguïté et rend une simple expression illisible.

    La précédence des opérateurs est quelque chose d'informatique, lié au compilateur et au langage.

    L'écriture d'un test ou d'une équation est quelque chose de mathématique, indépendant du compilateur ou du langage.

    Ecrire

    (3 + (5 * (3+2)) )

    n'est pas équivalent à

    (3 + 5 * 3 + 2 )

    Et à plus forte raison pour les "et", "ou", et combinaisons de "et" et "ou"...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Je suis à 100% d'accord avec ça :

    Citation Envoyé par souviron34
    Ecrire

    (3 + (5 * (3+2)) )

    n'est pas équivalent à

    (3 + 5 * 3 + 2 )
    Et c'est d'ailleurs valable autant en mathématique qu'en programmation... Oh, oh, oh, comme c'est bizarre...


    Citation Envoyé par souviron34
    La précédence des opérateurs est quelque chose d'informatique, lié au compilateur et au langage.

    L'écriture d'un test ou d'une équation est quelque chose de mathématique, indépendant du compilateur ou du langage.

    Les règles définissant la précédence des opérateurs sont à l'origine mathématique !
    C'est bien en mathématique qu'on déclare que la multiplication est prioritaire sur l'addition et que donc l'expression "5 + 2 x 3" donne le calcule : 2 x 3 = 6, 6 + 5 = 11, et non pas 5 + 2 = 7, 7 * 3 = 21.
    Ce sont des règles mathématiques et non pas programmatique. Et ces règles ont été reprises telles quelles en programmation...
    Ce qui fait que quelque soit le compilateur, les opérations == seront toujours évaluées avant les opérations && qui seront toujours évaluée avant les opération ||...

  13. #13
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Libre à toi...

    Mais ne viens pas te plaindre le jour où ton compilateur préféré (et bien réglé ) vient te dire

    "ambiguous && .. Add some braces... "

    ou bien

    "ambiguous || .. Add some braces..."


    2 solutions s'offrent à toi dans ce cas :


    • C'est ton code, tu sais ce que tu voulais faire, tu corriges.

    • Ce n'est pas ton code, tu ne sais pas ce que le programmeur voulait faire, et tu es dans la m.rde...


    Il y a pleins d'exemples du 2ième cas de figure dont des freeware mondialement utilisés d'organisations mondiales respectées (pour n'en citer qu'un, dans les softs officiels fournis par MPEG.org....).

    Correction impossible à faire.. D'où impossible de savoir ce que fera la compilo, d'où potentialité de bug majeur...


    Mais tu fais comme tu veux...

    Et je donne ceci comme conseil, c'est tout..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #14
    Membre régulier
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    Points : 76
    Points
    76
    Par défaut
    @PsychoH13

    @ j0o0 : désolé de te contredire mais ces deux tests sont strictement équivalent :
    Je suis complètement d'accord avec toi, Surikat14 a dû éditer son message entre temps ou alors je n'avais vraiment pas les yeux en face des trous

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    "ambiguous && .. Add some braces... "

    ou bien

    "ambiguous || .. Add some braces..."
    Ah parce qu'en cas d'ambiguïté le compilateur choisi une expression au hasard et la compile ? Enfin... sauf si tes messages provoquent des erreurs, mon compilateur préféré n'émet que des warnings... (et il me dit même pas d'ajouter de parenthèses )
    En cas d'ambiguïté, le comportement par défaut est adopté... Et ce comportement par défaut c'est celui de la précédence de && sur ||...

    Donc :

    Citation Envoyé par souviron34
    Correction impossible à faire.. D'où impossible de savoir ce que fera la compilo, d'où potentialité de bug majeur...
    Deux cas :
    • Soit le concepteur a fait l'inverse du comportement par défaut : il a écrit a && b || c alors qu'il voulait faire a && (b || c), bah là la correction est "impossible"...
    • Soit le concepteur a utilisé justement le comportement par défaut : il a écrit a && b ||*c alors qu'il voulait faire (a && b) || c, bah là aucun problème...


    Dans ces deux cas, le comportement du compilateur n'est pas indéfini, certes si tu le mets en mode paranoïaque il va te faire remarquer cette "ambiguïté" mais la compilation fera toujours la même chose, ce n'est ambiguë que pour les gens qui ne font pas attention, ou qui ne connaisse pas les règles mathématiques de base.
    Si t'es le concepteur du programme, bah révise tes maths si c'est pas clair pour toi.
    Si t'es pas le concepteur, on peut espérer que le code donné a été testé et débogué, si c'est pas le cas bah va chercher ailleurs.

    Quand un architecte fait mettre une cheminée à la place de la porte d'entrée bah t'en changes. Si le concepteur d'un programme ne connaît pas le comportement des expressions qu'il écrit ça sert à rien de continuer à bosser avec lui.

  16. #16
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Tu fais ce que tu veux...

    Ici c'est un forum où on essaye de donner des avis et conseils de professionnels. C'en est un. C'est tout.

    Libre à toi de prendre des risques et de t'arracher les cheveux à comprendre une expression....

    Mais une longue pratique me dicte ce comportement...

    Et franchement, du point de vue lisibilité, c'est nettement plus clair, pour peu qu'on veuille mettre des espaces (et ça n'est pas fatiguant de taper quelques parenthèses)...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/05/2015, 17h28
  2. Réponses: 7
    Dernier message: 21/10/2010, 13h30
  3. remplacer des espaces dans un champ par des zero
    Par yeep dans le forum Access
    Réponses: 4
    Dernier message: 08/10/2004, 09h41
  4. Cherche table des communes de France et table des codes NAF
    Par grandmaitrezen dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 09/08/2004, 14h32

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