Unlike C, Fortran does not need a break in each case. But is there a way to jump out of the select case statement besides goto
? (I'd rather choose another way to jump if possible and I cannot use exit in select case statement.)
select case(key)
case("cat")
if(value > 5) !break!
case("dog")
...
endselect
Here is an more detailed example. Though there are other types of flow control, break will be the best in my opinion
integer, allocatable :: Err(:)
select case(key)
case("cat")
if(value1 > 5) call PushBack(Err, 1001)
if(NotANumber(value2)) call PushBack(Err, 1002)
if(value3 /= "good") call PushBack(Err, 1003)
if(allocated(Err)) !break!
.... !some processing
case("dog")
....
endselect
if(allocated(Err)) call ShowError(key, Err)
If I put everything in if:
integer, allocatable :: Err(:)
select case(key)
case("cat")
if(value1 > 5) then !Here only one of the value1, value2... is checked
call PushBack(Err, 1001)
elseif(NotANumber(value2)) then
call PushBack(Err, 1002)
elseif(value3 /= "good") then
call PushBack(Err, 1003)
else
.... !some processing
case("dog")
....
endselect
if(allocated(Err)) call ShowError(key, Err)
If there are better solutions, please let me know.
You have encountered an improvement introduced in Fortran 2008 that is not fully implemented in compilers. In Fortran 2008 exit
can be used relating to things other than do
loops.
I consider three approaches valid:
case1: select case(key)
case("cat")
if (value > 5) exit case1
case("dog")
...
end select case1
This is the Fortran 2008 way.
case1: select case(key)
case("cat")
if (value > 5) goto 1 ! Let's pretend this is an exit: we'll have compiler
! support soon enough, and we can replace with exit
case("dog")
...
end select case1
1 continue
This is fake-Fortran 2008 way. The comment is vital to this approach.
massive_hack: do k=1,1
select case(key)
case("cat")
if (value > 5) exit massive_hack
case("dog")
...
end select case1
end do massive_hack
This is the Fortran 2003/hating goto
s way.
All of these are preferable, to me, to introducing spurious flow-control within cases.
Explanation:
The wording in the Fortran 2003 standard for the exit
statement is:
The EXIT statement provides one way of terminating a loop.
...
An EXIT statement belongs to a particular DO construct. If the EXIT statement refers to a DO construct name, it belongs to that DO construct; otherwise, it belongs to the innermost DO construct in which it appears.
whereas Fortran 2008 extends that with:
The EXIT statement provides one way of terminating a loop, or completing execution of another construct.
...
An EXIT statement belongs to a particular construct. If a construct name appears, the EXIT statement belongs to that construct; otherwise, it belongs to the innermost DO construct in which it appears.
The select case
construct is one to which the above explicitly applies.
Cursory glances suggest current versions of the Cray, NAG, GCC and IBM compilers support this enhanced behaviour.
Extended comment rather than answer ...
I don't understand what the problem is that @Francescalus has solved for you. Only one of the case
s will be executed, the break to the end of the select case
construct is the way that Fortran behaves. In your fragment:
select case(key)
case("cat")
if(value > 5) !break!
case("dog")
...
endselect
only the line if(value > 5) !break!
is executed if cat
is selected. If your fragment ought to have been
select case(key)
case("cat")
if(value > 5) then
break
else
long and tedious processing
end if
case("dog")
...
endselect
well that's just a long-winded way of writing
select case(key)
case("cat")
if(value <= 5) then
long and tedious processing
end if
case("dog")
...
endselect
The break
statement (or some syntactic equivalent) is needed in C and its ilk because the default behaviour is to fall through at the end of each case
.
It seems to me @Francescalus's massive_hack
is an absolutely appropriate use of exit
in Fortran 2008, enabling an exit from an enclosing do
construct to terminate a computationally-heavy loop over a sequence of elements.
I expect I've missed the point entirely ....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With