Flow-control structures
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
These are examples of control structures. You may also be interested in:
In this task, we document common flow-control structures. One common example of a flow-control structure is the goto
construct. Note that Conditional Structures and Loop Structures have their own articles.
Ada
goto
Top: Put_Line("Hello, World"); goto Top;
exit
Exit is used to break out of loops. Exit can be used with a label to break out of an inner loop to an outer loop and its enclosing outer loop
Outer: loop -- do something loop -- do something else exit Outer; -- exits both the inner and outer loops end loop; end loop;
C
goto
One common use of goto in C is to break out of nested loops.
int main() { int i,j; for (j=1; j<1000; j++) { for (i=0; i<j, i++) { if (exit_early()) goto out; /* etc. */ } } out: return 0; }
C++
goto
Compiler: GCC 3.3.4
#include <iostream> int main() { LOOP: std::cout << "Hello, World!\n"; goto LOOP; }
Note that "goto" may also be used in conjunction with other forms of branching.
Exceptions
Compiler: GCC 4.0.2
Exceptions are a way to give control back to a direct or indirect caller in case of an error.
#include <iostream> #include <ostream> void foo() { std::cout << "Going to throw an exception.\n"; throw 7; // almost any object can be thrown, including ints std::throw << "This output will never execute.\n"; } void bar() { std::cout << "Going to call foo().\n"; foo(); std::cout << "This will be skipped by the exception coming from foo.\n"; } void baz() { try // everything thrown from inside the following code block { // will be covered by the following catch clauses std::cout << "Going to call bar().\n"; bar(); std::cout << "This will be skipped by the exception coming from foo.\n"; } catch(...) // a simple catch-all, but doesn't give access to the thrown exception { std::cout << "An exception occured. I'll just throw it on.\n"; throw; // without an argument, the caught exception is re-thrown } std::cout << "This will not be executed due to the re-throw in the catch block\n"; } void foobar() { try { baz(); } catch(char const* s) { std::cout << "If foo had thrown a char const*, this code would be executed.\n"; std::cout << "In that case, the thrown char const* would read " << s << ".\n"; } catch(int i) { std::cout << "Caught an int, with value " << i << " (should be 7).\n"; std::cout << "Not rethrowing the int.\n"; } catch(...) { std::cout << "This catch-all doesn't get invoked because the catch(int) above\n" << "already took care of the exception (even if it had rethrown the\n" << "exception, this catch-all would not be invoked, because it's\n" << "only invoked for exceptions coming from the try block.\n"; } std::cout << "This will be executed, since the exception was handled above, and not rethrown.\n"; } int main() { try { foobar(); } catch(...) { std::cout << "The main function never sees the exception, because it's completely handled\n" << "inside foobar(). Thus this catch-all block never gets invoked.\n"; } }
Forth
CATCH-THROW
Forth does not have goto, but the standard does have an exception mechanism.
: checked-array CREATE ( size -- ) DUP , CELLS ALLOT DOES> ( i -- a+i ) 2DUP @ 0 SWAP WITHIN IF SWAP 1+ CELLS + ELSE 1 THROW THEN ; 8 checked-array myarray : safe-access ( i -- a[i] ) ['] myarray CATCH 1 = IF ." Out of bounds!" 0 THEN ;
IDL
goto
test: ..some code here goto, test
(This is almost never used)
on_error
on_error, test
(This resumes at the label test if an error is encountered)
on_ioerror
on_ioerror, test
(Same as on_error, but for EOFs and read-errors and such)
break
break
immediately terminates the innermost current loop (or if or case etc)
continue
continue
immediately starts the next iteration of the current innermost loop
Perl
Interpreter: Perl 5.x
goto
Goto is typically looked down upon by most perl programmers
FORK: # some code goto FORK;
Pop11
quitloop
quitloop with argument exits from nested loops:
while condition1 do while condition2 do if condition3 then quitloop(2); endif; endwhile; endwhile;
above quitloop(2) exits from both loops.
goto
goto l transfers control to the label l. goto may be used to exit from nested loops:
while condition1 do while condition2 do if condition3 then goto l; endif; endwhile; endwhile; l:;
Another use is to implement finite state machines:
state1: DO_SOMETHING(); if condition1 then goto state1; elseif condition2 then goto state2; .... else goto stateN; endif; state2: .... ... ... stateN: ....
Pop11 goto is a nonlocal one, so "jump out" from a chain of procedure calls:
define outer(); define inner(n); if n = 0 then goto final; endif; inner(n - 1); enddefine; inner(5); final:; enddefine;
This is useful to exit early from succesful recursive search, and for exception handling.
go_on
go_on is a multiway jump
go_on expression to lab1, lab2, ..., labN else elselab ;
If expression has value K the above will jump to label labK, if expression is not an ingeger, or if it ouside range from 1 to N, then control passes to label elselab. The else part may be omitted (then out of range values of expression cause an exception).
There is a more structured variant of go_on:
go_on expression to lab :
lab 1 : statement1; lab 2 : statement2; ....
endgo_on;
where lab is a prefix choosen by the user.
return
return ends execution of current function. In simplest form it is just:
return;
but it is also possible to specify one or more return values:
return(val1, val2, val3);
chain
chain has effect of "tail call" but is not nececcarly in tail position More precisely inside proc1
chain proc2(x1, x2, x3);
finishes execution of proc1 and transfers control to the proc2 passing it x1, x2, and x3 as arguments. On return from proc2 control passes to caller of proc1.
Remark: Pop11 does not perform "tail call optimization", one has to explicitely use chain.
Tcl
exception
Tcl's catch command can be used to provide a basic exception-handling mechanism:
if {[catch { ... code that might give error ... } result]} { puts "Error was $result" } else { ... process $result ... }
custom control structures
A novel aspect of Tcl is that it's relatively easy to create new control structures (more detail at http://wiki.tcl.tk/685). Eg. defining a command to perform some operation for each line of an input file:
proc forfilelines {linevar filename code} { upvar $linevar line ; # connect local variable line to caller's variable set filechan [open $filename] while {[gets $filechan line] != -1} { uplevel 1 $code ; # Run supplied code in caller's scope } close $filechan }
Now use it to print the length of each line of file "mydata.txt":
forfilelines myline mydata.txt { puts [string length $myline] }
Python
# Flow Control Structures in Python (Exceptions) # Exceptions are handled by the following operators: # try, except, finally, break, and continue, etc. # See each case for details... import math def main(): # ***** Case 1 - Try, Except ***** # try: temp = 0/0 # 'except' catches any errors that may have been raised between the code of 'try' and 'except' except: print "An error occurred." # Output : "An error occurred" # ***** Case 2 - Try, Except ***** # try: temp = 0/0 # here, 'except' catches a specific type of error raised within the try block. except ZeroDivisionError: print "You've divided by zero!" # Output : "You've divided by zero!" # ***** Case 3 - Try, Except, Finally ***** # try: temp = 0/0 except: print "An error occurred." # here, 'finally' executes when the try - except block ends, regardless of whether an error was raised or not # useful in areas such as closing opened file streams in the try block whether they were successfully opened or not finally: print "End of 'try' block..." # Output : # An error occurred # End of 'try' block... # ***** Case 4 - Try, Except within a function ***** # def divisionbyzero(): # create a function that is sure to fail temp = 0/0 try: divisionbyzero() except ZeroDivisionError: print "You've divided by zero!" # Output : # You've divided by zero! # ***** Case 5 - Try, Except, Else ***** # try: temp = 1/1 # not a division by zero error except ZeroDivisionError: # so... it is not caught print "You've divided by zero." # here, 'else' executes when no exceptions are caught... else: print "No apparent error occurred." # Output : # No apparent error occurred. # ***** Case 6 - Try, Except, break, continue ***** # i = 0 while 1: # infinite loop try: temp2 = 0/i # will raise a ZeroDivisionError first. temp = math.sqrt(i) break # 'break' will break out of the while loop except ValueError: # print "Imaginary Number! Breaking out of loop" break # 'break' out of while loop except ZeroDivisionError: print "You've divided by zero. Decrementing i and continuing..." i-=1 # we decrement i. # we 'continue', everything within the try - except block will be executed again, # this time however, ZeroDivisionError would not be raised again. continue # Note that removing it, replacing it with 'pass' would perform the equivalent # see below for a better example # Output : # You've divided by zero. Decrementing i and continuing... # Imaginary Number! Breaking out of loop # ***** Case 7 - Creating your own custom exceptions, raise ***** # # Let's call our custom error "StupidError"; it inherits from the Exception class class StupidError(Exception): def __init__(self, value): # 'value' is a constructor argument self.value = value def __str__(self): return repr(self.value) # Try it out. try: raise StupidError("Segfault") # here, we manually 'raise' the error within the try block except StupidError, details: # 'details' is the StupidError object we create in the try block. print 'Something stupid occurred:', details.value # so we access the value we had stored for it... # Output : # Something stupid occurred: Segfault # ***** Case 8 - continue ***** # i = 101 for i in range(0,4): # loop 4 times print "I will always be seen." continue # continue goes back to the loop beginning for a new iteration. print "I'll never be seen." print "Loop done" # Output: # I will always be seen. # I will always be seen. # I will always be seen. # I will always be seen. # Loop done if(__name__ == "__main__"): main()