Statement DO WHILE Foundation

Executes a program loop until a condition evaluates to .F. (false).

Syntax
[DO] WHILE <lExpression>
   <SourceCode>...
   [EXIT]
   <SourceCode>...
   [LOOP]
   <SourceCode>...
END[DO]
Parameters
WHILE <lExpression>
<lExpression> is a logical expression. As long as this expression evaluates to .T. (true), the code between DO WHILE and ENDDO is executed.
EXIT
The EXIT statement terminates the DO WHILE loop and branches the program to the program line following the ENDDO statement.
LOOP
The LOOP statement immediately branches the program to the beginning of the DO WHILE loop.
Description

The control structure DO WHILE...ENDDO defines a block of statements which is executed repeatedly until the logical expression <lExprssion> evaluates to .F. (false). As soon as the program encounters the ENDDO statement, it begins again with the statement DO WHILE and reevaluates the condition<lExpression>. If a LOOP statement is executed within the loop, the loop begins again immediately without the code between LOOP and ENDDO being executed. The loop can be exited immediately with the EXIT statement, without <lExpression>being evaluated again. In this case, the program continues at the first executable line following ENDDO.

DO WHILE loops can be nested to any depth, and other control structures can be used within them. An exception is BEGIN SEQUENCE in connection with the RECOVER statement: no LOOP or EXIT statement is permitted between BEGIN SEQUENCE and RECOVER.

Examples
DO WHILE usage
// The example shows a simple print program which 
// outputs address labels to a text file with "?". 
// All records are read until the end of the file is reached. 

PROCEDURE Main 

   USE Customer NEW 
   INDEX ON Upper(Customer->LastName + Customer->FirstName) ; 
         TO CustA 

   SET PRINTER ON 
   SET PRINTER TO Label.txt 

   DO WHILE .NOT. Eof() 

      ?  Trim( Customer->Salutation ) 
      ?? Trim( Customer->FirstName ) + " " + ; 
         Trim( Customer->LastName ) 
      ? Trim( Customer->Street ) 
      ? Trim( Customer->City ) + ", " + Customer->State + " " + ; 
       Customer->ZIP 
      EJECT 
      SKIP 

   ENDDO 

   SET PRINTER OFF 
   SET PRINTER TO 

   CLOSE Customer 
RETURN 
DO WHILE with continuous loop

// The example shows a continuous loop such as might be used in the main 
// procedure of an application. In this case, a menu is displayed by 
// which a user can branch to different parts of the application. 

PROCEDURE Main 
   LOCAL nMenuItem 

   DO WHILE .T.                     // Continuous loop 

      CLS 
      @ 2, 1 PROMPT " DBF file " 
      @ 4, 1 PROMPT " NTX file " 
      @ 6, 1 PROMPT " Search   " 
      @ 8, 1 PROMPT " Quit     " 

      MENU TO nMenuItem 
      SetPos( 0, 0 ) 

      DO CASE 
      CASE nMenuItem == 1 
         ? "Selects DBF file" 
      CASE nMenuItem == 2 
         ? "Selects index file" 
      CASE nMenuItem == 3 
         ? "Searches data records" 
      CASE nMenuItem == 4 
         EXIT                        // exits loop 
      OTHERWISE 

         nMenuItem := Alert( "Exit program?", ; 
                             {" Yes "," No " }  ) 
         SetPos( 0, 0 ) 
         DO CASE 
         CASE nMenuItem == 0 
              LOOP                   // Back to the beginning 
         CASE nMenuItem == 1 
              EXIT                   // Exits loop 
         CASE nMenuItem == 2 
            ? "Continue program"     // Normally continues 
         ENDCASE 

      ENDCASE 

      ? "Press a key..." 
      Inkey(0)                       // Wait... 

   ENDDO 
RETURN 
DO WHILE...ENDDO as REPEAT...UNTIL
// In this example, two user-defined commands are used to form a 
// DO WHILE loop. The logical expression which causes an exit condition 
// is tested at the end of the loop and not, as with DO WHILE, at 
// the entrance to the loop. The loop is exited when the loop 
// condition evaluates to .T. (true). 

#command REPEAT          =>  DO WHILE .T. 

#command UNTIL <lExpr>   =>  IF <lExpr> ;; 
                                EXIT ;; 
                             ENDIF ;; 
                             ENDIF 

#include "Inkey.ch" 

PROCEDURE Main 
   LOCAL nKey := 0 

   REPEAT 

      ? "Last pressed key has Inkey() Code:", nKey 
      nKey := Inkey(0) 

   UNTIL nKey == K_ESC 

RETURN 
Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.