75% encontró este documento útil (4 votos)
12K vistas639 páginas

Programacion en Java

El documento describe la evolución de los lenguajes de programación desde los lenguajes de máquina primitivos hasta los lenguajes de alto nivel modernos como Java. Explica que los primeros lenguajes eran lenguajes de máquina que requerían programar directamente en códigos numéricos, mientras que lenguajes posteriores como los ensambladores y FORTRAN proporcionaron mayores niveles de abstracción. Finalmente, Java fue diseñado para ser un lenguaje orientado a objetos, independiente de plataforma y seguro que permite el des

Cargado por

jose-alamo-7352
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
75% encontró este documento útil (4 votos)
12K vistas639 páginas

Programacion en Java

El documento describe la evolución de los lenguajes de programación desde los lenguajes de máquina primitivos hasta los lenguajes de alto nivel modernos como Java. Explica que los primeros lenguajes eran lenguajes de máquina que requerían programar directamente en códigos numéricos, mientras que lenguajes posteriores como los ensambladores y FORTRAN proporcionaron mayores niveles de abstracción. Finalmente, Java fue diseñado para ser un lenguaje orientado a objetos, independiente de plataforma y seguro que permite el des

Cargado por

jose-alamo-7352
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 639

Programacin

Lenguajes de programacin
Al desarrollarse las primeras computadoras electrnicas, se vio la necesidad de programarlas, es decir, de almacenar en memoria la informacin sobre la tarea que iban a ejecutar. Las primeras se usaban como calculadoras simples; se les indicaban los pasos de clculo, uno por uno. John Von Neumann desarroll el modelo que lleva su nombre, para describir este concepto de "programa almacenado". En este modelo, se tiene una abstraccin de la memoria como un conjunto de celdas, que almacenan simplemente nmeros. Estos nmeros pueden representar dos cosas: los datos, sobre los que va a trabajar el programa; o bien, el programa en s. Cmo es que describimos un programa como nmeros? Se tena el problema de representar las acciones que iba a realizar la computadora, y que la memoria, al estar compuesta por switches correspondientes al concepto de bit, solamente nos permita almacenar nmeros binarios. La solucin que se tom fue la siguiente: a cada accin que sea capaz de realizar nuestra computadora, asociarle un nmero, que ser su cdigo de operacin (opcode). Por ejemplo, una calculadora programable simple podra asignar los opcodes: 1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE. Supongamos que queremos realizar la operacin 5 * 3 + 2, en la calculadora descrita arriba. En memoria, podramos "escribir" el programa de la siguiente forma: Localidad Opcode Significado Comentario 0 5 5 En esta localidad, tenemos el primer nmero de la frmula 1 3 * En esta localidad, tenemos el opcode que representa la multiplicacin. 2 3 3 En esta localidad, tenemos el segundo nmero de la frmula 3 1 + En esta localidad, tenemos el opcode que representa la suma. 4 2 2 En esta localidad, tenemos el ltimo nmero de la frmula Podemos ver que con esta representacin, es simple expresar las operaciones de las que es capaz el hardware (en este caso, nuestra calculadora imaginaria), en la memoria. La descripcin y uso de los opcodes es lo que llamamos lenguaje de mquina . Es decir, la lista de cdigos que la mquina va a interpretar como instrucciones, describe las capacidades de programacin que tenemos de ella; es el lenguaje ms primitivo, depende directamente del hardware, y requiere del programador que conozca el funcionamiento de la mquina al ms bajo nivel. los lenguajes ms primitivos fueron los lenguajes de mquina. Esto, ya que el hardware se desarroll antes del software, y adems cualquier software finalmente tiene que expresarse en el lenguaje que maneja el hardware. La programacin en esos momentos era sumamente tediosa, pues el programador tena que "bajarse" al nivel de la mquina y decirle, paso a pasito, cada punto de la tarea que tena que realizar. Adems, deba expresarlo en forma numrica; y por supuesto, este proceso era propenso a errores, con lo que la productividad del programador era muy limitada. Sin embargo, hay que recordar que en estos momentos, simplemente an no exista alternativa. El primer gran avance que se dio, como ya se coment, fue la abstraccin dada por el Lenguaje Ensamblador, y con l, el nacimiento de las primeras herramientas automticas para generar el

cdigo mquina. Esto redujo los errores triviales, como poda ser el nmero que corresponda a una operacin, que son sumamente engorrosos y difciles de detectar, pero fciles de cometer. Sin embargo, an aqu es fcil para el programador perderse y cometer errores de lgica, pues debe bajar al nivel de la forma en que trabaja el CPU, y entender bien todo lo que sucede dentro de l. Con el desarrollo en los 50s y 60s de algoritmos de ms elevado nivel, y el aumento de poder del hardware, empezaron a entrar al uso de computadoras cientficos de otras ramas; ellos conocan mucho de Fsica, Qumica y otras ramas similares, pero no de Computacin, y por supuesto, les era sumamente complicado trabajar con lenguaje Ensamblador en vez de frmulas. As, naci el concepto de Lenguaje de Alto Nivel, con el primer compilador de FORTRAN (FORmula TRANslation), que, como su nombre indica, inici como un "simple" esfuerzo de traducir un lenguaje de frmulas, al lenguaje ensamblador y por consiguiente al lenguaje de mquina. A partir de FORTRAN, se han desarrollado innumerables lenguajes, que siguen el mismo concepto: buscar la mayor abstraccin posible, y facilitar la vida al programador, aumentando la productividad, encargndose los compiladores o intrpretes de traducir el lenguaje de alto nivel, al lenguaje de computadora. Hay que notar la existencia de lenguajes que combinan caractersticas de los de alto nivel y los de bajo nivel (es decir, Ensamblador). Mi ejemplo favorito es C: contiene estructuras de programacin de alto nivel, y la facilidad de usar libreras que tambin son caractersticas de alto nivel; sin embargo, fue diseado con muy pocas instrucciones, las cuales son sumamente sencillas, fciles de traducir al lenguaje de la mquina; y requiere de un entendimiento apropiado de cmo funciona la mquina, el uso de la memoria, etctera. Por ello, muchas personas consideramos a lenguajes como C (que fue diseado para hacer sistemas operativos), lenguajes de nivel medio.

Java
El lenguaje de programacin Java, fue diseado por la compaa Sun Microsystems Inc, con el propsito de crear un lenguaje que pudiera funcionar en redes computacionales heterogneas ( redes de computadoras formadas por ms de un tipo de computadora, ya sean PC, MAC's, estaciones de trabajo, etc.),y que fuera independiente de la plataforma en la que se vaya a ejecutar. Esto significa que un programa de Java puede ejecutarse en cualquier mquina o plataforma. El lenguaje fue diseado con las siguientes caractersticas en mente: Simple. Elimina la complejidad de los lenguajes como "C" y da paso al contexto de los lenguajes modernos orientados a objetos. Orientado a Objetos. La filosofa de programacin orientada a objetos es diferente a la programacin convencional. Familiar. Como la mayora de los programadores estn acostumbrados a programar en C o en C++, el sintaxis de Java es muy similar al de estos. Robusto. El sistema de Java maneja la memoria de la computadora por ti. No te tienes que preocupar por apuntadores, memoria que no se est utilizando, etc. Java realiza todo esto sin necesidad de que uno se lo indique. Seguro. El sistema de Java tiene ciertas polticas que evitan se puedan codificar virus con este lenguaje. Existen muchas restricciones, especialmente para los applets, que limitan lo que se puede y no puede hacer con los recursos crticos de una computadora. Portable. Como el cdigo compilado de Java (conocido como byte code) es interpretado, un programa compilado de Java puede ser utilizado por cualquier computadora que tenga implementado el interprete de Java. Independiente a la arquitectura. Al compilar un programa en Java, el cdigo resultante un tipo de cdigo binario conocido como byte code. Este cdido es interpretado por diferentes computadoras de igual manera, solamente hay que implementar un intrprete para cada plataforma. De esa manera Java logra ser un lenguaje que no depende de una arquitectura computacional definida.

Multithreaded. Un lenguaje que soporta multiples threads es un lenguaje que puede ejecutar diferentes lneas de cdigo al mismo tiempo. Interpretado. Java corre en mquina virtual, por lo tanto es interpretado. Dinmico. Java no requiere que compiles todas las clases de un programa para que este funcione. Si realizas una modificacin a una clase Java se encarga de realizar un Dynamic Bynding o un Dynamic Loading para encontrar las clases.

Java puede funcionar como una aplicacin sola o como un "applet", que es un pequeo programa hecho en Java. Los applets de Java se pueden "pegar" a una pgina de Web (HTML), y con esto puedes tener un programa que cualquier persona que tenga un browser compatible podr usar. Nota: Diferencia entre Java y CGI La diferencia es esencialmente simple, un CGI se ejecuta en el servidor mientras que un programa en Java se ejecuta en la mquina del usuario. Java funciona de la siguiente manera: El compilador de Java deja el programa en un Pseudocdigo (no es cdigo maquinal) y luego el intrprete de Java ejecuta el programa (lo que se conoce como el "Java Virtual Machine"). Por eso Java es multiplataforma, existe un intrprete para cada mquina diferente. Nota: El cdigo maquinal es el cdigo binario que la computadora entiende y puede ejecutar. Para entender bien como funciona un applet de Java vean el siguiente ejemplo: 1. Existe un cdigo de Java en un servidor de Web. (Los cdigos de Java se caracterizan por tener la extensin *.class). 2. Una persona en Internet, con un browser compatible con Java, realiza una coneccin al servidor. 3. El servidor enva el documento HTML y el cdigo en Java (*.class). 4. En la computadora del usuario remoto llegan ambos, y la Mquina Virtual de Java, que est en el browser, transforma el cdigo Java en un cdigo que entienda la mquina local y se ejecuta el programa dentro de la pgina de Web. 5. Si el usuario realiza otra conexin a otro URL o se sale del browser, el programa se deja de ejecutar y en la computadora no queda rastro de el.

Ejemplo de tutorial de Java: En Java hay tres tipos de comentarios: // comentarios para una sola lnea /* comentarios de una o ms lneas */ /** comentario de documentacin, de una o ms lneas */ Los dos primeros tipos de comentarios son los que todo programador conoce y se utilizan del mismo modo. Los comentarios de documentacin, colocados inmediatamente antes de una declaracin (de variable o funcin), indican que ese comentario ha de ser colocado en la documentacin que se genera automticamente cuando se utiliza la herramienta de Java, javadoc.

Dichos comentarios sirven como descripcin del elemento declarado permitiendo generar una documentacin de nuestras clases escrita al mismo tiempo que se genera el cdigo. En este tipo de comentario para documentacin, se permite la introduccin de algunos tokens o palabras clave, que harn que la informacin que les sigue aparezca de forma diferente al resto en la documentacin. Identificadores Los identificadores nombran variables, funciones, clases y objetos; cualquier cosa que el programador necesite identificar o usar. En Java, un identificador comienza con una letra, un subrayado (_) o un smbolo de dlar ($). Los siguientes caracteres pueden ser letras o dgitos. Se distinguen las maysculas de las minsculas y no hay longitud mxima. Seran identificadores vlidos: identificador nombre_usuario Nombre_Usuario _variable_del_sistema $transaccion y su uso sera, por ejemplo: int contador_principal; char _lista_de_ficheros; float $cantidad_en_Ptas;

C
C es un lenguaje de programacin diseado por Dennis Ritchie, de los Laboratorios Bell, y se instal en un PDP-11 en 1972; se dise para ser el lenguaje de los Sistemas Operativos UNIX1. A su vez, UNIX es un Sistema Operativo desarrollado por Ken Thompson, quin utiliz el lenguaje ensamblador y un lenguaje llamado B para producir las versiones originales de UNIX, en 1970. C se invent para superar las limitaciones de B. C es un lenguaje maduro de propsitos generales que se desarroll a partir de estas races; su definicin aparece en 1978 en el apndice ``C Reference Manual'' del libro The C Programming Language, de Brian W. Kernighan y Dennis M. Ritchie (Englewood Cliffs, Nueva Jersey, PrenticeHall 1978), pero el estndar recomendable ms reciente apareci en junio de 1983, en el documento de los Laboratorios Bell titulado The C Programming Language-Reference Manual, escrito por Dennis M. Ritchie. Un programa en C

Generalizando, un programa en C consta de tres secciones. La primera seccin es donde van todos los ``headers''. Estos ``headers'' son comnmente los ``#define'' y los ``#include''. Como segunda seccin se tienen las ``funciones''. Al igual que Pascal, en C todas las funciones que se van a ocupar en el programa deben ir antes que la funcin principal (main()). Declarando las funciones a ocupar al principio del programa, se logra que la funcin principal est antes que el resto de las funciones. Ahora, solo se habla de funciones ya que en C no existen los procedimientos. Y como ltima seccin se tiene a la funcin principal, llamada main. Cuando se ejecuta el programa, lo primero que se ejecuta es esta funcin, y de ah sigue el resto del programa. Los smbolos { y } indican ``begin'' y ``end'' respectivamente. Si en una funcin o en un ciclo while, por ejemplo, su contenido es de solamente una lnea, no es necesario usar ``llaves'' ({ }), en caso contrario es obligacin usarlos. Ejemplo de un programa en C /*Programa ejemplo que despliega el contenido de "ROL" en pantalla*/ #include <stdio.h> #define ROL "9274002-1" despliega_rol() { printf("Mi rol es : \%s\n", ROL); } void main() { despliega_rol(); } /* Fin programa */

Pascal
Pascal es un lenguaje de programacin de alto nivel de propsito general; esto es, se puede utilizar para escribir programas para fines cientficos y comerciales. El lenguaje de programacin Pascal fue desarrollado por el profesor Niklaus (Nicols) Wirth en Zurich, Zuiza, al final de los aos 1960s y principios de los 70s. Wirth dise este lenguaje para que fuese un buen primer lenguaje de programacin para personas comenzando a aprender a programar. Pascal tiene un nmero relativamente pequeo de conceptos para aprender y dominar. Su diseo facilita escribir programas usando un estilo que est generalmente aceptado como prctica estndar de programacin buena. Otra de las metas del diseo de Wirth era la implementacin fcil. l dise un lenguaje para el cual fuese fcil escribir un compilador para un nuevo tipo de computadora. program Sorting;

{ Este programa lee un natural y una secuencia de N caracteres de la entrada estandar; construye un indice para ordenarlos de menor a mayor e imprime en la salida la secuencia ordenada. } uses CRT; Const Max = 10; Espacio = ' '; Enter = chr (13); type Indice = 1..Max; Cantidad= 0..Max; SecOfChar = record elems : array [Indice] of char; ult : Cantidad; end; SecOfInd = record elems : array [Indice] of Indice; ult : Cantidad; end; Natural = 0..MaxInt; function PosMin (idx: SecOfInd; i: Indice; s: SecOfChar): Cantidad; { Devuelve la posicion en el indice idx del menor caracter en s, para las posiciones >= i. } var j: Indice; pm: Cantidad; begin if i > [Link] then pm := 0 else begin

pm := i; for j := i+1 to [Link] do if [Link][[Link][j]] < [Link][[Link][pm]] then pm := j; end; PosMin := pm; end; procedure Swap (var idx: SecOfInd; i,j: Indice); { Intercambia las posiciones i j en idx. } var tmp: Indice; begin if (i<=[Link]) and (j<=[Link]) then begin tmp := [Link][i]; [Link][i] := [Link][j]; [Link][j] := tmp; end; end; procedure InicInds (var idx: SecOfInd; cant: Indice); { Construye la secuencia de indices 1,2,3,...,n. Sera el indice inicial para el ordenamiento de una secuencia de caracteres c1,c2,...,cn. } var n: Natural; begin n := cant; [Link] := n; while n > 0 do begin [Link] [n] := n;

n := n-1; end; end; procedure InicSecChar (var s: SecOfChar); { Devuelve la secuencia vacia. } begin [Link] := 0; end; function Llena (s: SecOfChar): Boolean; begin Llena := [Link] = Max; end; { PRE: not Llena(s) } procedure InsCar (var s: SecOfChar; c: char); { Inserta el caracter c en la secuencia s } begin [Link] := [Link] + 1; [Link] [[Link]] := c; end; procedure IndSelSort (s: SecOfChar; var ind: SecOfInd); { Construye el indice que ordena la secuencia s. Ordena el indice inicial 1,2, ..., n por el metodo de selection sort } var i: Indice; begin InicInds (ind, [Link]); for i := 1 to [Link]-1 do begin

Swap (ind, i, PosMin (ind, i, s)); end end; procedure WriteSorted (idx: SecOfInd; s: SecOfChar); { Imprime en la salida estandar la secuencia s ordenada segun el indice idx } var i: Indice; begin write ('Ordenado: '); for i := 1 to [Link] do write ([Link][[Link][i]],' '); writeln; end; procedure LeerCar (var c: char; var ok: boolean; sep: Char); { Lee de la entrada estandar un caracter seguido del caracter sep } var c1, c2: char; begin c := ReadKey; write (c); c1 := ReadKey; write (c1); ok := c1 = sep; end; procedure LeerSecOfChar (var s: SecOfChar; cant: Natural; var ok: Boolean); { Construye una secuencia de cant caracteres provistos por el procedimeinto LeerCar. Si cant > Max trunca. } var bien: Boolean; i: Natural;

10

ch, sep: Char; begin writeln ('Ingrese ',cant, ' caracteres separados por blancos. Enter para terminar '); write (' > '); InicSecChar (s); i := 1; ok := true; sep := Espacio; while ok and (i <= cant) and not Llena (s) do begin if i = cant then sep := Enter; LeerCar (ch, bien, sep); i := i+1; ok := ok and bien; if ok then InsCar (s, ch); end; end; procedure LeerCant (var n: Natural); { Lee de la entrada estandar un natural <= Max } begin repeat writeln ('Ingrese cantidad de caracteres (<=',Max,')'); write (' > '); readln (n); until n <= Max;

11

end; procedure Continuar (var seguir: Boolean); var car: Char; begin writeln; writeln ('Otro ? (s/n)'); write (' > '); car := ReadKey; writeln (car); seguir := car in ['s','S']; end; var cant: Natural; cars: SecOfChar; inds: SecOfInd; seguir, ok: boolean; begin repeat ClrScr; LeerCant (cant); LeerSecOfChar (cars, cant, ok); if ok then begin IndSelSort (cars, inds); writeln; WriteSorted (inds, cars); end else begin

12

writeln; writeln ('Error en los datos'); end; Continuar (seguir); until not seguir; end.

QBasic
Qbasic es un lenguaje de alto nivel, el cual consiste en instrucciones que los humanos pueden relacionar y entender. El compilador de Qbasic se encarga de traducir el mismo a lenguaje de mquina. Un programa es una secuencia de instrucciones. El proceso de ejecutar esas instrucciones se llama correr el programa. Los programas contienen las funciones de entrada, procesamiento y salida. La persona que resuelve problemas mediante escribir programas en la computadora se conoce como programador. Despus de analizar el problema y desarrollar un plan para solucionarlo, escribe y prueba el programa que instruye a la computadora como llevar a cabo el plan. El procedimiento que realiza el programador se define como "problem solving". Pero es necesario especificar que un programador y un usuario no son lo mismo. Un usuario es cualquier persona que use el programa. Ejemplo de qbasic, para hacer una calculadora DIM total AS DOUBLE DIM number AS DOUBLE DIM secondNumber AS DOUBLE DIM more AS STRING DIM moreNumbers AS STRING DIM operation AS STRING total = 0 more = "y" moreNumbers = "c" CLS WHILE more = "y" INPUT "Enter the first number"; number

13

total = number WHILE moreNumbers = "c" COLOR 14 PRINT "The total is:"; total COLOR 7 PRINT "Select an operation" COLOR 2 PRINT "(+)" COLOR 5 PRINT "(-)" COLOR 1 PRINT "(x)" COLOR 4 INPUT "(/)"; operation COLOR 7 CLS IF operation = "+" THEN REM where we do additions PRINT "Enter the number to Add to"; total INPUT secondNumber total = secondNumber + total COLOR 14 PRINT "The total is now:"; total COLOR 7 ELSE IF operation = "-" THEN

14

REM subtraction PRINT "Enter the number to Subtract from"; total INPUT secondNumber total = total - secondNumber COLOR 14 PRINT "The total is now:"; total COLOR 7 ELSE IF operation = "x" THEN REM multiplication PRINT "Enter the number to Multiply"; total; "by" INPUT secondNumber total = secondNumber * total REM * is the multiplication sign in programs COLOR 14 PRINT "The total is now:"; total COLOR 7 ELSE IF operation = "/" THEN REM division PRINT "Enter the number to Divide"; total; "by" INPUT secondNumber IF secondNumber = 0 THEN COLOR 4 PRINT "You cannot divide by zero" COLOR 7

15

ELSE total = total / secondNumber REM / is the division sign in programs END IF COLOR 14 PRINT "The total is now:"; total COLOR 7 ELSE PRINT "you must select an operation" END IF END IF END IF END IF INPUT "Do you wish to continue (c) or start with new numbers (n)";moreNumbers CLS WEND COLOR 14 PRINT "The grand total is:"; total COLOR 7 INPUT "Do you wish to make more calculations (y - n)"; more moreNumbers = "c" REM if we don't put "moreNumbers" back to y, it will always REM come back to "Do you wish to make more calculations" and never REM ask for numbers again

16

REM (try it) total = 0 REM if we don't reset the total to 0, it will just REM keep on adding to the total WEND END

Ensamblador
Cuando abstraemos los opcodes y los sustituimos por una palabra que sea una clave de su significado, a la cual comnmente se le conoce como mnemnico , tenemos el concepto de Lenguaje Ensamblador. As, podemos definir simplemente al Lenguaje Ensamblador de la siguiente forma: Lenguaje Ensamblador es la primera abstraccin del Lenguaje de Mquina, consistente en asociar a los opcodes palabras clave que faciliten su uso por parte del programador Como se puede ver, el Lenguaje Ensamblador es directamente traducible al Lenguaje de Mquina, y viceversa; simplemente, es una abstraccin que facilita su uso para los seres humanos. Por otro lado, la computadora no entiende directamente al Lenguaje Ensamblador; es necesario traducirle a Lenguaje de Mquina. Originalmente, este proceso se haca a mano, usando para ello hojas donde se escriban tablas de programa similares al ejemplo de la calculadora que vimos arriba . Pero, al ser tan directa la traduccin, pronto aparecieron los programas Ensambladores, que son traductores que convierten el cdigo fuente (en Lenguaje Ensamblador) a cdigo objeto (es decir, a Lenguaje de Mquina). Una caracterstica que hay que resaltar, es que al depender estos lenguajes del hardware, hay un distinto Lenguaje de Mquina (y, por consiguiente, un distinto Lenguaje Ensamblador) para cada CPU. Por ejemplo, podemos mencionar tres lenguajes completamente diferentes, que sin embargo vienen de la aplicacin de los conceptos anteriores: [Link] Ensamblador de la familia Intel 80x86 [Link] Ensamblador de la familia Motorola 68000 [Link] Ensamblador del procesador POWER, usado en las IBM RS/6000. Tenemos 3 fabricantes distintos, compitiendo entre s y cada uno aplicando conceptos distintos en la manufactura de sus procesadores, su arquitectura y programacin; todos estos aspectos, influyen en que el lenguaje de mquina y ensamblador cambie bastante. Ventajas y desventajas del Lenguaje Ensamblador Una vez que hemos visto la evolucin de los lenguajes, cabe preguntarse: En estos tiempos "modernos", para qu quiero el Lenguaje Ensamblador? El proceso de evolucin trajo consigo algunas desventajas, que ahora veremos como las ventajas de usar el Lenguaje Ensamblador, respecto a un lenguaje de alto nivel: [Link]

17

[Link] de tamao [Link] Por otro lado, al ser un lenguaje ms primitivo, el Ensamblador tiene ciertas desventajas respecto a los lenguajes de alto nivel: [Link] de programacin [Link] fuente grandes [Link] de afectar recursos inesperadamente [Link] de portabilidad Velocidad El proceso de traduccin que realizan los intrpretes, implica un proceso de cmputo adicional al que el programador quiere realizar. Por ello, nos encontraremos con que un intrprete es siempre ms lento que realizar la misma accin en Lenguaje Ensamblador, simplemente porque tiene el costo adicional de estar traduciendo el programa, cada vez que lo ejecutamos. De ah nacieron los compiladores, que son mucho ms rpidos que los intrpretes, pues hacen la traduccin una vez y dejan el cdigo objeto, que ya es Lenguaje de Mquina, y se puede ejecutar muy rpidamente. Aunque el proceso de traduccin es ms complejo y costoso que el de ensamblar un programa, normalmente podemos despreciarlo, contra las ventajas de codificar el programa ms rpidamente. Sin embargo, la mayor parte de las veces, el cdigo generado por un compilador es menos eficiente que el cdigo equivalente que un programador escribira. La razn es que el compilador no tiene tanta inteligencia, y requiere ser capaz de crear cdigo genrico, que sirva tanto para un programa como para otro; en cambio, un programador humano puede aprovechar las caractersticas especficas del problema, reduciendo la generalidad pero al mismo tiempo, no desperdicia ninguna instruccin, no hace ningn proceso que no sea necesario. Para darnos una idea, en una PC, y suponiendo que todos son buenos programadores, un programa para ordenar una lista tardar cerca de 20 veces ms en Visual Basic (un intrprete), y 2 veces ms en C (un compilador), que el equivalente en Ensamblador. Por ello, cuando es crtica la velocidad del programa, Ensamblador se vuelve un candidato lgico como lenguaje. Ahora bien, esto no es un absoluto; un programa bien hecho en C puede ser muchas veces ms rpido que un programa mal hecho en Ensamblador; sigue siendo sumamente importante la eleccin apropiada de algoritmos y estructuras de datos. Por ello, se recomienda buscar optimizar primero estos aspectos, en el lenguaje que se desee, y solamente usar Ensamblador cuando se requiere ms optimizacin y no se puede lograr por estos medios. Tamao Por las mismas razones que vimos en el aspecto de velocidad, los compiladores e intrpretes generan ms cdigo mquina del necesario; por ello, el programa ejecutable crece. As, cuando es importante reducir el tamao del ejecutable, mejorando el uso de la memoria y teniendo tambin beneficios en velocidad, puede convenir usar el lenguaje Ensamblador. Entre los programas que es crtico el uso mnimo de memoria, tenemos a los virus y manejadores de dispositivos (drivers). Muchos de ellos, por supuesto, estn escritos en lenguaje Ensamblador. Flexibilidad

18

Las razones anteriores son cuestin de grado: podemos hacer las cosas en otro lenguaje, pero queremos hacerlas ms eficientemente. Pero todos los lenguajes de alto nivel tienen limitantes en el control; al hacer abstracciones, limitan su propia capacidad. Es decir, existen tareas que la mquina puede hacer, pero que un lenguaje de alto nivel no permite. Por ejemplo, en Visual Basic no es posible cambiar la resolucin del monitor a medio programa; es una limitante, impuesta por la abstraccin del GUI Windows. En cambio, en ensamblador es sumamente sencillo, pues tenemos el acceso directo al hardware del monitor. Resumiendo, la flexibilidad consiste en reconocer el hecho de que Todo lo que puede hacerse con una mquina, puede hacerse en el lenguaje ensamblador de esta mquina; los lenguajes de alto nivel tienen en una u otra forma limitantes para explotar al mximo los recursos de la mquina. Tiempo de programacin Al ser de bajo nivel, el Lenguaje Ensamblador requiere ms instrucciones para realizar el mismo proceso, en comparacin con un lenguaje de alto nivel. Por otro lado, requiere de ms cuidado por parte del programador, pues es propenso a que los errores de lgica se reflejen ms fuertemente en la ejecucin. Por todo esto, es ms lento el desarrollo de programas comparables en Lenguaje Ensamblador que en un lenguaje de alto nivel, pues el programador goza de una menor abstraccin. Programas fuente grandes Por las mismas razones que aumenta el tiempo, crecen los programas fuentes; simplemente, requerimos ms instrucciones primitivas para describir procesos equivalentes. Esto es una desventaja porque dificulta el mantenimiento de los programas, y nuevamente reduce la productividad de los programadores. Peligro de afectar recursos inesperadamente Tenemos la ventaja de que todo lo que se puede hacer en la mquina, se puede hacer con el Lenguaje Ensamblador (flexibilidad). El problema es que todo error que podamos cometer, o todo riesgo que podamos tener, podemos tenerlo tambin en este Lenguaje. Dicho de otra forma, tener mucho poder es til pero tambin es peligroso. En la vida prctica, afortunadamente no ocurre mucho; sin embargo, al programar en este lenguaje vern que es mucho ms comn que la mquina se "cuelgue", "bloquee" o "se le vaya el avin"; y que se reinicialize. Por qu?, porque con este lenguaje es perfectamente posible (y sencillo) realizar secuencias de instrucciones invlidas, que normalmente no aparecen al usar un lenguaje de alto nivel. En ciertos casos extremos, puede llegarse a sobreescribir informacin del CMOS de la mquina (no he visto efectos ms riesgosos); pero, si no la conservamos, esto puede causar que dejemos de "ver" el disco duro, junto con toda su informacin. Falta de portabilidad Como ya se mencion, existe un lenguaje ensamblador para cada mquina; por ello, evidentemente no es una seleccin apropiada de lenguaje cuando deseamos codificar en una mquina y luego llevar los programas a otros sistemas operativos o modelos de computadoras. Si

19

bien esto es un problema general a todos los lenguajes, es mucho ms notorio en ensamblador: yo puedo reutilizar un 90% o ms del cdigo que desarrollo en "C", en una PC, al llevarlo a una RS/6000 con UNIX, y lo mismo si despus lo llevo a una Macintosh, siempre y cuando est bien hecho y siga los estndares de "C", y los principios de la programacin estructurada. En cambio, si escribimos el programa en Ensamblador de la PC, por bien que lo desarrollemos y muchos estndares que sigamos, tendremos prcticamente que reescribir el 100 % del cdigo al llevarlo a UNIX, y otra vez lo mismo al llevarlo a Mac.

20

Programacin en C
Para familiarizarnos con el lenguaje C lo mejor es comenzar haciendo pequeos programas. El objetivo ser dar una primera impresin de como trabaja el C, sin profundizar demasiado en todas sus caractersticas. En esta primera parte se abordarn los mtodos que son comunes a todos los lenguajes de programacin estructurada. Los programas en C estn formados por una serie de lneas de cdigo que se ejecutan sucesivamente. Todos los programas se dividen en bloques. Cada bloque de cdigo se encierra en funciones. La ejecucin del programa siempre comienza en la funcin main(). Esta funcin es la encargada de llamar a las dems. Para escribir la funcin main se coloca al principio de la funcin el siguiente cdigo: main() { Luego escribimos todas las lneas de cdigo. A cada lnea de cdigo le llamaremos sentencia. Despus de cada sentencia escribiremos un ';'. En C todas las sentencias acaban con un . Hay varios tipos de sentencia. Las ms comunes la llamada a una funcin. Cuando hace esto el programa llama a la funcin. Entonces se ejecuta el cdigo de la funcin. Cuando la funcin finaliza la ejecucin devuelve el control a la funcin main(). Las funciones son muy difciles de reconocer, pues a continuacin de su nombre van los parntesis. Para acabar el cdigo de una funcin siempre escribiremos al principio de una nueva lnea una llave de cierre '}'. Por ejemplo: #include <stdio.h> main() { printf("hola, mundo\n"); } En este programa la funcin main consta de una sola sentencia, que es la llamada a la funcin printf(). La funcin printf imprime en la salida habitual, que generalmente es el terminal en el que trabajamos, el mensaje que le demos. El mensaje que queremos imprimir es hola, mundo, seguido de un avance del cursor al principio de la lnea siguiente. El mensaje lo debemos encerrar entre comillas ", para que el compilador sepa cual es su longitud. La funcin printf() es una funcin que pertenece a la librera estndar del C. Esta librera tiene un conjunto muy amplio de funciones listas para usar, lo que nos evitar el trabajo de usarlas. Para

21

usar esta librera debemos avisar al compilador. Por ello incluimos como primera lnea del programa la lnea #include <stdio.h>. En esta librera hay un montn de funciones tiles. Para comenzar daremos una lista de alguna de ellas, con una pequea explicacin de lo que hacen, aunque no nos extenderemos en su uso. Cuando comencemos a usarlas rpidamente nos daremos cuenta de su uso. Estas funciones son: printf(mensaje) imprime un mensaje en el terminal putchar(carcter) escribe un carcter en el terminal getchar() recoge un carcter del terminal scanf(variables) lee variables del terminal gets() lee una lnea del terminal De estas funciones, printf() y scanf() son las mas complicadas de usar, y las que admiten ms posibilidades de funcionamiento. De echo son unas de las mas complicadas de la librera estndar. Estructura de un programa en C Un programa en C es simplemente un fichero de caracteres que contiene un conjunto de instrucciones que un programa especial, el compilador o traductor, se encargar de transformar en un programa que la computadora pueda ejecutar. Un programa normalmente suele estar compuesto de tres partes: la seccin de variables, que especifica los datos y sus tipos que vamos a manejar a lo largo del programa. la funcin principal, que se suele llamar "main", que ser la que defina la estructura del programa. las funciones o subrutinas auxiliares, que son llamados por la rutina principal, la funcin main. Estas subrutinas se suelen colocar despus de la funcin main. Cuando la envergadura del programa es grande se suele fragmentar el programa en varias partes, incluyendo cada parte en un fichero separado. El lenguaje C define el mtodo que debemos seguir para separar las diferentes partes del programa. Normalmente colocaremos en cada fichero todas las subrutinas y funciones que se encarguen de una tarea del programa. As la funcin main ir "llamando" a las subrutinas a medida que las vaya necesitando. Un primer vistazo a la programacin estructurada: las funciones

22

Como hemos visto en C los programas constan de una rutina principal, de nombre main y una serie de subrutinas asociadas. En C las rutinas se crean mediante una funcin. Una funcin es un fragmento de cdigo que realiza una tarea. En C las funciones siempre tienen un nombre, que viene dado por un identificador. Por ejemplo main es el identificador de la funcin main, que es la rutina principal de todo programa en C. Para escribir la funcin main solo tenemos que colocar al principio de una lnea su identificador, seguido de los caracteres '(' y ')'. Es costumbre entre los programadores de C de escribir el primer parntesis pegado al identificador de la funcin, ya que facilita enormemente su clasificacin como funcin. En realidad esto no es necesario ya que el compilador salta los espacios automticamente. A continuacin del ultimo parntesis se escribe el carcter de abrir llaves '{' . Tambin es costumbre entre los programadores el escribir esta llave en la lnea siguiente, y no a continuacin del parntesis, aunque al compilador le da igual, y no protestar si introducimos o quitamos espacios en blanco. Recordemos que decamos que el C es un lenguaje de formato libre. A continuacin de la llave se escribe el cdigo de la funcin. Por ltimo, al principio de una nueva lnea debemos incluir otra llave '}', que servir de cierre de nuestra funcin. Un ejemplo de funcin main puede ser: main() { printf("Hola, mundo\n"); } Esta funcin casi constituye un programa completo, salvo que al intentar compilarlo el compilador se puede quejar y decirnos que no conoce el identificador printf. Si repasamos nuestra lista de palabras reservadas veremos que no aparecen ni la palabra main ni la palabra printf, sin embargo el sistema slo se quejar probablemente de la palabra printf. Esto se debe a que la palabra main suele estar predefinida como funcin en la mayora de los sistemas en C. La funcin printf simplemente imprime en la salida del sistema (generalmente la pantalla del usuario) la frase que le demos. La funcin printf forma parte de lo que se conoce como librera estndar del C. Con casi todos los compiladores se suele incluir un conjunto de funciones predefinidas que realizan las funciones mas usuales de los lenguajes de programacin: entrada y salida de datos por pantalla, creacin y manipulacin de ficheros y otras muchas funciones. En esto el lenguaje C es muy potente, pues la librera estndar es muy amplia. Para avisar al compilador que vamos a usar la funcin printf simplemente debemos aadir una lnea al principio de nuestro programa, quedando ahora el programa como sigue: #include <stdio.h> main() { printf("Hola, mundo\n"); } Este es ya un programa completo en C, uno de los ms simples que se pueden crear. Simplemente escribe un mensaje de salida en nuestro terminal. El significado de sus partes se ir viendo ms adelante.

23

El cdigo de un programa en C El C es un lenguaje de formato libre. Esto quiere decir que consiste en que un programa est formado por comandos que estn separados por espacios en blanco y tambin. Para ello el C considera como espacios en blanco, no slo el carcter blanco ' ', sino tambin el carcter de tabulador '\t' y el carcter de nueva lnea '\n' o '\r'. El numero de espacios que empleemos no vara el significado del programa. Aunque al compilador del lenguaje le da igual el nmero de espacios en blanco que insertemos entre los comandos, por motivos de legibilidad seguiremos una serie de normas. La primera de ellas hace referencia a los comentarios. Un comentario es una lnea que se incluye en el programa, cuya misin consiste en aclarar la funcin de una parte concreta del programa a otro lector, o incluso al mismo programador. En C hay dos formas de incluir estos comentarios. La primera es incluir el texto que sirve de comentario al principio de la seccin, entre dos smbolos especiales: el /* o principio de comentario y el */ o fin de comentario. Todo el texto que incluyamos entre ellos el compilador lo ignorar , incluyendo los saltos de lnea. Por ejemplo si una seccin del programa se encarga de ofrecer los resultados finales del programa, podramos incluir en el cdigo el siguiente comentario: /* esta seccin se encarga de imprimir los datos en la impresora asignada */ Y aqu ira el resto del programa. El otro tipo de comentarios se suele usar para sealar una determinada lnea del programa. Para ello escribimos el comentario a la derecha de la lnea a comenta. Por ejemplo, si en una lnea aparece el comando gets(), podramos poner a la derecha en un comentario lo que hace: gets(linea); /* recoge una lnea del teclado */ Este tipo de comentario es el que usaremos en muchas de la explicaciones de ahora en adelante. La seccin de variables globales Normalmente en todo programa en C hay una seccin de variables globales. En las variables globales almacenaremos datos que deben ser accesibles a todo el programa. Cuando el programa es pequeo, por ejemplo si consta de un slo fichero, por comodidad se suelen definir todas las variables como globales. Esto tiene como ventaja que no deberemos definir el tipo de las variables en las funciones auxiliares, ya que ser n directamente visibles para ellas. Como inconveniente tenemos que al ser las variables globales accesibles por todas las funciones podremos modificarlas por error, por lo que pueden aparecer errores difciles de depurar. La mejor estrategia es dejar como variables globales slo las estrictamente necesarias, definiendo en cada funcin las variables que necesitemos. La funcin main Si el programa es pequeo es probable que la mayor parte del programa se halle dentro de la funcin main. Cuando el programa comienza a tener un tamao mayor conviene dejar para la funcin main slo el cuerpo del programa. Al principio de la funcin main colocaremos todas las rutinas de inicializacin. Si vamos a manejar algn fichero a lo largo del programa la funcin main es un buen lugar para abrirlo. Tambin se suele procesar en la funcin main los mensajes de bienvenida, en los que se muestra el nombre del autor y dems informacin. Si el programa admite par metros en la lnea de rdenes, la funcin main debe procesarlos, ya que la funcin main tiene normalmente acceso a la lnea de argumentos con que fue ejecutado el programa.

24

Las variables El siguiente paso para programar en C consiste en presentar las variables. Las variables permiten guardar informacin. Los principales tipos de datos son los datos numricos, los caracteres y las cadenas de caracteres. En principio situaremos las variables al principio del programa. Para utilizar una variable situaremos antes de la funcin main el nombre de la variable precedido de su tipo. En principio vamos a usar tres tipos de variables: los enteros, cuyo especificador de tipos es la palabra reservada int, los caracteres, cuya palabra reservada es char, y las cadenas de caracteres, cuyo especificador de tipo es char *. Los enteros son cualquier nmero positivo o negativo sin decimal, de digamos "tamao pequeo". Los caracteres son letras, nmeros, signos de puntuacin y algn carcter especial, como el fin de lnea y la campanilla. Las cadenas de caracteres son un conjunto de caracteres, de cualquier longitud encerado entre comillas dobles". Comencemos creando un programa con una variable numrica, numero1: #include <stdio.h> int numero1 = 1; main() { printf("numero1 vale %d\n", numero1); } Como siempre, haremos el programa siguiendo la estructura que hemos seguido. Observar que al crear la variable le hemos colocado un = 1. Esto permite almacenar un 1 en nuestra variable. Luego dentro de la funcin main salo tenemos que llamar a printf() para imprimir nuestra variable. Aqu ya empezamos a ver complicaciones en el uso de printf(). Printf coge nuestra cadena de caracteres numero1 vale %d\n. El %d indica que printf debe insertar en el mensaje el valor de la variable que a continuacin le demos, en nuestro caso numero1. El carcter \n es un carcter especial, el de nueva lnea, y le dice a printf() que debe avanzar el cursor al principio de la lnea siguiente. El valor de las variables es, como su propio nombre indica, variable. Podemos alterar su valor en cualquier punto del programa. La forma mas sencilla de hacerlo es mediante una sentencia de asignacin. Para asignar un nombre a una variable se escribe su identificador seguido de un = y el nuevo valor. Este tipo de sentencia es el segundo ms importante. As: #include <stdio.h> int i = 1; main() { printf("el antiguo valor de i es %d\n", i); i = 2;

25

printf("el nuevo es %d\n", i); } El lado derecho de una asignacin es una expresin. Una expresin es otro tipo de sentencia, quiz s el tercero ms importante. Una expresin es una sentencia que al ser evaluada devuelve un valor. Los tipos de expresiones ms frecuentes son las operaciones aritmticas: suma, resta, multiplicaciones y divisiones. Para escribir una expresin aritmtica usaremos una notacin similar a la usada en las calculadoras, incluyendo el uso de parntesis. Por ejemplo: #include<stdio.h> int i; main() { i = 2 + 2; printf(" 2 + 2 = %d\n" , i); } Otros ejemplos de operaciones aritmticas son: i = 2 * 2 + 6; i = 2 * (2+ 6); i = 1 - 4 / 2; Observar que el * y el / tienen mayor "precedencia" que el + y el -, es decir al evaluar la expresin se evala antes un * y un - que un + o un -. El tema de la evaluacin de expresiones es mas complejo, y lo dejaremos para un captulo mas avanzado. Adems contamos con otro tipo de expresiones, el resultado de llamar a una funcin. Lo veremos mejor con el tipo de variable carcter. Las variables de tipo carcter se emplean de modo anlogo a las de tipo entero, salvo que ahora almacenan un carcter. En el siguiente ejemplo crearemos una variable y despus de imprimirla la asignaremos el resultado de una expresin del tipo llamada a funcin. Utilizaremos la funcin getchar() que devuelve el siguiente carcter disponible desde el terminal. #include <stdio.h> char c = 'a' ; main() {

26

putchar(c); putchar('\n'); printf("introduce un carcter por el terminal\n"); c = getchar(); printf("el primer carcter que has "); printf("introducido es: %c\n", c); } Observar que el modificador para imprimir un carcter con printf() es %c. Si sustituimos este modificador por el %d se imprimir el cdigo ASCII del carcter introducido. Aqu ya podemos observar una caracterstica muy importante del C, que es la equivalencia de tipos. El tipo de datos entero y el tipo de datos carcter son intercambiables, es decir, si una expresin espera un entero y le damos un carcter y le damos un entero, el compilador promocionar el carcter a entero. Esto siempre es posible. El proceso inverso tambin se puede hacer. Si a una variable de tipo carcter y le damos un entero el compilador tratar de meterlo como pueda. Si el entero es pequeo esto se har sin problemas. Si el entero es grande, el compilador truncar el entero, es decir, le cortar un trozo. El proceso de truncado se ve mejor usando representacin binaria. Los caracteres se suelen representar mediante bytes, es decir 8 bits. Los enteros suelen ser dos o cuatro bytes. El compilador para pasar de un carcter a entero simplemente le aade un byte a cero. Para pasar de entero a carcter el compilador se olvida de todos los bytes salvo el de menor orden. Por eso la conversin entre tipos funciona la mayora de las ocasiones. As la funcin getchar() devuelve un entero, no un carcter. Esto se hace as por otro motivo un poco ms oscuro, relacionado con el fin de fichero, que explicaremos al tratar el tema de los ficheros. No obstante, la funcin getchar() funciona sin complicaciones. As mismo la funcin putchar() admite un carcter o un entero, pero siempre los imprime como carcter. Cadenas de caracteres y arreglos. Las cadenas de caracteres nos permiten manejar texto con facilidad. Ya hemos visto que la funcin printf nos permite sacar una cadena por pantalla. Esto nos hace pensar que las cadenas de caracteres pueden servir para almacenar tiras de caracteres, como nombres o texto. Sin embargo poseen una pega: son constantes, por lo que no se pueden alterar. Para almacenar grupos de caracteres utilizaremos los arreglos de caracteres. Identificadores y palabras reservadas El lenguaje C est formado por un conjunto pequeo de palabras clave o comandos y una serie de operadores. Hay cerca de 40 palabras claves, frente a las 150 del BASIC o 200 que poseen otros lenguajes, como el COBOL y el PASCAL. Estas palabras son: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct typedef union unsigned void volatile while

27

A este conjunto de palabras se les denomina "palabras reservadas". Cuando en el C creemos nuestras propias subrutinas y conjuntos de datos les deberemos poner nombres. Para nombrar las funciones (subrutinas) y variables (datos) utilizaremos los identificadores. Un identificador es un conjunto de caracteres alfanumricos (letras y nmeros) que comienzan siempre por una letra. Para formar un identificador usaremos indiferentemente maysculas y minsculas, nmeros y tambin el carcter '_' (subrayado), aunque este carcter tiene un significado especial, por lo que en principio debemos evitar su uso. Como identificador vale cualquier secuencia de letras y nmeros, de cualquier longitud, pero con dos limitaciones: no podemos empezar con un nmero las palabras reservadas no se pueden usar como identificador, aunque un identificador puede comenzar con una palabra reservada. De aqu la denominacin de palabras reservadas. Ejemplos de identificadores validos seran: hola hola127 printf whiledo Variables Una variable es un lugar donde se puede almacenar temporalmente un dato. En C las variables tienen un nombre que las identifica, y sirve para hacer referencia a ellas. Tambin tienen un tipo, que es el tipo de datos que puede almacenar. Por ejemplo podemos tener una variable de tipo entero de nombre num. Observar que para dar un nombre a una variable tenemos que usar un identificador. Para crear una variable en un lugar determinado del un programa escribiremos primero el tipo de variable y luego el identificador con el que queremos nombrar la variable, seguido todo de un ';'. Por ejemplo: int numero; /* crea la variable numero de */ /* tipo entero */ char caracter1; /* crea una variable de tipo caracter1 */ las variables se pueden inicializar, es decir, darles un valor inicial, en el momento de creacin. Para ello detrs del identificador ponemos el caracter1 '=' seguido del valor inicial. Los valores iniciales pueden ser cualquier constante vlida para el tipo de variable que creemos. Por ejemplo: int numero = 0; /*crea la variable entera numero */ /* y la inicializa a 0*/ char c = 'a'; /* crea una variable caracter1 y */

28

/* la inicializa a 'a' */ Duracin de las variables Las variables pueden ser de dos tipos: estticas y dinmicas. Las estticas se crean al principio del programa y duran mientras el programa se ejecute. Las variables son dinmicas si son creadas dentro de una funcin. Su existencia est ligada a la existencia de la funcin. Se crean cuando la funcin es llamada y se destruyen cuando la funcin o subrutina devuelve el control a la rutina que la llam. Las variables estticas se utilizan para almacenar valores que se van a necesitar a lo largo de todo el programa. las variables dinmicas se suelen utilizar para guardar resultados intermedios en los clculos de las funciones. Como regla general una variable es esttica cuando se crea fuera de una funcin y es dinmica cuando se crea dentro de una funcin. Por ejemplo en el siguiente programa : #include <stdio.h> int numero1 = 1; main() { int numero2 = 2; printf("%d, %d\n", numero1, numero2); } hemos creado la variable esttica numero1, que dura todo el programa, y la variable numero2, que dura slo mientras se ejecuta la funcin main(). En este programa tan pequeo , la funcin main() es la que ocupa todo el tiempo de ejecucin, por lo que no apreciaremos diferencia en el uso de ambas, aunque ms adelante si se ver su uso. Alcance de las variables Otra caracterstica de las variables es su alcance. El alcance se refiere a los lugares de un programa en los que podemos utilizar una determinada variable. Distinguiremos as dos tipos principales de variables: globales y locales. Una variable es global cuando es accesible desde todo el programa, y es local cuando solo puede acceder a ella la funcin que la creo. Tambin hay una norma general para el alcance de las variables: una variable es global cuando se define fuera de una funcin, y es local cuando se define dentro de una funcin. En nuestro ejemplo anterior numero1 es una variable global y numero2 es una variable local. Dentro de las variables globales hay dos tipos: las que son accesibles por todos los ficheros que componen nuestro programa y las que son accesibles solo por todas las funciones que componen un fichero. Esto es debido a que normalmente los programas en C se fragmentan en mdulos ms

29

pequeos, que son mas fciles de manejar y depurar. Por ello hay veces que nos interesar que una variable sea accesible desde todos los mdulos, y otras solo queremos que sea accesible por las funciones que componen un determinado modulo. Por defecto todas las variables globales que creemos son accesibles por todos los ficheros que componen nuestro programa. Modificadores de tipo Podemos fcilmente modificar el alcance y la duracin de una variable que tiene asignado por defecto: Esto es una operacin muy comn y til. Para hacerlo antepondremos al tipo de la variable un modificador, que es una palabra reservada, que cambiar estas caracterstica. El primer modificador es la palabra clave static. Cuando a una variable local se le aade el modificador static pasa de ser dinmica a ser esttica. As la duracin de la variable se ampla a la duracin del programa completo. Observar que una variable esttica solo se crea una vez, al principio del programa, por lo que la inicializacin solo se produce una vez para una variable esttica. Adems el modificador static tiene otro uso. Si aadimos este modificador a una variable global, definida fuera de una funcin, entonces modificamos su alcance: pasa de tener alcance global a todos los ficheros del programa a ser solo accesible por las funciones del fichero en el que se crea. Otro modificador usual es externa. Este modificador se usa cuando una variable que se creo en otro modulo se quiere usar en un modulo. Cuando aadimos a la variable este modificador el compilador queda advertido de que la variable ya existe en otro modulo, por lo que el compilador no tiene que crearla, sino simplemente usarla. Entonces a este tipo de proceso se le llama declaracin de tipo de variable. Por ejemplo: extern int numero; main() { printf("%d\n", numero); } es un programa en que declaramos la variable externa numero, que habremos creado en otro modulo. Una diferencia muy importante entre una definicin y una declaracin es que en la definicin no se reserva espacio en la memoria para la variable, y en la definicin si se crea. Hay otros modificadores que no son tan usuales: auto, volatile y register. El modificador auto indica que una variable local es dinmica (en la terminologa del C automtica). Observar que por defecto las variables locales a una funcin son automticas, por lo que no se usa. Sin embargo todos los compiladores la reconocen y no protestan si la usamos. Por ejemplo: main() { auto numero = 1;

30

printf("%d\n", numero); } crea una variable automtica entera. Si quitamos auto el programa no se diferencia. El modificador register se usa ms a menudo, sobre todo en la llamada "programacin de sistemas". Recordemos que el C fue creado para este tipo de programacin. Este modificador le pide al compilador que almacene la variable en un registro de la maquina, que es el lugar ms eficiente para guardar las variables. Esto se hace porque el trabajo con los registros del procesador es mucho ms r pido que el trabajo con la memoria central. Hay dos detalles importantes: normalmente no hay muchos registros libres en el procesador, pues el compilador los usa para otros propsitos. Entonces el modificador register es mas bien un ruego que una orden. Otro aspecto es que muchos compiladores realizan trabajos de optimizacin, que son modificaciones en el cdigo que generan que hace trabajar al programa ms deprisa. Aun as, en rutinas crticas, que deben ejecutarse deprisa se suele usar. El modificador volatile se usa para decirle que el contenido de la variable puede ser modificado en cualquier momento desde el exterior de nuestro programa, sin que podamos evitarlo. Lo que hace el modificador es instruir al compilador para que lea de nuevo el valor de la variable de la memoria cuando tenga que usarlo. Este modificador evita que el compilador no genere cdigo para optimizar la variable. Evidentemente el uso de volatile excluye el uso de register y viceversa. Ambos modificadores, register y voltiles se emplean de manera anloga al modificador auto. Tipos de datos en C Un programa normalmente lo que hace es procesar un conjunto de datos para obtener alguna conclusin de ellos. Pos ejemplo un programa de estadsticas recoge una serie de datos y elabora grficas que nos ayudan a tomar decisiones. En C los datos de una aplicacin se representa haciendo uso de un conjunto de datos predefinidos en el lenguaje. Distinguiremos para empezar tres tipos de datos fundamentales: caracteres, enteros y cadenas de caracteres (en ingles "strings"). El tipo de datos carcter consiste de un nico carcter y se suele representar por su carcter en cdigo ASCII situado entre apstrofes. Por ejemplo: 'p' /* la letra p minscula */ '1' /* el numero 1 */ ' ' /* el carcter en blanco */ Hay otras formas de representar caracteres, que se emplean cuando es un carcter que no se puede introducir directamente desde el teclado. Para ello debemos conocer su cdigo ASCII. Para representar el carcter de numero ascii 27, (el cdigo para el carcter ESCAPE), basta colocar el numero ascii en el sistema octal precedido de la barra atrs, y todo ello entre apstrofes, tal y como hacemos para los dems caracteres: '\27**' /* representa el cdigo ESCAPE, de ASCII 27 */ En C hay algunos caracteres especiales que se usan frecuentemente. Estos caracteres tiene una representacin especial. Algunos de ellos son:

31

'\n' /* carcter nueva lnea */ '\r' /* retorno de carro (carriage return) */ '\t' /* tabulador */ El siguiente tipo de datos es el entero. Consiste en un nmero sin parte decimal, aunque puede tener signo. Generalmente con el tipo de datos entero no representamos nmeros muy grandes. son ejemplos: 0 124 -2000 El tipo de datos entero nos permitir hacer operaciones aritmticas, como la suma y la multiplicacin. El tipo de datos entero es quizs el ms importante de todos los tipos de datos, y muchas veces es el tipo d datos por defecto, es decir, cuando el compilador se encuentre con un dato y no le hayamos dicho cual es su tipo supondr que es un entero. Esto se ve claramente con las funciones, ya que siempre devuelven un valor, que por defecto es un entero. El ltimo tipo de datos importante en C es la cadena de caracteres. Est formada por un conjunto de caracteres encerrados entre comillas. Podemos usar todos los caracteres del conjunto ASCII, incluso los especiales. Los caracteres normales se incluyen entre las comillas tal cual, sin necesidad de apstrofes, y los especiales se incluyen utilizando la representacin del C. Por ejemplo: "Hola, mundo\n" En este ejemplo observamos la cadena de caracteres "Hola, mundo", a la que hemos aadido un carcter de retorno de carro al final. El motivo de ello es que ms adelante cuando la imprimamos el carcter de retorno de carro \n actuar como un comando que obligar al cursor a avanzar una lnea y situarse al principio de la siguiente. Los tipos de datos carcter, entero y cadena no son los nicos que posee el lenguaje C, pero si los mas importantes. Como avance podemos decir que tambin posee el tipo de datos en coma flotante, que es el que usan las calculadoras cientficas, varios tipos da datos enteros, de diferente tamao, el tipo de datos entero sin signo, un tipo de datos cientfico de mayor precisin, y otros tipos de datos que sirven para fabricarnos un tipo de datos a medida de nuestra necesidad: arreglos, estructuras y uniones. Pero esto es un tema ms avanzado. Tipos de enteros El tipo de datos entero admite varias variantes, que le permiten representar cantidades ms grandes. Aunque el tamao de los enteros depende de la implementacin con la que estemos trabajando, suele ser habitual que tenga un tamao de 16 bits. Por ello el entero ms grande que se puede representar suele estar en torno al 32000. Cuando queremos alcanzar un nmero mas alto y no nos importa el signo le podemos pedir al compilador que el tipo de datos sea "sin signo". Esto se hace con la palabra reservada unsigned. As el tipo de datos entero sin signo se comporta como un nuevo tipo de datos. Podemos definir variables del tipo unsigned int, al igual que lo hacamos con enteros normales. Normalmente cuando nos referimos al tipo de datos sin signo nos estamos refiriendo al tipo entero sin signo.

32

Por ello cuando definamos un entero sin signo no har falta escribir la palabra reservada int. Un ejemplo de definicin con inicializacin de un unsigned es: unsigned u = 40000; Podramos tambin haber escrito unsigned int, pero no suele ser habitual. Si trabajamos con enteros de 16 bits, el nmero 40000 no cabria en un entero normal. Otro tipo de datos til es el entero largo, que anlogamente al entero sin signo se representa con la palabra reservada long. Las palabras long y unsigned son modificadores de tipo, ya que actan sobre uno de los tipos incorporados. Por ejemplo: long largo = 100000; define una variable de tipo entero largo. Hay ms modificadores de tipo. El modificador short hace referencia a un entero corto, de pequeo tamao. Hay que tener en cuenta que el tamao de cada tipo de datos depende del sistema. En C estndar un entero corto tiene al menos 16 bits. Muchas veces el entero corto y el entero coinciden. En los sistemas basados en microprocesadores de 32 bits suele ser frecuente encontrar enteros de 32 bits de anchos, por lo que no coinciden el entero corto y el entero. Adems tambin podemos definir enteros cortos y largos sin signo. Por ejemplo: unsigned short int u = 1; unsigned long l = 1000000; El signo de los caracteres Dependiendo del sistema el tipo de datos carcter puede tener signo o no. Normalmente es una cuestin que no posee relevancia, pero por si necesitsemos que el tipo de datos carcter lleve o no signo, podemos aplicarle dos modificadores: unsigned para caracteres sin signo, y signed para caracteres con signo. Tipos de datos en coma flotante Para representar nmeros decimales el C posee dos tipos de datos: nmeros en coma flotante con simple y doble precisin. El tipo de datos float corresponde al nmero de simple precisin. El tipo double representa a los de doble precisin. Expresiones Las expresiones son sentencias que tras realizar determinada una accin devuelven un resultado. En C la mayora de las expresiones devuelven un entero. Hay tres tipos de expresiones: Valores por la izquierda o lvalue (del ingles left value). Al evaluarlas devuelven la direccin de un cierto dato, que nos permitir acceder a l para inicializarlo, modificarlo, etc. Se llaman as porque son las expresiones que normalmente se colocan en el lado izquierdo del = en una expresin de asignacin. Suelen ser nombres de variables, elementos de un arreglo, etc.

33

Valores por la derecha o rvalue (del ingles right value). Al evaluarlas obtenemos un dato de cierto tipo. Normalmente son las expresiones que se colocan a la derecha del = en la asignacin. Ejemplos de ellos son los contenidos de las variables, los datos contenidos en los arreglos y los valores constantes. Llamada a una funcin. Si la funcin no es de tipo void, al llamarla devolver un dato. Este dato puede ser usado como una expresin del tipo valor por la derecha. Tipos de expresiones El primer tipo a considerar dada su importancia es la asignacin. La sintaxis de una asignacin es lvalue = rvalue; Para evaluar una asignacin el compilador evala el lado derecho. El dato que obtiene es entonces cargado en la direccin que resulta de evaluar el lado izquierdo. Por ejemplo: i = 1; introduce el entero 1 en la direccin de la variable i. Como toda expresin la asignacin devuelve un valor, que es el mismo que se carga en la variable. Esto puede ser usado para inicializar varias variables con el mismo valor. Por ejemplo, si tenemos tres variables enteras i, j y k: i = j = k = 0; las inicializa a las tres a 0. Observar que una misma variable puede estar en ambos lados de una asignacin: i = i + 1; incrementa la variable i en una unidad. El segundo tipo de expresiones son los operadores. Hay varios tipos de operadores: -operadores aritmticos: Son el +, - , *, % y /, que realizan las operaciones aritmticas bsicas. Estas expresiones tienen de sintaxis: rvalue operador rvalue Los operadores aritmticos son: + el operador de suma - el operador de resta * el la multiplicacin / la divisin entera % el resto de la divisin (operador modulo). Por ejemplo:

34

i = a + 1; j = b * 4 + 10 / 2; Operadores de incremento y decremento. Sirven para incrementar una cierta variable. Admiten cuatro posibles combinaciones: ++lvalue incrementa el contenido de lvalue y devuelve el contenido nuevo --lvalue decrementa el contenido de lvalue y devuelve el contenido nuevo lvalue++ incrementa el contenido de lvalue y devuelve el valor que contena antes de incrementarlo. lvalue-- decrementa el contenido de lvalue y devuelve el valor que contena antes de decrementarlo. Por ejemplo: i = j++; /* carga en i el valor de j y */ /* luego incrementa j */ i = ++j; /* incrementa j y luego carga su valor en i */ Estos operadores son muy usados en las variables de los bucles y con los punteros. El tipo de datos que devuelven es el del lvalue. Operadores de comparacin. Son: < "menor que" > "mayor que" <= "menor o igual que" >= "mayor o igual que" == "igual que" != "no igual que" La sintaxis para estas expresiones son: rvalue operador rvalue El valor que devuelve es de tipo entero: devuelve un 0 si el resultado de la comparacin es falso y un valor distinto de 0 si el resultado de la comparacin es verdadero. En C el cero se toma como valor falso, y cualquier valor diferente del cero es verdadero. El valor concreto empleado para

35

representar el valor verdadero es irrelevante, y normalmente depende del sistema empleado. Cuando lo que comparamos son caracteres, se compara realmente su cdigo ASCII. Por ejemplo: 1 > 2 devuelve un valor verdadero 1 == 1 devuelve un valor verdadero '1' == 1 devuelve falso 'a' < 'b' es verdadero Operadores lgicos Realizan las operaciones lgicas habituales en el lgebra de Bool. Realizan el AND (Y lgico), el OR (O lgico) y el NOT (negacin lgica). Son: && AND (Y lgico) || OR (O lgico) ! NOT (negacin lgica Los dos primeros son operadores binarios y el tercero es un operador unario. Su sintaxis es: expresion1 && expresion2 expresion1 || expresion2 !expresion1 El resultado de evaluar la expresin AND es verdadero si ambos son verdaderos, y falso en caso contrario. El resultado de evaluar la expresin OR es verdadero si alguna o las dos expresiones es verdadera. Es falsa si las dos expresiones son falsas. El resultado de la expresin NOT es falso si la expresin es verdadera, y verdadero si la expresin es verdadera. Para evaluar estos operadores se toma como verdadero un valor de la expresin distinto de 0 y como falso un valor 0. Control del flujo del programa En C las sentencias se ejecutan sucesivamente una tras otra. Esto define un camino o direccin segn la cual se va desarrollado el programa. Sin embargo, habr momentos en que el programa deba ejecutar determinadas partes dependiendo del estado en el que se halle el programa o de las variables externas. Esto permitir modificar el orden de la ejecucin para adaptarse al estado del programa y bifurcar hacia nuevas subrutinas cuando se cumplan ciertas condiciones, que el programador fijar de antemano. La sentencia if La primera sentencia de control es la sentencia if. Admite dos tipos de sintaxis: if (expresin1)

36

sentencia1; o tambin: if (expresin1) sentencia1; else sentencia2; Esta sentencia es equivalente a la que poseen la mayora de lenguajes de programacin y sirve para bifurcar en un punto de programa. la sentencia if permite tomar decisiones al programa. En su primera forma la sentencia1 slo se ejecuta si el resultado de evaluar la expresin1 es verdadero (distinto de cero). En la segunda forma tenemos dos posibilidades: si al evaluar la expresin1 el resultado es verdadero se ejecuta la sentencia1, pero si el resultado es falso se ejecuta la sentencia2. En cualquier caso slo una de las dos sentencias se ejecuta. Por ejemplo: if (numero1 == 1) puts("la variable numero1 vale 1"); else puts("la variable numero1 no vale 1"); Tras evaluarse la expresin if y ejecutarse la sentencia adecuada, el programa continua con la lnea siguiente a la de la ultima sentencia del if. Para la sentencia if vale como expresin cualquier expresin v lida en C, incluso las asignaciones y llamadas a funciones. El caso en que la expresin es una asignacin suele ser sorprendente, ya que en la mayora de los lenguajes este tipo de expresiones no es valido. Como sentencia vale cualquier tipo de sentencia v lida en C, entre ellas la propia sentencia if. En este caso hablaremos de sentencias if anidadas. Por ejemplo: if (num > 0) if (num == 1) puts("num es igual a 1") else puts("num es mayor que 1) else puts("num es menor que 1"); Cuando hay dos if anidados y a continuacin hay un else, este else pertenece al ultimo if. As en el caso anterior el primer else corresponde al segundo if. Si queremos que un else pertenezca al primer if de un if anidado deberemos encerrar al segundo entre parntesis. Por ejemplo:

37

if (num > 0) { if (num == 1) puts("num es igual a 1"); } else puts("num es menor que 0"); Cuando necesitamos ejecutar varias sentencias que depende de un if, utilizaremos la sentencia de tipo bloque de sentencias. Un bloque de sentencias es un grupo de sentencias encerradas entre llaves { y }. Por ejemplo: if (num >= 0) { printf("num %d\n"); if (num == 0) puts("num 0"); if (num >= 1) puts("num mayor o igual a 1"); } El bucle while Un bucle es un conjunto de sentencias que se ejecutan repetidamente hasta que se alcanza una condicin de fin de bucle o condicin de salida. El bucle while es el tipo de bucle ms sencillo. En su modo ms simple se escribe: while (expresin1) sentencia1; El bucle while comienza por evaluar la expresin1. Si es cierta se ejecuta la sentencia1. Entonces se vuelve a evaluar la expresin1. De nuevo si es verdadera se vuelve a ejecutar la sentencia1. Este proceso continua hasta que el resultado de evaluar la expresin es falso. Por esto se le llama a esta expresin la condicin de salida. Por ejemplo: int variable = 10; while (variable) printf("la variable vale %d\n", variable--);

38

En este caso se imprimir el valor de la variable hasta que se llegue a 1. Normalmente en las sentencias del bucle while se coloca alguna instruccin que modifique la expresin de control. Lo ms habitual es utilizar un bloque de sentencias en vez de una sentencia en vez de una sentencia nica. Por ejemplo: int variable = 10; while (variable) { printf("valor de la variable %d\n", variable); printf("valor tras decrementar la variable %d\n", variable); } El bucle do-while La sintaxis de este bucle es: do sentencia1; while (expresin1); Su funcionamiento es anlogo el del bucle while, salvo que la expresin de control se evala al final del bucle. Esto nos garantiza que el bucle do-while se ejecuta al menos una vez. Es menos habitual que el bucle while. Podemos incluir dentro del bucle un grupo de sentencias, en vez de la sentencia1. Este es el nico bucle que no necesita llaves para encerrar un grupo de sentencias. Por ejemplo: char c = '9'; do printf("numero actual %c\n", c); --c; /* ahora la decrementamos como si fuera entera */ while (c >= '0'); El bucle for La sintaxis del bucle for es: for (inicio, control, incremento) sentencia1;

39

Este bucle se utiliza para realizar una accin un nmero determinado de veces. Est compuesto de tres expresiones: la de inicio, la de control y la de incremento, y una sentencia. Su versin ms sencilla es: for (i =0; i < 10; i++) printf("i vale %d\n", i); Esta versin del bucle imprime un mensaje en la pantalla mientras que no se alcance la condicin de salida, i == 10. El funcionamiento del bucle for es el siguiente: Primero se ejecuta la expresin de inicio. Normalmente esta es una expresin de asignacin a una variable, que le da un valor inicial. Luego se comprueba la expresin de control. Si esta expresin es verdadera se ejecuta la sentencia, o el grupo de sentencias. Si la expresin es falsa el bucle finaliza. Tras ejecutarse la sentencia se evala la expresin de incremento. Habitualmente lo que hace esta expresin es incrementar la variable de control. A continuacin se vuelve al segundo paso. El bucle finaliza cuando la expresin de control es falsa. En un bucle for podemos omitir la expresin de inicio, por ejemplo si sabemos que la variable ya esta inicializada: int i = 0; for ( ; i <= 10; ++i) printf("%d\n", i); Tambin podemos omitir la expresin de incremento. Esto es habitual cuando la variable de control ya se modifica dentro del bucle. Por ejemplo: int i= 10; for ( ; i < 10; ) printf("i = %d\n", i++); El bucle for es equivalente a un bucle while escrito del siguiente modo: inicio; while (control) { sentencia1;

40

incremento; } Este bucle while puede servirnos para salir fcilmente de dudas al escribir un bucle for, ya que se ve claramente el orden de ejecucin de las expresiones y sentencias dentro del bucle for. Como se ve, en cada pasada del bucle for se sigue el orden: evaluacin de control, ejecucin de sentencia1 y evaluacin de incremento. Las sentencias break y continue Hay veces en que interesa romper un bucle en una determinada posicin, para ejecutar una nueva pasada del bucle o para finalizar su ejecucin Esto suele ser habitual cuando el bucle tiene una gran complicacin o cuando necesitamos salir "por las malas" de l. Esto ultimo suele ser frecuente cuando en el bucle se producen "condiciones de error". Para realizar estos dos tipos de salto disponemos de dos sentencias, la sentencia break y la sentencia continue. La sentencia break rompe la ejecucin de un bucle o bloque de instrucciones y continua en la instruccin que siga al bucle o bloque. Por ejemplo: int a = 10; while (1) { if (a-- <= 1) break; printf("%d\n", a); } Aunque en apariencia este es un bucle sin fin, ya que la condicin con while (1) siempre es cierta, este bucle se acabar cuando la variable a valga 1. El bucle simplemente decrementa la variable e imprime su valor. La sentencia continue rompe la ejecucin habitual del bucle y procede a evaluar de nuevo la expresin del bucle. Acta como si se saltase al final del bloque de un bucle. Por ejemplo: int a = 1; while (a < 10) { printf("%d\n", a); if (a==7) continue; } La sentencia de seleccin mltiple switch

41

Esta sentencia sirve para agrupar varias sentencias if en una sola, en el caso particular en el que una variable es comparada a diferentes valores, todos ellos constantes, y que realiza acciones si coincide con ellos. Su sintaxis es: switch (control) { case exp1: sent1; break; case exp2: sent2; break; default sent0; break; } Su sintaxis es ms complicada que la de anteriores bucles, ya que agrupa un mayor nmero de acciones y posibilidades en una sola sentencia. El modo de funcionamiento es el siguiente: Primero se evala la expresin de control. A continuacin se compara con la expresin de la primera etiqueta case. Si son iguales se ejecuta la sentencia1. Luego se vuelve a comparar la expresin de control con la etiqueta del segundo case. De nuevo , si son iguales se ejecuta la sentencia2. Se repite el proceso hasta agotar todas las etiquetas case. Si al llegar a la etiqueta default no se ha ejecutado ninguna otra sentencia. Esta es la accin por defecto. La etiqueta default es opcional. Si no la ponemos el programa simplemente salta a la lnea siguiente. Hay que tener cuidado con un aspecto de este bucle. Cuando una expresin de una etiqueta case es igual a la sentencia de control, se ejecutan todas las sentencias que sigan hasta que se alcance una nueva etiqueta case, y luego se vuelve a comparar la expresin de control. Este mecanismo tiene una ventaja y un inconveniente. La ventaja es que no necesitamos encerrar entre llaves el grupo de sentencias a ejecutar para cada etiqueta. El inconveniente es que al agotar las sentencias de una determinada etiqueta la sentencia switch prosigue con la siguiente etiqueta case. Habitualmente lo que se pretende es que tras ejecutar el grupo de sentencias se finalice el switch. Para evitar el que se ejecuten ms sentencias habitualmente se acaba cada grupo de sentencias con una sentencia break. La sentencia break pasa entonces la ejecucin a la siguiente lnea de programa que prosiga al bucle switch. Tambin se permite poner etiquetas mltiples para un mismo grupo de sentencias. Si dejamos una etiqueta case sin sentencias a ejecutar entonces se asocia a la siguiente etiqueta. Esto es til para ejecutar una misma accin para distintos valores de la expresin. Funciones Una funcin es una rutina o conjunto de sentencias que realiza una determinada labor. En C todas las funciones devuelven un valor, que por defecto es un entero. las funciones admiten argumentos, que son datos que le pasan a la funcin las sentencias que la llaman. Definicin de una funcin La sintaxis habitual en la definicin de una funcin es:

42

tipo identificador(lista_de_argumentos) { /* bloque de cdigo */ } Donde: tipo es el tipo de datos devuelto por la funcin identificador es el nombre de la funcin. Debe ser un identificador valido. lista_de_argumentos es una lista de variables, separadas por comas, que conforman los datos que le pasamos a la funcin. El tipo y la lista de argumentos son opcionales. Si omitimos el tipo, la funcin por defecto devolver un entero. Muchas veces el valor devuelto por la funcin es ignorado en el programa. La lista de argumentos es tambin opcional. Un ejemplo es la funcin main(), que en principio no tiene argumentos. Podemos escribir como ejemplo: hola() { printf("hola\n"); } Que simplemente es una funcin que cuando es llamada imprime en pantalla un mensaje de saludo. Cuando el programa al ejecutarse alcanza la llave de cierre '}' de la funcin, esta finaliza y devuelve el control al punto del programa que la llam. Retorno de valores Cuando la funcin finaliza hemos dicho que se devuelve un valor. Este valor en principio no est definido, es decir, puede devolver cualquier cosa. Para obligar a la funcin a retornar un determinado valor se utiliza la sentencia return, seguida del valor a retornar. Como todas las sentencias en C se debe acabar con un ';'. Por ejemplo: lista() { return 1;

43

} devuelve el entero 1 cada vez que es llamada. En C podemos devolver cualquier tipo de datos de los llamados escalares. Los tipos de datos escalares son los punteros, tipos numricos y el tipo carcter. En C no se pueden devolver arreglos ni estructuras. Paso de parmetros a una funcin Utilizando la lista de argumentos podemos pasar par metros a una funcin. En la lista de par metros se suele colocar un conjunto de identificadores, separados por comas, que representar cada uno de ellos a uno de los par metros de la funcin. Observar que el orden de los par metros es importante. Para llamar a la funcin habr que colocar los par metros en el orden en que la funcin los espera. Cada par metro puede tener un tipo diferente. Para declarar el tipo de los par metros aadiremos entre el parntesis ')' y la llave '{' una lista de declaraciones, similar a una lista de declaraciones de variables. Es habitual colocar cada par metro en una lnea, tabulados hacia la derecha. Asi: imprime(numero, letra) int numero; char letra; { printf("%d, %c\n", numero, letra); } es una funcin que admite dos variables, una entera u otra de tipo carcter. Paso de par metros por valor y por referencia En los lenguajes de programacin estructurada hay dos formas de pasar variables a una funcin: por referencia o por valor. Cuando la variable se pasa por referencia funcin puede acceder a la variable original. Este enfoque es habitual en lenguajes como el Pascal. En C sin embargo todos los par metros se pasan por valor. La funcin recibe una copia de los par metros y variables, y no puede acceder a las variables originales. Cualquier modificacin que efectuemos sobre un par metro no se reflejar en la variable original. Esto hace que no podamos alterar el valor de la variable por equivocacin. Sin embargo, en determinadas ocasiones necesitaremos alterar el valor de la variable que le pasamos a una funcin. Para ello en el C se emplea el mecanismo de los punteros, que se ve mas adelante. Declaracin y comprobacin de tipos

44

Al igual que para las variables, cuando una funcin se va a usar en un programa antes del lugar donde se define, o cuando una funcin s define en otro fichero (funciones externas), la funcin se debe declarar. La declaracin de una funcin consiste en especificar el tipo de datos que va a retornar la funcin. Esto es obligatorio cuando vamos a usar una funcin que no devuelve un entero. Adems en la declaracin se puede especificar el nmero de argumentos y su tipo. Una declaracin tpica de funcin es: tipo identificador( lista_de_argumentos_con_tipo ); Esto avisa al compilador de que la funcin ya existe, o que la vamos a definir despus. La lista de argumentos con tipo difiere de la lista de argumentos antes presentada en que el tipo de cada argumento se coloca dentro de la lista, antes de su correspondiente identificador, como hacamos en la definicin de variables. Por ejemplo: char print(int numero, int letra); declara una funcin que devuelve un carcter y tiene dos par metros, un entero y un carcter. La lista de argumentos permite al compilador hacer comprobacin de tipos, ya que el tipo y numero de argumentos debe coincidir en la declaracin, definicin y llamada a una funcin. Este tipo de especificacin del tipo de argumentos tambin se puede emplear en la definicin de las funciones, aunque lo contrario no es posible. Asi: char print(int numero, int letra) { printf("%d, %c\c", numero, letra); } es otra definicin v lida para la funcin print que hemos empleado. Arreglo Los arreglos son conjuntos de datos de un mismo tipo, el tipo base. A cada uno de los datos de un arreglo le llamaremos elemento de arreglo, y esta designado por un nmero. En C al primer elemento de un arreglo le corresponde siempre el nmero 0, y los dems tienen la numeracin consecutiva. Declaracin de una matriz. Para crear un arreglo de n elementos de un cierto tipo se introduce la lnea: Tipo identificador [n];

45

donde n es una constante de tamao fijo. Si el arreglo es esttico o global el compilador crea el espacio para la matriz al principio del programa, generalmente en el rea de datos. Si es de tipo automtico, reservar el espacio en la pila de datos. Como todos los tipos de datos , un arreglo se puede inicializar. Si el arreglo es esttico, por defecto cada elemento se inicializa a 0. Si es din mico los valores de cada elemento no est n definidos y antes de usarlos los debemos inicializar. Para inicializar un arreglo en el momento de su creacin aadiremos tras el identificador y los corchetes de tamao un = y la serie de valores. Cada valor debe ser una constante v lida para el tipo de datos del arreglo, y cada valor ir separado del valor precedente mediante una coma. Para abrir y cerrar la serie de valores usaremos las llaves. Por ejemplo: int vector [4]={0, 1,2,3 }; char hola[] = { 'h', 'o', 'l', 'a', '\0'}; No podemos dar un nmero de valores mayor al tamao del arreglo , pero si podemos dar menos de los necesarios. El compilador siempre rellenar los dems con ceros. El compilador siempre asignar el primer valor al primer elemento del arreglo, y los dems los asignar consecutivamente. Como siempre acabaremos la lnea con un ;. Acceso a los miembros de un arreglo Para usar un elemento de un arreglo se utiliza el identificador y el nmero de orden del elemento. Al primer elemento siempre le corresponde el nmero 0. Asi printf ("%d", vector[0]) imprimira el contenido del primer elemento del arreglo que definimos antes, que lo habamos inicializado a 0. En el lenguaje C no se hace ningn control acerca de si intentamos leer un nmero de elemento mayor que el ultimo nmero del arreglo. Esto es lo que llama sobrepasar el lmite, y el compilador deja al programador la tarea de preocuparse por los lmites del arreglo. Si los sobrepasamos, pueden ocurrir resultados imprevisibles (normalmente modificaremos alguna otra variable del programa, o incluso bloquearemos el programa). Tamao de los arreglos El tamao de los arreglos es siempre constante y se especifica al crear el arreglo. Hay dos formas de especificar el tipo: ndice dndoselo explcitamente al compilador o hacindolo implcitamente. El primer modo es el ya sealado anteriormente . Para dar un tamao al arreglo simplemente indicamos el nmero de elementos entre los corchetes. Este es el modo ms habitual de dar el tamao, sobre todo si no se va a inicializar en el momento de su creacin. El otro modo consiste en hacer que sea el compilador el que decida el tamao. Esto se hace cuando en la creacin del arreglo le damos una lista de valores iniciales . En este caso si omitimos el tamao del arreglo el compilador ajusta el tamao del arreglo segn el nmero de elementos que le demos para inicializar el arreglo. Por ejemplo: int vetor[] = { 1, 2, 3, 4, 5, 6 }; Este ultimo mtodo es muy cmodo, sobre todo si el arreglo va a tener un tamao pequeo y todos los valores iniciales son constantes.

46

Cadenas de caracteres Hay un tipo de arreglos de especial importancia; las cadenas de caracteres. Una cadena de caracteres es un arreglo de caracteres que acaba con el carcter nulo. En C siempre las cadenas de caracteres acaban con este carcter. Esto se hace as por dos motivos: el tamao de la cadena no tiene un lmite prefijado: puede ser tan grande como lo permita la memoria. Las operaciones de manipulacin de cadenas de caracteres se simplifican bastante. El inconveniente es que para conocer el tamao de la cadena normalmente necesitamos recorrerla con un bucle, aunque esto suele hacerse rpidamente. Para inicializar una cadena de caracteres basta crear un arreglo de caracteres, en el que no necesitamos definir el tamao e inicializarlo con la cadena de caracteres entrecomillada. Observar que el compilador siempre aade un carcter nulo al final, por lo que el tamao del arreglo es una unidad mayor del aparente. Por ejemplo: char cadena[] = "abracadabra" /* cadena de 12 caracteres*/ Los caracteres especiales como el tabulador \t y el retorno de carro \r se almacenan como un nico carcter. El carcter nulo est representado por un 0. Esto nos permitir utilizar comparaciones con este carcter en los bucles que recorren cadenas de caracteres . Arreglos multidimensionales En C se pueden construir arreglos de arreglos , es decir tipos de arreglos tipos de arreglos cuyos elementos son a su vez arreglos. Dado que ahora necesitaremos un ndice para situarnos dentro del arreglo principal y otro ms para movernos dentro de cada uno de los nuevos arreglos , diremos que los arreglos de arreglos poseen dos dimensiones. A un arreglo de dos dimensiones se le suele llamar matriz, y a un arreglo de una dimensin, vector. Las matrices son tipos de datos ampliamente usados en matemticas. Normalmente diremos que un ndice representa a las filas de la matriz y otro a las columnas. Otro uso habitual de las matrices es para representar tablas de valores. Para crear una matriz de enteros, es decir, un arreglo de arreglos de enteros, lo haremos de modo anlogo a cuando crebamos un arreglo, salvo que ahora aadiremos el nuevo ndice entre corchetes. Por ejemplo: int matriz[8][9]; declara una matriz de 8 filas por 9 columnas, o 9 por 8 columnas, segn queramos representar. La eleccin de cual ndice representa las filas y cual las columnas es arbitrario. Podemos usar la norma habitual en matemticas: el de la izquierda representa filas y el de la derecha columnas. Acceso a los miembros de una matriz Para acceder a un miembro concreto de una matriz, siguiendo el convenio anterior, colocaremos su nmero de fila y de columna entre corchetes. Por ejemplo: printf("%d\n", matriz[1][2]); imprime el elemento correspondiente a la fila 1, columna 2. Para inicializar las matrices disponemos ahora de dos formas:

47

-incluir todos los elementos de la matriz entre llaves, ordenados por filas y por columnas. Para ello se hace del siguiente modo: tras el signo igual en la definicin abrimos una llave. A continuacin colocamos cada columna de valores, todos ellos separados por sus comas. Cada columnas de valores debe ir encerrada entre llaves, separando una columna de otra por comas. Al final cerramos la llave que habamos abierto al principio. Por ejemplo: int matriz[2][3] = { {1, 2, 3}, {4, 5, 6} }; define una matriz de 2 filas con 3 columnas por fila. -incluir la lista completa de elementos de la matriz entre llaves, separados por comas, uno tras otro sin separar las columnas. Para colocar todos los valores correctamente necesitamos saber como accede el compilador a los elementos de una matriz. El compilador supone que en la memoria est n guardados los elementos ordenados por filas, es decir, est n juntos todos los datos correspondientes a una fila. As la matriz la podamos haber inicializado con: int matriz[2][3] = { 1, 2, 3, 4, 5, 6}; y obtendremos el mismo resultado de antes. Vemos que los tres primeros elementos corresponden a la fila 1, y los tres siguientes son los de la fila 2. Cuando el compilador necesita acceder al elemento de fila i y columna j hace el siguiente calculo: multiplica (i - 1) por el nmero de columnas, y al resultado le suma (j - 1). Con ello accede a la matriz como si fuese de una sola dimensin. En nuestro caso el elemento matriz[1][3] ser el que ocupe el lugar 0 * 3 + 2, es decir, el tercer elemento de un arreglo unidimensional. Los dos unos que aparecen restando se deben a que el compilador empieza a contar los elementos de la matriz desde el 0. Como cabe esperar se pueden formar arreglos de cualquier dimensin. Por ejemplo un arreglo de tres dimensiones podra ser: tresdim[10][15][20]; Esto podra representar un conjunto de 10 tablas, cada una de 15 filas y 20 columnas por fila. Para inicializarla procederamos de un modo anlogo al caso bidimensional. Punteros Cuando queramos pasar un dato a una funcin normalmente pasamos una copia del dato. Esto es sencillo de hacer y r pido, siempre que no queramos modificar mediante la funcin el dato original o que el dato sea pequeo. Otro enfoque consiste en decirle a la funcin donde encontrar los datos. Para ello le pasamos a la funcin una direccin. Con ella la funcin podr acceder a los datos utilizando un puntero. Un puntero es un nuevo tipo de datos, que no contiene un dato en si, si no que contiene la direccin donde podemos encontrar el dato. Decimos que un puntero "apunta" a un dato, pudiendo alterar dicho dato a travs del puntero. Definicin de un puntero Para poder usar punteros y direcciones de datos vamos a introducir dos nuevos operadores. el primero es el operador puntero, que se representa con un asterisco *. el operador puntero nos permite definir las variables como punteros y tambin acceder a los datos. El otro nuevo operador, el operador direccin, nos permite obtener la direccin en la que se halla ubicada una variable en la memoria. Vemos que el operador direccin es el complementario al operador puntero.

48

Para definir un puntero lo primero que hay que tener en cuenta es que todo puntero tiene asociado un tipo de datos. Un puntero se define igual que una variable normal, salvo que delante del identificador colocaremos un asterisco. Por ejemplo: char *pc; /*puntero a carcter */ char *pi; /* puntero a entero */ Normalmente al definir un puntero lo solemos inicializar para que apunte a algn dato. Disponemos de tres formas de inicializar un puntero: Inicializarlo con la direccin de una variable que ya existe en memoria. Para obtener la direccin en la que est ubicada una variable colocamos delante del identificador de la variable el operador direccin &. No se suele dejar espacios entre el signo & y el identificador. Por ejemplo: char *p = &p1; Asignarle el contenido de otro puntero que ya est inicializado: char *p = &p1; char *p2 = p; /* p ya est inicializado */

Inicializarlo con cualquier expresin constante que devuelva un lvalue. Las mas frecuentes son una cadena de caracteres, el identificador de un arreglo, el identificador de una funcin, y otros muchos. Este es un detalle importante: los identificadores de funciones y de arreglos son en si mismos valores por la izquierda (lvalues), por lo que se pueden usar directamente para inicializar punteros. Una forma adicional de inicializarlo es darle directamente una posicin de memoria. Este mtodo no es portable, ya que depende del sistema, pero suele ser muy til en programacin de sistemas, que es uno de los usos fundamentales del C. Un error muy frecuente consiste en no inicializar el puntero antes de usarlo. Este error frecuentemente lo localiza el compilador y avisa de ello. Desreferenciacion de un puntero Una vez que el puntero apunta a un objeto o dato en la memoria podemos emplear el puntero para acceder al dato. A este proceso se la llama desreferenciar el puntero, debido a que es una operacin inversa a obtener la direccin de una variable. Para desreferenciar un puntero se utiliza el operador puntero. Para acceder al dato al que apunta el puntero basta colocar el asterisco * delante del identificador. Como norma de buena escritura no se deja ningn espacio entre el * y el identificador, aunque el compilador lo acepte. Un puntero desreferenciado se comporta como una variable normal. Por ejemplo: int entero = 4, *p = &entero; printf("%d %d \n", *p, entero);

49

Aritmtica de punteros. Un uso habitual de los punteros es para recorrer los arreglos. En efecto, comencemos por crear un arreglo y un puntero al comienzo del arreglo. int arreglo[] ={ 1, 2, 3, 4, 5}; int *p = arreglo; En este momento el puntero apunta al primer miembro del arreglo. Podemos modificar fcilmente el primer miembro, por ejemplo: *p = 5; printf("%d\n", arreglo[0]; Ya que un puntero es una variable tambin, le podemos sumar una cantidad. Sin embargo el resultado no se parece al que obtenemos con variables. Si a un puntero de tipo carcter le sumamos 1 o lo incrementamos, el contenido de la variable puntero es aumentado una unidad, con lo que el puntero a caracteres apuntara al siguiente miembro del arreglo. En principio este es el efecto que necesitaremos. Supongamos que tenemos ahora nuestro puntero a enteros, y apunta al principio del arreglo. Si nuestro sistema necesita dos bytes para representar los enteros, tras incrementar un puntero en una unidad veremos que el contenido de la variable puntero ha aumentado en dos unidades. Esto lo podemos ver utilizando la funcin printf con el modificador %p. En efecto: printf("%p\n", p); /* usamos el puntero anterior */ ++p; printf("%p\n", p; El resultado es que el puntero apunta ahora al siguiente elemento del arreglo. Este modo de incrementar el puntero es muy conveniente pues nos permite recorre un arreglo fcilmente. Para recorrer el arreglo slo tendremos que crear un puntero apuntando al principio del arreglo e irlo incrementando mientras manipulamos los datos del arreglo. Por ejemplo, el siguiente bucle imprime todos los caracteres de una cadena: MP! char *p = "Hola, mundo.\n"; /* la cadena es un lvalue */ while (*p) putchar(*p++); Aqu observamos como se usa el operador incremento con los punteros. Ya que el operador puntero tiene mayor precedencia que el operador incremento, en la expresin *p++ primero se desreferencia el puntero, usndose en con la funcin putchar(), y luego se incrementa el puntero. Por eso no hacen falta los parntesis con este operador. Si quisisemos incrementar el carcter al que apunta el puntero, debemos encerrar entre parntesis al operador puntero y al puntero. Por ejemplo:

50

char *p = "Hola, mundo.\n"; /* la cadena es un lvalue */ ++(*p); /* Aparecer una I */ while (*p) putchar(*p++); Cadenas de caracteres La manipulacin de cadenas de caracteres est implementado en la librera estndar del C. Como habamos definido, una cadena de caracteres es un arreglo de caracteres cuyo ultimo carcter es el carcter nulo '\0'. Para definir una cadena de caracteres basta definir un arreglo de caracteres del tamao conveniente, dejando espacio para el carcter nulo. Por ejemplo: char cadena[100] = "Hola"; La mayora de las funciones de cadenas de la librera estndar comienzan con el prefijo str y se hayan definidas en el fichero de cabecera <string.h>. Las funciones mas importantes de esta librera son: size_t strlen( const char *s); La funcin strlen() devuelve el tamao de una cadena de caracteres, sin incluir el carcter nulo de terminacin. Por ejemplo: printf("numero de caracteres de la palabra hola = %d", strlen("hola"); Necesita un par metro de tipo puntero a carcter y devuelve un size_t, que suele est r definido como entero sin signo. char *strcpy(char *s1, const char *s2); La funcin strcpy() copia la cadena s2 en la cadena s1, incluyendo el carcter de terminacin y devuelve un puntero a s1. Los dos parametros que necesita son punteros a caracteres, y devuelve un puntero a caracteres. Deberemos asegurarnos de que s1 tiene sitio para almacenar la cadena s2. char *strcat(char *s1, const char *s2); La funcin strcat() copia la cadena s2 al final de la cadena s1. Para ello busca el carcter de terminacin de s1 y a partir de all va colocando sucesivamente los caracteres de s2, incluyendo el carcter de terminacin. Los par metros que necesita y que devuelve son del mismo tipo que los de strcpy. Tampoco hace comprobaciones de que exista espacio para la cadena s2, ya que de ello debe asegurarse el programador. char *strchr(const char *s, int c);

51

La funcin strchr() busca el carcter c a lo largo de la cadena s. si lo encuentra devuelve un puntero a la primera posicin del carcter. Si falla la bsqueda devuelve un puntero nulo. La funcin tiene dos par metros, el puntero a la cadena en la que buscar el carcter y el carcter a buscar. Devuelve un puntero a caracteres. int strcmp(const char *s1, const char *s2); La funcin strcmp() compara dos cadenas de caracteres. Para ello compara elementos sucesivos de ambas cadenas hasta que encuentra dos elementos diferentes. Si ambas cadenas son iguales la funcin devuelve un 0. Si el elemento diferente es menor en s1 entonces devuelve un nmero negativo, y si es mayor en s1 entonces devuelve un nmero positivo. para comparar los caracteres la funcin toma los caracteres como enteros sin signo. Al utilizar el cdigo ASCII para representar las cadenas, los nmeros tienen un cdigo menor que las minsculas, y stas que las maysculas. Esta funcin no es muy eficiente cuando se trata de ordenar cadenas en las que aparecen caracteres acentuados o ees, pero es fcil construir una a medida. char *strncat(char*s1, const char *s2, size_t n); La funcin strncat() sirve para copiar un fragmento de la cadena s2 en al final de la cadena s1. Necesita tres par metros, dos punteros a caracteres y un nmero del tipo size_t, generalmente un unsigned. La funcin copia los primeros n caracteres de s2 al final de s1 y luego aade un carcter nulo al final de s1. La funcin devuelve un puntero a carcter que apunta a s1. Estructuras Una estructura es un tipo de datos compuesto por un grupo de datos, cada uno de los cuales puede ser de un tipo distinto. A cada componente de la estructura se le llama campo. Las estructuras tiene su equivalente en otros lenguajes de programacin, como el Pascal, en los registros. Tambin se llaman registros a los grupos de datos en la terminologa de las bases de datos. Definicin de una estructura Para la definicin de estructuras el C dispone de la palabra reservada estruct. Para crear una estructura primero comenzamos por definir el tipo de estructura. Para ello se procede de manera parecida a la definicin de una variable, con algunas modificaciones. Primero colocamos la palabra reservada struct y luego el identificador que dar nombre al nuevo tipo de estructura. Luego abriremos llaves y comenzaremos a definir los campos de la estructura. Cada campo se define como una variable normal, es decir, dando su tipo y un identificador. Vale cualquier definicin de tipo habitual, incluso punteros y estructuras. El identificador servir para designar a cada campo. Cada definicin de campo acabar con un punto y coma, como siempre. Finalizaremos la definicin de la estructura con una llave de cierre y un punto y coma. Por ejemplo: struct fecha { /* para almacenar una fecha */ int dia; char mes[14]; int anyo;

52

}; double real; double imaginario; }; Una vez que hemos definido un tipo de estructura ya podemos definir variables estructuras de dicho tipo. Esto se hace de una forma anloga a la definicin de variables normales, esto es, se pone la palabra reservada struct, el identificador del tipo de estructura y el identificador de la nueva estructura. Por ejemplo: struct fecha fecha_de_hoy; struct complejo x, y; Una estructura tambin se puede inicializar. Para ello se dan los valores iniciales entre llaves, separados por comas, al igual que hacamos son los arreglos. La novedad es que ahora cada dato puede tener un tipo diferente. Por ejemplo: struct fecha fecha_actual = { 12, "Enero", 1900}; struct complejo x = {1, 1}; Hay dos posibilidades ms en la definicin de estructuras. La primera es definir una variable estructura a la vez que se define el tipo de estructura. Para ello hasta dar los identificadores de las nuevas variables estructuras despus de la llave de cierre. Por ejemplo: struct complejo{ double x ; double y; } z1, z2; Adems podemos definir variables estructuras sin tipo especfico. Para ello basta omitir el identificador del tipo de estructura en la definicin de la estructura, dando slo el identificador de la variable estructura. De este modo la nueva variable va asociada al tipo creado. Por ejemplo: struct { int dia; char mes[14]; int anyo; } mi_aniversario;

53

Campos de bits Hay un nuevo tipo de datos que solo se puede usar con estructuras: el campo de bits. Un campo de bits se comporta igual que un entero sin signo, slo que al definir el campo de bits se define el nmero de bits que lo compondr . Por Ejemplo: struct comida { unsigned clase : 2; /* dos bites para el tipo */ unsigned temporada : 1; /* a 1 si es de temporada */ unsigned es_perecedero :1, es_congelado : 1; }; Si el tamao del campo de bits es 0 nos permite alinear el siguiente campo sobre un entero. Hay que tener en cuenta que la alineacin de los campos de bits y de los dems campos la define el compilador. Hay que tener en cuenta que no se puede obtener la direccin de un campo de bits. El C estndar define la macro offsetof() para calcular el desplazamiento de un campo de una estructura desde el principio de la misma. El uso de campos de bits permite empaquetar informacin pequea eficientemente dentro de una estructura. Su uso est bastante extendido en la programacin de sistemas. Paso de estructuras a las funciones En C estndar esta permitido pasar una estructura como argumento de una funcin, devolverla como resultado de una funcin, asi como asignar una estructura completa a una funcin. Esto no era posible en los primeros compiladores de C. No est permitido comparar estructuras completas. Por ejemplo: struct complejo { double x, y; } z1, z2, suma; struct complejo suma_complejos( struct complejo j1, struct complejo j2); suma = suma_complejos(j1, j2); /*esta funcin se definira aparte */ if (j1 > j2) puts("es mayor j1"); /*esto no est permitido */

54

Sin embargo esto no es lo ms eficiente. Como las estructuras tienen a menudo un tamao considerable suele ser conveniente pasarlas a travs de punteros. Para obtener la direccin donde se halla una estructura usaremos el operador direccin &, como con una variable normal. Para definir un puntero a una estructura usaremos el operador *. Por ejemplo: struct complejo j; struct complejo *pj = &j; Acceso a los campos de una estructura. Para acceder individualmente a cada campo de una estructura se usa el operador punto '.'. Para ello colocamos el operador de la estructura , un punto y el identificador del campo. Cada campo de una estructura designado mediante este operador se comporta como si de una variable del mismo tipo que el campo se tratase. Podemos realizar todas las operaciones habituales de las variables: asignacin, uso de punteros, llamadas a funciones con el campo como par metro: struct complejo z = {1,1}; printf("z vale %f, i%f\n", z.x, z.y); z.x = z.y = 0; Para acceder a los campos de una estructura a travs de un puntero tenemos un nuevo operador, el operador puntero a campo -> (un guin seguido de un signo "mayor que"). Para acceder a un campo de una estructura a travs de un puntero a ella basta poner el identificador del puntero, el nuevo operador puntero a campo y luego el identificador del campo. Por ejemplo: struct complejo z = {1, 1}; struct complejo *pz = &z; printf("%f, i%f\n", pz->x, pz->y); Podramos haber usado la notacin habitual para punteros y el operador punto de acceso a campos, pero nos aparece un nuevo inconveniente: ya que el operador punto tiene mayor precedencia que el operador puntero tendramos que encerrar el identificador y el operador puntero entre parntesis, para luego aplicarles el operador punto. En efecto, las siguientes expresiones son equivalentes: pz->x = 1; (*pz).x = 1; Si omitimos los parntesis se hara lo siguiente: pz sera considerado como una estructura, luego el operador punto dara el campo x de la estructura y el operador puntero intentara acceder a donde apuntase el campo x. Vemos que hay dos errores, ya que ni pz es una estructura ni el campo x es un campo puntero. Esta expresin sera v lida si tuvisemos una estructura del tipo: struct elemento { int tipo;

55

char *nombre; } uno = {1, "estructura"}; printf("%c\n",*[Link]); /*imprime la primera letra de nombre */ Uniones Una unin es un tipo de datos formado por un campo capaz de almacenar un solo dato pero de diferentes tipos. Dependiendo de las necesidades del programa el campo adoptar uno de los tipos admitidos para la unin. Para definir uniones el C utiliza la palabra reservada unin. La definicin y el acceso al campo de la unin es anlogo al de una estructura. Al definir una variable de tipo unin el compilador reserva espacio para el tipo que mayor espacio ocupe en la memoria. Siempre hay que tener en cuenta que slo se puede tener almacenado un dato a la vez en la variable. En C es responsabilidad del programador el conocer que tipo de dato se est guardando en cada momento en la unin. Para definir una unin seguimos la misma sintaxis que para las estructuras. Por ejemplo: unin dato_num { int num1; float num2; } dato; define una unin en la que el campo puede ser de tipo entero o de tipo nmero con coma flotante. Las uniones normalmente se emplean como campos en las estructuras. Para llevar la cuenta del tipo de datos almacenado en la unin normalmente se reserva un campo en la estructura. Por ejemplo: struct dato_num { int tipo; unin { float simple; double doble; }dato; }; Las uniones son especialmente tiles para la realizacin de registros de bases de datos, ya que permiten almacenar informacin de diferentes tipos dentro de los registros. En programacin de

56

sistemas es usual encontrarlas dentro de las estructuras de datos de las rutinas, ya que permiten una gran flexibilidad a la hora de almacenar informacin. Tipos de datos enumerados Gestin de la memoria En C se pueden almacenar variables y estructuras de datos en tres lugares diferentes: la pila para las variables automticas, la memoria global para las variables globales y la memoria dinmica. La pila es una seccin de la memoria que es gestionada automticamente por el compilador y es donde se almacenan las variables locales. El compilador crea el espacio para la variable en tiempo de ejecucin y libera el espacio ocupado cuando la variable deja de usarse (cuando salimos del mbito o funcin en que se declar). Por eso reciben el calificativo de automticas. Las variables estticas globales se almacenan en la seccin de la memoria llamada memoria global. El compilador tambin se encarga de proporcionarles espacio a estas variables, pero lo hace en tiempo de compilacin, por lo que el espacio queda reservado durante toda la ejecucin del programa. Generalmente los valores iniciales de las variables globales son asignados en tiempo de compilacin. El ultimo tipo de memoria es el almacenamiento libre (free store en ingles) conocido habitualmente como la memoria dinmica (heap en ingles). El compilador no se hace cargo de ella, sino que es el programador el que solicita su uso a travs de funciones predefinidas que se encargan de manejar la memoria dinmica. Estas funciones son malloc, calloc, realloc y free, y se definen en el fichero de cabecera <stdlib.h>. Estas funciones generalmente trabajan solicitando directamente porciones de memoria al sistema operativo. Su uso es muy sencillo y generalmente se usan a travs de punteros. La funcin malloc() nos permite solicitar memoria al sistema. Posee un nico argumento: el tamao del espacio que queremos reservar. En C el tamao de un tipo de datos es el nmero de caracteres que ocupa en la memoria, ya que el tipo carcter tiene un tamao de un byte generalmente. El tamao de un tipo de datos tambin se puede calcular con el operador sizeof. La funcin malloc se define como: void * malloc(size_t longitud); y su nombre viene de memory alloc (asignacin de memoria, en ingles). Necesita un par metro, que es la longitud del espacio que vamos a reserva. Este par metro es del tipo size_t, que es el tipo empleado en c para medir tamaos de tipos. Normalmente se suele definir size_t como unsigned, y el valor longitud representa el nmero de caracteres que se asignan. La funcin malloc devuelve un puntero del tipo puntero a caracteres al espacio de memoria asignado. Si el sistema no puede proporcionar la memoria pedida devuelve un puntero nulo. El espacio que devuelven las funciones malloc, c alloc y realloc no est inicializado, por lo que lo que debe inicializarlo el programador. Para liberar el espacio asignado con malloc basta llamar a la funcin free, (liberar en ingles). Esta funcin se define como:

57

void free(void *ptr); y su argumento es el puntero que devolvi malloc. No devuelve ningn valor y funciona igualmente con los punteros que devuelven calloc y realloc. La funcin calloc funciona de modo anlogo a malloc salvo que tiene un par metro adicional, numelem, que le permite especificar el nmero de objetos a asignar. Se define como: void *calloc(size_t numelem, size_t longitud); Como la funcin malloc devuelve un puntero al espacio de memoria asignado y un puntero null si no ha sido posible asignar el espacio. Normalmente se utiliza para asignar espacio para un grupo de datos del mismo tipo. La funcin realloc nos permite modificar el tamao del espacio asignado con malloc o calloc. Se define como: void *realloc(void *ptr, size_t longitud); El primer argumento ptr es un puntero a un espacio previamente asignado con calloc o malloc. El segundo es la nueva longitud que le queremos dar. Devuelve un puntero al nuevo espacio asignado o un puntero nulo si fall la asignacin. Adems la funcin copia el contenido del antiguo espacio en el nuevo al comienzo de este. Esto siempre lo puede hacer se la longitud del anterior espacio asignado es menor que la nueva longitud solicitada. El espacio sobrante en este caso no se inicializa. Si el espacio solicitado es de menor tamao que el anterior se copia slo la parte que quepa, siempre desde el principio, al comienzo del nuevo espacio asignado. Uso de las funciones de asignacin de memoria Para reservar espacio en la memoria dinmica para un arreglo comenzaremos asignando el espacio con malloc. Por ejemplo: #include <stdlib.h> main() { char *p; int i; p = (char *) malloc(1000); for (i = 0; i < 1000; ++i) p[i] = getchar(); for (i = 999; i >= 0; --i)

58

putchar(p[i]); free(p); } Este programa lee los primeros 1000 caracteres de la entrada estndar y los imprime en orden inverso. Se puede ver el uso de malloc y de free. En la lnea de llamada a malloc hemos introducido una variante: hemos forzado una conversin del tipo devuelto por malloc. Esto lo hemos hecho porque conviene acostumbrarse a asignar a los punteros otros punteros del mismo tipo. Aunque en C estndar se puede asignar un puntero void a cualquier puntero, es conveniente realizar el moldeado del tipo, ya que en C++, el lenguaje C avanzado, esto no est permitido. Muchos compiladores nos avisar n si intentamos asignar un puntero void a otro puntero, aunque nos permiten compilar el programa sin problemas. Los compiladores de C++ directamente paran la compilacin. Ya que no nos cuesta mucho hacer el moldeado, es buena costumbre el hacerlo. Funciones variadic En C se permite definir funciones con un nmero variable de argumentos. Son las llamadas funciones variadic. El ejemplo ms comn de funcin variadic es la funcin printf(). En C estndar se define un mtodo para crear funciones variadic. Para ello se proporciona la cabecera stdarg.h que incluye los tipos y macros que permiten crear dichas funciones. Declaracin de funciones variadic Una funcin variadic se declara igual que las dems funciones salvo que en su lista de argumentos aparece en ultimo lugar el smbolo de elipsis (tres puntos). Puede tener otros argumentos adicionales, pero el ultimo siempre es una elipsis. Un ejemplo de declaracin variadic es la funcin printf(), que se declara como: int printf(char *formato, ...); En esta declaracin observamos que la funcin printf() necesita al menos un argumento, que debe ser del tipo puntero a carcter y luego un nmero variable de argumentos. Como la funcin no conoce a priori el nmero de argumentos debemos disear algn mtodo de decirle el nmero de argumentos. Hay dos mtodos sencillos. El primero, que es el usado en printf(), es suministrarle a la funcin la informacin sobre el nmero de argumentos en uno de los argumentos. La cadena de formato pasada como primer argumento a printf() le indica los argumentos que van a continuacin y el tipo de los mismos. Otro mtodo usual es utilizar como ultimo argumento uno con significado especial. Por ejemplo en una funcin que calcule el mayor de los argumentos podemos colocar como ultimo argumento el nmero 0, o en una funcin en la que se hagan operaciones con punteros el puntero nulo. Definicin de funciones variadic Para definir una funcin variadic debemos seguir los siguientes pasos: incluimos como ultimo argumento de la lista de argumentos la elipsis.

59

en la lista de variables declaramos una variable de tipo va_list. Este tipo, al igual que las dems macros necesarias est declarado en stdarg.h, por lo que nos debemos asegurar de incluir dicha cabecera. ejecutar la macro va_start antes de comenzar a leer los argumentos. La macro va_start necesita dos argumentos. El primero es de tipo va_list, y debe ser la variable que hemos declarado anteriormente. El segundo es el nombre del ultimo argumento que se declara en la lista de argumentos. Hay algunas restricciones en el tipo de este argumento. No es seguro utilizar como ultimo argumento un arreglo, un float o algn tipo que cambie al ser promocionado. Es seguro usar un puntero y un entero normal. para in leyendo los argumentos restantes se va ejecutando la macro va_arg sucesivamente. Esta macro va leyendo de la lista de argumentos cada argumento, segn el tipo que le proporcionemos. Necesita dos argumentos: el primero es la variable de tipo va_list que habamos definido y el segundo es un tipo, no una variable. Devuelve el valor del tipo que hemos solicitado. cuando hayamos ledo todos los argumentos debemos ejecutar la macro va_end, cuyo nico argumento es la variable de tipo va_list que hemos definido.

Como ejemplo crearemos una funcin que imprime todas las cadenas de caracteres que le pasemos como argumentos en la salida estndar: #include <stdarg.h> void prints(char *s, ...) { char *p; va_list arg; va_start(arg, s); puts(s); while ((p = va_arg(arg, char *)) != NULL) puts(s); va_end(arg); } Entrada y salida estndar Un programa en C se comunica con el usuario y con el sistema a travs de las funciones de entrada y salida. Con estas funciones se pueden solicitar y enviar datos al terminal del usuario y a otros programas. Adems podemos elegir entre enviar datos binarios o enviarlos como cadenas de texto. Las funciones de entrada y salida en C ms habituales son las que forman parte de la llamada "librera estndar". Originalmente esta librera fue implementada para atender las necesidades del sistema operativo UNIX, aunque es habitual encontrarlas en cualquier compilador de C, incluso en sistemas que difieren bastante del UNIX, como son los entornos grficos y de ventanas.

60

Entrada y salida de caracteres En la librera estndar se definen las dos principales vas de comunicacin de un programa en C: la entrada estndar y la salida estndar. Generalmente est n ambas asociadas a nuestro terminal de manera que cuando se imprimen datos en la salida estndar los caracteres aparecen en el terminal, y cuando leemos caracteres de la entrada estndar los leemos del teclado del terminal. La entrada y salida estndar trabaja con caracteres (en modo carcter), con datos o nmeros binarios. Es decir, todos los datos que enviemos a la salida estndar deben ser cadenas de caracteres. Por ello para imprimir cualquier dato en la salida estndar primero deberemos convertirlo en texto, es decir, en cadenas de caracteres. Sin embargo esto lo haremos mediante las funciones de librera, que se encargan de realizar esta tarea eficientemente. Comenzaremos con las dos funciones principales de salida de caracteres: putchar() y getchar(). La funcin putchar escribe un nico carcter en la salida estndar. Su uso en sencillo y generalmente est implementada como una macro en la cabecera de la librera estndar. La funcin getchar() devuelve el carcter que se halle en la entrada estndar. Esta funcin tiene dos particularidades. La primera es que aunque se utiliza para obtener caracteres no devuelve un carcter, sino un entero. Esto se hace as ya que con un entero podemos representar tanto el conjunto de caracteres que cabe en el tipo carcter (normalmente el conjunto ASCII de caracteres) como el carcter EOF de fin de fichero. En UNIX es habitual representar los caracteres usando el cdigo ASCII, tanto en su versin de 7 bits como en su versin ampliada a 8 bits. Estos caracteres se suelen representar como un entero que va del 0 al 127 o 256. El carcter EOF entonces es representado con un -1. Adems esto tambin lo aplicaremos cuando leamos los ficheros binarios byte a byte. Una tercera funcin de caracteres que no es muy frecuente es la funcin ungetchar(). Con ella devolvemos al sistema el ultimo carcter que hemos ledo con getchar(). No se puede llamar dos veces seguidas a ungetchar. El porqu queda ms claro al explicar el uso de ungetchar. Habitualmente cuando leemos un conjunto de caracteres de la entrada estndar le pediremos que sean de un determinado tipo. si por ejemplo queremos leer un dato numrico bastar con hacer un bucle que lea nmeros (caracteres numricos). El bucle normalmente terminar cuando el carcter ledo no sea un nmero. La mejor forma de saber si el siguiente carcter es un nmero es leerlo. Pero a leerlo, si no es un nmero ya no estar disponible para futuras lecturas. Aqu es desde se usa ungetchar(). Una vez que hemos comprobado que no es un nmero lo devolvemos, y as estar listo para la siguiente lectura. Visto esto podemos seguir con las funciones gets() y puts(). La funcin puts() simplemente se imprime una cadena de caracteres en la salida estndar. Le debemos proporcionar la direccin donde encontrar la cadena de caracteres. Como ejemplo vamos a dar una implementacion sencilla de esta funcin: void putchar(char *p) { while (*p) putchar(*p++); } realmente la funcin puts es ms complicada, pues devuelve un EOF si ha ocurrido algn error. Para imprimir datos de un modo ms general el C dispone de la funcin printf(), que se ocupa de la impresin formateada en la salida estndar.

61

La funcin printf() imprime los datos en la salida estndar segn una cadena de control. Est definida en la cabecera estndar stdio.h como: int printf(const char *formato, ...); La funcin printf() tiene varias caractersticas peculiares. La primera es que es una funcin comn nmero variable de argumentos. Normalmente a estas funciones se las llama variadic, y se reconocen porque incluyen en su lnea de argumentos el smbolo de elipsis (tres puntos ...). Slo el primer par metro es obligatorio, y es del tipo puntero constante a carcter. Esta cadena tiene dos funciones: imprimir un mensaje en la salida estndar y formatear los dems argumentos que se la pasan a la funcin para ser impresos como texto. Funcionamiento de la funcin printf() Si llamamos a la funcin printf() simplemente con una cadena de caracteres la funcin fprintf la imprime de modo parecido a como lo hace la funcin puts(). Por ejemplo: printf("Hola, mundo\n"); imprime la cadena "Hola, mundo\n" en la salida estndar. Pero adems la funcin printf es capaz de imprimir otros tipos de datos como variables numricas en la salida estndar. Para ello debemos avisar a la funcin printf() de que le pasamos como argumento una variable, ya que la funcin no tiene modo alguno de saber si le hemos pasado algn par metro. El modo de hacerlo es insertando cdigos de control en la cadena de formato. Estos cdigos normalmente van precedidos del carcter %. Por ejemplo el cdigo %d representa enteros en formato decimal. As la forma de imprimir una variable entera en la salida estndar es: printf("esto es un entero: %d\n", 10); Cuando printf() se encuentra el cdigo %d en la cadena de formato lee el siguiente argumento de la funcin, que debe ser un entero, y lo convierte en su representacin decimal como cadena de caracteres. La cadena que representa al nmero sustituye al cdigo %d de la cadena de formato y se imprime la cadena resultante. Hay una gran variedad de cdigos de control para formatear los diferentes tipos de datos. Los ms importantes son: para imprimir caracteres y cadenas de caracteres: %c imprime un carcter %s imprime una cadena de caracteres. Esta cdigo permite imprimir cadenas sin que printf() mire si la cadena contiene posibles cdigos de control. %% imprime el carcter % %p imprime la direccin donde apunta un puntero. El tipo de dato impreso depende de la implementacion. Se suele usar en la depuracin de programas o sistemas para imprimir enteros

62

%d imprime un entero en su representacin decimal %u imprime un entero sin signo en su representacin decimal %x imprime un entero en su representacin hexadecimal %o imprime un entero en su representacin octal %ld imprime un entero largo en su representacin decimal %hd imprime un entero corto en su representacin hexadecimal. Recordar que los enteros cortos se pasan como enteros para imprimir nmeros reales (con decimales) %f imprime un valor del tipo doble precisin como su valor real en simple precisin. Recordar que los floats se pasan como doubles %e imprime un valor double en sus representaciones doble precisin. La cadena generada es del tipo +-[Link] e+-ddd Estos cdigos de control pueden ser en la mayora de los casos completados con cdigos de alineacin y de signos. Los cdigos de alineacin se colocan entre el signo % y el cdigo de control. Los ms frecuentes son: - para justificar por la izquierda una conversin + aade un signo + a los valores positivos ' ' (espacio) aade un espacio a los valores con signo que no tengan signo ms o menos # para aadir el prefijo octal 0 en una conversin a octal, o el prefijo 0x en una conversin a hexadecimal 0 rellena con ceros antecedentes en una conversin cuando se ha especificado en ancho que es mayor que el resultado de la conversin

63

Entre el cdigo de alineacin y el cdigo de control podemos insertar un valor de anchura de campo que controla el ancho de la conversin. Por ejemplo: printf(":%3d:", 4); /* imprime : 3: */ Tambin podemos especificar un valor que controla el nmero de dgitos decimales en un valor real. Este valor se coloca tras la anchura de campo precedido de un punto. Por ejemplo: printf("%.3f", 3.99999); /* imprime 3.999 */ Para cadenas de caracteres tambin podemos insertar un valor que permite escoger cuantos caracteres se imprimen de la cadena. Para ello daremos este valor tras un punto, al igual que hacemos para el valor de precisin. Por ejemplo: printf("%.4s\n", "Hola, mundo\n"); /* imprime Hola */ La funcin scanf() La funcin scanf() hace el trabajo inverso a la funcin printf(), es decir, examina la entrada estndar y carga valores en variables. Se define como: int scanf(const char *formato, ...); Esta funcin trabaja de un modo parecido a como lo hace printf(). Necesita una cadena que indica el formato de los datos que se deben leer. La cadena de formato no se imprime, sino que slo sirve para que scanf() determine el tipo de datos a leer. El resto de los argumentos deben ser punteros a las variables donde se deben almacenar los datos ledos. Por ejemplo: scanf("%d", &i); lee un entero en formato decimal y lo almacena en la variable i. Hay que tener cuidado de pasar siempre punteros a scanf(), por lo que para guardar datos en variables normales deberemos emplear el operador direccin &. Los cdigos de control son Anlogos a los de printf, es decir, %d., %e, %s , ... La funcin scanf() es bastante sensible a los errores. Si el usuario introduce los datos incorrectamente la funcin scanf() simplemente falla. Si queremos realizar una funcin de lectura ms robusta podemos realizar lo siguiente: leemos la entrada en un arreglo de caracteres. Para ello simplemente usaremos la funcin gets() exploramos el arreglo de caracteres manualmente paso a paso. Para ello podemos usar la funcin sscanf().

La funcin sscanf se define como: int sscanf(const char *s, const char *formato, ...);

64

y realiza una tarea parecida a scanf(), pero explorando la cadena apuntada por s en vez de la entrada estndar. De este modo podemos ir explorando la cadena leda previamente con gets() paso a paso e informando al usuario del lugar donde ha cometido un error al introducir los datos. La funcin scanf salta los espacios precedentes cuando se lee un entero. Si la funcin no ha terminado de leer los datos pedidos espera a leer una nueva lnea de la entrada estndar. Esto lo hace as porque para efectos de formato la funcin scanf() coincidir al carcter de nueva lnea y al carcter de tabulador como un espacio en blanco, y la funcin scanf() salta los espacios en blanco. Este efecto de nuevo se puede evitar con el procedimiento anteriormente [Link] El sistema de ficheros habitual en C estndar est enfocado al sistema operativo UNIX, aunque otros sistemas operativos ofrecen con los compiladores de C una librera de funciones que emula en mayor o menor grado a la implementacion UNIX. El sistema de ficheros de UNIX El sistema UNIX organiza el sistema de ficheros en directorios. Cada directorio puede contener ficheros y otros directorios. Cada archivo o subdirectorio est identificado por un nombre y una extensin opcional. Es sistema UNIX considera a los dispositivos tambin como archivos, de manera que se utilizan las mismas funciones para escribir y leer de los dispositivos que las empleadas con ficheros habituales. Los archivos se manejan con la librera estndar del C mediante las estructuras de archivo FILE. Al ejecutar un programa en UNIX el sistema provee automticamente tres archivos al programa: la entrada estndar, la salida estndar y la salida de error estndar. El usuario no necesita realizar ninguna operacin previa de apertura para emplearlos. De hecho las funciones de entrada y salida estndar envan y recogen datos a travs de estos ficheros. Apertura y cierre de un fichero Para abrir un fichero primero debemos crear una variable de tipo puntero a FILE. Este puntero permitir realizar las operaciones necesarias sobre el fichero. Este puntero deber apuntar a una estructura de tipo FILE. Estas estructuras son creadas por el sistema operativo al abrir un fichero. Para poder inicializar nuestro puntero a fichero bastar llamar a la funcin fopen(). Esta funcin intenta abrir un fichero. Si tiene xito crear una estructura de tipo FILE y devuelve un puntero a FILE que apunta a la estructura creada. En caso de no poder abrir el fichero devuelve en puntero nulo. La funcin fopen() se define en la cabecera estndar stdio.h como: FILE *fopen( const char * filename, const char *modo); Necesita dos argumentos del tipo puntero a carcter. Cada uno de ellos debe apuntar a una cadena de caracteres. El primero indica el nombre del fichero a abrir. En UNIX y otros sistemas se puede especificar con el nombre del fichero el directorio donde se abrir el fichero. El segundo indica el modo en el que se abrir el fichero. Hay que tener cuidado en pasar un puntero a cadena de caracteres y no un solo carcter. Es fcil cometer la equivocacin de pasar como segundo argumento un carcter 'r' en vez de la cadena "r". Los modos ms frecuentes de abrir un fichero son: "r" Abre un fichero de texto que exista previamente para lectura. "w" Crea un fichero de texto para escritura si no existe el fichero con el nombre especificado, o trunca (elimina el anterior y crea uno nuevo) un fichero anterior

65

"a" Crea un fichero de texto si no existe previamente o abre un fichero de texto que ya exista para aadir datos al final del fichero. Al abrir el fichero el puntero del fichero queda posicionado a "rb" Funciona igual que "r" pero abre o crea el fichero en modo binario. "wb" Anlogo a "w" pero escribe en un fichero binario. "ab" Anlogo a "a" pero aade datos a un fichero binario. "r+" Abre un fichero de texto ya existente para lectura y escritura. "w+" Abre un fichero de texto ya existente o crea uno nuevo para lectura y escritura. "a+" Abre un fichero de texto ya existente o crea un fichero nuevo para lectura y escritura. El indicador de posicin del fichero queda posicionado al final del fichero an "r+b" "rb+" Funciona igual que "r+" pero lee y escribe en un fichero binario. "w+b" "wb+" Anlogo a "w+" pero en modo binario. "a+b" "ab+" Anlogo a "a+" pero en modo binario. Una llamada tpica a la funcin fopen() es la siguiente: FILE *fp; if (( fp = fopen( "mifichero", " r")) = = NULL) perror( "No puedo abrir el fichero mifichero\n"); /* imprime un mensaje de error */ Para cerrar un fichero basta llamar a la funcin fclose que se define en stdio.h como: int fclose(FILE *fichero); Su argumento es un puntero a una estructura FILE asociada a algn fichero abierto. Esta funcin devuelve 0 en caso de xito y EOF en caso de error. Lectura y escritura sobre un fichero Para leer y escribir en un fichero en modo texto se usan funciones anlogas a las de lectura y escritura de la entrada y salida estndar. La diferencia estriba en que siempre deberemos dar un puntero a FILE para indicar sobre que fichero efectuaremos la operacin, ya que podemos tener simultneamente abiertos varios ficheros. Las funciones que trabajar con ficheros tienen nombres

66

parecidos a las funciones de entrada y salida estndar, pero comienzan con la letra f. Las ms habituales son: int fprintf( FILE *fichero, const char *formato, ... ); /* trabaja igual que printf() sobre el fichero */ int fscanf( FILE *fichero, const char *formato, ... ); /* trabaja igual que scanf() sobre el fichero */ int fputs( const char *s, FILE *fichero ); /* escribe la cadena s en el fichero */ int fputc(int c, FILE *fichero); /* escribe el carcter c en el fichero */ int fgetc( FILE *fichero); /* lee un carcter del fichero */ char *fgets( char *s, int n, FILE * fichero); /* lee una lnea del fichero */ Hay una equivalencia entre las funciones de lectura y escritura estndar y las funciones de lectura y escritura de ficheros. Normalmente las funciones de lectura y escritura estndar se definen en la cabecea estndar como macros. As la lnea: printf("hola\n"); es equivalente a la escritura en el fichero stdout: fprintf(stdout, "hola\n"); A los ficheros stdin y stdout normalmente accederemos con las funciones de lectura y escritura estndar. Estos ficheros son automticamente abiertos y cerrados por el sistema. Para escribir en la salida de error estndar deberemos usar las funciones de ficheros con el fichero stderr. Normalmente en UNIX se redirige la salida de error estndar a la impresora. Esta salida de error es muy til en los procesos por lotes y cuando se usan filtros. Un filtro es simplemente un programa que lee datos de la entrada estndar, los procesa y los enva a la salida estndar. Por ello es conveniente que no se mezclen los mensajes de error con el resultado del proceso. Un ejemplo de filtro sera un programa que expande los caracteres de tabulacin en espacios en blanco. Si el programa se llama convierte y queremos procesar el fichero mifichero, debemos escribir la lnea: cat mifichero | convierte > nuevofichero

67

Hemos usado los mecanismos del UNIX de redireccion (> enva la salida estndar de un programa a un fichero), de tubera ( | conecta la salida estndar de un programa con la entrada estndar de otro) y la utilidad cat, que enva un fichero a la salida estndar. Lectura y escritura de datos binarios Para leer y escribir grupos de datos binarios, como por ejemplo arreglos y estructuras, la librera estndar provee dos funciones: fread() y fwrite(). Se declaran en stdio.h como: size_t fread(void *p, size_t longitud, size_t numelem, FILE *fichero); size_t fwrite(void *p, size_t longitud, size_t numelem, FILE *fichero); La funcin fread() lee del fichero pasado como ultimo argumento un conjunto de datos y lo almacena en el arreglo apuntado por p. Debemos especificar en longitud la longitud del tipo de datos a leer y en numelem el nmero de datos a leer. La funcin fwrite() se comporta igual que fread() pero escribe los datos desde la posicin apuntada por p en el fichero dado. Como siempre para usar estas funciones debemos abrir el fichero y cerrarlo despus de usarlas. Por ejemplo para leer un arreglo de 100 enteros: int arreglo[100]; FILE *fp; fp = fopen("mifichero", "rb"); fread(arreglo, sizeof(int), 100, fp); fclose(fp); Estas funciones devuelven el nmero de elementos ledos. Para comprobar si ha ocurrido un error en la lectura o escritura usaremos la funcin ferror(FILE *fichero), que simplemente devuelve un valor distinto de 0 si ha ocurrido un error al leer o escribir el fichero pasado como argumento. Al escribir datos binarios en un fichero debemos tener en cuenta consideraciones de portabilidad. Esto es debido a que el orden en que se almacenan los bytes que componen cada tipo de datos en la memoria puede variar de unos sistemas a otros, y las funciones fread() y fwrite() los leen y escriben segn est n en la memoria. Operaciones especiales con los ficheros Para comprobar si hemos alcanzado el fin de fichero, por ejemplo cuando leemos un fichero binario con fread(), podemos emplear la funcin feof(), que se define en stdio.h como: int feof( FILE *fichero); Esta funcin devuelve un 0 si no se ha alcanzado el fin de fichero y un valor distinto de 0 si se alcanz el fin de fichero.

68

Para comprobar si ha ocurrido un error en la lectura o escritura de datos en un fichero disponemos de la funcin ferror, que se declara en stdio.h como: int ferror( FILE *fichero); Esta funcin devuelve un valor distinto de 0 si ha ocurrido algn error en las operaciones con el fichero y un 0 en caso contrario. Estas dos funciones trabajan leyendo los indicadores de fin de fichero y error de la estructura FILE asociada a cada fichero. Podemos limpiar ambos indicadores utilizando la funcin clearerr(), que se define en stdio.h como: void clearerr( FILE *fichero); Posicionamiento del indicador de posicin del fichero Cuando se manejan ficheros de acceso aleatorio se necesita poder colocar el indicador de posicin del fichero en algn punto determinado del fichero. Para mover el puntero del fichero la librera estndar proporciona la funcin fseek(), que se define en stdio.h como: int fseek( FILE *fichero, long desplazamiento, int modo); La funcin devuelve un 0 si ha tenido xito y un valor diferente en caso de error. El argumento desplazamiento seala el nmero de caracteres que hay que desplazar el indicador de posicin. Puede ser positivo o negativo, o incluso 0, ya que hay tres modos diferentes de desplazar el indicador de posicin. Estos modos se indican con el argumento modo. En stdio.h se definen tres macros que dan los posibles modos. La macro SEEK_SET desplaza al indicador de posicin desde el comienzo del fichero. La macro SEK_CUR desplaza el indicador de posicin desde la posicin actual y la macro SEEK_END desplaza al indicador de posicin desde el final del fichero. Para este ultimo modo deberemos usar un valor de desplazamiento igual o menor que 0. Para ver en que posicin se halla el puntero del fichero podemos usar la funcin ftell(), que se define en stdio.h como: long ftell( FILE *fichero); Para un fichero binario ftell() devuelve el nmero de bytes que est desplazado el indicador de posicin del fichero desde el comienzo del fichero. Adems para llevar el indicador de posicin al comienzo del fichero tenemos la funcin rewind(), que se define en stdio.h como: void rewind( FILE * fichero); Esta funcin simplemente llama a fseek(fichero, 0L, SEEK_SET) y luego limpia el indicador de error. Entrada y salida con tampn Cuando la librera estndar abre un fichero le asocia un tampn (buffer) intermedio, que permite agilizar las lecturas y escrituras. As cada vez que se lee un dato del fichero primero se leen datos hasta llenar el tampn, y luego se van leyendo del tampn a medida que se solicitan. De este modo

69

se accede al sistema de ficheros ms eficientemente, ya que para leer un grupo de datos slo se efectan unas pocas lecturas del fichero. Este proceso se repite para la escritura de datos. Cuando se envan a un fichero se van almacenando temporalmente en el tampn y cuando se llena el tampn se escribe su contenido en el fichero. Esto plantea varios problemas. El primero es que siempre se debe vaciar el tampn cuando se cierra el fichero. Esto lo hace automticamente la funcin fclose(). Sin embargo las dems funciones no lo hacen. Por ello si estamos escribiendo datos en un fichero de lectura y escritura y queremos leer datos, primero debemos vaciar el tampn, para que los datos que leamos estn actualizados. Para ello la librera estndar proporciona la funcin fflush(), que se define en stdio.h como: int fflush( FILE *fichero); Esta funcin devuelve un 0 si tiene xito y EOF en caso de error. Adems si fichero es un puntero nulo entonces fflush() vaca los tampones de todos los fichero abiertos para escritura. Para alterar el tamao del tampn de un fichero podemos llamar a la funcin setvbuf() inmediatamente despus de abrir el fichero. Esta funcin se define en stdio.h como: int setvbuf(FILE *flujo, char *buffer, int modo, size_t longitud); El argumento longitud fija el tamao del tampn. Es argumento nos indica el tipo de tampn elegido. Hay tres tipos: tampn de lnea, tampn completo y sin tampn. Para especificar estos tres tipos de tampones se definen en stdio.h las macros _IOFBF (que indica tampn completo), _IOLBF (que indica tampn de lnea) y _IONBF ( que indica que el fichero no tiene tampn ). El argumento buffer apunta al lugar donde queremos que est el tampn. Si pasamos como argumento buffer un puntero nulo el sistema se encargar de reservar el lugar del tampn y lo liberar al cerrar el fichero. Podemos asignar a un fichero un tamao de tampn grande para que el sistema realice menor nmero de operaciones de lectura y escritura. si el fichero es interactivo( por ejemplo un terminal) quizs nos ser ms til ajustar el tampn al modo de lnea o incluido eliminar el tampn. Deberemos probar diferentes valores y modos para as determinar el mejor tampn a usar. Operaciones miscelneas con ficheros La librera estndar proporciona algunas funciones adicionales para manejar ficheros. Por ejemplo la funcin remove(), que se define en stdio.h como: int remove(const char *nombrefichero); Esta funcin elimina el fichero de nombre nombrefichero. Conviene cerrar el fichero antes de eliminarlo. Tambin disponemos de una funcin para renombrar el fichero. La funcin rename(), definida en stdio.h como: int rename(const char *antiguo, const char *nuevo); intenta renombrar al fichero de nombre antiguo. si tiene xito devuelve un 0. Hay que asegurarse antes de que no exista un fichero de nombre nuevo. Otra funcin para abrir ficheros es freopen(), que se define en stdio.h como:

70

FILE *freopen( const char *nombre, const char *modo, FILE *fichero); Esta funcin cierra el fichero pasado como tercer argumento y lo abre con el nuevo nombre y modo especificado. Devuelve un puntero a FILE que apunta al nuevo fichero abierto, o un puntero nulo en caso de error, tal y como lo hace fopen(). El Preprocesador de C El preprocesado es una parte de la compilacin en la que se hacen algunas tareas sencillas. Las fundamentales son: supresin de comentarios. expansin de macros. inclusin del cdigo de las cabeceras. conversin de las secuencias de escape en caracteres dentro de cadenas de caracteres y de constantes de tipo carcter.

El preprocesado puede ser de dos tipos: externo (lo realiza un programa adicional) o interno(se preprocesa y compila a la vez. En UNIX el preprocesado es externo, ya que lo hace el programa cpp, que es ejecutado automticamente por el compilador cc. Es bastante instructivo preprocesar un fichero y revisar el cdigo fuente resultante. Directivas de preprocesado Para realizar las diferentes acciones que admite el preprocesado disponemos de una serie de directivas de preprocesado, que son como comandos que instruyen al Preprocesador para realizar las expansiones. Todas las directivas del Preprocesador comienzan con el carcter # seguida del nombre de comando. El signo # debe estar al comienzo de una lnea, para que el Preprocesador lo pueda reconocer. La ms sencilla de las directivas es #include. Esta directiva debe ir seguida de un nombre de fichero. El nombre debe ir entrecomillado o encerrado entre signos de mayor y menor. Lo que hace el Preprocesador es sustituir la lnea donde se halla la directiva por el fichero indicado. Por ejemplo: #include <stdio.h> #include "stdio.h" La diferencia entre encerrar el nombre del fichero entre comillas o entre signos de mayor y menor es que al buscar el fichero con las comillas la bsqueda se hace desde el directorio actual, mientras que entre signos de mayor y menor la bsqueda se hace en un directorio especial. Este directorio vara con la implementacion, pero suele estar situado en el directorio del compilador. El Preprocesador y el compilador ya conocen donde se ubica el directorio. Todas las cabeceras estndar se hallan en ese directorio. Se puede incluir cualquier tipo de fichero fuente, pero lo habitual es incluir slo ficheros de cabecera. Hay que tener en cuenta que el fichero incluido es preprocesado. Esto permite expandir algunos tipos de macros y ajustar la cabecera al sistema mediante las directivas de preprocesado. Para ello se suelen usar macros que actan como banderas. Definicin de macros

71

En C una macro es un identificador que el Preprocesador sustituye por un conjunto de caracteres. Para definir una macro se dispone de la directiva #define. Su sintaxis es: #define identificador conjunto de caracteres Se utiliza habitualmente en los ficheros de cabecera para definir valores y constantes. Por ejemplo: #define EOF -1 #define SEEK_SET 0 #define BUFSIZ 512 Otro uso muy normal en los ficheros de cabecera emplear un smbolo definido con #define como bandera (selector para condiciones), utilizndolo con la directiva #ifdef. Una macro definida con #define no se puede redefinir a menos que la siguiente definicin coincida con la primera exactamente. Para redefinir una macro primero debemos eliminarla con la directiva #undef. Debemos acompaar a la directiva #undef con el nombre de la macro. Estilo de programacin: normas de indentacion Definicin de las normas de indentacion que se usar n a lo largo del curso en los programas en C. Se seguir n normas muy parecidas a las empleadas habitualmente por otros autores en libros recientes de programacin, con algunas variaciones propias. Estilo y disposicin general del programa. Cada archivo contendr en primer lugar un comentario donde se explicar brevemente el cometido del mismo. Por ejemplo: /* * HOLA.C Este programa imprime en mensage de saludo en la salida * estndar. */ A continuacin ir una lista de las cabeceras que se incluir n en l: #include <stdio.h> #include <stdlib.h> #include "hola.h" A continuacin la lista de variables globales: int i = 0,j,numero = 0,num2;

72

char c,temp; A continuacin la lista de declaracin de funciones, si no se usa un fichero de cabecera para este propsito. void impmensage(char *mensage); FILE *pidefichero(char *mensage); A continuacin la funcin main() y luego las dems. main(argc, argv) int argc; char *argv[]; { lista de variables locales; lista de sentencias; } Escritura de funciones Se comienza en la primera columna. Primero va el tipo de la funcin. Luego el nombre y la lista de argumentos. Entre el nombre y el parntesis de la lista de argumentos no se deja espacios en blanco. Detraes de cada coma que separa los argumentos se deja un espacio en blanco. Al final se cierra el parntesis. A continuacin va la declaracin de los tipos de los argumentos. Cada declaracin de tipo de argumento va en una lnea, precedida de un tabulador. A continuacin se abren las llaves de la funcin. Luego el cuerpo de la funcin, separando la lista de variables y la lista de declaracin de las funciones de las dems sentencias. Todas ellas tienen como mnimo un tabulador a la izquierda, no pudiendo empezar en la primera columna. Se finaliza con la llave de cierre. char *funcin1(arg1, arg2, arg3) int arg1; char *arg2; struct *sutipo arg3; { int i,

73

j; char *puntero; setencia1; . . sentencian; } Declaracin de variables Se tratar n de colocar por tipos en columnas, procurando que coincidan las comas y los puntos y comas: char carct1,c; Podremos incluir una breve explicacin de su uso: char temp; /* variable temporal */ Bucle while Si consta de una sola sentencia se separa la lnea de la expresin de la lnea de la sentencia. Se deja un espacio en blanco entre la palabra while y el parntesis de la expresin: while (expresin) sentencia; Si el bucle consta de un bloque de sentencias se aade la llave de comienzo de bloque detraes de la expresin, en la misma lnea. Las diferentes lneas del bloque las colocaremos debajo de la lnea de la expresin, colocndoles un tabulador al principio de cada lnea. Por ultimo, a la misma altura que las sentencias del bloque, colocaremos la llave de cierre: while (expresin) { /* comentario muy breve */ sentencia1; sentencia2; } Sentencia if/else Tras la palabra if, un espacio en blanco y la expresin entre parntesis.

74

La palabra else, si la hay, va a la misma altura que la palabra if. Como norma general seguiremos las mismas convenciones que para el bucle while en el asunto de los bloques y las sentencias, tanto para la para if como para else: if (expresin) sentencia1; else sentecia2; o tambin: if (expresin) { sentencia1; sentencia2; } else { sentencia3; sentencia4; } Forma general de un programa en C Declaraciones globales main( ) { variables locales sentencias } f1( ) { .........

75

} ... ... fn ( ) { ......... } Nombre de identificadores Son los nombres usados para referirse a las variables, funciones, etiquetas y otros objetos definidos por el usuario. La longitud de un identificador en Turbo C puede variar entre 1 y 32 caracteres. El primer carcter debe ser una letra o un smbolo de subrayado, los caracteres siguientes pueden ser letras, nmeros o smbolos de subrayado. Correcto: cont, cuenta23, balance_total Incorrecto: 1cont, hola!, balance...total En C las maysculas y las minsculas se tratan como distintas Tipos de datos Existen cinco tipos de datos atmicos: Tipo char int float double void bits 8 16 32 64 0 rango 0 a 255 -32.768 a 32.767 3,4 E -38 a 3,4 E +38 1,7 E -308 a 1,7 E +308 sin valor

(*) El void se usa para declarar funciones que no devuelven ningn valor o para declarar funciones sin parmetros. Modificadores de tipos signed unsigned long

76

short Los modificadores signed, unsigned, long y short se pueden aplicar a los tipos base entero y carcter. Sin embargo, long tambin se puede aplicar a double. Tipo char unsigned char Signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int float double long double bits 8 8 8 16 16 16 16 16 16 32 32 32 64 64 Rango -128 a 127 0 a 255 -128 a 127 -32.768 a 32.767 0 a 65.535 -32.768 a 32.767 -32.768 a 32.767 0 a 65.535 -32.768 a 32767 -2147483648 a 2147483647 -2147483648 a 2147483647 3,4 E -38 a 3,4 E +38 1,7 E -308 a 1,7 E +308 1,7 E -308 a 1,7 E +308

Modificadores de acceso Las variables de tipo const no pueden ser cambiadas durante la ejecucin del programa. Por ejemplo, const int a; Declaracin de variables Todas las variables han de ser declaradas antes de ser usadas. Forma general: tipo lista_de_variables; int i,j,l; short int si; Existen tres sitios donde se pueden declarar variables: dentro de las funciones (variables locales), en la definicin de parmetros de funciones (parmetros formales) y fuera de todas las funciones (variables globales). Variables externas Si una funcin situada en un fichero fuente desea utilizar una variable de este tipo declarada en otro fichero, la debe declarar (o mejor dicho referenciar) con la palabra extern. Archivo 1 Archivo 2

77

int x,y; extern int x,y; char ch; extern char ch; main ( ) void func1( ) { { x=120; x=y/10; . . . . . . . . . . . . . } } Variable estticas (static) Tienen memoria asignada durante toda la ejecucin del programa. Su valor es recordado incluso si la funcin donde est definida acaba y se vuelve a llamar ms tarde. Ejemplo: series (void) { static int num; num=num+23; return (num); } Variables registro El especificador register pide a Turbo C que mantenga el valor de una variable con ese especificador de forma que se permita el acceso ms rpido a la misma. Para enteros y carcteres esto significa colocarla en un registro de la CPU. Slo se puede aplicar a variables locales y a los parmetros fomales de una funcin. Son ideales para el control de bucles. pot_ent (int m, register int e) { register int temp; temp=1; for ( ; e; e--) temp *=m;

78

return (temp); } Sentencias de asignacin Forma general: nombre_variable = expresion; Abreviaturas en C x=x+10 <----------> x+=10 x=x-10 <----------> x-=10 Conversin de tipos Se da cuando se mezclan variables de un tipo con variables de otro tipo. El valor de la derecha de la asignacin se convierte al tipo del lado izquierdo. Puede haber prdida de los bits ms significativos en un caso como: short = long Inicializacin de variables Tipo nombre_variable = constante; char c='a'; int primero=0; float balance=123.23; Todas las variables globales se inicializan a cero sino se especifica otro valor inicial. Las variables locales y register tendrn valores desconocidos antes de que se lleve a cabo su primera asignacin. Constantes Tipo dato Ejemplo de constantes char 'a' '\n' '9' int 1 123 -234 float 123.23 Una constante de tipo cadena de caracteres est constituida por una secuencia de caracteres entre comillas dobles "Hola". Carcteres con barra invertida

79

\n Nueva lnea \t Tabulacin horizontal \b Espacio atrs \r Retorno de carro \f Salto de pgina \\ Barra invertida \' Comilla simple \" Comilla doble Operadores En C hay tres clases de operadores: aritmticos, relacionales y lgicos, y a nivel de bits. Aritmticos - resta + suma * producto / divisin % mdulo (resto de la divisin entera) -- decrementar ++ incrementar

x=10; x=10; y=++x; y=x++; y=11 y=10 Relacionales En C cierto es cualquier valor distinto de cero. Falso es cero. > mayor que >= mayor o igual que

80

< menor que <= menor o igual que == igual != distinto Lgicos && y || o ! no El operador ? Exp 1 ? Exp 2 : Exp 3 Se evala exp1 si es cierto se evala exp2 y toma ese valor para la expresin. Si exp1 es falso evala exp3 tomando su valor para la expresin. Ejemplo: x=10: y=x>9 ? 100 : 200 --------> y = 100 Los operadores de punteros & y * & devuelve la direccin de memoria del operando. Ejemplo: m=&cont; coloca en m la direccin de memoria de la variable cont & (la direccin de) * devuelve el valor de la variable ubicada en la direccin que se especifica. Ejemplo: q=*m; coloca el valor de cont en q. *(en la direccin) Sizeof Es un operador monario que devuelve la longitud, en bytes, de la variable o del especificador de tipo al que precede.

81

Ejemplo: flat f; printf ("%f",sizeof f); Mostrara 4 printf ("%d", sizeof (int)); Mostrara 2 El nombre del tipo debe ir entre parntesis. ESTRUCTURAS CONDICIONALES If if (expresion) { ............ ............ } else { ........... ........... } Switch switch (variable) { case cte1 : ........... ........... break; case cte2 : ........... ........... break; ..................

82

.................. default : ........... ........... } Switch slo puede comprobar la igualdad. BUCLES For for (inicializacin; condicin; incremento) sentencia inicializacin -> asignacin condicin -> expresin relacional Ejemplo: for (x=1; x<=100; x++) printf ("%d",x); Imprime los nmeros del 1 al 100 While while (condicin) sentencia; Ejemplo: while (c!='A') c=getchar( ); Do / While Analiza la condicin al final. do { ........... ........... } while (condicin); Break Tiene dos usos: para finalizar un case en una sentencia switch. para forzar la terminacin inmediata de un bucle.

83

Exit Para salir de un programa anticipadamente. Da lugar a la terminacin inmediata del programa, forzando la vuelta al S.O. Usa el archivo de cabecera stdlib.h Ejemplo: #include <stdlib.h> main (void) { if (!tarjeta_color( )) exit(1); jugar( ); } Continue Hace comenzar la iteracin siguiente del bucle, saltando as la secuencia de instrucciones comprendida entre el continue y el fin del bucle. do { scanf("%d",&num); if (x<0) continue; printf("%d",x); } while (x!=100); Funciones tipo nombre_funcion (lista de parametros) { ............ ............ } tipo, especifica el tipo de valor que devuelve la sentencia return de la funcin. Llamada por valor

84

Copia el valor de un argumento en el parmetro formal de la subrutina. Los cambios en los parmetros de la subrutina no afectan a las variables usadas en la llamada. int cuad (int x); main ( ) cuad (int x) { { int t=10; x=x*x; printf ("%d %d",cuad(t),t); return(x); return 0; } } Salida es << 100 10 >> Llamada por referencia Es posible causar una llamada por referencia pasando un puntero al argumento. Se pasa la direccin del argumento a la funcin, por tanto es posible cambiar el valor del argumento exterior de la funcin. int x,y; inter (int *x,int *y) inter (&x,&y); { int temp; temp=*x; *x=*y; *y=temp; } Arrays Todos los arrays tienen el 0 como ndice de su primer elemento. char p [10]; array de carcteres que tiene 10 elementos, desde p[0] hasta p[9]. Para pasar arrays unidimensionales a funciones, en la llamada a la funcin se pone el nombre del array sin ndice. Ejemplo:

85

main ( ) Si una funcin recibe un array unidimensional, se puede { declarar el parmetro formal como un puntero, como un int i[10]; array delimitado o como un array no delimitado. func1 (i); } func1 (int *x) /puntero/ func1 (int x[10]) /array delimitado/ func1 (int x[ ]) /array no delimitado/ Inicializacin de arrays Forma general de inicializacin de un array: tipo nombre_array [tamao] = {lista de valores}; lista de valores, es una lista de constantes separadas por comas, cuyo tipo es compatible con el tipo del array. La primera constante se coloca en la primera posicin del array, la segunda constante en la segunda posicin y as sucesivamente. Ejemplo: int i[10]={1,2,3,4,5,6,7,8,9,10}; Los arrays de carcteres que contienen cadenas permiten una inicializacin de la forma: char nombre_array [tamao]="cadena"; Se aade automticamente el terminador nulo al final de la cadena. Ejemplo char cad[5]="hola"; equivalentes char cad[5]={'h','o','l','a','\o'}; Es posible que C calcule automticamente las dimensiones de los arrays utilizando arrays indeterminados. Si en la inicializacin no se especifica el tamao el compilador crea un array suficientemente grande para contener todos los inicializadores presentes. char e1[ ]="error de lectura \n"; Cadenas

86

Aunque C no define un tipo cadena, estas se definen como un array de carcteres de cualquier longitud que termina en un carcter nulo ('\0'). Array que contenga 10 caracteres: char s[11]; Una constante de cadena es una lista de caracteres encerrada entre dobles comillas. Funciones de manejo de cadenas Archivo de cabecera string.h char *strcpy (char *s1, const char *s2); copia la cadena apuntada por s2 en la apuntada por s1. Devuelve s1. char *strcat (char *s1, consta char *s2); concatena la cadena apuntada por s2 en la apuntada por s1, devuelve s1. int strlen (const char *s1); devuelve la longitud de la cadena apuntada por s1. int strcmp (const char *s1, const char *s2); compara s1 y s2, devuelve 0 si con iguales, mayor que cero si s1>s2 y menor que cero si s1<s2. Las comparaciones se hacen alfabticamente. Arrays Bidimensionales Se declaran utilizando la siguiente forma general: tipo nombre_array [tamao 2 dim] [tamao 1 dim]; Ejemplo -> int d [10][20]; Cuando se utiliza un array bidimensional como argumento de una funcin realmente slo se pasa un puntero al primer elemento, pero la funcin que recibe el array tiene que definir al menos la longitud de la primera dimensin para que el compilador sepa la longitud de cada fila. Ejemplo: funcin que recibe un array bidimensional de dimensiones 5,10 se declara as: func1 (int x[ ][10]) { .................... } Arrays y Punteros Un nombre de array sin ndice es un puntero al primer elemento del array. Ejemplo: Estas sentencias son idnticas:

87

char p[10]; - p - &p[0] int *p, i[10]; p=i; ambas sentencias ponen el valor 100 en el sexto elemento de i. i[5]=100; *(p+5)=100; Esto tambin se puede aplicar con los arrays de dos o ms direcciones. int a[10][10]; a=&a[0][0]; a[0][4]=*((*a)+4); Memoria dinmica Malloc (n) reserva una porcin de memoria libre de n bytes y devuelve un puntero sobre el comienzo de dicho espacio. Free (p) libera la memoria apuntada con el puntero p.

Ambas funciones utilizan el archivo de cabecera stdlib.h Si no hay suficiente memoria libre para satisfacer la peticin, malloc ( ) devuelve un nulo. Ejemplo: char *p; p=malloc(1000); Estructuras La forma general de una definicin de estructura es: struct etiqueta { tipo nombre_variable; tipo nombre_variable; ............................. .............................

88

} variables _de_estructura Ejemplo: struct dir { char nombre[30]; char calle[40]; char ciudad[20]; char estado[3]; unsigned long int codigo; } info_dir; A los elementos individuales de la estructura se hace referencia utilizando . (punto). Ejemplo: info_dir.codigo = 12345; Forma general es: nombre_estructura.elemento Una estructura puede inicializarse igual que los vectores: struct familia { char apellido[10]; char nombrePadre[10]; char nombreMadre[10]; int numerohijos; } fam1={"Garcia","Juan","Maria",7}; Arrays de estructuras Se define primero la estructura y luego se declara una variable array de dicho tipo. Ejemplo: struct dir info_dir [100]; Para acceder a una determinada estructura se indexa el nombre de la estructura:

89

info_dir [2].codigo = 12345; Paso de estructuras a funciones Cuando se utiliza una estructura como argumento de una funcin, se pasa la estructura ntegra mediante el uso del mtodo estndar de llamada por valor. Ejemplo: struct tipo_estructura { int a,b; char c; }; void f1 (struct tipo_estructura param); main ( ) { struct tipo_estructura arg; arg.a = 1000; f1(arg); return 0; } void f1 (struct tipo_estructura param) { printf ("%d",param.a); } Punteros a estructuras Declaracin: struct dir * pruntero_dir; Existen dos usos principales de los punteros a estructuras: Para pasar la direccin de una estructura a una funcin. Para crear listas enlazadas y otras estructuras de datos dinmicas.

90

Para encontrar la direccin de una variable de estructura se coloca & antes del nombre de la estructura. Ejemplo: struct bal { float balance; char nombre[80]; } persona; struct bal *p; p = &persona; (coloca la direccin de la estructura persona en el puntero p) No podemos usar el operador punto para acceder a un elemento de la estructura a travs del puntero a la estructura. Debemos utilizar el operador flecha -> p -> balance Tipo enumerado enum identificador {lista de constantes simblicas}; Ejemplo: enum arcoiris {rojo, amarillo, verde, azul, blanco}; (realmente asigna rojo=0, amarillo=1, ...) printf ("%d %d", rojo, verde); imprime 0 2 en pantalla Podemos especificar el valor de uno o ms smbolos utilizando un inicializador. Lo hacemos siguiendo el smbolo con un signo igual y un valor entero. enum moneda {penique, niquel, diez_centavos, cuarto=100, medio_dolar, dolar}; Los valores son: penique 0, niquel 1, diez_centavos 2, cuarto 100, medio_dolar 101, dolar 102 Punteros int x=5, y=6; int *px, *py;

91

px=py; copia el contenido de py sobre px, de modo que px apuntar al mismo objeto que apunta py. *px=*py; copia el objeto apuntado por py a la direccin apuntada por px. px=&x; px apunta a x. py=0; hace que py apunte a nada (NULL). px++; apunta al elemento siguiente sobre el que apuntaba inicialmente Ejemplo:

Se puede sumar o restar enteros a y de punteros. p1=p1+9; p1 apunta al noveno elemento del tipo p1 que est ms all del elemento al que apunta actualmente. Punteros y arrays char cad[80], *p1; p1 = cad p1 ha sido asignado a la direccin del primer elemento del array cad. Para acceder al quinto elemento de cad se escribe: cad[4] o *(p1+4) Arrays de punteros Array de punteros a enteros: int *x [10];

92

Para asignar la direccin de una variable entera llamada var al tercer elemento del array de punteros, se escribe: x[2]=&var; Para encontrar el valor de var: *x[2] Punteros a punteros puntero -> variable Indireccin simple puntero -> puntero -> variable Indireccin mltiple float **balancenuevo; balancenuevo no es un puntero a un nmero en coma flotante, sino un puntero a un puntero a float. Ejemplo: main(void) { int x, *p, **q; x=10; p=&x; q=&p; printf("%d",**q); /* imprime el valor de x */ return 0; } E/S por consola getche ( ) lee un carcter del teclado, espera hasta que se pulse una tecla y entonces devuelve su valor. El eco de la tecla pulsada aparece automticamente en la pantalla. Requiere el archivo de cabecera conio.h putcahr ( ) imprime un carcter en la pantalla. Los prototipos son: int getche (void);

93

int putchar (int c); Ejemplo: main ( ) /* cambio de mayscula / minscula */ { char car; do { car=getche( ); if (islower(car)) putchar (toupper (car)); else putchar (tolower (car)); } while (car=!'.') } Hay dos variaciones de getche( ) : Getchar ( ): funcin de entrada de caracteres definida por el ANSI C. El problema es que guarda en un buffer la entrada hasta que se pulsa la tecla INTRO. Getch ( ): trabaja igual que getche( ) excepto que no muestra en la pantalla un eco del carcter introducido.

gets ( ) y puts ( ) Permiten leer y escribir cadenas de caracteres en la consola. gets ( ) lee una cadena de caracteres introducida por el teclado y la sita en la direccin apuntada por su argumento de tipo puntero a carcter. Su prototipo es: char * gets (char *cad); Ejemplo: main ( ) { char cad[80]; gets (cad); printf ("La longitud es %d", strlen (cad)); return 0;

94

} puts ( ) escribe su argumento de tipo cadena en la pantalla seguido de un carcter de salto de lnea. Su prototipo es: char * puts (const char *cad); E/S por consola con formato printf ( ) El prototipo de printf ( ) es: int printf (const char *cad_fmt, ...); La cadena de formato consiste en dos tipos de elementos: caracteres que se mostrarn en pantalla y rdenes de formato que empiezan con un signo de porcentaje y va seguido por el cdigo del formato. %c un nico caracter %d decimal %i decimal %e notacin cientfica %f decimal en coma flotante %o octal %s cadena de caracteres %u decimales sin signo %x hexadecimales %% imprime un signo % %p muestra un puntero Las rdenes de formato pueden tener modificadores que especifiquen la longitud del campo, nmero de decimales y el ajuste a la izquierda. Un entero situado entre % y el cdigo de formato acta como un especificador de longitud mnima de campo. Si se quiere rellenar con ceros, se pone un 0 antes del especificador de longitud de campo. %05 rellena con ceros un nmero con menos de 5 dgitos. %10.4f imprime un nmero de al menos diez caracteres con cuatro decimales.

95

Si se aplica a cadenas o enteros el nmero que sigue al punto especifica la longitud mxima del campo. %5.7s imprime una cadena de al menos cinco caracteres y no ms de siete. scanf ( ) Su prototipo es: int scanf ( ) (const char *cadena_fmt, ...); Ejemplo: scanf ("%d",&cuenta);

96

Curso de programacin en Java


1. INTRODUCCIN A JAVA
1.1 Origen de Java Sun Microsystems, lder en servidores para Internet, uno de cuyos lemas desde hace mucho tiempo es "the network is the computer" (lo que quiere dar a entender que el verdadero ordenador es la red en su conjunto y no cada mquina individual), es quien ha desarrollado el lenguaje Java, en un intento de resolver simultneamente todos los problemas que se le plantean a los desarrolladores de software por la proliferacin de arquitecturas incompatibles, tanto entre las diferentes mquinas como entre los diversos sistemas operativos y sistemas de ventanas que funcionaban sobre una misma mquina, aadiendo la dificultad de crear aplicaciones distribuidas en una red como Internet. He podido leer ms de cinco versiones distintas sobre el origen, concepcin y desarrollo de Java, desde la que dice que este fue un proyecto que rebot durante mucho tiempo por distintos departamentos de Sun sin que nadie le prestara ninguna atencin, hasta que finalmente encontr su nicho de mercado en la aldea global que es Internet; hasta la ms difundida, que justifica a Java como lenguaje de pequeos electrodomsticos. Hace algunos aos, Sun Microsystems decidi intentar introducirse en el mercado de la electrnica de consumo y desarrollar programas para pequeos dispositivos electrnicos. Tras unos comienzos dudosos, Sun decidi crear una filial, denominada FirstPerson Inc., para dar margen de maniobra al equipo responsable del proyecto. El mercado inicialmente previsto para los programas de FirstPerson eran los equipos domsticos: microondas, tostadoras y, fundamentalmente, televisin interactiva. Este mercado, dada la falta de pericia de los usuarios para el manejo de estos dispositivos, requera unos interfaces mucho ms cmodos e intuitivos que los sistemas de ventanas que proliferaban en el momento. Otros requisitos importantes a tener en cuenta eran la fiabilidad del cdigo y la facilidad de desarrollo. James Gosling, el miembro del equipo con ms experiencia en lenguajes de programacin, decidi que las ventajas aportadas por la eficiencia de C++ no compensaban el gran coste de pruebas y depuracin. Gosling haba estado trabajando en su tiempo libre en un lenguaje de programacin que l haba llamado Oak, el cual, an partiendo de la sintaxis de C++, intentaba remediar las deficiencias que iba observando. Los lenguajes al uso, como C o C++, deben ser compilados para un chip, y si se cambia el chip, todo el software debe compilarse de nuevo. Esto encarece mucho los desarrollos y el problema es especialmente acusado en el campo de la electrnica de consumo. La aparicin de un chip ms barato y, generalmente, ms eficiente, conduce inmediatamente a los fabricantes a incluirlo en las nuevas series de sus cadenas de produccin, por pequea que sea la diferencia en precio ya que, multiplicada por la tirada masiva de los aparatos, supone un ahorro considerable. Por tanto, Gosling decidi mejorar las caractersticas de Oak y utilizarlo. El primer proyecto en que se aplic este lenguaje recibi el nombre de proyecto Green y consista en un sistema de control completo de los aparatos electrnicos y el entorno de un hogar. Para ello se construy un ordenador experimental denominado *7 (Star Seven). El sistema presentaba una interfaz basada en la representacin de la casa de forma animada y el control se llevaba a cabo mediante una pantalla sensible al tacto. En el sistema apareca Duke, la actual mascota de Java.

97

Posteriormente se aplic a otro proyecto denominado VOD (Video On Demand) en el que se empleaba como interfaz para la televisin interactiva. Ninguno de estos proyectos se convirti nunca en un sistema comercial, pero fueron desarrollados enteramente en un Java primitivo y fueron como su bautismo de fuego. Una vez que en Sun se dieron cuenta de que a corto plazo la televisin interactiva no iba a ser un gran xito, urgieron a FirstPerson a desarrollar con rapidez nuevas estrategias que produjeran beneficios. No lo consiguieron y FirstPerson cerr en la primavera de 1994. Pese a lo que pareca ya un olvido definitivo, Bill Joy, cofundador de Sun y uno de los desarrolladores principales del Unix de Berkeley, juzg que Internet podra llegar a ser el campo de juego adecuado para disputar a Microsoft su primaca casi absoluta en el terreno del software, y vio en Oak el instrumento idneo para llevar a cabo estos planes. Tras un cambio de nombre y modificaciones de diseo, el lenguaje Java fue presentado en sociedad en agosto de 1995. Lo mejor ser hacer caso omiso de las historias que pretenden dar carta de naturaleza a la clarividencia industrial de sus protagonistas; porque la cuestin es si independientemente de su origen y entorno comercial, Java ofrece soluciones a nuestras expectativas. Porque tampoco vamos a desechar la penicilina aunque haya sido su origen fruto de la casualidad. 1.2 Caractersticas de Java Las caractersticas principales que nos ofrece Java respecto a cualquier otro lenguaje de programacin, son: Simple Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las caractersticas menos usadas y ms confusas de stos. C++ es un lenguaje que adolece de falta de seguridad, pero C y C++ son lenguajes ms difundidos, por ello Java se dise para ser parecido a C++ y as facilitar un rpido y fcil aprendizaje. Java elimina muchas de las caractersticas de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y aadir caractersticas muy tiles como el garbage collector (reciclador de memoria dinmica). No es necesario preocuparse de liberar memoria, el reciclador se encarga de ello y como es un thread de baja prioridad, cuando entra en accin, permite liberar bloques de memoria muy grandes, lo que reduce la fragmentacin de la memoria. Java reduce en un 50% los errores ms comunes de programacin con lenguajes como C y C++ al eliminar muchas de las caractersticas de stos, entre las que destacan: aritmtica de punteros no existen referencias registros (struct) definicin de tipos (typedef) macros (#define) necesidad de liberar memoria (free)

98

Aunque, en realidad, lo que hace es eliminar las palabras reservadas (struct, typedef), ya que las clases son algo parecido. Adems, el intrprete completo de Java que hay en este momento es muy pequeo, solamente ocupa 215 Kb de RAM. Orientado a objetos Java implementa la tecnologa bsica de C++ con algunas mejoras y elimina algunas cosas para mantener el objetivo de la simplicidad del lenguaje. Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las tres caractersticas propias del paradigma de la orientacin a objetos: encapsulacin, herencia y polimorfismo. Las plantillas de objetos son llamadas, como en C++, clases y sus copias, instancias. Estas instancias, como en C++, necesitan ser construidas y destruidas en espacios de memoria. Java incorpora funcionalidades inexistentes en C++ como por ejemplo, la resolucin dinmica de mtodos. Esta caracterstica deriva del lenguaje Objective C, propietario del sistema operativo Next. En C++ se suele trabajar con libreras dinmicas (DLLs) que obligan a recompilar la aplicacin cuando se retocan las funciones que se encuentran en su interior. Este inconveniente es resuelto por Java mediante una interfaz especfica llamada RTTI (RunTime Type Identification) que define la interaccin entre objetos excluyendo variables de instancias o implementacin de mtodos. Las clases en Java tienen una representacin en el runtime que permite a los programadores interrogar por el tipo de clase y enlazar dinmicamente la clase con el resultado de la bsqueda. Distribuido Java se ha construido con extensas capacidades de interconexin TCP/IP. Existen libreras de rutinas para acceder e interactuar con protocolos como http y ftp. Esto permite a los programadores acceder a la informacin a travs de la red con tanta facilidad como a los ficheros locales. La verdad es que Java en s no es distribuido, sino que proporciona las libreras y herramientas para que los programas puedan ser distribuidos, es decir, que se corran en varias mquinas, interactuando. Robusto Java realiza verificaciones en busca de problemas tanto en tiempo de compilacin como en tiempo de ejecucin. La comprobacin de tipos en Java ayuda a detectar errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaracin explcita de mtodos, reduciendo as las posibilidades de error. Maneja la memoria para eliminar las preocupaciones por parte del programador de la liberacin o corrupcin de memoria. Tambin implementa los arrays autnticos, en vez de listas enlazadas de punteros, con comprobacin de lmites, para evitar la posibilidad de sobreescribir o corromper memoria resultado de punteros que sealan a zonas equivocadas. Estas caractersticas reducen drsticamente el tiempo de desarrollo de aplicaciones en Java. Adems, para asegurar el funcionamiento de la aplicacin, realiza una verificacin de los bytecodes, que son el resultado de la compilacin de un programa Java. Es un cdigo de mquina virtual que es interpretado por el intrprete Java. No es el cdigo mquina directamente entendible por el hardware, pero ya ha pasado todas las fases del compilador: anlisis de instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecucin de rdenes.

99

Java proporciona, pues: Comprobacin de punteros Comprobacin de lmites de arrays Excepciones Verificacin de byte-codes Arquitectura neutral Para establecer Java como parte integral de la red, el compilador Java compila su cdigo a un fichero objeto de formato independiente de la arquitectura de la mquina en que se ejecutar. Cualquier mquina que tenga el sistema de ejecucin (run-time) puede ejecutar ese cdigo objeto, sin importar en modo alguno la mquina en que ha sido generado. Actualmente existen sistemas run-time para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando en el porting a otras plataformas.

El cdigo fuente Java se "compila" a un cdigo de bytes de alto nivel independiente de la mquina. Este cdigo (byte-codes) est diseado para ejecutarse en una mquina hipottica que es implementada por un sistema run-time, que s es dependiente de la mquina. En una representacin en que tuvisemos que indicar todos los elementos que forman parte de la arquitectura de Java sobre una plataforma genrica, obtendramos una figura como la siguiente:

100

En ella podemos ver que lo verdaderamente dependiente del sistema es la Mquina Virtual Java (JVM) y las libreras fundamentales, que tambin nos permitiran acceder directamente al hardware de la mquina. Adems, habr APIs de Java que tambin entren en contacto directo con el hardware y sern dependientes de la mquina, como ejemplo de este tipo de APIs podemos citar: Java 2D: grficos 2D y manipulacin de imgenes Java Media Framework : Elementos crticos en el tiempo: audio, video... Java Animation: Animacin de objetos en 2D Java Telephony: Integracin con telefona Java Share: Interaccin entre aplicaciones multiusuario Java 3D: Grficos 3D y su manipulacin Seguro La seguridad en Java tiene dos facetas. En el lenguaje, caractersticas como los punteros o el casting implcito que hacen los compiladores de C y C++ se eliminan para prevenir el acceso ilegal a la memoria. Cuando se usa Java para crear un navegador, se combinan las caractersticas del lenguaje con protecciones de sentido comn aplicadas al propio navegador. El lenguaje C, por ejemplo, tiene lagunas de seguridad importantes, como son los errores de alineacin. Los programadores de C utilizan punteros en conjuncin con operaciones aritmticas. Esto le permite al programador que un puntero referencie a un lugar conocido de la memoria y pueda sumar (o restar) algn valor, para referirse a otro lugar de la memoria. Si otros programadores conocen nuestras estructuras de datos pueden extraer informacin confidencial de nuestro sistema. Con un lenguaje como C, se pueden tomar nmeros enteros aleatorios y convertirlos en punteros para luego acceder a la memoria:

101

printf( "Escribe un valor entero: " ); scanf( "%u",&puntero ); printf( "Cadena de memoria: %s\n",puntero ); Otra laguna de seguridad u otro tipo de ataque, es el Caballo de Troya. Se presenta un programa como una utilidad, resultando tener una funcionalidad destructiva. Por ejemplo, en UNIX se visualiza el contenido de un directorio con el comando ls. Si un programador deja un comando destructivo bajo esta referencia, se puede correr el riesgo de ejecutar cdigo malicioso, aunque el comando siga haciendo la funcionalidad que se le supone, despus de lanzar su carga destructiva. Por ejemplo, despus de que el caballo de Troya haya enviado por correo el /etc/shadow a su creador, ejecuta la funcionalidad de ls persentando el contenido del directorio. Se notar un retardo, pero nada inusual. El cdigo Java pasa muchos tests antes de ejecutarse en una mquina. El cdigo se pasa a travs de un verificador de byte-codes que comprueba el formato de los fragmentos de cdigo y aplica un probador de teoremas para detectar fragmentos de cdigo ilegal -cdigo que falsea punteros, viola derechos de acceso sobre objetos o intenta cambiar el tipo o clase de un objeto-. Si los byte-codes pasan la verificacin sin generar ningn mensaje de error, entonces sabemos que: El cdigo no produce desbordamiento de operandos en la pila El tipo de los parmetros de todos los cdigos de operacin son conocidos y correctos. No ha ocurrido ninguna conversin ilegal de datos, tal como convertir enteros en punteros. El acceso a los campos de un objeto se sabe que es legal: public, private, protected. No hay ningn intento de violar las reglas de acceso y seguridad establecidas

El Cargador de Clases tambin ayuda a Java a mantener su seguridad, separando el espacio de nombres del sistema de ficheros local, del de los recursos procedentes de la red. Esto limita cualquier aplicacin del tipo Caballo de Troya, ya que las clases se buscan primero entre las locales y luego entre las procedentes del exterior. Las clases importadas de la red se almacenan en un espacio de nombres privado, asociado con el origen. Cuando una clase del espacio de nombres privado accede a otra clase, primero se busca en las clases predefinidas (del sistema local) y luego en el espacio de nombres de la clase que hace la referencia. Esto imposibilita que una clase suplante a una predefinida. En resumen, las aplicaciones de Java resultan extremadamente seguras, ya que no acceden a zonas delicadas de memoria o de sistema, con lo cual evitan la interaccin de ciertos virus. Java no posee una semntica especfica para modificar la pila de programa, la memoria libre o utilizar objetos y mtodos de un programa sin los privilegios del kernel del sistema operativo. Adems, para evitar modificaciones por parte de los crackers de la red, implementa un mtodo ultraseguro de autentificacin por clave pblica. El Cargador de Clases puede verificar una firma digital antes de realizar una instancia de un objeto. Por tanto, ningn objeto se crea y almacena en memoria, sin que se validen los privilegios de acceso. Es decir, la seguridad se integra en el momento de compilacin, con el nivel de detalle y de privilegio que sea necesario. Dada, pues la concepcin del lenguaje y si todos los elementos se mantienen dentro del estndar marcado por Sun, no hay peligro. Java imposibilita, tambin, abrir ningn fichero de la mquina local (siempre que se realizan operaciones con archivos, stas trabajan sobre el disco duro de la

102

mquina de donde parti el applet), no permite ejecutar ninguna aplicacin nativa de una plataforma e impide que se utilicen otros ordenadores como puente, es decir, nadie puede utilizar nuestra mquina para hacer peticiones o realizar operaciones con otra. Adems, los intrpretes que incorporan los navegadores de la Web son an ms restrictivos. Bajo estas condiciones (y dentro de la filosofa de que el nico ordenador seguro es el que est apagado, desenchufado, dentro de una cmara acorazada en un bunker y rodeado por mil soldados de los cuerpos especiales del ejrcito), se puede considerar que Java es un lenguaje seguro y que los applets estn libres de virus. Respecto a la seguridad del cdigo fuente, no ya del lenguaje, JDK proporciona un desemsamblador de byte-code, que permite que cualquier programa pueda ser convertido a cdigo fuente, lo que para el programador significa una vulnerabilidad total a su cdigo. Utilizando javap no se obtiene el cdigo fuente original, pero s desmonta el programa mostrando el algoritmo que se utiliza, que es lo realmente interesante. La proteccin de los programadores ante esto es utilizar llamadas a programas nativos, externos (incluso en C o C++) de forma que no sea descompilable todo el cdigo; aunque as se pierda portabilidad. Esta es otra de las cuestiones que Java tiene pendientes. Portable Ms all de la portabilidad bsica por ser de arquitectura independiente, Java implementa otros estndares de portabilidad para facilitar el desarrollo. Los enteros son siempre enteros y adems, enteros de 32 bits en complemento a 2. Adems, Java construye sus interfaces de usuario a travs de un sistema abstracto de ventanas de forma que las ventanas puedan ser implantadas en entornos Unix, Pc o Mac. Interpretado El intrprete Java (sistema run-time) puede ejecutar directamente el cdigo objeto. Enlazar (linkar) un programa, normalmente, consume menos recursos que compilarlo, por lo que los desarrolladores con Java pasarn ms tiempo desarrollando y menos esperando por el ordenador. No obstante, el compilador actual del JDK es bastante lento. Por ahora, que todava no hay compiladores especficos de Java para las diversas plataformas, Java es ms lento que otros lenguajes de programacin, como C++, ya que debe ser interpretado y no ejecutado como sucede en cualquier programa tradicional. Se dice que Java es de 10 a 30 veces ms lento que C, y que tampoco existen en Java proyectos de gran envergadura como en otros lenguajes. La verdad es que ya hay comparaciones ventajosas entre Java y el resto de los lenguajes de programacin, y una ingente cantidad de folletos electrnicos que supuran fanatismo en favor y en contra de los distintos lenguajes contendientes con Java. Lo que se suele dejar de lado en todo esto, es que primero habra que decidir hasta que punto Java, un lenguaje en pleno desarrollo y todava sin definicin definitiva, est maduro como lenguaje de programacin para ser comparado con otros; como por ejemplo con Smalltalk, que lleva ms de 20 aos en cancha. La verdad es que Java para conseguir ser un lenguaje independiente del sistema operativo y del procesador que incorpore la mquina utilizada, es tanto interpretado como compilado. Y esto no es ningn contrasentido, me explico, el cdigo fuente escrito con cualquier editor se compila generando el byte-code. Este cdigo intermedio es de muy bajo nivel, pero sin alcanzar las instrucciones mquina propias de cada plataforma y no tiene nada que ver con el p-code de Visual Basic. El byte-code corresponde al 80% de las instrucciones de la aplicacin. Ese mismo cdigo es el que se puede ejecutar sobre cualquier plataforma. Para ello hace falta el run-time, que s es completamente dependiente de la mquina y del sistema operativo, que interpreta dinmicamente

103

el byte-code y aade el 20% de instrucciones que faltaban para su ejecucin. Con este sistema es fcil crear aplicaciones multiplataforma, pero para ejecutarlas es necesario que exista el run-time correspondiente al sistema operativo utilizado. Multithreaded Al ser multithreaded (multihilvanado, en mala traduccin), Java permite muchas actividades simultneas en un programa. Los threads (a veces llamados, procesos ligeros), son bsicamente pequeos procesos o piezas independientes de un gran proceso. Al estar los threads contruidos en el lenguaje, son ms fciles de usar y ms robustos que sus homlogos en C o C++. El beneficio de ser miltithreaded consiste en un mejor rendimiento interactivo y mejor comportamiento en tiempo real. Aunque el comportamiento en tiempo real est limitado a las capacidades del sistema operativo subyacente (Unix, Windows, etc.), an supera a los entornos de flujo nico de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento. Cualquiera que haya utilizado la tecnologa de navegacin concurrente, sabe lo frustrante que puede ser esperar por una gran imagen que se est trayendo. En Java, las imgenes se pueden ir trayendo en un thread independiente, permitiendo que el usuario pueda acceder a la informacin en la pgina sin tener que esperar por el navegador. Dinamico Java se beneficia todo lo posible de la tecnologa orientada a objetos. Java no intenta conectar todos los mdulos que comprenden una aplicacin hasta el tiempo de ejecucin. Las librera nuevas o actualizadas no paralizarn las aplicaciones actuales (siempre que mantengan el API anterior).

Java tambin simplifica el uso de protocolos nuevos o actualizados. Si su sistema ejecuta una aplicacin Java sobre la red y encuentra una pieza de la aplicacin que no sabe manejar, tal como se ha explicado en prrafos anteriores, Java es capaz de traer automticamente cualquiera de esas piezas que el sistema necesita para funcionar. Java, para evitar que los mdulos de byte-codes o los objetos o nuevas clases, haya que estar trayndolos de la red cada vez que se necesiten, implementa las opciones de persistencia, para que no se eliminen cuando de limpie la cach de la mquina. Cul es la ventaja de todo esto?Qu gano con Java?

104

Primero: No debes volver a escribir el cdigo si quieres ejecutar el programa en otra mquina. Un solo cdigo funciona para todos los browsers compatibles con Java o donde se tenga una Mquina Virtual de Java (Mac's, PC's, Sun's, etc). Segundo: Java es un lenguaje de programacin orientado a objetos, y tiene todos los beneficios que ofrece esta metodologa de programacion (ms adelante doy una pequea introduccin a la filosofa de objetos). Tercero: Un browser compatible con Java deber ejecutar cualquier programa hecho en Java, esto ahorra a los usuarios tener que estar insertando "plug-ins" y dems programas que a veces nos quitan tiempo y espacio en disco. Cuarto: Java es un lenguaje y por lo tanto puede hacer todas las cosas que puede hacer un lenguaje de programacin: Clculos matemticos, procesadores de palabras, bases de datos, aplicaciones grficas, animaciones, sonido, hojas de clculo, etc. Quinto: Si lo que me interesa son las pginas de Web, ya no tienen que ser estticas, se le pueden poner toda clase de elementos multimedia y permiten un alto nivel de interactividad, sin tener que gastar en paquetes carsimos de multimedia.

Todo esto suena muy bonito pero tambien se tienen algunas limitantes: La velocidad. Los programas hechos en Java no tienden a ser muy rpidos, supuestamente se est trabajando en mejorar [Link] los programas de Java son interpretados nunca alcanzan la velocidad de un verdadero ejecutable. Java es un lenguaje de programacin. Esta es otra gran limitante, por ms que digan que es orientado a objetos y que es muy fcil de aprender sigue siendo un lenguaje y por lo tanto aprenderlo no es cosa fcil. Especialmente para los no programadores. Java es nuevo. En pocas palabras todava no se conocen bien todas sus capacidades.

Pero en general Java posee muchas ventajas y se pueden hacer cosas muy interesantes con esto. Hay que prestar especial atencin a lo que est sucediendo en el mundo de la computacin, a pesar de que Java es relativamente nuevo, posee mucha fuerza y es tema de moda en cualquier medio computacional. Muchas personas apuestan a futuro y piensan en Java. La pregunta es : Estarn en lo correcto? La verdad es que no se, pero este manual no es para filosofar sobre el futuro del lenguaje sino para aprender a programarlo. 1.3 HotJava HotJava, en pocas palabras, es un navegador con soporte Java (Java-enabled), desarrollado en Java. Como cualquier navegador de Web, HotJava puede decodificar HTML estndar y URLs estndares, aunque no soporta completamente el estndar HTML 3.0. La ventaja sobre el resto de navegadores, sin soporte Java, es que puede ejecutar programas Java sobre la red. La diferencia con Netscape, es que tiene implementado completamente los sistemas de seguridad que propone Java, esto significa que puede escribir y leer en el disco local, aunque esto hace disminuir la seguridad, ya que se pueden grabar en nuestro disco programas que contengan cdigo malicioso e introducirnos un virus, por ejemplo. No obstante, el utilizar esta caracterstica de HotJava es decisin del usuario. 1.4 Java para aplicaciones corporativas Java actualmente est en boca de todos, Java e Intranet son las palabras de moda. Pero, surge la pregunta de si esta es una buena tecnologa para desarrollar aplicaciones corporativas. Y la respuesta es afirmativa y voy a proponer argumentos para esa afirmacin. En donde la red sea algo crtico, Java facilita tremendamente la vida de la programacin corporativa.

105

Durante aos, las grandes empresas se han convencido de que la "red" corporativa es la arteria por donde fluye la sangre que mantiene vivo su negocio. Desde el gran servidor de sus oficinas centrales, hasta los servidores de las delegaciones, las estaciones de trabajo de los programadores y la marabunta de PCs, la informacin va fluyendo de unos a otros. Para muchas compaas, la Red es la Empresa. Si esta red no se mantiene sana, los pedidos no llegan, el inventario no se actualiza, el software no se desarrolla adecuadamente, los clientes no estn satisfechos y, fundamentalmente, el dinero no entra. La necesidad de diagnosticar y reducir la arterioesclerosis de la red, hace que se estn inyectando continuamente nuevas metodologas que subsanen este grave problema. Es Java la medicina? Est claro que cuando vemos un cepillo animado limpiando los dientes, cubos movindose en 3-D, o una banda de gatos locos en applets de Java, nos convencemos de que es el lenguaje idneo para Internet. Pero, qu pasa con las aplicaciones corporativas, sera una buena tecnologa all donde la red es el punto crtico? Vamos a intentar responder comparando las capacidades de Java contra la lista de necesidades de la red corporativa. Desarrollo rpido de aplicaciones Hace aos, se deca que los programadores pronto desapareceran. Los generadores automticos de programas, eliminaran a los generadores humanos y el mundo sera un lugar mejor para vivir. Desafortunadamente, quienes decan esto no tuvieron en cuenta una acelerada demanda de software de calidad para muy diferentes aplicaciones. Sin embargo, la tecnologa de objetos pronto vino a intentar facilitar la tarea, adoptando el modelo de "generar parte de un programa", as, generando la parte bsica de un programa (los objetos), se podra conectar con otras partes para proporcionar diferentes utilidades al usuario. El lenguaje C++ es una buena herramienta, pero no cumple totalmente la premisa. Visual Basic y NextStep, se acercan cada vez ms al poder de los objetos. Java facilita la creacin de entornos de desarrollo-aplicaciones de modo similar, pero adems es flexible, poderoso y efectivo. Los programadores ahora disponen de herramientas de programacin de calidad beta, que apuntan hacia esa meta, como son el Java WorkShop de SunSoft, el entorno Java de Borland, el Caf de Symantec, y pronto, herramientas ms sofisticadas como Netcode o FutureTense. Esto proporciona una gran progresin a los entornos de desarrollo Java. Aplicaciones efectivas y eficientes Las aplicaciones que se crean en grandes empresas deben ser ms efectivas que eficientes; es decir, conseguir que el programa funcione y el trabajo salga adelante es ms importante que el que lo haga eficientemente. Esto no es una crtica, es una realidad de la programacin corporativa. Al ser un lenguaje ms simple que cualquiera de los que ahora estn en el cajn de los programadores, Java permite a stos concentrarse en la mecnica de la aplicacin, en vez de pasarse horas y horas incorporando APIs para el control de las ventanas, controlando minuciosamente la memoria, sincronizando los ficheros de cabecera y corrigiendo los agnicos mensajes del linker. Java tiene su propio toolkit para interfaces, maneja por s mismo la memoria que utilice la aplicacin, no permite ficheros de cabecera separados (en aplicaciones puramente Java) y solamente usa enlace dinmico. Muchas de las implementaciones de Java actuales son puros intrpretes. Los byte-codes son interpretados por el sistema run-time de Java, la Mquina Virtual Java (JVM), sobre el ordenador del usuario. Aunque ya hay ciertos proveedores que ofrecen compiladores nativos Just-In-Time (JIT). Si la Mquina Virtual Java dispone de un compilador instalado, las secciones (clases) del byte-code de la aplicacin se compilarn hacia la arquitectura nativa del ordenador del usuario.

106

Los programas Java en ese momento rivalizarn con el rendimiento de programas en C++. Los compiladores JIT no se utilizan en la forma tradicional de un compilador; los programadores no compilan y distribuyen binarios Java a los usuarios. La compilacin JIT tiene lugar a partir del bytecode Java, en el sistema del usuario, como una parte (opcional) del entorno run-time local de Java. Muchas veces, los programadores corporativos, ansiosos por exprimir al mximo la eficiencia de su aplicacin, empiezan a hacerlo demasiado pronto en el ciclo de vida de la aplicacin. Java permite algunas tcnicas innovadoras de optimizacin. Por ejemplo, Java es inherentemente multithreaded, a la vez que ofrece posibilidades de multithread como la clase Thread y mecanismos muy sencillos de usar de sincronizacin; Java en s utiliza threads. Los desarrolladores de compiladores inteligentes pueden utilizar esta caracterstica de Java para lanzar un thread que compruebe la forma en que se est utilizando la aplicacin. Ms especficamente, este thread podra detectar qu mtodos de una clase se estn usando con ms frecuencia e invocar a sucesivos niveles de optimizacin en tiempo de ejecucin de la aplicacin. Cuanto ms tiempo est corriendo la aplicacin o el applet, los mtodos estarn cada vez ms optimizados (Guava de Softway es de este tipo). Si un compilador JIT est embebido en el entorno run-time de Java, el programador no se preocupa de hacer que la aplicacin se ejecute ptimamente. Siempre he pensado que en los Sistemas Operativos tendra que aplicarse esta filosofa; un optimizador progresivo es un paso ms hacia esta idea. Portabilidad para programador y programa En una empresa de relativo tamao hay una plyade diferente de ordenadores. Probablemente nos encontremos con estaciones de trabajo Sun para el desarrollo de software, hordas de PCs para cada empleado, algn Mac en el departamento de documentacin, una estacin de trabajo HP en administracin y una estacin SGI en la sala de demos. Desarrollar aplicaciones corporativas para un grupo tan diferente de plataformas en excesivamente complejo y caro. Hasta ahora era complicado convencer a los programadores de cada arquitectura que utilizasen un API comn para reducir el coste de las aplicaciones. Con un entorno run-time de Java portado a cada una de las arquitecturas de las plataformas presentes en la empresa y una buena librera de clases ("packages" en Java), los programadores pueden entenderse y encontrar muy interesante trabajar con Java. Esta posibilidad har tender a los programadores hacia Java, justo donde otros intentos anteriores con entornos universales (como Galaxy o XVT) han fracasado. Estos APIs eran simplemente inadecuados, no orientados a redes y, verdaderamente, pesados. Una vez que los programas estn escritos en Java, otro lado interesante del asunto es que los programadores tambin son portables. El grupo de programadores de la empresa puede ahora enfrentarse a un desarrollo para cualquiera de las plataformas. La parte del cliente y del servidor de una aplicacin estarn ahora escritas en el mismo lenguaje. Ya no ser necesario tener un grupo que desarrolle en Solaris en del departamento de I+D, programadores trabajando sobre Visual Basic en el departamento de documentacin y programadores sobre GNU en proyectos especiales; ahora todos ellos podrn estar juntos y formar el grupo de software de la empresa. Costes de desarrollo En contraste con el alto coste de los desarrollos realizados sobre estaciones de trabajo, el coste de creacin de una aplicacin Java es similar al de desarrollar sobre un PC. Desarrollar utilizando un software caro para una estacin de trabajo (ahora barata) es un problema en muchas empresas. La eficiencia del hardware y el poco coste de mantenimiento de una

107

estacin de trabajo Sun, por ejemplo, resulta muy atractivo para las empresas; pero el coste adicional del entorno de desarrollo con C++ es prohibitivo para la gran mayora de ellas. La llegada de Java e Intranet reducen considerablemente estos costes. Las herramientas Java ya no estn en el entorno de precios de millones de pesetas, sino a los niveles confortables de precio de las herramientas de PCs. Y con el crecimiento cada da mayor de la comunidad de desarrolladores de software freeware y shareware que incluso proporcionan el cdigo fuente, los programadores corporativos tienen un amplio campo donde moverse y muchas oportunidades de aprender y muchos recursos a su disposicin. El xito que Internet ha proporcionado a los equipos de software corporativos es un regalo. El precio del software es ahora el mismo para un poderoso equipo corriendo Unix que para un PC. Incluso Netscape tiene al mismo precio la versin Unix de su servidor Web SuiteSpot que la versin PC/NT. Esta es la filosofa de precios que parece ser ser la que se siga con las herramientas basadas en Java. Mantenimiento y soporte Un problema bien conocido que ocurre con el software corporativo es la demanda de cuidados y realimentacin. Java no es, ciertamente, la cura para la enfermedad del mantenimiento, pero tiene varias caractersticas que harn la vida del enfermero ms fcil. Uno de los componentes del JDK es javadoc. Si se usan ciertas convenciones en el cdigo fuente Java (como comenzar un comentario con /** y terminarlo con */), javadoc se puede fcilmente generar pginas HTML con el contenido de esos comentarios, que pueden visualizarse en cualquier navegador. La documentacin del API de Java ha sido creada de este modo. Esto hace que el trabajo de documentar el cdigo de nuevas clases Java sea trivial. Otro gran problema del desarrollador corporativo es la creacin y control de makefiles. Leerse un makefile es como estar leyendo la historia de empresa. Normalmente se pasan de programador a programador, quitando la informacin que no es esencial, siempre que se puede. Esto hace que muchos de los makefiles de las aplicaciones contengan docenas de libreras, una mirada de ficheros de cabecera y ultra-confusos macros. Es como mirar en el estmago de la ballena de Jons. Java reduce las dependencia de complejos makefiles drsticamente. Primero, no hay ficheros de cabecera. Java necesita que todo el cdigo fuente de una clase se encuentre en un solo fichero. Java tiene la inteligencia de make en el propio lenguaje para simplificar la compilacin de bytecodes. Por ejemplo: public class pepe { // Fichero: [Link] Guitarra flamenca ; } public class guitarra { // Fichero: [Link] } % javac -verbose [Link]

108

[parsed [Link] in 720ms] [loaded C:\JAVA\BIN\..\classes\java\lang\[Link] in 220ms] [checking class pepe] [parsed .\\[Link] in 50ms] [wrote [Link]] [checking class Guitarra] [wrote .\\[Link]] [done in 2300ms] El compilador Java se da cuenta de que necesita compilar el fichero [Link]. Ahora vamos a forzarlo a que recompile [Link] sin cambiar [Link], podremos comprobar que el compilador de byte-code Java no recompila innecesariamente el fichero [Link]. % javac -verbose [Link] [parsed [Link] in 440ms] [loaded C:\JAVA\BIN\..\classes\java\lang\[Link] in 160ms] [checking class pepe] [loaded .\\[Link] in 0ms] [wrote [Link]] [done in 1860ms] Ahora, si modificamos [Link] (aadiendo, por ejemplo, otro miembro a la clase) y compilamos [Link], el compilador Java se dar cuenta de que debe recompilar tanto [Link] como [Link] % javac -verbose [Link] [parsed [Link] in 710ms] [loaded C:\JAVA\BIN\..\classes\java\lang\[Link] in 220ms] [checking class pepe] [parsed .\\[Link] in 0ms] [wrote [Link]] [checking class Guitarra]

109

[wrote .\\[Link]] [done in 2640ms] En el libro Just Java de Peter van der Linden hay un captulo excelente acerca del compilador de Java, si tienes oportunidad, no dejes de leerlo. Aprendizaje Si la empresa est llena de programadores de C++ con alguna experiencia en el manejo de librera grficas, aprendern rpidamente lo esencial de Java. Si el equipo de ingenieros no conoce C++, pero maneja cualquier otro lenguaje de programacin orientada a objetos, les llevar pocas semanas dominar la base de Java. Lo que s que no es cierto es que haya que aprender C++ antes de aprender Java. Si los ingenieros de la empresa no conocen ningn lenguaje orientado a objetos, s que tienen que aprender los fundamentos de esta tecnologa antes de nada, y luego aplicarlos a la programacin con Java. El anlisis y diseo orientado a objetos debe ser comprendido antes de intentar nada con Java. Los programadores de Java sin un fondo de conocimientos de OOA/D producirn cdigo pobre. Adems, los libros sobre Java crecen como la espuma, ya hay ms de 25 publicados, y si buscas "Progamming in Java" en la Red, encontrars 312 Web sites, y 30 ms dedicados a "Learning Java". Y si esto, evidentemente, no es el sustituto de un instructor humano, hay ya varias empresas que ofrecen enseanza de Java, entre ellas, Sun.

2. INSTALACIN DEL JDK


Actualmente ya hay entornos de desarrollo integrados completos para Java, diferentes del JDK de Sun. Symantec dispone de un compilador de Java para Windows 95 y Windows NT, con las ventajas del aumento de velocidad de proceso y capacidades multimedia que esto proporciona, Symantec Caf. Borland tambin est trabajando en ello y la nueva versin de su entorno de desarrollo soporta Java. Sun ha lanzado la versin comercial de su propio entorno de desarrollo para Java, el Java Workshop, enteramente escrito en Java. Y Microsoft ha puesto en el mercado Visual J++, que sigue el estilo de todas sus herramientas de desarrollo. No obstante, trataremos solamente el JDK, que hasta el momento es lo ms conocido. El entorno bsico del JDK de Java que proporciona Sun est formado por herramientas en modo texto, que son: java, intrprete que ejecuta programas en byte-code. javac, compilador de Java que convierte el cdigo fuente en byte-code. javah, crea ficheros de cabecera para implementar mtodos para cualquier clase. javap, es un descompilador de byte-code a cdigo fuente Java. javadoc, es un generador automtico de documentos HTML a partir del cdigo fuente Java. javaprof, es un profiler para aplicaciones de un solo thread. HotJava, es un navegador Web escrito completamente en Java. El entorno habitual pues, consiste en un navegador que pueda ejecutar applets, un compilador que convierta el cdigo fuente Java a byte-code y el intrprete Java para ejecutar los programas. Estos son los componenetes bsicos para desarrollar algo en Java. No obstante se necesita un editor para escribir el cdigo fuente, y no son estrictamente necesarias otras herramientas como el debugger, un entorno visual, la documentacin o un visualizador de jerarqua de clases. Tan es as, que disponiendo del navegador Netscape 2.0 no se necesita ni tan siquiera el JDK (a peticin de varios amigos que disfrutan del uso de Linux pero no disponen de soporte ELF para poder utilizar el JDK portado por Randy Chapman, les indicar como conseguir utilizar el compilador embebido en Netscape). 2.1 Windows

110

La versin del JDK para Windows es un archivo autoextraible. Se necesitan alrededor de 6 Mb de espacio libre en disco. Ejecutar el fichero, que desempaquetar el contenido del archivo. El directorio donde se instale no es importante, pero supondremos que se instala en el raiz del disco C:, en cuyo caso los archivos colgarn de c:\java. Es necesario aadir c:\java\bin a la variable de entorno PATH. Adems de los ficheros java, el JDK incluye dos libreras dinmicas, [Link] y [Link], que se instalarn en el directorio de Java. Si tienes ninguna copia de estos ficheros en tu ordenador (probablemente en el directorio system de Windows) copia estos ficheros en el directorio c:\java\bin. Si estos ficheros ya estn en tu ordenador, elimina las copias extra que instala el JDK. 2.2 Solaris La versin del JDK para Solaris es un fichero tar comprimido. Se necesitan alrededor de 9 Mb de disco para descomprimir el JDK, aunque el doble de espacio sera una cifra ms cmoda. Ejecutar los siguientes comandos: % uncompress [Link].Z % tar xvf JDK-beta-solaris2-sparc-tar Puedes descomprimir el archivo en tu directorio home, o, si tienes privilegios de supervisor, en algn sitio ms conveniente de /usr/local para que todos los usuarios tengan acceso a los ficheros. Sin embargo, los privilegios del supervisor no son necesarios para instalar y ejecutar Java. Por simplicidad, supondr que has descomprimido el JDK en /usr/local, aunque el path completo donde se haga no tiene relevancia (tambin es posible colocarlo en /opt que es donde residen todas las aplicaciones de Solaris). Si lo has colocado en un sitio diferente, simplemente sustituye /usr/local por ese directorio (si lo has descomprimido en tu home, puedes utilizar ~/java y ~/hotjava, en vez del path completo). Es necesario aadir /usr/local/java/bin a la variable de entorno PATH. Utiliza el siguiente comando (suponiendo que tengas el shell csh o tcsh): set path=($PATH /usr/local/java/bin) Tambin puedes aadir esta lnea al final del fichero .profile y .cshrc, y ya tienes el sistema listo para ejecutar applets. Si quieres desembarazarte de la ventana que aparece cada vez que lances el appletviewer con la licencia de Sun, crea un directorio que se llame .hotjava en el directorio java/bin y ya no volvers a verla. 2.3 Linux Necesitas un kernel que soporte binarios ELF, por lo tanto tu Linux debe ser la versin 1.2.13 o superior, las anteriores tienen un bug que hacen que javac no funcione. Necesitas tambin Netscape, versin 2.0b4 o posterior. Sobre la versin 1.2.13 del kernel de Linux, hay que seguir los pasos que indico para conseguir que JDK funcione: Bajarse el JDK, [Link] y

[Link]-1.0 [Link] a /usr/local, descomprimirlo y hacer 'tar xvf'

111

En el fichero .java_wrapper (si no existe, crearlo) cambiar las variable J_HOME y PRG, para que queden como:

J_HOME=/usr/local/java PRG=/usr/local/java/bin Bajarse la librera [Link] a /, descomprimirla, hacer 'tar xvf'. Asegurarse de que /lib/[Link].5 es un link simblico a este nuevo [Link] no lo es, hacer el /lib 'ln -s [Link].5.2.18 [Link].5' Bajarse [Link] a un directorio temporal, descomprimirlo y hacer 'tar xvf'. Ejecutar '[Link]' y eliminar el directorio temporal. Aadir /usr/local/java a la variable de entorno PATH. Si se desea que est fijada para todos los usuarios, incorporar el directorio a la varible PATH que se fija en el fichero /etc/profile. Bajarse [Link].z a usr/local/netscape, descomprimirlo y hacer 'tar xvf' Crear un link en /usr/local/bin a /usr/local/netscape/netscape

Esto debera ser suficiente para compilar cualquier cosa en Java/Linux. En caso de tener problemas, es el momento de recurrir a las FAQ. Siguiendo los pasos indicados ya se puede ejecutar el ejemplo del Tic-Tac-Toe que propone la hoja de instalacin que Sun ha incluido en todas sus versiones y que en Linux consistira en cambiarse al directorio de la demo: % cd /usr/local/java/demo/TicTacToe ejecutar el visualizador de applets sobre la pgina html: % appletviewer [Link] y a jugar a las tres en raya. Por cierto, que el algoritmo que usa el ordenador est falseado por lo que es posible ganarle. 2.4 Compilacin sin JDK Parece raro, pero se puede conseguir. Lo nico necesario es el navegador Netscape 2.0. Este navegador, junto con la mquina virtual Java (JVM) y el sistema run-time, tiene un compilador Java. Si no se dispone del Java Development Kit (JDK), que no est disponible para todas las plataformas, pero s de la versin de Netscape para nuestra plataforma, aqu van los pasos a seguir para utilizar el compilador de Java embebido en Netscape.

112

Como necesito partir de algn punto para tomarlo como referencia, voy a suponer que estamos sobre Linux y que vamos a prescindir del JDK de Randy Chapman. Lo que habra que hacer sera lo siguiente. Primero. Instalar Netscape en el ordenador. Asegurarse de entender perfectamente y leerse hasta el final el fichero README, para seguir las instrucciones especficas de la instalacin de Netscape en la plataforma y que Netscape funcione perfectamente. En nuestro caso, en que vamos a intentar compilar cdigo Java con Netscape sobre Linux, la pieza clave es la situacin del fichero moz2_0.zip, que en mi mquina est en /usr/local/netscape/java/classes. Segundo. Extraer de una copia cualquiera del JDK (aunque sea de otra plataforma), el fichero java/lib/[Link] y guardarlo en el mismo sitio que el fichero moz2_0.zip; esta localizacin no es necesaria, pero simplifica la estructura. Tercero. Fijar la variable de entorno CLASSPATH para que Netscape pueda encontrar sus propias clases adems de las clases del Java de Sun. Asegurarse de incluir el "directorio actual", para poder compilar a la vez que se usan los ficheros .zip de Netscape y Sun. Por ejemplo:

setenv CLASSPATH .:/usr/local/netscape/java/classes/moz2_0.zip : /usr/local/netscape/java/classes/[Link] Cuarto. Compilar el cdigo Java (applet o aplicacin) con el comando: netscape -java [Link] [fichero].java (sustituir el nombre del fichero con el cdigo Java en vez de [fichero]). Esto convertir el cdigo fuente Java en byte-code, generndose el archivo [fichero].class. Quinto. Comprobar si se puede ejecutar la aplicacin con el comando:

netscape -java [clase] (sustituir el nombre de la clase de la aplicacin -la que contiene la rutina mainen vez de [clase]). Sexto. Si se ha compilado un applet Java, construir una pgina html que lo utilice para visualizarlo con el navegador en su forma normal. O tambin se puede visualizar utilizando el appletviewer, ejecutando:

netscape -java [Link] [clase] Desgraciadamente, la sentencia anterior no parece funcionar en todos los sistemas. Hay amigos mos que no han sido capaces de visualizar applets con este mtodo. Para aprovechar el tiempo, se puede crear un script que recoja los pasos 3, 4 y 6. Si estamos utilizando el csh, el contenido del script sera:

113

#/bin/csh -f setenv CLASSPATH .:/usr/local/netscape/java/classes/moz2_0.zip: /usr/local/netscape/java/classes/[Link] netscape -java [Link] $1 y lo almacenaramos como javac. Se ha de hacer el script ejecutable y cambiar /bin/csh por el path completo donde est situado el csh. De forma semejante podemos definir el intrprete java y el appletviewer, sustituyendo la lnea adecuada de llamada a Netscape.

3. CONCEPTOS BSICOS DE JAVA


3.1 Programacin en Java Cuando se programa en Java, se coloca todo el cdigo en mtodos, de la misma forma que se escriben funciones en lenguajes como C. Comentarios En Java hay tres tipos de comentarios: // comentarios para una sola lnea /* comentarios de una o ms lneas */ /** comentario de documentacin, de una o ms lneas */ Los dos primeros tipos de comentarios son los que todo programador conoce y se utilizan del mismo modo. Los comentarios de documentacin, colocados inmediatamente antes de una declaracin (de variable o funcin), indican que ese comentario ha de ser colocado en la documentacin que se genera automticamente cuando se utiliza la herramienta de Java, javadoc. Dichos comentarios sirven como descripcin del elemento declarado permitiendo generar una documentacin de nuestras clases escrita al mismo tiempo que se genera el cdigo. En este tipo de comentario para documentacin, se permite la introduccin de algunos tokens o palabras clave, que harn que la informacin que les sigue aparezca de forma diferente al resto en la documentacin. Identificadores Los identificadores nombran variables, funciones, clases y objetos; cualquier cosa que el programador necesite identificar o usar.

114

En Java, un identificador comienza con una letra, un subrayado (_) o un smbolo de dlar ($). Los siguientes caracteres pueden ser letras o dgitos. Se distinguen las maysculas de las minsculas y no hay longitud mxima. Seran identificadores vlidos: identificador nombre_usuario Nombre_Usuario _variable_del_sistema $transaccion y su uso sera, por ejemplo: int contador_principal; char _lista_de_ficheros; float $cantidad_en_Ptas; Palabras clave Las siguientes son las palabras clave que estn definidas en Java y que no se pueden utilizar como indentificadores: abstract continue for new switch boolean default goto null synchronized break do if package this byte double implements private threadsafe byvalue else import protected throw case extends instanceof public transient catch false int return true char final interface short try class finally long static void const float native super while Palabras Reservadas

115

Adems, el lenguaje se reserva unas cuantas palabras ms, pero que hasta ahora no tienen un cometido especfico. Son: cast future generic inner operator outer rest var Literales Un valor constante en Java se crea utilizando una representacin literal de l. Java utiliza cinco tipos de elementos: enteros, reales en coma flotante, booleanos, caracteres y cadenas, que se pueden poner en cualquier lugar del cdigo fuente de Java. Cada uno de estos literales tiene un tipo correspondiente asociado con l. Enteros: byte 8 bits complemento a dos short 16 bits complemento a dos int 32 bits complemento a dos long 64 bits complemento a dos Por ejemplo: 21 077 0xDC00 Reales en coma flotante: float 32 bits IEEE 754 double 64 bits IEEE 754 Por ejemplo: 3.14 2e12 3.1E12 Booleanos: true false Caracteres: Por ejemplo: a \t \u???? [????] es un nmero unicode Cadenas: Por ejemplo: "Esto es una cadena literal" Arrays Se pueden declarar en Java arrays de cualquier tipo:

116

char s[]; int iArray[]; Incluso se pueden construir arrays de arrays: int tabla[][] = new int[4][5]; Los lmites de los arrays se comprueban en tiempo de ejecucin para evitar desbordamientos y la corrupcin de memoria. En Java un array es realmente un objeto, porque tiene redefinido el operador []. Tiene una funcin miembro: length. Se puede utilizar este mtodo para conocer la longitud de cualquier array. int a[][] = new int[10][3]; [Link]; /* 10 */ a[0].length; /* 3 */ Para crear un array en Java hay dos mtodos bsicos. Crear un array vaco: int lista[] = new int[50]; o se puede crear ya el array con sus valores iniciales: String nombres[] = { "Juan","Pepe","Pedro","Maria" }; Esto que es equivalente a: String nombres[]; nombres = new String[4]; nombres[0] = new String( "Juan" ); nombres[1] = new String( "Pepe" ); nombres[2] = new String( "Pedro" ); nombres[3] = new String( "Maria" ); No se pueden crear arrays estticos en tiempo de compilacin: int lista[50]; // generar un error en tiempo de compilacin Tampoco se puede rellenar un array sin declarar el tamao con el operador new:

117

int lista[]; for( int i=0; i < 9; i++ ) lista[i] = i; Es decir, todos los arrays en Java son estticos. Para convertir un array en el equivalente a un array dinmico en C/C++, se usa la clase vector, que permite operaciones de insercin, borrado, etc. en el array. Operadores Los operadores de Java son muy parecidos en estilo y funcionamiento a los de C. En la siguiente tabla aparecen los operadores que se utilizan en Java, por orden de precedencia: . [] () ++ -! ~ instanceof

*/% +<< >> >>> < > <= >= == != &^| && || ?: = op= (*= /= %= += -= etc.) , Los operadores numricos se comportan como esperamos: int + int = int Los operadores relacionales devuelven un valor booleano. Para las cadenas, se pueden utilizar los operadores relacionales para comparaciones adems de + y += para la concatenacin: String nombre = "nombre" + "Apellido";

118

El operador = siempre hace copias de objetos, marcando los antiguos para borrarlos, y ya se encargar el garbage collector de devolver al sistema la memoria ocupada por el objeto eliminado. Separadores Slo hay un par de secuencias con otros caracteres que pueden aparecer en el cdigo Java; son los separadores simples, que van a definir la forma y funcin del cdigo. Los separadores admitidos en Java son: () - parntesis. Para contener listas de parmetros en la definicin y llamada a mtodos. Tambin se utiliza para definir precedencia en expresiones, contener expresiones para control de flujo y rodear las conversiones de tipo. {} - llaves. Para contener los valores de matrices inicializadas automticamente. Tambin se utiliza para definir un bloque de cdigo, para clases, mtodos y mbitos locales. [ ] - corchetes. Para declarar tipos matriz. Tambin se utiliza cuando se referencian valores de matriz. ; - punto y coma. Separa sentencias. , - coma. Separa identificadores consecutivos en una declaracin de variables. Tambin se utiliza para encadenar sentencias dentro de una sentencia for. . - punto. Para separar nombres de paquete de subpaquetes y clases. Tambin se utiliza para separar una variable o mtodo de una variable de referencia. 3.2 Control de Flujo Muchas de las sentencias de control del flujo del programa se han tomado del C: Sentencias de Salto if/else if( Boolean ) { sentencias; } else { sentencias; } switch switch( expr1 ) { case expr2:

119

sentencias; break; case expr3: sentencias; break; default: sentencias; break; } Sentencias de Bucle Bucles for for( expr1 inicio; expr2 test; expr3 incremento ) { sentencias; } El siguiente trocito de cdigo Java que dibuja varias lneas en pantalla alternando sus colores entre rojo, azul y verde. Este fragmento sera parte de una funcin Java (mtodo): int contador; for( contador=1; contador <= 12; contador++ ) { switch( contador % 3 ) { case 0: setColor( [Link] ); break; case 1: setColor( [Link] ); break; case 2:

120

setColor( [Link] ); break; } [Link]( 10,contador*10,80,contador*10 ); } Tambin se soporta el operador coma (,) en los bucles for for( a=0,b=0; a < 7; a++,b+=2 ) Bucles while while( Boolean ) { sentencias; } Bucles do/while do { sentencias; }while( Boolean ); Excepciones try-catch-throw try { sentencias; } catch( Exception ) { sentencias; } Java implementa excepciones para facilitar la construccin de cdigo robusto. Cuando ocurre un error en un programa, el cdigo que encuentra el error lanza una excepcin, que se puede capturar y recuperarse de ella. Java proporciona muchas excepciones predefinidas. Control General del Flujo break [etiqueta]

121

continue [etiqueta] return expr; etiqueta: sentencia; En caso de que nos encontremos con bucles anidados, se permite el uso de etiquetas para poder salirse de ellos, por ejemplo: uno: for( ) { dos: for( ) { continue; // seguira en el bucle interno continue uno; // seguira en el bucle principal break uno; // se saldra del bucle principal } } En el cdigo de una funcin siempre hay que ser consecuentes con la declaracin que se haya hecho de ella. Por ejemplo, si se declara una funcin para que devuelva un entero, es imprescindible que se coloque un return final para salir de esa funcin, independientemente de que haya otros en medio del cdigo que tambin provoquen la salida de la funcin. En caso de no hacerlo se generar un Warning, y el cdigo Java no se puede compilar con Warnings. int func() { if( a == 0 ) return 1; return 0; // es imprescindible porque se retorna un entero } 3.3 Clases Las clases son lo ms simple de Java. Todo en Java forma parte de una clase, es una clase o describe como funciona una clase. El conocimiento de las clases es fundamental para poder entender los programas Java.

122

Todas las acciones de los programas Java se colocan dentro del bloque de una clase o un objeto. Todos los mtodos se definen dentro del bloque de la clase, Java no soporta funciones o variables globales. Esto puede despistar a los programadores de C++, que pueden definir mtodos fuera del bloque de la clase, pero esta posibilidad es ms un intento de no separarse mucho y ser compatible con C, que un buen diseo orientado a objetos. As pues, el esqueleto de cualquier aplicacin Java se basa en la definicin de una clase. Todos los datos bsicos, como los enteros, se deben declarar en las clases antes de hacer uso de ellos. En C la unidad fundamental son los ficheros con cdigo fuente, en Java son las clases. De hecho son pocas las sentencias que se pueden colocar fuera del bloque de una clase. La palabra clave import (equivalente al #include) puede colocarse al principio de un fichero, fuera del bloque de la clase. Sin embargo, el compilador reemplazar esa sentencia con el contenido del fichero que se indique, que consistir, como es de suponer, en ms clases. Tipos de Clases Hasta ahora slo se ha utilizado la palabra clave public para calificar el nombre de las clases que hemos visto, pero hay tres modificadores ms. Los tipos de clases que podemos definir son: abstract Una clase abstract tiene al menos un mtodo abstracto. Una clase abstracta no se instancia, sino que se utiliza como clase base para la herencia. final Una clase final se declara como la clase que termina una cadena de herencia. No se puede heredar de una clase final. Por ejemplo, la clase Math es una clase final. public Las clases public son accesibles desde otras clases, bien sea directamente o por herencia. Son accesibles dentro del mismo paquete en el que se han declarado. Para acceder desde otros paquetes, primero tienen que ser importadas. synchronizable Este modificador especifica que todos los mtodos definidos en la clase son sincronizados, es decir, que no se puede acceder al mismo tiempo a ellos desde distintos threads; el sistema se encarga de colocar los flags necesarios para evitarlo. Este mecanismo hace que desde threads diferentes se puedan modificar las mismas variables sin que haya problemas de que se sobreescriban. 3.4 Variables y Mtodos de Instancia Una clase en Java puede contener variables y mtodos. Las variables pueden ser tipos primitivos como int, char, etc. Los mtodos son funciones. Por ejemplo, en el siguiente trozo de cdigo podemos observarlo: public MiClase { int i;

123

public MiClase() { i = 10; } public void Suma_a_i( int j ) { i = i + j; } } La clase MiClase contiene una variable (i) y dos mtodos, MiClase que es el constructor de la clase y Suma_a_i( int j ). Ambito de una variable Los bloques de sentencias compuestas en Java se delimitan con dos llaves. Las variables de Java slo son vlidas desde el punto donde estn declaradas hasta el final de la sentencia compuesta que la engloba. Se pueden anidar estas sentencias compuestas, y cada una puede contener su propio conjunto de declaraciones de variables locales. Sin embargo, no se puede declarar una variable con el mismo nombre que una de mbito exterior. El siguiente ejemplo intenta declarar dos variables separadas con el mismo nombre. En C y C++ son distintas, porque estn declaradas dentro de mbitos diferentes. En Java, esto es ilegal. Class Ambito { int i = 1; // mbito exterior { // crea un nuevo mbito int i = 2; // error de compilacin } } Mtodos y Constructores Los mtodos son funciones que pueden ser llamadas dentro de la clase o por otras clases. El constructor es un tipo especfico de mtodo que siempre tiene el mismo nombre que la clase. Cuando se declara una clase en Java, se pueden declarar uno o ms constructores opcionales que realizan la inicializacin cuando se instancia (se crea una ocurrencia) un objeto de dicha clase. Utilizando el cdigo de ejemplo anterior, cuando se crea una nueva instancia de MiClase, se crean (instancian) todos los mtodos y variables, y se llama al constructor de la clase: MiClase mc;

124

mc = new MiClase(); La palabra clave new se usa para crear una instancia de la clase. Antes de ser instanciada con new no consume memoria, simplemente es una declaracin de tipo. Despus de ser instanciado un nuevo objeto mc, el valor de i en el objeto mc ser igual a 10. Se puede referenciar la variable (de instancia) i con el nombre del objeto: mc.i++; // incrementa la instancia de i de mc Al tener mc todas las variables y mtodos de MiClase, se puede usar la primera sintaxis para llamar al mtodo Suma_a_i() utilizando el nuevo nombre de clase mc: mc.Suma_a_i( 10 ); y ahora la variable mc.i vale 21. Finalizadores Java no utiliza destructores (al contrario que C++) ya que tiene una forma de recoger automticamente todos los objetos que se salen del alcance. No obstante proporciona un mtodo que, cuando se especifique en el cdigo de la clase, el reciclador de memoria (garbage collector) llamar: // Cierra el canal cuando este objeto es reciclado protected void finalize() { close(); } 3.5 Alcance de Objetos y Reciclado de Memoria Los objetos tienen un tiempo de vida y consumen recursos durante el mismo. Cuando un objeto no se va a utilizar ms, debera liberar el espacio que ocupaba en la memoria de forma que las aplicaciones no la agoten (especialmente las grandes). En Java, la recoleccin y liberacin de memoria es responsabilidad de un thread llamado automatic garbage collector (recolector automtico de basura). Este thread monitoriza el alcance de los objetos y marca los objetos que se han salido de alcance. Veamos un ejemplo: String s; // no se ha asignado todavia s = new String( "abc" ); // memoria asignada s = "def"; // se ha asignado nueva memoria // (nuevo objeto) Ms adelante veremos en detalle la clase String, pero una breve descripcin de lo que hace esto es; crear un objeto String y rellenarlo con los caracteres "abc" y crear otro (nuevo) String y colocarle los caracteres "def".

125

En esencia se crean dos objetos: Objeto String "abc" Objeto String "def" Al final de la tercera sentencia, el primer objeto creado de nombre s que contiene "abc" se ha salido de alcance. No hay forma de acceder a l. Ahora se tiene un nuevo objeto llamado s y contiene "def". Es marcado y eliminado en la siguiente iteracin del thread reciclador de memoria. 3.6 Herencia La Herencia es el mecanismo por el que se crean nuevos objetos definidos en trminos de objetos ya existentes. Por ejemplo, si se tiene la clase Ave, se puede crear la subclase Pato, que es una especializacin de Ave. class Pato extends Ave { int numero_de_patas; } La palabra clave extends se usa para generar una subclase (especializacin) de un objeto. Una Pato es una subclase de Ave. Cualquier cosa que contenga la definicin de Ave ser copiada a la clase Pato, adems, en Pato se pueden definir sus propios mtodos y variables de instancia. Se dice que Pato deriva o hereda de Ave. Adems, se pueden sustituir los mtodos proporcionados por la clase base. Utilizando nuestro anterior ejemplo de MiClase, aqu hay un ejemplo de una clase derivada sustituyendo a la funcin Suma_a_i(): import MiClase; public class MiNuevaClase extends MiClase { public void Suma_a_i( int j ) { i = i + ( j/2 ); } } Ahora cuando se crea una instancia de MiNuevaClase, el valor de i tambin se inicializa a 10, pero la llamada al mtodo Suma_a_i() produce un resultado diferente: MiNuevaClase mnc; mnc = new MiNuevaClase(); mnc.Suma_a_i( 10 );

126

En Java no se puede hacer herencia mltiple. Por ejemplo, de la clase aparato con motor y de la clase animal no se puede derivar nada, sera como obtener el objeto toro mecnico a partir de una mquina motorizada (aparato con motor) y un toro (aminal). En realidad, lo que se pretende es copiar los mtodos, es decir, pasar la funcionalidad del toro de verdad al toro mecnico, con lo cual no sera necesaria la herencia mltiple sino simplemente la comparticin de funcionalidad que se encuentra implementada en Java a travs de interfaces. 3.7 Control de Acceso Cuando se crea una nueva clase en Java, se puede especificar el nivel de acceso que se quiere para las variables de instancia y los mtodos definidos en la clase: public public void CualquieraPuedeAcceder(){} Cualquier clase desde cualquier lugar puede acceder a las variables y mtodos de instacia pblicos. protected protected void SoloSubClases(){} Slo las subclases de la clase y nadie ms puede acceder a las variables y mtodos de instancia protegidos. private private String NumeroDelCarnetDeIdentidad; Las variables y mtodos de instancia privados slo pueden ser accedidos desde dentro de la clase. No son accesibles desde las subclases. friendly (sin declaracin especfica) void MetodoDeMiPaquete(){} Por defecto, si no se especifica el control de acceso, las variables y mtodos de instancia se declaran friendly (amigas), lo que significa que son accesibles por todos los objetos dentro del mismo paquete, pero no por los externos al paquete. Es lo mismo que protected. Los mtodos protegidos (protected) pueden ser vistos por las clases derivadas, como en C++, y tambin, en Java, por los paquetes (packages). Todas las clases de un paquete pueden ver los mtodos protegidos de ese paquete. Para evitarlo, se deben declarar como private protected, lo que hace que ya funcione como en C++ en donde slo se puede acceder a las variables y mtodos protegidos de las clases derivadas. 3.8 Variables y Mtodos Estticos En un momento determinado se puede querer crear una clase en la que el valor de una variable de instancia sea el mismo (y de hecho sea la misma variable) para todos los objetos instanciados a

127

partir de esa clase. Es decir, que exista una nica copia de la variable de instancia. Se usar para ello la palabra clave static. class Documento extends Pagina { static int version = 10; } El valor de la variable version ser el mismo para cualquier objeto instanciado de la clase Documento. Siempre que un objeto instanciado de Documento cambie la variable version, sta cambiar para todos los objetos. De la misma forma se puede declarar un mtodo como esttico, lo que evita que el mtodo pueda acceder a las variables de instancia no estticas: class Documento extends Pagina { static int version = 10; int numero_de_capitulos; static void annade_un_capitulo() { numero_de_capitulos++; // esto no funciona } static void modifica_version( int i ) { version++; // esto si funciona } } La modificacin de la variable numero_de_capitulos no funciona porque se est violando una de las reglas de acceso al intentar acceder desde un mtodo esttico a una variable no esttica. Todas las clases que se derivan, cuando se declaran estticas, comparten la misma pgina de variables; es decir, todos los objetos que se generen comparten la misma zona de memoria. Las funciones estticas se usan para acceder solamente a variables estticas. class UnaClase { int var; UnaClase() { var = 5;

128

} UnaFuncion() { var += 5; } } En el cdigo anterior, si se llama a la funcin UnaFuncion a travs de un puntero a funcin, no se podra acceder a var, porque al utilizar un puntero a funcin no se pasa implcitamente el puntero al propio objeto (this). Sin embargo, s se podra acceder a var si fuese esttica, porque siempre estara en la misma posicin de memoria para todos los objetos que se creasen de UnaClase. 3.9 this Y super Al acceder a variables de instancia de una clase, la palabra clave this hace referencia a los miembros de la propia clase. Volviendo al ejemplo de MiClase, se puede aadir otro constructor de la forma siguiente: public class MiClase { int i; public MiClase() { i = 10; } // Este constructor establece el valor de i public MiClase( int valor ) { this.i = valor; // i = valor } public void Suma_a_i( int j ) { i = i + j; } } Aqu this.i se refiere al entero i en la clase MiClase.

129

Si se necesita llamar al mtodo padre dentro de una clase que ha reemplazado ese mtodo, se puede hacer referencia al mtodo padre con la palabra clave super: import MiClase; public class MiNuevaClase extends MiClase { public void Suma_a_i( int j ) { i = i + ( j/2 ); super.Suma_a_i( j ); } } En el siguiente cdigo, el constructor establecer el valor de i a 10, despus lo cambiar a 15 y finalmente el mtodo Suma_a_i() de la clase padre (MiClase) lo dejar en 25: MiNuevaClase mnc; mnc = new MiNuevaClase(); mnc.Suma_a_i( 10 ); 3.10 Clases Abstractas Una de las caractersticas ms tiles de cualquier lenguaje orientado a objetos es la posibilidad de declarar clases que definen como se utiliza solamente, sin tener que implementar mtodos. Esto es muy til cuando la implementacin es especfica para cada usuario, pero todos los usuarios tienen que utilizar los mismos mtodos. Un ejemplo de clase abstracta en Java es la clase Graphics: public abstract class Graphics { public abstract void drawLine( int x1,int y1,int x2, int y2 ); public abstract void drawOval( int x,int y,int width, int height ); public abstract void drawArc( int x,int y,int width, int height,int startAngle,int arcAngle ); .. }

130

Los mtodos se declaran en la clase Graphics, pero el cdigo que ejecutar el mtodo est en algn otro sitio: public class MiClase extends Graphics { public void drawLine( int x1,int y1,int x2,int y2 ) { <cdigo para pintar lneas -especfico de la arquitectura-> } } Cuando una clase contiene un mtodo abstracto tiene que declararse abstracta. No obstante, no todos los mtodos de una clase abstracta tienen que ser abstractos. Las clases abstractas no pueden tener mtodos privados (no se podran implementar) ni tampoco estticos. Una clase abstracta tiene que derivarse obligatoriamente, no se puede hacer un new de una clase abstracta. Una clase abstracta en Java es lo mismo que en C++ virtual func() = 0; lo que obliga a que al derivar de la clase haya que implementar forzosamente los mtodos de esa clase abstracta. 3.11 Interfaces Los mtodos abstractos son tiles cuando se quiere que cada implementacin de la clase parezca y funcione igual, pero necesita que se cree una nueva clase para utilizar los mtodos abstractos. Los interfaces proporcionan un mecanismo para abstraer los mtodos a un nivel superior. Un interface contiene una coleccin de mtodos que se implementan en otro lugar. Los mtodos de una clase son public, static y final. La principal diferencia entre interface y abstract es que un interface proporciona un mecanismo de encapsulacin de los protocolos de los mtodos sin forzar al usuario a utilizar la herencia. Por ejemplo: public interface VideoClip { // comienza la reproduccion del video void play(); // reproduce el clip en un bucle void bucle(); // detiene la reproduccion void stop();

131

} Las clases que quieran utilizar el interface VideoClip utilizarn la palabra implements y proporcionarn el cdigo necesario para implementar los mtodos que se han definido para el interface: class MiClase implements VideoClip { void play() { <cdigo> } void bucle() { <cdigo> } void stop() { <cdigo> } Al utilizar implements para el interface es como si se hiciese una accin de copiar-y-pegar del cdigo del interface, con lo cual no se hereda nada, solamente se pueden usar los mtodos. La ventaja principal del uso de interfaces es que una clase interface puede ser implementada por cualquier nmero de clases, permitiendo a cada clase compartir el interfaz de programacin sin tener que ser consciente de la implementacin que hagan las otras clases que implementen el interface. class MiOtraClase implements VideoClip { void play() { <cdigo nuevo> } void bucle() { <cdigo nuevo> } void stop() { <cdigo nuevo>

132

} 3.12 Mtodos Nativos Java proporciona un mecanismo para la llamada a funciones C y C++ desde nuestro cdigo fuente Java. Para definir mtodos como funciones C o C++ se utiliza la palabra clave native. public class Fecha { int ahora; public Fecha() { ahora = time(); } private native int time(); static { [Link]( "time" ); } } Una vez escrito el cdigo Java, se necesitan ejecutar los pasos siguientes para poder integrar el cdigo C o C++: Utilizar javah para crear un fichero de cabecera (.h) Utilizar javah para crear un fichero de stubs, es decir, que contiene la declaracin de las funciones Escribir el cdigo del mtodo nativo en C o C++, es decir, rellenar el cdigo de la funcin, completando el trabajo de javah al crear el fichero de stubs Compilar el fichero de stubs y el fichero .c en una librera de carga dinmica (DLL en Windows '95 o [Link] en Unix) Ejecutar la aplicacin con el appletviewer

Ms adelante trataremos en profundidad los mtodos nativos, porque aaden una gran potencia a Java, al permitirle integrar a travs de librera dinmica cualquier algoritmo desarrollado en C o C+ +, lo cual, entre otras cosas, se utiliza como mtodo de proteccin contra la descompilacin completa del cdigo Java. 3.13 Paquetes La palabra clave package permite agrupar clases e interfaces. Los nombres de los paquetes son palabras separadas por puntos y se almacenan en directorios que coinciden con esos nombres. Por ejemplo, los ficheros siguientes, que contienen cdigo fuente Java: [Link], [Link], [Link], [Link]

133

contienen en su cdigo la lnea: package [Link]; Y las clases que se obtienen de la compilacin de los ficheros anteriores, se encuentran con el nombre nombre_de_clase.class, en el directorio: java/applet Import Los paquetes de clases se cargan con la palabra clave import, especificando el nombre del paquete como ruta y nombre de clase (es lo mismo que #include de C/C++). Se pueden cargar varias clases utilizando un asterisco. import [Link]; import [Link].*; Si un fichero fuente Java no contiene ningn package, se coloca en el paquete por defecto sin nombre. Es decir, en el mismo directorio que el fichero fuente, y la clase puede ser cargada con la sentencia import: import MiClase; Paquetes de Java El lenguaje Java proporciona una serie de paquetes que incluyen ventanas, utilidades, un sistema de entrada/salida general, herramientas y comunicaciones. En la versin actual del JDK, los paquetes Java que se incluyen son: [Link] Este paquete contiene clases diseadas para usar con applets. Hay una clase Applet y tres interfaces: AppletContext, AppletStub y AudioClip. [Link] El paquete Abstract Windowing Toolkit (awt) contiene clases para generar widgets y componentes GUI (Interfaz Grfico de Usuario). Incluye las clases Button, Checkbox, Choice, Component, Graphics, Menu, Panel, TextArea y TextField. [Link] El paquete de entrada/salida contiene las clases de acceso a ficheros: FileInputStream y FileOutputStream. [Link] Este paquete incluye las clases del lenguaje Java propiamente dicho: Object, Thread, Exception, System, Integer, Float, Math, String, etc.

134

[Link] Este paquete da soporte a las conexiones del protocolo TCP/IP y, adems, incluye las clases Socket, URL y URLConnection. [Link] Este paquete es una miscelnea de clases tiles para muchas cosas en programacin. Se incluyen, entre otras, Date (fecha), Dictionary (diccionario), Random (nmeros aleatorios) y Stack (pila FIFO). 3.14 Referencias Java se asemeja mucho a C y C++. Esta similitud, evidentemente intencionada, es la mejor herramienta para los programadores, ya que facilita en gran manera su transicin a Java. Desafortunadamente, tantas similitudes hacen que no nos paremos en algunas diferencias que son vitales. La terminologa utilizada en estos lenguajes, a veces es la misma, pero hay grandes diferencias subyacentes en su significado. C tiene tipos de datos bsicos y punteros. C++ modifica un poco este panorama y le aade los tipos referencia. Java tambin especifica sus tipos primitivos, elimina cualquier tipo de punteros y tiene tipos referencia mucho ms claros. Todo este maremgnum de terminologa provoca cierta consternacin, as que vamos a intentar aclarar lo que realmente significa. Conocemos ya ampliamente todos los tipos bsicos de datos: datos base, integrados, primitivos e internos; que son muy semejantes en C, C++ y Java; aunque Java simplifica un poco su uso a los desarrolladores haciendo que el chequeo de tipos sea bastante ms rgido. Adems, Java aade los tipos boolean y hace imprescindible el uso de este tipo booleano en sentencias condicionales.

4. PROGRAMAS BSICOS EN JAVA


4.1 Una mnima aplicacin en java La aplicacin ms pequea posible es la que simplemente imprimir un mensaje en la pantalla. Tradicionalmente, el mensaje suele ser "Hola Mundo!". Esto es justamente lo que hace el siguiente fragmento de cdigo: // // Aplicacin HolaMundo de ejemplo // class HolaMundoApp { public static void main( String args[] ) { [Link]( "Hola Mundo!" ) ; }

135

} HolaMundo Vamos ver en detalle la aplicacin anterior, lnea a lnea. Esas lneas de cdigo contienen los componenetes mnimos para imprimir Hola Mundo! en la pantalla. // // Aplicacin HolaMundo de ejemplo // Estas tres primera lneas son comentarios. Hay tres tipos de comentarios en Java, // es un comentario orientado a lnea. class HolaMundoApp { Esta lnea declara la clase HolaMundoApp. El nombre de la clase especificado en el fichero fuente se utiliza para crear un fichero [Link] en el directorio en el que se compila la aplicacin. En nuestro caso, el compilador crear un fichero llamado [Link]. public static void main( String args[] ) { Esta lnea especifica un mtodo que el intrprete Java busca para ejecutar en primer lugar. Igual que en otros lenguajes, Java utiliza una palabra clave main para especificar la primera funcin a ejecutar. En este ejemplo tan simple no se pasan argumentos. public significa que el mtodo main puede ser llamado por cualquiera, incluyendo el intrprete Java. static es una palabra clave que le dice al compilador que main se refiere a la propia clase HolaMundoApp y no a ninguna instancia de la clase. De esta forma, si alguien intenta hacer otra instancia de la clase, el mtodo main no se instanciara. void indica que main no devuelve nada. Esto es importante ya que Java realiza una estricta comprobacin de tipos, incluyendo los tipos que se ha declarado que devuelven los mtodos. args[] es la declaracin de un array de Strings. Estos son los argumentos escritos tras el nombre de la clase en la lnea de comandos: %java HolaMundoApp arg1 arg2 ... [Link]( "Hola Mundo!" ); Esta es la funcionalidad de la aplicacin. Esta lnea muestra el uso de un nombre de clase y mtodo. Se usa el mtodo println() de la clase out que est en el paquete System. El mtodo println() toma una cadena como argumento y la escribe en el stream de salida estndar; en este caso, la ventana donde se lanza la aplicacin. }

136

} Finalmente, se cierran las llaves que limitan el mtodo main() y la clase HolaMundoApp. Compilacion y Ejecucion de HolaMundo Vamos a ver a continuacin como podemos ver el resultado de nuestra primera aplicacin Java en pantalla. Generaremos un fichero con el cdigo fuente de la aplicacin, lo compilaremos y utilizaremos el intrprete java para ejecutarlo. Ficheros Fuente Java Los ficheros fuente en Java terminan con la extensin ".java". Crear un fichero utilizando cualquier editor de texto ascii que tenga como contenido el cdigo de las ocho lneas de nuestra mnima aplicacin, y salvarlo en un fichero con el nombre de [Link]. Para crear los ficheros con cdigo fuente Java no es necesario un procesador de textos, aunque puede utilizarse siempre que tenga salida a fichero de texto plano o ascii, sino que es suficiente con cualquier otro editor. Compilacin El compilador javac se encuentra en el directorio bin por debajo del directorio java, donde se haya instalado el JDK. Este directorio bin, si se han seguido las instrucciones de instalacin, debera formar parte de la variable de entorno PATH del sistema. Si no es as, tendra que revisar la Instalacin del JDK. El compilador de Java traslada el cdigo fuente Java a byte-codes, que son los componentes que entiende la Mquina Virtual Java que est incluida en los navegadores con soporte Java y en appletviewer. Una vez creado el fichero fuente [Link], se puede compilar con la lnea siguiente: %javac [Link] Si no se han cometido errores al teclear ni se han tenido problemas con el path al fichero fuente ni al compilador, no debera aparecer mensaje alguno en la pantalla, y cuando vuelva a aparecer el prompt del sistema, se debera ver un fichero [Link] nuevo en el directorio donde se encuentra el fichero fuente. Si ha habido algn problema, en Problemas de compilacin al final de esta seccin, hemos intentado reproducir los que ms frecuentemente se suelen dar, se pueden consultar por si pueden aportar un poco de luz al error que haya aparecido. Ejecucin Para ejecutar la aplicacin HolaMundoApp, hemos de recurrir al intrprete java, que tambin se encuentra en el directorio bin, bajo el directorio java. Se ejecutar la aplicacin con la lnea: %java HolaMundoApp y debera aparecer en pantalla la respuesta de Java: %Hola Mundo!

137

El smbolo % representa al prompt del sistema, y lo utilizaremos para presentar las respuestas que nos ofrezca el sistema como resultado de la ejecucin de los comandos que se indiquen en pantalla o para indicar las lneas de comandos a introducir. Problemas de compilacin A continuacin presentamos una lista de los errores ms frecuentes que se presentan a la hora de compilar un fichero con cdigo fuente Java, nos basaremos en errores provocados sobre nuestra mnima aplicacin Java de la seccin anterior, pero podra generalizarse sin demasiados problemas. %javac: Command not found No se ha establecido correctamente la variable PATH del sistema para el compilador javac. El compilador javac se encuentra en el directorio bin, que cuelga del directorio java, que cuelga del directorio donde se haya instalado el JDK (Java Development Kit). %[Link][Link] Method printl([Link]) not found in class [Link]. [Link]( "HolaMundo!); ^ Error tipogrfico, el mtodo es println no printl.

%In class HolaMundoApp: main must be public and static Error de ejecucin, se olvid colocar la palabra static en la declaracin del mtodo main de la aplicacin.

%Cant find class HolaMundoApp Este es un error muy sutil. Generalmente significa que el nombre de la clase es distinto al del fichero que contiene el cdigo fuente, con lo cual el fichero nombre_fichero.class que se genera es diferente del que cabra esperar. Por ejemplo, si en nuestro fichero de cdigo fuente de nuestra aplicacin [Link] colocamos en vez de la declaracin actual de la clase HolaMundoApp, la lnea: class HolaMundoapp { se crear un fichero [Link], que es diferente del [Link], que es el nombre esperado de la clase; la diferencia se encuentra en la a minscula y mayscula. 4.2 El Visor de applets de Sun (appletviewer) El visualizador de applets (appletviewer) es una aplicacin que permite ver en funcionamiento applets, sin necesidad de la utilizacin de un navegador World-Wide-Web como HotJava, Microsoft Explorer o Nescape. En adelante, recurriremos muchas veces a l, ya que el objetivo del tutorial es el lenguaje Java. Applet

138

La definicin ms extendida de applet, muy bien resumida por Patrick Naughton, indica que un applet es "una pequea aplicacin accesible en un servidor Internet, que se transporta por la red, se instala automticamente y se ejecuta in situ como parte de un documento web". Claro que as la definicin establece el entorno (Internet, Web, etc.). En realidad, un applet es una aplicacin pretendidamente corta (nada impide que ocupe ms de un gigabyte, a no ser el pensamiento de que se va a transportar por la red y una mente sensata) basada en un formato grfico sin representacin independiente: es decir, se trata de un elemento a embeber en otras aplicaciones; es un componente en su sentido estricto. Un ejemplo en otro mbito de cosas podra ser el siguiente: Imaginemos una empresa, que cansada de empezar siempre a codificar desde cero, disea un formulario con los datos bsicos de una persona (nombre, direccin, etc.). Tal formulario no es un dilogo por s mismo, pero se podra integrar en dilogos de clientes, proveedores, empleados, etc. El hecho de que se integre esttica (embebido en un ejecutable) o dinmicamente (intrpretes, DLLs, etc.) no afecta en absoluto a la esencia de su comportamiento como componente con que construir dilogos con sentido autnomo. Pues bien, as es un applet. Lo que ocurre es que, dado que no existe una base adecuada para soportar aplicaciones industriales Java en las que insertar nuestras miniaplicaciones (aunque todo se andar), los applets se han construido mayoritariamente, y con gran acierto comercial (parece), como pequeas aplicaciones interactivas, con movimiento, luces y sonido... en Internet. Llamadas a Applets con appletviewer Un applet es una mnima aplicacin Java diseada para ejecutarse en un navegador Web. Por tanto, no necesita preocuparse por un mtodo main() ni en dnde se realizan las llamadas. El applet asume que el cdigo se est ejecutando desde dentro de un navegador. El appletviewer se asemeja al mnimo navegador. Espera como argumento el nombre del fichero html que debe cargar, no se le puede pasar directamente un programa Java. Este fichero html debe contener una marca que especifica el cdigo que cargar el appletviewer: <HTML> <APPLET CODE=[Link] WIDTH=300 HEIGHT=100> </APPLET> </HTML> El appletviewer crear un espacio de navegacin, incluyendo un rea grfica, donde se ejecutar el applet, entonces llamar a la clase applet apropiada. En el ejemplo anterior, el appletviewer cargar una clase de nombre HolaMundo y le permitir trabajar en su espacio grfico. Arquitectura de appletviewer El appletviewer representa el mnimo interfaz de navegacin. En la figura se muestran los pasos que seguira appletviewer para presentarnos el resultado de la ejecucin del cdigo de nuestra clase.

139

Esta es una visin simplificada del appletviewer. La funcin principal de esta aplicacin es proporcionar al usuario un objeto de tipo Graphics sobre el que dibujar, y varias funciones para facilitar el uso del objeto Graphics. Ciclo de vida de un Applet Cuando un applet se carga en el appletviewer, comienza su ciclo de vida, que pasara por las siguientes fases:

Se crea una instancia de la clase que controla el applet. En el ejemplo de la figura anterior, sera la clase HolaMundo. El applet se incializa. El applet comienza a ejecutarse. El applet empieza a recibir llamadas. Primero recibe una llamada init (inicializar), seguida de un mensaje start (empezar) y paint (pintar). Estas llamadas pueden ser recibidas asncronamente. 4.3 Escribir Applets Java Para escribir applets Java, hay que utilizar una serie de mtodos, algunos de los cuales ya se hay sumariado al hablar de los mtodos del appletviewer, que es el visualizador de applets de Sun. Incluso para el applet ms sencillo necesitaremos varios mtodos. Son los que se usan para arrancar (start) y detener (stop) la ejecucin del applet, para pintar (paint) y actualizar (update) la pantalla y para capturar la informacin que se pasa al applet desde el fichero HTML a travs de la marca APPLET. init ( ) Esta funcin miembro es llamada al crearse el applet. Es llamada slo una vez. La clase Applet no hace nada en init(). Las clases derivadas deben sobrecargar este mtodo para cambiar el tamao

140

durante su inicializacin, y cualquier otra inicializacin de los datos que solamente deba realizarse una vez. Deberan realizarse al menos las siguientes acciones: Carga de imgenes y sonido El resize del applet para que tenga su tamao correcto Asignacin de valores a las variables globales Por ejemplo: public void init() { if( width < 200 || height < 200 ) resize( 200,200 ); valor_global1 = 0; valor_global2 = 100; // cargaremos imgenes en memoria sin mostrarlas // cargaremos msica de fondo en memoria sin reproducirla } destroy ( ) Esta funcin miembro es llamada cuando el applet no se va a usar ms. La clase Applet no hace nada en este mtodo. Las clases derivadas deberan sobrecargarlo para hacer una limpieza final. Los applet multithread debern usar destroy() para "matar" cuanquier thread del applet que quedase activo. start ( ) Llamada para activar el applet. Esta funcin miembro es llamada cuando se visita el applet. La clase Applet no hace nada en este mtodo. Las clases derivadas deberan sobrecargarlo para comenzar una animacin, sonido, etc. public void start() { estaDetenido = false; // comenzar la reproduccin de la msica [Link](); }

141

Tambin se puede utilizar start() para eliminar cualquier thread que se necesite. stop ( ) Llamada para detener el applet. Se llama cuando el applet desaparece de la pantalla. La clase Applet no hace nada en este mtodo. Las clases derivadas deberan sobrecargarlo para detener la animacin, el sonido, etc. public void stop() { estaDetenido = true; if( /* se est reproduciendo msica? */ ) [Link](); } resize ( int width,int height ) El mtodo init() debera llamar a esta funcin miembro para establecer el tamao del applet. Puede utilizar las variables ancho y alto, pero no es necesario. Cambiar el tamao en otro sitio que no sea init() produce un reformateo de todo el documento y no se recomienda. En el navegador Netscape, el tamao del applet es el que se indica en la marca APPLET del HTML, no hace caso a lo que se indique desde el cdigo Java del applet. width Variable entera, su valor es el ancho definido en el parmetro WIDTH de la marca HTML del APPLET. Por defecto es el ancho del icono. height Variable entera, su valor es la altura definida en el parmetro HEIGHT de la marca HTML del APPLET. Por defecto es la altura del icono. Tanto width como height estn siempre disponibles para que se puede chequear el tamao del applet. Podemos retomar el ejemplo de init(): public void init() { if( width < 200 || height < 200 ) resize( 200,200 ); ... paint( Graphics g )

142

Se llama cada vez que se necesita refrescar el rea de dibujo del applet. La clase Applet simplemente dibuja una caja con sombreado de tres dimensiones en el rea. Obviamente, la clase derivada debera sobrecargar este mtodo para representar algo inteligente en la pantalla. Para repintar toda la pantalla cuando llega un evento Paint, se pide el rectngulo sobre el que se va a aplicar paint() y si es ms pequeo que el tamao real del applet se invoca a repaint(), que como va a hacer un update(), se actualizar toda la pantalla. Podemos utilizar paint() para imprimir nuestro mensaje de bienvenida: void public paint( Graphics g ) { [Link]( "Hola Java!",25,25 ); // Dibujaremos la imgenes que necesitemos } update( Graphics g ) Esta es la funcin que se llama realmente cuando se necesita actualizar la pantalla. La clase Applet simplemente limpia el rea y llama al mtodo paint(). Esta funcionalidad es suficiente en la mayora de los casos. De cualquier forma, las clases derivadas pueden sustituir esta funcionalidad para sus propsitos. Podemos, por ejemplo, utilizar update() para modificar selectivamente partes del rea grfica sin tener que pintar el rea completa: public void update( Graphics g ) { if( estaActualizado ) { [Link](); // garantiza la pantalla limpia repaint(); // podemos usar el mtodo padre: [Link]() } else // Informacin adicional [Link]( "Otra informacin",25,50 ); } repaint() A esta funcin se la debera llamar cuando el applet necesite ser repintado. No debera sobrecargarse, sino dejar que Java repinte completamente el contenido del applet.

143

Al llamar a repaint(), sin parmetros, internamente se llama a update() que borrar el rectngulo sobre el que se redibujar y luego se llama a paint(). Como a repaint() se le pueden pasar parmetros, se puede modificar el rectngulo a repintar. getParameter ( String attr ) Este mtodo carga los valores parados al applet va la marca APPLET de HTML. El argumento String es el nombre del parmetro que se quiere obtener. Devuelve el valor que se le haya asignado al parmetro; en caso de que no se le haya asignado ninguno, devolver null. Para usar getParameter(), se define una cadena genrica. Una vez que se ha capturado el parmetro, se utilizan mtodos de cadena o de nmeros para convertir el valor obtenido al tipo adecuado. public void init() { String pv; pv = getParameter( "velocidad" ); if( pv == null ) velocidad = 10; else velocidad = [Link]( pv ); } getDocumentBase ( ) Indica la ruta http, o el directorio del disco, de donde se ha recogido la pgina HTML que contiene el applet, es decir, el lugar donde est la hoja en todo Internet o en el disco. getCodeBase ( ) Indica la ruta http, o el directorio del disco, de donde se ha cargado el cdigo bytecode que forma el applet, es decir, el lugar donde est el fichero .class en todo Internet o en el disco. print ( Graphics g ) Para imprimir en impresora, al igual que paint() se puede utilizar print(), que pintar en la impresora el mapa de bits del dibujo.

5. EL DEPURADOR DE JAVA - jdb


El depurador de Java, jdb es un depurador de lnea de comandos, similar al que Sun proporciona en sus Sistemas, dbx. Es complicado de utilizar y un tanto crptico, por lo que, en principio, tiene escasa practicidad y es necesaria una verdadera emergencia para tener que recurrir a l.

144

Trataremos por encima los comandos que proporciona el jdb, pero sin entrar en detalles de su funcionamiento, porque no merece la pena. Casi es mejor esperar a disponer de herramientas visuales para poder depurar con cierta comodidad nuestro cdigo Java. Para poder utilizar el depurador, las aplicaciones Java deben estar compiladas con la opcin de depuracin activada, -g. Posteriormente se puede lanzar appletviewer con la opcin de depuracin, debug, y habremos puesto en marcha jdb. 5.1 Depurar HolaMundo Hemos modificado nuestro applet de ejemplo para utilizarlo en nuestra sesin de ejemplo con el depurador. Se compilara con el comando: %javac -g [Link] y el contenido de nuestro applet HolaMundo modificado y guardado en el fichero [Link] sera el siguiente: // // Applet HolaMundo de ejemplo, para depurar // import [Link]; import [Link]; public class hm extends Applet { int i; public void paint( Graphics g ) { i = 10; [Link]( "Hola Mundo!",25,25 ); } } Una vez compilado, iniciamos la sesin lanzando el visor de applets de Sun con la opcin de depuracin, utilizando el comando: %appletviewer -debug [Link] El fichero [Link] contiene las lneas mnimas para poder activar el applet, estas lneas son las que reproducimos: <html>

145

<applet code=[Link] width=100 height=100> </applet> </html> Se inicia pues la sesin con el depurador y vamos a ir reproduciendo lo que aparece en la pantalla a medida que vamos introduciendo comandos: %appletviewer -debug [Link] Loading jdb... 0xee301bf0:class([Link]) > 5.2 Comando help El comando help proporciona una lista de los comandos que estn disponibles en la sesin de jdb. Esta lista es la que sigue, en donde hemos aprovechado la presencia de todos los comandos para comentar la accin que cada uno de ellos lleva a cabo. >help ** command list ** threads [threadgroup] -- lista threads thread <thread id> -- establece el thread por defecto suspend [thread id(s)] -- suspende threads (por defecto, todos) resume [thread id(s)] -- contina threads (por defecto, todos) where [thread id]|all -- muestra la pila de un thread threadgroups -- lista los grupos de threads threadgroup <name> -- establece el grupo de thread actual print <id> [id(s)] -- imprime un objeto o campo dump <id> [id(s)] -- imprime toda la informacin del objeto locals -- imprime las variables locales de la pila actual classes -- lista las clases conocidas methods <class id> -- lista los mtodos de una clase

146

stop in <class id>.<method> -- fija un punto de ruptura en un mtodo stop at <class id>:<line> -- establece un punto de ruptura en una lnea up [n frames] -- ascender en la pila de threads down [n frames] -- descender en la pila de threads clear <class id>:<line> -- eliminar un punto de ruptura step -- ejecutar la lnea actual cont -- continuar la ejecucin desde el punto de ruptura catch <class id> -- parar por la excepcin especificada ignore <class id> -- ignorar la excepcin especificada list [line number] -- imprimir cdigo fuente use [source file path] -- ver o cambiar la ruta del fichero fuente memory -- informe del uso de la memoria load <classname> - carga la clase Java a ser depurada run <args> - comienza la ejecucin de la clase cargada !! - repite el ltimo comando help (or ?) - lista los comandos exit (or quit) - salir del depurador > 5.3 Comando threadgroups El comando threadgroups permite ver la lista de threads que se estn ejecutando. Los grupos system y main deberan estar siempre corriendo. >threadgroups 1.([Link])0xee300068 system 2.([Link])0xee300a98 main > 5.4 Comando threads

147

El comando threads se utiliza para ver la lista completa de los threads que se estn ejecutando actualmente. >threads Group system: 1.([Link])0xee300098 clock handler cond 2.([Link])0xee300558 Idle thread run 3.([Link])0xee3005d0 sync Garbage Collector cond 4.([Link])0xee300620 Finalizer thread cond 5.([Link])0xee300a20 Debugger agent run 6.([Link])0xee300b58) Breakpoint handler cond Group main: 7.([Link])0xee300048 main suspended > 5.5 Comando run El comando run es el que se utiliza para arrancar el appletviewer en la sesin de depuracin. Lo teclearemos y luego volveremos a listar los threads que hay en ejecucin. >run run [Link] [Link] running... main[1]threads threads Group [Link]: 1.([Link])0xee3000c0 AWT-Motif running 2.([Link])0xee302ed0 ScreenUpdater cond. Waiting Group [Link]: 3.([Link])0xee302f38 Thread-6 cond. Waiting main[1]

148

El visor de applets de Sun aparecer en la pantalla y mostrar el conocido mensaje de saludo al Mundo. Ahora vamos a rearrancar el appletviewer con un punto de ruptura, para detener la ejecucin del applet, y podamos seguir mostrando los comandos disponibles en el jdb. main[1]exit %appletviewer -debug [Link] Loading jdb... 0xee3009c8:class([Link]) >stop in [Link] Breakpoint set in [Link] >run run [Link] [Link] running... Breakpoint hit: [Link]([Link]) AWT-Motif[1] 5.6 Comando where El comando where mostrar la pila de ejecucin del applet. AWT-Motif[1]where [1][Link]([Link]) [2][Link]([Link]) [3][Link]([Link]) AWT-Motif[1] 5.7 Comando use El comando use nos informa del camino donde jdb va a buscar los ficheros fuentes que contienen el cdigo Java de las clases que se estn depurando. Por defecto, utilizar el camino que se especifique en la variable de entorno CLASSPATH. AWT-Motif[1]use /usr/local/java/classes: AWT-Motif[1]

149

5.8 Comando list El comando list mostrar el cdigo fuente actual al comienzo del punto de ruptura que hayamos fijado. AWT-Motif[1]list 9 public void paint( Graphics g ) { 10 => i = 10; 11 [Link]( "Hola Mundo!",25,25 ) ; 12 } 13 } AWT-Motif[1] 5.9 Comando dump El comando dump nos permitir ahora ver el valor del objeto g pasado desde el appletviewer. AWT-Motif[1]dump g g = ([Link].X11Graphics)0xee303df8 { int pData = 1342480 Color foreground = ([Link])0xee302378 Font font = ([Link])0xee302138 int originX = 0 int originY = 0 float scaleX = 1 float scaleY = 1 Image image = null } AWT-Motif[1] 5.10 Comando step El comando step nos porporciona el mtodo para ejecutar la lnea actual, que estar siendo apuntada por el indicador si hemos utilizado el comando list.

150

AWT-Motif[1]step Breakpoint hit: [Link]([Link]) AWT-Motif[1]list 9 public void paint( Graphics g ) { 10 i = 10; 11 => [Link]( "Hola Mundo!",25,25 ); 12 } 13 } AWT-Motif[1]

6. AWT
6.1 Introduccin al AWT AWT es el acrnimo del X Window Toolkit para Java, donde X puede ser cualquier cosa: Abstract, Alternative, Awkward, Another o Asqueroso; aunque parece que Sun se decanta por Abstracto, seriedad por encima de todo. Se trata de una biblioteca de clases Java para el desarrollo de Interfaces de Usuario Grficas. La versin del AWT que Sun proporciona con el JDK se desarroll en slo dos meses y es la parte ms dbil de todo lo que representa Java como lenguaje. El entorno que ofrece es demasiado simple, no se han tenido en cuenta las ideas de entornos grficos novedosos, sino que se ha ahondado en estructuras orientadas a eventos, llenas de callbacks y sin soporte alguno del entorno para la construccin grfica; veremos que la simple accin de colocar un dibujo sobre un botn se vuelve una tarea harto complicada. Quiz la presin de tener que lanzar algo al mercado haya tenido mucho que ver en la pobreza de AWT. JavaSoft, asegura que esto slo era el principio y que AWT ser multi-idioma, tendr herramientas visuales, etc. En fin, al igual que dicen los astrlogos, el futuro nos deparar muchas sorpresas. La estructura bsica del AWT se basa en Componentes y Contenedores. Estos ltimos contienen Componentes posicionados a su respecto y son Componentes a su vez, de forma que los eventos pueden tratarse tanto en Contenedores como en Componentes, corriendo por cuenta del programador (todava no hay herramientas de composicin visual) el encaje de todas las piezas, as como la seguridad de tratamiento de los eventos adecuados. Nada trivial. No obstante y pese a ello, vamos a abordar en este momento la programacin con el AWT para tener la base suficiente y poder seguir profundizando en las dems caractersticas del lenguaje Java, porque como vamos a ir presentando ejemplos grficos es imprescindible el conocimiento del AWT. Mientras tanto, esperemos que JavaSoft sea fiel a sus predicciones y lo que ahora veamos nos sirva de base para migrar a un nuevo y maravilloso AWT. 6.2 Interface de Usuario La interface de usuario es la parte del programa que permite a ste interactuar con el usuario. Las interfaces de usuario pueden adoptar muchas formas, que van desde la simple lnea de comandos hasta las interfaces grficas que proporcionan las aplicaciones ms modernas.

151

La interface de usuario es el aspecto ms importante de cualquier aplicacin. Una aplicacin sin un interfaz fcil, impide que los usuarios saquen el mximo rendimiento del programa. Java proporciona los elementos bsicos para construir decentes interfaces de usuario a travs del AWT. Al nivel ms bajo, el sistema operativo transmite informacin desde el ratn y el teclado como dispositivos de entrada al programa. El AWT fue diseado pensando en que el programador no tuviese que preocuparse de detalles como controlar el movimiento del ratn o leer el teclado, ni tampoco atender a detalles como la escritura en pantalla. El AWT constituye una librera de clases orientada a objeto para cubrir estos recursos y servicios de bajo nivel. Debido a que el lenguaje de programacin Java es independiente de la plataforma en que se ejecuten sus aplicaciones, el AWT tambin es independiente de la plataforma en que se ejecute. El AWT proporciona un conjunto de herramientas para la construccin de interfaces grficas que tienen una apariencia y se comportan de forma semejante en todas las plataformas en que se ejecute. Los elementos de interface proporcionados por el AWT estn implementados utilizando toolkits nativos de las plataformas, preservando una apariencia semejante a todas las aplicaciones que se creen para esa plataforma. Este es un punto fuerte del AWT, pero tambin tiene la desventaja de que una interface grfica diseada para una plataforma, puede no visualizarse correctamente en otra diferente. 6.3 Estructura del AWT La estructura de la versin actual del AWT podemos resumirla en los puntos que exponemos a continuacin: Los Contenedores contienen Componentes, que son los controles bsicos No se usan posiciones fijas de los Componentes, sino que estn situados a travs de una disposicin controlada (layouts) El comn denominador de ms bajo nivel se acerca al teclado, ratn y manejo de eventos Alto nivel de abstraccin respecto al entorno de ventanas en que se ejecute la aplicacin (no hay reas cliente, ni llamadas a X, ni hWnds, etc.) La arquitectura de la aplicacin es dependiente del entorno de ventanas, en vez de tener un tamao fijo Es bastante dependiente de la mquina en que se ejecuta la aplicacin (no puede asumir que un dilogo tendr el mismo tamao en cada mquina) Carece de un formato de recursos. No se puede separar el cdigo de lo que es propiamente interface. No hay ningn diseador de interfaces (todava)

6.4 Componentes y Contenedores Una interface grfica est construida en base a elementos grficos bsicos, los Componentes. Tpicos ejemplos de estos Componentes son los botones, barras de desplazamiento, etiquetas, listas, cajas de seleccin o campos de texto. Los Componentes permiten al usuario interactuar con la aplicacin y proporcionar informacin desde el programa al usuario sobre el estado del programa. En el AWT, todos los Componentes de la interface de usuario son instancias de la clase Component o uno de sus subtipos. Los Componentes no se encuentran aislados, sino agrupados dentro de Contenedores. Los Contenedores contienen y organizan la situacin de los Componentes; adems, los Contenedores son en s mismos Componentes y como tales pueden ser situados dentro de otros Contenedores. Tambin contienen el cdigo necesario para el control de eventos, cambiar la forma del cursor o modificar el icono de la aplicacin. En el AWT, todos los Contenedores son instancias de la clase Container o uno de sus subtipos.

152

Los Componentes deben circunscribirse dentro del Contenedor que los contiene. Esto hace que el anidamiento de Componentes (incluyendo Contenedores) en Contenedores crean rboles de elementos, comenzando con un Contenedor en la raiz del rbol y expandindolo en sus ramas.

7. GRAFICOS
7.1 Objetos Grficos En pginas anteriores ya se ha mostrado cmo escribir applets, cmo lanzarlos y los fundamentos bsicos de la presentacin de informacin sobre ellos. Ahora, pues, querremos hacer cosas ms interesantes que mostrar texto; ya que cualquier pgina HTML puede mostrar texto. Para ello, Java proporciona la clase Graphics, que permite mostrar texto a travs del mtodo drawString(), pero tambin tiene muchos otros mtodos de dibujo. Para cualquier programador, es esencial el entendimiento de la clase Graphics, antes de adentrarse en el dibujo de cualquier cosa en Java. Esta clase proporciona el entorno de trabajo para cualquier operacin grfica que se realice dentro del AWT. Juega dos importantes papeles: por un lado, es el contexto grfico, es decir, contiene la informacin que va a afectar a todas las operaciones grficas, incluyendo los colores de fondo y texto, la fuente de caracteres, la localizacin y dimensiones del rectngulo en que se va a pintar, e incluso dispone de informacin sobre el eventual destino de las operaciones grficas (pantalla o imagen). Por otro lado, la clase Graphics proporciona mtodos que permiten el dibujo de primitivas, figuras y la manipulacin de fonts de caracteres y colores. Tambin hay clases para la manipulacin de imgenes, doble-buffering, etc. Para poder pintar, un programa necesita un contexto grfico vlido, representado por una instancia de la clase Graphics. Pero, como esta clase es abstracta, no se puede instanciar directamente; as que debemos crear un componente y pasarlo al programa como un argumento a los mtodos paint() o update(). Los dos mtodos anteriores, paint() y update(), junto con el mtodo repaint() son los que estn involucrados en la presentacin de grficos en pantalla. El AWT, para reducir el tiempo que necesitan estos mtodos para realizar el repintado en pantalla de grficos, tiene dos axiomas: Primero, el AWT repinta solamente aquellos Componentes que necesitan ser repintados, bien porque estuviesen cubiertos por otra ventana o porque se pida su repintado directamente Segundo, si un Componente estaba tapado y se destapa, el AWT repinta solamente la porcin del Componente que estaba oculta

En la ejecucin del applet que aparece a continuacin, [Link], podemos observar como se realiza este proceso. Ignorar la zona de texto de la parte superior del applet de momento, y centrar la mirada en la parte coloreada. Utilizando otra ventana, tapar y destapar parte de la zona que ocupa el applet. Se observar que solamente el trozo de applet que estaba cubierto es el que se repinta. Yendo un poco ms all, solamente aquellos componentes que estn ocultos y se vuelvan a ver sern los que se repinten, sin tener en cuenta su posicin dentro de la jerarqua de componentes. La pantalla en Java se incrementa de izquierda a derecha y de arriba hacia abajo, tal como muestra la figura:

153

Los pixels de la pantalla son pues: posicin 0 + ancho de la pantalla - 1. En los textos, el punto de insercin se encuentra en la lnea base de la primera letra. 7.2 Mtodos para Dibujos Vamos a presentar mtodos para dibujar varias figuras geomtricas. Como estos mtodos funcionan solamente cuando son invocados por una instancia vlida de la clase Graphics, su mbito de aplicacin se restringe a los componentes que se utilicen en los mtodos paint() y update(). Normalmente los mtodos de dibujo de primitivas grficas funcionan por pares: un mtodo pinta la figura normal y el otro pinta la figura rellena. drawLine( x1,y1,x2,y2 ) drawRect( x,y,ancho,alto ) fillRect( x,y,ancho,alto ) clearRect( x,y,[Link] ) drawRoundRect( x,y,ancho,alto,anchoArco,altoArco ) fillRoundRect( x,y,ancho,alto,anchoArco,altoArco ) draw3DRect( x,y,ancho,alto,boolean elevado ) fill3DRect( x,y,ancho,alto,boolean elevado ) drawOval( x,y,ancho,alto ) fillOval( x,y,ancho,alto ) drawArc( x,y,ancho,alto,anguloInicio,anguloArco ) fillArc( x,y,ancho,alto,anguloInicio,anguloArco ) drawPolygon( int[] puntosX,int[] puntosY[],numPuntos ) fillPolygon( int[] puntosX,int[] puntosY[],numPuntos )

154

drawString( string s,x,y ) drawChars( char data[],offset,longitud,x,y ) drawBytes( byte data[],offset,longitud,x,y ) copyArea( xSrc,ySrc,ancho,alto,xDest,yDest ) 7.3 Mtodos para Imagenes Los objetos Graphics pueden mostrar imgenes a travs del mtodo: drawImage( Image img,int x,int y,ImageObserver observador ); Hay que tener en cuenta que el mtodo drawImage() necesita un objeto Image y un objeto ImageObserver. Podemos cargar una imagen desde un fichero de dibujo (actualmente slo se soportan formatos GIF y JPEG) con el mtodo getImage(): Image img = getImage( getDocumentBase(),"[Link]" ); La forma de invocar al mtodo getImage() es indicando un URL donde se encuentre el fichero que contiene la imagen que queremos presentar y el nombre de ese fichero: getImage( URL directorioImagen,String ficheroImagen ); Un URL comn para el mtodo getImage() es el directorio donde est el fichero HTML. Se puede acceder a esa localizacin a travs del mtodo getDocumentBase() de la clase Applet, como ya se ha indicado. Normalmente, se realiza el getImage() en el mtodo init() del applet y se muestra la imagen cargada en el mtodo paint(), tal como se muestra en el ejemplo siguiente: public void init() { img = getImage( getDocumentBase(),"[Link]" ); } public void paint( Graphics g ) { [Link]( img,x,y,this ); } En el applet [Link], podemos ver el ejemplo completo. Su ponemos en l la existencia del fichero "Imagenes/[Link]": import [Link].*; import [Link];

155

import [Link]; public class Imagen extends Applet { Imagen pepe; public void init() { pepe = getImage( getDocumentBase(),"Imagenes/[Link]" ); } public void paint( Graphics g ) { [Link]( pepe,25,25,this ); } } 7.4 Sonido en Java Java tambin posee mtodos predefinidos para reproducir sonido. El ordenador remoto no necesita tener un reproductor de audio; Java realizar la reproduccin (evidentemente, el ordenador remoto, en donde se ejecuta el applet, necesitar disponer de hardware de sonido). Reproduccin de sonido La forma ms fcil de reproducir sonido es a travs del mtodo play(): play( URL directorioSonido,String ficheroSonido ); o, simplemente: play( URL unURLdeSonido ); Un URL comn para el mtodo play() es el directorio donde est el fichero HTML. Se puede acceder a esa localizacin a travs del mtodo getDocumentBase() de la clase Applet: play( getDocumentBase(),"[Link]" ); para que esto funcione, el fichero de la clase y el fichero [Link] deberan estar en el mismo directorio. Reproduccin Repetitiva Se puede manejar el sonido como si de imgenes se tratara. Se pueden cargar y reproducir ms tarde. Para cargar un clip de sonido, se utiliza el mtodo getAudioClip():

156

AudoClip sonido; sonido = getAudioClip( getDocumentBase(),"[Link]" ); Una vez que se carga el clip de sonido, se pueden utilizar tres mtodos: [Link](); para reproducir el clip de sonido. [Link](); para iniciar la reproduccin del clip de sonido y que entre en un blucle de reproduccin, es decir, en una repeticin automtica del clip. [Link](); para detener el clip de sonido que se encuentre en ese instante en reproduccin. 7.5 Entrada por Ratn Una de las caractersticas ms tiles que ofrece Java es el soporte directo de la interactividad. La aplicacin puede reaccionar a los cambios producidos en el ratn, por ejemplo, sin necesidad de escribir ninguna lnea de cdigo para su control, solamente indicando qu se quiere hacer cuando el ratn haga algo. El evento ms comn en el ratn es el click. Este evento es gobernado por dos mtodos: mouseDown() (botn pulsado) y mouseUp() (botn soltado). Ambos mtodos son parte de la clase Applet, pero se necesita definir sus acciones asociadas, de la misma forma que se realiza con init() o con paint().

8. EXCEPCIONES EN JAVA
8.1 Manejo de Excepciones Vamos a mostrar como se utilizan las excepciones, reconvirtiendo nuestro applet de saludo a partir de la versin iterativa de [Link]: import [Link].*; import [Link]; public class HolaIte extends Applet { private int i = 0; private String Saludos[] = { "Hola Mundo!", "HOLA Mundo!",

157

"HOLA MUNDO!!" }; public void paint( Graphics g ) { [Link]( Saludos[i],25,25 ); i++; } } Normalmente, un programa termina con un mensaje de error cuando se lanza una excepcin. Sin embargo, Java tiene mecanismos para excepciones que permiten ver qu excepcin se ha producido e intentar recuperarse de ella. Vamos a reescribir el mtodo paint() de nuestra versin iterativa del saludo: public void paint( Graphics g ) { try { [Link]( Saludos[i],25,25 ); } catch( ArrayIndexOutOfBoundsException e ) { [Link]( "Saludos desbordado",25,25 ); } catch( Exception e ) { // Cualquier otra excepcin [Link]( [Link]() ); } finally { [Link]( "Esto se imprime siempre!" ); } i++; } La palabra clave finally define un bloque de cdigo que se quiere que sea ejecutado siempre, de acuerdo a si se captur la excepcin o no. En el ejemplo anterior, la salida en la consola, con i=4 sera: Saludos desbordado

158

Esto se imprime siempre! 8.2 Generar Excepciones en Java Cuando se produce un error se debera generar, o lanzar, una excepcin. Para que un mtodo en Java, pueda lanzar excepciones, hay que indicarlo expresamente. void MetodoAsesino() throws NullPointerException,CaidaException Se pueden definir excepciones propias, no hay por qu limitarse a las predefinidas; bastar con extender la clase Exception y proporcionar la funcionalidad extra que requiera el tratamiento de esa excepcin. Tambin pueden producirse excepciones no de forma explcita como en el caso anterior, sino de forma implcita cuando se realiza alguna accin ilegal o no vlida. Las excepciones, pues, pueden originarse de dos modos: el programa hace algo ilegal (caso normal), o el programa explcitamente genera una excepcin ejecutando la sentencia throw (caso menos normal). La sentencia throw tiene la siguiente forma: throw ObtejoExcepction; El objeto ObjetoException es un objeto de una clase que extiende la clase Exception. El siguiente cdigo de ejemplo origina una excepcin de divisin por cero: class melon { public static void main( String[] a ) { int i=0, j=0, k; k = i/j; // Origina un error de division-by-zero } } Si compilamos y ejecutamos esta aplicacin Java, obtendremos la siguiente salida por pantalla: > javac [Link] > java melon [Link]: / by zero at [Link]([Link]) Las excepciones predefinidas, como ArithmeticException, se conocen como excepciones runtime. Actualmente, como todas las excepciones son eventos runtime, sera mejor llamarlas excepciones irrecuperables. Esto contrasta con las excepciones que generamos explcitamente, que suelen ser mucho menos severas y en la mayora de los casos podemos recuperarnos de ellas. Por ejemplo,

159

si un fichero no puede abrirse, preguntamos al usuario que nos indique otro fichero; o si una estructura de datos se encuentra completa, podremos sobreescribir algn elemento que ya no se necesite. 8.3 Excepciones Predefinidas Las excepciones predefinidas y su jerarqua de clases es la que se muestra en la figura:

160

Las siguientes son las excepciones predefinidas ms frecuentes que se pueden encontrar: ArithmeticException Las excepciones aritmticas son tpicamente el resultado de una divisin por 0: int i = 12 / 0; NullPointerException Se produce cuando se intenta acceder a una variable o mtodo antes de ser definido: class Hola extends Applet { Image img; paint( Graphics g ) { [Link]( img,25,25,this ); } } IncompatibleClassChangeException El intento de cambiar una clase afectada por referencias en otros objetos, especficamente cuando esos objetos todava no han sido recompilados. ClassCastException El intento de convertir un objeto a otra clase que no es vlida. y = (Prueba)x; // donde x no es de tipo Prueba NegativeArraySizeException Puede ocurrir si hay un error aritmtico al intentar cambiar el tamao de un array. OutOfMemoryException No debera producirse nunca! El intento de crear un objeto con el operador new ha fallado por falta de memoria. Y siempre tendra que haber memoria suficiente porque el garbage collector se encarga de proporcionarla al ir liberando objetos que no se usan y devolviendo memoria al sistema. NoClassDefFoundException Se referenci una clase que el sistema es incapaz de encontrar.

161

ArrayIndexOutOfBoundsException Es la excepcin que ms frecuentemente se produce. Se genera al intentar acceder a un elemento de un array ms all de los lmites definidos inicialmente para ese array. UnsatisfiedLinkException Se hizo el intento de acceder a un mtodo nativo que no existe. Aqu no existe un mtodo [Link] class A { native void kk(); } y se llama a [Link](), cuando debera llamar a [Link](). InternalException Este error se reserva para eventos que no deberan ocurrir. Por definicin, el usuario nunca debera ver este error y esta excepcin no debera lanzarse. 8.4 Crear Excepciones Propias Tambin podemos lanzar nuestras propias excepciones, extendiendo la clase [Link]. Por ejemplo, consideremos un programa cliente/servidor. El cdigo cliente se intenta conectar al servidor, y durante 5 segundos se espera a que conteste el servidor. Si el servidor no responde, el servidor lanzara la excepcin de time-out: Cualquier mtodo que lance una excepcin tambin debe capturarla, o declararla como parte de la interface del mtodo. Cabe preguntarse entonces, el porqu de lanzar una excepcin si hay que capturarla en el mismo mtodo. La respuesta es que las excepciones no simplifican el trabajo del control de errores. Tienen la ventaja de que se puede tener muy localizado el control de errores y no tenemos que controlar millones de valores de retorno, pero no van ms all. 8.5 Capturar Excepciones Las excepciones lanzadas por un mtodo que pueda hacerlo deben recoger en bloque try/catch o try/finally. try Es el bloque de cdigo donde se prev que se genere una excepcin. Es como si dijsemos "intenta estas sentencias y mira a ver si se produce una excepcin". El bloque try tiene que ir seguido, al menos, por una clusula catch o una clusula finally catch Es el cdigo que se ejecuta cuando se produce la excepcin. Es como si dijsemos "controlo cualquier excepcin que coincida con mi argumento". En este bloque tendremos que asegurarnos

162

de colocar cdigo que no genere excepciones. Se pueden colocar sentencias catch sucesivas, cada una controlando una excepcin diferente. No debera intentarse capturar todas las excepciones con una sola clusula. Esto representara un uso demasiado general, podran llegar muchas ms excepciones de las esperadas. En este caso es mejor dejar que la excepcin se propague hacia arriba y dar un mensaje de error al usuario. Se pueden controlar grupos de excepciones, es decir, que se pueden controlar, a travs del argumento, excepciones semejantes. La clusula catch comprueba los argumentos en el mismo orden en que aparezcan en el programa. Si hay alguno que coincida, se ejecuta el bloque. El operador instanceof se utiliza para identificar exactamente cual ha sido la identidad de la excepcin. finally Es el bloque de cdigo que se ejecuta siempre, haya o no excepcin. Hay una cierta controversia entre su utilidad, pero, por ejemplo, podra servir para hacer un log o un seguimiento de lo que est pasando, porque como se ejecuta siempre puede dejarnos grabado si se producen excepciones y nos hemos recuperado de ellas o no. Este bloque finally puede ser til cuando no hay ninguna excepcin. Es un trozo de cdigo que se ejecuta independientemente de lo que se haga en el bloque try. Cuando vamos a tratar una excepcin, se nos plantea el problema de qu acciones vamos a tomar. En la mayora de los casos, bastar con presentar una indicacin de error al usuario y un mensaje avisndolo de que se ha producido un error y que decida si quiere o no continuar con la ejecucin del programa. 8.6 Propagacion de Excepciones La clusula catch comprueba los argumentos en el mismo orden en que aparezcan en el programa. Si hay alguno que coincida, se ejecuta el bloque y sigue el flujo de control por el bloque finally (si lo hay) y concluye el control de la excepcin. Si ninguna de las clusulas catch coincide con la excepcin que se ha producido, entonces se ejecutar el cdigo de la clusula finally (en caso de que la haya). Lo que ocurre en este caso, es exactamente lo mismo que si la sentencia que lanza la excepcin no se encontrase encerrada en el bloque try. El flujo de control abandona este mtodo y retorna prematuramente al mtodo que lo llam. Si la llamada estaba dentro del mbito de una sentencia try, entonces se vuelve a intentar el control de la excepcin, y as continuamente. Veamos lo que sucede cuando una excepcin no es tratada en la rutina en donde se produce. El sistema Java busca un bloque try..catch ms all de la llamada, pero dentro del mtodo que lo trajo aqu. Si la excepcin se propaga de todas formas hasta lo alto de la pila de llamadas sin encontrar un controlador especfico para la excepcin, entonces la ejecucin se detendr dando un mensaje. Es decir, podemos suponer que Java nos est proporcionando un bloque catch por defecto, que imprime un mensaje de error y sale.

163

No hay ninguna sobrecarga en el sistema por incorporar sentencias try al cdigo. La sobrecarga se produce cuando se genera la excepcin. Hemos dicho ya que un mtodo debe capturar las excepciones que genera, o en todo caso, declararlas como parte de su llamada, indicando a todo el mundo que es capaz de generar excepciones. Esto debe ser as para que cualquiera que escriba una llamada a ese mtodo est avisado de que le puede llegar una excepcin, en lugar del valor de retorno normal. Esto permite al programador que llama a ese mtodo, elegir entre controlar la excepcin o propagarla hacia arriba en la pila de llamadas.

9. Threads y Multithreading
Considerando el entorno multithread, cada thread (hilo, flujo de control del programa) representa un proceso individual ejecutndose en un sistema. A veces se les llama procesos ligeros o contextos de ejecucin. Tpicamente, cada thread controla un nico aspecto dentro de un programa, como puede ser supervisar la entrada en un determinado perifrico o controlar toda la entrada/salida del disco. Todos los threads comparten los mismos recursos, al contrario que los procesos en donde cada uno tiene su propia copia de cdigo y datos (separados unos de otros). Grficamente, los threads se parecen en su funcionamiento a lo que muestra la figura siguiente:

9.1 Flujo en Programas Programas de flujo nico Un programa de flujo nico o mono-hilvanado (single-thread) utiliza un nico flujo de control (thread) para controlar su ejecucin. Muchos programas no necesitan la potencia o utilidad de mltiples flujos de control. Sin necesidad de especificar explcitamente que se quiere un nico flujo de control, muchos de los applets y aplicaciones son de flujo nico. Programas de flujo mltiple En nuestra aplicacin de saludo, no vemos el thread que ejecuta nuestro programa. Sin embargo, Java posibilita la creacin y control de threads explcitamente. La utilizacin de threads en Java, permite una enorme flexibilidad a los programadores a la hora de plantearse el desarrollo de aplicaciones. La simplicidad para crear, configurar y ejecutar threads, permite que se puedan implementar muy poderosas y portables aplicaciones/applets que no se puede con otros lenguajes de tercera generacin. En un lenguaje orientado a Internet como es Java, esta herramienta es vital. Si se ha utilizado un navegador con soporte Java, ya se habr visto el uso de mltiples threads en Java. Habr observado que dos applet se pueden ejecutar al mismo tiempo, o que puede desplazarla pgina del navegador mientras el applet contina ejecutndose. Esto no significa que el applet utilice mltiples threads, sino que el navegador es multithreaded.

164

Las aplicaciones (y applets) multithreaded utilizan muchos contextos de ejecucin para cumplir su trabajo. Hacen uso del hecho de que muchas tareas contienen subtareas distintas e independientes. Se puede utilizar un thread para cada subtarea. Mientras que los programas de flujo nico pueden realizar su tarea ejecutando las subtareas secuencialmente, un programa multithreaded permite que cada thread comience y termine tan pronto como sea posible. Este comportamiento presenta una mejor respuesta a la entrada en tiempo real. 9.2 Creacion y Control de threads Creacin de un Thread Hay dos modos de conseguir threads en Java. Una es implementando la interface Runnable, la otra es extender la clase Thread. La implementacin de la interface Runnable es la forma habitual de crear threads. Las interfaces proporcionan al programador una forma de agrupar el trabajo de infraestructura de una clase. Se utilizan para disear los requerimientos comunes al conjunto de clases a implementar. La interface define el trabajo y la clase, o clases, que implementan la interface realizan ese trabajo. Los diferentes grupos de clases que implementen la interface tendrn que seguir las mismas reglas de funcionamiento. Hay una cuantas diferencias entre interface y clase. Primero, una interface solamente puede contener mtodos abstractos y/o variables estticas y finales (constantes). Las clases, por otro lado, pueden implementar mtodos y contener variables que no sean constantes. Segundo, una interface no puede implementar cualquier mtodo. Una clase que implemente una interface debe implementar todos los mtodos definidos en esa interface. Una interface tiene la posibilidad de poder extenderse de otras interfaces y, al contrario que las clases, puede extenderse de mltiples interfaces. Adems, una interface no puede ser instanciada con el operador new; por ejemplo, la siguiente sentencia no est permitida: Runnable a = new Runnable(); // No se permite El primer mtodo de crear un thread es simplemente extender la clase Thread: class MiThread extends Thread { public void run() { . . . } El ejemplo anterior crea una nueva clase MiThread que extiende la clase Thread y sobrecarga el mtodo [Link]() por su propia implementacin. El mtodo run() es donde se realizar todo el trabajo de la clase. Extendiendo la clase Thread, se pueden heredar los mtodos y variables de la clase padre. En este caso, solamente se puede extender o derivar una vez de la clase padre. Esta limitacin de Java puede ser superada a travs de la implementacin de Runnable: public class MiThread implements Runnable {

165

Thread t; public void run() { // Ejecucin del thread una vez creado } } En este caso necesitamos crear una instancia de Thread antes de que el sistema pueda ejecutar el proceso como un thread. Adems, el mtodo abstracto run() est definido en la interface Runnable tiene que ser implementado. La nica diferencia entre los dos mtodos es que este ltimo es mucho ms flexible. En el ejemplo anterior, todava tenemos oportunidad de extender la clase MiThread, si fuese necesario. La mayora de las clases creadas que necesiten ejecutarse como un thread , implementarn la interface Runnable, ya que probablemente extendern alguna de su funcionalidad a otras clases. No pensar que la interface Runnable est haciendo alguna cosa cuando la tarea se est ejecutando. Solamente contiene mtodos abstractos, con lo cual es una clase para dar idea sobre el diseo de la clase Thread. De hecho, si vemos los fuentes de Java, podremos comprobar que solamente contiene un mtodo abstracto: package [Link]; public interface Runnable { public abstract void run() ; } Y esto es todo lo que hay sobre la interface Runnable. Como se ve, una interface slo proporciona un diseo para las clases que vayan a ser implementadas. En el caso de Runnable, fuerza a la definicin del mtodo run(), por lo tanto, la mayor parte del trabajo se hace en la clase Thread. Un vistazo un poco ms profundo a la definicin de la clase Thread nos da idea de lo que realmente est pasando: public class Thread implements Runnable { ... public void run() { if( tarea != null ) [Link]() ; } } ...

166

} De este trocito de cdigo se desprende que la clase Thread tambin implemente la interface Runnable. [Link]() se asegura de que la clase con que trabaja (la clase que va a ejecutarse como un thread) no sea nula y ejecuta el mtodo run() de esa clase. Cuando esto suceda, el mtodo run() de la clase har que corra como un thread. Arranque de un Thread Las aplicaciones ejecutan main() tras arrancar. Esta es la razn de que main() sea el lugar natural para crear y arrancar otros threads. La lnea de cdigo: t1 = new TestTh( "Thread 1",(int)([Link]()*2000) ); crea un nuevo thread. Los dos argumentos pasados representan el nombre del thread y el tiempo que queremos que espere antes de imprimir el mensaje. Al tener control directo sobre los threads, tenemos que arrancarlos explcitamente. En nuestro ejemplo con: [Link](); start(), en realidad es un mtodo oculto en el thread que llama al mtodo run(). Manipulacin de un Thread Si todo fue bien en la creacin del thread, t1 debera contener un thread vlido, que controlaremos en el mtodo run(). Una vez dentro de run(), podemos comenzar las sentencias de ejecucin como en otros programas. run() sirve como rutina main() para los threads; cuando run() termina, tambin lo hace el thread. Todo lo que queramos que haga el thread ha de estar dentro de run(), por eso cuando decimos que un mtodo es Runnable, nos obliga a escribir un mtodo run(). En este ejemplo, intentamos inmediatamente esperar durante una cantidad de tiempo aleatoria (pasada a travs del constructor): sleep( retardo ); El mtodo sleep() simplemente le dice al thread que duerma durante los milisegundos especificados. Se debera utilizar sleep() cuando se pretenda retrasar la ejecucin del thread. sleep() no consume recursos del sistema mientras el thread duerme. De esta forma otros threads pueden seguir funcionando. Una vez hecho el retardo, se imprime el mensaje "Hola Mundo!" con el nombre del thread y el retardo. Suspensin de un Thread Puede resultar til suspender la ejecucin de un thread sin marcar un lmite de tiempo. Si, por ejemplo, est construyendo un applet con un thread de animacin, querr permitir al usuario la opcin de detener la animacin hasta que quiera continuar. No se trata de terminar la animacin, sino desactivarla. Para este tipo de control de thread se puede utilizar el mtodo suspend().

167

[Link](); Este mtodo no detiene la ejecucin permanentemente. El thread es suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocacin al mtodo resume(): [Link](); Parada de un Thread El ltimo elemento de control que se necesita sobre threads es el mtodo stop(). Se utiliza para terminar la ejecucin de un thread: [Link](); Esta llamada no destruye el thread, sino que detiene su ejecucin. La ejecucin no se puede reanudar ya con [Link](). Cuando se desasignen las variables que se usan en el thread, el objeto thread (creado con new) quedar marcado para eliminarlo y el garbage collector se encargar de liberar la memoria que utilizaba. En nuestro ejemplo, no necesitamos detener explcitamente el thread. Simplemente se le deja terminar. Los programas ms complejos necesitarn un control sobre cada uno de los threads que lancen, el mtodo stop() puede utilizarse en esas situaciones. Si se necesita, se puede comprobar si un thread est vivo o no; considerando vivo un thread que ha comenzado y no ha sido detenido. [Link](); Este mtodo devolver true en caso de que el thread t1 est vivo, es decir, ya se haya llamado a su mtodo run() y no haya sido parado con un stop() ni haya terminado el mtodo run() en su ejecucin. 9.3 Estados de un thread Durante el ciclo de vida de un thread, ste se puede encontrar en diferentes estados. La figura siguiente muestra estos estados y los mtodos que provocan el paso de un estado a otro. Este diagrama no es una mquina de estados finita, pero es lo que ms se aproxima al funcionamiento real de un thread .

168

Nuevo Thread Cuando un thread est en este estado, es simplemente un objeto Thread vaco. El sistema no ha destinado ningn recurso para l. Desde este estado solamente puede arrancarse llamando al mtodo start(), o detenerse definitivamente, llamando al mtodo stop(); la llamada a cualquier otro mtodo carece de sentido y lo nico que provocar ser la generacin de una excepcin de tipo IllegalThreadStateException. Ejecutable La llamada al mtodo start() crear los recursos del sistema necesarios para que el thread puede ejecutarse, lo incorpora a la lista de procesos disponibles para ejecucin del sistema y llama al mtodo run() del thread. En este momento nos encontramos en el estado "Ejecutable" del diagrama. Y este estado es Ejecutable y no En Ejecucin, porque cuando el thread est aqu no esta corriendo. Muchos ordenadores tienen solamente un procesador lo que hace imposible que todos los threads estn corriendo al mismo tiempo. Java implementa un tipo de scheduling o lista de procesos, que permite que el procesador sea compartido entre todos los procesos o threads que se encuentran en la lista. Sin embargo, para nuestros propsitos, y en la mayora de los casos, se puede considerar que este estado es realmente un estado "En Ejecucin", porque la impresin que produce ante nosotros es que todos los procesos se ejecutan al mismo tiempo. Cuando el thread se encuentra en este estado, todas las instrucciones de cdigo que se encuentren dentro del bloque declarado para el mtodo run(), se ejecutarn secuencialmente. Parado El thread entra en estado "Parado" cuando alguien llama al mtodo suspend(), cuando se llama al mtodo sleep(), cuando el thread est bloqueado en un proceso de entrada/salida o cuando el thread utiliza su mtodo wait() para esperar a que se cumpla una determinada condicin. Cuando ocurra cualquiera de las cuatro cosas anteriores, el thread estar Parado. Para cada una de los cuatro modos de entrada en estado Parado, hay una forma especfica de volver a estado Ejecutable. Cada forma de recuperar ese estado es exclusiva; por ejemplo, si el thread ha sido puesto a dormir, una vez transcurridos los milisegundos que se especifiquen, l solo se despierta y vuelve a estar en estado Ejecutable. Llamar al mtodo resume() mientras est el thread durmiendo no servira para nada.

169

Los mtodos de recuperacin del estado Ejecutable, en funcin de la forma de llegar al estado Parado del thread, son los siguientes: Si un thread est dormido, pasado el lapso de tiempo Si un thread est suspendido, luego de una llamada al mtodo resume() Si un thread est bloqueado en una entrada/salida, una vez que el comando E/S concluya su ejecucin Si un thread est esperando por una condicin, cada vez que la variable que controla esa condicin vare debe llamarse a notify() o notifyAll()

Muerto Un thread se puede morir de dos formas: por causas naturales o porque lo maten (con stop()). Un thread muere normalmente cuando concluye de forma habitual su mtodo run(). Por ejemplo, en el siguiente trozo de cdigo, el bucle while es un bucle finito -realiza la iteracin 20 veces y termina-: El mtodo isAlive() La interface de programacin de la clase Thread incluye el mtodo isAlive(), que devuelve true si el thread ha sido arrancado (con start()) y no ha sido detenido (con stop()). Por ello, si el mtodo isAlive() devuelve false, sabemos que estamos ante un "Nuevo Thread" o ante un thread "Muerto". Si nos devuelve true, sabemos que el thread se encuentra en estado "Ejecutable" o "Parado". No se puede diferenciar entre "Nuevo Thread" y "Muerto", ni entre un thread "Ejecutable" o "Parado". 9.4 Comunicacion entre threads Otra clave para el xito y la ventaja de la utilizacin de mltiples threads en una aplicacin, o aplicacin multithreaded, es que pueden comunicarse entre s. Se pueden disear threads para utilizar objetos comunes, que cada thread puede manipular independientemente de los otros threads. El ejemplo clsico de comunicacin de threads es un modelo productor/consumidor. Un thread produce una salida, que otro thread usa (consume), sea lo que sea esa salida. Vamos entonces a crear un productor, que ser un thread que ir sacando caracteres por su salida; crearemos tambin un consumidor que ira recogiendo los caracteres que vaya sacando el productor y un monitor que controlar el proceso de sincronizacin entre los threads. Funcionar como una tubera, insertando el productor caracteres en un extremos y leyndolos el consumidor en el otro, con el monitor siendo la propia tubera.

11. METODOS NATIVOS

170

Un mtodo nativo es un mtodo Java (una instancia de un objeto o una clase) cuya implementacin se ha realizado en otro lenguaje de programacin, por ejemplo, C. Vamos a ver cmo se integran mtodos nativos en clases Java. Actualmente, el lenguaje Java solamente proporciona mecanismos para integrar cdigo C en programas Java. Veamos pues los pasos necesarios para mezclar cdigo nativo C y programas Java. Recurriremos (Cmo no!) a nuestro saludo; en este caso, el programa HolaMundo tiene dos clases Java: la primera implementa el mtodo main() y la segunda, HolaMundo, tiene un mtodo nativo que presenta el mensaje de saludo. La implementacin de este segundo mtodo la realizaremos en C. 10.1 Escribir Cdigo Java En primer lugar, debemos crear una clase Java, HolaMundo, que declare un mtodo nativo. Tambin debemos crear el programa principal que cree el objeto HolaMundo y llame al mtodo nativo. Las siguientes lneas de cdigo definen la clase HolaMundo, que consta de un mtodo y un segmento esttico de cdigo: class HolaMundo { public native void presentaSaludo(); static { [Link]( "hola" ); } } Podemos decir que la implementacin del mtodo presentaSaludo() de la clase HolaMundo est escrito en otro lenguaje, porque la palabra reservada native aparece como parte de la definicin del mtodo. Esta definicin, proporciona solamente la definicin para presentaSaludo() y no porporciona ninguna implementacin para l. La implementacin la proporcionaremos desde un fichero fuente separado, escrito en lenguaje C. La definicin para presentaSaludo() tambin indica que el mtodo es un mtodo pblico, no acepta argumentos y no devuelve ningn valor. Al igual que cualquier otro mtodo, los mtodos nativos deben estar definidos dentro de una clase Java. El cdigo C que implementa el mtodo presentaSaludo() debe ser compilado en una librera dinmica y cargado en la clase Java que lo necesite. Esta carga, mapea la implementacin del mtodo nativo sobre su definicin. El siguiente bloque de cdigo carga la librera dinmica, en este caso hola. El sistema Java ejecutar un bloque de cdigo esttico de la clase cuando la cargue. Todo el cdigo anterior forma parte del fichero [Link], que contiene la clase HolaMundo. En un fichero separado, [Link], vamos a crear una aplicacin Java que instancie a la clase HolaMundo y llame al mtodo nativo presentaSaludo(). class Main {

171

public static void main( String args[] ) { new HolaMundo().presentaSaludo(); } } Como se puede observar, llamamos al mtodo nativo del mismo modo que a cualquier otro mtodo Java; aadimos el nombre del mtodo al final del nombre del objeto con un punto ("."). El conjunto de parntesis que sigue al nombre del mtodo encierra los argumentos que se le pasen. En este caso, el mtodo presentaSaludo() no recibe ningn tipo de argumento. 10.2 Compilar el Cdigo Java Utilizaremos ahora el compilador javac para compilar el cdigo Java que hemos desarrollado. Compilaremos los dos ficheros fuentes de cdigo Java que hemos creado, tecleando los siguientes comandos: > javac [Link] > javac [Link] 10.3 Crear el Fichero de Cabecera Ahora debemos utilizar la aplicacin javah para conseguir el fichero de cabecera .h. El fichero de cabecera define una estructura que representa la clase HolaMundo sobre cdigo C y proporciona la definicin de una funcin C para la implementacin del mtodo nativo presentaSaludo() definido en ese clase. Ejecutamos javah sobre la clase HolaMundo, con el siguiente comando: > javah HolaMundo Por defecto, javah crear el nuevo fichero .h en el mismo directorio en que se encuentra el fichero .class, obtenido al compilar con javac el cdigo fuente Java correspondiente a la clase. El fichero que crear, ser un fichero de cabecera del mismo nombre que la clase y con extensin .h. Por ejemplo, el comando anterior habr creado el fichero HolaMundo.h, cuyo contenido ser el siguiente: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <native.h> /* Header for class HolaMundo */ #ifndef _Included_HolaMundo #define _Included_HolaMundo typedef struct ClassHolaMundo {

172

char PAD; /* ANSI C requires structures to have a least one member */ } ClassHolaMundo; HandleTo(HolaMundo); #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void HolaMundo_presentaSaludo(struct HHolaMundo *); #ifdef __cplusplus } #endif #endif Este fichero de cabecera contiene la definicin de una estructura llamada ClassHolaMundo. Los miembros de esta estructura son paralelos a los miembros de la clase Java correspondiente; es decir, los campos en la estructura corresponden a las variables de la clase. Pero como HolaMundo no tiene ninguna variable, la estructura se encuentra vaca. Se pueden utilizar los miembros de la estructura para referenciar a variables instanciadas de la clase desde las funciones C. Adems de la estructura C similar a la clase Java, vemos que la llamada de la funcin C est declarada como: extern void HolaMundo_presentaSaludo( struct HHolaMundo *); Esta es la definicin de la funcin C que deberemos escribir para implementar el mtodo nativo presentaSaludo() de la clase HolaMundo. Debemos utilizar esa definicin cuando lo implementemos. Si HolaMundo llamase a otros mtodos nativos, las definiciones de las funciones tambin apareceran aqu. El nombre de la funcin C que implementa el mtodo nativo est derivado del nombre del paquete, el nombre de la clase y el nombre del mtodo nativo. As, el mtodo nativo presentaSaludo() dentro de la clase HolaMundo es HolaMundo_presentaSaludo(). En este ejemplo, no hay nombre de paquete porque HolaMundo se considera englobado dentro del paquete por defecto. La funcin C acepta un parmetro, aunque el mtodo nativo definido en la clase Java no acepte ninguno. Se puede pensar en este parmetro como si fuese la variable this de C++. En nuestro caso, ignoramos el parmetro this. 10.4 Crear el Fichero de stubs Volvemos a utilizar la aplicacin javah para crear el fichero de stubs, que contiene todas las declaraciones de mtodos, con sus llamadas y argumentos, listos para que nosotros rellenemos el cuerpo de los mtodos con los algoritmos que necesitemos implementar. Proporciona la unin entre la clase Java y su estructura C paralela.

173

Para generar este fichero, debemos indicar el parmetro .stubs al ejecutar la aplicacin javah sobre la clase HolaMundo, de la siguiente forma: > javah -stubs HolaMundo Del mismo modo que se generaba el fichero .h; el nombre del fichero de stubs ser el nombre de la clase con la extensin .c. En nuestro ejemplo, ser HolaMundo.c, y su contenido ser el siguiente: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <StubPreamble.h> /* Stubs for class HolaMundo */ /* SYMBOL: "HolaMundo/presentaSaludo()V", Java_HolaMundo_presentaSaludo_stub */ __declspec(dllexport) stack_item *Java_HolaMundo_presentaSaludo_stub(stack_item *_P_,struct execenv *_EE_) { extern void HolaMundo_presentaSaludo(void *); (void) HolaMundo_presentaSaludo(_P_[0].p); return _P_; } 10.5 Escribir la funcion C Escribiremos la funcin C para el mtodo nativo en un fichero fuente de cdigo C. La implementacin ser una funcin habitual C, que luego integraremos con la clase Java. La definicin de la funcin C debe ser la misma que la que se ha generado con javah en el fichero HolaMundo.h. La implementacin que proponemos la guardaremos en el fichero HolaImp.c, y contendr las siguientes lnea de cdigo: #include <StubPreamble.h> #include "HolaMundo.h> #include <stdio.h> void HolaMundo_presentaSaludo( struct HHolaMundo *this ) { printf( "Hola Mundo, desde el Tutorial de Java\n" ); return; }

174

Como se puede ver, la implementacin no puede ser ms sencilla: hace una llamada a la funcin printf() para presentar el saludo y sale. En el cdigo se incluyen tres ficheros de cabecera: StubsPreamble.h Proporciona la informacin para que el cdigo C pueda interactuar con el sistema Java. Cuando se escriben mtodos nativos, siempre habr que incluir este fichero en el cdigo fuente C. HolaMundo.h Es el fichero de cabecera que hemos generado para nuestra clase. Contiene la estructura C que representa la clase Java para la que estamos escribiendo el mtodo nativo y la definicin de la funcin para ese mtodo nativo. stdio.h Es necesario incluirlo porque utilizamos la funcin printf() de la librera estndar de C, cuya declaracin se encuentra en este fichero de cabecera. 10.6 Crear la Libreria Dinmica Utilizaremos el compilador C para compilar el fichero .h, el fichero de stubs y el fichero fuente .c; para crear una librera dinmica. Para crearla, utilizaremos el compilador C de nuestro sistema, haciendo que los ficheros HolaMundo.c y HolaImp.c generen una librera dinmica de nombre hola, que ser la que el sistema Java cargue cuando ejecute la aplicacin que estamos construyendo. Vamos a ver cmo generamos esta librera en Unix y en Windows. Unix Teclearemos el siguiente comando: % cc -G HolaMundo.c HolaImp.c -o [Link] En caso de que no encuentre el compilador los ficheros de cabecera, se puede utilizar el flag -I para indicarle el camino de bsqueda, por ejemplo: % cc -G -I$JAVA_HOME/include HolaMundo.c HolaImp.c -o [Link] donde $JAVA_HOME es el directorio donde se ha instalado la versin actual del Java Development Kit. Windows El comando a utilizar en este caso es el siguiente: c:\>cl HolaMundo.c HolaImp.c -[Link] -MD -LD [Link]

175

Este comando funciona con Microsoft Visual C++ 2.x y posteriores. Si queremos indicar al compilador donde se encuentran los ficheros de cabecera y las libreras, tendremos que fijar dos variables de entorno: c:\>SET INCLUDE=%JAVAHOME%\include;%INCLUDE% c:\>SET LIB=%JAVAHOME%\lib;%LIB% donde %JAVAHOME% es el directorio donde se ha instalado la versin actual del Java Development Kit. 10.7 Ejecutar el Programa Y, por fin, utilizaremos el intrprete de Java, java, para ejecutar el programa que hemos construido siguiendo todos los pasos anteriormente descritos. Si tecleamos el comando: > java Main obtendremos el resultado siguiente: % Hola Mundo, desde el Tutorial de Java Si no aparece este mensaje de saludo y lo que aparece en pantalla son expresiones como UnsatisfiedLinkError, es porque no tenemos fijado correctamente el camino de la librera dinmica que hemos generado. Este camino es la lista de directorios que el sistema Java utilizar para buscar las libreras que debe cargar. Debemos asegurarnos de que el directorio donde se encuentra nuestra librera hola recin creada, figura entre ellos. Si fijamos el camino correcto y ejecutamos de nuevo el programa, veremos que ahora s obtenemos el mensaje de saludo que esperbamos. Con ello, hemos visto como integrar cdigo C en programas Java. Quedan muchas cuestiones por medio, como la equivalencia de tipos entre Java y C, el paso de parmetros, el manejo de cadenas, etc. Pero eso supondra entrar en mucha ms profundidad dentro de Java de la que aqu pretendemos (por ahora).

11. Entrada/Salida Estndar


Los usuarios de Unix, y aquellos familiarizados con las lneas de comandos de otros sistemas como DOS, han utilizado un tipo de entrada/salida conocida comnmente por entrada/salida estndar. El fichero de entrada estndar (stdin) es simplemente el teclado. El fichero de salida estndar (stdout) es tpicamente la pantalla (o la ventana del terminal). El fichero de salida de error estndar (stderr) tambin se dirige normalmente a la pantalla, pero se implementa como otro fichero de forma que se pueda distinguir entre la salida normal y (si es necesario) los mensajes de error. 11.1 La clase System Java tiene acceso a la entrada/salida estndar a travs de la clase System. En concreto, los tres ficheros que se implementan son: Stdin

176

[Link] implementa stdin como una instancia de la clase InputStream. Con [Link], se accede a los mtodos read() y skip(). El mtodo read() permite leer un byte de la entrada. skip( long n ), salta n bytes de la entrada. Stdout [Link] implementa stdout como una instancia de la clase PrintStream. Se pueden utilizar los mtodos print() y println() con cualquier tipo bsico Java como argumento. Stderr [Link] implementa stderr de la misma forma que stdout. Como con [Link], se tiene acceso a los mtodos de PrintStream. Vamos a ver un pequeo ejemplo de entrada/salida en Java. El cdigo siguiente, [Link], reproduce, o funciona como la utilidad cat de Unix o type de DOS: import [Link].*; class miType { public static void main( String args[] ) throws IOException { int c; int contador = 0; while( (c = [Link]() ) != '\n' ) { contador++; [Link]( (char)c ); } [Link](); // Lnea en blanco [Link]( "Contados "+ contador +" bytes en total." ); } } 11.2 Clases comunes de Entrada/Salida Adems de la entrada por teclado y salida por pantalla, se necesita entrada/salida por fichero, como son: FileInputStream

177

DataInputStream FileOutputStream DataOutputStream Tambin existen otras clases para aplicaciones ms especficas, que no vamos a tratar, por ser de un uso muy concreto: PipedInputStream BufferedInputStream PushBackInputStream StreamTokenizer PipedOutputStream BufferedOutputStream

12. FICHEROS EN JAVA


Todos los lenguajes de programacin tienen alguna forma de interactuar con los sistemas de ficheros locales; Java no es una excepcin. Cuando se desarrollan applets para utilizar en red, hay que tener en cuenta que la entrada/salida directa a fichero es una violacin de seguridad de acceso. Muchos usuarios configurarn sus navegadores para permitir el acceso al sistema de ficheros, pero otros no. Por otro lado, si se est desarrollando una aplicacin Java para uso interno, probablemente ser necesario el acceso directo a ficheros. Antes de realizar acciones sobre un fichero, necesitamos un poco de informacin sobre ese fichero. La clase File proporciona muchas utilidades relacionadas con ficheros y con la obtencin de informacin bsica sobre esos ficheros. 12.1 Creacin de un objeto File Para crear un objeto File nuevo, se puede utilizar cualquiera de los tres constructores siguientes: File miFichero; miFichero = new File( "/etc/kk" ); o miFichero = new File( "/etc","kk" ); o

178

File miDirectorio = new File( "/etc" ); miFichero = new File( miDirectorio,"kk" ); El constructor utilizado depende a menudo de otros objetos File necesarios para el acceso. Por ejemplo, si slo se utiliza un fichero en la aplicacin, el primer constructor es el mejor. Si en cambio, se utilizan muchos ficheros desde un mismo directorio, el segundo o tercer constructor sern ms cmodos. Y si el directorio o el fichero es una variable, el segundo constructor ser el ms til. 12.2 Ficheros de Acceso Aleatorio A menudo, no se desea leer un fichero de principio a fin; sino acceder al fichero como una base de datos, donde se salta de un registro a otro; cada uno en diferentes partes del fichero. Java proporciona una clase RandomAccessFile para este tipo de entrada/salida. Creacin de un Fichero de Acceso Aleatorio Hay dos posibilidades para abrir un fichero de acceso aleatorio: Con el nombre del fichero: miRAFile = new RandomAccessFile( String nombre,String modo ); Con un objeto File: miRAFile = new RandomAccessFile( File fichero,String modo ); El argumento modo determina si se tiene acceso de slo lectura (r) o de lectura/escritura (r/w). Por ejemplo, se puede abrir un fichero de una base de datos para actualizacin: RandomAccessFile miRAFile; miRAFile = new RandomAccessFile( "/tmp/[Link]","rw" ); Acceso a la Informacin Los objetos RandomAccessFile esperan informacin de lectura/escritura de la misma manera que los objetos DataInput/DataOutput. Se tiene acceso a todas las operaciones read() y write() de las clases DataInputStream y DataOutputStream. Tambin se tienen muchos mtodos para moverse dentro de un fichero: long getFilePointer(); Devuelve la posicin actual del puntero del fichero void seek( long pos ); Coloca el puntero del fichero en una posicin determinada. La posicin se da como un desplazamiento en bytes desde el comienzo del fichero. La posicin 0 marca el comienzo de ese fichero.

179

long length(); Devuelve la longitud del fichero. La posicin length() marca el final de ese fichero. Actualizacin de Informacin Se pueden utilizar ficheros de acceso aleatorio para aadir informacin a ficheros existentes: miRAFile = new RandomAccessFile( "/tmp/[Link]","rw" ); [Link]( [Link]() ); // Cualquier write() que hagamos a partir de este punto del cdigo // aadir informacin al fichero Vamos a ver un pequeo ejemplo, [Link], que aade una cadena a un fichero existente: import [Link].*; // Cada vez que ejecutemos este programita, se incorporara una nueva // linea al fichero de log que se crea la primera vez que se ejecuta // // class Log { public static void main( String args[] ) throws IOException { RandomAccessFile miRAFile; String s = "Informacion a incorporar\nTutorial de Java\n"; // Abrimos el fichero de acceso aleatorio miRAFile = new RandomAccessFile( "/tmp/[Link]","rw" ); // Nos vamos al final del fichero [Link]( [Link]() ); // Incorporamos la cadena al fichero [Link]( s ); // Cerramos el fichero [Link]();

180

} }

13. COMUNICACIONES EN JAVA


13.1 Modelo de Comunicaciones con Java En Java, crear una conexin socket TCP/IP se realiza directamente con el paquete [Link]. A continuacin mostramos un diagrama de lo que ocurre en el lado del cliente y del servidor:

El modelo de sockets ms simple es: El servidor establece un puerto y espera durante un cierto tiempo (timeout segundos), a que el cliente establezca la conexin. Cuando el cliente solicite una conexin, el servidor abrir la conexin socket con el mtodo accept(). El cliente establece una conexin con la mquina host a travs del puerto que se designe en puerto# . El cliente y el servidor se comunican con manejadores InputStream y OutputStream. Hay una cuestin al respecto de los sockets, que viene impuesta por la implementacin del sistema de seguridad de Java. Actualmente, los applets slo pueden establecer conexiones con el nodo desde el cual se transfiri su cdigo. Esto est implementado en el JDK y en el intrprete de Java de Netscape. Esto reduce en gran manera la flexibilidad de las fuentes de datos disponibles para los applets. El problema si se permite que un applet se conecte a cualquier mquina de la red, es que entonces se podran utilizar los applets para inundar la red desde un ordenador con un cliente Netscape del que no se sospecha y sin ninguna posibilidad de rastreo. 13.2 Clases Utiles en Comunicaciones Vamos a exponer otras clases que resultan tiles cuando estamos desarrollando programas de comunicaciones, aparte de las que ya se han visto. El problema es que la mayora de estas clases se prestan a discusin, porque se encuentran bajo el directorio sun. Esto quiere decir que son

181

implementaciones Solaris y, por tanto, especficas del Unix Solaris. Adems su API no est garantizada, pudiendo cambiar. Pero, a pesar de todo, resultan muy interesantes y vamos a comentar un grupo de ellas solamente que se encuentran en el paquete [Link]. Socket Es el objeto bsico en toda comunicacin a travs de Internet, bajo el protocolo TCP. Esta clase proporciona mtodos para la entrada/salida a travs de streams que hacen la lectura y escritura a travs de sockets muy sencilla. ServerSocket Es un objeto utilizado en las aplicaciones servidor para escuchar las peticiones que realicen los clientes conectados a ese servidor. Este objeto no realiza el servicio, sino que crea un objeto Socket en funcin del cliente para realizar toda la comunicacin a travs de l. DatagramSocket La clase de sockets datagrama puede ser utilizada para implementar datagramas o fiables (sockets UDP), no ordenados. Aunque la comunicacin por estos sockets es muy rpida porque no hay que perder tiempo estableciendo la conexin entre cliente y servidor. DatagramPacket Clase que representa un paquete datagrama conteniendo informacin de paquete, longitud de paquete, direcciones Internet y nmeros de puerto. MulticastSocket Clase utilizada para crear una versin multicast de las clase socket datagrama. Mltiples clientes/servidores pueden transmitir a un grupo multicast (un grupo de direcciones IP compartiendo el mismo nmero de puerto). NetworkServer Una clase creada para implementar mtodos y variables utilizadas en la creacin de un servidor TCP/IP. NetworkClient Una clase creada para implementar mtodos y variables utilizadas en la creacin de un cliente TCP/IP. SocketImpl Es un Interface que nos permite crearnos nuestro propio modelo de comunicacin. Tendremos que implementar sus mtodos cuando la usemos. Si vamos a desarrollar una aplicacin con requerimientos especiales de comunicaciones, como pueden se la implementacin de un cortafuegos (TCP es un protocolo no seguro), o acceder a equipos especiales (como un lector de cdigo de barras o un GPS diferencial), necesitaremos nuestra propia clase Socket.

182

14. ARQUITECTURA Modelo/Vista/Controlador


La arquitectura MVC (Model/View/Controller) fue introducida como parte de la versin Smalltalk-80 del lenguaje de programacin Smalltalk. Fue diseada para reducir el esfuerzo de programacin necesario en la implementacin de sistemas mltiples y sincronizados de los mismos datos. Sus caractersticas principales son que el Modelo, las Vistas y los Controladores se tratan como entidades separadas; esto hace que cualquier cambio producido en el Modelo se refleje automticamente en cada una de las Vistas. Adems del programa ejemplo que hemos presentado al principio y que posteriormente implementaremos, este modelo de arquitectura se puede emplear en sistemas de representacin grfica de datos, como se ha citado, o en sistemas CAD, en donde se presentan partes del diseo con diferente escala de aumento, en ventanas separadas. En la figura siguiente, vemos la arquitectura MVC en su forma ms general. Hay un Modelo, mltiples Controladores que manipulan ese Modelo, y hay varias Vistas de los datos del Modelo, que cambian cuando cambia el estado de ese Modelo.

Este modelo de arquitectura presenta varias ventajas: Hay una clara separacin entre los componentes de un programa; lo cual nos permite implementarlos por separado. Hay un API muy bien definido; cualquiera que use el API, podr reemplazar el Modelo, la Vista o el Controlador, sin aparente dificultad. La conexin entre el Modelo y sus Vistas es dinmica; se produce en tiempo de ejecucin, no en tiempo de compilacin. Al incorporar el modelo de arquitectura MVC a un diseo, las piezas de un programa se pueden construir por separado y luego unirlas en tiempo de ejecucin. Si uno de los Componentes, posteriormente, se observa que funciona mal, puede reemplazarse sin que las otras piezas se vean afectadas. Este escenario contrasta con la aproximacin monoltica tpica de muchos programas Java. Todos tienen un Frame que contiene todos los elementos, un controlador de eventos, un montn de clculos y la presentacin del resultado. Ante esta perspectiva, hacer un cambio aqu no es nada trivial. 14.1 Definicin de las partes El Modelo es el objeto que representa los datos del programa. Maneja los datos y controla todas sus transformaciones. El Modelo no tiene conocimiento especfico de los Controladores o de las Vistas, ni siquiera contiene referencias a ellos. Es el propio sistema el que tiene encomendada la responsabilidad de mantener enlaces entre el Modelo y sus Vistas, y notificar a las Vistas cuando cambia el Modelo.

183

La Vista es el objeto que maneja la presentacin visual de los datos representados por el Modelo. Genera una representacin visual del Modelo y muestra los datos al usuario. Interacta con el Modelo a travs de una referencia al propio Modelo. El Controlador es el objeto que proporciona significado a las ordenes del usuario, actuando sobre los datos representados por el Modelo. Cuando se realiza algn cambio, entra en accin, bien sea por cambios en la informacin del Modelo o por alteraciones de la Vista. Interacta con el Modelo a travs de una referencia al propio Modelo. Vamos a mostrar un ejemplo concreto. Consideremos como tal el sistema descrito en la introduccin a este captulo, una pieza geomtrica en tres dimensiones, que representamos en la figura siguiente:

En este caso, la pieza central de la escena en tres dimensiones es el Modelo. El Modelo es una descripcin matemtica de los vrtices y las caras que componen la escena. Los datos que describen cada vrtice o cara pueden modificarse (quizs como resultado de una accin del usuario, o una distorsin de la escena, o un algoritmo de sombreado). Sin embargo, no tiene nocin del punto de vista, mtodo de presentacin, perspectiva o fuente de luz. El Modelo es una representacin pura de los elementos que componen la escena. La porcin del programa que transforma los datos dentro del Modelo en una presentacin grfica es la Vista. La Vista incorpora la visin del Modelo a la escena; es la representacin grfica de la escena desde un punto de vista determinado, bajo condiciones de iluminacin determinadas. El Controlador sabe que puede hacer el Modelo e implementa el interface de usuario que permite iniciar la accin. En este ejemplo, un panel de datos de entrada es lo nico que se necesita, para permitir aadir, modificar o borrar vrtices o caras de la figura.

184

Curso de Visual Basic I


Qu es Visual Basic? La palabra "Visual" hace referencia al mtodo que se utiliza para crear la interfaz grfica de usuario (GUI). En lugar de escribir numerosas lneas de cdigo para describir la apariencia y la ubicacin de los elementos de la interfaz, simplemente puede arrastrar y colocar objetos prefabricados en su lugar dentro de la pantalla. Si ha utilizado alguna vez un programa de dibujo como Paint, ya tiene la mayor parte de las habilidades necesarias para crear una interfaz de usuario efectiva. La palabra "Basic" hace referencia al lenguaje BASIC (Beginners All-Purpose Symbolic Instruction Code), un lenguaje utilizado por ms programadores que ningn otro lenguaje en la historia de la informtica o computacin. Visual Basic ha evolucionado a partir del lenguaje BASIC original y ahora contiene centenares de instrucciones, funciones y palabras clave, muchas de las cuales estn directamente relacionadas con la interfaz grfica de Windows. Los principiantes pueden crear aplicaciones tiles con slo aprender unas pocas palabras clave, pero, al mismo tiempo, la eficacia del lenguaje permite a los profesionales acometer cualquier objetivo que pueda alcanzarse mediante cualquier otro lenguaje de programacin de Windows. El lenguaje de programacin Visual Basic no es exclusivo de Visual Basic. La Edicin para aplicaciones del sistema de programacin de Visual Basic, incluida en Microsoft Excel, Microsoft Access y muchas otras aplicaciones Windows, utilizan el mismo lenguaje. El sistema de programacin de Visual Basic, Scripting Edition (VBScript) para programar en Internet es un subconjunto del lenguaje Visual Basic. La inversin realizada en el aprendizaje de Visual Basic le ayudar a abarcar estas otras reas. Si su objetivo es crear un pequeo programa para su uso personal o para su grupo de trabajo, un sistema para una empresa o incluso aplicaciones distribuidas de alcance mundial a travs de Internet, Visual Basic dispone de las herramientas que necesita.

Las caractersticas de acceso a datos le permiten crear bases de datos y aplicaciones cliente para los formatos de las bases de datos ms conocidas, incluidos Microsoft SQL Server y otras bases de datos de mbito empresarial. Las tecnologas ActiveX le permiten utilizar la funcionalidad proporcionada por otras aplicaciones, como el procesador de textos Microsoft Word, la hoja de clculo Microsoft Excel y otras aplicaciones Windows. Puede incluso automatizar las aplicaciones y los objetos creados con la Edicin profesional o la Edicin empresarial de Visual Basic. Las capacidades de Internet facilitan el acceso a documentos y aplicaciones a travs de Internet desde su propia aplicacin. La aplicacin terminada es un autntico archivo .exe que utiliza una biblioteca de vnculos dinmicos (DLL) de tiempo de ejecucin que puede distribuir con toda libertad.

Ediciones de Visual Basic


Visual Basic se encuentra disponible en tres versiones, cada una de las cuales est orientada a unos requisitos de programacin especficos.

185

La Edicin de aprendizaje de Visual Basic permite a los programadores crear robustas aplicaciones para Microsoft Windows 95 y Windows NT. Incluye todos los controles intrnsecos, adems de los controles de cuadrcula, de fichas y los controles enlazados a datos. La documentacin que se proporciona con esta edicin incluye Learn VB Now (un CD-ROM multimedia), un Manual del programador impreso, la Ayuda en pantalla y los Libros en pantalla de Visual Basic. La Edicin profesional proporciona a los profesionales un completo conjunto de herramientas para desarrollar soluciones para terceros. Incluye todas las caractersticas de la Edicin de aprendizaje, as como controles ActiveX adicionales, incluidos controles para Internet y el Generador de informes de Crystal Reports. La documentacin que se proporciona con la Edicin profesional incluye el Manual del programador, la Ayuda en pantalla, la Gua de herramientas componentes y el Manual del usuario de Crystal Reports para Visual Basic. La Edicin empresarial permite a los profesionales crear slidas aplicaciones distribuidas en un entorno de equipo. Incluye todas las caractersticas de la Edicin profesional, as como el Administrador de automatizacin, la Galera de objetos, las herramientas de administracin de bases de datos, el sistema de control de versiones orientado a proyectos Microsoft Visual SourceSafe, etc. La documentacin impresa que se proporciona con la Edicin empresarial incluye toda la documentacin de la Edicin profesional, y la Gua para la creacin de aplicaciones cliente-servidor con Visual Basic y el Manual del usuario de SourceSafe.

1-

Introduccin:

1.1- Programacin orientada a objetos. 1.1.1- Objetos.


Un objeto es una entidad que tiene asociado un conjunto de mtodos, eventos y propiedades. Ejemplo: Una caja de texto (TextBox) en la cual podemos escribir cualquier lnea es un objeto.

1.1.2- Propiedades.
Son las caractersticas que posee un objeto o un formulario (ventana de Windows). Ejemplo: Color de fondo del formulario, Fuente de texto de un TextBox, .

1.1.3- Mtodos.
Los mtodos son funciones internas de un determinado objeto que permite realizar funciones sobre l o sobre otro objeto. Ejemplo: Deseamos poner en la ventana Windows de nuestra aplicacin "Hola mundo", por tanto pondremos el mtodo -> [Link] "Hola mundo"

1.1.4- Eventos.

186

Los eventos son acciones que se pueden realizar en cualquier control: click, doble click, movimiento del ratn. A estos eventos se les puede asociar cdigo para que se ejecute al producir el evento. Un programa Visual Basic es un POE (Programa orientado a eventos). Todo lo que hacemos en un programa Visual Basic est generado por medio de eventos

1.1.5- Explicacin integrada y ejemplo de Objetos, Propiedades, Mtodos y Eventos.


Los formularios y controles de Visual Basic son objetos que exponen sus propios mtodos, propiedades y eventos. Las propiedades se pueden considerar como atributos de un objeto, los mtodos como sus acciones y los eventos como sus respuestas. Un objeto de uso diario como el globo de un nio tiene tambin propiedades, mtodos y eventos. Entre las propiedades de un globo se incluyen atributos visibles como el peso, el dimetro y el color. Otras propiedades describen su estado (inflado o desinflado) o atributos que no son visibles, como su edad. Por definicin, todos los globos tienen estas propiedades; lo que vara de un globo a otros son los valores de estas propiedades. Un globo tiene tambin mtodos o acciones inherentes que puede efectuar. Tiene un mtodo inflar (la accin de llenarlo de helio) o un mtodo desinflar (expeler su contenido) y un mtodo elevarse (si se deja escapar). De nuevo, todos los globos pueden efectuar estos mtodos. Los globos tienen adems respuestas predefinidas a ciertos eventos externos. Por ejemplo, un globo respondera al evento de pincharlo desinflndose o al evento de soltarlo elevndose en el aire. Los objetos tienen propiedades, responden a eventos y ejecutan mtodos: Si se pudiera programar un globo, el cdigo de Visual Basic podra ser como el siguiente. Para establecer las propiedades del globo: [Link] = Rojo [Link] = 10 [Link] = True Observe la sintaxis del cdigo: el objeto (Globo) seguido de la propiedad (Color) seguida de la asignacin del valor (Rojo). Podra modificar el color del globo desde el cdigo si repitiera esta instruccin y sustituyera el valor por otro diferente. Las propiedades tambin se pueden establecer en la ventana Propiedades mientras se est diseando la aplicacin. Los mtodos de un globo se invocan de esta forma: [Link] [Link] [Link] 5

187

La sintaxis es similar a la sintaxis de las propiedades: el objeto (un nombre) seguido de un mtodo (un verbo). En el tercer ejemplo hay un elemento adicional, llamado argumento, que indica la distancia que se eleva. Algunos mtodos tendrn uno o ms argumentos para describir ms a fondo la accin que se va a ejecutar. El globo puede responder a un evento como se muestra a continuacin: Sub Globo_Pinchazo() [Link] [Link] "Bang" [Link] = False [Link] = 1 End Sub En este caso, el cdigo describe el comportamiento del globo cuando se produce un evento Pinchazo: invoca el mtodo Desinflar y luego invoca el mtodo HacerRuido con un argumento Bang (el tipo de ruido que se va a hacer). Como el globo ya no est inflado, la propiedad Inflado tiene el valor False y la propiedad Dimetro adopta un nuevo valor. Si bien no puede programar un globo, s puede programar un formulario o un control de Visual Basic. Como programador, tiene el control: decide qu propiedades se deben modificar, qu mtodos se deben invocar o a qu eventos hay que responder para conseguir la apariencia y el comportamiento deseados

1.1.6- Diferencias entre la programacin procedural y la programacin bajo Windows.


Un estudio profundo del funcionamiento interno de Windows necesitara un libro completo. No es necesario tener un profundo conocimiento de todos los detalles tcnicos. Una versin reducida del funcionamiento de Windows incluye tres conceptos clave: ventanas, eventos y mensajes. Una ventana es simplemente una regin rectangular con sus propios lmites. Probablemente ya sabe que hay varios tipos de ventanas: una ventana Explorador en Windows 95, una ventana de documento dentro de su programa de proceso de textos o un cuadro de dilogo que emerge para recordarle una cita. Aunque stos son los ejemplos ms comunes, realmente hay otros muchos tipos de ventanas. Un botn de comando es una ventana. Los iconos, cuadros de texto, botones de opcin y barras de mens son todos ventanas. El sistema operativo Microsoft Windows administra todas estas ventanas asignando a cada una un nico nmero identificador (controlador de ventana o hWnd). El sistema controla continuamente cada una de estas ventanas para ver si existen signos de actividad o eventos. Los eventos pueden producirse mediante acciones del usuario, como hacer clic con el mouse (ratn) o presionar una tecla, mediante programacin o incluso como resultado de acciones de otras ventanas. Cada vez que se produce un evento se enva un mensaje al sistema operativo. El sistema procesa el mensaje y lo transmite a las dems ventanas. Entonces, cada ventana puede realizar la accin apropiada, basndose en sus propias instrucciones para tratar ese mensaje en particular (por ejemplo, volverse a dibujar cuando otra ventana la ha dejado al descubierto).

188

Como puede imaginar, tratar todas las combinaciones posibles de ventanas, eventos y mensajes podra ser interminable. Afortunadamente, Visual Basic le evita tener que tratar con todos los controladores de mensajes de bajo nivel. Muchos de los mensajes los controla automticamente Visual Basic, mientras que otros se tratan como procedimientos de evento para su comodidad. Esto le permite crear rpidamente eficaces aplicaciones sin tener que tratar detalles innecesarios. En las aplicaciones tradicionales o "por procedimientos", la aplicacin es la que controla qu partes de cdigo y en qu secuencia se ejecutan. La ejecucin comienza con la primera lnea de cdigo y contina con una ruta predefinida a travs de la aplicacin, llamando a los procedimientos segn se necesiten. En una aplicacin controlada por eventos, el cdigo no sigue una ruta predeterminada; ejecuta distintas secciones de cdigo como respuesta a los eventos. Los eventos pueden desencadenarse por acciones del usuario, por mensajes del sistema o de otras aplicaciones, o incluso por la propia aplicacin. La secuencia de estos eventos determina la secuencia en la que se ejecuta el cdigo, por lo que la ruta a travs del cdigo de la aplicacin es diferente cada vez que se ejecuta el programa. Puesto que no puede predecir la secuencia de los eventos, el cdigo debe establecer ciertos supuestos acerca del "estado del mundo" cuando se ejecute. Cuando haga suposiciones (por ejemplo, que un campo de entrada debe contener un valor antes de ejecutar un procedimiento para procesar ese valor), debe estructurar la aplicacin de forma que asegure que esa suposicin siempre ser vlida (por ejemplo, deshabilitando el botn de comando que inicia el procedimiento hasta que el campo de entrada contenga un valor). El cdigo tambin puede desencadenar eventos durante la ejecucin. Por ejemplo, cambiar mediante programacin el texto de un cuadro de texto hace que se produzca el evento Change del cuadro de texto. Esto causara la ejecucin del cdigo (si lo hay) contenido en el evento Change. Si supone que este evento slo se desencadenar mediante la interaccin del usuario, podra ver resultados inesperados. Por esta razn es importante comprender el modelo controlado por eventos y tenerlo en cuenta cuando disee su aplicacin.

1.3- Proyecto. 1.3.1- Definicin de Proyecto en Visual Basic.


Para crear una aplicacin con Visual Basic se trabaja con proyectos. Un proyecto es una coleccin de archivos que se usan para generar una aplicacin. Este tema describe cmo generar y administrar proyectos. Al crear una aplicacin probablemente crear nuevos formularios; tambin puede volver a usar o modificar formularios creados en proyectos anteriores. Esto tambin se aplica a otros mdulos o archivos que pueda incluir en su proyecto. Los controles ActiveX y los objetos de otras aplicaciones tambin se pueden compartir entre proyectos. Despus de ensamblar todos los componentes de un proyecto y escribir el cdigo, puede compilar el proyecto para crear un archivo ejecutable.

1.3.2-Componentes de un Proyecto.
Cuando desarrolla un aplicacin, trabaja con un archivo de proyecto para administrar todos los diferentes archivos que crea. Un proyecto consta de lo siguiente:

189

Un archivo de proyecto que realiza el seguimiento de todos los componentes (.vbp) Un archivo para cada formulario (.frm). Un archivo de datos binario para cada formulario que contenga datos sobre propiedades de controles del formulario (.frx). Estos archivos no se pueden modificar y los genera automticamente cualquier archivo .frm que tenga propiedades en formato binario, como Picture o Icon. Opcionalmente, un archivo para cada mdulo de clase (.cls). Opcionalmente, un archivo para cada mdulo estndar (.bas). Opcionalmente, uno o ms archivos con controles ActiveX (.ocx). Opcionalmente, un nico archivo de recursos (.res).

El archivo de proyecto es simplemente una lista de todos los archivos y objetos asociados con el proyecto, as como informacin sobre las opciones de entorno establecidas. Esta informacin se actualiza cada vez que guarda el proyecto. Todos los archivos y objetos tambin se pueden compartir con otros proyectos. Cuando ha completado todos los archivos del proyecto puede convertir el proyecto en un archivo ejecutable (.exe): en el men Archivo, elija el comando Generar [Link].

[Link]-Formularios.
Un formulario es una ventana. La ventana Windows de cualquier aplicacin. Podemos abrir tantas ventanas como queramos en nuestro proyecto, pero el nombre de las ventanas debe ser distinto. Por defecto como ya hemos visto, la ventana que se abre en Visual Basic tiene el nombre de Form1. Ya veremos como cambiar estas "Propiedades" ms adelante. Los mdulos de formularios (extensin de nombre de archivo .frm) pueden contener descripciones en forma de texto del formulario y sus controles, incluyendo los valores de sus propiedades. Tambin pueden contener declaraciones a nivel de formulario de constantes, variables y procedimientos externos, procedimientos de evento y procedimientos generales.

[Link]-Mdulos de clase.
Los mdulos de clase (extensin de nombre de archivo .cls) son similares a los mdulos de formulario, excepto en que no tiene interfaz de usuario visible. Puede usar mdulos de clase para crear sus propios objetos, incluyendo cdigo para mtodos y propiedades.

[Link]-Mdulos estndar.
Un mdulo es un archivo Visual Basic donde escribimos parte del cdigo de nuestro programa, y digo parte, porque puede haber cdigo en el formulario tambin. Las rutinas incluidas dentro de los mdulos pueden ser ejecutadas desde los formularios de la aplicacin. Los mdulos estndar (extensin de nombre de archivo .bas) pueden contener declaraciones pblicas o a nivel de mdulo de tipos, constantes, variables, procedimientos externos y procedimientos pblicos.

[Link]-Archivos de Recursos.

190

Los archivos de recursos (extensin de nombre de archivo .res) contienen mapas de bits, cadenas de texto y otros datos que puede modificar sin volver a modificar el cdigo. Por ejemplo, si piensa traducir su aplicacin a un idioma extranjero, puede guardar todas las cadenas de texto de la interfaz de usuario y los mapas de bits en un archivo de recursos, y simplemente traducir el archivo de recursos en vez de la aplicacin completa. Un proyecto slo puede contener un archivo de recursos.

[Link]-Controles Active X.
Los controles ActiveX (extensin de nombre de archivo .ocx) son controles opcionales que se pueden agregar al cuadro de herramientas y se pueden usar en formularios. Cuando instala Visual Basic, los archivos que contienen los controles incluidos en Visual Basic se copian a un directorio comn (el subdirectorio \Windows\System en Windows 95). Existen controles ActiveX adicionales disponibles en diversas fuentes. Tambin puede crear sus propios controles mediante las ediciones Profesional y Empresarial de Visual Basic.

[Link]-Controles estndar.
Los controles estndar los proporciona Visual Basic. Los controles estndar, como CommandButton (botn de comando) o Frame (marco), siempre estn incluidos en el cuadro de herramientas, al contrario de lo que ocurre con los controles ActiveX y los objetos insertables, que se pueden agregar y quitar del cuadro de herramientas.

1.4-Entorno de Desarrollo. 1.4.1-Barra de men. y 1.4.2-Barra de Herramientas.


En la ventana del programa, podemos hacer todas las funciones normales que nos permite el compilador Visual Basic.

1.4.3-Ventana de Proyecto.

Pulse "Ctrl+R" (Ver -> Proyecto) y se abrir la ventana de proyectos (3). En esta ventana tenemos todos los ficheros del proyecto Visual Basic en el que vamos a trabajar.

1.4.4- Formulario.

191

Al principio y por defecto, el programa abre un formulario con el nombre Form1 que es la ventana Windows de nuestra aplicacin.

1.4.5- Ventana de Propiedades.

Pulsando la tecla "F4", aparecer la ventana de propiedades . Esta ventana es fundamental, ya que contiene todas las propiedades de cada objeto que insertaremos en nuestro formulario, as como las propiedades del formulario en s.

1.4.6- Caja de Herramientas.

192

La ventana caja de herramientas contiene todos los objetos que podemos incluir en nuestro formulario. Esta ventana se puede abrir en el men principal (Ver -> Caja de herramientas).

2-Programacin: 2.1- Fundamentos de la Programacin.


Cada mdulo de formulario contiene procedimientos de evento (secciones de cdigo donde se colocan las instrucciones que se ejecutarn como respuesta a eventos especficos). Los formularios pueden contener controles. Por cada control de un formulario, existe el correspondiente conjunto de procedimientos de evento en el mdulo de formulario. Adems de procedimientos de evento, los mdulos de formulario pueden contener procedimientos generales que se ejecutan como respuesta a una llamada desde cualquier procedimiento de evento. El cdigo que no est relacionado con un control o un formulario especfico se puede colocar en un tipo diferente de mdulo, un mdulo estndar (.bas). Se deben colocar en un mdulo estndar los procedimientos que se puedan utilizar como respuesta a eventos de diversos objetos, en lugar de duplicar el cdigo en los procedimientos de evento de cada objeto.

2.1.1- Como funciona una aplicacin controlada por eventos.


Un evento es una accin reconocida por un formulario o un control. Las aplicaciones controladas por eventos ejecutan cdigo Basic como respuesta a un evento. Cada formulario y control de Visual Basic tiene un conjunto de eventos predefinidos. Si se produce uno de dichos eventos y el procedimiento de evento asociado tiene cdigo, Visual Basic llama a ese cdigo. Aunque los objetos de Visual Basic reconocen automticamente un conjunto predefinido de eventos, usted decide cundo y cmo se responder a un evento determinado. A cada evento le corresponde una seccin de cdigo (un procedimiento de evento). Cuando desea que un control responda a un evento, escribe cdigo en el procedimiento de ese evento. Los tipos de eventos reconocidos por un objeto varan, pero muchos tipos son comunes a la mayora de los controles. Por ejemplo, la mayora de los objetos reconocen el evento Click: si un usuario hace clic en un formulario, se ejecuta el cdigo del procedimiento de evento Click del formulario; si un usuario hace clic en un botn de comando, se ejecuta el cdigo del procedimiento de evento Click del botn. El cdigo en cada caso ser diferente.

193

He aqu una secuencia tpica de eventos en una aplicacin controlada por eventos: 1. Se inicia la aplicacin y se carga y muestra un formulario. 2. El formulario (o un control del formulario) recibe un evento. El evento puede estar causado por el usuario (por ejemplo, por la pulsacin de una tecla), por el sistema (por ejemplo, un evento de cronmetro) o, de forma indirecta, por el cdigo (por ejemplo, un evento Load cuando el cdigo carga un formulario). 3. Si hay cdigo en el procedimiento de evento correspondiente, se ejecuta. 4. La aplicacin espera al evento siguiente.

2.2- Variables. 2.2.1- Alcance de las variables.


El alcance de una variable define qu partes del cdigo son conscientes de su existencia. Cuando declara una variable en un procedimiento, slo el cdigo de dicho procedimiento puede tener acceso o modificar el valor de la variable; tiene un alcance que es local al procedimiento. A veces, sin embargo, se necesita utilizar una variable con un alcance ms general, como aquella cuyo valor est disponible para todos los procedimientos del mismo mdulo o incluso para todos los procedimientos de toda la aplicacin. Visual Basic le permite especificar el alcance de una variable cuando la declara. Establecimiento del alcance de las variables Dependiendo de cmo se declara, una variable tiene como alcance un procedimiento (local) o un mdulo. Alcance Nivel de procedimiento Nivel de mdulo Privado Las variables son privadas del procedimiento en el que aparecen. Las variables son privadas del mdulo en el que aparecen. Pblico No es aplicable. No puede declarar variables pblicas dentro de un procedimiento. Las variables estn disponibles para todos los mdulos.

Variables utilizadas en un procedimiento Las variables a nivel de procedimiento slo se reconocen en el procedimiento en el que se han declarado. Se las conoce tambin como variables locales. Se declaran mediante las palabras clave Dim o Static. Por ejemplo: Dim intTemp As Integer o bien Static intPermanent As Integer Los valores de variables locales declaradas con Static existen mientras se ejecuta la aplicacin, mientras que las variables declaradas con Dim slo existen mientras se ejecuta el procedimiento.

194

Las variables locales resultan una eleccin apropiada para clculos temporales. Por ejemplo, puede crear una docena de procedimientos distintos que contengan una variable llamada intTemp. Como cada intTemp se ha declarado como una variable local, cada procedimiento slo reconoce su propia versin de intTemp. Cualquier procedimiento puede alterar el valor de su intTemp local sin que ello afecte a las variables intTemp de los dems procedimientos. Variables utilizadas en un mdulo De forma predeterminada, una variable a nivel de mdulo est disponible para todos los procedimientos del mdulo, pero no para el cdigo de otros mdulos. Cree variables a nivel de mdulo declarndolas con la palabra clave Private en la seccin Declaraciones al principio del mdulo. Por ejemplo: Private intTemp As Integer A nivel de mdulo, no hay diferencia entre Private y Dim, pero es preferible Private porque contrasta con Public y hace que el cdigo sea ms fcil de comprender. Variables utilizadas por todos los mdulos Para hacer que una variable a nivel de mdulo est disponible para otros mdulos, utilice la palabra clave Public para declarar la variable. Los valores de las variables pblicas estn disponibles para todos los procedimientos de la aplicacin. Al igual que todas las variables a nivel de mdulo, las variables pblicas se declaran en la seccin Declaraciones al principio del mdulo. Por ejemplo: Public intTemp As Integer Nota: No puede declarar variables pblicas en un procedimiento, slo en la seccin Declaraciones de un mdulo.

2.2.2- Declaracin
La forma de declarar las variables es la siguiente: Dim Public Static nombre_variable As tipo Dim: Al declarar una variable con esta palabra estamos diciendo que la variable sea local al mbito en que se declara. Puede ser dentro de un procedimiento o dentro de un formulario, de esta forma no sera accesible desde los dems procedimientos o formularios. Public: Las variables declaradas sern publicas y podrn estar accesibles desde todos los formularios de la aplicacin. Para conseguirlo tendremos que declararlas en un mdulo de cdigo, no en la seccin declarations de cualquier formulario de los que conste la aplicacin. Para crear un mdulo de cdigo en el men principal de Visual Basic marcamos en PROYECTO/INSETAR MDULO y aparecer junto a los dems formularios de la ventana de proyecto aunque con un icono distinto indicando que se trata de un mdulo de cdigo. Static: Con esta forma de declarar variables conseguiremos que las variables locales no se creen y se destruyan al entrar y salir de los procedimientos donde fueron declaradas sino que se mantenga su valor durante todo el periodo de ejecucin de la aplicacin. De esta forma a entrar en algn procedimiento las variables recuerdan el valor que tenan cuando se sali de l.

195

2.2.3- Tipos de variables


PRIVATE<TBODY>TIPO BOOLEAN BYTE INTEGER LONG SINGLE DOUBLE CURRENCY STRING DATE COMENTARIO Slo admite 2 valores TRUE o FALSE admite valores entre 0 y 255 admite valores entre -32768 y 32767 admite valores entre -[Link] y [Link] admite valores decimales con precisin simple admite valores decimales de doble precisin vlido para valores de tipo moneda cadenas de caracteres fechas, permite operar con ellas</TBODY>

2.2.4- Matrices
Para declarar matrices debemos colocar entre parntesis el nmero de elementos de los que constar a continuacin del nombre de la variable: Dim medidas(9) as integer De esta forma tenemos una matriz de 10 elementos identificados del 0 al 9 Podemos obligar a que el primer elemento de una matriz tenga el ndice con valor 1. Esto lo haremos colocando la instruccin option base 1 en la seccin declarations de nuestro formulario. Tambin podemos indicar los lmites inferior y superior de la matriz: Dim medidas(5 to 14) as integer es una matriz de 10 elementos cuyos indices van del 5 al 14 Las matrices multidimensionales se declaran de la siguiente forma: Dim medidas(1 to 10, 1 to 10) as integer CONSIDERACIONES Al trabajar con Visual Basic es preferible que activemos la opcin que nos obligue a declarar todas las variables que utilicemos, de esta forma nos ahorraremos errores inesperados como el de trabajar con una variable ya utilizada anteriormente producindose un conflicto difcil de resolver. En cambio si intentamos declarar 2 variables con el mismo nombre, en el mismo formulario o procedimiento se produce un error en tiempo de edicin avisndonos de la situacin. Para activar esta opcin debemos ir a la opcin del men Herramientas y Opciones para que aparezca un cuadro de dialogo como este.

196

La opcin que nos interesa activar es Requerir declaracin de variables que en este caso ya lo est. De esta forma en cada seccin declarations de cada formulario aparecer la sentencia option explicit Otra opcin que es interesante activar, es la de Guardar los cambios en la ficha entorno, la cual te guarda una copia del cdigo antes de ejecutarlo por si acaso luego no podemos, se bloquea la aplicacin etc... no suele pasar pero nunca se sabe. De esta forma te aseguras que lo ltimo que hayas ejecutado lo tienes guardado en el disco. La opcin Comprobacin automtica de sintaxis normalmente viene activada por defecto, no conviene desactivarla puesto que te avisa de errores de sintaxis conforme vas escribiendo el cdigo: Si te falta el then despus del if, el do antes del while etc...

2.3- Procedimientos y funciones. 2.3.1-Introduccin a los Procedimientos.


Puede simplificar las tareas de programacin si divide los programas en componentes lgicos ms pequeos. Estos componentes, llamados procedimientos, pueden convertirse en bloques bsicos que le permiten mejorar y ampliar Visual Basic. Los procedimientos resultan muy tiles para condensar las tareas repetitivas o compartidas, como clculos utilizados frecuentemente, manipulacin de texto y controles, y operaciones con bases de datos. Hay dos ventajas principales cuando se programa con procedimientos: Los procedimientos le permiten dividir los programas en unidades lgicas discretas, cada una de las cuales se puede depurar ms fcilmente que un programa entero sin procedimientos.

197

Los procedimientos que se utilizan en un programa pueden actuar como bloques de construccin de otros programas, normalmente con pocas o ninguna modificacin.

En Visual Basic se utilizan varios tipos de procedimientos: Procedimientos Sub que no devuelven un valor. Procedimientos Function que devuelven un valor (normalmente conocidos como funciones).

2.3.2- Procedimientos.
Un procedimiento Sub es un bloque de cdigo que se ejecuta como respuesta a un evento. Al dividir el cdigo de un mdulo en procedimientos Sub, es ms sencillo encontrar o modificar el cdigo de la aplicacin. La sintaxis de un procedimiento Sub es la siguiente: [Private|Public][Static]Sub nombre_procedimiento (argumentos) instrucciones End Sub Cada vez que se llama al procedimiento se ejecutan las instrucciones que hay entre Sub y End Sub. Se pueden colocar los procedimientos Sub en mdulos estndar, mdulos de clase y mdulos de formulario. De forma predeterminada, los procedimientos Sub son Public en todos los mdulos, lo que significa que se les puede llamar desde cualquier parte de la aplicacin. Los argumentos de un procedimiento son como las declaraciones de variables; se declaran valores que se pasan desde el procedimiento que hace la llamada. Resulta muy til en Visual Basic distinguir entre dos tipos de procedimientos Sub, procedimientos generales y procedimientos de evento. Procedimientos generales Un procedimiento general indica a la aplicacin cmo realizar una tarea especfica. Una vez que se define un procedimiento general, se le debe llamar especficamente desde la aplicacin. Por el contrario, un procedimiento de evento permanece inactivo hasta que se le llama para responder a eventos provocados por el usuario o desencadenados por el sistema. Por qu crear procedimientos generales? Una razn es que muchos procedimientos de evento distintos pueden necesitar que se lleven a cabo las mismas acciones. Es una buena estrategia de programacin colocar las instrucciones comunes en un procedimiento distinto (un procedimiento general) y hacer que los procedimientos de evento lo llamen. Esto elimina la necesidad de duplicar cdigo y tambin hace que la aplicacin sea ms fcil de mantener. Procedimientos de evento Cuando un objeto en Visual Basic reconoce que se ha producido un evento, llama automticamente al procedimiento de evento utilizando el nombre correspondiente al evento. Como

198

el nombre establece una asociacin entre el objeto y el cdigo, se dice que los procedimientos de evento estn adjuntos a formularios y controles. Un procedimiento de evento de un control combina el nombre real del control (especificado en la propiedad Name), un carcter de subrayado (_) y el nombre del evento. Por ejemplo, si desea que un botn de comando llamado cmdPlay llame a un procedimiento de evento cuando se haga clic en l, utilice el procedimiento cmdPlay_Click. Un procedimiento de evento de un formulario combina la palabra "Form", un carcter de subrayado y el nombre del evento. Si desea que un formulario llame a un procedimiento de evento cuando se hace clic en l, utilice el procedimiento Form_Click. (Como los controles, los formularios tienen nombres nicos, pero no se utilizan en los nombres de los procedimientos de evento.)

Todos los procedimientos de evento utilizan la misma sintaxis general. Sintaxis de un evento de control Sintaxis de un evento de formulario

Private Sub nombrecontrol_nombreevento (argumentos ) instrucciones End Sub Private Sub Form_nombreevento (argumentos) instrucciones End Sub Aunque puede escribir procedimientos de evento nuevos, es ms sencillo utilizar los procedimientos de cdigo que facilita Visual Basic, que incluyen automticamente los nombres correctos de procedimiento. Puede seleccionar una plantilla en la ventana Editor de cdigo si selecciona un objeto en el cuadro Objeto y selecciona un procedimiento en el cuadro Procedimiento. Tambin es conveniente establecer la propiedad Name de los controles antes de empezar a escribir los procedimientos de evento para los mismos. Si cambia el nombre de un control tras vincularle un procedimiento, deber cambiar tambin el nombre del procedimiento para que coincida con el nuevo nombre del control. De lo contrario, Visual Basic no ser capaz de hacer coincidir el control con el procedimiento. Cuando el nombre de un procedimiento no coincide con el nombre de un control, se convierte en un procedimiento general.

2.3.3- Funciones.
La sintaxis de un procedimiento Function es la siguiente: [Private|Public][Static]Function nombre_procedimiento (argumentos) [As tipo] instrucciones End Function

199

Al igual que un procedimiento Sub, un procedimiento Function es un procedimiento diferente que puede tomar argumentos, realizar una serie de instrucciones y cambiar el valor de los argumentos. A diferencia de los procedimientos Sub, los procedimientos Function pueden devolver un valor al procedimiento que realiza la llamada. Hay tres diferencias entre los procedimientos Sub y Function: Generalmente, se llama a una funcin incluyendo el nombre y los argumentos del procedimiento en la parte derecha de una instruccin o expresin mayor (valor_retorno = funcin()). Los procedimientos Function tienen tipos de datos, al igual que las variables. Esto determina el tipo del valor de retorno. (En ausencia de la clusula As, el tipo es el tipo predeterminado Variant.) Se devuelve un valor asignndole al propio nombre_procedimiento. Cuando el procedimiento Function devuelve un valor, se puede convertir en parte de una expresin mayor.

Por ejemplo, podra escribir una funcin que calculara el tercer lado, o hipotenusa, de un tringulo rectngulo, dados los valores de los otros dos lados: Function Hipotenusa (A As Integer, B As Integer) As String Hipotenusa = Sqr(A ^ 2 + B ^ 2) End Function Se llama a un procedimiento Function de la misma forma que a las funciones incorporadas en Visual Basic: [Link] = Hipotenusa(CInt([Link]),CInt([Link])) strX = Hipotenusa(Width, Height)

2.3.4- Llamadas a procedimientos.


Un procedimiento Sub difiere de un procedimiento Function en que al procedimiento Sub no se le puede llamar mediante su nombre en una expresin. La llamada a un procedimiento Sub es una instruccin nica. Adems, un procedimiento Sub no devuelve un valor en su nombre como hace una funcin. Sin embargo, al igual que Function, un procedimiento Sub puede modificar los valores de las variables que se le pasan. Hay dos formas de llamar a un procedimiento Sub: Ambas instrucciones llaman a un Sub denominado MiProc. Call MiProc (PrimerArgumento, SegundoArgumento) MiProc PrimerArgumento, SegundoArgumento Observe que cuando utiliza la sintaxis Call, debe poner los argumentos entre parntesis. Si omite la palabra clave Call, deber tambin omitir los parntesis alrededor de los argumentos.

2.3.5- Llamadas a Funciones.

200

Normalmente se llama a un procedimiento de funcin que se ha escrito de la misma forma en que se llama a una funcin intrnseca de Visual Basic como Abs; es decir, utilizando su nombre en una expresin: Las instrucciones siguientes llamaran a una funcin ' llamada ToDec. Print 10 * Adec X = Adec If Adec = 10 Then [Link] "Fuera del intervalo" X = OtraFuncin(10 * Adec) Tambin es posible llamar a una funcin igual que se llama a un procedimiento Sub. Las instrucciones siguientes llaman a la misma funcin: Call Year(Now) Year Now Cuando llama a una funcin de esta manera, Visual Basic desecha el valor de retorno.

2.3.6- Pasaje de argumentos a los procedimientos y funciones.


Normalmente el cdigo de un procedimiento necesita cierta informacin sobre el estado del programa para realizar su trabajo. Esta informacin consiste en variables que se pasan al procedimiento cuando se le llama. Cuando se pasa una variable a un procedimiento, se llama argumento. Tipos de datos de los argumentos Los argumentos de los procedimientos que escriba tienen el tipo de dato Variant de forma predeterminada. Sin embargo, puede declarar otros tipos de datos para los argumentos. Por ejemplo, la funcin siguiente acepta una cadena y un entero: Function QuComer (DaSemana As String, Hora As Integer) As String ' Devuelve el men del almuerzo basndose en el da y la hora. If DaSemana = "Viernes" then QuComer = "Pescado" Else QuComer = "Pollo" End If

201

If Hora > 4 Then QuComer = "Demasiado tarde" End Function Paso de argumentos por valor Slo se pasa una copia de la variable cuando se pasa un argumento por valor. Si el procedimiento cambia el valor, el cambio afecta slo a la copia y no a la variable propiamente dicha. Utilice la palabra clave ByVal para indicar un argumento pasado por valor. Por ejemplo: Sub Cuentas (ByVal intNumCuenta as Integer) . . ' Ponga aqu sus instrucciones. . End Sub Paso de argumentos por referencia Pasar argumentos por referencia le da al procedimiento acceso al contenido real de la variable en su ubicacin de direccin de memoria. Como resultado, el procedimiento al que se ha pasado el valor de la variable se puede modificar de forma permanente. La forma predeterminada de pasar valores en Visual Basic es por referencia. Si especifica el tipo de dato de un argumento que se pasa por referencia, debe pasar un valor de ese tipo para el argumento. Puede eludirlo si pasa una expresin en vez de un tipo de dato como argumento. Visual Basic evala la expresin y la pasa como el tipo requerido si puede. La forma ms sencilla de convertir una variable en una expresin es ponerla entre parntesis. Por ejemplo, para pasar una variable declarada como entero a un procedimiento que espera una cadena como argumento, debera hacer lo siguiente: Sub ProcedimientoQueLlama () Dim intX As Integer intX = 12 * 3 Foo(intX) End Sub Sub Foo(Bar As String) MsgBox Bar End Sub 'El valor de Bar es la cadena "36".

202

2.4- Estructuras de Control (Repeticin y Decisin). 2.4.1-Do While Loop / Do Loop While.
Utilice el bucle Do para ejecutar un bloque de instrucciones un nmero indefinido de veces. Hay algunas variantes en la instruccin Do...Loop, pero cada una evala una condicin numrica para determinar si contina la ejecucin. Como ocurre con If...Then, la condicin debe ser un valor o una expresin que d como resultado False (cero) o True (distinto de cero). En el ejemplo de Do...Loop siguiente, las instrucciones se ejecutan siempre y cuando condicin sea True: Do While condicin instrucciones Loop Cuando Visual Basic ejecuta este bucle Do, primero evala condicin. Si condicin es False (cero), se salta todas las instrucciones. Si es True (distinto de cero), Visual Basic ejecuta las instrucciones, vuelve a la instruccin Do While y prueba la condicin de nuevo. Por tanto, el bucle se puede ejecutar cualquier nmero de veces, siempre y cuando condicin sea distinta de cero o True. Nunca se ejecutan las instrucciones si condicin es False inicialmente. Por ejemplo, este procedimiento cuenta las veces que se repite una cadena de destino dentro de otra cadena repitiendo el bucle tantas veces como se encuentre la cadena de destino: Function ContarCadenas (cadenalarga, destino) Dim posicin, contador posicin = 1 Do While InStr(posicin, cadenalarga, destino) posicin = InStr(posicin, cadenalarga, destino)

+1

contador = contador + 1 Loop ContarCadenas = contador End Function Si la cadena de destino no est en la otra cadena, InStr devuelve 0 y no se ejecuta el bucle. Otra variante de la instruccin Do...Loop ejecuta las instrucciones primero y prueba condicin despus de cada ejecucin. Esta variacin garantiza al menos una ejecucin de instrucciones:

203

Do instrucciones Loop While condicin Hace el bucle cero o ms veces Do Until condicin instrucciones Loop Hace el bucle al menos una vez Do instrucciones Loop Until condicin

2.4.2- For Next.


Los bucles Do funcionan bien cuando no se sabe cuntas veces se necesitar ejecutar las instrucciones del bucle. Sin embargo, cuando se sabe que se van a ejecutar las instrucciones un nmero determinado de veces, es mejor elegir el bucle ForNext. A diferencia del bucle Do, el bucle For utiliza una variable llamada contador que incrementa o reduce su valor en cada repeticin del bucle. La sintaxis es la siguiente: For contador = iniciar To finalizar [Step incremento] instrucciones Next [contador] Los argumentos contador, iniciar, finalizar e incremento son todos numricos. Nota: El argumento incremento puede ser positivo o negativo. Si incremento es positivo, iniciar debe ser menor o igual que finalizar o no se ejecutarn las instrucciones del bucle. Si incremento es negativo, iniciar debe ser mayor o igual que finalizar para que se ejecute el cuerpo del bucle. Si no se establece Step, el valor predeterminado de incremento es 1. Al ejecutar el bucle For, Visual Basic: 1. Establece contador al mismo valor que iniciar. 2. Comprueba si contador es mayor que finalizar. Si lo es, Visual Basic sale del bucle. (Si incremento es negativo, Visual Basic comprueba si contador es menor que finalizar.) 3. Ejecuta instrucciones. 4. Incrementa contador en 1 o en instrucciones, si se especific. 5. Repite los pasos 2 a 4. Este cdigo imprime los nombres de todas las fuentes de pantalla disponibles: Private Sub Form_Click () Dim I As Integer For i = 0 To [Link]

204

Print [Link](i) Next End Sub En la aplicacin de ejemplo VCR, el procedimiento HighlightButton utiliza un bucle For...Next para pasar por la coleccin de controles del formulario VCR y mostrar el control Shape apropiado: Sub HighlightButton(MyControl As Variant) Dim i As Integer For i = 0 To [Link] - 1 If TypeOf [Link](i) Is Shape Then If [Link](i).Name = MyControl

Then

= True Else

[Link](i).Visible

[Link](i).Visible = False End If End If Next End Sub

2.4.3- If Else End If.


Use la estructura If...Then para ejecutar una o ms instrucciones basadas en una condicin. Puede utilizar la sintaxis de una lnea o un bloque de varias lneas: If condicin Then instruccin If condicin Then instrucciones End If Condicin normalmente es una comparacin, pero puede ser cualquier expresin que d como resultado un valor numrico. Visual Basic interpreta este valor como True o False; un valor numrico cero es False y se considera True cualquier valor numrico distinto de cero. Si condicin

205

es True, Visual Basic ejecuta todas las instrucciones que siguen a la palabra clave Then. Puede utilizar la sintaxis de una lnea o de varias lneas para ejecutar una instruccin basada en una condicin (estos dos ejemplos son equivalentes): If cualquierFecha < Now Then cualquierFecha = Now If cualquierFecha < Now Then cualquierFecha = Now End If Observe que el formato de una nica lnea de If...Then no utiliza la instruccin End If. Si desea ejecutar ms de una lnea de cdigo cuando condicin sea True, debe utilizar la sintaxis de bloque de varias lneas If...Then...End If. If cualquierFecha < Now Then cualquierFecha = Now [Link] = False End If If...Then...Else Utilice un bloque If...Then...Else para definir varios bloques de instrucciones, uno de los cuales se ejecutar: If condicin1 Then [bloque de instrucciones 1] [Else [bloque de instrucciones n]] End If Visual Basic evala primero condicin1. Si es False, Visual Basic ejecuta el bloque de instrucciones correspondientes a Else y despus ejecuta el cdigo que sigue a End If. Por ejemplo, la aplicacin podra realizar distintas acciones dependiendo del control en que se haya hecho clic de una matriz de controles de men: Private Sub mnuCut_Click (Index As Integer) If Index = 0 Then Comando Cortar. CopyActiveControl ClearActiveControl ' ' Desactiva el control Timer.

206

Else PasteActiveControl End If End Sub

' Comando Pegar.

2.4.4- Select - Case


Visual Basic proporciona la estructura Select Case como alternativa a If...Then...Else para ejecutar selectivamente un bloque de instrucciones entre varios bloques de instrucciones. La instruccin Select Case ofrece posibilidades similares a la instruccin If...Then...Else, pero hace que el cdigo sea ms legible cuando hay varias opciones. La estructura Select Case funciona con una nica expresin de prueba que se evala una vez solamente, al principio de la estructura. Visual Basic compara el resultado de esta expresin con los valores de cada Case de la estructura. Si hay una coincidencia, ejecuta el bloque de instrucciones asociado a ese Case: Select Case expresin_prueba [Case lista_expresiones1 [bloque de instrucciones 1]] [Case lista_expresiones2 [bloque de instrucciones 2]] . . .

[Case Else

[bloque de instrucciones n]] End Select Cada lista_expresiones es una lista de uno o ms valores. Si hay ms de un valor en una lista, se separan los valores con comas. Cada bloque de instrucciones contiene cero o ms instrucciones. Si ms de un Case coincide con la expresin de prueba, slo se ejecutar el bloque de instrucciones asociado con la primera coincidencia. Visual Basic ejecuta las instrucciones de la clusula (opcional) Case Else si ningn valor de la lista de expresiones coincide con la expresin de prueba. Por ejemplo, suponga que agrega otro comando al men Edicin en el ejemplo If...Then...Else. Podra agregar otra clusula ElseIf o podra escribir la funcin con Select Case: Private Sub mnuCut_Click (Index As Integer) Select Case Index

207

Case 0 Comando Cortar. CopyActiveControl generales. ClearActiveControl Case 1

'

' Llama a procedimientos

Comando Copiar.

'

CopyActiveControl Case 2 Comando Borrar. ClearActiveControl Case 3 ' '

Comando Pegar.

PasteActiveControl Case Else [Link] ' Muestra el cuadro de

dilogo

Buscar. End Select

End Sub Observe que la estructura Select Case evala una expresin cada vez al principio de la estructura.

3-

Controles

3.1- Controles bsicos


Vamos a ver los siguientes puntos: Introduccin al uso de controles Control TextBox. Control Label Control CommandButton Control OptionButton Realizacon de una pequea aplicacin de ejemplo

Antes de empezar a conocer los controles bsicos veamos cuales son sus caractersticas generales:

208

Propiedades:Todos los controles disponen de una serie de propiedades las cuales podemos cambiar al incluirlos en nuestras aplicaciones. Ejemplos de propiedades son el color, el tipo de letra, el nombre, el texto, etc... Metodos: Son procedimientos asociados a los controles, es decir, rutinas ya establecidas que podemos invocar desde nuestras aplicaciones para que se realice alguna operacin sobre el control. Por ejemplo el control ListView ( la lista de archivos que aparece en el explorador de windows) dispone del mtodo order que te ordena los datos aparecidos en la lista. Eventos: Son acciones que pueden ser motivadas por el propio usuario o por mismo sistema operativo. Ejemplos pueden ser el movimiento del ratn o hacer click sobre su botn. En Visual Basic digamos que se utiliza la programacin orientada a eventos, lo cual es una de las diferencias ms importantes respecto a la programacin lineal de MS DOS. No necesitamos detectar cuando se ha producido un evento determinado, Windows lo detecta automticamente. Los eventos ya estan definidos, son bastantes y cada control cuenta con los suyos propios, aunque son muy parecidos. Lo nico que tendremos que hacer es asociar el cdigo necesario al evento que necesitemos tratar.

TextBox

Mediante este control podremos realizar tanto la entrada como la salida de datos en nuestras aplicaciones. No hace falta que indiquemos las coordenadas de la situacin del formulario en pantalla, simplemente tendremos que marcar sobre el control de la caja de herramientas y dibujarlo con el tamao que queramos en nuestro formulario. PROPIEDADES Las propiedades de las que dispone el control son las siguientes:(para obtener el cuadro de propiedades, seleccionar el control y pulsar F4 o pulsar con el boton derecho para obtener el men contextual y marcar Propierties) Text: Aqu indicamos el texto que aparecer en el control. Podemos asignarle cualquier texto en tiempo de diseo o ejecucin. Tambin podemos tomar el texto que haya introducido el usuario para tratarlo durante la ejecucin. Name: Esta propiedad la tienen todos los controles, el nombre que viene por defecto en este caso Text1 y es el nombre con el que se conocer el control cuando lo utilicemos en el cdigo. En un mismo formulario no puede haber 2 controles con el mismo nombre. Conviene poner un nombre que represente la funcin que tiene el control en la aplicacin para que el cdigo quede ms claro. Ejemplo, si en el textbox vamos a introducir la direccin de una persona podemos asignarle a esta propiedad el valor Direccin. MultiLine: Permite que introduzcamos varias lineas de texto en el control en lugar de slo una. Alignment: Alineacin que tendr el texto dentro del control: izquierda, centro o derecha. Para que funcione la propiedad MultiLine debe estar con el valor true. Locked: Si esta con valor true bloquea el control, es decir, el usuario no puede introducir ni modificar el texto que contenga. Nos puede servir para utilizar el control como salida de datos sin que el usuario pueda modificarlos por error.

209

Otras propiedades que son comunes a la mayoria de los controles: Backcolor: color de fondo. Forecolor: color de letra. Font: tipo y tamao de letra. METODOS Recordemos que por mtodos se entienten los procedimientos o funciones asociados a un control, los cuales nos permiten realizar ciertas operaciones tiles sobre dicho control: Ej. ordenar sus elementos, buscar un dato, etc.. Pues bien, los controles bsicos que vamos a ver en este captulo nicamente contienen mtodos avanzados que no vamos a analizar por ahora, ya que son mtodos que no se suelen utilizar. Ms adelante cuando veamos otros tipos de controles estudiaremos cuales son los mtodos que nos podrn servir. Si alguien est interesado en conocer todas las caractersticas de los controles puede hacerlo mirando en la ayuda que proporciona VB, haciendo click sobre cualquier control de la caja de herramientas y pulsando a continuacin F1 obtendr ayuda referente a ese control donde aparecern todas sus propiedades, metodos y eventos. EVENTOS Los eventos son acciones que se pueden realizar en cualquier control: click, doble click, movimiento del ratn. A estos eventos se les puede asociar cdigo para que se ejecute al producir el evento. MouseMove: al mover el raton por encima del control. Mousedown: al pulsar cualquier boton del raton Change: al cambiar el contenido del control Click: al hacer click con el botn izquierdo del ratn sobre el control Doubleclick: al hacer doble click con el con el botn izquierdo del ratn sobre el control Getfocus: este evento se activa cuando el control recibe el enfoque, es decir, cuando se activa el control en tiempo de ejecucin para introducir datos en l o realizar alguna operacin. Lostfocus: Es el contrario del anterior evento, se activa cuando el control pierde el enfoque, es decir, se pasa a otro control para seguir introduciendo datos. EJEMPLO Vamos a probar el uso del control TextBox mediante un pequeo ejemplo en el que teniendo un nico control de este tipo en un formulario, lo programaremos de forma que al pasar el ratn sobre el control (evento mousemove) aparecer en el formulario el texto que contenga.

210

Observamos que al situar el control en el formulario aparece por defecto el texto Text1. Para que no aparezca ese texto al ejecutar la aplicacin, debemos cambiar la propiedad Text pulsando F4 y colocar el texto que queramos o no colocar nada. Lo que queremos hacer es que cada vez que movamos el raton por el control aparezca su contenido en el formulario. Entonces lo que habr que hacer abrir la ventana de cdigo, seleccionando el control y pulsando F7, o con el botn derecho del ratn y la opcin View code del men contextual. Este proceso nos llevar al cuadro de la imagen siguiente.

Lo que tendremos que hacer es seleccionar el evento que necesitemos de la seccin Proc, en nuestro caso mousemove y a continuacin teclear el codigo correspondiente: La instruccin print visualiza un texto en el formulario y si le ponemos [Link] le decimos que nos muestre la propiedad Text del control Text1 que ese ser el nombre que tendr el control por defecto si no lo hemos cambiado en la propiedad name. Al ejecutar esta pequea aplicacin pulsando F5 observaremos como aparece en el formulario lo que hayamos tecleado en el control cada vez que movemos el raton sobre el Textbox. Podemos modificar el programa para que responda a cualquier otro evento sin ms que seleccionarlo en la seccin Proc e introduciendo el codigo que sea necesario. Label

Este control es tambin uno de los ms utilizados, aunque su utilidad queda restringida a la visualizacin de datos en el mismo, no permitiendo la introduccin de datos por parte del usuario. La forma de utilizarlo es similar a la del control anterior, dibujar el control en el formulario con el tamao que queramos y asignarle un texto en tiempo de diseo o de ejecucin esta vez sin utilizar la propiedad text puesto que no la incorpora, sino utilizando la propiedad caption.

211

Este control sirve para mostrar mensajes en nuestro formulario que orienten al usuario sobre la utilidad de los dems controles que tengamos en la aplicacin o para indicarnos acciones que podemos realizar. En el ejemplo anterior donde apareca un textbox en el formulario, hubiera quedado mejor con un mensaje aclaratorio contenido en un control label:

PROPIEDADES Caption: Es el texto que contendr el control. Alignment: Alineacin del texto contenido en el control, no necesita que est activada ninguna otra propiedad. BorderStyle: Si queremos que aparezca un borde alrededor del control activaremos esta propiedad. Para este control no se suelen utilizar los eventos ya que su contenido suele cambiar poco a lo largo de la ejecucin de la aplicacin. De todas formas los eventos son casi los mismos del control textbox excepto que no dispone de los eventos GetFocus y LostFocus ya que a este control no se le puede dar el enfoque. En la parte final de este capitulo veremos un ejemplo donde se muestra el funcionamiento de todos los controles que vamos a ir [Link] ahora a ver si conseguis que ahora el mensaje no aparezca en el formulario sino en un segundo label situado en el formulario, dejando un control label que muestre el mensaje aclaratorio que hemos visto antes. CommandButton

Este control es el tpico botn que aparece en todas las aplicaciones y que al hacer click sobre l nos permite realizar alguna operacin concreta, normalmente Aceptar o Cancelar. Aunque segn el cdigo que le asociemos podremos realizar las operaciones que queramos. En el ejemplo anterior podemos aadir un control de este tipo para salir de la aplicacin sin tener pulsar sobre la equis de la esquina superior derecha.

Pero slo con introducir un control de este tipo con el texto salir que se introduce a traves de la propiedad caption no basta. Habr que asociarle un cdigo que nos permita salir de la aplicacin

212

en el evento adecuado. Y el evento por excelencia de este control es click. As pues accederemos al cdigo del control y la sentencia nos permitir salir de la aplicacin es End, simplemente tecleamos esa palabra en el evento click y comprobar que realmente finalizaremos nuestra aplicacin al pulsar sobre dicho botn. PROPIEDADES Caption: Aqui pondremos el letrero que queremos que apaezca en el botn: aceptar, cancelar, salir, etc... Enabled: Esta es una nueva propiedad, cuando su valor es true el botn funciona normalmente, cuando su valor es false el boton se encuentra desactivado, no responde a los eventos producidos sobre l y el texto aparece en un gris claro advirtiendonos de su estado. Podemos utilizar esta propiedad para activar o desactivar un boton dependiendo del estado de otros controles. Por ejemplo, en un boton Aceptar, no activarlo hasta que se haya introducido una cantidad en un control textbox, ya que ese botn nos calcular el IVA de la cantidad. EVENTOS Click: Es el evento tipico de este control y el que ms se utiliza. MouseMove: Como sabemos detecta el movimiento del raton sobre el control. Puede servir para que aparezca un mensaje en un control Label que nos aporte informacin sobre la utilidad del control ampliando el texto que hayamos colocado como caption del commandbutton. OptionButton

Este control nos permite elegir una opcin entre varias de las que se nos plantean. Cada opcin ser un control optionbutton diferente. Facilita la introduccin de datos por parte del usuario:

De todas las opciones que se nos ofrece, en este caso los 4 colores, slo podremos activar una. Si activamos cualquier otra opcin, se desactivar automticamente la ltima que tenamos activada.

213

El marco que est alrededor de los 4 controles optionbutton se trata del control Frame , es opcional, aunque es conviente colocarlo siempre que hagamos uso de las opciones. No slo por motivos de presentacin sino porque de esta manera podremos establecer grupos de controles optionbutton independientes en los que en cada grupo slo pueda haber una opcion activada a la vez. Tambin, al mover el marco se movern los controles incluidos en l facilitndonos las modificaciones. Para que los controles Optionbutton queden englobados dentro de un control Frame, primero tendremos que colocar el control Frame en el formulario con el tamao adecuado y despues ir colocando los controles Optionbutton dentro del Frame. Del control Frame la nica propiedad que nos interesar es caption, que es el texto que aparecer en el encabezado, en el ejemplo anterior: colores. PROPIEDADES DE OPTIONBUTTON Caption: El texto que aparecer al lado del control: Rojo, verde, etc... Value: Es el valor que tendr el control: True si se encuentra activado y False si no lo est. Para comprobar que opcion ha activado el usuario comprobaremos el estado de esta propiedad. Alignment: Alineacin del texto respecto al control: Left Justify: el control aparece a la izquierda del texto. Es el ejemplo [Link] Justify: el control aparece a la derecha del texto. Los eventos del control son los mismos que en anteriores controles, aunque no se suele asociar cdigo a los eventos de este tipo de controles, sino nicamente conocer el valor que tienen: true o false.

3.1.1- APLICACION DE EJEMPLO


Para practicar con los controles que hemos visto vamos a realizar una pequea aplicacin que consistir en realizar con 2 nmeros que introduzcamos, una operacin que seleccionemos y mostrar el resultado. El formulario donde estarn todos los controles es el siguiente:

La propiedad Caption de cada uno de los controles es la que se muestra en el formulario.

214

He modificado la propiedad Name de cada control para que al utilizarlos desde el codigo sepamos cual es el control con el que trabajamos: Los controles TextBox tienen los nombres: Num1, Num2 y Resul. Los controles Optionbutton tienen cada uno de ellos el mismo nombre que su caption Los controles CommandButton tienen los nombres: Calcular, Limpiar y Salir. A los controles Label y al Frame no have falta cambiarles el nombre.

Lo que habr que hacer ahora es asociar codigo a cada uno de los botones que es de donde se van a realizar las operaciones: Para el botn Calcular que es el que nos mostrar el resultado segn la operacin seleccionada, he utilizado la instruccin If Then Else que vimos en el captulo anterior:

El botn Limpiar Datos nos va a servir para borrar de una forma rpida los datos introducidos por el usuario y el resultado preparando los controles para introducir nuevos datos. El cdigo que tendremos que introducir es muy simple:

215

El botn Salir nicamente contendr la sentencia End.

4 -Formularios.
Los formularios tienen sus propios eventos, propiedades y mtodos con los que se puede controlar su apariencia y comportamiento. El primer paso para disear un formulario consiste en establecer sus propiedades. Puede establecer las propiedades de un formulario en tiempo de diseo en la ventana Propiedades o en tiempo de ejecucin, escribiendo cdigo. Nota En tiempo de diseo, que es cualquier momento mientras est desarrollando una aplicacin en el entorno de Visual Basic, se trabaja con formularios y controles, se establecen propiedades y se escribe cdigo para los eventos. Tiempo de ejecucin es cualquier momento mientras se ejecuta realmente la aplicacin y se interacta con ella como lo hara un usuario.

4.1- Estableciendo las Propiedades ms importantes de los formularios.


Muchas propiedades de un formulario afectan a su apariencia fsica. La propiedad Caption determina el texto que muestra la barra de ttulo del formulario y la propiedad Icon establece el icono que aparece cuando se minimiza un formulario. Las propiedades MaxButton y MinButton determinan si el formulario se puede maximizar o minimizar. Cambiando la propiedad BorderStyle puede controlar el comportamiento de cambio de tamao del formulario. Las propiedades Height y Width determinan el tamao inicial de un formulario, mientras que las propiedades Left y Top determinan la ubicacin del formulario en relacin con la esquina superior izquierda de la pantalla. Con la propiedad WindowState puede establecer si el formulario se inicia en estado maximizado, minimizado o normal. La propiedad Name establece el nombre con el que har referencia al formulario en el cdigo. De forma predeterminada, cuando se agrega un formulario por primera vez a un proyecto, su nombre es Form1, Form2, etc. Es conveniente establecer la propiedad Name a algo ms significativo, como frmEntry para un formulario de entrada de pedidos. La mejor manera de familiarizarse con las numerosas propiedades de los formularios es experimentar. Cambie algunas propiedades de un formulario en la ventana Propiedades y ejecute la aplicacin para ver su efecto. Puede aprender ms sobre cada propiedad si la selecciona y presiona F1 para ver Ayuda contextual.

4.2- Eventos y Mtodos de los formularios.


Como objetos que son, los formularios pueden ejecutar mtodos y responder a eventos. El evento Resize de un formulario se desencadena siempre que se cambia el tamao de un formulario, ya sea por una accin del usuario o a travs del cdigo. Esto permite realizar acciones como mover o cambiar el tamao de los controles de un formulario cuando han cambiado sus dimensiones. El evento Activate se produce siempre que un formulario se convierte en el formulario activo; el evento Deactivate se produce cuando otro formulario u otra aplicacin se convierte en activo. Estos eventos son adecuados para iniciar o finalizar acciones del formulario. Por ejemplo, en el evento Activate podra escribir cdigo para resaltar el texto de un determinado cuadro de texto; con el evento Deactivate podra guardar los cambios efectuados en un archivo o en una base de datos.

216

Para hacer visible un formulario se invoca el mtodo Show: [Link] Para descargar un formulario (cerrarlo), se invoca al mtodo Unload: [Link] Unload Me Me significa el Formulario activo.

Para ocultar un formulario (pero dejarlo activo en memoria) se invoca al mtodo Hide: [Link] Invocar el mtodo Show tiene el mismo efecto que establecer a True la propiedad Visible del formulario. Muchos mtodos de un formulario implican texto o grficos. Los mtodos Print, Line, Circle y Refresh son tiles para imprimir o dibujar directamente en la superficie de un formulario.

4.3- Establecer el formulario de arranque de la aplicacin.


De forma predeterminada, el primer formulario de la aplicacin es el formulario inicial. Cuando la aplicacin inicia la ejecucin, se presenta este formulario (el primer cdigo que se ejecuta es el del evento Form_Initialize de dicho formulario). Si quiere presentar un formulario diferente cuando se inicie la aplicacin, debe cambiar el formulario inicial. Para cambiar el formulario inicial 1. 2. En el men Proyecto, elija Propiedades del proyecto. Elija la ficha General.

3. En el cuadro de lista Objeto inicial, seleccione el formulario que desee que sea el nuevo formulario inicial. 4. Elija Aceptar.

Inicio sin formulario inicial Algunas veces puede desear que la aplicacin se inicie sin cargar ningn formulario. Por ejemplo, puede que desee ejecutar cdigo que cargue un archivo de datos y despus presentar uno de entre varios formularios, segn el contenido de dicho archivo. Puede hacerlo creando un procedimiento Sub llamado Main en un mdulo estndar, como en el siguiente ejemplo: Sub Main() Dim intStatus As Integer ' Llamar a un procedimiento de funcin para comprobar el estado

217

' del usuario. intStatus = GetUserStatus ' Mostrar un formulario inicial distinto segn el estado. If intStatus = 1 Then [Link] Else [Link] End If Este procedimiento tiene que ser un procedimiento Sub y no puede estar en un mdulo de formulario. Para establecer el procedimiento Sub Main como objeto inicial, en el men Proyecto elija Propiedades del proyecto, seleccione la ficha General y seleccione Sub Main en el cuadro Objeto inicial.

5 -Combo Box (lista combo)


Un control ComboBox combina las caractersticas de un control TextBox y un control ListBox; los usuarios pueden introducir informacin en la parte del cuadro de texto o seleccionar un elemento en la parte de cuadro de lista del control. Para agregar o eliminar elementos en un control ComboBox, use el mtodo AddItem o RemoveItem. Establezca las propiedades List, ListCount y ListIndex para permitir a un usuario tener acceso a los elementos de un control ComboBox. Como alternativa, puede agregar elementos a la lista mediante la propiedad List en tiempo de diseo. Nota Un evento Scroll ocurrir en un control ComboBox slo cuando se desplace el contenido de la parte desplegable del ComboBox, no cada vez que cambie el contenido del ComboBox. Por ejemplo, si la parte desplegable de un ComboBox contiene cinco elementos y el elemento superior est resaltado, no ocurrir un evento Scroll hasta que presione seis veces la flecha hacia abajo (o una vez la tecla AV PG). Despus de eso, ocurrir un evento Scroll por cada pulsacin de la tecla de flecha hacia abajo. Sin embargo, si despus presiona la tecla de flecha hacia arriba, no ocurrir un evento Scroll hasta que presione seis veces la tecla de flecha hacia arriba (o una vez la tecla RE PG). Despus de eso, cada vez que presione la tecla de flecha hacia arriba se producir un evento Scroll. Eventos: Evento Change Evento Click Evento DblClick Evento DragDrop Evento LostFocus Evento OLECompleteDrag Evento OLEDragDrop Evento OLEDragOver

218

Evento DragOver Evento DropDown Evento GotFocus Eventos KeyDown y KeyUp Evento KeyPress Mtodos: Mtodo AddItem

Evento OLEGiveFeedback Evento OLESetData Evento OLEStartDrag Evento Scroll

Mtodo Refresh Mtodo RemoveItem Mtodo SetFocus Mtodo ShowWhatsThis Mtodo ZOrder

Mtodo Clear (Clipboard, ComboBox, ListBox) Mtodo Drag Mtodo Move Mtodo OLEDrag Propiedades: Propiedad Appearance Propiedades BackColor y ForeColor Propiedad Container Propiedad DataChanged Propiedad DataField Propiedad DragIcon Propiedad DragMode Propiedad Enabled Propiedad Font

Propiedad ListIndex Propiedad Locked Propiedad MouseIcon Propiedad MousePointer Propiedad Name Propiedad NewIndex Propiedad OLEDragMode Propiedad OLEDropMode Propiedad Parent

Propiedades FontBold, FontItalic, FontStrikethru y FontUnderline Propiedad FontName ActiveX) Propiedad FontSize Propiedades Height y Width Propiedades SelLength, SelStart y SelText (Controles

Propiedad Sorted Propiedad Style

219

Propiedad HelpContextID Propiedad hWnd Propiedad Index (Control Array) Propiedad IntegralHeight Propiedad ItemData Propiedades Left y Top Propiedad List Propiedad ListCount

Propiedad TabIndex Propiedad TabStop Propiedad Tag Propiedad Text Propiedad ToolTipText Propiedad TopIndex Propiedad Visible Propiedad WhatsThisHelpID

Propiedades SelLength, SelStart y SelText

6- List Box (lista).


Un control ListBox muestra una lista de elementos entre los cuales el usuario puede seleccionar uno o ms. Si el nmero de elementos supera el nmero que puede mostrarse, se agregar automticamente una barra de desplazamiento al control ListBox. Si no se selecciona ningn elemento, el valor de la propiedad ListIndex ser -1. El primer elemento de la lista es ListIndex 0 y el valor de la propiedad ListCount siempre es uno ms que el mayor valor de ListIndex. Para agregar o eliminar elementos de un control ListBox, use el mtodo AddItem o RemoveItem. Establezca las propiedades List, ListCount y ListIndex para permitir que un usuario tenga acceso a elementos del ListBox. Tambin puede agregar elementos a la lista mediante la propiedad List en tiempo de diseo. Eventos Evento Click Evento DblClick Evento DragDrop Evento DragOver Evento GotFocus Evento ItemCheck Eventos KeyDown y KeyUp Evento KeyPress Eventos MouseDown y MouseUp Evento MouseMove Evento OLECompleteDrag Evento OLEDragDrop Evento OLEDragOver Evento OLEGiveFeedback Evento OLESetData Evento OLEStartDrag

220

Evento LostFocus Mtodos Mtodo AddItem

Evento Scroll

Mtodo Refresh Mtodo RemoveItem

Mtodo Clear (Clipboard, ComboBox, ListBox) Mtodo Drag Mtodo Move Mtodo OLEDrag Propiedades Propiedad Appearance Propiedades BackColor y ForeColor Propiedad Columns (ListBox) Propiedad Container Propiedad DataChanged Propiedad DataField Propiedad DataSource Propiedad DragIcon Propiedad DragMode Propiedad Enabled Propiedad Font

Mtodo SetFocus Mtodo ShowWhatsThis Mtodo ZOrder

Propiedad MousePointer Propiedad MultiSelect Propiedad Name Propiedad NewIndex Propiedad OLEDragMode Propiedad OLEDropMode Propiedad Parent Propiedad SelCount Propiedad Selected Propiedad Sorted Propiedad Style

Propiedades FontBold, FontItalic, FontStrikethru y FontUnderline Propiedad FontName Propiedad FontSize Propiedades Height y Width Propiedad HelpContextID Propiedad hWnd Propiedad Index (Control Array) Propiedad TabStop Propiedad Tag Propiedad Text Propiedad ToolTipText Propiedad TopIndex Propiedad Visible

221

Propiedad ItemData Propiedades Left y Top Propiedad List Propiedad ListIndex

Propiedad WhatsThisHelpID Propiedad TabIndex Propiedad ListCount Propiedad MouseIcon

7- Timer (cronmetro)
Un control Timer puede ejecutar cdigo a intervalos peridicos produciendo un evento Timer. El control Timer, invisible para el usuario, resulta til para el procesamiento de fondo. No puede establecer la propiedad Enabled de un Timer para una seleccin mltiple de controles que no sean controles Timer. No existe ningn lmite prctico en cuanto al nmero de controles Timer activos que puede tener en Visual Basic 5.0 ejecutndose en Windows 95 o en Windows NT. Eventos: Evento Timer Propiedades: Propiedad Enabled Propiedad Index (Control Array) Propiedad Interval Propiedades Left y Top Propiedad Name Propiedad Parent Propiedad Tag

8- Shape (figura).
Shape es un control grfico que se muestra como un rectngulo, un cuadrado, una elipse, un crculo, un rectngulo redondeado o un cuadrado redondeado. Utilice controles Shape en tiempo de diseo en lugar de o adems de invocar los mtodos Circle y Line en tiempo de ejecucin. Puede dibujar un control Shape en un contenedor, pero no puede actuar como contenedor. El efecto de establecer la propiedad BorderStyle depende del valor de la propiedad BorderWidth. Si BorderWidth no es 1 y BorderStyle no es 0 6, BorderStyle se establece a 1. Mtodos: Mtodo Move Mtodo Refresh Mtodo ZOrder

222

Propiedades: Propiedades BackColor y ForeColor Propiedad BackStyle Propiedad BorderColor Propiedad BorderStyle Propiedad BorderWidth Propiedad Container Propiedad DrawMode Propiedad FillColor Propiedad FillStyle Propiedades Height y Width Propiedad Index (Control Array) Propiedades Left y Top Propiedad Name Propiedad Parent Propiedad Shape Propiedad Tag Propiedad Visible

9- Line (lnea).
Line es un control grfico que se muestra como una lnea horizontal, vertical o diagonal. Puede utilizar un control Line en tiempo de diseo para dibujar lneas en formularios. En tiempo de ejecucin puede utilizar un control Line en lugar del mtodo Line, o adems de l. Las lneas dibujadas con el control Line permanecen en el formulario aunque la propiedad AutoRedraw sea False. Los controles Line pueden mostrarse en formularios, en cuadros de imagen y en marcos. No puede utilizar el mtodo Move para mover un control Line en tiempo de ejecucin, pero s se puede mover o cambiar de tamao alterando sus propiedades X1, X2, Y1 e Y2. El efecto de establecer la propiedad BorderStyle depende del valor de la propiedad BorderWidth. Si BorderWidth no es 1 y BorderStyle no es 0 6, BorderStyle se establecer a 1. Mtodos: Mtodo Refresh Mtodo ZOrder Propiedades: Propiedad BorderColor Propiedad BorderStyle Propiedad BorderWidth Propiedad Container Propiedad DrawMode Propiedad Name Propiedad Parent Propiedad Tag Propiedad Visible Propiedades X1, Y1, X2 y Y2

223

Propiedad Index (Control Array)

10- Image (imagen)


Utilice el control Image para mostrar un grfico. Un control Image puede mostrar un grfico desde un mapa de bits, un icono o un metarchivo, as como un metarchivo mejorado, un archivo JPEG o archivos GIF. El control Image utiliza menos recursos del sistema y actualiza con ms rapidez que un control PictureBox, pero slo admite un subconjunto de las propiedades, los eventos y los mtodos de PictureBox. Use la propiedad Stretch para determinar si el grfico se escala para ajustarse al control o viceversa. Aunque puede colocar un control Image dentro de un contenedor, un control Image no puede actuar como contenedor. Eventos: Evento Click Evento DblClick Evento DragDrop Evento DragOver Eventos MouseDown y MouseUp Evento MouseMove Mtodos: Mtodo Drag Mtodo Move Mtodo OLEDrag Propiedades: Propiedad Appearance Propiedad BorderStyle Propiedad Container Propiedad DataChanged Propiedad DataField Propiedad DataSource Propiedad DragIcon Propiedad MouseIcon Propiedad MousePointer Propiedad Name Propiedad OLEDragMode Propiedad OLEDropMode Propiedad Parent Propiedad Picture Mtodo Refresh Mtodo ShowWhatsThis Mtodo ZOrder Evento OLECompleteDrag Evento OLEDragDrop Evento OLEDragOver Evento OLEGiveFeedback Evento OLESetData Evento OLEStartDrag

224

Propiedad DragMode Propiedad Enabled Propiedades Height y Width Propiedad Index (Control Array) Propiedades Left y Top

Propiedad Stretch Propiedad Tag Propiedad ToolTipText Propiedad Visible Propiedad WhatsThisHelpID

11- Data (acceso a bases de datos)


Proporciona acceso a datos almacenados en bases de datos mediante uno de los tres tipos de objetos Recordset. El control Data le permite desplazarse de un registro a otro, as como presentar y manipular datos de los registros en controles enlazados. Sin un control Data los controles enlazados a datos (vinculados) de un formulario no pueden tener acceso a los datos automticamente. Puede realizar la mayora de las operaciones de acceso a datos utilizando el control Data sin escribir cdigo. Los controles enlazados a datos vinculados a un control Data presentan automticamente los datos de uno o varios campos del registro actual o, en algunos casos, de un conjunto de registros situado a ambos lados del registro actual. El control Data realiza todas sus operaciones sobre el registro actual. Si el control Data recibe instrucciones para desplazarse a un registro diferente, todos los controles enlazados pasan automticamente los posibles cambios al control Data para que los guarde en la base de datos. Despus, el control Data se desplaza al registro solicitado y pasa los datos del registro actual a los controles enlazados, en los que se presentan. El control Data administra automticamente una serie de contingencias entre las que se incluyen los conjuntos de registros vacos, la insercin de nuevos registros, la modificacin y actualizacin de registros existentes, y la administracin de ciertos tipos de errores. Sin embargo, en aplicaciones ms sofisticadas es necesario interceptar algunas condiciones de error que el control Data no puede administrar. Por ejemplo, si el motor de base de datos Microsoft Jet tiene un problema al tener acceso al archivo de base de datos, no tiene el permiso adecuado o no puede ejecutar la consulta, se producir un error interceptable. Si el error se produce antes de que se inicien los procedimientos de la aplicacin o se trata de errores internos, se desencadenar el evento Error.

12- Controles enlazados


Los controles DBList, DBCombo, DBGrid y MSFlexGrid son capaces de administrar conjuntos de registros cuando estn enlazados a un control Data. Todos estos controles permiten presentar o manipular varios registros a la vez. Los controles incorporados Picture, Label, TextBox, CheckBox, Image, OLE, ListBox y ComboBox tambin son controles enlazados a datos y se pueden enlazar a un nico campo de un Recordset administrado por un control Data. En las ediciones Profesional y Empresarial se encuentran disponibles otros controles enlazados a datos como MaskedEdit y RichTextBox; otros proveedores tambin ofrecen controles adicionales.

12.1 Funcionamiento

225

Una vez iniciada la aplicacin, Visual Basic utiliza las propiedades del control Data para abrir la base de datos seleccionada, crear un objeto Database y crear un objeto Recordset. Las propiedades Database y Recordset del control Data hacen referencia a los objetos Database y Recordset recin creados, que se pueden manipular de forma independiente del control Data, con o sin controles enlazados. El control Data se inicializa antes del evento Form_Load inicial del formulario en el que se encuentra. Si se producen errores durante esta fase de inicializacin, se produce un error no interceptable. Cuando Visual Basic utiliza el motor de base de datos Jet para crear un Recordset, no se pueden producir otras operaciones o eventos de Visual Basic hasta que se termine la operacin. Sin embargo, otras aplicaciones basadas en Windows pueden seguir en ejecucin mientras se est creando el Recordset. Si el usuario presiona CTRL+INTER mientras el motor Jet est generando un Recordset, la operacin termina, se produce un error interceptable y la propiedad Recordset del control Data se establece a Nothing. En tiempo de diseo, la segunda vez que se presiona CTRL+INTER hace que Visual Basic presente la ventana Depuracin. Puede manipular el control Data con el mouse (ratn), desplazndose de un registro a otro, o al principio o al final del Recordset. Las propiedades EOFAction y BOFAction determinan lo que ocurre cuando el usuario se desplaza al principio o al final de un Recordset con el mouse. No puede establecer el enfoque en un control Data.

12.2 Validacin
El evento Validate y la propiedad DataChanged se utilizan para realizar comprobaciones de ltima hora sobre los registros que se van a escribir en la base de datos.

12.3 Objetos de acceso a datos


En los procedimientos puede utilizar los objetos de acceso a datos Database y Recordset creados por el control Data. Cada objeto Database y Recordset tiene sus propias propiedades y mtodos, y puede escribir procedimientos que utilicen dichas propiedades y mtodos para manipular sus datos. Por ejemplo, el mtodo MoveNext de un objeto Recordset desplaza el registro actual al siguiente registro dentro del Recordset. Para invocar este mtodo, podra utilizar el cdigo siguiente: [Link] El control Data puede tener acceso a cualquiera de los tres tipos de objetos Recordset del motor Jet versin 3.0. Si no selecciona el tipo de conjunto de registros, se crea un Recordset de tipo dynaset. En muchos casos, el tipo predeterminado y la configuracin del objeto Recordset creado son muy ineficientes. Es decir, puede que no necesite un cursor actualizable totalmente desplazable de conjunto de claves para tener acceso a los datos. Por ejemplo, un Recordset de tipo snapshot, de slo lectura y unidireccional se creara con ms rapidez que el cursor predeterminado. Asegrese de elegir el tipo ms eficiente, as como las propiedades Exclusive, Options y ReadOnly adecuadas a su situacin. Para seleccionar un tipo de Recordset especfico, establezca la propiedad RecordsetType del control Data a:

226

RecordsetType Table Dynaset Snapshot

Valor 0 1 2

Constante vbRSTypeTable vbRSTypeDynaset vbRSTypeSnapshot (Predeterminado)

12.4 Ediciones Profesional y Empresarial


En lo que concierne al acceso a datos, la principal diferencia entre las ediciones de Aprendizaje, Profesional y Empresarial de Visual Basic es la capacidad de crear nuevos objetos de acceso a datos. En la Edicin estndar no puede declarar (con la palabra clave Dim) variables como objetos de acceso a datos dentro del cdigo. Esto significa que slo el control Data puede crear objetos Database y Recordset. En las ediciones Profesional y Empresarial de Visual Basic versin 5.0 puede crear un objeto Recordset y asignarlo a la propiedad Recordset de un control Data. Cualquier control enlazado que est conectado al control Data permitir manipular los registros del Recordset que ha creado. Asegrese de que las propiedades DataField de los controles enlazados estn establecidas a nombres de campo vlidos dentro del nuevo Recordset.

12.5 Consultas almacenadas


Otra opcin importante al utilizar el control Data es la posibilidad de ejecutar consultas almacenadas. Si antes ha creado un objeto QueryDef, el control Data puede ejecutarlo y crear un Recordset mediante las propiedades SQL, Connect y otras del objeto QueryDef. Para ejecutar un QueryDef, establezca la propiedad RecordSource del control Data al nombre del QueryDef y utilice el mtodo Refresh. Si el QueryDef almacenado contiene parmetros, tiene que crear el Recordset y pasarlo al control Data.

12.6 Tratamiento de BOF/EOF


El control Data tambin puede administrar lo que ocurre cuando se encuentre con un Recordset sin registros. Modificando la propiedad EOFAction puede programar el control Data para que pase al modo AddNew de forma automtica. Puede programar el control Data para que se ajuste automticamente a la parte superior o inferior del formulario primario utilizando la propiedad Align. En cualquiera de los casos, el control Data cambia de tamao horizontalmente para llenar todo el ancho de su formulario primario, siempre que ste cambie de tamao. Eventos: Evento DragDrop Evento DragOver Evento Error Evento OLEDragOver Evento OLEGiveFeedback Evento OLESetData

227

Eventos MouseDown, MouseUp Evento MouseMove Evento OLECompleteDrag Evento OLEDragDrop Mtodos Mtodo Drag Mtodo Move Mtodo OLEDrag Mtodo Refresh Propiedades Propiedad Align Propiedad Appearance Propiedades BackColor, ForeColor Propiedad BOFAction, EOFAction Propiedad Caption Propiedad Connect Propiedad Database Propiedad DatabaseName Propiedad DefaultCursorType Propiedad DefaultType Propiedad DragIcon Propiedad DragMode Propiedad EditMode Propiedad Enabled Propiedad Exclusive Propiedad Font

Evento OLEStartDrag Evento Reposition Evento Resize Evento Validate

Mtodo ShowWhatsThis Mtodo UpdateControls Mtodo UpdateRecord Mtodo ZOrder

Propiedad FontSize Propiedades Height, Width Propiedad Index (Matriz de controles) Propiedades Left, Top Propiedad MouseIcon Propiedad MousePointer Propiedad Name Propiedad OLEDropMode Propiedad Options Propiedad Parent Propiedad ReadOnly (Aceso de datos) Propiedad Recordset Propiedad RecordsetType Propiedad RecordSource Propiedad Tag Propiedad ToolTipText

228

Propiedades FontBold, FontItalic, FontStrikethru, FontUnderline Propiedad FontName Propiedad Visible Propiedad WhatsThisHelpID

229

Curso de Visual Basic II


13 -Eventos ms importantes de los controles estndares. 13.1-Change
Aplicable a: Control ComboBox, Controles HScrollBar y VScrollBar, Control Label, Control PictureBox, Control TextBox Indica que el contenido de un control ha cambiado. Cmo y cundo ha ocurrido este evento vara segn el control: ComboBox: cambia el texto de la parte de cuadro de texto del control. Ocurre slo si la propiedad Style est establecida a 0 (Dropdown Combo) o 1 (Simple Combo) y el usuario cambia el texto o usted cambia la configuracin de la propiedad Text mediante cdigo. DirListBox: cambia el directorio seleccionado. Ocurre cuando el usuario hace doble clic en un nuevo directorio o cuando usted cambia la configuracin de la propiedad Path mediante cdigo. DriveListBox: cambia la unidad seleccionada. Ocurre cuando el usuario selecciona una nueva unidad o cuando usted cambia la configuracin de la propiedad Drive mediante cdigo. HScrollBar y VScrollBar (barras de desplazamiento horizontal y vertical): mueven la parte de cuadro de desplazamiento de la barra de desplazamiento. Ocurre cuando el usuario desplaza o cuando usted cambia la configuracin de la propiedad Value mediante cdigo. Label: cambia el contenido del control Label. Ocurre cuando un vnculo DDE actualiza los datos o cuando usted cambia la configuracin de la propiedad Caption mediante cdigo. PictureBox: cambia el contenido del control PictureBox. Ocurre cuando un vnculo DDE actualiza los datos o cuando usted cambia la configuracin de la propiedad Picture mediante cdigo. TextBox: cambia el contenido del cuadro de texto. Ocurre cuando un vnculo DDE actualiza los datos, cuando un usuario cambia el texto o cuando usted cambia la configuracin de la propiedad Text mediante cdigo.

Sintaxis Private Sub objeto_Change([ndice As Integer]) La sintaxis del evento Change consta de las siguientes partes: Parte objeto ndice Descripcin Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. Un entero que identifica nicamente a un control si est en una matriz de controles.

Comentarios

230

El procedimiento del evento Change puede sincronizar o coordinar la presentacin de datos entre controles. Por ejemplo, puede utilizar un procedimiento de evento Change de una barra de desplazamiento para actualizar la configuracin de la propiedad Value de la barra de desplazamiento de un control TextBox. O bien, puede utilizar un procedimiento de evento Change para mostrar datos y frmulas en un rea de trabajo y los resultados en otra rea. Los procedimientos de evento Change son tambin tiles para actualizar propiedades de controles del sistema de archivos (DirListBox, DriveListBox y FileListBox). Por ejemplo, puede actualizar la configuracin de la propiedad Path para que un control DirListBox refleje un cambio en la configuracin de la propiedad Drive de un control DriveListBox. Nota Un procedimiento de evento Change puede algunas veces causar un evento en cascada. Esto ocurre cuando el procedimiento de evento Change del control altera el contenido del control, por ejemplo, estableciendo una propiedad en el cdigo que determina el valor del control, como el valor de la propiedad Text para un control TextBox. Para impedir un evento en cascada: Si es posible, evite escribir un procedimiento de evento Change para un control que altere el contenido de ese control. Si escribe un procedimiento as, asegrese de establecer un indicador que impida cambios posteriores mientras el cambio actual est en curso. Evite crear dos o ms controles cuyos procedimientos de evento Change se vean afectados entre s, por ejemplo, dos controles TextBox que se actualicen entre s durante sus eventos Change. Evite utilizar una funcin o una instruccin MsgBox en este evento para los controles HScrollBar y VScrollBar.

Ejemplo del evento Change Este ejemplo muestra la configuracin numrica de la propiedad Value de una barra de desplazamiento horizontal en un control TextBox. Para probar este ejemplo, cree un formulario con un control TextBox y un control HScrollBar y despus pegue el cdigo en la seccin Declaraciones de un formulario que contenga una barra de desplazamiento horizontal (control HScrollBar) y un control TextBox. Presione F5 y haga clic en la barra de desplazamiento horizontal. Private Sub Form_Load () [Link] = 0 '

Establece Min.

Establece Max.

[Link] = 1000

'

[Link] = 100 Establece LargeChange. [Link] = 1 Establece SmallChange. End Sub Private Sub HScroll1_Change () [Link] = [Link]

'

'

231

End Sub

13.2-Click
Aplicable a: Control CheckBox, Control ComboBox, Control CommandButton, Objeto Form, Control Frame, Control Image, Control Label, Control ListBox, Control Menu, Control OptionButton, Control PictureBox, Control TextBox. Ocurre cuando el usuario presiona y suelta un botn del mouse (ratn) en un objeto. Tambin puede ocurrir cuando se cambia el valor de un control. Para un objeto Form, este evento ocurre cuando el usuario hace clic en un rea en blanco o en un control desactivado. Para un control, este evento ocurre cuando el usuario: Hace clic en un control con el botn primario o secundario del mouse. Con un control CheckBox, CommandButton, ListBox o OptionButton, el evento Click slo ocurre cuando el usuario hace clic con el botn primario del mouse. Selecciona un elemento de un control ComboBox o ListBox, ya sea presionando las teclas de direccin o haciendo clic con el botn del mouse. Presiona la BARRA ESPACIADORA cuando un control CommandButton, OptionButton o CheckBox tiene el enfoque. Presiona ENTRAR cuando un formulario tiene un control CommandButton con su propiedad Default establecida a True. Presiona ESC cuando un formulario tiene un botn Cancelar, un control CommandButton con su propiedad Cancel establecida a True. Presiona una tecla de acceso para un control. Por ejemplo, si el ttulo de un control CommandButton es "&Ir", al presionar ALT+I se desencadena este evento.

Tambin puede desencadenar el evento Click en el cdigo si: Sintaxis Private Sub Form_Click( ) Private Sub objeto_Click([ndice As Integer]) La sintaxis del evento Click consta de las siguientes partes: Parte objeto ndice Descripcin Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. Un entero que identifica nicamente a un control si est en una matriz de controles. Establece la propiedad Value de un control CommandButton a True. Establece la propiedad Value de un control OptionButton a True. Cambia el valor de la propiedad Value de un control CheckBox.

Comentarios

232

Por lo general se adjunta un procedimiento de evento Click a un control CommandButton, un objeto Menu o un control PictureBox para realizar comandos y acciones similares a comandos. Para los dems controles aplicables, utilice este evento para desencadenar acciones como respuesta a un cambio en el control. Puede utilizar la propiedad Value de un control para comprobar el estado del control desde el cdigo. Hacer clic en un control genera los eventos MouseDown y MouseUp adems del evento Click. El orden en que ocurren estos tres eventos vara de un control a otro. Por ejemplo, para los controles ListBox y CommandButton, los eventos ocurren en este orden: MouseDown, Click, MouseUp. Pero para los controles FileListBox, Label o PictureBox, los eventos ocurren en este otro orden: MouseDown, MouseUp y Click. Cuando est adjuntando procedimientos para estos eventos relacionados, asegrese de que sus acciones no entran en conflicto. Si el orden de los eventos es importante en la aplicacin, pruebe el control para determinar el orden de los mismos. Nota Para distinguir entre los botones primario, secundario y central del mouse, utilice los eventos MouseDown y MouseUp. Si hay cdigo en el evento Click, nunca se activar el evento DlbClick ya que de los dos eventos, Click es el primero que se activa. Como resultado, el evento Click intercepta el clic del mouse, por lo que DblClick nunca se producir. Ejemplo del Evento Click En este ejemplo, cada vez que se hace clic en un control PictureBox se mueve diagonalmente por un formulario. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control PictureBox en la esquina inferior izquierda del mismo, despus presione F5 y haga clic en el control PictureBox. Private Sub Picture1_Click () [Link] [Link] + 750, [Link] - 550 End Sub

13.3- GotFocus
Aplicable a: Control CheckBox, Control ComboBox, Control CommandButton, , Objeto Form Controles HScrollBar y VScrollBar, Control ListBox, Control OptionButton, Control PictureBox, Control TextBox. Ocurre cuando un objeto recibe el enfoque, ya sea mediante una accin del usuario, como tabular o hacer clic en el objeto, o cambiando el enfoque en el cdigo mediante el mtodo SetFocus. Un formulario recibe el enfoque slo cuando todos los controles visibles estn desactivados. Sintaxis Private Sub Form_GotFocus( )

Private Sub objeto_GotFocus([ndice As Integer]) La sintaxis del evento GotFocus consta de las siguientes partes:

233

Parte

Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. ndice Un entero que identifica de manera nica a un control si est en una matriz de controles. Comentarios Normalmente, el procedimiento de evento GotFocus se utiliza para especificar las acciones que ocurren cuando un control o un formulario recibe primero el enfoque. Por ejemplo, si adjunta un procedimiento de evento GotFocus a cada control de un formulario puede guiar al usuario mostrndole instrucciones breves o mensajes en la barra de estado. Tambin puede proporcionar avisos visuales activando, desactivando o mostrando otros controles que dependan del control que tiene el enfoque. Nota Un objeto puede recibir el enfoque slo si sus propiedades Enabled y Visible estn establecidas a True. Para personalizar el interfaz de teclado en Visual Basic para mover el enfoque, establezca el orden de tabulacin o especifique teclas de acceso para controles de un formulario. Ejemplo del evento GotFocus Este ejemplo muestra un mensaje en la barra de estado cuando un botn de un grupo OptionButton obtiene el enfoque. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga dos controles OptionButton y un control Label. Establezca la propiedad Name de ambos controles OptionButton a OptionGroup y, despus, presione F5 y haga clic en los controles OptionButton. Private Sub Form_Load () [Link] = True End Sub Private Sub OptionGroup_GotFocus (Index As Integer) Select Case Index Case 0 [Link] = "La opcin 1 tiene el enfoque." Case 1 [Link] = "La opcin 2 tiene el

enfoque." End Select End Sub

234

Private Sub OptionGroup_LostFocus (Index As Integer) [Link] = "" End Sub

13.4- KeyPress
Aplicable a: Control CheckBox, Control ComboBox, Control CommandButton, Objeto Form Controles HScrollBar y VScrollBar, Control ListBox, Control OptionButton, Control PictureBox, Control TextBox. Ocurre cuando el usuario presiona y suelta una tecla. Sintaxis Private Sub Form_KeyPress(keyascii As Integer) Private Sub objeto_KeyPress([ndice As Integer,]keyascii As Integer) La sintaxis del evento KeyPress consta de las siguientes partes: Parte Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. ndice Un entero que identifica de manera nica a un control si est en una matriz de controles. keyascii Un entero que devuelve un cdigo de tecla numrico ANSI estndar. keyascii se pasa por referencia; al cambiarlo se enva un carcter diferente al objeto. Cambiar keyascii a 0 cancela la pulsacin de tecla, de forma que el objeto no recibe ningn carcter. Comentarios El objeto que tiene el enfoque recibe el evento. Un formulario puede recibir el evento slo si no tiene controles visibles y activados. Un evento KeyPress puede implicar a cualquier carcter imprimible del teclado, a la tecla CTRL combinada con un carcter del alfabeto estndar o uno de los caracteres especiales, y la tecla ENTRAR o RETROCESO. Un procedimiento de evento KeyPress es til para interceptar pulsaciones de teclas realizadas en un control TextBox o ComboBox. Esto le permite comprobar inmediatamente la validez de las pulsaciones o el formato de los caracteres a medida que se escriben. Cambiar el valor del argumento keyascii cambia el carcter mostrado. KeyPress interpreta las maysculas y minsculas de cada carcter como cdigos de tecla distintos y, por tanto, como caracteres diferentes. Nota El nmero ANSI para la combinacin de teclado CTRL+@ es 0. Puesto que Visual Basic reconoce un valor keyascii de 0 como una cadena de longitud cero (""), evite utilizar CTRL+@ en sus aplicaciones.

235

Ejemplo del evento KeyPress Este ejemplo convierte a maysculas el texto escrito en un control TextBox. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control TextBox y, despus, presione F5 y escriba algo en el control TextBox. Private Sub Text1_KeyPress (KeyAscii As Integer) Char = Chr(KeyAscii) KeyAscii = Asc(UCase(Char)) End Sub

13.5- Load
Aplicable a: Objeto Form. Ocurre cuando se carga un formulario. Para un formulario de inicio, ocurre cuando una aplicacin se inicia como resultado de una instruccin Load o como resultado de una referencia a una propiedad o control de un formulario descargado. Sintaxis Private Sub Form_Load( ) Private Sub MDIForm_Load( ) Comentarios Normalmente utiliza un procedimiento de evento Load para incluir cdigo de inicializacin para un formulario; por ejemplo, cdigo que especifica los valores predeterminados de los controles, indica el contenido que se va a cargar en controles ComboBox o ListBox e inicializa variables a nivel del formulario. El evento Load ocurre tras el evento Initialize. Nota Cuando cree procedimientos para eventos relacionados, como Activate, GotFocus, Paint y Resize, asegrese de que sus acciones no entran en conflicto y no producen eventos recursivos. Ejemplo del evento Load Este ejemplo carga elementos en un control ComboBox cuando se carga un formulario. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control ComboBox y despus presione F5. Private Sub Form_Load () [Link] "Mozart" ' Agrega elementos a la

lista.

236

[Link] "Beethoven" [Link] "Rock 'n Roll" [Link] "Reggae" [Link] = 2 predeterminada. End Sub ' Establece la seleccin

13.6- LostFocus
Aplicable a Control CheckBox, Control ComboBox, Control CommandButton, Objeto Form Controles HScrollBar y VScrollBar, Control ListBox, Control OptionButton, Control PictureBox, Control TextBox. Ocurre cuando un objeto pierde el enfoque, ya sea por una accin del usuario, como tabular o hacer clic en otro objeto, o bien mediante un cambio del enfoque en el cdigo con el mtodo SetFocus. Sintaxis Private Sub Form_LostFocus( ) Private Sub objeto_LostFocus([ndice As Integer]) La sintaxis del evento LostFocus consta de las siguientes partes: Parte Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. ndice Un entero que identifica de manera nica a un control si est en una matriz de controles. Comentarios Un procedimiento de evento LostFocus resulta especialmente til para comprobar y validar actualizaciones. Utilizar LostFocus puede hacer que la validacin tenga lugar conforme el usuario mueve el enfoque del control. Otro uso para este tipo de procedimiento de evento es activar, desactivar, ocultar y mostrar otros objetos, como en un procedimiento de evento GotFocus. Tambin puede invertir o cambiar condiciones que estableci en el procedimiento de evento GotFocus del objeto. Ejemplo del evento LostFocus Este ejemplo cambia el color de un control TextBox cuando recibe o pierde el enfoque (se selecciona con el mouse o la tecla TAB) y muestra el texto apropiado en el control Label. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga

237

dos controles TextBox y un control Label y, despus, presione F5 y mueva el enfoque entre Text1 y Text2. Private Sub Text1_GotFocus () ' Muestra el enfoque en rojo. [Link] = RGB(255, 0, 0) [Link] = "Text1 tiene el enfoque." End Sub Private Sub Text1_LostFocus () ' Muestra la prdida del enfoque en azul. [Link] = RGB(0, 0, 255) [Link] = "Text1 no tiene el enfoque." End Sub

13.7- MouseMove
Aplicable a: Control CheckBox, Control CommandButton, Control Data, Objeto Form, Control Frame, Control Image, Control Label, Control ListBox, Control OptionButton, Control PictureBox, Control TextBox. Ocurre cuando el usuario mueve el mouse. Sintaxis Private Sub Form_MouseMove(botn As Integer, mays As Integer, x As Single, y As Single) Private Sub MDIForm_MouseMove(botn As Integer, mays As Integer, x As Single, y As Single) Private Sub objeto_MouseMove([ndice As Integer,] botn As Integer, mays As Integer, x As Single, y As Single) La sintaxis del evento MouseMove consta de las siguientes partes: Parte Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. ndice Un entero que identifica de manera nica a un control si est en una matriz de controles.

238

botn Un entero que corresponde al estado de los botones del mouse en el cual un bit se establece si el botn est presionado. El argumento botn es un campo de bit con los bits correspondientes al botn primario (bit 0), al botn secundario (bit 1) y al botn central (bit 2). Estos bits corresponden a los valores 1, 2 y 4, respectivamente. Indica el estado completo de los botones del mouse; alguno, todos o ninguno de estos tres bits puede estar establecido, lo que indica que algunos, todos o ninguno de los botones est presionado. mays Un entero que corresponde al estado de las teclas MAYS, CTRL y ALT. Un bit est establecido si la tecla est presionada. El argumento mays es un campo de bits con los bits menos significativos correspondientes a la tecla MAYS (bit 0), CTRL (bit 1) y ALT (bit 2 ). Estos bits corresponden a los valores 1, 2 y 4, respectivamente. El argumento mays indica el estado de estas teclas. Alguno, todos o ninguno de los bits puede estar establecido, lo que indica que alguna, todas o ninguna de las teclas est presionada. Por ejemplo, si se presionaron las teclas CTRL y ALT, el valor de shift sera 6. x, y Un nmero que especifica la ubicacin actual del puntero del mouse. Los valores x e y siempre se expresan en trminos del sistema de coordenadas establecido por las propiedades ScaleHeight, ScaleWidth, ScaleLeft y ScaleTop del objeto. Comentarios El evento MouseMove se genera continuamente a medida que el puntero del mouse se mueve por los objetos. A menos que otro objeto haya capturado el mouse, un objeto reconoce un evento MouseMove siempre que la posicin del mouse est dentro de sus bordes. Ejemplo del evento MouseMove Este ejemplo muestra una aplicacin de dibujo simple. El procedimiento de evento MouseDown funciona con un procedimiento MouseMove relacionado para activar el dibujo cuando est presionado cualquier botn del mouse. El procedimiento de evento MouseUp desactiva el dibujo. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario, despus presione F5, haga clic en el formulario y mueva el mouse mientras est presionado el botn del mismo. Dim PaintNow As Boolean ' Declara una variable.

Private Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single) PaintNow = True ' Activa el dibujo. End Sub Private Sub Form_MouseUp (Button As Integer, X As Single, Y As Single) PaintNow = False End Sub Private Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single) If PaintNow Then ' Desactiva el dibujo.

239

PSet (X, Y) punto. End If End Sub Private Sub Form_Load () DrawWidth = 10 ForeColor = RGB(0, 0, 255) dibujo. End Sub

' Dibuja un

' Utiliza un pincel ms ancho. ' Establece el color de

13.8- Timer
Aplicable a: Control Timer Ocurre cuando ha transcurrido un intervalo preestablecido para un control Timer. La frecuencia del intervalo se almacena en la propiedad Interval del control, que especifica el tiempo en milisegundos. Sintaxis Private Sub objeto_Timer([ndice As Integer]) La sintaxis del evento Timer consta de las siguientes partes: Parte Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Aplicable a. ndice Un entero que identifica de manera nica a un control si est en una matriz de controles. Comentarios Utilice este procedimiento de evento para indicar a Visual Basic qu hacer cada vez que se agote el intervalo de tiempo de un control Timer. Cuando est trabajando con el evento Timer: La propiedad Interval especifica el intervalo entre los eventos Timer, en milisegundos. Siempre que la propiedad Enabled del control Timer est establecida a True y la propiedad Interval sea mayor que 0, el evento Timer espera durante el periodo especificado en la propiedad Interval.

Ejemplo del evento Timer

240

Este ejemplo muestra un reloj digital. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control Label y un control Timer y, despus, presione F5. Private Sub Form_Load () [Link] = 1000 ' Establece el intervalo de

Timer. End Sub

Private Sub Timer1_Timer () [Link] = Time ' Actualiza la presentacin de la

hora. End Sub

Este ejemplo mueve un control PictureBox por un formulario. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control Timer y un control PictureBox y, despus, presione F5. Si desea obtener un efecto visual mejor puede asignar un mapa de bits al control PictureBox mediante la propiedad Picture. Dim DeltaX, DeltaY As Integer Private Sub Timer1_Timer () [Link] [Link] + DeltaX, [Link] + DeltaY If [Link] < ScaleLeft Then DeltaX = 100 If [Link] + [Link] > ScaleWidth + ScaleLeft Then DeltaX = -100 End If If [Link] < ScaleTop Then DeltaY = 100 If [Link] + [Link] > ScaleHeight + ScaleTop ' Declara variables.

Then

DeltaY = -100 End If End Sub Private Sub Form_Load () [Link] = 1000 ' Establece el intervalo.

241

DeltaX = 100 DeltaY = 100 End Sub

' Inicializa variables.

13.9- Unload
Aplicable a: Objeto Form. Ocurre cuando un formulario est a punto de quitarse de la pantalla. Cuando ese formulario se vuelve a cargar, el contenido de todos sus controles se reinicializa. Este evento se desencadena porque un usuario cierra el formulario mediante el comando Cerrar del men Control o una instruccin Unload. Sintaxis Private Sub objeto_Unload(cancelar As Integer) La sintaxis del evento Unload consta de las siguientes partes: Parte objeto Descripcin Una expresin de objeto que da como resultado un objeto de la lista Aplicable a.

cancelar Un entero que determina si el formulario se quita de la pantalla. Si cancelar es 0, el formulario se quita. Establecer cancelar a cualquier valor distinto de cero impide que el formulario se quite. Comentarios Establecer cancelar a un valor distinto de cero impide que el formulario se quite, pero no detiene los dems eventos, como la salida del entorno operativo Microsoft Windows. Utilice el evento QueryUnload para detener la salida de Windows. Utilice un procedimiento de evento Unload para comprobar si el formulario se debe descargar o para especificar acciones que desea que tengan lugar cuando se descargue el formulario. Tambin puede incluir cualquier cdigo de validacin a nivel del formulario que pueda necesitar para cerrar el formulario o guardar los datos en un archivo. El evento QueryUnload ocurre antes que el evento Unload. El evento Unload ocurre antes que el evento Terminate. El evento Unload puede estar causado por la utilizacin de la instruccin Unload o porque el usuario elija el comando Cerrar del men Control del formulario, salga de la aplicacin con el botn Finalizar tarea de la Lista de tareas, o salga del entorno operativo Microsoft Windows mientras la aplicacin se est ejecutando. Ejemplo del evento Unload

242

Este ejemplo muestra un procedimiento simple para cerrar un formulario mientras se avisa al usuario con varios cuadros de mensajes. En una aplicacin real, puede agregar llamadas a procedimientos Sub de propsito general que emulen el proceso de los comandos Salir, Guardar y Guardar como del men Archivo de Visual Basic. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario y, despus, presione F5. Una vez que se muestre el formulario, presione ALT+F4 para cerrar el formulario. Private Sub Form_Unload (Cancel As Integer) Dim Msg, Response ' Declara variables.

Msg = "Desea guardar los datos antes de cerrar?" Response = MsgBox(Msg, vbQuestion + vbYesNoCancel, "Dilogo

Cerrar")

Select Case Response Case vbCancel ' No se permite cerrar.

Cancel = -1 Msg = "Se ha cancelado el comando." Case vbYes ' Introduzca cdigo para guardar los datos aqu. Msg = "Datos guardados."' Case vbNo Msg = "Datos no guardados." End Select MsgBox Msg, vbOKOnly, "Confirmacin" End Sub ' Mostrar mensaje.

13.10- QueryUnload
Aplicable a: Objeto Form y Coleccin Forms, Objeto MDIForm Ocurre antes de que se cierre un formulario o una aplicacin. Sintaxis

243

Private Sub Form_QueryUnload(cancelar As Integer, modo_descarga As Integer) Private Sub MDIForm_QueryUnload(cancelar As Integer, modo_descarga As Integer) La sintaxis del evento QueryUnload consta de las siguientes partes: Parte Descripcin

cancelar Un entero. Establecer este argumento a cualquier valor distinto de 0 detiene el evento QueryUnload en todos los formularios cargados y detiene el cierre del formulario y de la aplicacin. modo_descarga Un valor o una constante que indica la causa del evento QueryUnload, tal y como se describe en Valores que se pueden obtener. Valores que se pueden obtener El argumento modo_descarga devuelve los siguientes valores: Constante vbFormControlMenu formulario. vbFormCode VbAppWindows 2 vbAppTaskManager Valor 0 Descripcin El usuario eligi el comando Cerrar del men Control del

Se invoc la instruccin Unload desde el cdigo.

La sesin actual del entorno operativo Microsoft Windows est inalizando. 3 El Administrador de tareas de Microsoft Windows est cerrando la

aplicacin. vbFormMDIForm formulario MDI 4 Un formulario MDI secundario se est cerrando porque el

tambin se est cerrando. Comentarios Normalmente este evento se utiliza para asegurarse de que no hay tareas sin finalizar en los formularios incluidos en una aplicacin antes de que esa aplicacin se cierre. Por ejemplo, si un usuario no ha guardado todava algunos datos nuevos de cualquier formulario, su aplicacin puede pedir al usuario que los guarde. Cuando una aplicacin se cierra, puede utilizar los procedimientos de evento QueryUnload o Unload para establecer la propiedad Cancel a True, deteniendo el proceso de cierre. Sin embargo, el evento QueryUnload ocurre en todos los formularios antes de que se descargue ninguno de ellos y el evento Unload ocurre conforme se descarga cada formulario.

244

Ejemplo del evento QueryUnload En este ejemplo, al cerrar un formulario se consulta al operador si realmente quiere salir o no. Tambin se chequea si est saliendo del formulario o de toda la aplicacin. ' Pegar en la seccin Declaraciones de Form1. Private Sub Form_QueryUnload (Cancel As Integer, UnloadMode As Integer) Dim Msg ' Declara la variable.

If UnloadMode > 0 Then ' Si sale de la aplicacin. Msg = "Realmente desea salir de la aplicacin?" Else ' Si slo se cierra el formulario. Msg = "Realmente desea cerrar el formulario?" End If ' Si el usuario hace clic en el botn No, se detiene QueryUnload. If MsgBox(Msg, vbQuestion + vbYesNo, [Link]) = vbNo Then Cancel = True End Sub

13.11- Validate
Aplicable a: Control Data Se produce antes de que otro registro se convierta en el registro actual, antes del mtodo Update (excepto cuando se guardan los datos con el mtodo UpdateRecord) y antes de una operacin Delete, Unload o Close. Sintaxis Private Sub objeto_Validate ([ndice As Integer,] accin As Integer, guardar As Integer) La sintaxis del evento Validate consta de las siguientes partes: Parte Descripcin

245

objeto Una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a ndice Identifica el control si se encuentra en una matriz de controles accin Un entero que indica la operacin que provoca el evento, como se describe en Valores guardar Una expresin booleana que especifica si los datos enlazados han cambiado, como se describe en Valores Valores Los valores de accin son: Constante vbDataActionCancel vbDataActionMoveFirst vbDataActionMovePrevious vbDataActionMoveNext vbDataActionMoveLast vbDataActionAddNew vbDataActionUpdate vbDataActionDelete vbDataActionFind vbDataActionBookmark vbDataActionClose vbDataActionUnload Los valores de guardar son: Valor True False Descripcin Los datos enlazados han cambiado Los datos enlazados no han cambiado Valor 0 1 2 3 4 5 6 7 8 9 10 11 Descripcin Cancela la operacin al salir de Sub Mtodo MoveFirst Mtodo MovePrevious Mtodo MoveNext Mtodo MoveLast Mtodo AddNew Operacin Update (no UpdateRecord) Mtodo Delete Mtodo Find Se ha establecido la propiedad Bookmark El mtodo Close Se est descargando el formulario

Comentarios El argumento guardar indica inicialmente si los datos enlazados han cambiado. Este argumento puede ser False si los datos del bfer de copia han cambiado. Si guardar es True cuando este

246

evento termina, se invocan los mtodos Edit y UpdateRecord. El mtodo UpdateRecord slo guarda los datos de controles enlazados o del bfer de copia en los que la propiedad DataChanged sea True. Este evento se produce incluso aunque no se hayan modificado los datos de los controles enlazados y aunque no existan controles enlazados. Puede utilizar este evento para cambiar valores y actualizar datos. Tambin puede decidir guardar los datos o detener cualquier accin que est provocando el evento y sustituirla por otra accin diferente. Puede cambiar el argumento accin para cambiar una accin por otra. Puede cambiar los diversos mtodos Move y el mtodo AddNew, que se pueden intercambiar libremente (cualquier Move en AddNew, cualquier Move en cualquier otro Move o AddNew en cualquier Move). Cuando utilice AddNew, puede utilizar MoveNext y despus ejecutar otro AddNew para examinar la propiedad EditMode y determinar si hay una operacin Edit o AddNew en curso. El intento de sustituir AddNew o una accin Move en cualquier otra accin se pasa por alto o genera un error interceptable. Si se establece accin a 0, se puede detener cualquier accin. Dentro del cdigo de este evento puede comprobar los datos de cada control enlazado en el que DataChanged sea True. Despus puede establecer DataChanged a False para evitar guardar dichos datos en la base de datos. Durante este evento no puede utilizar ningn mtodo (como MoveNext) en el objeto Recordset subyacente. Ejemplo de la propiedad DataChanged y del evento Validate Este ejemplo ilustra una validacin de datos sencilla. En la tabla Authors de la base de datos [Link] hay dos campos: Au_ID y Author. Como el valor de Au_ID se utiliza para identificar de forma nica al autor, este valor no se debe cambiar. El ejemplo no permite que se modifique el campo Au_ID, que est enlazado a Text1. Private Sub Data1_Validate (Action As Integer, Save As Integer) If [Link] Then han cambiado. ' Comprueba si los datos

MsgBox "No puede cambiar el nmero de Id." [Link] = False los datos modificados. End If ... End Sub ' No guarda

14- Mtodos ms importantes de los controles estndares. 14.1- AddItem


Aplicable a:

247

ControlComboBox, ControlListBox Agrega un elemento a un control ListBox o ComboBox. Sintaxis [Link] elemento, ndice La sintaxis del mtodo AddItem consta de las siguientes partes: Parte objeto Elemento objeto. Descripcin Requerido. Una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. Requerido. expresin de cadena que especifica el elemento que se va a agregar al

ndice Opcional. Entero que especifica la posicin dentro del objeto donde se insertan el elemento o la fila nuevos. Para el primer elemento de un control ListBox o ComboBox, ndice es 0. Comentarios Si se especifica un valor vlido para ndice, elemento se sita en dicha posicin dentro del objeto. Si se omite ndice, elemento se agrega en la posicin que le corresponda dentro del orden apropiado (si la propiedad Sorted es True) o al final de la lista (si Sorted es False). Los controles ListBox o ComboBox que estn enlazados a un control Data no aceptan el mtodo AddItem. Ejemplo del mtodo AddItem Este ejemplo utiliza el mtodo AddItem para agregar 100 elementos a un cuadro de lista. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario con un control ListBox llamado List1, y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Entry, I, Msg ' Declara variables.

Msg = "Haga clic en Aceptar para agregar 100 elementos a su cuadro de lista." MsgBox Msg ' Muestra el mensaje. ' Cuenta de 1 a 100. ' Crea la entrada. ' Agrega la entrada.

For I = 1 To 100

Entry = "Entrada " & I [Link] Entry Next I

248

Msg = "Haga clic en Aceptar para quitar una de cada dos entradas." MsgBox Msg For I = 1 To 50 ' Muestra el mensaje. ' Determina cmo

quitar

[Link] I Next I

' cada elemento

Msg = "Haga clic en Aceptar para quitar todos los elementos del cuadro de lista." MsgBox Msg [Link] End Sub ' Muestra el mensaje. ' Limpia el cuadro de lista.

14.2- AddNew (Objeto Recordset)


Aplicable a: Objeto Recordset. Crea un nuevo registro para un objeto Recordset de tipo Table o Dynaset. Sintaxis [Link] El marcador de posicin del recordset es una variable de objeto que representa un objeto Recordset que se puede actualizar al que puede agregar un registro nuevo. Comentarios Utilice el mtodo AddNew para crear y agregar un nuevo registro en el objeto Recordset llamado por el recordset. Este mtodo establece los campos a los valores predeterminados y si no se especifican valores predeterminados, establece los campos a Null (los valores predeterminados especificados pare el Recordset tipo Table). Despus de modificar el nuevo registro, utilice el mtodo Update para guardar los cambios y agregar el registro al Recordset. No se producirn cambios en la base de datos hasta que no se utilice el mtodo Update. Precaucin Si ejecuta un AddNew y a continuacin realiza una operacin que desplace otro registro sin usar Update, los cambios se perdern sin previo aviso. Adems, si cierra el Recordset o finaliza el procedimiento que declara el Recordset o su objeto Database, el nuevo registro y los cambios realizados se descartarn sin previo aviso.

249

Si no se ha desplazado hasta el ltimo registro de su Recordset, los registros agregados a las tablas subyacentes pueden incluirse, si se colocan ms all del registro activo. Sin embargo, si agrega un registro a un Recordset, el registro ser visible en el Recordset y se incluir en la tabla subyacente donde estar visible para todos los nuevos objetos Recordset. La posicin del nuevo registro depende del tipo de Recordset: En un objeto Recordset tipo Dynaset, los registros se insertan al final del conjunto del Recordset, independientemente de las reglas de clasificacin u orden que estuvieran en vigor cuando se abri el Recordset. En un objeto Recordset tipo Table en el que su propiedad Index se haya establecido, los registros se insertan en el lugar adecuado dentro del orden definido. Si no se ha establecido la propiedad Index, los nuevos registros se insertarn al final del Recordset.

Ejemplo de mtodo AddNew En este ejemplo se agrega un regisro nuevo a la tabla Agenda de la base de datos Clientes, tomando los datos desde un formulario que contiene 3 cajas de texto (txtCodigo, txtNombre y txtDireccion) y un botn para agregar los datos (cmdAgregar) Private Sub cmdAgregar_Click () Dim wsp as WorkSpace Dim Base as Database Dim Agenda as Recordset Set wsp = [Link](0) trabajo Set Base = [Link] ([Link]) Seteo el espacio de Dimensiono las variables

Abro la base de Datos Abro

Set Agenda = [Link](SELECT * FROM Agenda) el Recordset [Link] Agenda!Codigo = [Link] texto a los campos Agenda!Direccion = [Link] [Link] = [Link] [Link] [Link] [Link] [Link] Cierro el Recordset Cierro la base de Datos Cierro el espacio de trabajo

Agrego un registro en blanco Asigno los valores de las cajas de

250

End Sub

14.3- CancelUpdate (Objeto Recordset)


Aplicanble a: Objeto Recordset. Cancela todas las actualizaciones pendientes del objeto Recordset. Sintaxis [Link] tipo La sintaxis del mtodo CancelUpdate consta de las siguientes partes. Parte Descripcin

recordset Una variable de objeto que representa el objeto Recordset en el que se cancelan las actualizaciones pendientes. Tipo Opcional. Una constante que indica el tipo de actualizacin, como se especifica en Valores (slo espacios de trabajo ODBCDirect). Comentarios El mtodo CancelUpdate cancela todas las actualizaciones pendientes a causa de una operacin Edit o AddNew. Por ejemplo, si un usuario llama al mtodo Edit o AddNew sin haber llamado anteriormente al mtodo Update, CancelUpdate cancelar todos los cambios efectuados despus de llamar a Edit o AddNew. Ejemplo del mtodo CancelUpdate Al mismo ejemplo del Evento AddNew, le agregamos la opcin de confirmar o volver para atrs la actualizacin al operador, segn la respuesta a una caja de mensajes. Private Sub cmdAgregar_Click () Dim wsp as WorkSpace Dim Base as Database Dim Agenda as Recordset Set wsp = [Link](0) trabajo Set Base = [Link] ([Link]) Seteo el espacio de Dimensiono las variables

Abro la base de Datos Abro

Set Agenda = [Link](SELECT * FROM Agenda) el Recordset

251

[Link] registro en blanco Agenda!Codigo = [Link] texto a los campos Agenda!Direccion = [Link] [Link] = [Link] If

Agrego un

Asigno los valores de las cajas de

MsgBox ("Agrega el nuevo registro, vbYesNo) = vbYes then [Link] Else [Link]

End If [Link] [Link] [Link] End Sub Cierro el Recordset Cierro la base de Datos Cierro el espacio de trabajo

14.4- Clear (Clipboard, Combo Box, List Box)


Aplicable a: Objeto Control ComboBox, Control ListBoxBorra el contenido de los controles ListBox o ComboBox. Sintaxis [Link] El marcador de posicin objeto representa una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. Comentarios Los controles ListBox o ComboBox que estn enlazados a un control Data no aceptan el mtodo Clear. Ejemplo del mtodo Clear

252

Este ejemplo utiliza el mtodo Clear para borrar todos los elementos de un cuadro de lista. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario con un control ListBox llamado List1, y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Entry, I, Msg ' Declara variables.

Msg = "Haga clic en Aceptar para agregar 100 elementos a su cuadro de lista." MsgBox Msg For I = 1 To 100 ' Muestra el mensaje. ' Cuenta de 1 a 100. ' Crea la entrada. ' Agrega la entrada.

Entry = "Entrada " & I [Link] Entry Next I

entrada."

Msg = "Haga clic en Aceptar para quitar cualquier otra

MsgBox Msg For I = 1 To 50 cmo quitar

' Muestra el mensaje. ' Determina

[Link] I dos Next I elementos.

' uno de cada

'

Msg = "Haga clic en Aceptar para quitar todos los elementos del cuadro de lista." MsgBox Msg [Link] End Sub ' Muestra el mensaje. ' Limpia el cuadro de lista.

14.5- Close (Objetos Database, Recordset o Workspace)


Aplicable a: Objeto Database, Objeto Recordset, Objeto Workspace. Cierra un objeto DAO (Data Access Object).

253

Sintaxis [Link] El marcador de posicin objeto es una variable de objeto que representa un objeto Database, Recordset o Workspace abierto. Comentarios Si el objeto Database, Recordset o Workspace llamado por objeto est cerrado cuando utiliza Close se produce un error en tiempo de ejecucin. Precaucin Si sale de un procedimiento que declara objetos Database o Recordset y la base de datos est cerrada, los cambios no guardados se perdern, todas las transacciones pendientes se anularn y se anularn todas las modificaciones pendientes de los datos. Si intenta cerrar un objeto Connection o Database mientras hay algn objeto Recordset abierto, estos objetos Recordset se cerrarn y las actualizaciones o modificaciones pendientes quedarn anuladas. Si intenta cerrar un objeto Workspace mientras hay algn objeto Database abierto, los objetos Database se cerrarn, el cual cerrar sus objetos Recordset. La utilizacin del mtodo Close en un objeto Recordset original o duplicado no afecta al otro objeto Recordset. Una alternativa al mtodo Close es establecer el valor de una variable de objeto a Nothing (Set dbsTemp = Nothing). Ejemplo de mtodo Close Son vlidos los ejemplos de los mtodos AddNew y CancelUpdate. (donde se cierran objetos Workspace, Database y Recordset),

14.6- Cls
Aplicable a: Objeto Form, Control PictureBox. Borra los grficos y el texto generados en tiempo de ejecucin de los controles Form o PictureBox. Sintaxis

[Link]
El marcador de posicin objeto representa una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. Si se omite objeto, se supone que el objeto es el control Form que tenga el enfoque. Comentarios

254

Cls borra el texto y los grficos generados en tiempo de ejecucin por instrucciones grficas y de impresin. Los mapas de bits de fondo definidos mediante la propiedad Picture y los controles colocados en un Form en tiempo de diseo no se ven afectados por Cls. Despus de llamar a Cls, las propiedades CurrentX y CurrentY del objeto se restablecen a 0. Ejemplo del mtodo Cls Este ejemplo utiliza el mtodo Cls para eliminar la informacin impresa de un formulario. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario, y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Msg ForeColor = QBColor(15) primer plano a blanco. BackColor = QBColor(1) fondo a azul. Msg = "Esta informacin se imprime en el fondo del formulario." Print Msg formulario. Msg = "Haga clic en Aceptar para borrar la informacin y el patrn de fondo " Msg = Msg & "mostrado en el formulario." MsgBox Msg Cls End Sub ' Muestra el mensaje. ' Borra el fondo del formulario. ' Imprime el mensaje en el ' Declara variable. ' Establece el color de

' Establece el color de

14.7- CompactDatabase (Objeto DBEngine)


Aplicable a: Objeto DBEngine Copia, compacta y ofrece la posibilidad de cambiar la versin, la secuencia de ordenacin y la codificacin. (slo espacio de trabajo Microsoft Jet). Sintaxis [Link] antiguabasededatos, nuevabasededatos, escenario, opciones, contrasea

255

La sintaxis del mtodo CompactDatabase tiene los siguientes argumentos: -Antiguabasededatos: Una String que identifica una base de datos existente y cerrada. Puede ser una ruta completa y un nombre de archivo, como "C:\[Link]". Si el nombre de archivo tiene una extensin, deber especificarla. Si su red lo admite, tambin puede especificar una ruta de red, como "\\server1\share1\dir1\[Link]". -nuevabasededatos: Un tipo de datos String que es la ruta completa de la base de datos compactada que va a crear. Tambin puede especificar una ruta de acceso de red al igual que con antiguabasededatos. No puede usar el argumento nuevabasededatos para especificar el mismo archivo de base de datos que antiguabasededatos. -Escenario: Opcional. Un tipo de datos Variant que es una expresin de cadena que se utiliza para especificar la secuencia de ordenacin para crear nuevabasededatos, como se especifica en Opciones. Si omite este argumento, el escenario de la nuevabasededatos ser el mismo que el de la antiguabasededatos. Tambin puede crear una contrasea para nuevabasededatos concatenando la cadena de la contrasea (que comienza con ";pwd=") con una constante del argumento escenario, como este: dbLangSpanish & ";pwd=NuevaContrasea" Si desea utilizar el mismo escenario como antiguabasededatos (el valor predeterminado), pero especificar una contrasea nueva, simplemente escriba una contrasea en escenario: ";pwd=NuevaContrasea" opciones Opcional. Un valor entero que indica una o ms opciones, segn se especifica en Opciones. Puede combinar opciones sumando las correspondientes constantes. -Contrasea: Opcional. Un tipo de datos Variant que es una expresin de cadena que contiene una contrasea, si la base de datos est protegida con contrasea. La cadena ";pwd=" debe preceder a la propia contrasea. Si incluye una valor de contrasea en escenario, este valor se ignora. Puede utilizar una de las siguientes constantes en el argumento opciones para especificar si desea o no codificar la base de datos mientras se compacta. Constante dbEncrypt DbDecrypt Descripcin Codifica la base de datos durante la compactacin. Descodifica la base de datos durante la compactacin.

Si omite una constante de codificacin o si incluye a la vez dbDecrypt y dbEncrypt, nuevabasededatos tendr la misma codificacin que antiguabasededatos. Puede usar una de las siguientes constantes en el argumento opciones para especificar la versin del formato de los datos para la base de datos compactada. Esta constante afecta slo a la versin del formato de datos de nuevabasededatos y no afecta a la versin de ninguno de los objetos definidos por Microsoft Access, como formularios e informes. Constante Descripcin

256

dbVersion10 versin 1.0

Crea una base de datos que utiliza el motor de base de datos Microsoft Jet

durante la compactacin. DbVersion11 versin 1.1 Crea una base de datos que utiliza el motor de base de datos Microsoft Jet

durante la compactacin. DbVersion20 versin 2.0 Crea una base de datos que utiliza el motor de base de datos Microsoft Jet

durante la compactacin. DbVersion30 Crea una base de datos que utiliza el motor de base de datos Microsoft Jet versin 3.0 (compatible con la versin 3.5) durante la compactacin. Slo puede especificar una constante de versin. Si omite una constante de versin, nuevabasededatos tendr la misma versin que antiguabasededatos. Slo puede compactar nuevabasededatos a una versin igual o posterior a la de antiguabasededatos. Comentarios Al cambiar datos de una base de datos, el archivo de base de datos puede fragmentarse y utilizar ms espacio en disco del necesario. Regularmente, puede usar el mtodo CompactDatabase en la base de datos para desfragmentar el archivo de base de datos. La base de datos compactada suele ser ms pequea y ejecutarse con ms rapidez. Tambin puede cambiar la secuencia de ordenacin, la codificacin o la versin del formato de datos, mientras copia y compacta la base de datos. Tiene que cerrar antiguabasededatos antes de compactarla. En un entorno multiusuario, los dems usuarios no pueden tener abierta antiguabasededatos mientras usted la compacta. Si antiguabasededatos no est cerrada o no se encuentra disponible para su uso exclusivo, se producir un error. Puesto que CompactDatabase crea una copia de la base de datos, deber disponer de espacio suficiente en disco para la base de datos original y la duplicada. La operacin de compactacin fracasar si no hay suficiente espacio disponible en disco. La base de datos duplicada nuevabasededatos no tiene por qu estar en el mismo disco que antiguabasededatos. Despus de compactar una base de datos, puede eliminar el archivo antiguabasededatos y cambiar el nombre del archivo compactado nuevabasededatos por el nombre del archivo original. El mtodo CompactDatabase copia todos los datos y valores de permisos de seguridad de la base de datos especificada en antiguabasededatos a la base de datos especificada en nuevabasededatos. Si utiliza el mtodo CompactDatabase para convertir una base de datos versin 1.x a una versin 2.5 o 3.x, solamente las aplicaciones que utilizan las versiones de Microsoft Jet 2.5 o 3.x pueden abrir la base de datos convertida. Precaucin Debido a que el mtodo CompactDatabase no convertir objetos Microsoft Access, no es recomendable utilizar CompactDatabase para convertir una base de datos que contenga dichos

257

objetos. Para convertir una base de datos que contenga objetos Microsoft Access, en el men Herramientas, elija Utilidades de la base de datos y despus haga clic en Convertir base de datos. Ejemplo de mtodo CompactDatabase Este ejemplo utiliza el mtodo CompactDatabase compactar la base de Datos [Link]. Sub CompactDatabaseX() [Link] "[Link]", [Link]" End Sub

14.8- Delete (Objeto Recordset)


Aplicable a: Objeto Recordset. Objetos Recordset: elimina el registro activo de un objeto Recordset de tipo Dynaset o Table. Para espacios de trabajo ODBCDirect, el tipo de controlador determina si los objetos Recordset se pueden actualizar y, por tanto, admiten el mtodo Delete.

Sintaxis [Link] La sintaxis del mtodo Delete utiliza los siguientes argumentos. Argumentos Descripcin

recordset Una variable de objeto que identifica un objeto Recordset de tipo Dynaset o Table abierto, que contiene el registro que desea eliminar. Comentarios Puede utilizar el mtodo Delete para eliminar un registro activo de un objeto Recordset. Recordsets Un objeto Recordset debe contener un registro activo antes de que utilice el mtodo Delete; en caso contrario se produce un error en tiempo de ejecucin. En objetos Recordset, Delete elimina el registro activo y lo hace inaccesible. Aunque no pueda modificarlo o utilizarlo, el registro eliminado permanecer activo. Sin embargo, una vez que se desplace a otro registro no podr volver a convertir en activo el registro eliminado. Las referencias subsiguientes a un registro eliminado en un Recordset no son vlidas y producen un error. Si la tabla base es la tabla principal en una relacin de eliminacin de cascada, al eliminar el registro activo tambin se eliminarn uno o ms registros de una tabla externa.

258

Nota Para agregar, modificar o eliminar un registro, debe tener un ndice nico en el registro en el origen de datos de base. Si no es as, se producir un error "Permiso denegado" en la llamada al mtodo AddNew, Delete o Edit en un espacio de trabajo Microsoft Jet. Ejemplo de mtodo Delete Se necesitan borrar todos los registros de la tabla Agenda (dentro de la base de datos Clientes) cuyos cdigos de Clientes sean menores a 10. Private Sub cmdAgregar_Click () Dim wsp as WorkSpace Dim Base as Database Dim Agenda as Recordset Set wsp = [Link](0) trabajo Set Base = [Link] ([Link]) Seteo el espacio de Dimensiono las variables

Abro la base de Datos

Set Agenda = [Link](SELECT * FROM Agenda WHERE [Link] < 10) Abro el Recordset If Not [Link] [Link] Do While Not [Link] [Link] [Link] registro Loop End If [Link] [Link] [Link] End Sub Cierro el Recordset Cierro la base de Datos Cierro el espacio de trabajo si encontr algn registro me muevo al primer registro mientras no sea fin de archivo elimino el registro me desplazo al siguiente

14.9- Edit (Objeto Recordset)


Aplicable a :

259

Objeto Recordset. Copia el registro activo de un objeto Recordset al bfer de copia para su posterior edicin. Sintaxis [Link] El recordset representa el nombre de un objeto Recordset abierto y que se puede actualizar que contiene el registro que desea modificar. Comentarios Una vez que utiliza el mtodo Edit, los cambios realizados en los campos del registro activo son copiados al bfer de copia. Despus de realizar los cambios deseados en el registro, utilice el mtodo Update para guardar los cambios. El registro activo permanece activo despus de utilizar el mtodo Edit. Precaucin Si modifica un registro y a continuacin pasa a otro registro sin utilizar antes Update, los cambios se perdern sin previo aviso. Adems, si cierra recordset o finaliza el procedimiento que declara el Recordset o el objeto Database o Connection, el registro modificado se descarta sin previo aviso. La utilizacin de Edit produce un error bajo las siguientes condiciones: No hay ningn registro activo. El objeto Database o Recordset se abri de slo lectura. No hay campos que se pueden actualizar en el registro. El objeto Database o Recordset se abri para uso en modo exclusivo por otro usuario (espacio de trabajo Microsoft Jet).

Nota Para agregar, modificar o eliminar un registro, debe tener un ndice nico en el registro en el origen de datos de base. Si no es as, se producir un error "Permiso denegado" en la llamada al mtodo AddNew, Delete o Edit en un espacio de trabajo Microsoft Jet, o se producir un error "Argumento no vlido" el la llamada al mtodo Update en un espacio de trabajo ODBCDirect. Ejemplo de mtodo Edit Se necesita asignar la zona 1 a todos los registros de la tabla Agenda (dentro de la base de datos Clientes) cuyos cdigos de Clientes sean menores a 20. Private Sub cmdAgregar_Click () Dim wsp as WorkSpace Dim Base as Database Dim Agenda as Recordset Set wsp = [Link](0) trabajo Seteo el espacio de Dimensiono las variables

260

Set Base = [Link] ([Link])

Abro la base de Datos

Set Agenda = [Link](SELECT * FROM Agenda WHERE [Link] < 20) Abro el Recordset If Not [Link] [Link] Do While Not [Link] [Link] Agenda!Zona = 1 [Link] [Link] registro Loop End If [Link] [Link] [Link] End Sub Cierro el Recordset Cierro la base de Datos Cierro el espacio de trabajo me desplazo al siguiente si encontr algn registro me muevo al primer registro mientras no sea fin de archivo Edito el registro

14.10- Hide
Aplicable a: Objeto Form. Oculta un objeto Form pero no lo descarga. Sintaxis [Link] El marcador de posicin objeto representa una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. Si se omite objeto, se supone que objeto es el formulario que tenga el enfoque. Comentarios Cuando se oculta un formulario, se quita de la pantalla y su propiedad Visible queda establecida a False. Los controles de un formulario oculto no son accesibles para el usuario, pero estn

261

disponibles para la aplicacin de Visual Basic en ejecucin y para otros procesos que se estn comunicando con la aplicacin mediante DDE, as como para los eventos del control Timer. Cuando se oculta un formulario, el usuario no puede interactuar con la aplicacin hasta que el cdigo del procedimiento de evento que ha provocado la ocultacin del formulario haya terminado de ejecutarse. Si el formulario no est cargado cuando se llama al mtodo Hide, el mtodo Hide carga el formulario pero no lo presenta. Ejemplo del mtodo Hide Este ejemplo utiliza el mtodo Hide para ocultar un formulario. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario, y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Msg Hide ' Declara variable. ' Oculta el formulario.

formulario."

Msg = "Haga clic en Aceptar para que vuelva a aparecer el

MsgBox Msg Show End Sub

' Muestra el mensaje.

' Muestra de nuevo el formulario.

14.11-MoveFirst - MoveLast - MoveNext MovePrevious (Objeto Recordset)


Aplicable a: Objeto Recordset. Mueven al registro primero, ltimo, siguiente o anterior de un objeto Recordset y lo convierten en el registro activo. Sintaxis recordset.{MoveFirst | MoveLast [dbRunAsync] | MoveNext | MovePrevious} El marcador de posicin recordset es una variable de objeto que representa un objeto Recordset abierto. Comentarios Precaucin Si modifica el registro activo, utilice el mtodo Update para guardar los cambios antes de ir a otro registro. Si va a otro registro sin actualizar, los cambios se perdern sin previo aviso.

262

Al abrir un Recordset, el primer registro est activo y la propiedad BOF es False. Si el Recordset no contiene registros la propiedad BOF es True y no habr ningn registro activo. Si el primer o el ltimo registro est activo cuando utiliza MoveFirst o MoveLast, el registro activo no cambia. Si utiliza MovePrevious cuando el primer registro est activo, la propiedad BOF es True y no habr ningn registro activo. Si vuelve a utilizar MovePrevious se producir un error y BOF ser True. Si utiliza MoveNext cuando el ltimo registro est activo, la propiedad EOF es True y no habr ningn registro activo. Si vuelve a utilizar MoveNext se producir un error y EOF ser True. Si recordset hace referencia a un objeto Recordset de tipo Table (slo espacios de trabajo Microsoft Jet), el movimiento seguir el ndice activo. Puede establecer el ndice activo utilizando la propiedad Index. Si no establece el ndice activo, el orden de los registros devueltos no estar definido. Importante Puede utilizar el mtodo MoveLast para llenar completamente un objeto Recordset de tipo Dynaset o Snapshot para obtener el nmero de registros activos en el Recordset. Sin embargo, si utiliza MoveLast puede hacer ms lentas sus aplicaciones. Slo debe utilizar MoveLast para obtener un total de registros si es absolutamente necesario obtener un total exacto en un Recordset abierto recientemente. No puede utilizar los mtodos MoveFirst, MoveLast y MovePrevious en un Recordset de tipo Forward-only. Para mover la posicin del registro activo en un objeto Recordset un nmero especfico de registros hacia adelante o hacia atrs, utilice el mtodo Move. Ejemplo de mtodos MoveFirst, MoveLast, MoveNext, MovePrevious Para un ejemplo de uso de los mtodos MoveFirst y MoveNext, mire el ejemplo del mtodo Edit. Se necesita asignar la zona 1 a todos los registros de la tabla Agenda (dentro de la base de datos Clientes) cuyos cdigos de Clientes sean menores a 20. Es necesario recorrer la tabla de atrs hacia adelante. Private Sub cmdAgregar_Click () Dim wsp as WorkSpace Dim Base as Database Dim Agenda as Recordset Set wsp = [Link](0) trabajo Set Base = [Link] ([Link]) Seteo el espacio de Dimensiono las variables

Abro la base de Datos

Set Agenda = [Link](SELECT * FROM Agenda WHERE [Link] < 20) Abro el Recordset

263

If Not [Link] [Link] Do While Not [Link] archivo [Link] Agenda!Zona = 1 [Link] [Link] anterior Loop End If [Link] [Link] [Link] End Sub

si encontr algn registro me muevo al ltimo registro mientras no sea principio de

Edito el registro

me desplazo al registro

Cierro el Recordset Cierro la base de Datos Cierro el espacio de trabajo

14.12- OpenDatabase (Objeto Workspace)


Aplicable a: Objeto DBEngine, Objeto Workspace. Abre una base de datos especificada en un objeto Workspace y devuelve una referencia al objeto Database que la representa. Sintaxis Set basededatos = [Link] (nombrebasededatos, opciones, slolectura, conexin) La sintaxis del mtodo OpenDatabase consta de las siguientes partes. Argumento basededatos Descripcin Una variable de objeto que representa el objeto Database que va a abrir.

264

espaciodetrabajo existente que

Opcional. Una variable de objeto que representa el objeto Workspace

contendr la base de datos. Si no incluye un valor para espaciodetrabajo, OpenDatabase utiliza el espacio de trabajo predeterminado. Nombrebasededatos Microsoft Jet Un tipo de datos String que es el nombre de un archivo de base de datos

existente o el nombre del origen de datos (DSN) de un origen de datos ODBC existente. opciones base de Opcional. Un tipo de datos Variant que establece varias opciones para la

datos, como se especifica en Valores. slolectura desea Opcional. Un valor de tipo de datos Variant (subtipo Boolean) que es True si

abrir la base de datos con acceso de slo lectura o False (predeterminado) si desea abrir la base de datos con acceso de lectura/escritura. conexin Opcional. Un tipo de datos Variant (subtipo String) que especifica informacin variada sobre la conexin, incluyendo las contraseas. Valores Para los espacios de trabajo Microsoft Jet, puede utilizar los siguientes valores para el argumento opciones: Valor True False Descripcin Abre la base de datos en modo exclusivo. (Predeterminado) Abre la base de datos en modo compartido.

Comentarios Cuando abre una base de datos, automticamente se agrega a la coleccin Databases. Estas son algunas consideraciones que debe aplicar cuando utilice nombrebasededatos:

265

Si hace referencia a una base de datos que ya est abierta para acceso en modo exclusivo por otro usuario, se produce un error. Si no hace referencia a una base de datos existente, se produce un error.

El argumento conexin se expresa en dos partes: el tipo de base de datos, seguido por punto y coma (;) y los argumentos opcionales. Primero debe proporcionar el tipo de base de datos, como "ODBC;" o "FoxPro 2.5;". A continuacin, os argumentos opcionales sin un orden concreto, separados por punto y coma. Uno de los parmetros puede ser la contrasea (si hay alguna asignada). Por ejemplo: "FoxPro 2.5; pwd=micontrasea" Para cerrar una base de datos y, de este modo, quitar el objeto Database de la coleccin Databases, utilice el mtodo Close en el objeto . Ejemplo mtodo OpenDatabase Es vlido el mismo ejemplo utilizado para los mtodos MoveFirst, MoveLast, MoveNext, MovePrevious.

14.13- OpenRecordset (Objeto Database)


Aplicable a: Objeto Database. Crea un nuevo objeto Recordset y lo aade a la coleccin Recordsets. Sintaxis Set variable = [Link] (origen, tipo, opciones, bloquearmodificaciones) La sintaxis del mtodo OpenRecordset consta de las siguientes partes. Argumento variable que desea abrir. Objeto desea crear Descripcin Una variable de objeto que representa el objeto Recordset

Una variable de objeto que representa un objeto existente desde el que

el objeto Recordset nuevo. Origen nuevo Un tipo de datos String que especifica el origen de los registros para el

Recordset. El origen puede ser un nombre de tabla, un nombre de consulta o una instruccin SQL que devuelve registros.

266

Tipo como se

Opcional. Una constante que indica el tipo de objeto Recordset a abrir,

especifica en Valores. Opciones caractersticas del Opcional. Una combinacin de constantes que especifican las

objeto Recordset nuevo, como se especifica en Valores. Bloquearmodificaciones Recordset, Opcional. Una constante que determina el bloqueo para el objeto

como se especifica en Valores. Valores Puede utilizar una de las siguientes constantes para el argumento tipo. Constante dbOpenTable Microsoft Jet). dbOpenDynaset DbOpenSnapshot DbOpenForwardOnly Descripcin Abre un objeto Recordset de tipo Table (slo espacios de trabajo

Abre un objeto Recordset de tipo Dynaset (actualizable). Abre un objeto Recordset de tipo Snapshot (slo lectura) Abre un objeto Recordset de tipo Forward-only.

Nota Si abre un objeto Recordset en un espacio de trabajo Microsoft Jet y no especifica un tipo, el mtodo OpenRecordset crea una objeto Recordset de tipo Table, si es posible. Si especifica una tabla vinculada o una consulta, el mtodo OpenRecordset crea un objeto [Link] tipo Dynaset. Puede utilizar una combinacin de las siguientes constantes para el argumento opciones: -DbAppendOnly: Permite al usuario anexar registros nuevos al objeto Recordset, pero impide la modificacin o eliminacin de registros existentes (slo objetos Recordset de tipo Dynaset de Microsoft Jet). -DbSeeChanges: Genera un error en tiempo de ejecucin si otro usuario est cambiando los datos que usted est modificando.(Slo en objetos Recordset de tipo Snapshot de Microsoft Jet). Esto es til en aplicaciones donde varios usuarios tiene acceso de lectura/escritura simultneo a los mismos datos. -DbDenyWrite: Previene que otros usuarios puedan modificar o agregar registros (slo objetos Recordset de Microsoft Jet). -DbDenyRead: Previene que otros usuarios puedan leer datos de una tabla (slo objetos Recordset de tipo Table de Microsoft Jet).

267

-DbForwardOnly: Crea un objeto Recordset de tipo Forward-only (slo objetos Recordset de tipo Snapshot de Microsoft Jet). Se proporciona slo para compatibilidad con versiones anteriores y debe utilizar la constante dbOpenForwardOnly en el argumento tipo en vez de utilizar esta opcin. -DbReadOnly : Previene que otros usuarios puedan hacer cambios el objeto Recordset (slo Microsoft Jet). La constante dbReadOnly en el argumento bloquearmodificaciones reemplaza esta opcin, la cual se proporciona para compatibilidad con versiones anteriores. -dbInconsistent : Permite actualizaciones inconsistentes (slo objetos Recordset de tipo Dynaset de Microsoft Jet). -DbConsistent : Permite slo actualizaciones consistentes (slo objetos Recordset de tipo Dynaset de Microsoft Jet). Nota Las constantes dbConsistent y dbInconsistent se excluyen mutuamente y el uso de ambos produce un error. Proporcionar un argumento bloquearmodificaciones cuando el argumento opciones utiliza la constante dbReadOnly tambin produce un error. Puede utilizar las siguientes constantes para el argumento bloquearmodificaciones:. -dbReadOnly: Previene que los usuarios hagan cambios al Recordset. Puede utilizar dbReadOnly en el argumento opciones o en el argumento bloquearmodificaciones, pero nunca en ambos. Si lo utiliza en ambos argumentos, se produce un error en tiempo de ejecucin. -DbPessimistic: Utiliza el bloqueo pesimista para determinar cmo se pueden hacer cambios al objeto Recordset en un entorno multiusuario. La pgina que contiene el registro que est modificando est bloqueada mientras utiliza el mtodo Edit (predeterminado en espacios de trabajo Microsoft Jet). -DbOptimistic: Utiliza el bloqueo optimista para determinar cmo se pueden hacer cambios al objeto Recordset en un entorno multiusuario. La pgina que contiene el registro que est modificando est bloqueada mientras se ejecuta el mtodo Update. Comentarios En un espacio de trabajo Microsoft Jet, si objeto hace referencia a un objeto QueryDef o Recordset de tipo Dynaset o Snapshot o si origen hace referencia a una instruccin SQL o un TableDef que representa una tabla adjunta, no podr utilizar dbOpenTable para el argumento tipo y si lo hace, se producir un error interceptable. Si objeto hace referencia a un Recordset de tipo Dynaset o Snapshot, el Recordset nuevo es del mismo tipo objeto. Si objeto hace referencia a un objeto Recordset de tipo Table, el tipo del objeto nuevo es un objeto Recordset de tipo Dynaset. No puede abrir objetos Recordset nuevos desde objetos Recordset de tipo Forward-only. Utilice la constante dbSeeChanges en espacio de trabajo Microsoft Jet si desea captar los cambios realizados mientras dos o ms usuarios estn modificando o eliminando el mismo registro. Por ejemplo, si dos usuarios empiezan a modificar el mismo registro, el primer usuario que ejecute el mtodo Update consigue realizar la operacin. Cuando el segundo usuario ejecute el mtodo Update ocurre un error de tiempo de ejecucin. Del mismo modo, si el segundo usuario intenta utilizar el mtodo Delete para eliminar un registro y el primer usuario ha cambiado ya el mismo, se produce un error de tiempo de ejecucin.

268

En general, si al usuario se le presenta este error mientras est actualizando, su cdigo debe actualizar el contenido de los campos y leer los valores recientemente modificados. Si se produce el error durante el proceso de eliminacin, el cdigo puede mostrar al usuario los nuevos datos del registro junto con un mensaje que indica que se han modificado recientemente los datos. En este momento, el cdigo puede solicitar una confirmacin de que el usuario desea an eliminar el registro. Al cerrar un Recordset utilizando el mtodo Close, se eliminar automticamente de la coleccin Recordsets. Ejemplo del mtodo OpenRecordset Es vlido el mismo ejemplo utilizado para los mtodos MoveFirst, MoveLast, MoveNext, MovePrevious.

14.14- RemoveItem
Aplicable a: Control ComboBox, Control ListBox. Quita un elemento de un control ListBox o ComboBox. No acepta argumentos con nombre. Sintaxis [Link] ndice La sintaxis del mtodo RemoveItem consta de las siguientes partes: Parte Descripcin

objeto Requerido. Una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. ndice Requerido. Un entero que especifica la posicin dentro del objeto del elemento o la fila que se va a quitar. Para los primeros elementos de los controles ListBox o ComboBox, ndice es 0. Comentarios Los controles ListBox o ComboBox que estn enlazados a un control Data no aceptan el mtodo RemoveItem. Ejemplo del mtodo RemoveItem Este ejemplo utiliza el mtodo RemoveItem para quitar entradas de un cuadro de lista. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario que contenga un control ListBox llamado List1, y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Entry, I, Msg ' Declara variables.

269

Msg = "Haga clic en Aceptar para agregar 100 elementos al cuadro de lista." MsgBox Msg For I = 1 To 100 ' Muestra el mensaje. ' Cuenta de 1 a 100. ' Crea la

Entry = "Entrada " & I entrada. [Link] Entry entrada. Next I

' Agrega la

entradas."

Msg = "Haga clic en Aceptar para quitar una de cada dos

MsgBox Msg For I = 1 To 50

' Muestra el mensaje. ' Determina cmo quitar [Link] I ' uno de

cada dos Next I

' elementos.

Msg = "Haga clic en Aceptar para quitar todos los elementos del cuadro de lista." MsgBox Msg [Link] End Sub ' Muestra el mensaje. ' Borra el cuadro de lista.

14.15- RepairDatabase (Objeto DBEngine)


Aplicable a: Objeto DBEngine. Intenta reparar una base de datos daada que accede a base de datos Microsoft Jet. Sintaxis [Link] nombrebasededatos El argumento nombrebasededatos representa un tipo de datos String que es la ruta de acceso y el nombre de un archivo de base de datos del motor Microsoft Jet existente. Si se omite la ruta, slo se buscar en el directorio activo.

270

Comentarios Debe cerrar la base de datos especificada por nombrebasededatos antes de repararla. En un entorno multiusuario, los dems usuarios no podrn tener abierto nombrebasededatos mientras usted la repara. Si no est cerrado nombrebasededatos o no est disponible para uso exclusivo, se producir un error. Este mtodo intenta reparar una base de datos marcada como posiblemente daada por una operacin de escritura incompleta. Esto puede ocurrir si una aplicacin que utiliza el motor de base de datos Microsoft Jet termina inesperadamente debido a un corte en el suministro elctrico o un problema de hardware. La base de datos no se marcar como posiblemente daada si utiliza el mtodo Close o si sale de la aplicacin de una manera normal. El mtodo RepairDatabase tambin intenta validar todas las tablas del sistema y todos los ndices. Se descartan los datos que no se puedan reparar. Si no se puede reparar la base de datos, se produce un error interceptable. Cuando intente abrir o compactar una base de datos daada, normalmente se producir un error interceptable. En algunas situaciones, sin embargo, puede que no se detecte una base de datos daada y no se produzca ningn error. Es conveniente ofrecer a los usuarios un mtodo de ejecutar el mtodo RepairDatabase en su aplicacin, si la base de datos se comporta de manera impredecible. Algunos tipos de bases de datos se pueden daar si un usuario termina una aplicacin sin cerrar los objetos Database o Recordset y el motor de base de datos Microsoft Jet, Microsoft Windows no tienen la oportunidad de vaciar las memorias de cach de datos. Para evitar que se daen las bases de datos, establezca procedimientos para cerrar las aplicaciones y apagar los sistemas que aseguren que todas las pginas de la memoria cach estn guardadas en la base de datos. En algunos casos, puede que sean necesarias fuentes de alimentacin ininterrumpida para evitar prdidas de datos por las fluctuaciones del suministro elctrico. Nota Despus de reparar una base de datos, tambin es conveniente compactar la misma utilizando el mtodo CompactDatabase para defragmentar el archivo y recuperar espacio en disco. Ejemplo del mtodo RepairDatabase Este ejemplo intenta reparar la base de datos llamada [Link]. Sub RepairDatabaseX() Dim errBucle As Error If MsgBox("Desea reparar la base de datos Neptuno?", vbYesNo) = vbYes Then [Link] "[Link]" MsgBox "Fin del procedimiento reparar!" End If

271

End Sub

14.16- SetFocus
Aplicable a Control CheckBox, Control ComboBox, Control CommandButton, Objeto Form Controles HScrollBar y VScrollBar, Control ListBoxControl OptionButton, Control PictureBox, Control TextBox. Mueve el enfoque al control o formulario especificado. Sintaxis [Link] El marcador de posicin objeto representa una expresin de objeto que da como resultado un objeto de la lista Aplicable a. Comentarios El objeto debe ser un objeto Form o un control que pueda recibir el enfoque. Despus de invocar el mtodo SetFocus, cualquier entrada del usuario se dirige al formulario o al control especificado. El enfoque slo se puede mover a un formulario o un control visible. Como un formulario y los controles de un formulario no son visibles hasta que el evento Load del formulario ha terminado, no puede usar en su propio evento Load el mtodo SetFocus para mover el enfoque al formulario que se est cargando a menos que use primero el mtodo Show para mostrar el formulario antes de que el procedimiento de evento Form_Load haya terminado. Tampoco puede mover el enfoque a un formulario o un control si su propiedad Enabled es False. Si la propiedad Enabled se ha establecido a False en tiempo de diseo, primero debe establecerla a True antes de poder recibir el enfoque mediante el mtodo SetFocus. Ejemplo del mtodo SetFocus Al hacer click en un botn de comando, setea el foco a la caja de texto txtCodigo Private Sub cmd1_Click() [Link] End Sub

14.17- Show
Aplicable a: Objeto Form. Sintaxis

272

[Link] estilo, formulario_propietario La sintaxis del mtodo Show consta de las siguientes partes: Parte Descripcin

objeto Opcional. Una expresin de objeto cuyo resultado es un objeto de la lista Aplicable a. Si se omite objeto, se supone que objeto es el formulario asociado con el mdulo de formulario activo. estilo Opcional. Un entero que determina si el formulario es modal o no modal. Si estilo es 0, el formulario es no modal; si estilo es 1, el formulario es modal. formulario_propietario Opcional. Una expresin de cadena que especifica el componente que "posee" el formulario que se muestra. Para los formularios estndar de Visual Basic, utilice la palabra clave Me. Comentarios Si el formulario especificado no est cargado cuando se invoca el mtodo Show, Visual Basic lo carga automticamente. Cuando Show presenta un formulario no modal, contina con la ejecucin del cdigo que haya a continuacin. Cuando Show presenta un formulario modal, el cdigo que hay a continuacin no se ejecuta hasta que el formulario se oculta o se descarga. Cuando Show presenta un formulario modal, no hay entradas (de teclado o del mouse) excepto sobre los objetos del formulario modal. El programa debe ocultar o descargar los formularios modales (normalmente como respuesta a alguna accin del usuario) antes de que pueda producirse la entrada en otro formulario. Aunque los dems formularios de la aplicacin estn deshabilitados cuando se presenta un formulario modal, los de las dems aplicaciones no lo estn. El formulario inicial de una aplicacin se muestra automticamente despus de invocar su evento Load. Ejemplo del mtodo Show Este ejemplo utiliza el mtodo Show para mostrar un formulario oculto. Para probar este ejemplo, pegue el cdigo en la seccin Declaraciones de un formulario y despus presione F5 y haga clic en el formulario. Private Sub Form_Click () Dim Msg Hide ' Declara variable. ' Oculta el formulario.

Msg = "Haga clic en Aceptar para que vuelva a aparecer el formulario."

273

MsgBox Msg Show End Sub

' Muestra el mensaje. ' Muestra de nuevo el formulario.

14.18- Update (Objeto recordset)


Aplicable a Objeto Recordset. Guarda el contenido del bfer de copia en un objeto Recordset de tipo Dynaset o Table especificado. Sintaxis [Link] (tipo, obligar ) La sintaxis del mtodo Update tiene las siguientes partes. Parte Descripcin Una variable de objeto que representa un objeto Recordset abierto que se puede

Recordset actualizar. Tipo Valores

Opcional. Una constante que indica el tipo de actualizacin,