Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 10:19 19 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Exiting Nested "FOR . . . NEXT"  loops

     Page 1 of 3    
Author Message
Andrew_G
Guru

Joined: 18/10/2016
Location: Australia
Posts: 839
Posted: 08:57pm 03 Oct 2022
Copy link to clipboard 
Print this post

Hi all,
Fairly trivial but out of interest I'm looking for a neat way to EXIT nested FOR . . . NEXT loops.

I have a set of multiple loops that when a test is true I want to EXIT all of the loops and move on.
I could use a GOTO statement.

OR (& what I am doing now) is:

When the test becomes true set a flag eg "ExitNow" and just before each NEXT statement test the flag and, if true, invoke "EXIT FOR".
Then after the dust has settled set ExitNow to FALSE again and carry on.

Is there a better way to EXIT all the FORs?

Cheers,

Andrew

Here is an extract of the code, with the old GOTO statements commented out:


. . .
 For dd = 3 to 3
   for hh = 1 to 3
     for mm = 0 to 59
       for ss = 0 to 0
         In$ = str$(dd,2,0,"0") + "-04-2022 " +str$(hh,2,0,"0")+":"+Str$(mm,2,0,"0")+":"+str$(ss,2,0,"0")
         print In$, IsDST(In$), Out$
         if IsDST(In$) = 0 and mm > 2 then ExitNow = True: Exit For  'Goto Skip
       Next ss
       If ExitNow then Exit For
     Next mm
     If ExitNow then Exit For
   next hh
   If ExitNow then Exit For
 Next dd
 ExitNow = False
 
'Skip:
.
.
.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5879
Posted: 09:26pm 03 Oct 2022
Copy link to clipboard 
Print this post

One method I used was:
Make the outer loop a DO...LOOP and then you can EXIT DO to get out from any level.
Not sure if Peter/Geoff will groan but it has worked for me (so far)

Jim
VK7JH
MMedit   MMBasic Help
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 09:33pm 03 Oct 2022
Copy link to clipboard 
Print this post

There is no EXIT ALL LOOPS command and your method is the most "sensible" method of achieving this.  Jumping straight out of the loop as you suggested will also work as MMBasic is designed to handle such manoeuvres, although it is untidy and will give the GOTO police a heart attack.

The only other way that I can think of to do what you want is to set all the looping variables to a value that is greater than their terminating TO value (is, 999).  However that is also rather untidy.

Geoff
Geoff Graham - http://geoffg.net
 
Tinine
Guru

Joined: 30/03/2016
Location: United Kingdom
Posts: 1646
Posted: 09:46pm 03 Oct 2022
Copy link to clipboard 
Print this post

  Quote  
GOTO police a heart attack


 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 1769
Posted: 09:52pm 03 Oct 2022
Copy link to clipboard 
Print this post

Over use of GOTO gets confusing, however a single instance isn't a problem. Especially if the Label is explanatory.

GOTO Nest_Exit

or
GOTO Exit_All_Loops
Edited 2022-10-04 07:56 by phil99
 
Andrew_G
Guru

Joined: 18/10/2016
Location: Australia
Posts: 839
Posted: 10:36pm 03 Oct 2022
Copy link to clipboard 
Print this post

Thanks folks.

I like Jim's idea - if Geoff and Peter have no objections?
(It just needs an EXIT DO after the last NEXT, as well as where the test becomes TRUE)

Cheers,

Andrew
Edited 2022-10-04 08:39 by Andrew_G
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5879
Posted: 10:41pm 03 Oct 2022
Copy link to clipboard 
Print this post

Or
Do


LOOP UNTIL 1=1

or
replace the outer for-next with the do-loop

My concern is I don't know if the stack gets properly cleared.

Jim
Edited 2022-10-04 08:42 by TassyJim
VK7JH
MMedit   MMBasic Help
 
Andrew_G
Guru

Joined: 18/10/2016
Location: Australia
Posts: 839
Posted: 10:43pm 03 Oct 2022
Copy link to clipboard 
Print this post

Very cleaver Jim!
(that's why you really are a Guru!)

Andrew
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9042
Posted: 12:18am 04 Oct 2022
Copy link to clipboard 
Print this post

I do pretty much the same thing as your example: If Y THEN EXIT DO, and I set and clear Y as needed to make loops drop to the next level.  Its always worked for me, so I think that is a good a way as any, and pretty much anyone else reading your code will understand why you did that, as I think plenty of people write exits in a similar way and for a similar reason as you just highlighted.

  Jim said  LOOP UNTIL 1=1


Huh?
One will always equal one, so how does that work?
Is that just another way of forcing an exit cos one will always equal one, so it will exit at that point?
Never seen that idea before, so it kinda shorted out my brain a bit!
Smoke makes things work. When the smoke gets out, it stops!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5879
Posted: 01:23am 04 Oct 2022
Copy link to clipboard 
Print this post

  Grogster said  
  Jim said  LOOP UNTIL 1=1


Huh?
One will always equal one, so how does that work?
Is that just another way of forcing an exit cos one will always equal one, so it will exit at that point?
Never seen that idea before, so it kinda shorted out my brain a bit!

Yes. A crude way to make sure that you only do the loop once without wasting a variable.

I normally convert the outer FOR NEXT into a DO LOOP so no need for such oddities.

Jim
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5879
Posted: 02:08am 04 Oct 2022
Copy link to clipboard 
Print this post

I ran this test on a picomite with the RC5 firmware to use the MM.INFO(STACK) function
'
 OPTION EXPLICIT
 OPTION DEFAULT INTEGER
 DIM x,y,z,t, quit
 DIM stack1, stack2
 
 stack1 = mm.info(stack)
 x = 0
 DO
'for x = 0 to 9
   FOR y = 0 TO 9
     FOR z = 0 TO 9
       t = x*100+y*10+z
       PRINT t
       IF t > 200 THEN EXIT DO ' quit = 1 : exit for
     NEXT z
'   if quit = 1 then exit for
   NEXT y
' if quit = 1 then exit for
' next x
   INC x
 LOOP UNTIL x > 9

 stack2 = mm.info(stack)
 PRINT stack1
 PRINT stack2, stack1-stack2 ' stack grows downwards


There was no obvious difference between the various methods including GOTO, setting a flag and multiple EXIT FOR and DO LOOP as a wrapper or as replacement for the outer FOR NEXT

Jim
VK7JH
MMedit   MMBasic Help
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3490
Posted: 03:36pm 04 Oct 2022
Copy link to clipboard 
Print this post

@Jim

I use
Do
Loop


All the time. No need for the 1=1......
probably a remainder of the Arduino world....
Edited 2022-10-05 01:37 by Volhout
PicomiteVGA PETSCII ROBOTS
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1639
Posted: 03:43pm 04 Oct 2022
Copy link to clipboard 
Print this post

I used to use goto but it is frowned upon now but the easiest way out of a nested for next loop. elegant.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5705
Posted: 05:22pm 04 Oct 2022
Copy link to clipboard 
Print this post

Help save GOTO! Don't let it become extinct! Join Friends Of GOTO now - we need your support urgently!


(Said with more than a little tongue in cheek and too many exclamation marks)


More seriously, I don't see much of a problem with GOTO <label>. In the days of line numbers or, even worse, GOTO <function> it could get extremely confusing, but a simple GOTO to a label can often be the clearest way to write a program. I think rejecting them out of hand is a mistake.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Martin H.

Guru

Joined: 04/06/2022
Location: Germany
Posts: 890
Posted: 05:47pm 04 Oct 2022
Copy link to clipboard 
Print this post

oh the GOTO POLICE
what is wrong with Goto?
In Assembler you wouldn't gat anywhere without Branches or Jump Statements.
Not so elegant(for some Hipsters) but sometimes necessary  

initialise:
'some Variables
LIveLost%=0

Intro:
cls:Print "Bla Bla Bla"
prepare_Playfield
Live%=5
next_Live:
LIveLost%=0
If not Live% the goto Intro
do
something
something_else
 If LIveLost% then inc Live%,-1: goto next_Live

loop

sub prepare_Playfield
end sub
sub something
end sub
sub
something_else
end sub

Edited 2022-10-05 03:48 by Martin H.
'no comment
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1639
Posted: 07:22pm 04 Oct 2022
Copy link to clipboard 
Print this post

goto supported in gcbasic and still the most elegant way of exiting nested loops.
worst was before labels and goto line numbers. zx basic, remember?
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3008
Posted: 07:27pm 04 Oct 2022
Copy link to clipboard 
Print this post

  Martin H. said  Not so elegant(for some Hipsters) but sometimes necessary


Hipster? Me? LOL indeed! Not only inelegant, but in that case, certainly not necessary. I do use GOTO when encountering an unrecoverable error deep in loops.

You only really get into trouble with larger programs (though I've seen plenty of beginners fall into places they didn't want to be with GOTOs). I have no problem with a use such as Grogster proposes, though I'd probably use the EXIT DO instead (even though it's just an obfuscated GOTO).
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1639
Posted: 07:53pm 04 Oct 2022
Copy link to clipboard 
Print this post

  TassyJim said  I ran this test on a picomite with the RC5 firmware to use the MM.INFO(STACK) function
'
 OPTION EXPLICIT
 OPTION DEFAULT INTEGER
 DIM x,y,z,t, quit
 DIM stack1, stack2
 
 stack1 = mm.info(stack)
 x = 0
 DO
'for x = 0 to 9
   FOR y = 0 TO 9
     FOR z = 0 TO 9
       t = x*100+y*10+z
       PRINT t
       IF t > 200 THEN EXIT DO ' quit = 1 : exit for
     NEXT z
'   if quit = 1 then exit for
   NEXT y
' if quit = 1 then exit for
' next x
   INC x
 LOOP UNTIL x > 9

This got my attention. Please explain mmbasic stack ie push pop and relevance to for next counters. I thought they were ram variables.

 stack2 = mm.info(stack)
 PRINT stack1
 PRINT stack2, stack1-stack2 ' stack grows downwards


There was no obvious difference between the various methods including GOTO, setting a flag and multiple EXIT FOR and DO LOOP as a wrapper or as replacement for the outer FOR NEXT

Jim
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5879
Posted: 08:54pm 04 Oct 2022
Copy link to clipboard 
Print this post

  Volhout said  @Jim

I use
Do
Loop


All the time. No need for the 1=1......
probably a remainder of the Arduino world....

The 1=1 was to make sure that the loop only passed through the one time. In this instance, the DO LOOP is only a target for the EXIT DO and not really a loop.
Normally, I convert the outer FOR NEXT into a DO LOOP so don;'t resort to such crudities.

JIm
VK7JH
MMedit   MMBasic Help
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3490
Posted: 09:11pm 04 Oct 2022
Copy link to clipboard 
Print this post

There is a problem with goto exit a loop.
Geoff has apparently fixed it, but in the loop, the return address, and maybe more, is pushed on stack.
When you exit with goto, the return address remains on stack. Slowly your stack will fill up, with every goto exit.
PicomiteVGA PETSCII ROBOTS
 
     Page 1 of 3    
Print this page
© JAQ Software 2024