Está en la página 1de 595

CAP N° 1: PROGRAMACION ESTRUCTURADA

CLIPPER 5.2 El siguiente curso surge como necesidad de preparar una serie de clases sobre dicho lenguaje, para impartir en una academia.

Pero un buen curso no se ha de limitar solo ha explicar los conceptos básicos, y ver cuatro ejemplos inconexos, que puede que sirvan a nível teórico, pero no en la práctica, sino que ha de transmitir a los alumnos la experiencia profesional del profesor, y lo que es más

importante prepararlos para la resolución de problemas. Lamentablemente esto no suele ocurrir, mucho y llegado

a cierto punto, el alumno solo ante un problema de

programación se bloquea, y lo se porque he pasado por ellos.

No solo hay que enseñar la sintaxis del lenguaje, sino que hay que enseñar programación y resolución de problemas, pensad que para cada problema hay más de una solución, y que aunque exponga varios métodos, podéis encontrar más, y también me puedo equivocar.

Por ello el curso se divide en varios apartados: una parte teórica (puede que la más pesada, lo siento) y

otra práctica, una serie de ejercicios (solo para recordar aspectos claves), una serie de programas con su código fuente, la lista de comandos y funciones de CA-Clipper

y un diccionario de terminos informaticos

¿ QUE ES CLIPPER ?

Una definición de Clipper, en sus inicios, podrías ser:

"Compilador del lenguaje dBase"

Sin embargo, en la actualidad dicha definición ya no es válida Clipper va más alla de ser un mero compilador de dBase, e incorporá un lenguaje propio, con una sintaxis y potencia cercanas al C, y una serie de elementos que desde el punto de dialectos xBase, existentes en el mercado.

Historia de Clipper

Clipper supongo que toma su nombre de uno de los veleros más rápidos del siglo XIX. Esto es una suposición ya que en sus inicios fue comercializado por Nantucket, y actualmente es propiedad de Computer Associates.

Aparece en 1985 para cubrir una de las necesidades de un esplendido producto, el dBase, que por aquel entonces era de AsthonTate (ahora lo es de Borland), cuyo lenguaje, aunque potente era interpretado. Y como es lógico los programadores necesitaban de un producto que les permitiera distribuir sus aplicaciones libremente, sin el costo adicional que suponía para el usuario la adquisición obligatoria del dBase, y más en aquellos tiempos con el precio que tenía el software.

Por lo que en sucesivas versiones, Clipper Autumn'86 y Clipper Summer'87, fue manteniendo la compatibilidad con dBase pero incorporando nuevas mejoras: conexión con el lenguaje C y ensamblador, uso de tablas, etc. En Abril-90, al aparecer el Clipper 5, se rompe dicha compa tibilidad con dBase, y se acerca más al lenguaje C++, el lenguaje de programación por excelencia.

INSTALACION Y CONFIGURACION DEL ENTORNO DE TRABAJO

Requisitos del sistema

La instalación de CA-Clipper requiere unos requisitos mínimos que son:

* Ordenador IBM-PC o 100% compatible

* Versión 3.3 o superior de MS-DOS

* 640 Kb. de memoria RAM

* Entre 3 Mb. y 6 Mb. de disco duro, según se realize la ins talación mínima o completa.

Instalación El sistema de instalación es sencillo, y el número de disquets es reducido al estar CA-Clipper comprimido.

Para empezar la instalación situese en la correspondientes unidad de disquet A: o B:, y teclee: INSTALL.

A continuación tendrá que indicar o confirmar, el directorio principal de la instalación, y los modulos a instalar.

Estructura de Directorios Una vez instalado CA-Clipper, dependiendo del tipo de ficheros,estos se encuentran en directorios concretos:

Subdirectorio Descripción

\CLIPPER5

(o el nombre indicado)

Directorio principal de CA-Clipper

\BIN

 

Ficheros ejecutables: (.EXE y .BAT) (aquí se encuentran: clipper, rtlink, cld, cl.bat, rmake, etc. )

\INCLUDE

Ficheros de cabecera (.CH y .H)

 

\LIB

 

Ficheros de librería (.LIB)

\PLL

Ficheros de preenlace (.PLL)

\SOURCE

Ficheros con código fuente (.PRG)

   
 

\DBU

Utilidad de Base de Datos

\PE

Editor de programas

 

\RL

Utilidad de informes y etiquetas

 
 
 

\SAMPLE

Programas fuente de ejemplo

 

\SYS

Programas fuentes del subsistema

 

\NG

Documentación en línea (NORTON GUIDES)

Configuración Para poder trabajar eficientemente con CA-Clipper, tenemos que especificar los directorios de búsqueda de ficheros (PATH), e incluir una serie de variables de entorno en el AUTOEXEC.BAT y en el CONFIG.SYS

Si queremos al instalar CA-Clipper, podemos realizar los cambios automáticamente o que estos queden guardados en los ficheros AUTOEXEC.CHG y CONFIG.CHG para que luego podamos añadirlos manualmente (los deseados) a los ficheros oportunos.

Si tenemos que trabajar con distintas versiones de Clipper, necesitaremos una configuración para cada versión, entonces es mejor guardar estas en ficheros BATCH, y activarlos según las necesidades.

Una configuración mínima para poder trabajar sería:

REM Añadir al AUTOEXEC.BAT lo siguiente:

REM ------------------------------------

REM En el PATH

REM No dejar espacios en blanco, antes o despues de los "=" SET CLIPPER=F35

SET INCLUDE=C:\CLIPPER5\INCLUDE SET LIB=C:\CLIPPER5\LIB SET OBJ=C:\CLIPPER5\OBJ

;C:\CLIPPER5\BIN;C:\NG

El comando PATH establece la ruta de búsqueda para los ficheros ejecutables.

VARIABLES DE ENTORNO

La variable de entorno SET CLIPPER, determina la configuración que tendrá un programa realizado con CA- Clipper, y puede tener los siguientes parámetros:

SET CLIPPER=//E:<nnn>; //F:<nnn>; //X:<nn>; //BADCACHE; //CGACURS; //DYNF:<n>; //INFO; //NOIDLE; //SWAPK:<nnnnn>; //SWAPPATH:<vía>; //TEMPPATH:<vía>

E:<nnn> Siendo nnn los Kb. de memoria expandida a usar.

F:<nnn> Siendo nnn el nº máximo de ficheros abiertos simultaneamente. Trabaja en conjunción con los FILES del CONFIG.SYS, y se toma el valor más bajo de los dos.

X:<nn> Siendo nn la memoria a excluir de CA-Clipper.

BADCACHE Salva/recupera el estado de la memoria expandida (EMS), cuando accedemos a ella.

CGACURS Impide la utilización de ciertos modos de cursor en algunos adaptadores EGA/VGA.

DINF:<n> Siendo n el nº de manejadores de ficheros a utilizar en

la gestión de los overlays dinámicos. Por defecto es 2,

y los límites de 1 a 8.

NOIDLE

Impide que CA-Clipper realice sus gestiones de memoria

y disco, en los tiempos muertos (InKey(), prompt, read, get,etc.).

INFO Muestra en pantalla la información de configuración de la memoria durante el arranque.

SWAPK:<nnnnn> Especifica los Kb. de disco que se usarán para el

manejo de la memoria virtual. Por defecto son 16 Mb.,

y los límites 256 Kb.y 65 Mb.

SWAPPATH:<vía> Indica el disco y el directorio del fichero de intercambio de memoria virtual.

TEMPPATH:<vía> Indica el disco y directorio de ubicación de los ficheros temporales.

SET CLIPPERCMD=<lista opciones compilador> Especifica una lista de opciones del compilador que se utilizarán por defecto, si no indicamos lo contrario. Ver compilador, Clipper.

SET INCLUDE=<vía> Indica el disco y directorios, separados por punto y coma (;), donde buscar los ficheros de cabecera (#include).

SET LIB=<vía> Indica el disco y directorios, separados por punto y coma (;), donde buscar los ficheros de librería (.LIB).

SET OBJ=<vía> Indica el disco y directorios, separados por punto y coma (;), donde buscar los ficheros objeto (.OBJ).

SET PLL=<vía> Indica el disco y directorios, separados por punto y coma (;), donde buscar los ficheros de transferencia preenlazados (.PLT) y los ficheros de biblioteca preenlazados (.PLL).

SET RMAKE=<lista opciones rMake> Indica una lista de opciones para la utilidad de mantenimiento de programas rMake, que utilizaremos por defecto si no indicamos lo contrario. Ver mantenimiento de programas con RMAKE.

SET RTLINKCMD=<lista opciones enlace> Indica una lista de opciones a utilizar por defecto por el enlazador, si no indicamos lo contrario. Ver enlazador, RTLINK.

SET TMP=<vía> Indica el disco y directorio donde el compilador y enlazador escribirán sus ficheros temporales.

REM Añadir o modificar en el CONFIG.SYS lo siguiente:

REM -------------------------------------------------

FILES=35

BUFFERS=35

El comando FILES indica el número de ficheros abiertos a la vez que podamos tener, el máximo es de 255. Pero tenga en cuenta que se consume memoria.

El comando BUFFERS aumenta la memoria que el MS-DOS reserva para la transferencia de ficheros.

EL COMPILADOR DE CA-CLIPPER: CLIPPER.EXE

Compila uno o más fuentes (.PRG) que contienen los procedimientos y funciones definidos por el programador para formar un fichero (.OBJ). Luego, una vez enlazado por RTLINK con las librerías necesarias se formará el (.EXE).

Sintaxis:

---------

necesarias se formará el (.EXE). Sintaxis: --------- CLIPPER [<fichero fuente> | @<fichero

CLIPPER [<fichero fuente> | @<fichero Script> [<lista opciones>]]

Argumentos de línea:

--------------------

<fichero fuente> Es el nombre del programa a compilar, (.PRG).

<fichero script> Es el nombre de un fichero de texto ASCII que contiene una lista de ficheros fuentes a compilar en un solo fichero objeto. Por defecto, tienen la extensión (.CLP).

Por ejemplo, suponga que tenemos los siguientes fuentes:

* FTR.PRG, programa de facturación que será el (.EXE).

* FUNCION.PRG, funciones de usuario.

* ARTICULO.PRG, mantenimiento de artículos.

* CLIENTES.PRG, mantenimiento de clientes.

* FACTURA.PRG, proceso de facturación.

Si creamos el siguiente fichero ASCII: FTR.CLP

FTR

FUNCION

ARTICULO

CLIENTES

FACTURA

Al compilarlo con: CLIPPER @FTR, se generá un único fichero

Al compilarlo con: CLIPPER @FTR, se generá un único fichero objeto que es el FTR.OBJ

Opciones del compilador

/A Declara variables privadas (PRIVATE), públicas (PUBLIC) o parámetros (PARAMETERS) como MEMVAR, es decir, que sean accesibles por los procedimientos y funciones que se utilizen desde el procedimiento donde se han declarado.

/B Incluye información de depuración en el fichero objeto.

/CREDIT Muestra los créditos de CA-Clipper en la pantalla.

/D<identificador>[=<texto>] Define un identificador al preprocesador con <texto> asignado al <identificador>, si esté es especificado.

/ES Nível de error por defecto, si se produce salimos al DOS.

/ES0

Similar al anterior.

/ES1

Si se detectan advertencias (warnings) durante la compilación, salimos al DOS.

/ES2

Si se detectan advertencias, no se genera el (.OBJ), y salimos al DOS.

/l<vía> Añade al principio de la variable de entorno, un nuevo directorio donde buscar los ficheros INCLUDE.

/L Excluye de los ficheros objeto los números de línea del código fuente del programa. Si este ocupa mucho, podemos reducir con esta opción algunas Kb.

/M Compila solamente el programa actual, sin hacer caso de las llamadas a otros programas mediante: DO, SET FORMAT y SET PROCEDURE.

/N Permite que las funciones y procedimientos puedan tener el mismo nombre que los programas fuente.

/O<fichero obj> Define el nombre y/o ubicación del fichero objeto de salida.

/P Preprocesa el módulo fuente y copia el resultado en un fichero de salida con extensión (.PPO). Posteriormente y en capítulo aparte explicaremos el funcionamiento del preprocesador.

/Q Suprime la visualización de los números de línea durante la compilación.

/R[<fichero lib>] Indica al enlazador donde en que librería buscar las funciones y procedimientos no encontrados al compilar. Si sólo se especifica /R, las librerías por defecto son:

CLIPPER.LIB, EXTEND.LIB y DBFNTX.LIB.

/S Comprueba la sintaxis del programa fuente, sin generar el fichero objeto.

/T<vía> Indica un directorio distinto para los ficheros temporales generados durante la compilación.

/U[<fichero cabecera standard de usuario>] Indica el preprocesamiento de otro fichero de cabecera estándard, en lugar del STD.CH

/V Indica al compilador que asuma todas las referencias a nombres de variables declaradas o sin declarar como variables públicas y privadas.

/W Genera mensajes de advertencia para variables sin declarar o ambiguas.

/Z Elimina la evaluación abreviada para operadores lógicos, para aislar el código de versiones anteriores de CA-Clipper.

Resumiendo:

-----------

Como mínimo en la compilación es recomendable utilizar las siguientes opciones:

CLIPPER <programa> /N /W

De esta forma podemos tener funciones con el mismo nombre del fichero fuente, y tener controladas todas las variables.

Si tuviesemos que reducir el tamaño del (.OBJ), entonces aplicar la opción /L, y /S en la fase de depuración, para encon trar errores de sintaxis.

EL ENLAZADOR RTLINK

Enlaza los ficheros (.OBJ), con los de librería (.LIB) para crear ficheros ejecutables (.EXE) o preenlazados (.PLL).

Sintaxis:

---------

Se puede llamar de dos formas:

1) Formato libre (por defecto):

RTLINK [FILE <lista ficheros OBJ> [OUTPUT <fichero salida> [LIBRARY [lista ficheros librería>] [<lista opciones de enlace>]] | [@<fichero Script>]

2) De forma posicional, si lo indicamos en el AUTOEXEC.BAT -> SET RTLINKCMD=/POSITIONAL :

RTLINK [<lista ficheros OBJ>, [<fichero salida>], [<fichero map>], [<lista ficheros librería>] [<lista opciones de enlace>]] | [@<fichero Script>][;]

Argumentos de línea de mandato

<lista ficheros OBJ> Es la lista de los ficheros (.OBJ) a enlazar.

<fichero salida> Es el nombre del fichero .EXE a generar, sino se indica se toma por defecto, el nombre del primer fichero (.OBJ) de la línea de mandato.

<fichero map> Es el nombre de un fichero MAP a generar. Contiene información sobre direcciones de segmentos y símbolos en la memoria.

<lista ficheros librería> Es la lista de los ficheros de librería (.LIB) a enlazar con los (.OBJ).

<lista opciones de enlace> Son algunas de las especificaciones que puede recibir el enlazador.

<fichero Script> Es el nombre de un fichero de texto ASCII que contiene la lista de los ficheros (.OBJ) a enlazar.

Por ejemplo, en el anterior capítulo teníamos los siguientes fuentes que convertimos en (.OBJ) : FTR, FUNCION, ARTICULO, CLIENTES y FACTURA, para enlazarlos podríamos crear un fichero FTR.LNK, con lo siguiente:

FILE FTR FILE FUNCION FILE ARTICULO FILE CLIENTES FILE FACTURA

Y ejecutar luego: rtlink @ftr

Opciones del enlazador

/BATCH | NOBATCH Con BATCH impide que el enlazador le avise cuando

no encuentre los ficheros. La opción por defecto es

NOBATCH.

BEGINAREA

.

<sentencias>

.

ENDAREA Indica una area de overlays estáticos, permite anidación. (Más adelante veremos ejemplos).

/DEBUG Muestra un mensaje de identificación de overlays a medida que estos se cargan en la memoria durante la ejecución del programa.

/DEFAULTLIBRARYSEARCH/NODEFAULTLIBRARYS EARCH Con NODEFAULTLIBRARYSEARCH ignoramos los nombres de biblioteca incorporados por el compilador

. La opción por defecto es DEFAULTLIBRARYSEARCH.

/DYNAMIC[:<fichero OVL>] DYNAMIC [INTO <fichero OVL>] Hace que los módulos se sitúen en un overlay dinámico.

/EXCLUDE:<símbolo> EXCLUDE <lista símbolos> Excluye una serie de módulos en el modo de preenlace (.PLL).

/EXTDICTIONARY | /NOEXTDICTIONARY Con NOEXTDICTIONARY el enlazador no realiza búsquedas en el diccionario extendido (lista de localizaciones de símbolos y dependencias). La opción por defecto es EXTDICTIONARY.

/FREEFORMAT Es el modo de entrada libre, y es el utilizado por defecto. /HELP Muestra la lista de opciones del enlazador.

/IGNORECASE | /NOIGNORECASE Con NOIGNORECASE se hace distinción entre mayúsculas y minús- culas en los nombres de símbolos y segmentos. IGNORECASE es a opción por defecto.

/INCREMENTAL[:<espacio perdido>] | /NOINCREMENTAL Con INCREMENTAL hace que se enlazen solo los módulos que han sufrido cambios. NOINCREMENTAL es la opción por defecto.

/MAP[:<lista opciones MAP>] MAP[=<fichero MAP>][<lista opciones MAP>] Genera un fichero MAP con uno o varios informes sobre la sesión de enlace.

MODULE <lista nombres módulo> Desplaza los segmentos de los módulos especificados a la sección de overlays estáticos actual.

/PLL:<librería de preenlace> Se utiliza en modo de preenlace para especificar la librería preenlazada de la cúal depende el ejecutable.

/POSITIONAL Cambia el formato de entrada. Por defecto utilizamos el FREEFORMAT.

/PRELINK Cambia al modo de preenlazado generando un fichero (.PLL).

PRELOAD Hace que los overlays estáticos se carguen en memoria antes de comenzar la ejecución del programa. Normalmente solo se cargan las secciones residentes.

/REFER:<símbolo> REFER <lista símbolos> Se utiliza en el modo de preenlace, para que busque en todas las librerías especificadas el código asociado con los símbolos especificados.

/RESIDENT Carga todo el programa en memoria ignorando la creación automática de overlays dinámicos.

SECTION [= <nombre sección>] [INTO <fichero OVL>] Crea una sección de overlays estáticos.

/SILENT Suprime las indicaciones y respuestas del enlazador si invocamos un fichero script.

/STACK:<tamaño bytes> Especificamos una pila de programa. El tamaño máximo es hasta 65535 bytes.

/VERBOSE[:<nivel>] Muestra mensajes de estado durante el enlace, a distintos níveles.

EL DEPURADOR DE CA-CLIPPER (CLD.EXE)

Permite la depuración del código fuente mientras se está ejecutando el fichero (.EXE). Tiene que tener los fuentes del programa a depurar, y haberlo compilado con la opción /B.

Sintaxis:

---------

CLD [[/43 | /50 | /S][@<fichero Script<] <fichero EXE> [<lista argumentos>]]

Argumentos de la línea de mandato

---------------------------------

/43

Especifica el modo de 43 líneas para monitores EGA y VGA.

/50

Especifica el modo de 50 líneas para monitores VGA.

/S Divide la pantalla entre la aplicación y el depurador solo en monitores EGA y VGA.

<fichero Script> Es el nombre del fichero script, que contiene una serie de mandatos del depurador, en líneas separadas. La extensión por defecto es (.CLD).

<fichero EXE> Es el nombre del fichero ejecutable a depurar. Previamente se tendrá que haber compilado con la opción /B

<lista argumentos> Es la lista de argumentos para el fichero ejecutable.

Mandatos del Menú del Depurador

Al ser su funcionamiento dirigido por menús, su uso es fácil y no requiere muchas explicaciones, cabe recordar lo siguiente:

- El mandato ? o ?? le muestra el valor de una expresión (variable, operación aritmética, etc.)

- Puede ejcutar el programa de distintos modos:

automático, normal, paso a paso, por níveles, etc.

- Puede establecer puntos de ruptura para evaluar resultados,y acciones <tecla F9>.

- Puede visualizar ficheros <F6>, y el contenido de las variables.

Para desplazarse entre las ventanas de variables, fuentes, y comandos, utilice la tecla del tabulador.

MANTENIMIENTO DE PROGRAMAS CON RMAKE

Automatiza la compilación y enlazado de programas, comparando las fechas y horas de los ficheros relacionados entre sí, para ejecutar una serie de acciones según sea el caso.

Sintaxis:

---------

RMAKE [<lista ficheros MAKE>] [lista def macro>] [<lista opciones>]

Argumentos de la línea de mandato

---------------------------------

<lista ficheros MAKE> Es la lista de los ficheros MAKE a procesar. La extensión por defecto es (.RMK).

Por ejemplo, siguiendo con los ejemplos anteriores de los ficheros: FTR, FUNCION, ARTICULO, CLIENTES y FACTURA, el fichero MAKE resultante, FTR.RMK, quedaría así:

FTR.OBJ:

FUNCION.OBJ:

ARTICULO.OBJ:

FTR.PRG CLIPPER FTR

FUNCION.PRG CLIPPER FUNCION

ARTICULO.PRG CLIPPER ARTICULO

CLIENTES.OBJ:

FACTURA.OBJ:

CLIENTES.PRG CLIPPER CLIENTES

FACTURA.PRG CLIPPER FACTURA

FTR.EXE:

FTR.OBJ

FUNCION.OBJ

ARTICULO.OBJ\

CLIENTES.OBJ FACTURA.OBJ

<lista def macro> Es una lista de una o más definiciones de macro con el formato <nombre macro>=<valor>

<lista opciones> Lista de opciones de control de RMAKE.

Opciones de RMAKE

/B Muestra en pantalla información sobre la depuración.

/D<nombre macro>[:<valor>] Define una macro y un valor opcional. Si no se indica valor se toma un valor nulo.

/I Ignora los errores de ejecución.

/N Simula la ejecución del make.

/S Busca en los subdirectorios los ficheros make.

/U Activa el carácter # como indicador de comentarios y suprime su utilización como indicador de directivas.

/W Muestra en pantalla mensajes de advertencia.

/XS<nº símbolos> Establece el tamaño de la tabla interna de símbolos. El tamaño por defecto es de 500.

/XW<nº bytes> Establece el tamaño del espacio de trabajo interno. El tamaño por defecto es de 2048 bytes.

Comentarios

indicar al estilo del C: /*

del make de UNIX con (#), este último teniendo activada la opción /U.

*/

o //, o al estilo

Macros

Se definen de las siguientes formas:

<nombre macro>=<valor> $(<nombre macro>) <nombre macro> := $(<nombre macro>)

Existen también las macros MakePath que indican donde buscar y crear ficheros, su sintaxis es la siguiente:

makepath[.<extensión> = <vía>

Macros predefinidas

$* Se expande al nombre del fichero destino sin vía o extensión.

$@ Se expande al nombre del fichero destino con vía y extensión.

$** Se expande a toda la lista de nombres de ficheros de dependencia completos.

$< Se expande al nombre completo del primer fichero de la lista de ficheros de dependencia.

$? Se expande a una lista de dependencias que tienen una fecha y hora más recientes que el fichero destino.

Directivas de control del Make #! <acción> Ejecuta un mandato del DOS.

#if #else #end[if] Ejecuta las sentencias existentes entre las directivas según sea verdad o falto el resultado de las condiciones.

#ifdef <nombre macro> Comprueba la existéncia de un nombre de macro.

#ifndef <nombre macro> Comprueba que el nombre de la macro no exista.

#ifeq <palabra1> <palabra2> Comprueba que las palabras sean idénticas.

#iffile <fichero> Comprueba la existéncia de un fichero.

#include "<nombre fichero>"inserta y procesa el contenido del fichero antes de continuar con el fichero make actual.

#stderr "<texto>" Escribe el texto en el fichero o dispositivo de error estándard.

#stdout "<texto>"Escribe el texto en el fichero o dispositivo de salida estándard.

#undef <nombre macro> Suprime cualquier definición anterior del <nombre macro> especificado.

EL EDITOR DE PROGRAMAS: PE

Se trata de un editor básico, se incluyen los fuentes C:\CLIPPER5\SOURCE\PE, y en el proceso de instalación podemos indicar su compilación.

Sintaxis:

---------

PE [<nombre fichero>] Si se encuentra el fichero se carga para su edición, y sino crea uno de nuevo. La extensión por defecto es (.PRG).

Teclas

Acción

------

------

Flecha arriba, Ctrl-E Flecha abajo, Ctrl-X Flecha Izda., Ctrl-S Flecha dcha., Ctrl-D Ctrl-Flecha izda., Ctrl-A Ctrl-Flecha dcha., Ctrl-F Inicio Fin Ctrl-Inicio Ctrl-Fin

Línea arriba Línea abajo Carácter a la izquierda Carácter a la derecha Palabra a la izquierda Palabra a la derecha Inicio de línea Fin de línea Parte superior de la ventana Fin de la ventana

tecla

RePág AvPág Ctrl-RePág Ctrl-AvPág Intro Borrar Retroceso Tabulador Ctrl-Y Ctrl-T Alt-H, F1 Ctrl-W Alt-W Alt-O Alt-X, Esc Alt-F Alt-S Alt-A Alt-I, Ins

accion

Ventana anterior Ventana siguiente Inicio texto Final texto Nueva línea Borrar carácter Borrar carácter a la izda. Inserta tabuladores/espacios Borrar línea Borrar palabra a la derecha Ayuda Grabar y salir Grabar y continuar Nuevo nombre de fichero salida Salir Mostrar nombre fichero Buscar Buscar de nuevo Activa/desactiva modo inserción

Dado que no permite realizar operaciones con bloques, es mejor utilizar un editor profesional, sin embargo, puede ser útil para incroporarlo en nuestros programas.

UTILIDAD DE BASE DE DATOS: DBU

Se trata de una sencilla base de datos controlada por menús, utilizada para la creación y manipulación de bases de datos. Se incluyen los fuentes: C:\CLIPPER5\SOURCE\DBU

Sintaxis:

---------

DBU [/<cadena color>][<nombre fichero>] /e

Argumentos de línea de mandato

------------------------------

<cadena color> Permite indicar si queremos la visualización en color (/C) o en monocromo (/M). Si no lo indicamos se utiliza la función ISCOLOR() para comprobar el modo color.

<nombre fichero> Es el nombre de un fichero de vista (.WEW), estos son de uso nexclusivo de la DBU, o de un fichero de base de datos (.DBF).

/e Abre el fichero en modo exclusivo (solo puede utilizarlo un usuario, en red local).

Opciones de DBU

F1 - Ayuda

F2 - Abrir Permite la apertura de ficheros de base de datos (.DBF), índice (.NTX) y de vista (.WEW).

F3 - Crear Permite la creación y modificación de ficheros de base de datos e índices.

Estructura de las bases de datos

--------------------------------

Nombre de Campo Esta formado por 10 caracteres de longitud, debe de empezar con una letra y puede contener únicamente:

letras, números y el carácter de subrayado (_).

Tipos de Campos

Los tipos de campos permitidos son:

C - Carácter

D - Fecha

L - Lógico (.T. o .F.) M - Memo (texto)

N - Numérico

Ancho Campos

La longitud para los tipos de campo anteriores es:

C - Carácter, entre 1 y 1024, por defecto son 10.

D - Fecha, el ancho es fijo, 8.

L - Lógico, el ancho es fijo, 1. M - Memo, el ancho es fijo, 10.

N - Numérico, entre 1 y 19, por defecto es 10.

Decimales

Solo se utilizan en los campos numéricos e indican el nº de decimales que admiten estos. Por ejemplo, un campo que permita esto: 99.99, tendría un ancho de 5 (se contabiliza el punto decimal), y 2 decimales.

Para crear los ficheros índice, hemos de indicar el nombre de este y su clave de indexación.

F4 - Grabar Permite la grabación de una estructura de base de datos o de un fichero de vista.

F5 - Ver Permite visualizar una base de datos o un fichero de vista.

F6 - Utilidad Se incluyen diversas utilidades para manipular registros.

- Copiar, copia un fichero de base de datos en otro o en uno de texto.

- Añadir, añade registros al fichero activo desde otra base de datos o un fichero de texto.

- Cambiar, efectúa sustituciones en campos condicionales o globales. Solo un campo cada vez.

- Purgar, elimina de forma permanente, registros marcados para borrado.

- Vaciar, elimina todos los registros de la base de datos, pero manteniendo su estructura.

- Ejecutar, ejecuta un comando del DOS u otro programa en caso de disponer de suficiente memoria.

F7 - Mover Es un método rápido de desplazamiento dentro de una ventana de visualización. Podemos realizar búsquedas por los valores clave de los índices, ir a un determinado registro, localizar por un campo concreto y saltar determinado número de registros.

F8 - Establecer Permite establecer relaciones entre bases de datos y configu- rar una lista de ficheros y condiciones para definir una vista.

Esc - Salir

Notas: En lecciones posteriores construiremos un sistema de utilidad de base de datos parecido, con algunas de las opciones anteriores.

UTILIDAD DE INFORMES Y ETIQUETAS: RL

Para mantener la compatibilidad con dBase III+, CA- Clipper incorpora una utilidad de informes y etiquetas RL.EXE, que crean ficheros binarios de informes (.FRM) y de etiquetas (.LBL).

Se incluyen los fuentes: C:\CLIPPER5\SOURCE\RL

Sintaxis: RL

Y desde un programa:

Para imprimir informes:

USE <base de datos> INDEX <ficheros índice> NEW REPORT FROM <informe> TO PRINTER

Para imprimir etiquetas:

USE <base de datos> INDEX <ficheros índice> NEW LABEL FORM <etiqueta> TO PRINTER

Informes:

---------

Además del nombre, un informe tiene una serie de columnas, y cada columna tiene:

Contenido Es una expresión referida a un campo o variable.

Cabecera Es el título de la columna.

Formato Permite especificar la anchura a visualizar, si el campo es numérico los decimales a mostrar y si se ha de totalizar.

También se pueden indicar una serie de opciones en el informe,como:

Cabecera de Página Es el título de la página.

Anchura de Página Determina el ancho total de la página. El valor por defecto es 80.

Margen izquierdo Su valor se suma al de SET MARGIN. El valor por defecto es 8. El valor por defecto es 0.

Margen derecho No tiene utilidad, solo es para compatibilizarlo con dBase. El valor por defecto es 0.

Líneas por página Determina el total de líneas a imprimir. El valor por defecto es 58.

Doble espacio Determina si las líneas de detalle se imprimirán a doble espacio. El valor por defecto es N.

Salto de Página antes de imprimir El valor por defecto es S. Se puede anular indicando en el comando REPORT FROM, la cláusula NOEJECT.

Salto de Página después de imprimir El valor por defecto es N.

Página normal El valor por defecto es N. Si indicamos S, la cabecera de la página, el número y la fecha no se imprimem.

También pueden definirse grupos, dentro del informe, como por ejemplo, grupos de ventas por meses, y su composición es la siguiente:

Expresión de Grupo Indica la expresión clave de la agrupación.

Cabecera de Grupo Es el título del grupo.

Informe resumido El valor por defecto es N, informe detallado y S, para resumido.

Etiquetas

---------

Los ficheros de etiqueta tienen la extensión (.LBL), y las siguientes características:

Dimensiones:

Anchura horizontal de la etiqueta De 1 a 255 caracteres. El valor por defecto es 35.

Altura (líneas verticales) De 1 a 16 líneas. El valor por defecto es 5.

Transversal Indica las columnas de etiquetas por página, que puede ser de 1 a 255. El valor por defecto es 1.

Margen Izquierdo Su valor se añade al de SET MARGIN, y puede oscilar entre 0 a 255. El valor por defecto es 0.

Líneas entre etiquetas Determina el nº de líneas de separación entre etiquetas, dicho valor va de 0 a 255. El valor por defecto es una línea en blanco.

Espacio entre etiquetas (vertical) El valor por defecto es 0, en caso de que haya más de una etiqueta por columna, puede llegar hasta 255.

Observaciones Sirve para anotar una serie de comentarios como las medidas, la referencia del fabricante, etc.

Se incluyen una serie de formatos predefinidos que pueden escogerse con F3.

Contenido de la etiqueta:

Una vez indicadas las dimensiones, hemos de especificar el contenido de las líneas de la etiqueta. Podemos utilizar expresiones simples y compuestas, y dejar líneas en blanco:

NOMBRE DIRECCION CPOSTAL + " - " + alltrim( POBLACION )

Una vez, creado o modificado el formato podemos grabarlo con F10.

DOCUMENTACION INTERACTIVA: NG.

La Guía de CA-Clipper esta compuesta por una serie de guías Norton, accesibles mediante el Instant Access de Norton (NG.EXE), que queda residente en memoria y que podemos utilizar desde nuestro editor mismo o cualquier otro programa.

Se encuentra en: C:\NG

Sintaxis:

-

NG [<línea de mandatos>]

Argumentos de NG

<línea de mandato> Indica que cargemos NG en modo temporal, es decir, que permenezca en memoria hasta que termine la ejecución del programa que lo utiliza. Por ejemplo: ng edit programa.prg

Si no indicamos nada, actúa de modo residente (TSR).

Teclas de desplazamiento

Al estar dirigido por menús su funcionamiento es sencillo, aunque cabe recordar que se compone de varios níveles de ayuda y que desde el menú Options podemos cambiar de base de datos, de tecla clave de acceso, desintalarlo, etc.

Tecla

---------

Acción

-----------------------------------------

Shift-F1

Activar NG.

F1

Ayuda.

F9

Intercambio media pantalla/pantalla

F10,

completa. Shift-F1 Salir.

Esc

Subir de nível o salir, depende de

Intro

la situación. Bajar de nível, seleccionar elemento

- (Bloq. Num) + (Bloq. Num) Ctrl-S Flecha arriba

o ir a un elemento relacionado (See Also). Muestra elemento anterior. Muestra siguiente elemento. Continúa la búsqueda indicada. Va al elemento anterior o desplaza

Flecha abajo

ventana arriba Va al elemento siguiente o desplaza

Flecha izda. Flecha dcha. RePág AvPág Inicio Fin

ventana abajo Va al elemento anterior. Va al siguiente elemento. Vamos a la pantalla anterior. Vamos a la pantalla siguiente. Va al primer elemento. Va al último elemento .

NOTA

Tenga presenta que en la parte derecha de la lista de comandos y funciones aparecen los siguientes caracteres que indican:

Û - Elemento nuevo õ - Cambiado o actualizado * - Obsoletos

Por lo tanto los que están marcados como obsoletos procure no utilizarlos, ya que en versiones posteriores pueden desaparecer.

NOTACION HUNGARA

Notas: Adaptaciones realizadas a partir de las indicaciones y explicaciones efectuadas por los compañeros de GRUPO EIDOS, y en especial de Antonio Linares. ¡ Muchas gracias !

Una definición de notación sería la representación de alguna cosa mediante señales, caracteres, etc.

Cuando uno escribe un programa utiliza su propia notación, ya que miéntras uno se entienda ya es suficiente, pero y si se trabaja en grupo o se intercambian funciones con otros pro- gramadores, entonces sucede lo de la Torre de Babel.

Como los programadores de Microsoft Corporation se encontraban en este caso, uno de ellos, de origen húngaro (de ahí viene el apodo de la notación), especificó una serie de técnicas para la programación en C.

Como la idea es genial, se trasladó a Clipper, para unificar la sintaxis utilizada programación, y así poder entender el código de otros programadores.

Normas adaptadas de la Notación Húngara para Clipper

----------------------------------------------------

1) Los nombres de las variables han de ir precedidas por un identificador en minúsculas de su tipo. Es decir, a partir de la letra o letras iniciales de una variables podemos saber el tipo al cual pertenece (carácter, número, fecha, etc.)

c

Carácter o memo

 

n

Numérico

l

Lógico

d

Fecha (date, en inglés)

 

o

Objeto

b

Bloque de código (codeblock)

 

x

Indeterminado (no conocemos su tipo)

a

Array

ac

Array de cadenas

a

Array de

(otros elementos: an, al,

)

En la programación orientada al objeto (OOPS), para diferenciar a que clases pertenecen los objetos, utilizaremos identificadores de 3 letras consonantes.

Por ejemplo: Objeto de la clase Window -> wndMain

2) Utilización de la técnica WordMixing (mezcla de palabras) para diferenciar las distintas partes de un nombre.

Por ejemplo: cEstoEsUnEjemplo

No utilizar subguiones "_" como separadores.

3) Es recomendable aplicar las reglas anteriores para los nombres de las funciones:

SetColor, FuncionUsuario, cFuncionUsuario, etc.

4) Aplicar también, las reglas anteriores para los nombres de los campos. Aunque, yo particularmente utilizó aqui, el subguión como separador de campo, y los nombres de los ficheros y los campos los pongo en mayúsculas para que destaquen dentro del código y poderlos localizar fácilmente.

5) Todas las palabras que cambie el preprocesador se escribirán en mayúsculas. Para saber que palabras cambia o no el preprocesador, eche un vistazo al fichero de cabecera: std.ch (directorio \include).

Por ejemplo: SAY y GET, se pasan a mayúsculas. En cambio: if y endif, no porque no sufren variación.

6) Al declarar las directivas con el preprocesador (#define),utilizar un identificador de 2 a 3 letras, un subguión como separador, el identificador de tipo, y a continuación el nombre del identificador.

Por ejemplo: #define KEY_nESC

27

7) A partir de las reglas anteriores, y para clasificar las funciones podemos aplicar los siguientes varemos:

- Tipo, categoria y Acción.

Ejemplo:

cScrShadow()

varemos: - Tipo, categoria y Acción. Ejemplo: cScrShadow() Tipo Acción (sombrea area pantalla) Categoría (Función de
varemos: - Tipo, categoria y Acción. Ejemplo: cScrShadow() Tipo Acción (sombrea area pantalla) Categoría (Función de

Tipo

- Tipo, categoria y Acción. Ejemplo: cScrShadow() Tipo Acción (sombrea area pantalla) Categoría (Función de

Acción (sombrea area pantalla)

Categoría (Función de pantalla->Screen)

Devuelve un valor de tipo c

INTRODUCCION A LA PROGRAMACION

¿ Que es la programación ?

Es la acción de definir una serie de procesos (diseño, escritura y pruebas de programas) para resolver un problema.

Un programa es el conjunto de instrucciones que se le dan al ordenador para resolver un problema o tarea determinada.

Algoritmo

---------

Un algoritmo es un procedimiento paso a paso para resolver un problema. Los algoritmos han de ser independientes tanto del lenguaje de programación como del ordenador en que serán ejecutados, han de ser precisos y finitos (han de finalizar).

Pasos para la resolución de un problema:

1) Análisis del problema y diseño del algoritmo. 2) Fase de codificación: expresar el algoritmo mediante un lenguaje de programación.

3) Ejecución, validación y depuración del programa.

Lenguajes de Programación

-------------------------

Es el lenguaje utilizado para la escritura de los programas.

Clasificación de los lenguajes:

A) Lenguajes de bajo nivel y alto nivel

Los lenguajes de bajo nivel tienen una forma de operar más cercana a la máquina, mediante instrucciones nemotécnicas, quedando muchas veces su uso limitado a máquinas y modelos concretos, en cambio los de alto nivel tienen una sintaxis más cercana a la lengua humana, y son transportables entre entornos.

B) Interpretes y compiladores

Una vez escrito el programa (código fuente) este ha de ser comprendido por la máquina, para eso podemos utilizar un interprete que traduce y ejecuta línea a línea un programa fuente, o un compilador que genera un programa objeto ejecutable directamente por el ordenador, siendo este un método mucho más rápido.

Fases de la compilación

-----------------------

Con un editor escribimos el o los programas fuentes (.PRG), con el compilador CLIPPER, generamos un programa objeto (.OBJ) que linkado con las correspondientes librerías (.LIB), obtenemos el programa ejecutable (.EXE).

PROGRAMA FUENTE (*.PRG)

COMPILADOR

CLIPPER

(traductor)

PROGRAMA OBJE (*.OBJ)

LINKADOR RTLINK (*.OBJ + *.LIB)

PROG.EJECUTABLE

(*.EXE)

Análisis y resolución de problemas

----------------------------------

La resolución de problemas mediante el ordenador se resuelve mediante 3 pasos:

RESOLUCION DE PROBLEMAS

DISEÑO

DEL

ALGORITMO

ANALISIS

DEL

PROBLEMA

RESOLUCION DEL PROBLEMA CON EL ORDENADOR

Análisis del problema

---------------------

Para una solución eficaz del problema, este ha de estar bien definido, y las especificaciones de entrada/salida han de estar bien detalladas.

ANALISIS DEL PROBLEMA

han de estar bien detalladas. ANALISIS DEL PROBLEMA ESPECIFICACIONES DE ENTRADA DEFINICION DEL PROBLEMA

ESPECIFICACIONES DE ENTRADA

DEFINICION DEL PROBLEMA

ESPECIFICACIONES DE SALIDA

DISEÑO DE ALGORITMOS ====================

El ordenador por si solo no es capaz de resolver un problema, se le ha de especificar los sucesivos pasos a realizar, es lo que denominamos como algoritmo.

Un algoritmo recibe unos datos de entrada y devuelve unos datos de salida.

Los problemas complejos se han de dividir en otros de más simples y así sucesivamente, es lo que se denomina diseño descendente (top-down design).

Una vez realizado un primer acercamiento al problema, este se ha de ampliar, lo que denominamos como refinamiento del algoritmo (stepwise refinement).

DISEÑO DE UN ALGORITMO DISEÑO REFINAMIENTO POR PASOS HTAS. PROG.: DESCENDENTE - DIAGRAMA FLUJO -
DISEÑO
DE UN
ALGORITMO
DISEÑO
REFINAMIENTO
POR PASOS
HTAS. PROG.:
DESCENDENTE
- DIAGRAMA FLUJO
- DIAGRAMA N-S
- PSEUDOCODIGO

Supongamos que tengamos que crear un algoritmo para añadir registros a un fichero de clientes. Haríamos lo siguiente:

1) Abrir fichero de clientes. 2) Añadir ficha (registro) en blanco. 3) Rellenar datos. 4) Cerrar fichero de clientes.

Esto sería una primera aproximación, pero se tendría que refinar el algoritmo y tener en cuenta lo siguiente:

A) Si no existe el fichero, crearlo.

B) Si queremos grabar o no el registro.

Podemos representar el algoritmo anterior de las siguientes formas

- DIAGRAMA DE FLUJO (FLOWCHART)

- DIAGRAMA DE NASSI-SCHNEIDERMAN (N-S)

- PSEUDOCODIGO

Normalmente, y más en los lenguajes estructurados como Clipper,su uso no es necesario, salvo en algoritmos muy complicados. Yo particularmente uso el pseudocódigo, pero cada uno puede utilizar el que le sea más práctico.

Diagrama de flujo (flowchart) El diagrama de flujo o flowchart es una de las técnica de re presentación de algoritmos más antigua, y consiste en representar mediante símbolos las operaciones a realizar.

Por ejemplo: el inicio y el fin del algoritmo se representan con un símbolo elíptico, las entradas y salidas con un paralelogramo, las decisiones con un rombo, los procesos con un rectangulo, etc. Notas:

En las librerías o tiendas especializadas podrá encontrar, si es de su interés, plantillas con dichos símbolos.

Diagrama de Nassi-Schneiderman (N-S) El diagrama de Nassi-Schneiderman es como un diagrama de flujo pero con la omisión de las flechas de conexión, quedando las cajas de las acciones, pegadas unas a otras.

Ejemplo: El algoritmo anterior quedaría así:

Algoritmo de Altas de Clientes

Si no existe el fichero de Clientes lo creamos

Abrir el fichero de clientes

Añadir ficha vacía

Rellenar datos

Al llegar al final grabar ficha

Si pulsamos la tecla <Esc> borrar ficha

Cerrar fichero

Pseudocódigo

------------

El pseudocódigo es un lenguaje de especificación de algoritmos,de uso fácil y sintaxis similar al lenguaje de programación a utilizar, que permite al programador concentrarse en las estructuras de control, y olvidarse de la sintaxis del lenguaje a utilizar.

Ejemplo: El algoritmo anterior quedaría así:

inicio

{Algoritmo de Altas de Clientes} SI no existe el fichero CLIENTES CREAR fichero CLIENTES FIN-SI USAR CLIENTES.DBF AÑADIR ENTRAR NOMBRE LERE NOMBRE SI pulsamos la tecla ESC BORRAR registro actual FIN-SI CERRAR fichero CLIENTES fin

RESOLUCION DE PROBLEMAS

Una vez diseñado y representado el algoritmo, se han de realizar los siguientes pasos:

Codificación

------------

La codificación consiste en convertir el algoritmo a un lenguaje de programación mediante un editor de textos, es decir,escribir un programa fuente.

Compilación, ejecución y comprobación

-------------------------------------

Una vez escrito los fuentes, los hemos de compilar, linkarlos con las librerías que utilicemos, y comprobar su funcionamiento.

Depuración La depuración es el proceso de localizar, corregir y eliminar los errores (bugs) que podamos encontrar.

Los errores pueden ser de tres tipos:

1) Errores de sintaxis: que el propio compilador detecta. Para solventarlos hemos de recurrir a los manuales para comprobar la sintaxis correcta del comando o función.

2) Errores de ejecución: se producen cuando el ordenador comprende una instrucción pero no la puede ejecutar. Puede ser

debido a que nos hemos olvidado de indicar algún parámetro de una función, o concatemos variables incompatibles entre ellas (cadena + número, tendría que ser: cadena + str( número) ), o realicemos asignaciones incorrectas, etc.

3) Errores lógicos: estos son debidos al programador,

y pueden resultar dificiles de localizar.

Verificación La verificación consiste en examinar lo que hace un programa,como lo hace y las causas por las que falla.

Optimización La optimización consiste en que una vez el programa funcione correctamente, se perfeccione para que funcione mejor.

Documentación

La documentación del programa, es una de las tareas más tediosas, y puede que más importante, ya que

despues nos será de utilidad para el desarrollo, mejora

y modificación del programa en cuestión. Hemos de

especificar el cometido de cada función, los parámetros que recibe y lo que devuelve, así como las variables utilizadas, y los puntos claves de cada función o proceso.

Mantenimiento El mantenimiento del programa consiste en la actualización continua del programa.

TECNICAS DE PROGRAMACION

Antes la programación se limitaba a programas de pequeña y mediana complejidad, pero como cada vez eran más complejos surgieron las ténicas de programación modular y estructurada,y no hace muchos años la programación orientada al objeto.

Programación modular

--------------------

Los programas complejos se descomponen en módulos (partes independientes), que estos a su vez se analizan, codifican y se verifican por separado. Su codificación se realiza mediante programación estructurada u orientada al objeto.

Normalmente se diseñan en equipo, unos programadores se dedican al diseño de funciones, y otros al desarrollo de la aplicación, bajo la supervisión de un coordinador, para que todos los modulos tengan el mismo interface de usuario.

Programación estructurada

-------------------------

La programación estructurada consiste en descomponer un determinado problema en una serie de niveles o pasos (diseño descendente o top-down), y se compone de una serie de estruc- turas básicas:

Estructuras secuenciales Estructuras selectivas Estructuras repetitvas

Como habréis podido observar un programa, función y

procedimiento tiene un inicio y un fin, estas compuestos

por unas estructuras selectivas (DO CASE, IF

unas estructuras repetitivas (FOR

WHILE, etc.)

) y por

NEXT,

Programación Orientada al Objeto (OOPS) La programación orientada al objeto, es un tipo de programación más cercana al razonamiento humano; el mundo esta formado por objetos, y estos tienen unas características o propiedades, y sobre ellos podemos ejecutar acciones determinadas.

La OOPS surge como una solución a la programación de grandes programas, y para solventar el mantenimiento de dichas aplicaciones, ya que en la programación estructura el más mínimo cambio supone la modificación de muchas funciones relacionadas, en cambio con la OOPS solo es cuestión de añadir/modificar métodos de una clase o mejor, crear una nueva clase a partir de otra.

Para que sea más fácil comprender lo anterior, lo compararemos con el siguiente caso real:

"Un fabricante de coches a tardado 5 años en diseñar y fabricar el modelo XYZ, pero dadas las exigencias y evolución del mercado se ve con la obligación de incorporar nuevas caracteristicas, pero no puede estar 5 años más en diseñar nuevamente un nuevo modelo, por lo que coge todos los objetos que puede del modelo XYZ, y añade otros, teniendo un nuevo modelo, el XYZ+, en un tiempo record." Esta sería la sintésis de la OOPS.

COMPONENTES DEL LENGUAJE: COMENTARIOS

En Clipper Summer'87 utilizabamos para los comentarios de una línea el asterisco (*), y para situar un comentario al final de la línea utilizabamos el símbolo &&. Ahora en CA-Clipper 5,podemos utilizar además los símbolos de comentario del lenguaje C, es decir:

- Para comentarios de varias líneas o bloques:

/* Comentarios

*/

- Para los comentarios de una línea:

* Comentario // Comentario

- Para los comentarios a final de línea:

<sentencia>

<sentencia>

&& Comentario // Comentario

--------------------------------------------------------------

COMPONENTES DEL LENGUAJE: VARIABLES

Las variables sirven para almacenar valores, y tienen un tiempo de vida y ámbito de visibilidad determinados, y un nombre. Cuando llamamos a dicho nombre se nos devuelve el valor que contiene.

Declaración de variables

Declarar una variable es darle un nombre a esta, y podemos hacerlo de las siguientes formas:

A) Anteponiendo las sentencias: STATIC, LOCAL, MEMVAR,PUBLIC, PRIVATE, y/o FIELD.

B) Como parámetros de una sentencia FUNCTION y/o PROCEDURE.

Aunque la declaración es opcional en las privadas, Notas:

Con la opción /W del compilador podemos comprobar si nos hemos olvidado de declarar alguna variable. Y con /V forzamos a que las variables no declaradas o ambiguas sean precedidas por el calificador MEMVAR.

Ambito de una declaración

El ámbito de una declaración se determina según la parte del programa donde aplicamos dicha declaración.

Un programa se divide en bloques de código, normalmente estos bloques son PROCEDIMIENTOS o FUNCIONES, y las variables declaradas en ellos, quedan limitadas a estos a excepción de STATIC,FIELD y MEMVAR, si se declaran antes de las sentencias PROCEDURE o FUNCTION.

Referencias a Variables Las variables se referencian por su nombre. En el caso de que tenga variables distintas con el mismo nombre puede utilizar el operador alias (->) para distinguirlas:

<alias> -> <nombre>

FIELD

MEMVAR -> <nombre>

-> <nombre>

Variables Locales

- Se declaran anteponiendo la sentencia LOCAL.

- Pueden crearse e inicializarse a la vez.

- Se crean automáticamente cada vez que se ejecuta el bloque de código donde están.

- Su tiempo de vida es el tiempo de duración del procedimiento o función, y su visibilidad se ciñe al procedimiento o función en cuestión.

Variables Estáticas

-------------------

- Se declaran anteponiendo la sentencia STATIC.

- Es necesario inicializarlas (asignarles un valor) al crearlas, ya que por defecto toman el valor NIL, y puede provocar errores, sobretodo si lo utilizamos como contador.

- Se crean automáticamente antes de la ejecución del bloque de código donde están.

- Su ámbito de visibilidad depende de donde fueron

creadas, si lo fueron en el programa principal (MAIN) su ámbito es general, y si se crearón dentro de un procedimiento o función, su ámbito se limita a dicho procedimiento o función.

- Su tiempo de vida es todo el programa, existe y mantiene sus valores mientras dure el programa.

Ejemplo: STATIC nContador := 0

Variables Privadas

- Se declaran anteponiendo la sentencia PRIVATE o PARAMETER (en los procedimientos), o durante la compilación con MEMVAR.

- Pueden crearse e inicializarse a la vez.

- Pueden liberarse con la sentencia RELEASE (elimina variables de memoria).

- Su ámbito de visibilidad se ciñe al procedimiento donde se invoca y a los llamados por este.

- Su tiempo de vida es todo el programa, hasta que no la liberemos con RELEASE.

Variables Públicas

------------------

- Se declaran anteponiendo la sentencia PUBLIC, o durante la compilación con MEMVAR.

- Pueden crearse e inicializarse a la vez.

- Pueden liberarse con la sentencia RELEASE.

- Su ámbito de visibilidad y tiempo de vida es todo el programa, a no ser que la liberemos con RELEASE.

Ejemplo: PUBLIC nContador := 0

Variables de Campo

------------------

- Se declaran anteponiendo la sentencia FIELD, en realidad son sinónimos de campos de bases de datos, y su uso va ligado con el manejo de los ficheros.

- Su valor depende del valor del registro activo en dicho momento.

- Su ámbito de visibilidad y tiempo de vida, van desde l la apertura del fichero a la duración del programa.

Ejemplo: FIELD->NOMBRE

Notas:

Entre las variables PUBLICAS y PRIVADAS, unas pueden ocultar a las otras, o auto-ocultarse declarandose con el mismo nombre en un procedimiento inferior. Aconsejo no utilizar este sistema, a no ser que sea estrictamente necesario, ya que puede dar lugar a confusiones. Es mejor que todas las variables tengan nombres distintos.

COMPONENTES DEL LENGUAJE: EXPRESIONES

Una expresión en un lenguaje humano equivaldría a una palabra o frase, y en un lenguaje de programación una expresión esta equivale a un elemento o combinación de estos (variables, campos, etc.) con operadores, etc.

Y los elementos que componen el lenguaje de programación CA-Clipper son:

* Variables

* Operadores

* Arrays o matrices

* CodeBlocks o bloques de código

* Objetos y mensajes

* Funciones y procedimientos

* Comandos xBase (en realidad son funciones, pero

ocultas con la ayuda del preprocesador. Ver ficheros.CH)

COMPONENTES DEL LENGUAJE: TIPOS DE DATOS

En el tema anterior vimos que las expresiones estan formadas por una serie de elementos, estos pueden constituir por si solos un tipo de datos (arrays y CodeBlocks), o un elemento puede ser de distintos tipos (como las variables).

Tipos de Datos

--------------

* Arrays o matrices

* Caracteres

* CodeBlocks o bloques de código

* Numéricos

* Fechas

* Lógicos

* Memo

* NIL

Arrays o matrices

-----------------

Un array es un conjunto de variables de memoria, con un nombre común, y con uno o unos subíndices que los identifican.

Los arrays pueden ser monodimensionales o multidimensionales (varias dimensiones o arrays anidados). Cualquiera de ellos puede tener los elementos de varios tipos (carácter, numérico, fecha, etc.), y tener distintos anchos.

Para comprender mejor lo que es un array de varias dimensiones, maginarlo como una tabla, es decir, como un TBrowse, donde cada FILA es un REGISTRO, y cada COLUMNA es un CAMPO o DIMENSION.

Caracteres

----------

Los datos de tipo carácter son los que se manipulan como cadenas de longitud fija, y comprenden los caracteres ASCII imprimibles, es decir, desde el Chr( 32 ) al Chr( 126 ), y los caracteres gráficos del ASCII extendido, del Chr( 128 ) al Chr( 255 ) , y el carácter nulo Chr( 0 ).

Las cadenas válidas pueden estar formadas por 0 o más caracteres, hasta un máximo de 65535, y han de ir entre un par de delimitadores ( 'cadena', "cadena" ). Para indicar una cadena nula, se indica con solo un par de limitadores ( "" o [] ).

Notas: El delimitador más usado es "" .

CodeBlocks o bloques de código

------------------------------

Un CodeBlock, como su nombre indica es un bloque de código, es decir, forma un conjunto de código, y su comportamiento es parecido al de una función, y se puede asignar tanto a variables como a arrays. Resumiendo este tipo de dato es una mezcla de funciones y variables.

Su funcionamiento es similar al de las macros (&), pero a diferencia de estas que se compilan durante la ejecución, los CodeBlocks lo hacen durante la compilación junto al resto del programa, por lo que son más rápidas.

Numéricos

---------

Los tipos de datos numéricos son los que se utilizan para manipularse matemáticamente ( +, -, *, /, etc.), y estan formados por los dígitos ( 0 al 9 ), la coma como separador de decimales y los caracteres + y - para indicar el signo del número.

Fechas

------

Los datos de tipo fecha identifican las fechas del calendario. Sus caracteres válidos son los dígitos del 0 al 9, y el carácter separador indicado por SET DATE.

Lógicos

-------

El tipo de datos lógico identifica elementos de naturaleza Booleana, es decir, identifica valores como verdadero/falso, sí/no, etc., y comprende los siguientes caracteres válidos: Y, T, t, N, n, F y f.

Memo

---

Los tipos de datos memo, representan caracteres de longitud variable, sólo pueden existir como campos de bases de datos, y se almacenan en ficheros aparte de extensión (.dbt). Se manejan en bloques de 512 bytes, y su limitación es idéntica a la de las cadenas, 65535 bytes.

NIL

---

NIL es un nuevo tipo de dato que permite manipular variables no inicializadas sin generar errores de ejecución.

COMPONENTES DEL LENGUAJE: OPERADORES

Los operadores son las unidades básicas de construcción de bloques.

Clasificación según los argumentos que necesita

Dentro los distintos tipos de operadores cabe distinguir los que reciben un argumento, unarios ( ! lSalir, nCuenta++, etc.), o los que reciben dos, binarios (2 + 2, cVar1 + cVar2,etc.).

Operadores de Cadenas

Símbolo Operación

+ Concatenar (deja espacios intermedios intactos)

- Concatenar (elimina espacios intermedios)

Operadores de Fecha

Símbolo Operación

+ Suma un número de días a una fecha

- Resta un nº de días de una fecha, o resta dos fechas

Operadores Matemáticos

Símbolo Operación

+

Suma o unario positivo

-

Resta o unario negativo

*

Multiplicación

/

División

%

Resto de una división

** o ASCII(94) Exponenciación

Operadores Relacionales

Símbolo Operación

< Menor que

> Mayor que

= Igual que

== Exactamente igual para cadenas. Igual para el resto.

<> # != Desigual Menor o igual que Mayor o igual que

<=

>=

$ Esta contenido en (por ejemplo en cadenas)

Operadores Lógicos

Símbolo Operación

.AND. Conjunción lógica

.OR.

Disyunción inclusiva lógica

.NOT. ! Negación lógica

( y ) ( o ) (no )

Tabla de verdad de los operadores .AND., .OR. y .NOT.

Operando 1 Operando 2

----------

----------

Operando 1 Operando 1

.AND.

.OR.

.NOT.

Operando 2 Operando 2 Operando 1

----------

----------

----------

.t.

.t.

.t.

.t.

.f.

.t.

.f.

.f.

.t.

.f.

.f.

.t.

.f.

.t.

.t.

.f.

.f.

.f.

.f.

.t.

Operadores de Asignación de Variables

Símbolo Operación

=

:=

+=

-=

*=

Asignación (todos los tipos de datos) Asignación en línea (todos los tipos de datos) Suma (o concatenación) y asignación en línea(C,D,M,N) Resta (o concatenación) y asignación en línea (idem) Multiplicación y asignación en línea (numéricos)

Resta (o concatenación) y asignación en línea (idem) Multiplicación y asignación en línea (numéricos)
Resta (o concatenación) y asignación en línea (idem) Multiplicación y asignación en línea (numéricos)
Resta (o concatenación) y asignación en línea (idem) Multiplicación y asignación en línea (numéricos)
Resta (o concatenación) y asignación en línea (idem) Multiplicación y asignación en línea (numéricos)

/=

**= ASCII(94)= Exponenciación y asignación en línea (nºs)

%=

División y asignación en línea (numéricos)

Resto y asignación en línea (numéricos)

La asignación en línea permite declarar e inicializar variables a la vez:

LOCAL nNumero := 10

Así mismo, podemos indicar un mismo valor para distintas variables de la siguiente forma:

LOCAL nVar1 := nVar2 := 10

La asignación compuesta de los operadores se resuelve así:

Operador

Ejemplo

Definició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 )

**= ASCII(94)= a **= b

a := ( a ** b )

Operadores de Incremento y Decremento

Símbolo

Operación

------------

++

---------------------------------------------- Incremento como prefijo o sufijo (pre/postincremento)

--

Decremento como prefijo o sufijo (pre/postdecremento)

Ambos son operadores unarios y puede indicador como prefijo ( ++nValor ) o como sufijo ( nValor++ ), la diferencia estriba en que cuando actua como prefijo, la variable primero se incrementa/decrementa y luego se asigna, y como sufijo, primero se asigna y luego se incrementa/decrementa su valor.

Ejemplo:

nValorInicial := 1

nValorFinal := --nValorInicial

nValorInicial := 1 nValorFinal := nValorInicial-

-

?

nValorInicial // 0

? nValorInicial

// 1

?

nValorFinal

// 0

? nValorFinal

// 0

Símbolo

Operadores Especiales Operación

-------

()

-------------------------------------------- Función o agrupamiento de operaciones

[]

( a + b ) Elemento de un array o matriz

{}

Definición de array

->

Identificador de alias campos, variables

&

Compilar y evaluar (macros)

@

Pasar por referencia(argumentos de funciones y proc.)

PRIORIDAD DE LOS OPERADORES Al evaluar expresiones con operaciones existen una

serie de reglas para evaluarlas correctamente. Una de ellas es la evaluación de izquierda a derecha para el mismo nivel de prioridad, que es el siguiente:

Prioridad entre categorias

1. Paréntesis ( ) - Modifica el orden de evaluación.

2. Preincremento y Predecremento (++nValor, --nValor)

3. Operadores Matemáticos

3.1. Unarios positivos y negativos ( +, - )

3.2. Exponenciación ( **, ASCII(94) )

3.3. Multiplicación, división y resto ( *, /, % )

3.4. Suma y resta ( +, - )

4. Operadores Relacionales (todos tienen el mismo nivel)

5. Operadores Lógicos

5.1. Negación Lógica (.NOT., ! )

5.2. Conjunción Lógica ( .AND. )

5.3. Disyunción inclusiva lógica ( .OR. )

6. Asignación (todas tienen el mismo nivel)

COMPONENTES DEL LENGUAJE: OPERADOR &

El operador de macro (&), es un operador especial que permite compilar expresiones, y sustituir identificadores por cadenas.

Sintaxis

--------

Uso como variable de macro: &<varMacro>. El punto (.), es el terminador de la macro. Ejemplo: cFichero := "CLIENTES.DBF" USE &cFichero.

Uso como macroexpansión:

Ejemplo: ? &(INDEXKEY(0))

&(<macroExp>)

Notas: Más adelante en el desarrollo de funciones, sobre todo de propósito general, veremos su funcionamiento.

COMPONENTES DEL LENGUAJE:PREPROCESADOR

El preprocesador, realiza una opción de preproceso antes de procesar el código Clipper. El preprocesador examina el código fuente en busca de directivas (identificadores o directrices del preprocesador), que después traduce a código fuente normal, antes de compilar.

Directivas

#command

#define

#error

#ifdef

#ifndef

#include

#stdout

#translate

#undef

#xcommand

#xtranslate

Directiva #define

-----------------

Define un identificador, una constante declarada o pseudofunción.

Sintaxis:

#define <identificador> #define <constante> <salida> #define <funcion>(<parámetros>) <expresión> Ejemplos:

A)

#define DEMO

if DEMO

B)

#define ESCAPE 27

if nTecla = ESCAPE

endif

endif

Notas:

C)

#define SUMA(a,b) a+b

?

SUMA(5,3)

- Las asignaciones hechas con #define sólo son válidas para el fichero que las contiene.

- Al utilizarlas hemos de hacerlo de forma idéntica a la de la definición.

Directiva #include

------------------

Incluye un fichero en el módulo fuente actual, que puede ser un fichero de cabecera (.ch) u otro fichero fuente (.prg).

Sintaxis: #include "<Fichero.prg>" #include "<Fichero.ch>"

Notas:

Los ficheros (.ch) se han de incluir al principio del programa y los ficheros (.prg) al final.

Directivas #command y #translate

--------------------------------

Definen mandatos y pseudofunciones creados por el usuario o una directiva de traducción. La diferencia entre #command y #translate esa, en que esta última sirve para los casos en que dichos mandatos y pseudofunciones formen parte de otras expresiones.

Sintaxis:

#command <patrón entrada> => <patrón salida> #translate <patrón entrada> => <patrón salida>

Ejemplos:

A)

#command DELETE => dbdelete() El comando DELETE, siempre va aparte y no forma parte de ninguna expresión, por lo que se utiliza #command para su traducción.

B)

#translate ISDATE( <v1> ) => (valtype( <v1> ) == "D" ) En este caso utilizamos la directiva #translate ya que ISDATE() tambien puede formar parte de una expresión, como por ejemplo:if IsDate( dFecha )

Notas: Estas directivas se reemplazan con sólo coincidir las cuatro primeros caracteres.

Directivas #xcommand y #xtranslate

Realizan las mismas funciones que #command y #translate, pero no admiten abreviaturas.

#xcommand <patrón entrada> => <patrón salida> #xtranslate <patrón entrada> => <patrón salida>

Ejemplo:

Suponga que utilizamos el preprocesador para evitar la complejidad de la sintaxis OOPS:

#xcommand ACTIVATE WINDOW <oWnd> => <oWnd>:Display()

Si utilizamos además un ACTIVATE MENU, ACTIVATE MOUSE, etc., tendríamos problemas al utilizar #command que reconoce las abreviaciones.

Directiva #ifdef

----------------

Compila un bloque de código, si se ha definido un identifi- cador. Es de utilidad para la realización de versiones DEMO.

Sintaxis:

#ifdef <identificador> <instrucciones> [#else] <instrucciones> [#endif]

Directiva #ifndef

-----------------

Ejemplo:

#ifdef DEMO // Instrucciones #else // Instrucciones #endif

Tiene la misma aplicación y sintaxis que #ifdef, pero para cuando el identificador no esta definido.

Sintaxis:

#ifndef <identificador> <instrucciones> [#else] <instrucciones> [#endif]

Directiva #undef

---------------

Ejemplo:

#ifndef DEMO // Instrucciones

#else // Instrucciones #endif

Elimina una definición realizada con #define.

Sintaxis:

#undef <identificador>

Ejemplo:

#undef ESCAPE

Directivas #error y #stdout

---------------------------

Indicarán el mensaje que aparecerá cuando se produzca un error de compilación.

Sintaxis:

#error [<mensaje>] #stdout [<mensaje>]

COMPONENTES DEL LENGUAJE: ARRAYS

Un array es un conjunto de variables de memoria, con un nombre común, y con uno o unos subíndices que los identifican. Cada valor del array se denomina elemento, y el número máximo de elementos de un array es de 4096.

Los arrays pueden ser monodimensionales o multidimensionales (varias dimensiones o arrays anidados). Cualquiera de ellos puede tener los elementos de varios tipos (carácter, numérico, etc.), incluso puede tener otros arrays o CodeBlocks, excepto los de tipo Memo, que sólo pueden aplicarse a campos.

Declaración de arrays

---------------------

Al crear las matrices podemos indicar su ámbito anteponiendo al identificador las sentecnias: PRIVATE, PUBLIC, LOCAL y STATIC.

Sintaxis:

<identificador>[

<identificador>[

Notas:

<nElementos1>,

<nElementos1> ]

<nElementos2>,

]

[ <nElementos2> ]

Excepto la primera dimensión, todas las demás son opcionales.También podemos utilizar la función ARRAY() para declarar matrices.

Ejemplos:

LOCAL acMatriz[12][4] es lo mismo que, LOCAL acMatriz := Array( 12, 4 )

Declaración y asignación:

* Arrays monodimensionales

LOCAL anArray := { 1, 2, 3, 4 }

* Arrays multidimensionales

LOCAL axArray := { 1, 2, { "A", "B", "C" } }

Direccionamiento de los Elementos de un Array

Una vez creado el array, se accede a sus elementos medianet el subíndice (empieza a partir de 1).

Por ejemplo:

* Arrays monodimensionales

Para acceder al primer elemento: anArray[ 1 ]

* Arrays multidimensionales

Para acceder al elemento de la primera fila, segunda columna.

anArray[ 1 ][ 2 ] o también anArray[ 1, 2 ]

Función

-----------

Descripción

---------------------------------------------

aAdd()

Añade un nuevo elemento al final de un array

aChoice()

Realiza un scroll a través de los elem. del array

aClone()

Duplica un array

aCopy()

Copia elementos de un array a otro

aDel()

Borra un elemento de un array

aDir()

Rellena un array con los ficheros encontrados

aEval()

Evalúa un CodeBlock para cada elemento del array

aFields()

Rellena arrays con la información de los campos

aFill()

Rellena los elementos del array con un valor dado

aIns()

Inserta un elemento en un array

array()

Crea/inicializa un array con los elem. y dimens.

aScan()

Busca secuencialmente un elemento en un array

aSize()

Modifica el tamaño de un array

aSort()

Ordena el contenido total o parcial de un array

aTail()

Devuelve el último elemento de un array

dbCreate()

Crea una base de datos desde un array

dbStruct()

Crea un array que contiene la estructura de .DBF

Directory()

Crea un array con información sobre ficheros

len()

Aplicado a un array, devuelve el tamaño de este

COMPONENTES DEL LENGUAJE: CODEBLOCKS

Un CodeBlock o bloque de código, es un nuevo tipo de dato,que mezcla los conceptos de funciones y variables, recibe y devuelve parámetros, y se puede asignar tanto a variables como arrays.

Sintaxis:

{ |Parámetros| Expresiones }

Notas:

Si hay varios parámetros y/o expresiones estas irán separadas por comas.

Declaración

-----------

En la declaración almacenamos el código, pero no lo ejecutamos (evaluamos).

Ejemplos:

bBloque := { || "cadena" } bBloque := { |x| x + 1 } bBloque := { |x,y| SQRT( x ) + SQRT( y ) } bBloque := { |a,b,c| Func( a ), Func( b ), Func( c ) }

Evaluación

En la evaluación, ejecutamos el CodeBlock almacenado anteriormente.

Eval( bBloque )

Aunque también podemos realizar lo mismo pasando un parámetro:

Eval( bBloque, "cadena" )

Operaciones con CodeBlocks

--------------------------

Operación

--------- -------------------------------------------------

Descripción

=

Asignación

:=

Asignación en línea

AEval()

Evaluación en cada elemento de un array

DbEval()

Evaluación en cada registro de un área de trabajo

Eval()

Evaluación de un bloque

COMPONENTES DEL LENGUAJE: FUNCIONES Y PROCEDIMIENTOS

Las funciones y los procedimientos son los elementos principales de la programación en CA-Clipper, y constan de un grupo de sentencias que realizan una tarea o acción determinada. Su funcionamiento es como el de "caja negra", recibe unos parámetros y devuelve otros, sin necesidad de conocer a fondo la rutina invocada.

Ambito de visibilidad

1) Ambito PUBLIC Se declaran con las sentencias FUNCTION y PROCEDURE.

2) Ambito del módulo fuente actual (.PRG) Se declaran con STATIC FUNCTION y STATIC PROCEDURE, cuando su aplicación procede reducen el tamaño del (.EXE), ya que su localización se resuelve en tiempo de compilación y no se almacenan en la tabla de símbolos.

Declaración de funciones y procedimientos

1) Funciones:

[STATIC] FUNCTION <identificador>[(<lista parámetros locales>) [<declaración de variables>]

.

.<sentencias ejecutables>

.

RETURN <expresión de retorno>

Notas: Los valores devueltos por RETURN, pueden ser cualquier tipo de datos( arrays, objetos, CodeBlocks, NIL, etc.)

2) Procedimientos:

[STATIC] PROCEDURE <identificador>[(<lista parámetr. locales>)] [<declaración de variables>]

.

.<sentencias ejecutables>

.

[RETURN]

Llamadas a funciones y procedimientos

1) Funciones:

<función>( [<lista parámetros>] )

2) Procedimientos:

<procedimiento>( [<lista parámetros>] ) DO <procedimiento> [WITH] [<lista parámetros>]

Notas: No se recomienda el uso de DO

WITH, ya

que pasan los argumentos por referencia.

Paso de parámetros

------------------

Cuando invocamos a una función o a un procedimiento, los va lores pasados se denominan argumentos o parámetros reales, y cuando la función los recibe se denominan argumentos o parámetros formales.

Ejemplo: Invocación -> Suma( nNum1, nNum2 ) Recepción -> FUNCTION Suma( n1, n2 ) RETURN( n1 + n2 )

Al invocar podemos omitir parámetros que serán inicializados desde la función receptora con un valor NIL, también podemos comprobar los parámetros pasados con la función PCOUNT().

Paso por Valor

Pasar un parámetro por valor significa que la función o procedimiento receptor opera con una copia del parámetro recibido, por lo tanto, no altera el valor inicial.

Paso por Referencia

En cambio, el paso por referencia, significa todo lo contrario, ya que no pasamos ninguna copia sino que hacemos referencia al valor del parámetro (misma posición de memoria), por lo que podemos alterar el valor del parámetro pasado. Para ello utilizamos el signo (@).

Ejemplo: Invocación -> Suma( @nNum1, nNum2 ) Recepción -> FUNCTION Suma( n1, n2 ) n1 := n1 + n2 RETURN

Notas: Este sistema puede ser util, por ejemplo, al trabajar con arrays, cuyos elementos hemos de actualizar.

Paso de parámetros desde MAIN()

También es posible pasar parámetros desde el programa (.EXE), si lo hemos especificado en la rutina principal con PARAMETERS, o desde MAIN().

Ejemplo: Desde el DOS : PROGRAMA COLOR En el programa: FUNCTION MAIN( cMonitor)

Recursividad

Un procedimiento o función es recursiva si contiene una llamada a si misma, ya sea de forma directa o indirecta, cuando se llame a otra función y esta invoca a la función primera.

Un ejemplo típico es el del factorial (extraída del manual):

FUNCTION Factorial( nFactorial ) IF nFactorial = 0 RETURN( 1 ) ELSE RETURN(nFactorial * Factorial(nFactorial - 1)) ENDIF

CONTROL DEL FLUJO DEL PROGRAMA

Anteriormente vimos que la programación estructurada seguía un flujo secuencial, que podíamos alterar mediante estructuras de control selectivas y repetitivas para la resolución de problemas.

REGLAS DE FUNCIONAMIENTO DE ESTRUC. SELECTIVAS Y REPETITIVAS

1) Han de tener una sentencia inicial y una de final. 2) Pueden anidarse estructuras dentro de otras.

ESTRUCTURAS SELECTIVAS

----------------------

El flujo de control del programa, es secuencial, es decir, va de sentencia en sentencia, de forma correlativa, sin embargo,muchas veces hemos de tomar una decisión, entre varias. Este tipo de estructura la denominaremos SELECTIVA.

Dependiendo del número de alternativas de selección podemos dividir las estructuras de control selectivas en:

- Bifurcaciones SIMPLES

- Bifurcaciones DOBLES

- Bifurcaciones MULTIPLES

BIFURCACIONES SIMPLES

---------------------

En las bifurcaciones simples la selección depende de si se cumple o no una condición. Ejecutandose la acción o acciones solo si se cumple la condición.

la acción o acciones solo si se cumple la condición. VERDAD Condición F A L S
la acción o acciones solo si se cumple la condición. VERDAD Condición F A L S

VERDAD

Condición

acciones solo si se cumple la condición. VERDAD Condición F A L S O Acción/es *

F

A

L

S

O

Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es
Acción/es

Acción/es

Acción/es
Acción/es
Acción/es
Acción/es
Acción/es

* Si la condición se cumple se ejecuta la acción u acciones

Sintaxis:

IF <condición> <instrucción/es> ENDIF

Ejemplo: Suponga un contador del número de filas para impresión.

// nFila++ if nFila = 55 @ nFila, 0 say "* FIN PAGINA *" EJECT nFila := 0 endif //

Mientrás nFila no sea igual a 55, no se producirá el SALTO DE PAGINA.

BIFURCACIONES DOBLES

--------------------

En las bifurcaciones dobles, siempre se ejecuta una acción, tanto si se cumple o no la condición.

ejecuta una acción, tanto si se cumple o no la condición. Condición VERDAD * Si la
ejecuta una acción, tanto si se cumple o no la condición. Condición VERDAD * Si la

Condición

VERDAD

* Si la condición se cumple, se ejecuta la Acción B

* Si la condición no se cumple, se ejecuta la Acción A

Acción A Acción B
Acción A
Acción B

FALSO

Sintaxis:

IF <condición> <instrucción/es> ELSE <instrucción/es> ENDIF

IIF( <condición>, <expresión 1>, <expresión 2> )

Si se cumple

No se cumple

Dependiendo del número de instrucciones, puede utilizar uno u otro formato.

Ejemplo: Suponga una entrada de datos.

// @ 0,0 GET cNombre READ

dbAppend()

// Añadimos registro vacío

IF LASTKEY() = 27 dbDelete() ELSE

// Pulsamos tecla <Esc> // Borramos registro // Reemplazamos datos

-> ACCION A

FieldPut( 1, cNombre ) ENDIF //

También podríamos expresar la estructura anterior de igual forma con IIF:

// -> ACCION B

-------------------------------------------------------------

IIF( LASTKEY() = 27, dbDelete(), FieldPut( 1, cNombre ) )

BIFURCACIONES MULTIPLES

En las bifurcaciones multiples la condición evaluada, puede tener más de dos acciones a elegir, es decir, no se limita a VERDAD (.T.) o a FALSO (.F.).

Condición Acción A Acción N Acción B Acción C Acción D
Condición
Acción A
Acción N
Acción B
Acción C
Acción D

Sintaxis:

Estructura DO CASE

Estructura IF

ENDIF

DO CASE CASE <condición 1> <instrucción/es> [CASE <condición n> <instrucción/es>] [OTHERWISE <instrucción/es>]

ENDCASE Ejemplo: Suponga el siguiente menú.

IF <condición 1> <instrucción/es> [ELSEIF <condición n> <instrucción/es> ] [ELSE <instrucción/es> ] ENDIF

FUNCTION MAIN() LOCAL nOpcion := 0

CLS

@ 05,35 PROMPT " Altas

@ 07,35 PROMPT " Bajas

@ 09,35 PROMPT " Modificar "
@ 11,35 PROMPT " Visualizar "
@ "

13,35 PROMPT " Imprimir

@ 15,35 PROMPT " Salir

"

"

"

MENU TO nOpcion

// Utilizando DO CASE y utilizando IF

ENDIF

DO CASE CASE nOpcion = 1 Altas() CASE nOpcion = 2 Bajas() CASE nOpcion = 3 Modificar() CASE nOpcion = 4 Visualizar() CASE nOpcion = 5 Imprimir() CASE nOpcion = 6 QUIT OTHERWISE

IF nOpcion = 1 Altas() ELSEIF nOpcion = 2 Bajas() ELSEIF nOpcion = 3 Modificar() ELSEIF nOpcion = 4 Visualizar() ELSEIF nOpcion = 5 Imprimir() ELSEIF nOpcion = 6 QUIT ELSE

Alert( "CASO NO PREVISTO")

Alert("NO PREVISTO")

ENDCASE

RETURN NIL

ENDIF

ESTRUCTURAS REPETITIVAS o BUCLES ITERATIVOS

Las estructuras repetitivas son una alteración del control del flujo secuencial del programa, pero a diferencia de las selectivas, las repetitivas se utilizan, como su nombre indica, para la resolución de problemas que requieren de la repetición de una serie de instrucciones hasta que se cumpla una condición,

ya sea verdadera o falsa, que provoque la salida del bucle

Iteración

falsa, que provoque la salida del b u c l e Iteración Condición Falso Cuerpo del

Condición

Falso
Falso
la salida del b u c l e Iteración Condición Falso Cuerpo del bucle Verdad Partes

Cuerpo del bucle

Verdad

c l e Iteración Condición Falso Cuerpo del bucle Verdad Partes de un bucle: * Cuerpo
c l e Iteración Condición Falso Cuerpo del bucle Verdad Partes de un bucle: * Cuerpo

Partes de un bucle:

* Cuerpo del bucle, es el conjunto de instrucciones que se repiten.

* Iteración, es cada vez que se repite el cuerpo del bucle.

* Salida del bucle, es el punto donde se termina la

ejecución del bucle y pasamos el control a la instrucción siguiente a este.

* Control de terminación, es la condición de salida del bucle.

MANDATO FOR

La estructura FOR

NEXT

NEXT, repite una serie de

instrucciones un determinado número de veces. Este tipo de bucle es de los denominados, controlados por una variable contador, que se incrementa o disminuye cada vez

que se ejecuta el cuerpo del bucle, hasta que se cumpla la condición de salida del bucle, es decir, hasta que la variable contador sea mayor que su valor final.

Sintaxis:

FOR nContador := nInicial TO nFinal [STEP nIncremento] <instrucciones> NEXT

o también:

FOR nContador := nFinal TO nInicial [STEP nDecremento]

<instrucciones>

NEXT

Ejemplo: Realice la siguiente prueba.

FUNCTION MAIN() LOCAL i := 0 CLS // Bucle con incremento, ira de 1 a 99, de 2 en 2 FOR i := 1 TO 100 STEP 2 QQOut( i ) NEXT

InKey( 0 )

// Bucle con decremento, ira de 100 a 2, de 2 en 2 FOR i:= 100 TO STEP -2 QQOut( i ) NEXT

RETURN NIL

MANDATO DO WHILE

ENDDO

ENDDO, repite

el cuerpo del bucle, hasta que se cumpla la condición de salida del bucle.

La estructura repetitiva DO WHILE

Sintaxis:

[DO] WHILE <condición> <instrucciones> [EXIT] [LOOP] END[DO]

Notas: La sentencia EXIT, provoca la salida forzosa del bucle, sin que se cumpla la condición de salida de dicho bucle.

La sentencia LOOP, provoca el comienzo de otra iteración sin que lleguemos a completar todo el cuerpo de bucle.

Ejemplo: Mostrar por pantalla el contenido de un fichero (sin parada de pantalla).

FUNCTION MAIN() USE CLIENTES

DO WHILE !EOF() QOut( NOMBRE ) dbSkip() ENDDO dbCloseArea() RETURN NIL

//Mientras no sea final de fichero //Muestra NOMBRE cliente //Siguiente registro

Notas: Observe los fuentes de algunos de los programas

y

funciones, para encontrar ejemplos del uso de EXIT

y

LOOP, que suelen emplearse en algoritmos complejos

de programación donde se concurre el anidamiento de bucles.

IMPORTANTE:

Existe aún otra estructura de control, se trata de:

BEGIN SEQUENCE

END SEQUENCE, que al estar

muy ligada al tratamiento de errores, se estudiará junto al OBJETO ERROR.

OPERACIONES CON DATOS DE TIPO CARACTER

Los datos de tipo carácter son los que se manipulan como cadenas de longitud fija, y comprenden los

caracteres ASCII del 32 al 126, y del 128 al 255, y el

0.

Notas: En las siguientes explicaciones utilizaremos la función QOut( <expresión> ), para mostrar el resultado de las expresiones, aunque también podríamos haber utilizado el antiguo formato: ? <Expresión> También podría haber simplificado algunos IF, por IIF() pero así se comprende mejor el código.

Operación

--------

+

-

=

==

Descripción -------------------------------------

Descripción -------------------------------------

Concatenar cadenas. Ejemplos: cCadena1 + cCadena2 "Nombre: " + cCadena "Nombre: " + Field->NOMBRE

Concatenar sin espacios intermedios. Ejemplo: QOut( "Nombre " - "Pepe" ) // Resultado: NombrePepe

Comprobar si son iguales.

Comprobar si son exactamente iguales. Ejemplo:

LOCAL cClave

LOCAL cEntrada := "XYZ"

IF cClave = cEntrada

:= "XYZ "

// La condición se cumple, aunque a cEntrada le

// falte un ENDIF IF cClave == cEntrada // La condición no se cumple, ya que a cEntrada // le falta un espacio ENDIF

!=, <> o #

<

Comprobar si son desiguales. Ejemplo: IF cClave != cEntrada Alert( "CLAVE INCORRECTA" ) ENDIF

Comprobar si se clasifica antes.

Ejemplo: IF "A" < "B" QOut( "SI" ) ENDIF

// .T.

Operación

--------------

<=

>

>=

= o STORE

Descripción

--------------------------

omprobar si se clasifica antes o en la misma posición.

Ejemplo: IF "a" <= "A"

// .F.

QOut( "SI" ) ENDIF

Comprobar si se clasifica después.

Ejemplo: IF "Z" > "1" QOut( "Si" ) ELSE QOut( "No" ) ENDIF

// .T.

Comprobar si se clasifica después o en la misma posición.

Ejemplo: IF "1" >= "A" QOut( "Si" ) ELSE QOut( "No" ) ENDIF

Asignación. (STORE en desuso). Ejemplo: cCadena = "Hola"

// .F.

:=

+=

-=

Asignación en línea. Ejemplo: cCadena := "Hola"

Concatenación y asignación en línea. Ejemplo: LOCAL cVar := "Hola, " cVar += "que tal" QOut( cVar ) // Hola, que tal Concatenación sin espacios intermedios, y asig- nación en línea. Ejemplo: LOCAL cVar := "Hola, " cVar -= "que tal"

sin espacios intermedios, y asig- nación en línea. Ejemplo: LOCAL cVar := "Hola, " cVar -=

QOut( cVar ) // Hola,que tal

Operación

--------------

$

REPLACE

ALLTRIM()

Descripción -------------------------

Comprueba la existencia de una subcadena. Ejemplo: QOut( "Hola"$"Hola, que tal" ) // .T.

Sustituye el valor de un campo. Ejemplo: LOCAL cNombre := SPACE( 30 ) @ 0,0 SAY "Nombre: " GET cNombre READ USE CLIENTES INDEX CLIENTES dbAppend() REPLACE Field->NOMBRE with cNombre dbCloseArea()

Elimina espacios iniciales y finales. Ejemplo: cVar := " XYZ "

cVar := AllTrim( cVar )

// "XYZ"

ASC()

Convierte un carácter en su número ASCII equi- valente.

Ejemplo: QOut( ASC( "A" ) )

// 65

AT()

Determina la posición de una subcadena. Ejemplo: cVar := "*HOLA*" QOut( AT( "HOLA", cVar ) ) // 2

CTOD()

Convierte una cadena a fecha. Ejemplo: CtoD( "01-04-94" )

DESCEND()

Convertir en forma complementada. Se utiliza

para crear ficheros índice en orden descendente (de mayor a menor). Ejemplo: USE CLIENTES INDEX ON DESCEND( NOMBRE ) TO CLIENTES // Zacarias // Ursula // Manuel

Operación

---------------

EMPTY()

ISALPHA()

ISDIGIT()

ISLOWER()

ISUPPER()

LEFT()

LEN()

LOWER()

LTRIM()

PADC()

Descripción .------------------------ Comprueba valor nulo (cadena vacía). Ejemplo: IF Empty( cVar ) QOut( "CADENA VACIA" ) ENDIF

Comprueba que el primer carácter sea una letra.

Ejemplo: QOut( IsAlpha( "XYZ" ) )

// .T.

Comprueba que el primer carácter sea un dígito.

Ejemplo: QOut( IsDigit( "XYZ" ) )

Comprueba que el primer carácter este en minúscula.

// .F.

Ejemplo: QOut( IsLower( "XYZ" ) )

// .F.

Comprueba que el primer carácter este en mayús- cula.

Ejemplo: QOut( IsUpper( "XYZ" ) )

// .T.

Extrae una subcadena por la izquierda.

Ejemplo: QOut( Left( "XYZ", 2 ) )

// XY

Devuelve la longitud de una cadena.

Ejemplo: QOut( Len( "XYZ" ) )

// 3

Convierte una cadena a minúsculas.

Ejemplo: QOut( Lower( "XYZ" ) )

Elimina espacios por la izquierda. Ejemplo: QOut( LTrim( " XYZ" ) )

// xyz

// XYZ

Centra una cadena por pantalla, rellenando con espacios u otro carácter, tanto el inicio como el final de la cadena, según una longitud deter- minada. Ejemplo: PadC( "XYZ", 80 )

Operación

-----------------

PADL()

Descripción ------------------------ Rellena con espacios u otro carácter, el inicio de una cadena, según una longitud determinada. Ejemplo: PadL( "XYZ", 80, "*" )

PADR()

Rellena con espacios u otro carácter, el final de una cadena, según una longitud determinada. Ejemplo: PadR( "XYZ", 40 )

RAT()

Devuelve la posición de una subcadena, empezando la búsqueda por la derecha. Sin

REPLICATE

embargo, el valor devuelto se cuenta por la izquierda.

Ejemplo: QOut( "HOLA", "*HOLA*" )

Repite una serie de caracteres, un determinado número de veces. Ejemplo: QOut( Replicate( "*", 5 ) ) // *****

// 2

RIGHT()

Extrae una subcadena por la derecha.

Ejemplo: QOut( Right( "XYZ", 2 ) )

// YZ

RTRIM()

Elimina los espacios finales de una cadena.

SOUNDEX()

SPACE()

Ejemplo: QOut( RTrim( "XYZ " ) )

// XYZ

Convierte una cadena en su equivalente fonético.

Ejemplo: QOut( Soundex( "Pez" ) ) QOut( Soundex( "Peso" ) )

// P200

// P200

Crea una cadena de espacios. Ejemplo: cVar := SPACE( 10 ) QOut( Len( cVar ) )

// 10

Operación

-----------------

STRTRAN()

STUFF()

Descripción ------------------------- Busca y reemplaza una serie de caracteres en una cadena. Ejemplo: QOut( StrTran( "999.99", ".", "," ) ) // Resultado: 999,99 // Sustituimos el punto decimal por // una coma.

Elimina, inserta y/o reemplaza caracteres en una cadena. Ejemplo: cVar := "**1**" nPos := AT( "1", cVar ) QOut( Stuff( cVar, nPos, 1, "0" ) ) // Resultado: **0**

SUBSTR()

Extrae una subcadena. Ejemplo: QOut( "XYZ", 2, 1 )

// Y

TRANSFORM()

Formatea una cadena. QOut( Transform( "xyz", "@!" ) )

// XYZ

TYPE()

Evalúa el tipo de datos de una expresión.

QOut( 'Left( "XYZ", 1 )' )

// C = cadena

UPPER()

Convierte las letras de una cadena a mayúsculas.

QOut( Upper( "xyz" ) )

// XYZ

VAL()

Convierte una cadena a valor numérico.

Ejemplo: QOut( Val( "123Z" ) )

// 123

QOut( Val( "Z123" ) )

// 0

VALTYPE()

Evalúa una expresión o variable directamente. Ejemplo: cVar := "XYZ"

QOut( ValType( cVar ) )

// C

Notas: La principal diferencia entre TYPE y VALTYPE, es en que este último se puede utilizar directamente sobre variables.

OPERACIONES CON DATOS DE TIPO NUMERICO

Los tipos de datos numéricos son los que se utilizan para manipularse matemáticamente, y estan formados por los dígitos ( 0 al 9 ), el punto como separador de decimales y los caracteres + y - para indicar el signo del número.

Podemos realizar las siguientes operaciones con ellos:

(Suponga para los ejemplos lo siguiente: LOCAL nNumero := 5)

Operación

Descripción

---------

----------------------------------------

+

Suma. Ejemplo: QOut( nNumero + 1 )

// 6

-

Resta. Ejemplo: QOut( nNumero - 1 )

// 5

*

Multiplicación. Ejemplo: QOut( nNumero * 2 )

// 10

Operación

----------------

/

%

5 2 1 2
5
2
1
2

** o chr(94)

Descripción

-------------------------

División. Ejemplo: QOut( nNumero / 2 )

Resto. Ejemplo: QOut( nNumero % 2 )

Exponenciación. Ejemplo: QOut( nNumero ** 2 )

// 2.5

// 1

// 25

++

--

= o ==

!=, <> o #

Incremento. Ejemplo: nNumero++ QOut( nNumero )

Decremento. Ejemplo: nNumero-- QOut( nNumero )

// 6

// 4

Comprobación igualdad. Ejemplo: IF nNumero = 5 QOut( "IGUAL A 5" ) ENDIF

Comprobación desigualdad. Ejemplo: IF nNumero != 5 QOut( "DESIGUAL A 5" ) ENDIF

<

Comprobar si es menor que Ejemplo: IF nNumero < 5 QOut( "MENOR QUE 5" ) ENDIF

Operación

---------------

Descripción

---------------------

<

<=

>

>=

Comprobar si es menor que Ejemplo: IF nNumero < 5 QOut( "MENOR QUE 5" ) ENDIF

Comprobar si es menor que o igual Ejemplo: IF nNumero <= 5 QOut( "MENOR O IGUAL A 5" ) ENDIF

Comprobar si es mayor que Ejemplo: IF nNumero > 5 QOut( "MAYOR QUE 5" ) ENDIF

Comprobar si es mayor o igual que Ejemplo: IF nNumero >= 5 QOut( "MAYOR O IGUAL A 5" ) ENDIF

= o STORE

Asignación. (STORE en desuso). Ejemplo: nNumero = 10

:=

+=

-=

*=

Asignación en línea. Ejemplo: LOCAL nNumero := 10

Suma y asignación en línea. Ejemplo: QOut( nNumero += 5 )

Resta y asignación en línea. Ejemplo: QOut( nNumero -= 5 )

+= 5 ) Resta y asignación en línea. Ejemplo: QOut( nNumero -= 5 ) // 10

// 10

// 0

Multiplicación y asignación en línea.

Multiplicación y asignación en línea.

Ejemplo: QOut( nNumero *= 5 )

// 25

Operación

----------------

/=

^=

%=

REPLACE

Descripción --------------------------- División y asignación en línea. Ejemplo: QOut( nNumero /= 5 )

// 1

Exponenciación y asignación en línea.

Ejemplo: QOut( nNumero 2 )

// 2

Resto y asignación en línea. Ejemplo: QOut( nNumero %= 5 )

// 0

Sustituir el valor de un campo. Ejemplo: REPLACE CODIGO WITH nNumero

ABS()

Calcula el valor absoluto (positivo).

Ejemplo: QOut( ABS( -3.25 * 5.5 ) // 17.875

QOut( -3.25 * 5.5 )

// -17.875

CHR()

Convierte un número a su equivalente ASCII.

DESCEND()

Ejemplo: QOut( CHR( 65 ) )

// A

Crea indexados en orden ascendente. Ejemplo: USE CLIENTES INDEX ON DESCEND( CODIGO ) TO CLIENTES

EMPTY()

EXP()

INT()

Comprueba valor cero. Ejemplo: IF Empty( nNumero ) QOut( "VALOR CERO" ) ENDIF

Comprueba valor cero. Ejemplo: IF Empty( nNumero ) QOut( "VALOR CERO" ) ENDIF

Exponenciación en base e. Ejemplo: QOut( EXP( 5 ) )

Convierte un número a entero. Ejemplo: QOut( INT( 3.25 ) )

// 148.41

// 3

Operación

Descripción

---------------- ---------------------------

LOG()

MAX()

Calcula el logaritmo natural. Ejemplo: QOut( LOG( 5 ) )

// 1.61

Calcula el valor máximo. Ejemplo: LOCAL nNum1 := 8, nNum2 := 5 QOut( MAX( nNum1, nNum2 ) ) // 8

Calcula el valor máximo. Ejemplo: LOCAL nNum1 := 8, nNum2 := 5 QOut( MAX( nNum1, nNum2

MIN()

MOD()

ROUND()

SQRT()

STR()

Calcula el valor mínimo. Ejemplo: LOCAL nNum1 := 8, nNum2 := 5 QOut( MIN( nNum1, nNum2 ) ) // 5

Calcula el resto (equivalencia con dBase III+). Ejemplo: LOCAL nNum1 := 8, nNum2 := 5 QOut( MOD( nNum1, nNum2 ) ) // 3

Redondeo. Ejemplo: LOCAL nNumero := 9.60 QOut( Round( nNumero ) )

Raiz cuadrada. Ejemplo: QOut( SQRT( 25 ) )

// 5

// 10

Convierte un número a cadena. Ejemplo: LOCAL nNumero := 5

LOCAL cNumero := Str( nNumero ) + A

TRANSFORM()

QOut( cNumero )

// 5A

Convertir en cadena formateada. Ej: LOCAL nNumero := 5.999 QOut( Transform( nNumero, "999.99" ) ) // Resultado = 6.00, se efectúa // redondeo al comernos un dígito.

Operación

----------------

TYPE()

VALTYPE()

Descripción

-------------------

Evalúa el tipo de dato de una expresión.

Ejemplo: QOut( Type( "5 * 2" ) )

// N

Evalúa el tipo de dato de una expresión, o de una variable de forma directa.

Ejemplo: QOut( ValType( nNumero ) )

// N

OPERACIONES CON DATOS DE TIPO FECHA

Los datos de tipo fecha, identifican como su nombre indica, las fechas del calendario, estan formados por los dígitos del 0 al 9, y por un carácter separador, especificado por el mandato SET DATE.

Podemos realizar las siguientes operaciones:

- para los siguientes ejemplos, suponga que:

La fecha del ordenador es 01-04-94 SET DATE ITALIAN

dFecha := date()

Operación

// 01-04-94

Descripción

---------

-------------------------------------------

+

Sumar días a una fecha. Ejemplo: QOut( dFecha + 10 )

// 11-04-94

-

Restar días de una fecha. Ejemplo: QOut( dFecha - 10 )

// 22-03-94

Operación

---------------

Descripción

-------------------

++

--

= o ==

Incrementar fecha en uno. Ejemplo: dFecha++ QOut( dFecha )

Decrementar fecha en uno. Ejemplo: dFecha-- QOut( dFecha )

// 02-04-94

// 31-03-94

Comprobar si son iguales dos fechas. Ejemplo: IF dFecha == CTOD( "01-04-94" ) QOut( "Fecha idénticas" ) ENDIF

si son iguales dos fechas. Ejemplo: IF dFecha == CTOD( "01-04-94" ) QOut( "Fecha idénticas" )

!=, <> o #

Comprobar si son desiguales. Ejemplo: IF dFecha != CTOD( "01-01-94" ) QOut( "Fecha desigual a 01-01-94" ) ENDIF

<

<=

>

Comprobar si es anterior. Ejemplo: IF dFecha < CTOD( "01-01-94" ) QOut( "Fecha año 93" ) ENDIF

Comprobar si es anterior o igual. Ejemplo: IF dFecha <= CTOD( "31-12-93" ) QOut( "Fecha anterior al 94" ) ENDIF

Comprobar si es posterior. Ejemplo: IF dFecha > CTOD( "31-12-93" ) QOut( "Fecha año 94" ) ENDIF

Operación

---------------

>=

= o STORE

Descripción

-------------------

Comprobar si es mayor o igual. Ejemplo: IF dFecha >= CTOD( "01-01-94" ) QOut( "Fecha año 94" ) ENDIF

Asignación. (STORE esta en desuso). Ejemplo: dFecha = date()

:=

+=

-=

Asignación en línea. Ejemplo: LOCAL dFecha := date()

Asignación en línea. Ejemplo: LOCAL dFecha := date()

Suma y asignación en línea. Ejemplo: QOut( dFecha += 1 )

Resta y asignación en línea. Ejemplo: QOut( dFecha -= 1 )

// 02-04-94

// 31-03-94

REPLACE

CDOW()

CMONTH()

DAY()

DESCEND()

Sustituir valor de un campo. Ejemplo: REPLACE FECHA WITH date()

Devuelve el nombre del día de la semana. Ejemplo: QOut( cDow( date() ) ) // Viernes

Devuelve el nombre del mes. Ejemplo: QOut( cMonth( date() ) ) // Abril

Extrae el día de una fecha. Ejemplo: QOut( day( date() ) ) // 1 ->01-04-94

Crea indexados en orden descendente. Ejemplo:

USE CLIENTES INDEX ON DESCEND( DTOS( FECHA ) ) TO FECHAS

Operación

---------------

Descripción

-------------------

DOW()

Devuelve el número del día de la semana.

(Domingo = 1, Lunes = 2,

,

Sabado = 7)

Ejemplo: QOut( dow( date() ) ) // 6

DTOC()

Convierte fecha en cadena de caracteres. Ejemplo: QOut( "Fecha: " + DtoC( date() ) ) // Resultado: Fecha: 01-04-94

DTOS()

Convierte fecha en cadena con formato de orde- nación. Es de mucha utilidad para los ficheros indexados por un campo de tipo fecha. Ejemplo: QOut( "Fecha: " + DtoS( date() ) ) // Resultado: Fecha: 19940401

EMPTY()

Comprobar valor nulo. Ejemplo: LOCAL dFecha IF Empty( dFecha ) QOut( "Fecha vacía" ) ENDIF

MONTH()

Devuelve el número del mes. Ejemplo: QOut( Month( date() ) ) // 4 ->01-04-94

TRANSFORM() Convertir en cadena formateada. Ejemplo: QOut( Transform( "01-04-94", "@D" )

TYPE()

Evalúa el tipo de datos de una expresión. Ejemplo: QOut( Type( 'CtoD( "01-04-92" )' ) ) // Resultado: D -> tipo de dato fecha

VALTYPE()

YEAR()

Evalúa directamente el tipo de datos de una variable. Ejemplo: QOut( ValType( dFecha ) ) // D

Devuelve el número de año completo, incluyendo

OPERACIONES CON DATOS DE TIPO LOGICO

Los tipos de datos lógicos identifican elementos de naturaleza booleana, es decir, elementos como verdad/mentira, si/no, etc.

Y sobre ellos podemos realizar las siguientes operaciones:

Operación

Descripción

---------

.AND.

-------------------------------------------- Conjunción lógica. Ejemplo: LOCAL nNumero := 99 IF nNumero >= 1 .AND. nNumero < 100 QOut( "Nº positivo menor que 100" ) ENDIF

.OR.

Disyunción inclusiva lógica. Ejemp: LOCAL cConfirma := SPACE( 1 ) // @ 0,0 SAY "Borrar (S/N)" GET cConfirma READ IF cConfirma == "S" .OR. cConfirma == "s" dbDelete() PACK ENDIF //

// La condición anterior se podría reducir a:

IF Upper( cConfirma ) == "S"

Operación

----------------

.NOT. o !

Descripción

---------------------

Negación. Eje : USE CLIENTES DO WHILE !EOF()

//Mientras no último

QOut( STR( CODIGO ) + NOMBRE ) dbSkip() ENDDO dbCloseArea()

= o ==

Comprobar si son iguales. Ejemplo: LOCAL lSN := .T.

@ 0,0 SAY "(T/F) " GET lSN picture "L"

READ IF lSN == .T. QOut( "VERDAD" ) ELSE QOut( "FALSO" ) ENDIF

!=, <> o #

Comprobar si son desiguales. Ejemplo: LOCAL lSN := .T.

@ 0,0 SAY "(T/F) " GET lSN picture "L"

READ IF lSN != .T. QOut( "FALSO" ) ELSE QOut( "VERDAD" ) ENDIF

Notas: Para mayor información sobre los operadores lógicos (.AND., .OR., .NOT.), consulte la lección nº 21.

OPERACIONES CON DATOS DE TIPO MEMO

Los datos de tipo MEMO, son campos de una base de datos, y estan representados por caracteres de longitud

Pudiendo realizar sobre ellos las siguientes operaciones:

Operación

---------

HARDCR()

MEMOEDIT()

MEMOLINE()

MEMOREAD()

MEMOTRAN()

MEMOWRIT()

MLCOUNT()

MLPOS()

Descripción

---------------------------------------------

Sustituye los retornos de carro blandos->CHR(141) (o automáticos) por retornos de carro forzados->

CHR(13)

Edita el contenido de un campo MEMO.

Extrae una línea de texto de un campo MEMO o de una cadena.

Lee un fichero ASCII.

Sustituye los retornos de carro forzados por los blandos o automáticos.

Escribe en un fichero ASCII.

Cuenta las líneas de un campo MEMO o de un cadena.

Calcula la posición que tendría una línea determi- nada, en caso de variar el ancho del campo MEMO o de una cadena.

Ejemplo: Para comprender mejor dicho funcionamiento, ejecute el siguiente programa.

// ----------------------------------------------------------- // Compilación: CLIPPER PROG /N

//

RTLINK FILE PROG

FUNCTION MAIN()

LOCAL nNumero := 0

LOCAL i

:= 0

// Creamos fichero con un campo MEMO

dbCreate( "TEXTO", { { "NUMERO", "N", 02, 00 }, ;

{ "NOTAS",

// Borramos pantalla, y creamos marco para la edición CLS

"M", 10, 00 } } )

@ 05,10 TO 10,70

@ 10,15 SAY " Ctrl + W = Grabar "

// Abrimos fichero y añadimos un registro

USE TEXTO dbAppend() nNumero++

REPLACE NUMERO WITH nNumero REPLACE NOTAS WITH MemoEdit( NOTAS, 06, 11, 09, 69, .T. ) READ

DevPos( 11, 00 ) QOut("Escribimos en un fichero ASCII el contenido de NOTAS") MemoWrit( "TEXTO.TXT", Field->NOTAS )

QOut( "Leemos y editamos dicho fichero ASCII" ) MemoEdit( MemoRead( "TEXTO.TXT" ), 06, 11, 09, 69, .T. ) Inkey( 0 )

LS QOut("Mostrar NOTAS, con sustitución retorno carro autom.") QOut("Contamos líneas-> MLCOUNT(), y extraemos->MEMOLINE()")

FOR i := 1 TO MlCount( Field->NOTAS, 59 ) QOut( HardCR( MemoLine( Field->NOTAS, 59, i ) ) ) NEXT

InKey( 0 )

CLS QOut("Mostrar campo NOTAS, con sustitución retornos carro:") QOut("Forzado, chr(13) = * y automático, chr(141) = **")

OR i := 1 TO MlCount( Field->NOTAS, 59 ) QOut( MemoTran( MemoLine(Field->NOTAS,59,i) ),"*","**" ) NEXT

dbCloseArea()

RETURN NIL // ------------------------------------------------------------

OPERACIONES CON DATOS DE TIPO NIL

El dato de tipo NIL, es un nuevo tipo de datos que nos permite manipular variables no inicializadas sin generar errores.

Un valor NIL, es siempre menor que cualquier otro tipo de dato, por lo que en cuanto a los operadores relacionales, solo usaremos los de igualdad o desigualdad. Es decir, si una variable es igual a NIL, se trata de un dato NIL, y si es desigual se trata de otro dato que tiene un valor superior a NIL.

Operación

---------

= o ==

!=, <> o #

Descripción

------------------------------------------------

Comprobar si son iguales. Ejemplo: LOCAL nNumero if nNumero == NIL QOut( "Variable no inicializada" ) endif

Comprobar si son desiguales. Ejemplo: LOCAL nNumero := 5 if nNumero != NIL QOut( "Variable inicializada" ) endif

=

o :=

STORE

Asignar a una variable de memoria, LOCAL o ESTATICA. (STORE esta en desuso). Ejemplo: LOCAL nNumero := 5

 

nNumero := 5

// o nNumero = 5

EMPTY()

Comprueba el valor NIL. Ejemplo: LOCAL xVariable

Operación

---------

Descripción

------------------------------------------------

EMPTY()

Comprueba el valor NIL. Ejemplo: LOCAL xVariable if Empty( xVariable ) QOut( "Variable VACIA" ) endif

TYPE()

Evalúa el tipo de datos de una expresión. Ejemplo: QOut( TYPE( 'NIL' ) ) // Resultado: U = NIL

VALTYPE()

Evalúa el tipo de datos de una expresión. Suele aplicarse directamente a variables. Ejemplo: LOCAL xVariable QOut( VALTYPE( xVariable ) ) // Resultado: U = NIL

OPERACIONES CON ARRAYS

Los arrays nos permiten almacenar un conjunto de variables en memoria de distintos tipos, realizar operaciones entre ellos, y al estar en memoria su manejo es mucho más rápido que la manipulación de registros de disco.

Operación Descripción

---------

-----------------------------------------

aAdd()

Añade un nuevo elemento al final de un array.

Sintaxis: aAdd( <axArray>, <xExpresion> ) Ejemplo: aAdd( acClientes, "Pepe" )

Operación

--------------

aChoice()

Descripción

-------------------------

Selecciona uno de los elementos de un array.

Sintaxis:

aChoice( <nTop>, <nLeft>, <nBottom>, <nRight>, ; <axArray> [, <alArray> ; [, <función usuario> [, ; <nElemInicial> [, <nFilaRelativa> ]]]] )

Ejemplo:

nOpcion := aChoice( 05, 05, 07, 10, { "Sí", "No" } )

aClone()

Duplica un array.

Sintaxis: aClone( <axArray> )

Ejemplo: anArray1 := { 1, 2, 3 } anArray2 := aClone( anArray1 )

aCopy()

Copia elementos de un array a otro.

Sintaxis: