La sintaxis formal de la estructura de flujo de control For...End for es:
For(Variable_Contador;Expresion_Inicio;Expresion_Fin{;Expresion_Incremento}) instrucción(es) End for
El bucle For...End for es un bucle controlado por una variable contador:
La variable contador Variable_Contador es una variable numérica (Real, Entero, o Entero largo) que el bucle For...End for inicializa en el valor especificado por Expresion_Inicio.
Cada vez que el bucle se ejecuta, el valor del contador se incrementa en el valor especificado por el parámetro opcional Expresion_Incremento. Si no especifica Expresion_Incremento, la variable contador se incrementará por defecto en uno (1).
Cuando el contador alcanza el valor de Expresion_Fin , el bucle se detiene.
Importante: las expresiones numéricasExpresion_Inicio,Expresion_Fin yExpresion_Incremento son evaluadas una sola vez al comienzo del bucle. Si estas expresiones son variables, su modificación al interior del bucle no afectará el bucle.
Tip: sin embargo, con fines especiales, puede modificar el valor de la variableVariable_Contador
dentro del bucle; esto afectará el bucle.
Generalmente Expresion_Inicio es menor que Expresion_Fin .
Si Expresion_Inicio y Expresion_Fin son iguales, el bucle será ejecutado sólo una vez.
Si Expresion_Inicio es mayor que Expresion_Fin, el bucle no se ejecutará a menos de que Expresion_Incremento sea negativo. Ver ejemplos.
2. El siguiente ejemplo va a través de todos los elementos del Array unArray:
For($vlElem;1;Size of array(unArray)) ` Hacer algo con el elemento
unArray{$vlElem}:=... End for
3. El siguiente ejemplo va a través de todos los caracteres del texto vtTexto:
For($vlCar;1;Length(vtTexto)) ` Hacer algo con el carácter si es un TAB If(Character code(vtTexto[[$vlCar]])=Tab) ` ... End if End for
4. El siguiente ejemplo va a través de los registros seleccionados para la tabla [unaTabla]:
FIRST RECORD([unaTabla]) For($vlRegistro;1;Records in selection([unaTabla])) ` Hacer algo con el registro SEND RECORD([unaTabla]) ` ... ` Ir al siguiente registro NEXT RECORD([unaTabla]) End for
La mayoría de los bucles For...End for que usted escriba en sus bases se verán como los que presentamos en estos ejemplos.
En algunos casos, podría querer tener un bucle cuyo contador disminuya en lugar de aumentar. Para hacer esto,Expresion_Inicio debe ser mayor que Expresion_Fin y Expresion_Incremento debe ser negativo. Los siguientes ejemplos efectúan las mismas tareas que los ejemplos anteriores, pero en orden inverso:
5. El siguiente ejemplo ejecuta 100 iteraciones:
For(vCounter;100;1;-1) ` Hacer algo End for
6. El siguiente ejemplo va a través de todos los elementos del Array unArray:
For($vlElem;Size of array(anArray);1;-1) `Hacer algo con el elemento
unArray{$vlElem}:=... End for
7. El siguiente ejemplo va a través de todos los caracteres de texto vtTexto:
For($vlCar;Length(vtTexto);1;-1) ` Hacer algo con el carácter si es un TAB If(ASCII(vtTexto[[$vlCar]])=Tab) ` ... End if End for
8. El siguiente ejemplo va a través de los registros seleccionados de la tabla [unaTabla]:
LAST RECORD([unaTabla]) For($vlRecord;Records in selection([unaTabla]);1;-1) ` Hacer algo con el registro SEND RECORD([unaTabla]) ` ... ` Ir al registro anterior PREVIOUS RECORD([unaTabla]) End for
En algunos casos, usted podría querer ejecutar un bucle un cierto número de veces, pero luego salir del bucle cuando otra condición sea TRUE. Para hacer esto, puede probar esta condición dentro del bucle y si es TRUE, explicitamente definir la variable contador en un valor superior al valor de la expresión final.
10. En el siguiente ejemplo, se efectúa un bucle entre los registros de una selección hasta llegar al final de la selección o hasta que la variable interproceso <>vbWeStop, inicialmente definida como FALSE, se vuelva TRUE. Esta variable se maneja por un método de proyecto ON EVENT CALL que le permite interrumpir la operación:
<>vbWeStop:=False ON EVENT CALL("GESTION STOP") ` GESTION STOP define <>vbStop como True si las teclas Ctrl-punto (Windows) o Cmd-Punto (Macintosh) son presionadas $vlNumRegistros:=Records in selection([unaTabla]) FIRST RECORD([unaTabla]) For($vlRegistro;1;$vlNumRegistros) ` Hacer algo con el registro SEND RECORD([unaTabla]) ` ... ` Ir al siguiente registro If(<>vbWeStop) $vlRecord:=$vlNbRecords+1 ` Forzar a la variable contador a salir del bucle Else NEXT RECORD([unaTabla]) End if End for ON EVENT CALL("") If(<>vbStop) ALERT("La operación ha sido interrumpida.") Else ALERT("La operación ha terminado con éxito.") End if
$i :=1 ` Inicialización del contador Repeat ` Hacer algo $i :=$i +1 ` Hay que incrementar el contador Until($i=100) ` Bucle 100 veces
Consejo: el bucle For...End for es generalmente más rápido que los bucles While...End while y Repeat...Until , porque 4D prueba la condición internamente para cada ciclo del bucle e incrementa el contador. Por lo tanto, utilice la estructura For...End for cada vez que sea posible.
Puede utilizar como contador una variable interproceso, proceso o local de tipo Real, Entero, y Entero largo. Para bucles largos, especialmente en modo compilado, utilice variables locales de tipo entero largo.
11. Este es un ejemplo:
C_LONGINT($vlContador) ` uso de una variable local de tipo entero largo For($vlContador;1;10000) ` Hacer algo End for
Usted puede anidar tantas estructuras de control como necesite. Esto incluye anidamiento de bucles For...End for. Para evitar errores, asegúrese de utilizar una variable contador diferente para cada estructura de bucle
Estos son dos ejemplos:
12. El siguiente ejemplo va a través de todos los elementos de un Array de dos dimensiones:
For($vlElem;1;Size of array(unArray)) ` ... ` Hacer algo con la fila ` ... For($vlSubElem;1;Size of array(unArray{$vlElem})) ` Hacer algo con el elemento
unArray{$vlElem}{$vlSubElem}:=... End for End for
13. El siguiente ejemplo construye un Array de punteros para todos los campos de tipo Fecha presentes en la base:
ARRAY POINTER($apCamposFecha;0) $vlElem:=0 For($vlTabla;1;Count table) For($vlCampo;1;Count fields($vlTabla)) $vpCampo:=Field($vlTabla;$vlCampo) If(Type($vpCampo->)=Is date) $vlElem:=$vlElem+1 INSERT IN ARRAY($apCamposFecha;$vlElem) $apCamposFecha{$vlElem}:=$vpCampo End if End if End for End if End for