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 averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    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 confirmé
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    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 averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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) ) )

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 32
    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 chevronné
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 309
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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...

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 309
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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"...

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 309
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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..

  14. #14
    Membre confirmé
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    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 chevronné
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 309
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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)...

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/05/2015, 18h28
  2. Réponses: 7
    Dernier message: 21/10/2010, 14h30
  3. remplacer des espaces dans un champ par des zero
    Par yeep dans le forum Access
    Réponses: 4
    Dernier message: 08/10/2004, 10h41
  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, 15h32

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