29 votes

Comment fonctionne continue ?

J'essaie de comprendre le fonctionnement de "continue". J'ai compris le concept du mot-clé mais lorsque j'exécute différents programmes, il fonctionne différemment :-/ Laissez-moi vous montrer quelques exemples :

Si je lance ce programme :

int j = 0;
int i = 0;
LABEL1: for (; i < 3; i++) {
  if (true)
    continue;
}

La valeur de i sera 3. Jusqu'ici tout va bien. Ajoutons une boucle externe :

int j = 0;
int i = 0;
LABEL2: for (; j < 3; j++) {
  LABEL1: for (; i < 3; i++) {
    if (true)
      continue LABEL2;
  }
}

La valeur de i va être ... 0 ! ! Je ne comprends pas pourquoi i n'est pas incrémenté si continue est utilisé avec un label qui va dans la boucle externe. Quelqu'un peut-il m'expliquer pourquoi ? Avez-vous des problèmes de ce genre avec break ? ou avec un do {} while ?

J'apprécie vraiment toute aide que vous pouvez m'apporter.

28voto

arshajii Points 65653

L'essentiel for La structure du relevé est la suivante :

BasicForStatement:
for ( \[ForInit\] ; \[Expression\] ; \[ForUpdate\] ) Statement

Maintenant, de JLS §14.14.1.3. Achèvement abrupt de for Déclaration :

Si l'exécution de la Déclaration se termine brusquement à cause d'un continue sans étiquette puis les deux étapes suivantes sont exécutées en séquence :

  1. D'abord, si le ForUpdate est présente, les expressions sont évaluées en séquence de gauche à droite ; leurs valeurs, le cas échéant, sont rejetées. Si le ForUpdate n'est pas présente, aucune action n'est entreprise.

  2. Deuxièmement, un autre for étape d'itération est effectuée.

Si l'exécution de la Déclaration se termine brusquement à cause d'un continue avec étiquette L alors il y a un choix à faire :

  • Si le for La déclaration a l'étiquette L puis les deux étapes suivantes sont exécutées en séquence :

    1. Premièrement, si le ForUpdate est présente, les expressions sont évaluées en séquence de gauche à droite ; leurs valeurs, le cas échéant, sont rejetées. Si la partie ForUpdate n'est pas présent, aucune action n'est entreprise.

    2. Deuxièmement, un autre for étape d'itération est effectuée.

  • Si le for La déclaration n'a pas d'étiquette L le for se termine brusquement à cause d'un "continue with label". L .

(c'est moi qui souligne)

ForUpdate dans votre cas, c'est i++ . Sur la base de ce qui précède :

  • Votre premier extrait relève du premier cas, donc i est incrémenté.

  • Votre deuxième extrait relève du deuxième cas, donc i n'est pas incrémenté parce que le for La déclaration se termine brusquement.

Notez que si vous aviez continue LABEL1 dans votre deuxième extrait, i aurait été incrémenté comme dans votre premier extrait (conformément à la JLS).

Comme conseil pour l'avenir, pour définitif les réponses concernant les règles de langue/sémantique, vous devez toujours consultez la spécification de la langue. Pour Java, il s'agit du JLS .

14voto

Frank Points 157

C'est vraiment normal. Le déroulement de l'expérience est comme ça :

  1. j=0
  2. i=0
  3. La boucle LABEL 2 est entrée,
  4. LABEL 1 boucle entrée,
  5. passer à l'ÉTIQUETTE 2
  6. j++
  7. LABEL 1 boucle entrée,
  8. passer à l'ÉTIQUETTE 2
  9. j++
  10. LABEL 1 boucle entrée,
  11. continuer à LABEL 2 ... jusqu'à ce que j==3

7voto

ammoQ Points 17866

i serait augmenté à la fin de la boucle interne. Mais continue LABEL2 saute hors de la boucle interne, à la fin de la boucle externe, donc i n'est pas augmenté ; au lieu de cela, seul j est augmenté jusqu'à ce que la condition de la boucle externe ne soit plus remplie.

Peut-être que cela devient plus clair lorsque nous réécrivons le code avec while à la place :

int j=0;
int i = 0;
while (j<3) {
    while(i<3) {
       if (true)
           goto END_OF_LOOP2;

       END_OF_LOOP1: i++;
    }
    END_OF_LOOP2: j++;
}

6voto

Noread Points 133

Continue fait simplement ce que son nom suggère, il passe immédiatement à l'exécution suivante de la boucle sans exécuter le reste du code dans la boucle.

Donc si vous avez une boucle comme celle-ci :

int j=0;
int i = 0;
    LABEL1 : for(;i < 3; i++){
        if (true) {
            continue;
        }
        someOtherMethod();
    }

La partie someOtherMethod n'est jamais exécutée car vous appuyez toujours sur la touche continue.

La raison pour laquelle votre compteur n'est jamais incrémenté a à voir avec les étiquettes, vous pouvez marquer une boucle avec une étiquette (dans votre cas LABEL1 et LABEL2 et utiliser cette étiquette pour continuer une des boucles extérieures de votre boucle intérieure.

Donc, avec votre code, la boucle de LABEL1 n'a jamais la chance d'incrémenter son compteur et donc i reste 0 parce que votre instruction continue passe immédiatement à l'itération suivante de la boucle externe.

4voto

Zhenxiao Hao Points 1582
continue LABEL2; 

que seule la boucle extérieure augmente. si vous avez

LABEL2 : for(;j <3;j++){
    LABEL1 : for(;i < 3; i++){
             if (true)
                 continue LABEL1;
             }
     }

i augmentera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X