Wednesday, August 15, 2012

AdaTutor - Operators and Control Constructs (3)

The "EXIT" Statement
    for I in 1 .. 10 loop            for I in 1 .. 10 loop
      J := 0;                          J := 0;
      loop                             loop
        J := J + 1;                      J := J + 1;
        if A(I, J) = 0 then
          exit;                          exit when A(I, J) = 0;
        end if;
      end loop;                        end loop;
      B(I) := J;                       B(I) := J;
    end loop;                        end loop;

The statement exit; exits the innermost loop.  In the example at the left, exit; transfers control to the statement B(I) := J;.  Since exit; is often the only statement in an if block, exit when is available to abbreviate an if block with exit; as its only statement.  The two examples above are equivalent.

Although exit; can appear anywhere inside any kind of loop, in the author's opinion it's usually best to use only exit when, and then only as the last statement of an otherwise infinite loop, as shown at the right above.  This simulates a "repeat ... until" loop, which isn't directly available in Ada.

      Outer:
      for I in 1 .. 10 loop
         J := 0;
         loop
            J := J + 1;
            exit Outer when A(I, J) = 0;
         end loop;
         B(I) := J;
      end loop Outer;
      K := J;

An exit statement can exit other than the innermost loop by naming the loop to be exited.  In this example, the for loop is named Outer.  A loop name is any Ada identifier, and is followed by a colon.  Of course, Outer: could have been placed on the same line as the for, with no semicolon being necessary to separate them.  When a loop is named, the end loop statement must repeat the name of the loop.  The exit statement can then name the loop to be exited, as in exit Outer; or exit Outer when A(I, J) = 0;.  In this example, the exit statement transfers control to the statement K := J;, not to B(I) := J;.

In the author's opinion, it's best to exit only the innermost loop, unless doing so unnecessarily complicates the program.

Labels and GOTOs
Although an Ada loop name looks exactly like a C or Pascal label, Outer: is not a label, and the program can't goto Outer.  An Ada label looks like this:
         << Jail >>

The << ... >> makes the label very conspicuous, whether it's on the same line as a statement or on a line by itself.  The program can then say goto Jail;.  Like all reserved words, goto can't contain a space.  Well-structured Ada programs don't need labels and gotos, so their use is very rare.

Question

       I_Loop:   for I in 1 .. 10 loop
                   J := 0;
       J_Loop:     loop
                     J := J + 1;
                     exit;
                   end loop J_Loop;
                   L := J;
                 end loop I_Loop;
                 M := J;

In the program segment above, which statement will be executed after exit;?
  1. L := J;
  2. M := J;
  3. for I in 1 .. 10 loop
The "CASE" Construct
         case C is                        
           when '*' =>                    
             -----;                       
             -----;                       
           when '#' | '$' =>              
             -----;                       
             -----;                       
             -----;                       
           when '0' .. '9' =>             
             -----;                       
           when 'A'..'Z' | 'a'..'z' =>    
             -----;                       
             -----;                       
             -----;                       
           when others =>                 
             -----;                       
             -----;                       
         end case;  

In this example, assume that C is of type Character.  The expression being tested (C), must have a discrete type: integer or enumeration type.  The case construct must handle all possible values, but when others is available.  If no action is desired for characters not mentioned, we can write when others => null;.  The Ada statement null; does nothing.  Note that the vertical bar can be used to apply several cases to one block of code, and that ranges can be used.  Here, if C is '*', the first block is executed; if it's '#' or '$', the second block is executed.  If it's a digit, the third block is executed, and if it's an unaccented letter A-Z (upper or lower case), the fourth block is executed.  If C is anything else, the fifth (last) block of code is executed.

      if C = '*' then
        -----;
        -----;
      elsif C = '#' or C = '$' then
        -----;
        -----;
        -----;
      elsif C in '0' .. '9' then
        -----;
      elsif C in 'A'..'Z' or C in 'a'..'z' then
        -----;
        -----;
        -----;
      else
        -----;
        -----;
      end if;

The two examples above are equivalent.  In both cases only one block of code will be executed.  By the way, the symbol => is read "choose" (or sometimes "arrow"), and may not contain a space.

Question

If we have
   type Rainbow_Color is (Red, Orange, Yellow, Green, Blue, Indigo,
                          Violet);
   type Traffic_Light_Color is (Red, Amber, Green);
   F : Float range 0.0 .. 2.0;
   R : Rainbow_Color;
   T : Traffic_Light_Color;
then which one of the following program segments is legal?
  1.   case R is
        when Red | Green =>
          -----;
        when Blue .. Violet =>   
          -----;
      end case;
    
  2.    case F is             
         when 0.0 .. 1.0 =>  
           -----;            
         when others =>      
           -----;             
       end case;              
    
  3.    case T is
         when Red =>
           -----;
         when others =>   
           -----;
       end case;
    

< prev   next >

No comments: