versión 6.0
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éricas
Expresion_Inicio,
Expresion_Finy
Expresion_Incrementoson 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 variable
Variable_Contadordentro 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.
Ejemplos básicos
1. El siguiente ejemplo ejecuta 100 iteraciones:
For (vContador;1;100) ` Hacer algo End for
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]])=Char(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.
Disminuir la variable contador
En algunos casos, podría querer tener un bucle cuyo contador disminuya en lugar de aumentar. Para hacer esto,
Expresion_Iniciodebe 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]])=Char(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
Incrementar la variable contador en más de uno
Si necesita esto, puede utilizar en Expresion_Incremento un valor (positivo o negativo) cuyo valor absoluto sera mayor que uno.
9. El siguiente bucle se dirigue sólo a los elementos pares del Array unArray:
For ($vlElem;2;((Size of array(unArray)+1)\2)*2;2) ` Hacer algo con los elementos #2,#4...#2n unArray{$vlElem}:=... End for
Observe que la expresión ((Size of Array(unArray)+1)\2)*2 trata los arrays pares e impares.
Salir de un bucle cambiando la variable contador
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
Comparación de estructuras de bucle
Regresemos al primer ejemplo For...End for:
El siguiente ejemplo ejecuta 100 iteraciones:
For (vCounter;1;100) ` Hacer algo End for
Es interesante ver cómo los bucles While...End while y Repeat...Until realizan la misma acción.
Este es el bucle While...End while equivalente :
$i := 1 ` Inicialización del contador While ($i<=100) ` Bucle 100 veces ` Hacer algo $i := $i + 1 ` Hay que incrementar el contador End while
Este es el bucle Repeat...Until equivalente:
$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.
Optimizar la ejecución de For...End for
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
Estructuras For...End for de bucles anidados
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 for End for
Ver también
Case of...Else...End case, Condiciones y bucles, If...Else...End if, Repeat...Until, While...End while.