Xbasic GuideLoop Statements
A statement that executes the same block of code multiple times is called a loop statement. Loops are used to perform some action for multiple entries in an array or while waiting for a response to an asynchronous action, such as Queues or callbacks.
Loops are created in Xbasic using FOR and WHILE statements.
FOR Loops
An Xbasic FOR loops is used to repeat a block of code a specified number of times. The FOR loop statement includes a numeric counter, a start value, and an end value. Each time the FOR loop executes, the counter is increased by 1.
DIM countingMsg AS C = "" FOR counter = 1 TO 10 'Count to 10 in the trace log countingMsg = countingMsg + counter + crlf() NEXT showvar(countingMsg,"Counting from 1 to 10")
You can optionally specify a STEP value if you wish to increment the counter by a value that is not 1.
FOR counter = start TO end STEP increment 'Xbasic code to execute NEXT
The STEP value can be any numeric number. For example, you can count backward from 10 to 1 by specifying a STEP of -1:
countingMsg = "" FOR counter = 10 TO 1 STEP -1 'Count from 10 to 1 countingMsg = countingMsg + counter + crlf() NEXT showvar(countingMsg,"Counting Backwards") countingMsg = "" FOR counter = 0 TO 10 STEP 2 'Count from 0 to 10 by 2 countingMsg = countingMsg + counter + crlf() NEXT showvar(countingMsg,"Counting by 2s")
You can optionally include the variable name for the counter in the NEXT statement for the FOR loop.
countingMsg = "" DIM counter AS N FOR x = 1 TO 10 FOR y = 1 TO 10 'Count to 100 counter = 10 * (x - 1) + y countingMsg = countingMsg + counter + crlf() NEXT y NEXT x showvar(countingMsg,"Counting from 1 to 100")
It is not required to include the counter variable in the NEXT statement. However, for long scripts or scripts with multiple FOR loops, it is useful to include the counter to document which FOR loop matches the NEXT statement.
FOR EACH: Looping Over Lists, Collections, or Arrays
The FOR EACH loop is a type of FOR loop for iterating over a data set stored in a character list, collection, or array. Instead of using a counter to track progress through the loop, the FOR EACH loop iterates over entries in an object.
FOR EACH element IN object ' Xbasic code to execute NEXT
The value of the current entry in the object can be accessed using the value property of the element.
valueOfElement = element.value
For example, consider the following list of cities and counties:
DIM places AS C = <<%txt% Canberra,Australia Brasilia,Brazil Ottawa,Canada Santiago,Chile Copenhagen,Denmark Tokyo,Japan Mexico City,Mexico Rabat,Morocco Wellington,New Zealand Oslo,Norway Lima,Peru Vanuatu,Port Vila Cape Town,South Africa Stockholm,Sweden Harare,Zimbabwe %txt%
The following FOR EACH loop builds a list of countries from the places list:
DIM countries AS C FOR EACH place IN places 'Get the value of the current element currentPlace = place.value 'Get the country name country = word(currentPlace,2,",") 'Add the country name to the countries list 'if the country is not in the list yet IF (country !$ countries) THEN countries = countries + country + crlf() END IF NEXT showvar(countries,"Countries")
When we run the script, the country list is displayed:
Skipping FOR Loop Iterations
It may not be necessary to execute a FOR loop until the loop's terminating condition evaluates to true (.T.). In some cases, you may only need to execute the code in the loop for some of the elements in the object. Iterations in a loop can be skipped using the CONTINUE keyword.
For example, using the places list created earlier, we could write the following script to create a list of countries that are not in North America:
'Create a list of places that are not in North America: DIM nonNorthAmericaPlaces as C DIM northAmerica as C = "USA,Canada,Mexico" FOR EACH place IN places country = word(place.value,2,",") 'Check to see if country is in Europe IF (country $ northAmerica) CONTINUE 'place is in North America, skip rest FOR loop END IF 'Add the place to the nonNorthAmericaPlaces list nonNorthAmericaPlaces = nonNorthAmericaPlaces + place.value + crlf() NEXT showvar(nonNorthAmericaPlaces,"Places not in North America")
If the country name is in the list of North American countries (northAmerica), the CONTINUE statement is executed, skipping the remainder of the current iteration of the FOR EACH loop and moving to the next entry in the places list.
Exiting FOR and FOR EACH Loops
You can exit a FOR loop or FOR EACH loop at any time using the EXIT FOR statement. EXIT FOR terminates the FOR loop and proceeds to the next line of code after the NEXT statement. For example, the script below searches the list of places for the city, Copenhagen. Once the city is found, there is no need to continue searching the rest of the list of places, so the FOR loop terminates with the EXIT FOR statement:
'Find the Country for "Copenhagen" DIM country AS C FOR EACH place IN places currentPlace = place.value city = word(currentPlace,1,",") IF (city = "Copenhagen") 'Country found country = word(place.value,2,",") EXIT FOR 'Exit the FOR loop because we found the country END IF NEXT showvar(country,"Copenhagen is located in...")
WHILE Loops
WHILE ... END WHILE is a control structure that repeats the statements it contains while the Logical Expression evaluates to true (.T.). Execution resumes at the line following the END WHILE statement when the Logical Expression is false (.F.) or when the EXIT WHILE statement executes.
countingMsg = "" counter = 1 WHILE counter <= 100 countingMsg = countingMsg + counter + crlf() 'Increment counter by 1 counter = counter + 1 END WHILE showvar(countingMsg,"Counting from 1 to 100")
Exiting WHILE Loops
Similar to FOR and FOR EACH loops, you can terminate WHILE loops early using the EXIT WHILE statement. For example, the code below computes the date of the next Tuesday for the current month. If no Tuesday is found before the end of the month (the value of the current month does not match the month of the nextDay variable), the WHILE loop terminates, and a message is shown stating that there are no Tuesdays left in the month.
noMoreTuesdays = .F. today = now() nextDay = today + 1 currentMonth = month(today) WHILE 3 != dow(nextDay) ' 3 = Tuesday IF (currentMonth <> month(nextDay)) THEN ' The month changed; there are no more Tuesdays ' Exit the WHILE loop noMoreTuesdays = .T. EXIT WHILE END IF nextDay = nextDay + 1 END WHILE IF (noMoreTuesdays) THEN showvar("There are no more Tuesdays this month.") ELSE showvar("The next Tuesday is on " + nextDay) END IF