El AdvPL tiene nueve tipos de operadores que permiten construir expresiones sobre valores de datos, variables, campos de archivos de datos y funciones. Los nueve tipos son:
Algunos operadores son unarios, es decir, sólo requieren un operando, mientras que otros son binarios, o sea, requieren dos operandos. Operandos son datos, variables, campos o funciones sobre los que actúan los operadores.
Operadores de Caracteres
Todos los operadores de caracteres son binarios, es decir, siempre actúan sobre dos expresiones de datos tipo carácter. Existen sólo dos operadores de caracteres:
Operador | Operación sobre los caracteres |
+ | Concatenación con blancos |
- | Concatenación sin blancos |
El operador (+), también conocido como concatenación con blancos, une dos cadenas de caracteres en una sola. Por ejemplo:
cTexto1 := “AdvPL “ cTexto2 := “ – Lenguaje de programación de TOTVS” cTexto3 := cTexto1 + cTexto2 MSGALERT(cTexto3) // Resulta: “AdvPL - Lenguaje de programación de TOTVS” |
El operador menos ( - ), concatenación sin blancos, también une dos cadenas de caracteres en una sola. No obstante, los espacios en blanco que preceden al operador se mueven hacia el final de la cadena de caracteres que lo sigue. Por ejemplo:
cTexto1 := “AdvPL“ cTexto2 := “ Lenguaje de programación de TOTVS” cTexto3 := cTexto1 + cTexto2 MSGALERT(cTexto3) // Resulta: “AdvPL Lenguaje de programación de TOTVS” cTexto4 := cTexto1 – cTexto2 MSGALERT(cTexto4) // Resulta: “AdvPLLinguaje de programación de TOTVS” |
Operadores de Fechas
Datos tipo fecha se pueden sumar o sustraer en términos de número de días por medio de los operadores suma ( + ) y sustracción ( - ).
Una adición de días a una fecha genera una nueva fecha en el futuro, mientras que una sustracción de días genera una nueva fecha en el pasado. En este caso, es obligatorio que el dato tipo fecha sea el primer operando y el número de días sea el segundo. Por ejemplo:
MSGALERT(DATE()) // Suponiendo que la fecha actual es 31/12/11, esta fecha es la que se mostrará. MSGALERT(DATE() + 1) // Resulta: 01/01/12 MSGALERT(DATE() – 1) // Resulta: 30/12/11 MSGALERT(1 + DATE()) / Resulta en error |
Una sustracción entre dos fechas resulta en un número valor numérico representando el intervalo de días entre ellas. Por ejemplo:
MSGALERT(CTOD(“19/12/90”) – CTOD(“25/12/90”)) // Resulta: 6. Es decir, seis días de intervalo. |
Operadores Matemáticos
Todos os operadores matemáticos, excepto los signos unarios positivo y negativo, son binarios y operan sobre expresiones o datos numéricos, que generan otros valores numéricos como resultado. Son los siguientes:
Operador | Operación matemática |
+ | Adición o unario positivo |
- | Sustracción o unario negativo |
* | Multiplicación |
/ | División |
^ | Potenciación |
% | Módulo (residuo de la división) |
El operador módulo calcula el residuo de la división de una expresión numérica por otra. Así, el 4% de 3 es igual a 1, por ejemplo:
En las operaciones de cálculo, el orden normal de precedencia para la ejecución de las operaciones matemáticas es:
Los paréntesis se utilizan para agrupar operaciones y modificar la precedencia de las operaciones. Por ejemplo:
MSGALERT(4 * 2 + 1) // Resulta 9 MSGALERT(4 * (2 + 1)) // Resulta 12 |
Se pueden definir tantos niveles de paréntesis como sean necesario, siempre y cuando su balanceo esté correcto. Es decir, el número de abre paréntesis debe ser idéntico al número de cierra paréntesis.
Operadores Relacionales
Los operadores relacionales son binarios y generan resultados lógicos (verdadero o falso) a partir de la comparación entre dos expresiones.. Se pueden utilizar en expresiones numéricas, carácter, fecha o NIL.
Las expresiones relacionadas deben ser obligatoriamente del mismo tipo de dato. Los operadores relacionales del AdvPL son:
Operador | Operación Relacional |
< | Menor que |
> | Mayor que |
= | Igual a |
== | Doble igual a |
<> | Diferente de o No igual |
# | Diferente de o No igual |
!= | Diferente de o No igual |
<= | Menor o igual a |
>= | Mayor o igual a |
$ | Comparación de subcadena de carácter |
Cuando se relacionan dos expresiones por medio de dichos operadores, la expresión de la derecha se compara con la de la izquierda. El resultado de esta comparación es un valor lógico verdadero (.T.) o falso (.F.). Por ejemplo:
nNum1 := 100 nNum2 := 200 MSGALERT(nNum1 > nNum2) // Resulta falso (.F.), puesto que 100 no es mayor que 200. MSGALERT(nNum2 > nNum1) // Resulta verdadero (.T.), puesto que 200 es mayor que 100. MSGALERT(nNum1 <> nNum2) // Resulta verdadero (.T.), puesto que 100 es diferente de 200. MSGALERT(“AdvPL” = “Adv”) // Resulta verdadero (.T.) MSGALERT(“Apple” <> “Aple”) // Resulta verdadero (.T.) |
Los operadores relacionales poseen tan sólo una orden de precedencia en la que las operaciones se realizan: de izquierda a derecha.
El operador $ (subcadena o substring) opera solamente sobre expresiones del tipo carácter. Éste compara la expresión de la izquierda con la de la derecha, regresando verdadero si la expresión de la izquierda está contenida en la de la derecha o si las dos expresiones son idénticas. Por ejemplo:
cTextoA := “AdvPL” cTextoB := “Programas” cTextoC := “Lenguaje para generar programas de TOTVS” MSGALERT(cTextoA $ cTextoB) // Resulta falso (.F.) MSGALERT(cTextoA $ cTextoC) // Resulta verdadero (.T.) MSGALERT(cTextoB $ cTextoC) // Resulta verdadero (.T.) MSGALERT(cTextoC $ cTextoA) // Resulta falso (.F.) |
El operador doble igual (==) actúa de manera idéntica al operador igual (=) para expresiones numéricas o tipo fecha. En el caso de expresiones del tipo carácter, retornará verdadero sólo si la expresión de la derecha es exactamente idéntica a la expresión de la izquierda. Por ejemplo:
cTextoA := “Adv” cTextoB := “AdvPL” MSGALERT(cTextoB = cTextoA) // Resulta verdadero (.T.) MSGALERT(cTextoB == cTextoA) // Resulta falso (.F.) |
Cuando se comparan dos array, el operador doble igual (==) regresa verdadero (.T.) si ambos tienen el mismo contenido. Es decir, si son idénticos, teniendo los mismos elementos y valores.
Operadores Lógicos
Los operadores lógicos suministran valores lógicos (falso / .F. o verdadero / .T.) a partir de la comparación de dos expresiones lógicas, que son sus operandos. Excepto el operador .NOT. o !, todos son binarios.
Los operadores lógicos del AdvPL son:
Operador | Operación Lógica |
.AND. | Conector lógico Y |
.OR. | Conector lógico O |
.NOT. o ! | Conector lógico NO |
El orden de precedencia para los operadores lógicos es:
Los operadores lógicos relacionan dos expresiones lógicas. Los siguientes ejemplos demuestran algunos casos:
nNumA := 100 nNumB := 200 nNumC := 300 MSGALERT(nNumB > nNumA .AND. nNumC > nNumB) // Resulta verdadero (.T.) MSGALERT(nNumB > nNumA .AND. nNumB = nNumC) // Resulta falso (.F.) MSGALERT(nNumB > nNumA .OR. nNumB = nNumC) // Resulta verdadero (.T.) |
El operador .NOT. o ! (negación) es unario. Es decir, actúa sobre una sola expresión. Si la expresión es verdadera, la transformará en falsa y viceversa. Por ejemplo:
lCont := .T. MSGALERT( .NOT. lCont ) // Resulta falso (.F.) MSGALERT( ! lCont ) // Resulta falso (.F.) // Función para buscar el código del cliente FUNCTION PesqCli(cCodigo) dbSelectArea(“SA1”) dbSetOrder(1) dbSeek(cCodigo) IF ! FOUND() // Si no se encontró RETURN // Finaliza ENDIF |
Para comprender mejor el resultado de los operadores lógicos, verifique en la siguientes tabla las situaciones en las que se entrega el resultado verdadero (.T.):
Operador | Resultado |
.AND. | Provee verdadero (.T.) si ambos operandos son verdaderos (.T.). |
.OR. | Provee verdadero (.T.) si tan sólo uno de los operandos es verdadero (.T.). |
.NOT. o ! | Provee verdadero (.T.) si su operando es falso (.F.) |
Operadores de Atribución
Los operadores de atribución relacionados a continuación, atribuyen valores o datos a las variables, campos o elementos de array:
Operador | Operación de Atribución |
= | Atribución normal |
:= | Atribución en línea de instrucción |
+= | Adición y atribución en línea de instrucción |
-= | Sustracción y atribución en línea de instrucción |
*= | Multiplicación y atribución en línea de instrucción |
/= | División y atribución en línea de instrucción |
^= | Potenciación y atribución en línea de instrucción |
%= | Módulo y atribución en línea de instrucción |
Todos los operadores de atribución son binarios. Es decir, requieren dos operandos. El primero debe ser obligatoriamente el nombre de una variable y el segundo puede ser cualquier expresión válida, incluso el valor NIL.
Para los operadores compuestos, es decir, los que realizan una operación matemática y otra de atribución, el primer operando (la variable) a la que se atribuirá el valor de una expresión), debe estar previamente creado y debe ser del mismo tipo de dato que el segundo operando.
La siguiente tabla muestra los tipos de datos que se pueden operar por cada uno de los operadores de atribución.
Operador | Tipos de datos válidos |
= | Cualquier tipo de dato |
:= | Cualquier tipo de dato |
+= | Carácter, fecha, memo y numérico |
-= | Carácter, fecha, memo y numérico |
*= | Numérico |
/= | Numérico |
^= | Numérico |
%= | Numérico |
El operador igual ( = ) atribuye un valor para una variable o campo de archivo de datos. El primer operando debe ser el nombre del campo de un archivo de datos o el nombre de una variable. Por ejemplo:
nNum = 100 // Atribuye el valor 100 a la variable nNum cNome = “Laércio Cosentino” // Atribuye la cadena de caracteres a la variable cNome SA1->A1_NOME = cNome // Atribuye el contenido de la variable cNome al campo del archivo de clientes |
El operador en línea ( := ) es similar al operador igual ( = ). Entretanto, éste se puede utilizar en cualquier comando o función cuya sintaxis permita el uso de una expresión. Por ejemplo:
// Declara variables privadas y las ejecuta PRIVATE nNum1 := 100 PRIVATE nNum2 := 300 IF (total := nNum1 + nNum2) > 300 // Condición utilizando el operador en línea SA1->A1_OBS := SPACE(30) // Se graba 30 espacios en blanco en el campo del archivo de datos ENDIF |
Los operadores de atribución compuestos realizan una operación entre dos operandos y después atribuyen el resultado al primero. La siguiente tabla aclara como funciona. Note que todos los operadores compuestos son del tipo en línea.
Operador | Utilización | Operación |
+= | A += B | A := A + B |
-= | A -= B | A := A – B |
*= | A *= B | A := A * B |
/= | A /= B | A := A / B |
%= | A %= B | A := A / B |
^= | A ^= B | A := A ^ B |
Operadores de Incremento y Decremento
Los operadores de incremento son unarios, es decir, operan sobre un único operando del tipo numérico o fecha. El operando debe ser el nombre de una variable y no debe ser un campo de archivo de datos. El tipo de dato que resulta de la operación será idéntico al del operando. La siguiente tabla muestra estos operadores y su operación
Operador | Utilización | Operación |
++ | A++ | A := A + 1 |
-= | A-- | A := A – 1 |
++ | ++A | A := A + 1 |
-= | --A | A := A – 1 |
El operador doble más ( ++ ) incrementa su operando en una unidad, mientras que el operador doble menos ( -- ) decrementa su operando en una unidad. Se pueden utilizar como prefijo o como sufijo.
Al utilizarlos como prefijo modifican el operando antes de efectuar la atribución. Al utilizarlos como sufijo modifican el operando después de realizar la atribución. Los ejemplos ilustran algunas operaciones típicas con estos operadores.
nNum1 := 0 nNum2 := ++nNum1 MSGALERT(nNum1) // Resulta 1 MSGALERT(nNum2) // Resulta 1 nNum2 := 1 nNum4 := nNum2-- MSGALERT(nNum2) // Resulta 0 MSGALERT(nNum4) // Resulta 1 nNum5 := 2 MSGALERT(nNum5++ * nNum5) // Resulta 6 MSGALERT(nNum5) // Resulta 3 MSGALERT(nNum6 := 2) MSGALERT(--nNum6 * nNum6) // Resulta 1 MSGALERT(nNum6) // Resulta 1 |
Operadores Especiales
La siguiente tabla muestra los operadores especiales del AdvPL y su respectivo objetivo.
Operador | Objetivo |
( ) | Función o agrupación |
[ ] | Especifica un elemento de un array |
{ } | Definición de un array o de bloques de código |
-> | Identificador de alias |
@ | Paso de parámetros por referencia |
Además de participar de la definición de funciones, incluyendo la lista de parámetros, los paréntesis se utilizan en expresiones para agrupar determinadas operaciones que se deben evaluar primeramente. Los paréntesis se utilizan para modificar y determinar el orden en que las operaciones se deben efectuar. Las operaciones que estén dentro de los paréntesis más internos, se ejecutarán en primer lugar, y así por delante, hasta evaluar el valor final de la expresión.
Por lo general, las operaciones se efectúan a partir de los paréntesis más internos hacia los más externos, siendo que inicialmente se ejecutan las operaciones matemáticas, seguidas de las comparaciones relacionales. Finalmente, se evalúan los conectores lógicos. Por ejemplo, el resultado de la siguiente expresión es verdadero (.T.).
lResult := ( 4 * ( 3 + 5 ) ) / 2 > 100 .OR. ( 5 * ( 3 + 4 ) ) / 2 < 100 |
En la ejecución de funciones, los paréntesis se utilizan después del nombre identificador de la respectiva rutina, incluso la lista de argumentos. Por ejemplo:
MSGALERT(SQRT(nNum1)) // Muestra en la pantalla la raíz cuadrada del número contenido en la variable nNum1 MSGALERT(“¡Ésta es una prueba!”) // Muestra un mensaje en la pantalla MSGALERT(DATE()) // Muestra en la pantalla la fecha actual |
Los corchetes ( [ ] ) se utilizan en referencia a elementos de array. Por ejemplo:
PRIVATE aTeste[10, 10] // Declara el array aTeste con 10 líneas y 10 columnas aTeste[1, 1] := 100 // Atribuye el valor 100 al primer elemento del array aTeste MSGALERT(aTeste[1, 1]) // Muestra en la pantalla el valor de dicho elemento del array. Resulta 100. |
Las llaves ( { } ) se utilizan para crear y referenciar matrices literales, sólo con una dimensión. Los elementos de la matriz deben estar entre las llames, separados por comas. Las claves se utilizan también en la creación de bloques de código. Por ejemplo:
PRIVATE aMatriz := { 10, 20, 30, 40, 50, 98 } // Crea un array sólo con una dimensión MSGALERT(aMatriz[3]) // Muestra el valor 30 en la pantalla bBloco := { | nDado, nCoef | nDado * nCoef } // Crea un bloque de código con dos argumentos |
El identificador de alias ( -> ) se utiliza para hacer una referencia explícita a un campo de archivos de datos. Si el nombre de un área de trabajo (alias) precede este operador, el mismo puede ser seguido por un nombre de campo de archivo de datos correspondiente o por cualquier expresión válida que contenga referencias al archivo de datos abierto en el área de trabajo, cuyo alías se especificó. Por ejemplo:
SA1->A1_NOME := cNome // Se refiere al campo A1_NOME de la tabla SA1 (Archivo de Clientes) |
Finalmente, el operador de paso de parámetros por referencia ( @ ) se utiliza precediendo argumentos de funciones. Es un operador unario que opera como prefijo de nombres de variables, indicando que el argumento se está pasando por referencia, en lugar de hacerlo por valor, como es lo normal, para la función invocada. Por ejemplo:
// Ejecuta (Invoca) la función Búsqueda, pasando los argumentos // cCod y cCodF por referencia. Pesquisa(@cCod, @cCodF, “Códigos Deseados”, “999”) |
Otro ejemplo de pasaje de parámetros por referencia con el uso del operador @:
FUNCTION Main() LOCAL nA := 0 LOCAL nB := 1 LOCAL nC := 2 LOCAL nX := 0 nX := Calculo(@nA, nB, nC) MSGALERT(nX) // Resulta 6 MSGALERT(nA) // Resulta 3 // El valor de la variable nA se modificó porque ésta fue pasada por referencia a la función Calculo() RETURN NIL // Función de cálculo FUNCTION Calculo(nParam1, nParam2, nParam3) LOCAL nRetorno := 0 nParam1 := nParam2 + nParam3 nRetorno := nParam1 * nParam2 * nParam3 RETURN nRetorno |
El Operador Macro ( & )
El operador macro permite compilar expresiones durante la ejecución de los programas y la sustitución del nombre de variables o expresiones tipo carácter por su contenido o resultado. Siempre que el operador macro ( & ) sea encontrado, la expresión se someterá al compilador del AdvPL
Una expresión macro se debe especificar por medio de la siguiente sintaxis:
&( <expresión macro> )
La expresión macro se debe colocar obligatoriamente entre paréntesis. La operación macro se ejecuta sobre su resultado, que debe ser del tipo carácter. Este recurso permite que el contenido de campos de archivos de datos y elementos de arrays se compilen y ejecuten como parte del código del programa, siempre y cuando contengan una expresión o un bloque de código.
El operador macro ( & ) puede ejecutar sustituciones de textos o compilación de expresiones durante la ejecución de un programa, dependiendo de como se especifique. Por ejemplo:
Sustitución de textos
cMacro := “colega” MSGALERT(“Cómo está “ + &(cMacro) + “?”) // Resulta: ¿Cómo va colega? //En este otro ejemplo, se mostrará el nombre del cliente. //Por ejemplo, el puntero del índice del archivo //está ubicado en el registro Carlos Alberto Montagnini. //En este caso, el mensaje será: //¿Cómo está Ud., Carlos Alberto Montagnini? MSGALERT(“Cómo está Ud.,“ + &(SA1->A1_NOME) + “?”) |
Compilación de expresiones
cMacro := “DTOC(DATE())” MSGALERT( &(cMacro) ) // Resulta “22/05/12” |
El operador macro no se puede utilizar para sustituir o compilar las palabras clave que identifican los comandos. Por ejemplo:
cMacro := “PRIVATE” &(cMacro) nJuros := 0 // No es válido!!! |
En el caso del alias de archivos de datos, no es necesario utilizar el operador macro ( & ). Basta utilizar el abre y cierra paréntesis. Por ejemplo:
(cAlias)->TRB_VALOR |
Orden de Precedencia de los Operadores
Cuando varios operadores distintos se utilizan en una misma expresión, el orden de precedencia para ejecutar las operaciones es:
Orden | Operación |
1 | Llamadas a funciones |
2 | Operadores especiales |
3 | Operador macro |
4 | Preincremento / Predecremento |
5 | Operadores de caracteres |
6 | Operadores matemáticos |
7 | Operadores relacionales |
8 | Operadores lógicos |
9 | Operadores de atribución |
10 | Postincremento / Postdecremento |
Los paréntesis se pueden utilizar para modificar el orden en el que se efectuarán las operaciones. Las operaciones que estén dentro de los paréntesis más internos se ejecutarán en primer lugar, y así por delante, hasta obtener el resultado final de la expresión que se está evaluando.
Dentro de una misma clase de operadores, excepto los operadores matemáticos y lógicos, las operaciones tienen la misma precedencia y siempre se ejecutan de izquierda a derecha. Mientras que, en el caso particular de múltiples atribuciones en línea ( := ), las atribuciones se ejecutan de derecha a izquierda.
Cuando varios operadores matemáticos aparecen en una misma expresión, el orden de precedencia seguida por el AdvPL es:
Orden | Operación |
1 | Las señales unarias positivo ( + ) y negativo ( - ). |
2 | Potenciación ( ^ ) |
3 | Multiplicación ( * ), división ( / ) y módulo ( % ) |
4 | La adición y sustracción |
Así como los operadores matemáticos, cuando varios operadores lógicos aparecen en una misma expresión, estos tiene su propria orden de precedencia:
Orden | Operación |
1 | Operador de negación ( .NOT. o ! ) |
2 | Conector aditivo ( .AND. ) |
3 | Conector alternativo ( .OR. ) |
Aunque el AdvPL defina automáticamente una orden de precedencia para sus operadores, se recomienda el uso de los paréntesis para determinar la precedencia, aún cuando sean dispensables. Esta práctica facilita la lectura y la comprensión de los programas.