Fortran do loop with internal goto - fortran

I have a Fortran77 snippet that looks like this:
DO 1301 N=NMLK-2,2,-1
Some code...
IF(NB1(N).EQ.50) GOTO 1300
Some code...
IF(BS(N).EQ.0.0) GOTO 1301
some code...
GOTO 1301
1300 NW(M)=NB1(N)
Some code...
1301 CONTINUE
When this hits the GOTO 1301 statement, does this jump to the next iteration of the loop or does it exit the loop?
As far as I understand the return keyword does nothing, so I assume that this will just exit the loop and continue code execution from label 1301, is that correct?
I am translating this to C# and am wondering if this is equivalent:
for (N = NMLK; N >= 2; N--)
{
Some code...
if (NB1[N] == 50)
goto l1300;
Some code...
if (BS[N] == 0)
return;
Some code...
return;
l1300:
NW[M] = NB1[N];
Some code...
}
or if I should have "continue" instead of "return"?

Yes, the GOTO 1301 statement makes the program jump to next iteration.
The DO label, label CONTINUE is an obsolete way to write a more contemporary DO ENDDO block. In this case the loop will iterate over variables specified on the DO line, and label CONTINUE line serves as an "ENDDO" placeholder.

Related

How to get out this Do-While loop?

I've this basic Arduino code, and I want to have 2 options to exit this Do-While loop.
I simplified my original code to highlight the real problem: the Do-While doesn't recognize the OR || condition to exit the loop
In this code I'm starting with two integer variables that are equal to zero and as soon as they enter the Do-While, they'will be setted equal to 2 both, so that they can immediately exit the Do-While in the first iteration.
Here's my code:
int fin = 0;
int ending = 0;
int counter = 0;
void setup() {
Serial.begin(9600);
}; //void setup
void loop () {
do {
Serial.println("We are IN Do-While #1");
ending = 2;
//fin = 2;
} while ((ending < 1) || (fin < 1)); //I have just one condition for exit the Do-While ending = 1
Serial.println("We are OUT Do-While #1");
delay(3000);
do {
counter++;
} while(counter<=100);
Serial.println("We are OUT Do-While #2");
delay(3000);
}
My problem is that I'm not setting fin = 2, because I want to test if the OR condition is working.
But it seems that it can't exit the Do-While unless they're both equal to 2. This is strange to me because the OR condition allows to exit the Do-While with a double options, in this particular case these options are:
ending<1 OR (the alternative option).. fin<1
Additionally if I change (the rest of the code is the same) the while condition with an AND it behave like I want: so that I have two ways to exit the Do-While loop.
Like this:
} while ((ending < 1) && (fin < 1));
But wouldn't be that in an AND condition I must match BOTH condition of ending >= 1 AND (at the same time) fin >= 1 to exit the loop?
Why is this happening?
and How can I solve this?
Remember that if you say while (condition), you'll loop so long as condition evaluates to true. So since your condition is
(ending < 1) || (fin < 1)
the only way for this to be false is if both ending < 1 is false AND fin < 1 is also false.
A simple trick when you're getting mixed up like this is to use DeMorgan's Law to find the contrapositive. In other words, if you want to loop while (ending < 1) || (fin < 1), that's the same as saying you want to STOP looping when the opposite is true. Using DeMorgan's Law, we can see that this is:
!((ending < 1) || (fin < 1))
!(ending < 1) && !(fin < 1)
ending >= 1 && fin >= 1
So we only STOP looping when ending >= 1 && fin >= 1!
Working the other way, if you want to STOP looping when ending >= 1 || fin >= 1, then we'll loop while the opposite is true. Again working through with DeMorgan's Law...
!(ending >= 1 || fin >= 1)
!(ending >= 1) && !(fin >= 1)
ending < 1 && fin < 1
So you wanted an AND instead of an OR all along!
But it seems that it can't exit the Do-While unless they're both equal to 2. This is strange to me because the OR condition allows to exit the Do-While with a double options, in this particular case these options are:
Actually, it's the opposite.
The loop has two options to keep going.
I'm sure you meant &&, not ||.
But wouldn't be that in an AND condition I must match BOTH condition of ending >= 1 AND (at the same time) fin >= 1?
Yes, to carry on.
Which means, you only need to not match one of them, to stop.
In your current state the loop will continue as long as (at least) one of the conditions is true (it doesnt have to be both!).
as long as ending is smaller than 2 OR fin is smaller than 2 then the loop will continue.
In your code, fin is smaller than 2 so the loop continues...
So, we are talking about the first loop in the code.
do {
Serial.println("We are IN Do-While #1");
ending = 2;
//fin = 2;
} while ((ending < 1) || (fin < 1));
Here if you don't change the "fin" variable it remains the same, and the exit condition will not be accomplished, that causing it not to end.
You could use an if condition it the loop,
do {
Serial.println("We are IN Do-While #1");
ending = 2;
//fin = 2;
if ( ending >= 1 ) break;
}
Or just use the || operator as you mentioned.

Fortran 77 Do Loop block clarification

Both NUM and ARRAY double precision variables, not sure how the if block will execute. When will it stop? What is it actually doing?, If we go to 8, then are we exiting the do loop?
Thanks
DO 7 I = 1,28
IF (NUM - ARRAY(I)) 8,7,7
7 CONTINUE
I=29
8 NUM = ARRAY(I)
....
....
....
....
As previously stated the conditional in the loop is an arithmetic if statement.
We know (and that's explicitly stated in the previous answer here) that if num is less than array(i) the label 8 is chosen, otherwise label 7 is chosen. It's also stated in that other answer that these have the effect of exiting the loop or cycling it. To be precise, I'll continue.
A DO construct has a range. A nonblock DO construct like the one in the question has range consisting of the statements between and including the do statement and the DO termination statement (in this case 7 continue). The DO termination statement is a valid target for a jump from within the range of the construct.
When the DO termination statement is jumped to, execution remains within the scope of the construct. That termination statement is executed (in this case, continue, doing nothing) and the loop iteration condition is again tested. That is, the loop cycles.
From within a DO construct, a jump to a statement outside the range of the construct terminates execution of the construct: like an exit.
This example, then, has the equivalent form using an IF construct (with go tos - bear with me)
DO 7 I = 1,28
IF (NUM < ARRAY(I)) THEN
GO TO 8
ELSE
GO TO 7
END IF
7 CONTINUE
I=29
8 NUM = ARRAY(I)
Now, because the statement labelled 7 is a continue statement, we can write this as
DO 7 I = 1,28
IF (NUM < ARRAY(I)) THEN
GO TO 8
ELSE
CYCLE
END IF
7 CONTINUE
I=29
8 NUM = ARRAY(I)
That's still pretty ugly (and not just because of all the upper case). Fortunately, we can make this prettier. The i=29 statement will be executed only when the loop terminates without the statement labelled 8 being jumped to. Now, the loop index i has control I = 1,28 so when the loop terminates naturally the index already has the value 29. That assignment does nothing (in modern Fortran) so we can remove it. Which leaves us with
DO 7 I = 1,28
IF (NUM < ARRAY(I)) THEN
GO TO 8
ELSE
CYCLE
END IF
7 CONTINUE
8 NUM = ARRAY(I)
When we also note that the IF construct is immediately followed by the end of the loop (and so we don't need to explicitly cycle) we have
DO 7 I = 1,28
IF (NUM < ARRAY(I)) EXIT
7 CONTINUE
NUM = ARRAY(I)
or (more nicely)
DO I = 1,28
IF (NUM < ARRAY(I)) EXIT
END DO
NUM = ARRAY(I)
All this example is doing is finding the value of the earliest element in array(1:28) which is larger than num, or array(29) if none is.
That is called arithmetic if: if(a) 1,2,3 . and it means: if a<0 it goes to 1, if(a==0) it goes to 2 and if (a>0) it goes to 3.
in your code if( num-array(i)<0 ) it goes to 8 (exit the loop and skip another line), else it goes to 7 (cycle).

If/else if not executing even though it appears conditions are met inside of a while loop

Pretty much what the title says. I'm to the last bit of this lottery numbers assignment, and I'm not sure why the second set of if/else if statements aren't displaying when I debug. I know that if/else statements are mutually exclusive - but shouldn't an if and then another if both test?
Here's the code.
count=0;
while(count<5)
{
if(lottery[count] == user[count])
{
lotto = lottery[count];
cout<<"So, you matched numbers with "<<lotto <<".\n";
tally++;
}
if(tally==5 && count == 5)
{
cout<<"Congratulations, you're the grand prize winner!";
}
else if(tally < 5 && count == 5)
{
cout<<"A total of "<<tally<<" of your lottery picks matched.";
}
else if(tally == 0 && count == 5)
{
cout<<"Caution. The following comment is an inside joke. Read at your own risk.";
cout<<"Bet you feel like a total loser huh? Nothing matched.";
}
count++;
}
I know I probably ought to have replaced the while loop with a for loop for simplicity's sake but i'm more comfortable with the while.
count will never be 5 when the if blocks are executed.
As soon as it becomes 5, the condition fails and the loop stops.
count will never be equal to 5 inside the while loop at the point where your if-else conditions require it. If you had incremented count before the if-else then it would have been possible to satisfy one of the conditions (depending on the value of tally).

How works this If statement? [duplicate]

This question already has an answer here:
Fortran IF statement with numbers/labels rather than another statement
(1 answer)
Closed 7 years ago.
I'm trying to teach myself fortran so I can unravel an old program and repurpose it for our own use. I can't figure out what this statement does:
if(s - fm) 198, 198, 197
s - fm isn't a condition that can be true or false, right?.
And when it passes control to the line marked 198, does it then continue to the end of the program? How does it know when to come back to execute 198 again and then 197?
This is an "archaic" form of IF:
IF (''arithmeticExpression'') ''firstLineNumber'', ''secondLineNumber'', ''thirdLineNumber''
In the second form, the arithmetic expression is evaluated. If the expression evaluates to a negative number, then execution continues at the first line number. If the expression evaluates to zero, then execution continues at the second line number. Otherwise, execution continues at the third line number.
It's a "three-way goto" depending on the sign of the expression.
In a more traditional C-like language it wood be
/* IF(a) label1, label2, label3 */
if(a > 0)
{
goto label3;
} else
if(a < 0)
{
goto label1;
} else
{
// a == 0
goto label2;
}
Your case contains two labels 198 which works like
if(s <= fm) { goto lbl198; } else { goto lbl197; }
Ref: wikibooks
This obsolete feature puzzles a lot of people:
FORTRAN compiler warning: obsolete arithmetic IF statement
Fortran strange IF
strange label usage

What does "for(;;)" mean?

In C/C++, what does the following mean?
for(;;){
...
}
It's an infinite loop, equivalent to while(true). When no termination condition is provided, the condition defaults to false (i.e., the loop will not terminate).
In C and C++ (and quite a few other languages as well), the for loop has three sections:
a pre-loop section, which executes before the loop starts;
an iteration condition section which, while true, will execute the body of the loop; and
a post-iteration section which is executed after each iteration of the loop body.
For example:
for (i = 1, accum = 0; i <= 10; i++)
accum += i;
will add up the numbers from 1 to 10 inclusive.
It's roughly equivalent to the following:
i = 1;
accum = 0;
while (i <= 10) {
accum += i;
i++;
}
However, nothing requires that the sections in a for statement actually contain anything and, if the iteration condition is missing, it's assumed to be true.
So the for(;;) loop basically just means:
don't do any loop setup;
loop forever (breaks, returns and so forth notwithstanding); and
don't do any post-iteration processing.
In other words, it's an infinite loop.
Loop until some break, exit, throw etc. statement inside the loop executes. Basically, you can think of a for loop as consisting of:
for (setup; test; advance)
...
If the "test" is empty it's considered to be true, and the loop keeps running. Empty "setup" and "advance" simply do nothing.
An infinite loop which continues until there is a break, exit, or goto statement.
Even if this answer suggests that both constructs are equivalent, there's a subtle difference between both for(;;) and while(1) (which both create infinite loops) in the C language (and possibly compiler-dependent).
Some compilers (Windriver DIABData for instance) complain about "condition is always true" when using while(1).
Changing to for(;;) allows to get rid of the warning, probably because the latter expression is semantically stronger to create an infinite loop on purpose, and there is no "always true" condition at all (plus it's shorter to write).
On the other hand, the C++ language doesn't make a difference about both constructs as Adrian stated in comments:
The C++ standard states that a missing condition makes the implied while clause equivalent to while(true) and for ( for-init-statement condition opt ; expression opt ) statement is equivalent to { for-init-statement while ( condition ) { statement expression ; } }