Je convertissais un algorithme C ++ en C #. Je suis tombé sur ceci pour la boucle:
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
Il ne donne aucune erreur en C ++, mais il le fait en C # (impossible de convertir un int en booléen). Je ne peux vraiment pas comprendre cela pour la boucle, où est la condition?
Quelqu'un peut-il expliquer?
PS. Juste pour vérifier, pour adapter un VECTEUR à une LISTE, b.back () correspond-il à b [b.Count-1]?
u--
. Les points-virgules sont utilisés pour délimiter les différentes parties de l'for
instruction.; u-- != 0;
b
,u
,v
, etc. La seule raison pour laquelle ils ont été nommés ainsi parce que quelqu'un voulait avoir l' air intelligent en faisant leur code illisible.do
signifie en C ++" - obtiendra des milliers de résultats de la part de débutants à la recherche d'un tutoriel.Réponses:
La condition de la
for
boucle est au milieu - entre les deux points-virgules;
.En C ++, il est possible de mettre presque n'importe quelle expression comme condition: tout ce qui est évalué à zéro signifie
false
; non nul signifietrue
.Dans votre cas, la condition est la suivante
u--
: lorsque vous convertissez en C #, ajoutez simplement!= 0
:la source
u = b.size() - 1
place.Beaucoup de réponses précises, mais je pense qu'il vaut la peine d'écrire l'équivalent en boucle while.
Est équivalent à:
Vous pouvez envisager de refactoriser au format while () lorsque vous traduisez en C #. À mon avis, c'est plus clair, moins un piège pour les nouveaux programmeurs et tout aussi efficace.
Comme d'autres l'ont souligné - mais pour que ma réponse soit complète - pour que cela fonctionne en C #, vous devrez changer
while(u--)
pourwhile(u-- != 0)
.... ou
while(u-- >0)
juste au cas où vous commenceriez par négatif. (OK,b.size()
ne sera jamais négatif - mais considérons un cas général où peut-être quelque chose d'autre a initialisé u).Ou, pour le rendre encore plus clair:
Il vaut mieux être clair que concis.
la source
while (u-- >0)
forme. Si l'espacement est gâché, vous pourriez vous retrouver avec une boucle "jusqu'à zéro":,while (u --> 0)
ce qui a tendance à dérouter tout le monde au premier coup d'œil. ( Je ne sais pas si c'est C # valide, mais c'est en C, et je pense que ça peut l'être aussi en C ++? )for
au lieu dewhile
est précisément que vous mettez l'initialisation et l'incrémentation / décrémentation dans une seule instruction, et cela ne rend pas nécessairement le code plus difficile à comprendre. Sinon, nous ne devrions pas utiliserfor
du tout.--
jeton suivi d'un>
jeton. Deux opérateurs distincts. Une boucle «jusqu'à zéro» est juste une simple combinaison de post-décrémentation et de supérieur à. La surcharge d'opérateurs C ++ ne crée pas de nouveaux opérateurs, elle réutilise simplement les opérateurs existants.La condition est
u--;
, car il est dans la deuxième position de l' instruction for .Si la valeur de
u--;
est différente de 0, elle sera interprétée commetrue
(c'est-à-dire transtypée implicitement en valeur booléennetrue
). Si, à la place, sa valeur est 0, il sera converti enfalse
.C'est un très mauvais code .
Mise à jour: j'ai discuté de l'écriture de boucles «for» dans ce billet de blog . Ses recommandations peuvent être résumées dans les paragraphes suivants:
Cet exemple enfreint clairement ces recommandations.
la source
Ce sera la forme C # de votre boucle.
Remplacez simplement l'équivalent pour size () et back ().
Ce qu'il fait, c'est inverser la liste et les stocker dans un tableau. Mais en C #, nous avons directement une fonction définie par le système pour cela. Vous n'avez donc pas besoin d'écrire cette boucle également.
la source
v = b.back();
supprimant l'initialiseur for, n'avez-vous pas simplement changé son fonctionnement, puisque lev = p[v]
est remplacé parv = b.back();
été exécuté une fois avant le début des itérations et av = p[v]
été exécuté au début de chaque itération. Dans cette version C #v = p[v]
est toujours exécutée au début de chaque itération maisv = b.back();
est exécutée juste après, en changeant la valeur dev
pour l'instruction suivanteb[u] = v;
. (peut-être que la question a été modifiée après l'avoir lue)v = b.back()
. Vous l'avez exécuté à chaque itération de boucle au lieu de la première - nous ne savons pas ce queback()
fait (y a-t-il des effets secondaires? Cela change-t-il la représentation interne deb
?), Donc cette boucle n'est pas équivalente à celle de la question.v = b.back()
était déplacé en dehors de la boucle, au-dessus. (De plus, si vous essayez de répondre à quelqu'un, utilisez-le@
devant son nom pour que nous recevions une notification)est l'initialisation.
est la condition.
est l'itération
la source
La condition est le résultat de
u--
, qui est la valeur deu
avant qu'elle ne soit décrémentée.En C et C ++, an
int
est convertible en booléen en faisant implicitement une!= 0
comparaison (0 estfalse
, tout le reste esttrue
).b.back()
est le dernier élément d'un conteneur, c'est-à-b[b.size() - 1]
dire quandsize() != 0
.la source
En C, tout ce qui n'est pas nul est
true
dans des contextes "booléens", tels que la condition de fin de boucle ou une instruction conditionnelle. En C # , vous devez faire ce contrôle explicite:u-- != 0
.la source
Comme indiqué par d'autres, le fait que C ++ ait un cast implicite en booléen signifie que le conditionnel est
u--
, qui sera vrai si la valeur est différente de zéro.Cela vaut la peine d'ajouter que vous avez une fausse hypothèse en demandant "où est le conditionnel". En C ++ et C # (et dans d'autres langages de syntaxe similaire), vous pouvez avoir un conditionnel vide. Dans ce cas , il est toujours vraie, de sorte que la boucle continue pour toujours, ou jusqu'à ce que d'autres sorties de l' état (via
return
,break
outhrow
).En effet, n'importe quelle partie de l'instruction for peut être omise, auquel cas elle n'est tout simplement pas exécutée.
En général,
for(A; B; C){D}
oufor(A; B; C)D;
devient:N'importe lequel ou plusieurs parmi A, B, C ou D peuvent être omis.
En conséquence, certains favorisent
for(;;)
les boucles infinies. Je le fais parce que pendant quewhile(true)
c'est plus populaire, je lis cela comme "jusqu'à ce que la vérité finisse par être vraie", ce qui semble quelque peu apocalyptique comparé à ma lecturefor(;;)
comme "pour toujours".C'est une question de goût, mais comme je ne suis pas la seule au monde à aimer,
for(;;)
il vaut la peine de savoir ce que cela signifie.la source
toutes les réponses sont correctes: -
La boucle for peut être utilisée de différentes manières, comme suit:
la source
Dans le code ci-dessus,
u
etv
sont initialisés avecb.size()
etb.back()
.Chaque fois que la condition est vérifiée, elle exécute également l'instruction de décrémentation, c'est-à-dire
u--
.La
for
boucle se terminera quandu
deviendra0
.la source
L'erreur rencontrée dans C # lui-même efface le doute. La boucle for recherche un
condition pour terminer. Et comme nous le savons,
mais C # ne peut pas traiter cela seul contrairement à C ++. La condition que vous recherchez est donc
mais vous devez explicitement donner la condition en C # comme
ou
Mais essayez toujours d'éviter ce genre de pratique de codage. le
indiqué ci-dessus en réponse est l'une des versions les plus simplifiées de votre
la source
Si vous êtes habitué à C / C ++, ce code n'est pas si difficile à lire, bien qu'il soit assez laconique et pas si génial en code. Alors laissez-moi vous expliquer les parties qui sont plus Cism qu'autre chose. Tout d'abord, la syntaxe générale d'une boucle C for ressemble à ceci:
Le code d'initialisation est exécuté une fois. Ensuite, la condition est testée avant chaque boucle et enfin l'incrément est appelé après chaque boucle. Donc, dans votre exemple, vous trouverez que la condition est
u--
Pourquoi fonctionne-t-il
u--
comme une condition en C et non en C #? Parce que C convertit implicitement beaucoup de choses trop booléennes et cela peut causer des problèmes. Pour un nombre, tout ce qui est différent de zéro est vrai et zéro est faux. Donc, il compte à rebours de b.size () - 1 à 0. Avoir l'effet secondaire dans la condition est un peu ennuyeux et il serait préférable de le mettre dans la partie incrémentielle de la boucle for, bien que beaucoup de C le code fait cela. Si je l'écrivais, je le ferais plus comme ceci:La raison en est, du moins pour moi, c'est plus clair. Chaque partie de la boucle for fait son travail et rien d'autre. Dans le code d'origine, la condition modifiait la variable. La partie incrémentation faisait quelque chose qui devrait être dans le bloc de code, etc.
L'opérateur virgule peut également vous lancer pour une boucle. En C, quelque chose comme
x=1,y=2
ressemble à une instruction en ce qui concerne le compilateur et s'inscrit dans le code d'initialisation. Il évalue simplement chacune des parties et renvoie la valeur de la dernière. Donc par exemple:imprimerait 2.
la source