Question sur une boucle do...while [c] - C - Programmation
Marsh Posté le 08-08-2007 à 10:00:17
Desolé j'ai fait une erreur, le || fonctionne bien aussi mais ce que je voulais savoir c'etait pourquoi le | fonctionne lui.
Marsh Posté le 08-08-2007 à 11:33:52
Je pense que la comparaison renvoie "1" lorsqu'elle est vrai, 0 si fausse. Donc, comme on ne s'intéresse qu'au 1er bit, le | a le même résultat que le ||
Marsh Posté le 08-08-2007 à 19:34:28
mrbebert a écrit : Je pense que la comparaison renvoie "1" lorsqu'elle est vrai, 0 si fausse. Donc, comme on ne s'intéresse qu'au 1er bit, le | a le même résultat que le || |
Exactement. Si tu écris "cond1 || cond2" il s'agit d'un ou logique qui obéit aux règles booléennes qui sera vrai si l'une des deux conditions est vérifiée. Le résultat numérique de cette écriture devrait être (suis pas sûr dans ce coup là) la valeur de la première condition vraie
ex: int a; a=(5 || 8) => je pense que "a" vaudra 5 mais dans tout les cas, le test "if (5 || 8)" est vrai.
Dans la 2° écriture, si tu écris "cond1 | cond2", il s'agit d'une opération mathématique sur chaque bit de "cond1" pris avec chaque bit de "cond2". Si un seul des bits vaut 1, l'ensemble complet ne vaudra pas 0 donc sera considéré comme vrai. Mais il s'agit d'un jonglage mathématique associé à la caractéristique du C concernant l'évaluation de ses booléens (0 = faux, pas 0 = vrai) et non d'une vraie expression booléenne.
PS: Je ne vois pas trop le rapport de ce topic avec une boucle do...while... mais ça me rappelle une fois j'avais posé à mes élèves 3 boucles pièges (en leur disant bien que c'était piégé) et je leur demandait d'évaluer le comportement des boucles
La première assez simple
int i; |
La seconde plus subtile
unsigned char i; |
La troisième vraiment ignoble
int i; |
Ca avait été un bon moment de bonne humeur
Marsh Posté le 09-08-2007 à 09:19:36
Dans le genre piege:
Code :
|
Marsh Posté le 09-08-2007 à 09:50:47
ReplyMarsh Posté le 09-08-2007 à 10:16:45
matafan a écrit : Je dois pas être bien réveillé, mais je vois pas le piège ? |
Ben tu traites pas l'élément [0] !!! (mais oui, moi aussi ça m'a pas sauté aux yeux immédiatements )
Marsh Posté le 09-08-2007 à 10:22:29
Sve@r a écrit : |
C'est le premier. Le deuxieme piege, c'est que
Code :
|
n'est toujours pas bon.
Marsh Posté le 09-08-2007 à 10:48:30
Un Programmeur a écrit :
|
Oui mais celui-là, comme je me suis déjà fait avoir avec, je le connais
Ca marchera si tu mets "ssize_t i" mais perso, si je dois écrire une boucle de ce style, je préfère commencer à sizeof(table)/sizeof(*table) et bosser sur "i - 1"...
Marsh Posté le 09-08-2007 à 11:24:19
Le coup de pas traiter l'élément 0 j'avais vu mais bon, c'est pas un piège, j'imagine que si on met > 0 en test de fin de boucle c'est qu'on ne veut pas traiter l'élément 0... A mon avis notre ami pensait au piège unsigned / >= 0, et s'est planté dans son message
Marsh Posté le 09-08-2007 à 11:49:22
matafan a écrit : A mon avis notre ami pensait au piège unsigned / >= 0, et s'est planté dans son message |
Non, c'est le sujet de son 2° post.
matafan a écrit : Le coup de pas traiter l'élément 0 j'avais vu mais bon, c'est pas un piège, j'imagine que si on met > 0 en test de fin de boucle c'est qu'on ne veut pas traiter l'élément 0 |
Non. C'est plutôt le programmeur qui programme une boucle dans le bon sens. Par exemple il a créé 10 alloc dans un tableau de pointeurs et il veut les libérer
Code :
|
Puis, il se dit que ce serait plus esthétique de libérer les pointeurs dans l'ordre inverse de leur création, comme si la mémoire était un lifo et que c'est plus sensé de les libérer à l'envers (et ça peut se justifier si l'élément "i" sert de support à l'élément "i + 1" ). Donc s'il fait pas trop gaffe, il inversera simplement les opérandes sans vraiment y penser
Code :
|
Le piège stupide quoi... (et en plus il commence hors tableau)
Marsh Posté le 09-08-2007 à 14:17:03
Sve@r a écrit : perso, si je dois écrire une boucle de ce style, je préfère commencer à sizeof(table)/sizeof(*table) et bosser sur "i - 1"... |
Code :
|
Marsh Posté le 09-08-2007 à 14:30:21
matafan a écrit : Le coup de pas traiter l'élément 0 j'avais vu mais bon, c'est pas un piège, j'imagine que si on met > 0 en test de fin de boucle c'est qu'on ne veut pas traiter l'élément 0... A mon avis notre ami pensait au piège unsigned / >= 0, et s'est planté dans son message |
Le piege est qu'on n'est pas dans la situation idiomatique de traiter des intervalles comprenant la borne initiale mais pas la finale. Dans mon exemple j'avais deja corrige en partie mais pas tout, le probleme avec le comportement des non signes etait bien un deuxieme.
Question auxilliaire, comme faire une boucle sur les nombres de debut a fin, y compris les deux bornes mais vide si debug > fin.
Code :
|
(Et la je suis interesse par une belle solution)
Marsh Posté le 09-08-2007 à 14:33:11
Un Programmeur a écrit :
|
Ah oui, décrémenter i lors de son évaluation pour que le traitement se fasse sur "i -1" c'est assez fin. J'y avais point pensé. Mais dans ce genre d'écriture on frôle dangereusement le point où le code devient porc (the pig's point). Evidemment tout se discute...
Un Programmeur a écrit : Question auxilliaire, comme faire une boucle sur les nombres de debut a fin, y compris les deux bornes mais vide si debut > fin.
|
Euh... ça me semble trivial (ou alors j'ai pas compris le pb) !!!
Code :
|
Il est évident que si "debut > fin", la boucle ne se fera pas et restera vide !!!
Un Programmeur a écrit : (Et la je suis interesse par une belle solution) |
Noproblemo
Code :
|
Ca c'est magnifique non ???
Marsh Posté le 09-08-2007 à 16:33:37
Un Programmeur a écrit : Et si fin = LONG_MAX ? |
Ah oui, boucle infinie (si "i" reste long). Mais dans ce cas, debut peut pas être > fin...
Marsh Posté le 09-08-2007 à 16:51:21
Sve@r a écrit : |
Le probleme est d'ecrire un code le plus simple possible que marche dans tous les cas.
Marsh Posté le 09-08-2007 à 17:24:45
Un Programmeur a écrit : |
for (i=debut; i <= fin && fin + 1 > fin; i++)
Marsh Posté le 09-08-2007 à 17:41:51
Sve@r a écrit : |
arrivee + 1 > fin je suppose. Ne fonctionne pas pour fin = LONG_MAX
Marsh Posté le 09-08-2007 à 20:23:50
Un Programmeur a écrit : |
Non, c'est bien "fin + 1 > fin" que je voulais dire (j'ai modifié mon post). Si fin = LONG_MAX, fin + 1 = LONG_MIN et le test sera faux
Marsh Posté le 09-08-2007 à 21:35:07
Sve@r a écrit : |
Et on ne passe pas dans la boucle. De plus, j'aime pas les comportements indéfinis (et dépasser LONG_MAX avec un calcul sur des entiers en est un, voir http://gcc.gnu.org/ml/gcc/2006-12/msg00459.html pour la tendance des optimiseurs à utiliser de plus en plus les ouvertures offertes par les comportements indéfinis).
Code :
|
est la manière la plus simple que j'ai trouvé qui n'a aucun problème (si on accepte l'overflow sur long, i++ != fin est un peu plus simple) mais on ne peut pas dire que j'apprécie.
Code :
|
fonctionne aussi mais ne me plait pas plus.
Marsh Posté le 09-08-2007 à 22:22:52
Un Programmeur a écrit : Et on ne passe pas dans la boucle. |
Ben c'est ce que j'ai compris en lisant la phrase
Citation : ...mais vide si debut > fin... |
Maintenant je comprends que tu veux une boucle qui puisse traiter toute la gamme des valeurs possibles.
Un Programmeur a écrit : De plus, j'aime pas les comportements indéfinis (et dépasser LONG_MAX avec un calcul sur des entiers en est un, voir http://gcc.gnu.org/ml/gcc/2006-12/msg00459.html pour la tendance des optimiseurs à utiliser de plus en plus les ouvertures offertes par les comportements indéfinis). |
Tu es plus pointu que moi. Je vais pas jouer la faignasse mais s'il me fallait lire toute la normalisation du dernier détail j'en finirais plus...
Un Programmeur a écrit :
fonctionne aussi mais ne me plait pas plus. |
Oui, quand je vois la solution je me dis "j'aurais pu trouver moi aussi" mais bon, j'aurais jamais penser à utiliser l'opérateur de concaténation pour shunter le fait que "i++" puisse donner 0. Bizarrement j'ai plus rapidement pigé la 2° soluce...
Ca m'a donné l'idée du truc suivant:
Code :
|
Marsh Posté le 09-08-2007 à 22:25:41
ReplyMarsh Posté le 10-08-2007 à 15:24:40
matafan a écrit : C'est quand même plus simple d'ajouter un break en fin de boucle si i == fin. |
Montre ta solution complete.
Marsh Posté le 10-08-2007 à 17:13:08
Un Programmeur a écrit : |
i=debut; |
Marsh Posté le 10-08-2007 à 17:31:05
C'est pas vraiment different de
Code :
|
que j'avais cite si on acceptait l'overflow (ce que je ne fais pas parce que les optimiseurs se mettent a utiliser le fait qu'un overflow de nombres signes est un comportement indefini) mais sans le test qui empeche le passage dans la boucle quand debut > fin.
Code :
|
Mais on ne peut pas dire que ca m'enchante plus. J'aime bien que tout le controle de la boucle soit dans le for.
Code :
|
Marsh Posté le 10-08-2007 à 19:00:07
Un Programmeur a écrit : C'est pas vraiment different de
que j'avais citée si on acceptait l'overflow |
Ben l'exemple invoké par Matafan et que j'ai codé au dessus ne se préoccupe pas de l'overflow !!!
Un Programmeur a écrit :
|
Ben ce que j'avais proposé juste avant était géré dans le for
Code :
|
Evidemment je joue sur l'overflow (qui était aussi l'idée de ma 2° boucle piège en début de topic). Mais ya pas de miracle. Si tu veux faire un "for" (où l'évaluation se fait en début de boucle), faut qu'en début de boucle tu aies gardé une trace de la boucle précédente. Si cette boucle précédente était la dernière qu'il aurait dû se passer alors tu rend l'évaluation fausse...
Ce qui nous ramène à ceci (issu de tes premières idées)
Code :
|
Marsh Posté le 08-08-2007 à 09:55:44
Bonjour à tous, voilà j'ai un petit problème en C, en fait je ne comprends pas pourquoi je ne peux pas utiliser le "OU" logique : || dans ce programme et que je doive utiliser le "OU" binaire : |.
Voici la boucle en question :