FOR ... NEXT iteration statement
Syntax: FOR Counter = StartNumber TO EndNumber [ STEP StepNumber ] Statements [ EXIT FOR ] NEXT Parameters:
☞ BCX uses the C/C++ rule of evaluating StartNumber, EndNumber, and StepNumber arguments on each iteration of a FOR ... NEXT loop. This allows dynamic changes to the loop bounds or step values during the loop's execution. PureBasic, also, uses the C/C++ rule. Microsoft GW-BASIC, QBASIC, and Visual Basic, as well as, FreeBASIC, VB, and PowerBASIC, evaluate, only once, the start, end, and step arguments in a FOR ... NEXT loop. |
Example:
Here is an easy to follow example that shows how BCX handles positive and negative STEP values (step up and step down).
CLS DIM AS INTEGER Counter, StartNumber, EndNumber, StepNumber StartNumber = 1 EndNumber = 10 StepNumber = 1 FOR Counter = StartNumber TO EndNumber STEP StepNumber PRINT Counter NEXT PRINT StartNumber = 10 EndNumber = 1 StepNumber = -1 FOR Counter = StartNumber TO EndNumber STEP StepNumber PRINT Counter NEXT PAUSE
Result:
1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1 Press any key to continue . . .
To start the next iteration of a NEXT early in control loops see the description of the ITERATE function.
☞ Underflow possibilities exist when any unsigned number is used for the count in a FOR ... NEXT loop coded to terminate at zero (0). Here is an example that will create an underflow. Press Any Key To Quit !
DIM AS UINT TheCounter, TheCount, EndNumber TheCount = 255 EndNumber = 0 FOR TheCounter = TheCount TO EndNumber STEP -1 PRINT " Press Any Key To Quit !", TheCounter IF INKEY$ <> "" THEN EXIT FOR END IF NEXT
FOR DataType ... NEXT iteration statement
BCX allows integrated loop iterator variable declarations. Using this option makes the iterator variable local, in scope, to the loop.
Valid Loop Variable DataTypes
Example 1: Here is an example of variables used in defining a loop which makes them local, in scope, to the loop and inaccessible from outside the loop.
DIM I = 100, J = 200 FOR DOUBLE I = 1.1 TO 18.7 STEP 1.1 FOR INTEGER J = 1 TO 10 STEP 5 ? USING$("#.##",I), " .....", J NEXT NEXT ? : ? : ? I , " ....." , J PAUSE
Result:
1.10 ..... 1 1.10 ..... 6 2.20 ..... 1 2.20 ..... 6 3.30 ..... 1 3.30 ..... 6 4.40 ..... 1 4.40 ..... 6 5.50 ..... 1 5.50 ..... 6 6.60 ..... 1 6.60 ..... 6 7.70 ..... 1 7.70 ..... 6 8.80 ..... 1 8.80 ..... 6 9.90 ..... 1 9.90 ..... 6 11.00 ..... 1 11.00 ..... 6 12.10 ..... 1 12.10 ..... 6 13.20 ..... 1 13.20 ..... 6 14.30 ..... 1 14.30 ..... 6 15.40 ..... 1 15.40 ..... 6 16.50 ..... 1 16.50 ..... 6 17.60 ..... 1 17.60 ..... 6 18.70 ..... 1 18.70 ..... 6 100 ..... 200 Press any key to continue . . .
Remarks:
☞ Using floating point numbers for the start and end value of a FOR ... NEXT loop can cause problems. The basis of the difficulty is that some floating point numbers will be rounded up or down because they cannot be represented, with absolute accuracy, bit for bit. One specific problem in a FOR ... NEXT loop is that this rounding of the floating point numbers, and more specifically that the rounding up of the accumulated value, may push beyond the end value causing the loop to end prematurely as in the following.
Example 2:
DIM I = 100, J = 200 FOR DOUBLE I = 9.9 TO 18.7 STEP 1.1 FOR INTEGER J = 1 TO 10 STEP 5 ? USING$("#.##",I), " .....", J NEXT NEXT ? : ? : ? I , " ....." , J
Result:
9.90 ..... 1 9.90 ..... 6 11.00 ..... 1 11.00 ..... 6 12.10 ..... 1 12.10 ..... 6 13.20 ..... 1 13.20 ..... 6 14.30 ..... 1 14.30 ..... 6 15.40 ..... 1 15.40 ..... 6 16.50 ..... 1 16.50 ..... 6 17.60 ..... 1 17.60 ..... 6 100 ..... 200
The problem is not simply the number of steps. For instance, in the example above the start value is different but the end value and STEP are the same as in the previous example which works as expected. The upward rounding problem can be guarded against by adding one-half of the STEP value to the end value. To apply this correction in the example above, the line
FOR DOUBLE I = 9.9 TO 18.7 STEP 1.1
would be changed to
FOR DOUBLE I = 9.9 TO 19.25 STEP 1.1
To start the next iteration of a NEXT early in control loops see the description of the ITERATE function.
FOR_EACH ... NEXT_EACH statement
Purpose: FOR_EACH ... NEXT_EACH iterates statements for each member of a one-dimensional, statically dimensioned array.
Syntax: FOR_EACH (LoopLocalVariable, NameOfOneDimensionalArray) PRINT " Value = ", NameOfOneDimensionalArray [LoopLocalVariable] [ EXIT_EACH ] ' more statements ..... NEXT_EACH |
☞ Do not DIM the LoopLocalVariable ... it is DIM'ed automatically.
Example 1: Here is an example showing a nested FOR_EACH loop:
DIM Numbers[3] AS SINGLE Numbers[0]=0.000 Numbers[1]=1.111 Numbers[2]=2.222 DIM Strings[3] AS STRING Strings$[0]="ZERO" Strings$[1]="ONE" Strings$[2]="TWO" CLS PRINT "Displaying the NUMERIC array ..." PRINT FOR_EACH (ZZ, Numbers) PRINT "Cell No.", ZZ, " Value = ", Numbers[ZZ] FOR_EACH (YY, Strings) PRINT "Now Showing a NESTED FOR_EACH LOOP: ", Strings[YY] NEXT_EACH NEXT_EACH PRINT PRINT "Displaying the STRING array one more time ..." PRINT FOR_EACH (HH, Strings$) PRINT "Cell No.", HH, " Value = ", Strings$[HH] NEXT_EACH
Result:
Displaying the NUMERIC array ... Cell No. 0 Value = 0 Now Showing a NESTED FOR_EACH LOOP: ZERO Now Showing a NESTED FOR_EACH LOOP: ONE Now Showing a NESTED FOR_EACH LOOP: TWO Cell No. 1 Value = 1.111 Now Showing a NESTED FOR_EACH LOOP: ZERO Now Showing a NESTED FOR_EACH LOOP: ONE Now Showing a NESTED FOR_EACH LOOP: TWO Cell No. 2 Value = 2.222 Now Showing a NESTED FOR_EACH LOOP: ZERO Now Showing a NESTED FOR_EACH LOOP: ONE Now Showing a NESTED FOR_EACH LOOP: TWO Displaying the STRING array one more time ... Cell No. 0 Value = ZERO Cell No. 1 Value = ONE Cell No. 2 Value = TWO
Example 2: Here is an example using a two (2) dimensional string array to simulate a poor mans dictionary:
DIM Dict[10,10] AS STRING CLS FOR_EACH (iter, Dict) Dict [iter, 1] = "Key" + STR$(iter) Dict [iter, 2] = "Value" + STR$(iter) NEXT_EACH FOR_EACH (iter, Dict) IF Dict [iter, 1] = "Key 5" THEN PRINT "Found: ", Dict [iter, 2] : PRINT NEXT_EACH PRINT "Here are the complete contents" : PRINT FOR_EACH (iter, Dict) PRINT Dict [iter, 1] , " ", Dict [iter, 2] NEXT_EACH PAUSE
Result:
Found: Value 5 Here are the complete contents Key 0 Value 0 Key 1 Value 1 Key 2 Value 2 Key 3 Value 3 Key 4 Value 4 Key 5 Value 5 Key 6 Value 6 Key 7 Value 7 Key 8 Value 8 Key 9 Value 9 Press any key to continue . . .
XFOR ... XNEXT iteration statement
Syntax: XFOR [StartParameters] [ WHILE ... UNTIL Condition] [ BY VariableChanges] Statements [ EXIT XFOR ] XNEXT Parameters: |
Remarks:
☞ With all of the parameters being optional, the following is legal and results in generation of a for ever loop
XFOR WHILE BY PRINT "Type Ctrl C to stop this!" XNEXT
Example 1:
Here is an example that uses XFOR ... XNEXT in the program which calculates and prints the combinations of a subset of items in a set.
DIM SetItemCount% DIM SubSetItemCount% DIM SubSetCount% DIM start AS clock_t DIM finish AS clock_t DIM duration# INPUT "Total number of items in set? ", SetItemCount% INPUT "Number of items in one subset combination? ", SubSetItemCount% PRINT start = clock() SubSetCount% = SubSets(SetItemCount%, SubSetItemCount%) finish = clock() duration# = ROUND((DOUBLE)(finish - start) / CLOCKS_PER_SEC, 2) PRINT PRINT "It took", duration#, " seconds to calculate that" PRINT "there are", SubSetCount%, " combinations of", SubSetItemCount%, " item subsets in a set of", SetItemCount%, " items." FUNCTION SubSets%(n%, k%) RAW buffer%[100] DIM i% = 0 DIM j% DIM SSCnt% XFOR j = 0 WHILE j <= n BY j++ buffer[j] = 0 XNEXT WHILE i >= 0 IF (buffer[i] < n + i - k + 1) THEN buffer[i]++ IF (i = k - 1) THEN XFOR j = 0 WHILE j < k BY j++ PRINT buffer[j]; XNEXT PRINT SSCnt++ ELSE buffer[++i] = buffer[i - 1] END IF ELSE i-- END IF WEND FUNCTION = SSCnt% END FUNCTION
Result:
Total number of items in set? 5 Number of items in one subset combination? 3 1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5 It took 0 seconds to calculate that there are 10 combinations of 3 item subsets in a set of 5 items.
Example 2:
Here is a more complex example using XFOR ... XNEXT.
' Make a file of names. OPEN "NAMES.TXT" FOR OUTPUT AS FPOUT FPRINT FPOUT, "John G.";",";"Kemeny" FPRINT FPOUT, "Thomas E.";",";"Kurtz" FPRINT FPOUT, "Mary Kenneth";",";"Keller" CLOSE ' Read in from file ' and display input. TYPE tagLink DIM szFirst$ DIM szLast$ DIM ptNxt AS tagLink PTR END TYPE DIM pzNames AS tagLink PTR DIM ptCurrent AS tagLink PTR pzNames = (tagLink*)calloc(1, SIZEOF(tagLink)) OPEN "NAMES.TXT" FOR INPUT AS FPIN XFOR ptCurrent = pzNames WHILE NOT EOF(FPIN) BY ptCurrent = ptCurrent->ptNxt = (tagLink*)calloc(1, SIZEOF(tagLink)) FINPUT FPIN, ptCurrent->szFirst$, ptCurrent->szLast$ XNEXT XFOR ptCurrent = pzNames WHILE ptCurrent BY ptCurrent = ptCurrent->ptNxt PRINT ptCurrent->szFirst$; " "; ptCurrent->szLast$ XNEXT PAUSE
Result:
John G. Kemeny Thomas E. Kurtz Mary Kenneth Keller
Example 3:
And here is an even more complex example using XFOR ... XNEXT.
TYPE tagRECORD DIM sName[16] AS CHAR DIM iAge AS INT DIM ptPRV AS tagRECORD PTR DIM ptNXT AS tagRECORD PTR END TYPE DIM szBuf$ DIM ptHIGH AS tagRECORD PTR DIM ptLOW AS tagRECORD PTR DIM ptHead AS tagRECORD PTR AddRec("Jim",22) AddRec("Jane",23) AddRec("Alex",22) AddRec("Mary",24) AddRec("John",26) AddRec("Steve",29) AddRec("Sally",25) AddRec("Zak",21) AddRec("Betty",29) AddRec("Clive",26) AddRec("Doris",28) AddRec("Kelly",22) sprintf(szBuf, "%12s%4s%3s", "Name", "", "Age") PRINT szBuf$ XFOR INT i = 1, tagRECORD PTR ptRL = ptLOW WHILE ptRL <> NULL BY i++, ptRL = ptRL->ptNXT sprintf(szBuf, "%14s %3i", ptRL->sName, ptRL->iAge) PRINT szBuf$ XNEXT PRINT sprintf(szBuf, "%12s%4s%3s", "Name", "", "Age") PRINT szBuf$; " "; szBuf$ XFOR INT i = 1, INT j = 12, tagRECORD PTR ptRL = ptLOW, tagRECORD PTR ptRH = ptHIGH WHILE i < j BY i++, j--, ptRL = ptRL->ptNXT, ptRH = ptRH->ptPRV sprintf(szBuf, "%14s %3i %14s %3i", ptRL->sName, ptRL->iAge, ptRH->sName, ptRH->iAge) PRINT szBuf$ XNEXT PAUSE SUB AddRec(pszN$, iA AS INT) RAW ptTMP AS tagRECORD PTR ptTMP = (tagRECORD *)calloc(1,SIZEOF(tagRECORD)) ptTMP->sName$ = pszN$ ptTMP->iAge = iA IF ptHead = NULL THEN ptHIGH = ptLOW = ptHead = ptTMP EXIT SUB END IF RAW ptREC AS tagRECORD PTR XFOR ptREC = ptHead WHILE ptREC <> NULL AND ptREC->iAge < iA BY ptREC = ptREC->ptNXT XNEXT IF ptREC = NULL THEN ptHIGH->ptNXT = ptTMP ptHIGH->ptNXT->ptPRV = ptHIGH ptHIGH = ptTMP EXIT SUB END IF IF ptREC = ptHead THEN ptTMP->ptNXT = ptHead ptHead->ptPRV = ptTMP ptHead = ptLOW = ptTMP ELSE ptTMP->ptNXT = ptREC ptREC->ptPRV->ptNXT = ptTMP ptTMP->ptPRV = ptREC->ptPRV ptREC->ptPRV = ptTMP END IF END SUB
Result:
Name Age Zak 21 Kelly 22 Alex 22 Jim 22 Jane 23 Mary 24 Sally 25 Clive 26 John 26 Doris 28 Betty 29 Steve 29 Name Age Name Age Zak 21 Steve 29 Kelly 22 Betty 29 Alex 22 Doris 28 Jim 22 John 26 Jane 23 Clive 26 Mary 24 Sally 25
WHILE ... WEND iteration statement
Syntax: [ DO ] WHILE expression ' "DO" is optional EXIT LOOP OR EXIT DO WEND |
Example:
DIM RetStr$ RetStr$ = NumberToRoman$(3999) ? RetStr$ RetStr$ = NumberToRoman$(0xF9F) ? RetStr$ RetStr$ = NumberToRoman$(%07637) ? RetStr$ RetStr$ = NumberToRoman$(0b111110011111) ? RetStr$ FUNCTION NumberToRoman$(NumberToConvert%) DIM FunctionReturnString$ SET RomanNumerals[] AS PCHAR "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" END SET SET ArabicNumerals%[] 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 END SET DIM Counter% WHILE (NumberToConvert) WHILE (NumberToConvert / ArabicNumerals[Counter]) CONCAT(FunctionReturnString$, RomanNumerals[Counter]) NumberToConvert -= ArabicNumerals[Counter] WEND Counter++ WEND FUNCTION = FunctionReturnString$ END FUNCTION
Result:
MMMCMXCIX MMMCMXCIX MMMCMXCIX MMMCMXCIX
Remarks:
To start the next iteration of a WEND early
in control loops see the description of the ITERATE function.
DO ... LOOP iteration statement
Syntax 1: DO Statements IF Condition THEN EXIT LOOP | EXIT DO END IF More Statements LOOP |
Example:
DIM a DO a++ IF a > 45 THEN EXIT LOOP END IF ? a LOOP
Result:
1 ... 45
DO UNTIL ... LOOP iteration statement
Syntax 2: DO UNTIL Condition Statements LOOP |
Example:
DIM a DO UNTIL a > 45 a++ ? a LOOP
Result:
1 ... 46
DO ... LOOP UNTIL iteration statement
Syntax 3: DO Statements LOOP UNTIL Condition |
Example:
DIM a DO a++ ? a LOOP UNTIL a > 45
Result:
1 ... 45
DO ... LOOP WHILE iteration statement
Syntax 4: DO Statements LOOP WHILE Condition |
Example:
DIM a DO a++ ? a LOOP WHILE a < 45
Result:
1 ... 45
Remarks:
See ITERATE to start the next iteration of a LOOP
early in control loops.
ITERATE statement
Purpose: ITERATE will start the next iteration of a loop early in control loops
Syntax 1: ITERATE |
Remarks:
ITERATE
has the effect of jumping to the LOOP, WEND, NEXT or
END
REPEAT at the end of the currently executing block.
Example:
DIM A,B CLS PRINT "This will print Iterations 7 thru 10 of the outer loop" PRINT "and will print the numbers 999 and 1000 from within" PRINT "the inner loop. All 10,000 iterations still occur," PRINT "it's the ADDED LEVEL OF CONTROL within your loops that " PRINT "ITERATE gives to you." FOR B = 1 TO 10 IF B < 7 THEN ITERATE PRINT PRINT "<Outer Loop> Iteration Number", B FOR A=1 TO 1000 IF A < 999 THEN ITERATE PRINT ">Inner Loop< Iteration Number", A NEXT NEXT
Result:
This will print Iterations 7 thru 10 of the outer loop and will print the numbers 999 and 1000 from within the inner loop. All 10,000 iterations still occur, it's the ADDED LEVEL OF CONTROL within your loops that ITERATE gives to you. Iteration Number 7 >Inner Loop< Iteration Number 999 >Inner Loop< Iteration Number 1000 Iteration Number 8 >Inner Loop< Iteration Number 999 >Inner Loop< Iteration Number 1000 Iteration Number 9 >Inner Loop< Iteration Number 999 >Inner Loop< Iteration Number 1000 Iteration Number 10 >Inner Loop< Iteration Number 999 >Inner Loop< Iteration Number 1000
IF ... THEN ... ELSE ... ELSEIF ... END IF or ENDIF selection statements
Syntax 1: IF Expression THEN Statement END IF |
Syntax 2: IF Expression1 THEN Statements ELSEIF Expression THEN Statements ELSE Statements END IF |
Example:
DIM i WHILE i < 10 INCR i IF i = 5 THEN PRINT "Five" ELSEIF i = 7 THEN PRINT "Seven" EXIT WHILE END IF WEND PRINT "The final value of i =" ; i PAUSE
Result:
Five Seven The final value of i = 7
Example:
☞ The IF ... THEN code above can be expressed as a single line but only with a modification. ELSEIF will not be parsed correctly when embedded in a single line conditional statement. ELSE IF, instead, must be used.DIM i WHILE i < 10 INCR i IF i = 5 THEN PRINT "Five" ELSE IF i = 7 THEN PRINT "Seven" : EXIT WHILE WEND PRINT "The final value of i =" ; i PAUSE
Result:
Five Seven The final value of i = 7
SELECT CASE selection statement
Syntax: SELECT CASE Expression CASE Expression1 your code here CASE Expression2 ... ' CASE Expression is tested for equality against all ... ' SELECT CASE expression and executes the instructions ... ' following if CASE found TRUE. CASE Expression N your code here CASE ELSE your default code here END SELECT |
Remarks:
CASE statements allow the following common
construct:
CASE 1 TO 10
which will capture the flow if the CASE is any number between 1 and 10.
☞ When AND or OR is used as a Boolean comparison operator, scalar operators (= or < or > etc.) must be used preceding the test expression.
CASE = "Selector" OR = "Selectee"
The following line is not valid and will cause an error.
CASE "Selector" OR "Selectee"
However, in the example above, the OR can be replaced with a comma to form a valid CASE test statement.
CASE "Selector", "Selectee"
Also allowed are less than, greater than, comparisons like
CASE > 5 AND < 9
The OR operator also may be used for less than, greater than, comparisons, for example,
CASE < 4 OR > 9
The scalar not equal <> operator may be used as well, for example,
CASE <> "BCX"
Arrays, functions and variations of variables that contain the dereferencing operator (->) may be used as arguments to the CASE statement, for example,
CASE A[1] TO A[9] CASE foo->f,foo->g CASE Funcfoo(A[foo->f],"nada"), foo->g CASE > foo->f AND < Funfoo(A[1])
Example 1:
DIM Choose$ Choose$ = "SelectOR" SELECT CASE Choose$ CASE = "SelectOR" OR = "SelectXOR" PRINT "Selected" END SELECT
Example 2: SELECT CASE variants:
DIM i INPUT "Enter a number: ", i SELECT CASE i CASE <1 PRINT "less than 1" CASE 1 PRINT "1" CASE 2 TO 4 PRINT "2 to 4 inclusive" CASE 5 PRINT "5" CASE >5 AND <9 PRINT "greater than 5 and less than 9" CASE 9 PRINT "9" CASE >9 PRINT "greater than 9" END SELECT
SELECT CASE BAND also may be used. This statement performs a binary AND on all CASE statements.
☞ In the C code translation, breaks normally inserted between the CASE statements are suppressed when using SELECT CASE BAND, otherwise the flow would exit after the first match.
Here is an example.
SELECT CASE BAND Style CASE WS_CHILD : CONCAT(StyleString$,"WS_CHILD,") CASE WS_VISIBLE : CONCAT(StyleString$,"WS_VISIBLE,") CASE WS_TABSTOP : CONCAT(StyleString$,"WS_TABSTOP") END SELECT
A status code is returned in lParam from which, depending on the bits set, the messages can be determined. This is how it would normally be written:
IF lParam BAND CE_BREAK THEN err$=err$ + "CE_BREAK " IF lParam BAND CE_FRAME THEN err$=err$ + "CE_FRAME " IF lParam BAND CE_IOE THEN err$=err$ + "CE_IOE " IF lParam BAND CE_MODE THEN err$=err$ + "CE_MODE " IF lParam BAND CE_OVERRUN THEN err$=err$ + "CE_OVERRUN " IF lParam BAND CE_RXOVER THEN err$=err$ + "CE_RXOVER " IF lParam BAND CE_RXPARITY THEN err$=err$ + "CE_RXPARITY " IF lParam BAND CE_TXFULL THEN err$=err$ + "CE_TXFULL"
Here is a similar solution using SELECT CASE BAND.
SELECT CASE BAND lParam CASE CE_BREAK : CONCAT(err$,"CE_BREAK ") CASE CE_FRAME : CONCAT(err$,"CE_FRAME ") CASE CE_IOE : CONCAT(err$,"CE_IOE ") CASE CE_MODE : CONCAT(err$,"CE_MODE ") CASE CE_OVERRUN : CONCAT(err$,"CE_OVERRUN ") CASE CE_RXOVER : CONCAT(err$,"CE_RXOVER ") CASE CE_RXPARITY : CONCAT(err$,"CE_RXPARITY ") CASE CE_TXFULL : CONCAT(err$,"CE_TXFULL") END SELECT
GOTO jump statement
Purpose: GOTO redirects program flow to a label.
Syntax: GOTO Label Label: |
Remarks:
BCX Console Sample Programs using GOTO function.
GOSUB ... RETURN statement
Purpose: GOSUB redirects program flow to a label. The flow continues from the label until a RETURN statement is encountered and the flow is returned to the line following the GOSUB Label statement.
Syntax: GOSUB Label Label: Statements RETURN |
Remarks:
BCX Console Sample Programs using GOSUB statement.
EXIT statement
Purpose: Causes EXIT from a
DO ... LOOP,
FOR ... NEXT,
FOR_EACH ... NEXT_EACH,
REPEAT ... END
REPEAT,
loop,
a
SELECT ... END
SELECT,
construct,
or a FUNCTION or SUB.
Syntax: EXIT CASE EXIT DO EXIT FOR EXIT_EACH EXIT LOOP EXIT REPEAT EXIT SELECT EXIT WHILE EXIT FUNCTION EXIT SUB |
When translated with the BCX -w flag, the following code generates a warning with the code generated exiting out of inner most FOR ... NEXT loop
DIM iW, iX, iY FOR iW = 1 TO 2 FOR iX = 1 TO 5 iY = iX+1 WHILE iY < 10 PRINT iX;iY IF iY = iX THEN EXIT FOR iY++ iY = IMOD(iY,10) WEND NEXT PRINT iX;iY NEXT
When translated with the BCX -w flag, the following code generates a warning with code generated exiting out of the XFOR ... XNEXT loop
DIM iW, iX, iY XFOR iW = 1 WHILE iW < 2 BY iW++ FOR iX = 1 TO 5 FOR iY = 1 TO 5 IF iY + iX + iW = 10 THEN EXIT XFOR PRINT iW;iX;iY NEXT NEXT XNEXT PRINT iW;iX;iY
When translated with BCX, the following code will generate an error since there is no DO ... LOOP.
DIM iX, iY FOR iX = 1 TO 5 FOR iY = iX+1 TO 5 PRINT iX;iY IF iY +iY > 7 THEN EXIT DO NEXT NEXT
EXIT without a control named results in a warning message with the innermost loop named. The code generated results in the exiting of the innermost control loop.
EXIT NEST statement
Purpose: Causes an EXIT out of the nest of current loop types to the positon in the code where a different loop type is encountered.
Syntax:
EXIT NEST
|
Example 1: This example will EXIT from the nested DO loops when (w+x)*(y+z) > 20.
DIM w, x, y, z w = 0 WHILE w < 10 x = 0 WHILE x < 5 y = 0 DO z = 0 DO IF (w+x)*(y+z) > 20 THEN PRINT "Exit Nest" EXIT NEST END IF z++ PRINT "z Pass"; z LOOP UNTIL z > 4 y++ LOOP UNTIL y > 4 PRINT "w equals"; w x++ WEND w++ WEND PRINT "At end w equals"; w PAUSE
EXIT SELECT statement
Purpose: Causes an EXIT out of the SELECT ... END SELECT.
Syntax: EXIT SELECT |
Example 1: Here is a general example of when one might need EXIT SELECT
SELECT CASE SomeCondition CASE Condition_1 IF SomeFlagIsSet THEN EXIT SELECT ELSE Do_Condition_1_Thing() ' Only if SomeFlagIsSet = FALSE END IF CASE Condition_2 Do_Condition_2_Thing() CASE Condition_3 Do_Condition_3_Thing() END SELECT
Example 2: Here is an specific example using EXIT SELECT
$BCXVERSION "6.50" DIM WajYaDoing$, SelexitFlag$, TheThing$, What$ SelexitFlag$ = "Selexit" What$ = "One" TheThing$ = ToBeDone$(What$) PRINT WajYaDoing$ PRINT TheThing$ PRINT SelexitFlag$ = "NoSelexit" What$ = "One" TheThing$ = ToBeDone$(What$) PRINT WajYaDoing$ PRINT TheThing$ PRINT FUNCTION ToBeDone$(DoSomething$) DIM Retstr$ SELECT CASE DoSomething$ CASE "One" IF SelexitFlag$ = "Selexit" THEN WajYaDoing$ = "I'm Selexiting." Retstr$ = "See if I care ..." EXIT SELECT ELSE WajYaDoing$ = "I'm not Selexiting. " Retstr$ = "You had your chance. No whining. No excuses." END IF END SELECT FUNCTION = Retstr$ END FUNCTION
Result:
I'm Selexiting. See if I care ... I'm not Selexiting. You had your chance. No whining. No excuses.
END statement
Purpose: Immediately terminates a running program
Syntax: END |
REPEAT ... END REPEAT statement
Purpose: REPEAT ... END REPEAT blocks allow you to create loops without the need of a loop variable. BCX translates these to "C" style for/next loops that instead use temporary variables that are local to the loop.
Example:
CLS REPEAT 2 REPEAT 5 PRINT "Here is an example of nested REPEATS" END REPEAT END REPEAT PRINT DIM Iterations INPUT "Type a number, press ENTER ", Iterations REPEAT(Iterations+1+((Iterations+1)*2)) PRINT "Calculated Expressions Allowed in REPEAT/END REPEAT" END REPEAT
Result:
Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Here is an example of nested REPEATS Type a number, press ENTER 3 Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT Calculated Expressions Allowed in REPEAT/END REPEAT
To count backwards, the argument must begin with a minus sign. The "add a minus sign" rule is the same rule that BCX has always used in FOR ... NEXT statements that contain a negative STEP clause. "add a minus sign" is the only way that BCX can detect and respond to the logic flow at compile time.
Examples :
REPEAT -10 REPEAT -A REPEAT -(A*2+100)
See ITERATE to start the next iteration of a END REPEAT early in control loops.
EXIT REPEAT immediately breaks the flow out of a REPEAT block.
BCX_REPEAT variable
The BCX_REPEAT variable automatically keeps count of how many times REPEAT has been executed within a REPEAT ... END REPEAT block.
Example:
REPEAT 2 PRINT BCX_REPEAT REPEAT 5 PRINT "... ", BCX_REPEAT END REPEAT END REPEAT
Result:
1 ... 1 ... 2 ... 3 ... 4 ... 5 2 ... 1 ... 2 ... 3 ... 4 ... 5
Here's another sample.
DIM a a = -10 REPEAT -ABS(a) PRINT BCX_REPEAT IF BCX_REPEAT = 5 THEN EXIT REPEAT END REPEAT
Result:
1 ... 1 ... 2 ... 3 ... 4 ... 5 2 ... 1 ... 2 ... 3 ... 4 ... 5
WITH ... END WITH statement
Purpose: WITH ... END WITH allows repeated reference to be made to an user defined type object or structure.
Syntax: WITH UserDefinedTypeObject [ statements ] END WITH |
Example 1:
TYPE QWERTY DIM a DIM b! DIM c[80] AS CHAR DIM q AS RECT END TYPE GLOBAL MyType [10,10,10] AS QWERTY WITH MyType[2,3,4] .a = 1 .b! = 2.345 .c$ = "Hello world from a poly-dimensional udt!" PRINT .a PRINT .b! PRINT UCASE$(.c$) WITH .q .left = 100 .right = 200 .top = 150 .bottom = 300 PRINT .left PRINT .top PRINT .right PRINT .bottom END WITH END WITH
Result:
1 2.345 HELLO WORLD FROM A POLY-DIMENSIONAL UDT! 100 150 200 300
Example 2:
TYPE Foo One AS LONG Two AS LONG Three AS LONG END TYPE DIM MyArray AS Foo WITH MyArray .One = 1 .Two = 2 .Three= 3 PRINT .One PRINT .Two PRINT .Three END WITH
Result:
1 2 3
Example 3:
? Rx$("xyz123", "[a-z]", "*") ' replace letters ? Rx$("xyz123", "[0-9]", "*") ' replace numbers '---------------------------------------------------------- FUNCTION Rx$(MainStr AS STRING, Pattern$, Replacement$) '---------------------------------------------------------- DIM rx AS OBJECT : rx = CREATEOBJECT("VBScript.RegExp") WITH rx .IgnoreCase = TRUE .global = TRUE .Pattern = Pattern$ END WITH DIM tmp$ : tmp$ = rx.replace(MainStr AS STRING, Replacement$) SET rx = NOTHING FUNCTION = tmp$ END FUNCTION
Result:
***123 xyz***