Gambas France BETA


Pas de compte ? Incription

Arrêter dans un boucle

1
AuteurMessages
Foromus#1 Posté le 3/9/2018 à 07:22:07
Bonjour à tous,

Dans certains cas j'utilise une boucle for each, et j'aimerais pouvoir l'arrêter temporairement, ou même définitivement. Par exemple, si je souhaite contrôler des fichiers, je peux utiliser un "Message warning" pour arrêter temporairement et ça repart dès que je clique sur OK. Mais si je veux sortir complètement de la boucle, et ignorer la suite, je fais comment ?
Ensuite, je peux très bien avoir un appel de procédure dans le cycle mais là, je ne sais pas comment ça se passe. Certes, la procédure demandée va bien être appelée, mais, est-ce qu'elle va être exécutée totalement avant de revenir dans la boucle, ou, est-ce que la boucle va reprendre avant la fin de l'exécution de la procédure ? J'ai eu un cas de figure semblable et je ne m'en suis sorti qu'en mettant une autre boucle do loop à l'intérieur, et je n'en sortais que par un booleen que je modifiais par ailleurs. Voici résumé les solutions et surtout les questions :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
........
FOR EACH files IN Dir(/machin)
n =+ 1
......
......
IF condition THEN Message.warning("Souci")
.....
.....
Flag1 = TRUE
MaProcedure2
DO UNTIL Flag1 = FALSE
LOOP
......
'[i]Là, je voudrais sortir complètement et ignorer le reste du répertoire, comment je fais ?[/i]
NEXT
........

PRIVATE SUB MaProcedure()
'[i]Là, je dois rentre un choix[/i]
......
'[i]Quand le choix est fait[/i]
Flag1 = FALSE
END


J'espère ne pas être trop confus...
didier18#2 Posté le 3/9/2018 à 14:02:58
Bonjour Foromus

Pourquoi n'utiliser qu'un seul bouton ?
Le message warning permet l'utilisation jusqu'à 3 boutons...
Pour l'exemple, ouvrir un nouveau projet, mettre "button1" sur le form
Dans la propriété texte mettre "Test boucle"
Enfin copier/coller le code...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PUBLIC SUB Form_Open() 'à l'ouverture du formulaire
DIM i AS INTEGER
DIM hfile AS File
IF NOT Exist("/tmp/boucle") THEN MKDIR "/tmp/boucle" 'création du répertoire contenant les fichiers
FOR i = 0 TO 49 'création de 50 fichiers
hfile = OPEN "/tmp/boucle/fichier" & i FOR CREATE 'créer le fichier[i] dans le répertoire /tmp/boucle
CLOSE hfile 'ferme le fichier[i] que l'on vient de créer
NEXT
END

PUBLIC SUB Button1_Click() 'quand l'utilisateur clique sur le button1
DIM i, j AS INTEGER
DIM fichier, smsg AS STRING
FOR EACH fichier IN Dir("/tmp/boucle") 'pour chaque fichiers contenus dans le répertoire
IF fichier LIKE "fichier2" THEN 'si le fichier est comme "fichier2"...
smsg = ("le fichier n°2 existe." & "\n"
smsg &= ("voulez-vous le supprimer ?")
j = Message.Warning(smsg, ("Oui") & "\n" & ("supprimer"), ("Non") & "\n" & ("garder"), ("Quitter"))
SELECT j 'on selectionne selon la valeur de j (qui ne peut contenir que 1 ou 2 ou 3)
CASE 1 'c'est le bouton (oui supprimmer)
TRY KILL "/tmp/boucle/fichier2" 'essai de supprimer le fichier
CASE 2 'c'est le bouton (non garder)
RETURN 'sort...
CASE 3 'c'est le bouton (quitter)
ME.Close 'ferme l'application
END SELECT
ENDIF
NEXT
'si le fichier a déjà été supprimé ou pas trouvé...
IF NOT Exist("/tmp/boucle/fichier2") THEN Message.Info("le fichier2 n'exite pas")
END


Dans ce cas, tu auras bien 3 actions selon le choix utilisateur...

soit on supprime le fichier n°2 (ou toute autre action qui sera appelée par une procédure)
Soit on sort de la boucle (ou toute autre action qui sera appelée par une procédure)
Soit on quitte l'application (ou toute autre action qui sera appelée par une procédure)

Bien entendu il te faudra adapter à ton besoin.
Est-ce que cela t'aide ?

Bonne journée.
Foromus#3 Posté le 3/9/2018 à 15:29:53
Bonjour Didier,

Merci pour cette réponse.
Le code présenté me semble accessible, quant à la fonction message.warning, j'utilise souvent, avec plusieurs types de réponses, là, je sais faire... Même si j'ai tendance à utiliser des If pour exploiter les réponses ( beaucoup plus court et sans risques, puisqu'il n'y a qu'une seule réponse possible), le select case me sert dans d'autres circonstances, mais par habitude, probablement.
Si j'ai bien compris :
Return me sort, et du select case ET du for each next ? Donc, le reste de la procédure est ignoré (c'est du reste le but de return).
Like, je ne connaissais pas, pas plus que try (kill oui)
Pour la ligne 30, j'aurais mis un Catch avant, à la 29....
Pour le "\n", j'ai un petit passage à vide, je ne sais plus si c'est un espace ou un retour chariot... Dans l'exemple, ça ne fait bien que 3 possibilités et pas 5. (Désolé).
Mais tout n'est pas encore clair dans mon esprit. Quand on appelle une procédure à partir de l'intérieur d'une boucle, que se passe-t-il ? J'ai vu, quand j'ai du faire du pas-à-pas (déboggage), des fois, le cheminement du programme n'était pas évident : appel d'une procédure ou d'un autre formulaire, puis retour à l'envoyeur pour terminer la procédure appelante. Pour peu qu'il y ait 3 ou 4 trucs d'emmanchés, ça n'était pas évident.
Dans un cas précis, j'avais besoin, en cours, de faire un choix, à cet effet, je mets à "Visible" un panel avec des boutons radio, et et un bouton "Valider" qui actera mon choix radio. Tant que je n'ai pas validé, il faut que le système reste en attente, tant dans le panel que dans la procédure appelante, or, il me semble que le fait d'afficher un panel ne va pas bloquer, comme dans un message.warning. C'est du reste dans ce cas précis que je m'en suis sorti en mettant un flag booleen et une boucle do loop...
Bon, j'ai encore des questions - en particulier sur une saturation de la RAM de la machine (et du swap....), j'en parlerai après, dans d'autres posts peut-être...
Merci beaucoup !
didier18#4 Posté le 4/9/2018 à 09:19:05
Bonjour Foromus

"Donc, le reste de la procédure est ignoré (c'est du reste le but de return)."
Oui et non… En fait "RETURN" peut aussi te "returner" la valeur d’une expression…

"LIKE" fait partie des opérateurs de comparaison de chaînes, dans l’exemple j’aurai pu remplacer like par =
Pour rappel (repris de l’aide gambas) :

Chaîne = Chaîne Retourne si deux chaînes sont égales.
Chaîne == Chaîne Retourne si deux chaînes sont égales. La comparaison est insensible à la casse.
Chaîne LIKE Chaîne Vérifie si une chaîne correspond au motif.
Chaîne MATCH Chaîne Vérifie si une chaîne correspond à une expression régulière PCRE. DEPUIS 3.5
Chaîne BEGINS Chaîne Teste si une chaîne débute par le motif.
Chaîne ENDS Chaîne Teste si une chaîne se termine par le motif.
Chaîne <> Chaîne Retourne si deux chaînes sont différentes.
Chaîne1 < Chaîne2 Retourne si Chaîne1 est strictement inférieure à Chaîne2.
Chaîne1 > Chaîne2 Retourne si Chaîne1 est strictement supérieure à Chaîne2.
Chaîne1 <= Chaîne2 Retourne si Chaîne1 est inférieure ou égale à Chaîne2.
Chaîne1 >= Chaîne2 Retourne si Chaîne1 est supérieure ou égale à Chaîne2.

"TRY" te permet d’exécuter une commande sans générer d’erreur, ce qui serai le cas si tu veux "killer" un fichier inexistant.
Si cette tentative de suppression génère une erreur, tu peux la récupérer avec la commande "ERROR" (regarde l’exemple dans l’aide).

"Pour la ligne 30, j'aurais mis un Catch avant, à la 29...."
Inutile, car la ligne 30 est un "IF" que je qualifierai de "oui/non ou boolean", en fait on teste si le "fichier2" n’existe pas, donc il ne peut pas y avoir d’erreur possible…
- Oui il existe, on passe à la ligne suivante (sans se préoccuper de ce qui se trouve après le "THEN").
- Non il n’existe pas, on affiche le message et après validation du message on passe à la ligne suivante.
En réalité les lignes 29 et 30 pourraient très bien être supprimées sans que cela nuise au bon fonctionnement de la procédure, c’est juste une info à destination de l’utilisateur (dans certains cas cela peut devenir rapidement barbant d’avoir à valider des fenêtres d’information)

Le "\n" est un retour à la ligne c’est l’équivalent de Chr$(10).
Il y a aussi le "\t" qui fait une tabulation (je ne sais pas son équivalent Chr$()).

J’espère que ces détails te seront utile et que cela t’aidera à l’avancement ton programme.

Bonne journée.
Foromus#5 Posté le 4/9/2018 à 11:53:37
Bonjour Didier,

Oui et non… En fait "RETURN" peut aussi te "returner" la valeur d’une expression…

Là, oui, j'utilise (au besoin...)
Pour le retour à la ligne, j'utilisais Chr$(13), il me semble (\n : trou de mémoire de ma part).
Je reviens à ma question "Arrêt en cours de boucle".
Message.Warning me met une fenêtre au milieu, dans certain cas, je voudrais éviter. Je préférerais un bouton "Stop" qui suspende le processus, bouton que je transforme en "Reprendre" une fois cliqué (2 boutons, 2 procédures). La possibilité d'utiliser une Message.Warning(),donc, rien dedans, me donnerait quand même une fenêtre, avec juste le bouton OK je suppose.
Maintenant, je ne vais pas m'éterniser sur le truc, ça marche avec le Flag booleen, au fond, c'est plutôt pour apprendre, et possiblement, améliorer un code !
Exact pour la ligne 30, avec le IF : j'ai réagi trop vite...
(dans certains cas cela peut devenir rapidement barbant d’avoir à valider des fenêtres d’information)

Ça, je l'ai vécu....

Merci pour les infos !
(J'ouvre un autre fil pour la mémoire)
spheris#6 Posté le 25/10/2018 à 17:22:24
Foromus, Didier18,
En fait je prends le problème à l'envers, je ne dis pas :

If gnagna = true then
maboucle

mais je dis

If gnagna = false THEN
sortdelaboucle
else
maboucle
endif

;)
1