You are on page 1of 197

PROGRAMACION DE COMPUTADORAS (VER 1.

00)

NOTAS

presenta Dr. Flix Caldern Solorio e o

Universidad Michoacana de San Nicols de Hidalgo a Agosto 2005

Contenido
Contenido . . . . . . Lista de Figuras . . Lista de Tablas . . . Lista de Algoritmos Lista de S mbolos . . Lista de Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii . vii . ix . xi . xiii . xv 1 1 3 3 3 5 5 7 9 9 12 12 13 14 14 16 16 16 17 17 18 18 20

1. Introduccin a los lenguajes de programacin C y Java o o 1.1. Programacin utilizando diagramas de bloque y/o metalenguajes o 1.1.1. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.2. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Caracter sticas de los lenguajes C y Java; diferencias y similitudes 1.3. Compilacin de archivos fuente . . . . . . . . . . . . . . . . . . . . o 1.3.1. Compilacin . . . . . . . . . . . . . . . . . . . . . . . . . . o 1.3.2. Ejemplo del programa Hola Mundo . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

2. Tipos de datos, operadores y expresiones 2.1. Tipos de datos, rango y operaciones validas . . . . . . . . . . . . . . . . . . 2.2. Operadores y expresiones; aritmticos, lgicos, a nivel de bits y de asignacin e o o 2.2.1. Operaciones aritmticas bsicas . . . . . . . . . . . . . . . . . . . . . e a 2.2.2. Incremento y asignaciones abreviadas . . . . . . . . . . . . . . . . . 2.2.3. Operaciones a nivel de bits . . . . . . . . . . . . . . . . . . . . . . . 2.2.4. Operadores relacionales . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.5. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3. Precedencia de los operadores. Literales, constantes y variables . . . . . . . 2.3.1. Precedencia de operadores . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2. Literales, Constantes y variable . . . . . . . . . . . . . . . . . . . . . 2.4. Instrucciones secuenciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1. Calculo de reas y volmenes de guras geomtricas regulares . . . . a u e 2.5.2. Ley de ohm y Anlisis bsico de transistores . . . . . . . . . . . . . a a iii

iv

Contenido

3. Entrada y salida por consola 3.1. Entrada salida en C . . . . . 3.1.1. Funcin prinft . . . . o 3.1.2. Funcin scanf . . . . . o 3.1.3. Funcin getch . . . . . o 3.1.4. Instruccin gets . . . . o 3.1.5. clase cout . . . . . . . 3.2. Entrada salida en Java . . . . 3.2.1. La clase Leer . . . . . 3.3. Ejemplos . . . . . . . . . . . 3.3.1. Calculo de Areas . . . 3.3.2. Ley de Ohm y Anlisis a

. . . . . . . . . . . . . . . . . . . . de

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . transistores

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

23 23 23 25 27 27 28 30 32 33 33 35 37 37 41 43 45 48 49 51 51 52 53 54 57 57 58 59 59 61 65 68 69 71 72 74 74 76 78

4. Instrucciones condicionales y de repeticin o 4.1. Sentencias if-else, escalera if-else y switch . . . . . . . . . 4.1.1. Ejemplo de solucin de una ecuacin cuadrtica . . o o a 4.1.2. Ejemplo de tipos de tringulos . . . . . . . . . . . a 4.2. Instrucciones de repeticin for, while, do-while, continue y o 4.2.1. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . 4.3. Ejemplo de sucesiones e Iteracin de punto jo . . . . . . o 4.3.1. Mtodos iterativos para resolver x = g(x) . . . . . e 4.3.2. Mtodos de punto jo . . . . . . . . . . . . . . . . e 4.3.3. Solucin de Sistemas no lineales . . . . . . . . . . o 4.4. Control de ujo incondicional. Sentencia go-to . . . . . . . 5. Funciones y la estructura de programacin o 5.1. Funciones y estructura de programacin en C. . . . . . o 5.1.1. Ejemplo de la funcin cuadrado . . . . . . . . . o 5.1.2. Prototipos de funcin . . . . . . . . . . . . . . o 5.1.3. Ejemplo de la funcin mximo . . . . . . . . . o a 5.2. Mtodos, clases y estructura de programacin en Java e o 5.2.1. Programacin modular y Java . . . . . . . . . . o 5.3. Ejemplo programacin modular Java C . . . . . . . . o 5.3.1. Implementacin en Java . . . . . . . . . . . . . o 5.3.2. Implementacin en C . . . . . . . . . . . . . . o 5.4. Recursividad . . . . . . . . . . . . . . . . . . . . . . . 5.5. Ejemplos de programas recursivos . . . . . . . . . . . . 5.5.1. mtodo de bisecciones . . . . . . . . . . . . . . e 5.5.2. Torres de Hanoi . . . . . . . . . . . . . . . . . 5.5.3. Algoritmo de quicksort . . . . . . . . . . . . . .

. . . . . . . . . . . . break . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

Contenido

6. Apuntadores y arreglos 6.1. Manejo de matrices y vectores . . . . . . . . . . . . . . 6.1.1. Los vectores . . . . . . . . . . . . . . . . . . . . 6.1.2. Matrices . . . . . . . . . . . . . . . . . . . . . . 6.1.3. Ejemplo . . . . . . . . . . . . . . . . . . . . . . 6.1.4. Ejemplo . . . . . . . . . . . . . . . . . . . . . . 6.2. Cadena de Texto . . . . . . . . . . . . . . . . . . . . . 6.2.1. En Java . . . . . . . . . . . . . . . . . . . . . . 6.2.2. En C . . . . . . . . . . . . . . . . . . . . . . . . 6.2.3. Manejo de cadenas <string.h> . . . . . . . . . 6.3. Apuntadores en C . . . . . . . . . . . . . . . . . . . . 6.3.1. Apuntadores y arreglos . . . . . . . . . . . . . 6.3.2. Aritmtica de apuntadores . . . . . . . . . . . e 6.3.3. Parmetros por valor y por referencia . . . . . a 6.3.4. Ejemplo de paso por referencia . . . . . . . . . 6.4. Matrices, Operaciones bsicas . . . . . . . . . . . . . . a 6.4.1. Suma de matrices . . . . . . . . . . . . . . . . 6.4.2. Resta de matrices . . . . . . . . . . . . . . . . 6.4.3. Multiplicacin de matrices . . . . . . . . . . . . o 6.4.4. Solucin de sistemas de ecuaciones triangulares o 6.4.5. Solucin de sistemas lineales de ecuaciones por o nacin Gaussiana . . . . . . . . . . . . . . . . . o 6.5. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . 7. Estructuras 7.1. Estructuras en C . . . . . . . . . . . . . . 7.1.1. Ejemplo de manejo de estructuras 7.1.2. Arreglos de Estructuras . . . . . . 7.1.3. Estructuras Anidadas . . . . . . . 7.2. Uniones en C . . . . . . . . . . . . . . . . 8. Programacin orientada a objetos o 8.1. Caracter sticas de los Objetos . . . . 8.1.1. Identidad del Objeto . . . . . 8.1.2. Clasicacin . . . . . . . . . o 8.1.3. Encapsulacin y ocultamiento o 8.1.4. Mantenibilidad . . . . . . . . 8.1.5. Reusabilidad . . . . . . . . . 8.1.6. Polimorsmo . . . . . . . . . 8.1.7. Herencia . . . . . . . . . . . . 8.2. Ejemplo de la clase complejo . . . . 8.2.1. En Java . . . . . . . . . . . . 8.2.2. En C . . . . . . . . . . . . . . 8.3. La clase matriz . . . . . . . . . . . . 8.3.1. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . el mtodo e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . de . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Elimi. . . . . . . . . . . . . . . . . . . . . . . . . . . .

81 81 81 85 86 87 89 89 93 93 98 100 102 104 104 106 106 107 107 107 108 116 121 121 122 123 124 126 129 130 130 131 131 133 133 134 135 136 136 138 142 145

. . . . . . . . . . . . . . . . . . de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

vi

Contenido

8.3.2. Ejemplo en C . . . . . . . . . . . . . 8.4. Herencia . . . . . . . . . . . . . . . . . . . . 8.4.1. Clases y mtodos abstractos . . . . . e 8.4.2. Ejemplo de la Clase punto . . . . . . 8.4.3. Ejemplo de la clase complejo . . . . 8.4.4. Interfaces . . . . . . . . . . . . . . . 8.5. Applets . . . . . . . . . . . . . . . . . . . . 8.5.1. Ejemplo . . . . . . . . . . . . . . . . 8.5.2. Ejemplo que describe una interfaz de 9. Archivos 9.1. Archivos secuenciales 9.2. Archivos . . . . . . . 9.2.1. Separacin en o 9.2.2. Ejemplo . . . en C . . . . . . . . . . . . . . . chas (tokens) . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . entrada salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

146 146 148 149 150 152 153 159 160 163 163 169 170 171 173 173 177 181

10. Aplicaciones 10.1. solucin de circuitos elctricos . . . . . . . . . . . . . . . . . . . . . . . . . . o e 10.1.1. Formato Estndar de Pspice . . . . . . . . . . . . . . . . . . . . . . a Referencias

Lista de Figuras
2.1. Ejemplo de transistores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Ejemplo de plano inclinado. . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1. Ejemplo de visualizacin del Applet con appletviewer. . . . . . . . . . . . . o 8.2. Ejemplo de visualizacin del Applet con Netscape. . . . . . . . . . . . . . . o 8.3. Ejemplo de visualizacin del Applet con Internet Explorer . . . . . . . . . . o 20 22 157 158 158

vii

Lista de Tablas

ix

Lista de Algoritmos
1. 2. Algoritmo para sumar los nmeros del 1 al 10 . . . . . . . . . . . . . . . . . u Algoritmo para sumar los nmeros pares del 1 al 10 . . . . . . . . . . . . . u 3 4

xi

Lista de S mbolos
** ***

xiii

Lista de Tareas
Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea Tarea 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. ................................................. ................................................. ................................................. ................................................. ................................................. ................................................. ................................................. ................................................. ................................................. ................................................. 3 12 15 22 36 45 50 54 54 67 72 78 89 98 116 128 146 153 172

xv

Cap tulo 1

Introduccin a los lenguajes de o programacin C y Java o


1.1. Programacin utilizando diagramas de bloque y/o meta o lenguajes
Algunas estructuras bsicas que podemos ver en la mayor de los lenguajes son: a a condicionales, sentencias de repeticin y funciones. A continuacin haremos una denicin o o o de las mismas que nos ayudaran a entender como realizar un programa Una sentencia condicional la podemos escribir como Si (condicin se cumple) entonces o { realizar tarea1 } Si no { realizar tarea2 } Una sentencia de repeticin, la cual esta sujeta al cumplimiento de una condicin o o especica es 1

Cap tulo 1: Introduccin a los lenguajes de programacin C y Java o o

Mientras (condicin se cumple) o { realizar tarea2 } Esta repeticin tambin podr llevarse de la siguiente manera. o e a Repetir { realizar tarea2 } Mientras (condicin se cumple) o A diferencia de la anterior este bloque se ejecutar al menos una sola vez, ya que a primero se realiza la tarea y despus se pregunta por la condicin. e o Otra manera de implementar una sentencia de repeticin es haciendo una estruco tura que repita, un nmero de veces jo, una tarea especica as u Para (x = 1, 2, 3, ... 10) { realizar tarea }

Finalmente podemos hacer conjuntos de estas funciones de tal forma que realicen una tarea especica. Este tipo de sentencias es una funcin la cual podemos denir como o nombre (variables necesarias) { grupo de sentencias 1 grupo de sentencias 2 ... }

1.2. Caracter sticas de los lenguajes C y Java; diferencias y similitudes

1.1.1.

Ejemplo
Hacer una funcin que sumar los nmeros del 1 al 10. El algoritmo resultante se o u

presenta en (algoritmo 1). Algoritmo 1 Algoritmo para sumar los nmeros del 1 al 10 u

Sumador() 1 2 3 4 5 6 7 8 x1 suma 0 mientras (x < 11) { suma suma + x x x+1 } regresar suma

1.1.2.

Ejemplo
Hacer una funcin que sume los nmeros pares de a a b. o u

Tarea 1 Hacer un algoritmo para multiplicar Recordando que la multiplicacin es una suma abreviada hacer un algoritmo que reciba x o y y y regrese la multiplicacin de estos. Solamente utilice sumas y sentencias de repeticin o o

1.2.

Caracter sticas de los lenguajes C y Java; diferencias y similitudes


Caracter sticas de C

Cap tulo 1: Introduccin a los lenguajes de programacin C y Java o o

Algoritmo 2 Algoritmo para sumar los nmeros pares del 1 al 10 u

Sumador Par(a, b) 1 xa 2 suma 0 3 mientras (x <= b) 4 5 6 7 8 9 10 xx+1 } regresar suma { si EsP ar(x) entonces suma suma + x

C es un lenguaje estructurado de nivel medio, ni de bajo nivel como ensamblador, ni de alto nivel. Esto permite una mayor exibilidad y potencia, a cambio de menor abstraccin. o No se trata de un lenguaje fuertemente tipado, lo que signica que se permite casi cualquier conversin de tipos. No es necesario que los tipos sean exactamente iguales para o poder hacer conversiones, basta con que sean parecidos. No lleva a cabo comprobacin de errores en tiempo de ejecucin, por ejemplo no o o se comprueba que no se sobrepasen los l mites de los arreglos. El programador es el unico responsable de llevar a cabo esas comprobaciones. Tiene un reducido numero de palabras clave, unas 32. C dispone de una biblioteca estndar que contiene numerosas funciones y que a siempre est disponible, adems de las extensiones que proporcione cada compilador o a a entorno de desarrollo. En resumen, es un lenguaje muy exible, muy potente, muy popular, pero que no protege al programador de sus errores. Caracter sticas de Java

1.3. Compilacin de archivos fuente o

Java es un lenguaje de programacin de ordenadores, diseado como una mejora o n de C++, y desarrollado por Sun Microsystems. (Nota: Para ms informacin sobre Sun, a o puede consultar su pgina Web: www.sun.com) a Hay varias hiptesis sobre su origen, aunque la ms difundida dice que se cre para o a o ser utilizado en la programacin de aparatos electrodomsticos (desde microondas hasta o e televisores interactivos). De ah evolucion (parece ser que porque el proyecto inicial no o acab de funcionar) hasta convertirse en un lenguaje orientado a Internet. o Pero su campo de aplicacin no es exclusivamente Internet: una de las grandes veno tajas de Java es que se procura que sea totalmente independiente del hardware: existe una mquina virtual Javapara varios tipos de ordenadores. Un programa en Java podr funa a cionar en cualquier ordenador para el que exista dicha mquina virtual Java(hoy en d es a a el caso de los ordenadores equipados con los sistemas operativos Windows, Linux, Solaris y algn otro). A cambio, la existencia de ese paso intermedio hace que los programas Java no u sean tan rpidos como puede ser un programa realizado en C, C++ o Pascal y optimizado a para una cierta mquina en concreto. a Tiene varias caracter sticas que pueden sonar interesantes a quien ya es programador, y que ya ir conociendo poco a poco quien no lo sea: La sintaxis del lenguaje es muy a parecida a la de C++ y, al igual que ste ultimo, es un lenguaje orientado a objetos. Java e soporta el manejo de threads, excepciones, est preparado para la realizacin de aplicacioa o nes cliente/servidor, es independiente de la mquina, es ms able y seguro que C++ (no a a existen los punteros) y cada vez incorpora ms facilidades para la creacin y manipulacin a o o de grcos, para el acceso a bases de datos, etc. Buena parte de estas posibilidades las a iremos tratando ms adelante, cuando hayamos visto las ms bsicas. a a a

1.3.
1.3.1.

Compilacin de archivos fuente o


Compilacin o
Para ejecutar un cdigo desarrollado en cualquier lenguaje de programacin ser neo o a

cesario realizarlo en dos pasos. Primeramente deber ser traducido el cdigo original, al que a o llamaremos fuente, a un cdigo binario, que nalmente es el unico lenguaje que entiende o

Cap tulo 1: Introduccin a los lenguajes de programacin C y Java o o

la computadora. Despus de realizado esto, el cdigo podr ser ejecutado y presentar los e o a resultados. La manera de realizar este procedimiento cambia de lenguaje a Lenguaje. En seguida se presenta el proceso en Java y C++ Compilacin en Java o Dado un cdigo fuente con cualquier nombre y extensin java (nombre.java) la o o compilacin se realiza con el siguiente comando o javac nombre.java y la ejecucin o java nombre El proceso de compilacin crear un cdigo, que llamaremos objeto, el cual toma o a o el mismo nombre que la clase principal puesta en el programa fuente y crea un archivo nombre.class. Compilacin en C o Dado un cdigo fuente, que generalmente tendr extensin .cpp (nombre.cpp), el o a o proceso de compilacin se realiza como o g++ -o nombre nombre.cpp y la ejecucin es o ./nombre Donde -o indica al compilador el nombre del archivo ejecutable, si este es omitido, en su lugar se generar un archivo a.out. a En el caso de tener mas de un archivo, en comn que se creen proyectos los cuales u se compilan con la instruccin make y una archivo Makele debe ser creado. Dentro del o archivo Makele se especican los archivos fuente y el nombre del archivo de salida. Un ejemplo de un archivo Makele es como es que se muestra a continuacin. o

1.3. Compilacin de archivos fuente o

1.3.2.

Ejemplo del programa Hola Mundo


A continuacin se da un ejemplo sencillo para desplegar un letrero utilizando tanto o

Java como C. Java


/** * Title: Hola Mundo * Description: Programa para desplegar el letrero de Hola Mundo * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ class ej001 { public static void main (String args[]) { System.out.println("Hola Mundo"); } }

C
//ejemplo ec001.cpp /** * Title: Hola Mundo * Description: Programa para desplegar el letrero de Hola Mundo * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> void main () { printf("Hola Mundo \n"); return; }

Podemos notar lo siguiente: Que en Java se dene una clase con la palabra clave class, dado que Java exige que todo este orientado a objetos Que ambos requiere de una funcin principal la cual se denomina main o Que en C es siempre necesario incluir librer utilizando la palabra clave #include as stdio.h. En java cuando sea necesario se utiliza la palabra clave import. Que la funcin main en el caso de Java exige argumentos y en C es opcional. o

Cap tulo 2

Tipos de datos, operadores y expresiones


2.1. Tipos de datos, rango y operaciones validas
En nuestro primer ejemplo escrib amos un texto en pantalla, pero este texto estaba prejado dentro de nuestro programa. Esto no es lo habitual: normalmente los datos que maneje nuestro programa sern a el resultado de alguna operacin matemtica o de cualquier otro tipo. Por eso, necesitaremos o a un espacio en el que ir almacenando valores temporales y resultados. En casi cualquier lenguaje de programacin podremos reservar esos .espacios, y o asignarles un nombre con el que acceder a ellos. Esto es lo que se conoce como variables. Por ejemplo, si queremos que el usuario introduzca dos nmeros y el ordenador u calcule la suma de ambos nmeros y la muestre en pantalla, necesitar u amos el espacio para almacenar al menos esos dos nmeros iniciales (en principio, para la suma no ser u a imprescindible, porque podemos mostrarla en pantalla nada ms calcularla, sin almacenarla a previamente en ningn sitio). Los pasos a dar ser los siguientes: u an Pedir al usuario que introduzca un nmero. u Almacenar ese valor que introduzca el usuario (por ejemplo, en un espacio de memoria al que podr amos asignar el nombre primerNumero). 9

10

Cap tulo 2: Tipos de datos, operadores y expresiones

Pedir al usuario que introduzca otro nmero. u Almacenar el nuevo valor (por ejemplo, en otro espacio de memoria llamado segundoNumero) Mostrar en pantalla el resultado de sumar primerNumero y segundoNumero. Pues bien, en este programa estar amos empleando dos variables llamadas primerNumero y segundoNumero. Cada una de ellas ser un espacio de memoria capaz de a almacenar un nmero. u El espacio de memoria que hace falta reservarser distinto segn la precisin que a u o necesitemos para ese nmero, o segn lo grande que pueda llegar a ser dicho nmero. Por u u u eso, tenemos disponibles diferentes tipos de variables. Por ejemplo, si vamos a manejar nmeros sin decimales (nmeros enteros) de u u como mximo 9 cifras, nos interesar el tipo llamado a a nt(abreviatura de nteger, que es .entero.en ingls). Este tipo de datos consume un espacio de memoria de 4 bytes (1 Mb es e cerca de 1 milln de bytes). Si no necesitamos guardar datos tan grandes (por ejemplo, o si nuestros datos va a ser nmeros inferiores a 1.000), podemos emplear el tipo de datos u llamado short(entero corto). Los tipos de datos numricos disponibles en Java son los siguientes: e Admite decimales no no no no s s Valor min -128 -32768 -2147483648 -9223372036854775808 1.401298E-45 4.94065645841247E-324 Valor max 127 32767 2147483647 9223372036854775807 3.402823E38 1.79769313486232E308

Nombre byte short int long oat double

Presicin o 6-7 cifras 14-15 cifras

ocupa 1 byte 2 bytes 4 bytes 8 bytes 4 bytes 8 bytes

La forma de declararvariables de estos tipos es la siguiente:


int numeroEntero; // La variable numeroEntero ser un nmero de a u tipo "int" short distancia; // La variable distancia guardar a nmeros "short" long gastos; u // La variable gastos es de tipo "long" byte edad; // Un entero de valores "peque~os" float porcentaje; n // Con decimales, unas 6 cifras de precisin double numPrecision; // Con decimales y precisin de o o unas 14 cifras

2.1. Tipos de datos, rango y operaciones validas

11

(es decir, primero se indica el tipo de datos que guardar la variable y despus el a e nombre que queremos dar a la variable). Se pueden declarar varias variables del mismo tipo a la vez:
int primerNumero, segundoNumero; // Dos enteros

Y tambin se puede dar un valor a las variables a la vez que se declaran: e


int a = 5; short b=-1, c, d=4; // "a" es un entero, e inicialmente vale 5 // "b" vale -1, "c" vale 0, "d" vale 4

Los nombres de variables pueden contener letras y nmeros (y algn otro s u u mbolo, como el de subrayado, pero no podrn contener otros muchos s a mbolos, como los de las distintas operaciones matemticas posibles, ni podrn tener vocales acentuadas o ees). a a n Vamos a aplicarlo con un ejemplo sencillo en Java que sume dos nmeros: u
/* -------------------------------* * Introduccin a Java - Ejemplo * o * -------------------------------* * Fichero: suma.java * * (Suma dos nmeros enteros) u * * -------------------------------*/

class Suma2 { public static void main( String args[] ) { int primerNumero = 56; int segundoNumero = 23; // Dos enteros con valores prefijados

System.out.println( "La suma es:" ); // Muestro un mensaje de aviso System.out.println( primerNumero+segundoNumero ); // y el resultado de la operacin o } }

Hay una importante diferencia entre las dos rdenes println: la primera contiene o comillas, para indicar que ese texto debe aparecer tal cual, mientras que la segunda no contiene comillas, por lo que no se escribe el texto primerNumero+segundoNumero, sino que se intenta calcular el valor de esa expresin (en este caso, la suma de los valores que en o ese momento almacenan las variables primerNumero y segundoNumero, 56+23 = 89). Lo correcto habr sido que los datos no los hubiramos escrito nosotros en el a e programa, sino que fuera el usuario quien los hubiera introducido, pero esto es algo relativamente complejo cuando creamos programas en modo texto en Java (al menos, comparado

12

Cap tulo 2: Tipos de datos, operadores y expresiones

con otros lenguajes anteriores), y todav no tenemos los conocimientos sucientes para a crear programas en modo grco, as que ms adelante veremos cmo podr ser el usuario a a o a de nuestro programa el que introdujese los valores que desea sumar. Tenemos otros dos tipos bsicos de variables, que no son para datos numricos: a e char. Ser una letra del alfabeto, o un d a gito numrico, o un s e mbolo de puntuacin. o Ocupa 2 bytes. Sigue un estndar llamado Unicode (que a su vez engloba a otro estndar a a anterior llamado ASCII). boolean. se usa para evaluar condiciones, y puede tener el valor verdadero(true) o false(false). Ocupa 1 byte. Estos ocho tipos de datos son lo que se conoce como tipos de datos primitivos(porque forman parte del lenguaje estndar, y a a partir de ellos podremos crear otros ms complejos). a Nota para C y C++: estos tipos de datos son muy similares a los que se emplean en C y en C++, apenas con alguna pequeadiferencia, como es el hecho de que el tamao n n de cada tipo de datos (y los valores que puede almacenar) son independientes en Java del sistema que empleemos, cosa que no ocurre en C y C++, lenguajes en los que un valor de 40.000 puede ser vlido para un en unos sistemas, pero desbordar.el mximo valor a nt. a permitido en otros. Otra diferencia es que en Java no existen enteros sin signo (nsigned). u a Y otra ms es que el tipo boolean a est incorporado al lenguaje, en vez de corresponder a a un entero distinto de cero Tarea 2 Conversin de Tipos o Hacer una funcin que permita hacer el redondeo de un nmero otante a dos cifras signio u cativas.
2

2.2.

Operadores y expresiones; aritmticos, lgicos, a nivel e o de bits y de asignacin o

2.2.1.

Operaciones aritmticas bsicas e a


Hay varias operaciones matemticas que son frecuentes. Veremos cmo expresarlas a o

en Java y C, y tambin veremos otras operaciones menos frecuentes. Las ms comunes son: e a

2.2. Operadores y expresiones; aritmticos, lgicos, a nivel de bits y de asignacin e o o

13

Operacin matemtica S o a mbolo correspondiente Suma + Resta Multiplicacin o * Divisin o / Hemos visto un ejemplo de cmo calcular la suma de dos nmeros; las otras opeo u raciones se emplear de forma similar. an Otras operaciones matemticas menos habituales. Esas son las operaciones que a todo el mundo conoce, aunque no haya manejado ordenadores. Pero hay otras operaciones que son frecuentes en informtica y no tanto para quien no ha manejado ordenadores, pero a que aun as deber amos ver: Operacin o S mbolo Resto de la divisin % o El resto de la divisin tambin es una operacin conocida. Por ejemplo, si dividimos o e o 14 entre 3 obtenemos 4 como cociente y 2 como resto, de modo que el resultado de 14 % 3 ser 2. a

2.2.2.

Incremento y asignaciones abreviadas


Hay varias operaciones muy habituales , que tienen una sintaxis abreviada en Java

y C. Por ejemplo, para sumar 2 a una variable a, la forma normalde conseguirlo ser a: a = a + 2; pero existe una forma abreviada : a += 2; Al igual que tenemos el operador += para aumentar el valor de una variable, tenemos -= para disminuirlo, /= para dividirla entre un cierto nmero, *= para multiplicarla u por un nmero, y as sucesivamente. Por ejemplo, para multiplicar por 10 el valor de la u variable bhar amos b *= 10; Tambin podemos aumentar o disminuir en una unidad el valor de una variable, e empleando los operadores de ncremento(++) y de decremento (). As para sumar 1 al , valor de a, podemos emplear cualquiera de estas tres formas: a = a +1; a += 1; a++;

14

Cap tulo 2: Tipos de datos, operadores y expresiones

Los operadores de incremento y de decremento se pueden escribir antes o despus e de la variable. As es lo mismo escribir estas dos l , neas: a++; ++a; Pero hay una diferencia si ese valor se asigna a otra variable al mismo tiempo que se incrementa/decrementa: int c = 5; int b = c++; da como resultado c = 6 y b = 5 (se asigna el valor a b antes de incrementar c) mientras que int c = 5; int b = ++c; da como resultado c = 6 y b = 6 (se asigna el valor a b despus de incrementar c). e

2.2.3.

Operaciones a nivel de bits


Las operaciones a nivel de bits deber ser habituales para los estudiantes de an

informtica, pero quizs no tanto para quien no haya trabajado con el sistema binario. a a No entrar por ahora en ms detalles, salvo poner un par de ejemplos para quien necesite e a emplear estas operaciones: para desplazar los bits de a dos posiciones hacia la izquierda, usar amos a << 2; para invertir los bits de c (complemento) usar amos ~c; para hacer una suma lgica de los bits de d y f ser d|f . o a Operacin o Desplazamiento de bits a la derecha Desplazamiento de bits a la derecha Desplazamiento rellenando con ceros Producto lgico (and) o Suma lgica (or) o Suma exclusiva (xor) Complemento S mbolo >> << >>> & | ^ ~

2.2.4.

Operadores relacionales
Tambin podremos comprobar si entre dos nmeros (o entre dos variables) existe e u

una cierta relacin del tipo es a mayor que b? o tiene a el mismo valor que b?. Los o operadores que utilizaremos para ello son:

2.2. Operadores y expresiones; aritmticos, lgicos, a nivel de bits y de asignacin e o o

15

Operacin o Mayor que Mayor o igual que Menor que Menor o igual que Igual que Distinto de

S mbolo > >= < <= == !=

As por ejemplo, para ver si el valor de una variable b es distinto de 5, escribir , amos algo parecido (veremos la sintaxis correcta un poco ms adelante) a a SI b != 5 ENTONCES ...

o para ver si la variable a vale 70, ser algo como (nuevamente, veremos la sintaxis a correcta un poco ms adelante) a SI a == 70 ENTONCES ...

Es muy importante recordar esta diferencia: para asignar un valor a una variable se emplea un unico signo de igual, mientras que para comparar si una variable es igual a otra (o a un cierto valor) se emplean dos signos de igual. Operadores lgicos. Podremos enlazar varias condiciones, para indicar qu hacer o e cuando se cumplan ambas, o slo una de ellas, o cuando una no se cumpla. Los operadores o que nos permitirn enlazar condiciones son: a Operacin o Y O No S mbolo && || !

Por ejemplo, la forma de decir si a vale 3 y b es mayor que 5, o bien a vale 7 y b no es menor que 4 en una sintaxis parecida a la de Java (aunque todav no es la correcta) a ser a: SI (a==3 && bb>5) || (a==7 Tarea 3 Expresiones Lgicas o Hacer un programa que verique si en el intervalo [2, 3] se cumple que la desigualdad (x + 2) (x 3) > 0. && ! (b<4))

16

Cap tulo 2: Tipos de datos, operadores y expresiones

2.2.5.

Ejemplo
Indique en que casos las siguientes sentencias son verdaderas o falsas dados los

valores a=1 b = 2 y c = 5;
1.- d = (a*b) < (c-4); 2.- d = (a < b) && (c!=4); 3.- d = (a &b)>2; 4.- d = ((c *c) | 5) <=4;

Las respuesta son false, true, false y false.

2.3.

Precedencia de los operadores. Literales, constantes y variables

2.3.1.

Precedencia de operadores
Las reglas de precedencia de operadores son una gu de accin, que le permiten a a o

los lenguajes calcular expresiones en el orden correcto. La siguiente tabla presenta el orden de precedencia Operadores () , /, % +, Ejercicio Dada la ecuacin y = ax3 + 7, cual de los que siguen, si es que existe alguno, son o enunciados correctos correspondientes a esta ecuacin?. o
a) y = a * x * x * x + 7; b) y = a * x * x * (x + 7); c) y = (a * x) * x * (x + 7); d) y = (a * x) * x * x + 7; e) y = a * (x * x * x) + 7; f) y = a * x * (x * x + 7);

Operaciones Parntesis e Multiplicacin, Divisin y Modulo o o Suma o resta

Orden de clculo a Se calculan primero. Se evalan en segundo lugar u Se calcula al ultimo

2.4. Instrucciones secuenciales

17

Ejercicio Declare el orden de clculo de los operadores en cada uno de los enunciados sia guientes y muestre el valor de x una vez que se ejecute cada una de ellas.

a) x = 7 + 3 * 6 / 2 - 1; b) x = 2 \% 2 + 2 * 2 - 2 / 2; c) y = (3 * 9 * (3 + (9 * 3 / (3))));

2.3.2.

Literales, Constantes y variable


Con el objetivo de generalizar nuestros programa haremos uso de letras que repre-

sentarn los valores que deseamos guardar para un procesamiento posterior en tiempo de a ejecucin. Las variables podrn ser de cualquiera de los tipos numricos, de tipo caracter o o a e los que tipos compuestos denidos por los usuarios. Los nombres de las variables validos comienzan con una letra seguida de otras letras o el caracter . La longitud de los nombres no tiene limite y normalmente se sugiere, por facilidad de lectura, tengan relacin con la variable que representa. o As por ejemplo int a= 10; almacenara el nmero 10 en la variable a. u char a = a almacenara en la variable a el caracter a. Note que los caracteres se pondrn entre comillas a a diferencia de los nombres de variables.

2.4.

Instrucciones secuenciales
Una manera de realizar un sencillo programa es utilizando una serie de instruc-

ciones de forma consecutiva (secuencial o en secuencia) que permita realizar una tarea. Algunos ejemplos de ellos se presentan en las siguientes tareas.

18

Cap tulo 2: Tipos de datos, operadores y expresiones

2.5.
2.5.1.

Ejemplos
Calculo de reas y volmenes de guras geomtricas regulares a u e
Dada la siguiente informacin, hacer un programa que permita calcular el rea de o a

un tringulo, de un cuadrado, y de un rectngulo, as como los volmenes de un cilindro y a a u de un cono. El tringulo es un pol a gono formado por tres lados y tres ngulos. La suma de todos a sus ngulos siempre es 180 grados. Para calcular el rea se emplea la siguiente frmula: a a o Area del tringulo = (base * altura) / 2 a El cuadrado es un pol gono de cuatro lados, con la particularidad de que todos ellos son iguales. Adems sus cuatro ngulos son de 90 grados cada uno. El rea de esta a a a gura se calcula mediante la frmula: o Area del cuadrado = lado al cuadrado El rectngulo es un pol a gono de cuatro lados, iguales dos a dos. Sus cuatro ngulos a son de 90 grados cada uno. El rea de esta gura se calcula mediante la frmula: a o Area del rectngulo = base * altura a El cilindro es el slido engendrado por un rectngulo al girar en torno a uno de o a sus lados. Para calcular su rea lateral, su rea total as como para ver su desarrollo pulsar a a sobre la gura anterior Para calcular su volumen se emplea la siguiente frmula: o Volumen del cilindro = rea de la base * altura a El cono es el slido engendrado por un tringulo rectngulo al girar en torno a uno o a a de sus catetos. Para calcular su rea lateral, su rea total as como para ver su desarrollo a a pulsar sobre la gura anterior Para calcular su volumen se emplea la siguiente frmula: o Volumen del cono = (rea de la base * altura) / 3 a La implementacin en Java es: o

2.5. Ejemplos

19

/** * Title: Calculo de areas y volumenes * Calcula utilizando simples sentencias las areas y volumenes de figuras * 2005 * Company: UMSNH * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej021 { public static void main(String[] args) { // datos double base = 10, altura = 5, radio = 2; // areas double Atriangulo = (base * altura) / 2.0; double Acuadrado = base*base; double Arectangulo = base * altura; // volumenes double Abase double Vcilindro double Vcono = 3.1416*radio*radio; = Abase * altura ; = Abase * altura / 3.0;

System.out.println("Area de triangulo = " + Atriangulo); System.out.println("Area de cuadrado = " + Acuadrado); System.out.println("Area de rectangulo = " + Arectangulo); System.out.println("Volumen cilindro System.out.println("Volumen cono } } = " + Vcilindro); = " + Vcono);

La implementacin en C es: o
// Ejemplo ec021.cpp include <stdio.h> /** * Title: Calculo de areas y volumenes * Calcula utilizando simples sentencias las areas y volumenes de figuras * 2005 * Company: UMSNH * @author Dr. Felix Calderon Solorio * @version 1.0 */ int main() { // datos double base = 10, altura = 5, radio = 2; // areas double Atriangulo = (base * altura) / 2.0;

20

Cap tulo 2: Tipos de datos, operadores y expresiones

double Acuadrado = base*base; double Arectangulo = base * altura; // volumenes double Abase double Vcilindro double Vcono printf("Area de printf("Area de printf("Area de printf("Volumen printf("Volumen return 0; } = 3.1416*radio*radio; = Abase * altura ; = Abase * altura / 3.0; triangulo cuadrado rectangulo cilindro cono = = = = = %f\n", %f\n", %f\n", %f\n", %f\n", Atriangulo); Acuadrado); Arectangulo); Vcilindro); Vcono);

2.5.2.

Ley de ohm y Anlisis bsico de transistores a a


Para el circuito mostrado en la gura 2.1, determinar la ganancia de voltaje de un

transistor en conguracin de base comn. o u

Figura 2.1: Ejemplo de transistores. La solucin utilizando Java es: o


/** * Title: Calculo de la ganacia de voltaje para un transistor * Description: Programa para determinar ganancias de voltaje * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */

public class ej023 { public static void main(String[] args) { double Vi = 200e-3, Re = 100, Rc = 100e+3, R = 5e3; double I, Il, Vl, Av; // calculo de la corriente de emisor. I = Vi/Re;

2.5. Ejemplos

21

System.out.println("I = " + I); // Asumiendo una ganacia alpha = 1 y que Ic = Ie Il = I; System.out.println("Il = " + Il); // el voltaje en la resistencia R es Vl = Il*R; System.out.println("Vl = " + Vl);

// finalmente la ganacia de voltaje es Av = Vl/Vi; System.out.println("Av = " + Av); } }

En C:
// Ejemplo ec023.cpp #include <stdio.h> /** * Title: Calculo de la ganancia de voltaje para un transistor * Description: Programa para determinar ganancias de voltaje * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ int main() { double Vi = 200e-3, Re = 100, Rc = 100e+3, R = 5e3; double I, Il, Vl, Av; // calculo de la corriente de emisor. I = Vi/Re; printf("I = %f\n", I); // Asumiendo una ganacia alpha = 1 y que Ic = Ie Il = I; printf("Il = %f\n", Il); // el voltaje en la resistencia R es Vl = Il*R; printf("Vl = %f\n", Vl);

// finalmente la ganacia de voltaje es Av = Vl/Vi; printf("Av = %f\n", Av); }

22

Cap tulo 2: Tipos de datos, operadores y expresiones

Tarea 4 Problema de F sica Un bloque de masa m1 = 3.0 slugs descansa en un plano liso que est inclinado un ngulo a a de 30 grados respecto a la horizontal y est unido, por medio de una cuerda que para por a una pequea polea sin friccin, con un segundo bloque de masa m2 = 2 slugs suspendido n o verticalmente tal como se muestra en la gura 2.2. (a) Cual es la aceleracin de cada cuero po? b) Cul es la tensin de la cuerda?. a o

Escriba el cdigo correspondiente en C y/o Java para solucionar este problema o Respuesta a.- 3.2 pies/seg2 y b.- 58 lb

Figura 2.2: Ejemplo de plano inclinado.

Cap tulo 3

Entrada y salida por consola


Una parte importante de la solucin de cualquier problema es la presentacin de o o resultados. Es este cap tulo analizaremos a fondo las caracter sticas de formato printf, scanf, getche y gets en C y las clases System.out y System.in en Java.

3.1.

Entrada salida en C
.

3.1.1.

Funcin prinft o
La funcin printf se utiliza para escribir una cadena de caracteres o bien un cono

junto de nmeros con formato. La sintaxis general de esta funcin es u o

printf("Cadena de formato de control", argumentos);

Los formatos numricos de esta funcin se muestran a continuacin. e o o 23

24

Cap tulo 3: Entrada y salida por consola

Descripcin o Despliega un entero decimal con signo Despliega un entero decimal con signo Muestra un entero octal sin signo Muestra un estero decimal sin signo Muestra un entero en Hexadecimal x las letras aparecen con minsculas u X las letras aparecen con maysculas u hol Se coloca antes de cualquier especicador de conversin de enteros para indicar short o o bien long, respectivamente Un ejemplo del uso de esta funcin para el caso de enteros se muestra en la siguiente o gura
// Ejemplo ec080.cpp /** * Ejemplo para mostrar los diferentes formatos de * la funcin printf, con numeros enteros. o */ #include <stdio.h> int main() { printf("%d\n", 511); printf("%i\n", 511); printf("%d\n", +511); printf("%d\n", -511); printf("%hd\n", 32000); printf("%ld\n", 2000000000); printf("%o\n", 511); printf("%u\n", 511); printf("%u\n", -511); printf("%x\n", 511); printf("%X\n", 511); return 0; }

Especicador d i o u xoX

Para imprimir nmeros otantes, la funcin printf, utiliza los siguientes especiu o cadores Especicador eoE f goG Descripcin o Muestra un valor en punto otante en notacin exponencial o Muestra valores de punto otante Despliega un valor en punto otante, ya sea en la forma forma de punto otante f o en la forma exponencial e o E Indicador de otante largo long double

L
// Ejemplo ec081.cpp

3.1. Entrada salida en C

25

/** * Ejemplo para mostrar los diferentes formatos de * la funcin printf, con numeros flotantes. o */ #include <stdio.h> int main() { printf("%e\n", printf("%e\n", printf("%E\n", printf("%f\n", printf("%g\n", printf("%G\n", return 0; }

1234567.89); +1234567.89); -1234567.89); 1234567.89); 1234567.89); 1234567.89);

Para imprimir caracteres y mensajes (cadenas de caracteres), el formato de la funcin printf es: o Especicador c s
// Ejemplo ec082.cpp /** * Este programa muestra los diferentes formatos para i * imprimir caracteres y cadenas de caracteres */ #include <stdio.h> int main() { char a = A; char cadena[] = "Esto es una cadena de texto"; char *cadenap = "Esto tambien es una cadena de texto"; printf("%c\n", printf("%s\n", printf("%s\n", printf("%s\n", return 0; } a); "Esto es una cadena de texto"); cadena); cadenap);

Descripcin o imprime un caracter imprime una cadena de caracteres

3.1.2.

Funcin scanf o
Esta funcin se puede utilizar para la introduccin de cualquier combinacin de o o o

valores numricos o caracteres. En trminos generales la funcin scanf se escribe: e e o


scanf(cadena de control, arg1,arg2,...,argn);

Donde cadena de control hace referencia a una cadena de caracteres que contiene cierta informacin sobre el formato de los datos y arg1,arg2,...,argn son argumentos que o

26

Cap tulo 3: Entrada y salida por consola

representan los datos. (En realidad los argumentos representan punteros que indican las direcciones de memoria en donde se encuentran los datos. Esto se ver ms adelante). a a En la cadena de control se incluyen grupos de caracteres, uno por cada dato de entrada. Cada grupo debe comenzar con el signo de porcentaje, que ir seguido, en su forma a ms sencilla, de un carcter de conversin que indica el tipo de dato correspondiente. a a o Carcter a Signicado de conversin o c El dato es un carcter. a d El dato es un entero decimal. e El dato es un valor en coma otante. f El dato es un valor en coma otante. g El dato es un valor en coma otante. h El dato es un entero corto. i El dato es un entero decimal, octal o hexadecimal. o El dato es un entero octal. s El dato es una cadena de caracteres. u El dato es un entero decimal sin signo. x El dato es un entero hexadecimal. [...] El dato es una cadena de caracteres que puede incluir caracteres de espaciado. Cada nombre de variable debe ir precedido por un ampersand &. Los datos que se introducen deben corresponderse en tipo y orden con los argumentos de la funcin scanf. o Ejemplo de utilizacin de scanf: o

// Ejemplo ec083.cpp /** * Ejemplo para mostrar el uso de la funcion scanf */ #include <stdio.h> int main () { char str [80]; int i; printf ("Ingrese su nombre : "); scanf ("%s",str); printf ("Ingrese su edad: "); scanf ("%d",&i); printf ("Sr. %s , %d a~os de edad.\n",str,i); n printf ("Ingrese un numero hexadecimal : "); scanf ("%x",&i); printf ("Usted dio el numero %#x (%d).\n",i,i); return 0; }

3.1. Entrada salida en C

27

3.1.3.

Funcin getch o
, Si lo que queremos es que el usuario introduzca un carcter por el teclado usamos a

las funciones getch y getche. Estas esperan a que el usuario introduzca un carcter por el a teclado. La diferencia entre getche y getch es que la primera saca por pantalla la tecla que hemos pulsado y la segunda no (la e del nal se reere a echo=eco). Ejemplo:
// Ejemplo ec084.cpp /** * Pide un caracter desde el teclado. */ #include <stdio.h> #include <conio.h> int main() { char letra; printf( "Introduce una letra: " );

letra = getche(); printf( "\nHas introducido la letra: %c", letra ); return 0; }

3.1.4.

Instruccin gets o
Esta funcin es la alternativa para captura de strings que tengan espacios en blanco o

intermedios cosa que scanf %s no puede hacer. Su formato completo es :


gets(variable string); // Ejemplo ec085.cpp /** * Ejemplo que muestra el uso de gets y puts */ #include <stdio.h> // Para gets() y puts() #include <conio.h> // Para clrscr() y gotoxy()

void main() {

28

Cap tulo 3: Entrada y salida por consola

char nombre[31]; // Declara un arreglo de 31 caracteres char saludo1[] = "HOLA,"; //Constante de caracteres

puts("Cual es tu nombre ? "); //Despliega cadena de car. gets(nombre); // Lee cadena de caracteres puts(saludo1); puts(nombre); }

3.1.5.

clase cout
En C++ se pueden seguir utilizando las mismas sentencias para mostrar informa-

cin por pantalla o pedirla mediante teclado. Pero a estas antiguas se aaden 2 nuevas de o n la misma potencia y mayor facilidad de uso. La cabecera que utilizan estas dos sentencias es iostream.h. Mostrar por pantalla: cout (( expresin; o ))Pedir por teclado: cin )) variable; La variable pude ser de cualquier tipo. EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> void main() { int i,j; double d; clrscr(); i=10; j=15; cout <<"Introducir valor: "; cin>>d; cout << "Estos son los valores: "; cout << i << " "<< j << " "<< d; getch(); }

INDICADORES DE FORMATO: Tres funciones miembro (width, precision y ll) que jan formato de anchura, precisin y carcter de relleno. Es necesario jar la ano a chura, precisin y carcter de relleno antes de cada sentencia de escritura. ANCHURA: o a cout.width(ancho); DECIMALES: cout.precision(no digitos); RELLENO: cout.ll(carcter); a EJEMPLO:
#include<iostream.h> #include<stdio.h> #include<conio.h>

3.1. Entrada salida en C

29

void main() { double numero=123.1234567; clrscr(); cout<< "hola" <<"\n"; cout.width(15); cout<< "hola" <<"\n"; cout.width(15); cout.fill(*); cout<< "hola"<<"\n"; cout<<numero <<"\n"; cout.precision(4); cout<<numero <<"\n"; cout.precision(10); cout<<numero; getch(); }

MODIFICADORES DE LA CLASE IOS: Estos modicadores son pertenecientes a la clase ios. Cuando se activan su valor se mantiene, es decir hay que desactivarlos para volver al formato de salida original. Fijar indicador: cout.setf(ios::identicadorios::identicador2); Anular identicador: cout.unsetf(ios::identicadorios::identicador2); IDENTIFICADOR DESCRIPCION oct Devuelve un entero en octal. hex Devuelve un entero en hexadecimal. scientic Devuelve un nmero en formato cient u co. showpoint Muestra 6 decimales aunque no sea necesario showpos Muestra el signo + en los valores positivos left Ajusta la salida a la izquierda. skipws Omite los espacios a la izquierda de la salida. uppercase Muestra el texto en maysculas. u EJEMPLO:
#include <stdio.h> #include <conio.h> #include<iostream.h> void main() { float num=200.0; int num1=200; clrscr(); cout<<num <<"\n"; cout.setf(ios::showpos|ios::showpoint); cout<<num <<"\n"; cout.setf(ios::scientific); cout<<num <<"\n"; cout.unsetf(ios::scientific|ios::showpoint|ios::showpos); cout<<num <<"\n"; cout.setf(ios::hex); cout<<num1 <<"\n"; getch(); }

30

Cap tulo 3: Entrada y salida por consola

3.2.

Entrada salida en Java


. Los objetos System.in y System.out La entrada/salida estndar (normalmente el a

teclado y la pantalla, respectivamente) se denen mediante dos objetos que puede usar el programador sin tener que crear ujos espec cos. La clase System tiene un miembro dato denominado in que es una instancia de la clase InputStream que representa al teclado o ujo de entrada estndar. Sin embrago, el a miembro out de la clase System es un objeto de la clase PrintStream, que imprime texto en la pantalla (la salida estndar). a Para leer un carcter solamente tenemos que llamar a la funcin read desde Sysa o tem.in.
try{ System.in.read(); }catch (IOException ex) { }

Obligatoriamente, el proceso de lectura ha de estar en un bloque try..catch. Esta porcin de cdigo es la que se ha empleado en muchas aplicaciones para o o detener la ejecucin de una aplicacin hasta que se pulse la tecla RETORNO. o o Para leer un conjunto de caracteres hasta que se pulse la tecla RETORNO escribimos
StringBuffer str=new StringBuffer(); char c; try{ while ((c=(char)System.in.read())!=\n){ str.append(c); } }catch(IOException ex){}

La clase StringBuer es una clase que nos permite crear strings. Contiene mtodos e para aadir nuevos caracteres a un buer y convertir el resultado nal en un string. Las n principales funciones miembro son insert y append. Usamos una versin de esta ultima o funcin para aadir un carcter al nal de un objeto de la clase StringBuer. o n a

3.2. Entrada salida en Java

31

Para convertir un objeto str de la clase StringBuer a String se usa la funcin o miembro toString. Esta llamada se hace de forma impl cita cuando dicho objeto se le pasa a System.out.println.
System.out.println(str);

Finalmente, se ha de hacer notar, que la funcin read miembro de InputStream o devuelve un int que es promocionado a char. (Ver ejemplo ej080.java) Existe la posibilidad de conectar el objeto System.in con un objeto de la clase InputStreamReader para leer los caracteres tecleados por el usuario. Esta conexin se realiza mediante la sentencia o Reader entrada=new InputStreamReader(System.in); Para leer una sucesin de caracteres se emplea un cdigo similar o o
StringBuffer str=new StringBuffer(); char c; try{ Reader entrada=new InputStreamReader(System.in); while ((c=(char)entrada.read())!=\n){ str.append(c); } }catch(IOException ex){}

Para imprimir los caracteres le dos se escribe como en la seccin anterior o


System.out.println(str);

ver ej081.java Podemos usar la segunda versin de la funcin read para leer el conjunto de cao o racteres tecleados por el usuario.
char[] buffer=new char[255]; try{ Reader entrada=new InputStreamReader(System.in); int numBytes=entrada.read(buffer); System.out.println("Nmero de bytes ledos "+numBytes); u }catch(IOException ex){ }

En esta segunda porcin de cdigo, se lee un conjunto de caracteres hasta que se o o pulsa la tecla RETORNO, los caracteres se guardan en el array buer. La funcin read o devuelve el nmero de caracteres le u dos.

32

Cap tulo 3: Entrada y salida por consola

Para imprimir los caracteres le dos se crea un objeto str de la clase String a partir de un array de caracteres buer, empleando uno de los constructores de dicha clase. A continuacin, se imprime el string str. o
String str=new String(buffer); System.out.println(str);

3.2.1.

La clase Leer
Para facilitar el uso de los procedimiento antes descritos, se creo la clase leer. Esta

clase permite leer Tipo de dato Funcin o String dato() double datoDouble() oat datoFloat() int datoInt() long datoLong() short datoShort() Como ejemplo del uso de esta clase podemos ver el siguiente
/** * <p>Title: Ejemplo de uso de la Clase leer</p> * <p>Description: Lee numeros de teclado utilizando los diferentes * tipos implementados.</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej035 { public static void main(String[] args) { System.out.println("Dame el valor de un double "); double a = Leer.datoDouble(); System.out.println("el valor dado fue " + a); System.out.println("Dame el valor de un flotante "); float b = Leer.datoFloat(); System.out.println("el valor dado fue " + b); System.out.println("Dame el valor de un entero "); int c = Leer.datoInt(); System.out.println("el valor dado fue " + c); System.out.println("Dame el valor de un entero largo "); long d = Leer.datoLong(); System.out.println("el valor dado fue " + d); System.out.println("Dame el valor de un entero corto "); short e = Leer.datoShort(); System.out.println("el valor dado fue " + e); }

3.3. Ejemplos

33

Nota: Para compilar este ejemplo, se debe tener la clase Leer en el mismo directorio de trabajo y la compilacin del ejemplo ser de manera similar. Esta es una de las ventajas o a de la programacin orientada a objetos. o

3.3.

Ejemplos
Utilizando la entrada salida por consola, reescribir los programas de la seccin 2.5, o

para que permitan utilizar valores dados desde teclado.

3.3.1.
En Java

Calculo de Areas

/** * <p>Title: Calculo de Areas de figuras</p> * <p>Description: Calcula el area y volumen de simples figuras utilizando * lectura de datos desde el teclado</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej036 { public static void main(String[] args) { // datos double base, altura, radio; System.out.print("Dame el valor de la base "); base = Leer.datoDouble(); System.out.print("Dame el valor de altura "); altura = Leer.datoDouble(); System.out.print("Dame el radio "); radio = Leer.datoDouble(); // areas double Atriangulo = (base * altura) / 2.0; double Acuadrado = base*base; double Arectangulo = base * altura; // volumenes double Abase double Vcilindro double Vcono = 3.1416*radio*radio; = Abase * altura ; = Abase * altura / 3.0; = " + Atriangulo);

System.out.println("Area de triangulo

34

Cap tulo 3: Entrada y salida por consola

System.out.println("Area de cuadrado = " + Acuadrado); System.out.println("Area de rectangulo = " + Arectangulo); System.out.println("Volumen cilindro System.out.println("Volumen cono } } = " + Vcilindro); = " + Vcono);

En C
// Ejemplo ec036.cpp /** * <p>Title: Calculo de Areas de figuras</p> * <p>Description: Calcula el area y volumen de simples figuras utilizando * lectura de datos desde el teclado</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> int main() { // datos float base, altura, radio; printf("Dame el valor de la base "); scanf("%f", &base); printf("Dame el valor de altura "); scanf("%f", &altura); printf("%f\n", altura); printf("Dame el radio "); scanf("%f", &radio ); // areas float Atriangulo = (base * altura) / 2.0; float Acuadrado = base*base; float Arectangulo = base * altura; // volumenes float Abase float Vcilindro float Vcono printf("Area de printf("Area de printf("Area de printf("Volumen printf("Volumen return 0; } = 3.1416*radio*radio; = Abase * altura ; = Abase * altura / 3.0; triangulo cuadrado rectangulo cilindro cono = = = = = %f\n", %f\n", %f\n", %f\n", %f\n", Atriangulo); Acuadrado); Arectangulo); Vcilindro); Vcono);

3.3. Ejemplos

35

3.3.2.
En Java

Ley de Ohm y Anlisis de transistores a

/** * Title: Calculo de la ganancia de voltaje para un transistor * Description: Programa para determinar ganancias de voltaje utilizando dato * desde el teclado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */

public class ej037 { public static void main(String[] args) { double Vi, Re, Rc, R; double I, Il, Vl, Av; System.out.print("Dame el Vi = Leer.datoDouble(); System.out.print("Dame el Re = Leer.datoDouble(); System.out.print("Dame el Rc = Leer.datoDouble(); System.out.print("Dame el R = Leer.datoDouble(); voltaje de entrada Vi = "); valor de la Resistencia de emisor Re = "); valor de la Resistencia de colector Rc = "); valore de la Resistencia de carga Rl = ");

// calculo de la corriente de emisor. I = Vi/Re; System.out.println("I = " + I); // Asumiendo una ganacia alpha = 1 y que Ic = Ie Il = I; System.out.println("Il = " + Il); // el voltaje en la resistencia R es Vl = Il*R; System.out.println("Vl = " + Vl);

// finalmente la ganacia de voltaje es Av = Vl/Vi; System.out.println("Av = " + Av); } }

En C
// Ejemplo ec037.cpp /** * Title: Calculo de la ganancia de voltaje para un transistor * Description: Programa para determinar ganancias de voltaje utilizando dato * desde el teclado

36

Cap tulo 3: Entrada y salida por consola

* Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> int main() { float Vi, Re, Rc, R; float I, Il, Vl, Av; printf("Dame el voltaje de entrada Vi = "); scanf("%f", &Vi); printf("Dame el valor de la Resistencia de emisor Re = "); scanf("%f", &Re); printf("Dame el valor de la Resistencia de colector Rc = "); scanf("%f", &Rc); printf("Dame el valore de la Resistencia de carga Rl = "); scanf("%f", &R); // calculo de la corriente de emisor. I = Vi/Re; printf("I = %f\n", I); // Asumiendo una ganacia alpha = 1 y que Ic = Ie Il = I; printf("Il = %f\n", Il); // el voltaje en la resistencia R es Vl = Il*R; printf("Vl = %f\n", Vl);

// finalmente la ganacia de voltaje es Av = Vl/Vi; printf("Av = %f\n", Av); return 0; }

Tarea 5 Entrada Salida Hacer un programa, que reciba tres nmeros de punto otante y calcule su promedio u

Cap tulo 4

Instrucciones condicionales y de repeticin o


En cualquier lenguaje de programacin es habitual tener que comprobar si se cumo ple una cierta condicin. La forma normal de conseguirlo es empleando una construccin o o que recuerda a:
SI condicin_a_comprobar o ENTONCES pasos_a_dar

4.1.

Sentencias if-else, escalera if-else y switch


En el caso de Java, la forma exacta ser empleando if (si, en ingls), seguido por la a e

condicin entre parntesis, e indicando nalmente entre llaves los pasos que queremos dar o e si se cumple la condicin, as : o if (condicin) sentencias o Por ejemplo,
if (x == 3) { System.out.println( "El valor es correcto" ); resultado = 5; }

Nota: Si slo queremos dar un paso en caso de que se cumpla la condicin, no es o o necesario emplear llaves. Las llaves sern imprescindibles slo cuando haya que hacer varias a o cosas: 37

38

Cap tulo 4: Instrucciones condicionales y de repeticin o

if (x == 3) System.out.println( "El valor es correcto" );

Una primera mejora, que tambin permiten muchos lenguajes de programacin, es e o indicar qu hacer en caso de que no se cumpla la condicin. Ser algo parecido a e o a
SI condicin_a_comprobar o ENTONCES pasos_a_dar EN_CASO_CONTRARIO pasos_alternativos

que en Java y/o C escribir amos as :


if (condicin) o { sentencias1 } else { sentencias2 }

Por ejemplo,
if (x == 3) { System.out.println( "El valor es correcto" ); resultado = 5; } else { System.out.println( "El valor es incorrecto" ); resultado = 27; }

Si queremos comprobar varias condiciones, podemos utilizar varios if - else - if else - if encadenados, pero tenemos una forma ms elegante en Java de elegir entre distintos a valores posibles que tome una cierta expresin. Su formato es ste: o e
switch case case case ... } (expresion) { valor1: sentencias1; break; valor2: sentencias2; break; valor3: sentencias3; break; // Puede haber ms valores a

Es decir, despus de la orden switch indicamos entre parntesis la expresin que e e o queremos evaluar. Despus, tenemos distintos apartados, uno para cada valor que queramos e comprobar; cada uno de estos apartados se precede con la palabra case, indica los pasos a dar si es ese valor el que se da, y terminar con break. Un ejemplo ser a:
switch case case case } ( x 30: 50: 60: * 10) { System.out.println( "El valor de x era 3" ); break; System.out.println( "El valor de x era 5" ); break; System.out.println( "El valor de x era 6" ); break;

4.1. Sentencias if-else, escalera if-else y switch

39

Tambin podemos indicar qu queremos que ocurra en el caso de que el valor de e e la expresin no sea ninguno de los que hemos detallado: o
switch (expresion) { case valor1: sentencias1; break; case valor2: sentencias2; break; case valor3: sentencias3; break; ... default: sentencias; }

// Puede haber ms valores a // Opcional: valor por defecto

Por ejemplo, as :
switch ( x case 30: case 50: case 60: default: } * 10) { System.out.println( System.out.println( System.out.println( System.out.println( "El "El "El "El valor valor valor valor de de de de x x x x era 3" era 5" era 6" no era ); ); ); 3, break; break; break; 5 ni 6" ); break;

Podemos conseguir que en varios casos se den los mismos pasos, simplemente eliminado la orden break de algunos de ellos. As un ejemplo algo ms completo podr , a a ser:
switch case case case ( x ) { 1: 2: 3: System.out.println( break; case 4: case 5: System.out.println( break; case 6: System.out.println( valorTemporal = 10; System.out.println( break; default: System.out.println( break;

"El valor de x estaba entre 1 y 3" );

"El valor de x era 4 o 5" );

"El valor de x era 6" ); "Operaciones auxiliares completadas" );

"El valor de x no estaba entre 1 y 6" );

Un poco ms adelante propondremos ejercicios que permitan aanzar todos estos a conceptos. Existe una construccin adicional, que permite comprobar si se cumple una condio cin y devolver un cierto valor segn si dicha condicin se cumple o no. Es lo que se conoce o u o como el operador condicional (?):
condicion ? resultado_si cierto : resultado_si_falso

40

Cap tulo 4: Instrucciones condicionales y de repeticin o

Es decir, se indica la condicin seguida por una interrogacin, despus el valor que o o e hay que devolver si se cumple la condicin, a continuacin un s o o mbolo de dos puntos y nalmente el resultado que hay que devolver si no se cumple la condicin. o Es frecuente emplearlo en asignaciones (aunque algunos autores desaconsejan su uso porque puede resultar menos legible que un if), como en este ejemplo: x = (a == 10) ? b*2 : a ; En este caso, si a vale 10, la variable tomar el valor de b*2, y en caso contrario a tomar el valor de a. Esto tambin se podr haber escrito de la siguiente forma, ms larga a e a a pero ms legible: a
if (a == 10) x = b*2; else x = a;

Ejemplo: Hacer un programa, que dados tres nmeros determine cual es el mayor y cual es u el menor.
/** * Title: Mayor y menor * Description: Dados tres numeros dice cual es el mayor y cual el menor * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */

class ej003 { public static void main (String args[]) { int a, b, c, d; a = 4; b = 2; c = 3; d = (a > b) ? a : b; d = (d > c) ? d : c; System.out.println("el Mayor es " + d);

// otra forma if(a> b) d = a; else d = b; if(d< c) d = c; System.out.println("el Mayor es " + d); } } La implementacin en C es: o

4.1. Sentencias if-else, escalera if-else y switch

41

// Ejemplo ec003.cpp /** * Title: Mayor y menor * Description: Dados tres numeros dice cual es el mayor y cual el menor * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */

#include <stdio.h> int main () { int a, b, c, d; a = 4; b = 2; c = 3; d = (a > b) ? a : b; d = (d > c) ? d : c; printf("el Mayor es %d\n", d);

// otra forma if(a> b) d = a; else d = b; if(d< c) d = c; printf("el Mayor es %d\n", d); return 0; }

4.1.1.

Ejemplo de solucin de una ecuacin cuadrtica o o a


La formula general de una ecuacin cuadrtica es f (x) = Ax2 + Bx + C, y resulta o a

de inters determinar los puntos donde esta ecuacin cruza el eje x, es decir f (x) = 0. La e o solucin de este problema esta dado por la formula general: o +

B x=

B 2 4AC

2A

La programacin de esta ecuacin no tiene mayor problema, solamente debemos o o cuidar, cuando B 2 4AC < 0, ya que en dicho caso, la ra cuadrada ser un nmero z a u imaginario. La implementacin en Java queda: o
/**

42

Cap tulo 4: Instrucciones condicionales y de repeticin o

* Title: Raices de un Polinomio * Description: este ejemplo calcula las raices de una ecuacion de segundo grado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ class ej002 { public static void main(String arqs[]) { double A=9, B=6, C=4; double X1=0, X2=0, G=0, I=0, D=0; D=(B*B-(4*A*C)); if (D>0) { // si las reices son positivas X1=(-B+Math.sqrt(D))/(2*A); X2=(-B-Math.sqrt(D))/(2*A); System.out.println("X1="+X1); System.out.println("X2="+X2); } else { // si las raices son negativas G=-B/(2*A); I=Math.sqrt(-D)/(2*A); System.out.println("X1="+""+G+"+"+I+"j"); System.out.println("X2="+""+G+"-"+I+"j"); } } }

La implementacin en C queda o
// Ejemplo ec002.cpp /** * Title: Raices de un Polinomio * Description: este ejemplo calcula las raices de una ecuacion de segundo grado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> #include <math.h> int main() { double A=9, B=6, C=4; double X1=0, X2=0, G=0, I=0, D=0; D=(B*B-(4*A*C)); if (D>0)

4.1. Sentencias if-else, escalera if-else y switch

43

{ // si las reices son positivas X1=(-B+sqrt(D))/(2*A); X2=(-B-sqrt(D))/(2*A); printf("X1 = %f\n", X1); printf("X2 = %f\n", X2); } else { // si las raices son negativas G=-B/(2*A); I=sqrt(-D)/(2*A); printf("X1 = %f, %f j\n", G, I); printf("X2 = %f, %f j\n", G, I); } return 0; }

4.1.2.

Ejemplo de tipos de tringulos a


El tringulo rectngulo es aqul que tiene un ngulo de 90 grados, el tringulo a a e a a

issceles aqul que tiene dos lados iguales y uno desigual, el tringulo escaleno es aqul que o e a e tiene los tres lados desiguales y por lo tanto sus ngulos, el tringulo equiltero es aqul a a a e que tiene los tres lados iguales y por lo tanto sus ngulos, siendo cada uno de 60 grados. a Dada esta informacin hacer un programa en Java que permita determinar de que o tipo de tringulo se trata, dados el tamao de cada uno de sus tres lados. a n En java la implementacin es: o
/** * Title: Tipos de triangulos * Description: Programa para determinar el tipo de triangulo dados tres lados * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ public class ej022 { public static void main(String[] args) { double a = 1, b = 1.5, c = 2; // tama~o de los lados n double A, B, C; // angulos double suma; A = Math.acos( (b * b + c * c - a * a) / (2 * b * c)) * 180 / Math.PI; B = Math.acos( (a * a + c * c - b * b) / (2 * a * c)) * 180 / Math.PI; C = Math.acos( (a * a + b * b - c * c) / (2 * a * b)) * 180 / Math.PI; suma = A + B + C; System.out.println("Los lados son c + "]"); = [ " + a + ", " + b + ", " +

44

Cap tulo 4: Instrucciones condicionales y de repeticin o

System.out.println("Los angulos son = [ " + A + ", " + B + ", " + C + "]"); System.out.println("La suma de sus angulos es = " + suma); if (suma == 180) { if (a == b && b == c) System.out.println("Es un triangulo equilatero"); else { if (A == 90 || B == 90 || C == 90) System.out.println("Es un triangulo rectangulo"); else { if (a == b || b == c || a == c) System.out.println("Es un triangulo isoceles"); else { if (A != B && B != C && C != A) System.out.println("Es un triangulo escaleno"); } } } } else System.out.println("Estos valores no forman un triangulo "); } }

Implementacin en C. o
// Ejemplo ec022.cpp /** * Title: Tipos de triangulos * Description: Programa para determinar el tipo de triangulo dados tres lados * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> #include <math.h> int main() { double a = 1, b = 1.5, c = 2; // tama~o de los lados n double A, B, C; // angulos double suma; double PI = 3.1416; A = acos( (b * b + c * c - a * a) / (2 * b * c)) * 180 / PI; B = acos( (a * a + c * c - b * b) / (2 * a * c)) * 180 / PI; C = acos( (a * a + b * b - c * c) / (2 * a * b)) * 180 / PI; suma = A + B + C; printf("Los lados son = [ %f %f %f ]\n", a, b, c); printf("Los angulos son = [ %f %f %f ]\n", A, B, C); printf("La suma de sus angulos es = %f\n", suma); if (suma == 180) { if (a == b && b == c) printf("Es un triangulo equilatero \n"); else { if (A == 90 || B == 90 || C == 90) printf("Es un triangulo rectangulo \n");

4.2. Instrucciones de repeticin for, while, do-while, continue y break o

45

else { if (a == b || b == c || a == c) printf("Es un triangulo isoceles \n"); else { if (A != B && B != C && C != A) printf("Es un triangulo escaleno \n"); } } } } else printf("Estos valores no forman un triangulo \n"); return 0; }

Tarea 6 Tringulos a Dados los valores a = 1, b = 2 y c = 3, note que no forman un tringulo y sin embargo el a programa anterior, dir que se trata de un tringulo. Modicar el cdigo para corregir este a a o error.

4.2.

Instrucciones de repeticin for, while, do-while, continue o y break


Con frecuencia tendremos que hacer que una parte de nuestro programa se repita

(algo a lo que con frecuencia llamaremos bucle), bien mientras se cumpla una condicin o o bien un cierto nmero prejado de veces. u Java incorpora varias formas de conseguirlo. La primera que veremos es la orden while, que hace que una parte del programa se repita mientras se cumpla una cierta condicin. Su formato ser: o a
while (condicin) o sentencia

Es decir, la sintaxis es similar a la de if, con la diferencia de que aquella orden realizaba la sentencia indicada una vez como mximo (si se cumpl la condicin), pero a a o while puede repetir la sentencia ms de una vez (mientras la condicin sea cierta). Al a o igual que ocurr con if, podemos realizar varias sentencias seguidas (dar ms de un a a paso) si las encerramos entre llaves:

46

Cap tulo 4: Instrucciones condicionales y de repeticin o

x = 20; while ( x > 10) { System.out.println("Aun no se ha alcanzado el valor limite"); x --; }

Existe una variante de este tipo de bucle. Es el conjunto do..while, cuyo formato es:
do { sentencias } while (condicion)

En este caso, la condicin se comprueba al nal, lo que quiere decir que las seno tencias intermedias se realizarn al menos una vez, cosa que no ocurr en la construccin a a o anterior (un unico while antes de las sentencias), porque si la condicin era falsa desde o un principio, los pasos que se indicaban a continuacin de while no llegaban a darse ni o una sola vez. Un ejemplo t pico de esta construccin do..while es cuando queremos que el o usuario introduzca una contrasea que le permitir acceder a una cierta informacin: n a o
do { System.out.println("Introduzca su clave de acceso"); claveIntentada = LeerDatosUsuario; // LeerDatosUsuario realmente no existe } while (claveIntentada != claveCorrecta)

En este ejemplo hemos supuesto que existe algo llamado LeerDatosUsuario, para que resulte legible. Pero realmente la situacin no es tan sencilla: no existe ese LeerDao tosUsuario, ni sabemos todav cmo leer informacin del teclado cuando trabajamos en a o o modo texto (porque supondr hablar de excepciones y de otros conceptos que todav son a a demasiado avanzados para nosotros), ni sabemos crear Applets en los que podamos utilizar una casilla de introduccin de textos. As que de momento nos creeremos que algo parecido o a lo que hemos escrito podr llegar a funcionar... pero todav no lo hace. a a Una tercera forma de conseguir que parte de nuestro programa se repita es la orden for. La emplearemos sobre todo para conseguir un nmero concreto de repeticiones. Su u formato es
for ( valor_inicial ; condicion_continuacion ; incremento ) { sentencias }

4.2. Instrucciones de repeticin for, while, do-while, continue y break o

47

(es decir, indicamos entre parntesis, y separadas por puntos y coma, tres rdenes: e o la primera dar el valor inicial a una variable que sirva de control; la segunda orden ser la a a condicin que se debe cumplir para que se repitan las sentencias; la tercera orden ser la o a que se encargue de aumentar -o disminuir- el valor de la variable, para que cada vez quede un paso menos por dar). Esto se ver mejor con un ejemplo. Podr a amos repetir 10 veces un bloque de rdenes o haciendo:
for ( i=1 ; i<=10 ; i++ ) { ... }

O bien podr amos contar descendiendo desde el 20 hasta el 2, con saltos de 2 unidades en 2 unidades, as :
for ( j = 20 ; j > 0 ; j -= 2 ) System.out.println( j );

Nota: se puede observar una equivalencia casi inmediata entre la orden for y la orden while. As el ejemplo anterior se podr reescribir empleando while, de esta , a manera:
j = 20; while ( j > 0 ) System.out.println( j ); j -= 2; }

Precauciones con los bucles: Casi siempre, nos interesar que una parte de nuestro a programa se repita varias veces (o muchas veces), pero no indenidamente. Si planteamos mal la condicin de salida, nuestro programa se puede quedar colgado, repitiendo sin n o los mismos pasos. Se puede modicar un poco el comportamiento de estos bucles con las rdenes o break y continue. La sentencia break hace que se salten las instrucciones del bucle que quedan por realizar, y se salga del bucle inmediatamente. Como ejemplo:
for ( i=1 ; i<=10 ; i++ ) { System.out.println( "Comenzada la vuelta" ); System.out.println( i ); if (i==8) break; System.out.println( "Terminada esta vuelta ); } System.out.println( "Terminado" );

48

Cap tulo 4: Instrucciones condicionales y de repeticin o

En este caso, no se mostrar el texto Terminada esta vuelta para la pasada con a i=8, ni se dar las pasadas de i=9 e i=10, porque ya se ha abandonado el bucle. an La sentencia continue hace que se salten las instrucciones del bucle que quedan por realizar, pero no se sale del bucle sino que se pasa a la siguiente iteracin (la siguiente o vuelta o pasada). Como ejemplo:
for ( i=1 ; i<=10 ; i++ ) { System.out.println( "Comenzada la vuelta" ); System.out.println( i ); if (i==8) continue; System.out.println( "Terminada esta vuelta ); } System.out.println( "Terminado" );

En este caso, no se mostrar el texto Terminada esta vuelta para la pasada con a i=8, pero s se dar la pasada de i=9 y la de i=10. an Tambin esta la posibilidad de usar una etiqueta para indicar dnde se quiere e o saltar con break o continue. Slo se deber utilizar cuando tengamos un bucle que a su vez o a est dentro de otro bucle, y queramos salir de golpe de ambos. Es un caso poco frecuente, a as que no profundizaremos ms, pero s veremos un ejemplo: a
for ( i=1 ; i<=10 ; i++ ) { System.out.println( "Comenzada la vuelta" ); System.out.println( i ); if (i==8) break salida; System.out.println( "Terminada esta vuelta ); } System.out.println( "Terminado" ); salida: ...

En este caso, a mitad de la pasada 8 se saltar hasta la posicin que hemos a o etiquetado como salida (se dene como se ve en el ejemplo, terminada con el s mbolo de dos puntos), de modo que no se escribir en pantalla el texto Terminado (lo hemos a saltado).

4.2.1.

Ejemplo
Hacer un programa que permita calcular la siguiente sumatoria
i=64

S=
i=0

2i

4.2. Instrucciones de repeticin for, while, do-while, continue y break o

49

/** * Title: Sumatoria * Description: Este programa calcula la suma de 1 + 2 + 4 + 8+ 16 + ...2n * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ class ej005 { public static void main (String args[]) { float i=1; float s=0; do { s=((2*s) +1); System.out.println("s="+s); i++; } while (i<=64); } }

La implementacin en C queda: o
// Ejemplo ec005.cpp /** * Title: Sumatoria * Description: Este programa calcula la suma de 1 + 2 + 4 + 8+ 16 + ...2n * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h>

int main () { float i=1; float s=0; do { s=((2*s) +1); printf("s=%f\n", s); i++; } while (i<=64); return 0; }

4.2.2.

Ejemplo
Que realiza el siguiente programa

50

Cap tulo 4: Instrucciones condicionales y de repeticin o

/** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: </p> * @author not attributable * @version 1.0 */ public class ej070 { public static void main(String[] args) { int i, j, k; double x, y, z; for(i=1, x = 100; i<=10; i++, x/=2); System.out.println(x); x = 100; y = 110; while(y-x > 1) { y -= 0.1; x *= 1.1; System.out.println(y + " " +x); } x = 1.1; y = 2; do { x *= x; z = y * 2; System.out.println(x + " " + z); }while (z > 2 && x <3); for(i = 0; i<2; i++) for(j=0; j<2; j++) for(k= 0; k<2; k++) System.out.println("" + i + j + k); } }

Tarea 7 Ciclos Escriba un programa que imprima las siguientes secuencias de nmeros, utilizando en los u tres casos ciclos for, while y do-while 10, 20, 30, 40 ... -7, -3, 1, 5, ... 25, 16, 9, 4, 1, 0, 1, 4, 16, 25

4.3. Ejemplo de sucesiones e Iteracin de punto jo o

51

4.3.
4.3.1.

Ejemplo de sucesiones e Iteracin de punto jo o


Mtodos iterativos para resolver x = g(x) e
Necesitamos una regla, frmula o funcin g(x) con la cual calcularemos temimos o o

sucesivos, para un valor de partida P0 . Lo que se produce es una sucesin de valores Pk o obtenida mediante el proceso iterativo Pk+1 = g(Pk ). La sucesin se ajusta al siguiente o patrn: o

P1 = g(P0 ) P2 = g(P1 ) P3 = g(P2 ) Pk+1 = g(Pk ) Lo que podemos observar de sta sucesin es que si Pk+1 > Pk la sucesin e o o converge a un valor, pero en el caso de que Pk+1 no tienda a Pk tenemos una sucesin o divergente.

Ejemplo Dada la sucesin Pk+1 = Ak con P0 = 1, producir: o a

P1 = A P2 = A A = A2 P3 = A A2 = A3 ... Pk = Ak

52

Cap tulo 4: Instrucciones condicionales y de repeticin o

4.3.2.

Mtodos de punto jo e
Un punto jo de una funcin g(x) es un nmero real P tal que P = g(P ). Geomtrio u e

camente hablando, los puntos jos de una funcin g(x) son los puntos de interseccin de la o o curva y = g(x) con la recta y = x. Ejemplo Consideremos la funcin p = ep y damos un valor inicial p0 = 0.5 o La solucin de esta recurrencia es: o

p1 = e0.5 = 0.606531p2 = 0.545339p3 = 0.579703...pk = 0.567143 La solucin en Java para este algoritmo es: o
} /** * <p>Title: Iteracion de punto fijo</p> * <p>Description: resuelve una ecuacion por el mtodo de punto fijo</p> e * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * Dr. Felix Calderon Solorio. * @version 1.0 */ public class ej018 { static public void main(String args[]) { int iter = 0; double x0, x1; x0 = x1 = 0.5; do { System.out.println("X("+iter+")= " + x1); x0 = x1; x1 = Math.exp(-x0); iter ++; }while (Math.abs((x0-x1)/x1) > 0.001); } }

La implementacin en C es o
// Ejemplo ec018.cpp /** * <p>Title: Iteracion de punto fijo</p> * <p>Description: resuelve una ecuacion por el mtodo de punto fijo</p> e

4.3. Ejemplo de sucesiones e Iteracin de punto jo o

53

* <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * Dr. Felix Calderon Solorio. * @version 1.0 */ #include <stdio.h> #include <Math.h> int main() { int iter = 0; double x0, x1; x0 = x1 = 0.5; do { printf("X(%d)= %f\n", iter, x1); x0 = x1; x1 = exp(-x0); iter ++; }while (fabs((x0-x1)/x1) > 0.001); return 0; }

4.3.3.

Solucin de Sistemas no lineales o


Consideremos el caso de la funciones : f1 (x, y) = x2 2x y + 0.5 f2 (x, y) = x2 + 4y 2 4

y queremos encontrar un mtodo para calcular los ceros de estas funciones, es decir, los e valores x y y que hacen f1 (x, y) = 0 y f 2(x, y) = 0 Podemos resolver el sistema, utilizando el mtodo de iteracin de punto jo. Para e o ello despejamos de la ecuacin 1 a x: o x2 y + 0.5 2

x=

A la segunda ecuacin agregamos un trmino o e

x2 + 4y 2 8y 4 = 8y y= x2 4y 2 + 8y + 4 8

De esto tenemos un sistema en sucesin dado por: o

54

Cap tulo 4: Instrucciones condicionales y de repeticin o

xk+1 = yk+1 =

x2 yk + 0.5 k 2

2 x2 4yk + 8yk + 4 k 8

La solucin de esta sucesin para un valor inicial [0, 1] es: o o k x x 0 0.0000 1.0000 1 -0.2500 1.0000 2 -0.2188 0.9922 3 -0.2222 0.9940 4 -0.2223 0.9938 5 -0.2222 0.9938 6 -0.2222 0.9938 Tarea 8 Solucin de un sistema de ecuaciones o Escribir un programa que permita replicar los resultados del problema anterior. Tarea 9 Nmeros de Fibonacci u Los nmeros de Fibonacci son una sucesin dada por los nmeros 1, 2, 3, 5, 8, 13, 21, 34. u o u Escriba un programa que permita escribir esta sucesin e imprimar los primeros 30 nmeros o u utilizando numeros

4.4.

Control de ujo incondicional. Sentencia go-to


El uso del GOTO implica un salto incondicional de un lugar a otro del programa.

Esta prctica hace que los programas sean muy dif a ciles de corregir mantener. Si no o quedara ms remedio que usarlo, (y en programacin estructurada SIEMPRE hay remedio) a o debe marcarse el destino del salto mediante un nombre seguido por dos puntos.
if( c == 0 ) goto OTRO_LADO;

............................. ............................. OTRO_LADO: printf(........

4.4. Control de ujo incondicional. Sentencia go-to

55

En este caso si c es cero se saltan todas las sentencias entre el if y el destino, continundose con la ejecucin del printf() . El destino puede ser posterior como anterior a o al GOTO invocante. Nota: esta instruccin es exclusiva de C y no esta denida en Java. o

Cap tulo 5

Funciones y la estructura de programacin o


5.1. Funciones y estructura de programacin en C. o
En C existen un conjunto de funciones matemticas de biblioteca las que permiten a al programador ciertos clculos comunes. Algunos ejemplos de estas funciones son: a funcin o double acos(double x) double asin(double x) double atan(double x) double atan2(double y, double x) double ceil(double x) double cos(double x) double cosh(double x) double exp(double x) double fabs(double x) double oor(double x) double fmod(double x, double y) double log(double x) double log10(double x) double pow(double x, double y) double sin(double x) double sinh(double x) double sqrt(double x) double tan(double x) double tanh(double x) descripcin o arco coseno de x. arco seno de x. arco tangente en radianes. arco tangente de las dos variables x e y. Redondea x hacia arriba al entero ms cercano. a coseno de x. coseno hiperblico de x. o Devuelve el valor de e valor absoluto Redondea x hacia abajo al entero ms cercano. a Calcula el resto de la divisin de x entre y. o Devuelve el logaritmo neperiano de x. Devuelve el logaritmo decimal de x. Devuelve el valor de x elevado a y. Devuelve el seno de x. Regresa el seno hiperblico de x. o Devuelve la ra cuadrada no negativa de x. z Devuelve la tangente de x. Devuelve la tangente hiperblica de x. o 57

58

Cap tulo 5: Funciones y la estructura de programacin o

Las funciones permiten al programador modularizar un programa. Todas las variables declaradas en las deniciones de funciones son variable locales, son conocidas solo en la funcin en la cual estn denidas. La mayor parte de las funciones tienen una liso a ta de parmetros. Los parmetros proporcionan la forma de comunicar informacin entre a a o funciones. Los parmetros de una funcin tambin son variable locales. a o e El formato para denir una funcin es o
tipo_de_valor_de_regreso nombre_de_la_funcin (lista de o parametros) { declaraciones; enunciados; }

El nombre de la funcin comienza con una letra y continua con letra numero o el o caracter , nunca debe dejarse espacios en blanco. El tipo de valor de regreso es el tipo de los datos del resultado que una funcin devolver por valor. Un tipo de valor de regreso o a no especicado ser siempre supuesto por el compilador cono int (en el caso de C). a La manera de regresar un valor es utilizando la sentencia
return expresion;

5.1.1.

Ejemplo de la funcin cuadrado o


A continuacin se presenta la implementacin de una simple funcin que calcula o o o

el cuadrado de un numero otante.


//Ejemplo ec019.cpp /** * <p>Title: Ejemplo de una funcin</p> o * <p>Description: Realiza la funcin x2</p> o * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> float cuadrado(float); // prototipo de funcin o

5.1. Funciones y estructura de programacin en C. o

59

int main() { int x; for(x=1; x<=10; x++) printf("%f ", cuadrado(x)); return 0; } // Definicin o de la funcin o

float cuadrado(float y) { return y*y; }

Una implementacin similar la tenemos en Java, en donde se siguen las mismas o reglas para denir el nombre de una funcin y los valores que recibe como parmetros y o a regresa como resultado.
/** * <p>Title: Ejemplo de una funcin</p> o * <p>Description: Realiza la funcin x2</p> o * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej019 { public static void main(String[] args) { int x; for(x=1; x<=10; x++) System.out.print(cuadrado(x) + " "); } public static float cuadrado(float y) { return y*y; } }

5.1.2.

Prototipos de funcin o
Un prototipo de funcin le indica al compilador el tipo de dato regresado por la o

funcin, el nmero de parmetros que la funcin espera recibir, los tipos de dichos parmeo u a o a tros y el orden en que se esperan dichos parmetros. a

5.1.3.

Ejemplo de la funcin mximo o a


Realizar un programa que permita calcular para tres nmeros enteros cual es el u

mayor y cual es el menor. La implementacin en C y Java se muestra a continuacin, note o o

60

Cap tulo 5: Funciones y la estructura de programacin o

que solamente en C, es necesario declarar los prototipos de funcin. o


//Ejemplo ec020.cpp /** * <p>Title: Funcion maximo</p> * <p>Description: Calcula en maximo de tres numeros enteros</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> int maximo(int x, int y, int z); int main() { int a, b, c, max; printf("Dar tres numeros enteros "); scanf("%d%d%d", &a, &b, &c); max = maximo(a,b,c); printf("El maximo es %d\n", max); return 0; } int maximo(int x, int y, int z) { int max = x; if(y > max) max = y; if(z > max) max = z; return max; } /** * <p>Title: Funcin mximo</p> o a * <p>Description: Calcula en mximo de tres numeros enteros</p> a * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Caldern Solorio o * @version 1.0 */ public class ej020 { public static void main(String[] args) { int a, b, c, maximo; System.out.println("Dar tres numeros enteros "); a = Leer.datoInt(); b = Leer.datoInt(); c = Leer.datoInt(); maximo = maximo(a,b,c); System.out.println("El maximo es " + maximo); }

5.2. Mtodos, clases y estructura de programacin en Java e o

61

static public int maximo(int x, int y, int z) { int max = x; if(y > max) max = y; if(z > max) max = z; return max; } }

5.2.

Mtodos, clases y estructura de programacin en Java e o


Cada clase puede tener una serie de atributos (o variables miembro), que son

sus caracter sticas, y varios mtodos (o funciones miembro), que son aquellas cosas que e es capaz de hacer. Pero hasta ahora no lo hab amos aplicado: las clases que hemos creado ten un an unico mtodo (el llamado main, que representaba el cuerpo de la aplicacin) y no ten e o an atributos. Ahora vamos a crear un ejemplo de clase que tendr un par de atributos y varios a mtodos, unos de los cuales devolvern valores y otros no: e a
// RectanguloTexto.java // Primer ejemplo de clase con varios // mtodos y atributos e // Introduccin a Java o class RectanguloTexto {

// --- Atributos: // --- la base y la altura del rectngulo a int altura; int base;

// --- Mtodo "fijaAltura": e // --- Da valor al atributo "altura" // --- No devuelve ningn valor u public void fijaAltura( int valor ) { altura = valor; }

// --- Mtodo "fijaBase": e // --- Da valor al atributo "base" // --- No devuelve ningn valor u public void fijaBase( int valor ) { base = valor; }

62

Cap tulo 5: Funciones y la estructura de programacin o

// --- Mtodo "leeAltura": e // --- Devuelve el valor del atributo "altura", // --- para no acceder directamente a el public int leeAltura( ) { return altura; }

// --- Mtodo "leeBase": e // --- Devuelve el valor del atributo "base", // --- para no acceder directamente a el public int leeBase( ) { return base; }

// --- Mtodo "leeArea": e // --- Devuelve el area del cuadrado // --- para no acceder directamente a el public int leeArea( ) { return altura * base; }

// --- Mtodo "dibuja": e // --- Dibuja un rectangulo en pantalla // --- No devuelve ningn valor u public void dibuja( ) { // Para bucles // Cada linea horizontal // rectangulo que dibujamos

int i, j; String lineaActual;

for (i=0; i<altura; i++) { // Cada fila horiz // Primero la fila esta vacia lineaActual = ""; // Luego a~ado cuadraditos n for (j=0; j<base; j++) lineaActual = lineaActual + "#"; // Y finalmente escribo la lea System.out.println( lineaActual ); } }

// --- Mtodo "main": e // --- Cuerpo de la aplicacin, o // --- Dibuja un par de rectangulos de ejemplo public static void main( String args[] ) { RectanguloTexto r = new RectanguloTexto(); r.fijaAltura( 10 ); r.fijaBase( 20 ); System.out.println( "El area del rectngulo es" ); a System.out.println( r.leeArea() ); System.out.println( "Vamos a dibujarlo..." );

5.2. Mtodos, clases y estructura de programacin en Java e o

63

r.dibuja(); } }

Comentemos cosas: Nuestra clase rectngulo tiene dos atributos: la base y la altura (ambos son nmea u ros enteros). Tiene varios mtodos. Los ms comprensibles son dibuja, que lo muestra el e a rectngulo en pantalla (y no devuelve ningn valor, por eso lo denimos como void), y a u leeArea, que devuelve un nmero entero (int), que es el rea del rectngulo. Pero tambin u a a e hemos incluido mtodos leeAltura, leeBase, jaAltura y jaBase. Esto es para lograr otra e de las caracter sticas deseables de la Programacin Orientada a Objetos, que ya hab o amos comentado: la ocultacin de los detalles. As un cualquier aplicacin que emplease nuestra o , o clase RectanguloTexto no necesita saber cmo son internamente los atributos altura y base o para acceder a ellos. Si ms adelante, nosotros decidimos optimizar al mximo el espacio a a y utilizar atributos de tipo byte (por ejemplo), bastar con modicar ligeramente estos 4 a mtodos para que conviertan de byte a int y viceversa, pero todas las aplicaciones que se e basen en esta clase seguir funcionando sin cambios. Este tipo de detalles hacen que un an programa sea ms robusto. a La salida de este programa ser esta: a El rea del rectngulo es 200 Vamos a dibujarlo... a a
#################### #################### #################### #################### #################### #################### #################### #################### #################### ####################

Por lo dems, este programa no deber presentar mayor dicultad. Vemos que los a a mtodos se denen de la forma que ya hab e amos empleado para main, salvo que en un caso general, puede ocurrir que devuelvan un valor de un cierto tipo, distinto de void (en nuestro caso, tenemos varios que devuelven nmeros enteros -int-). u Para indicar qu valor queremos devolver, se emplea la sentencia return, como se e ve en el ejemplo.

64

Cap tulo 5: Funciones y la estructura de programacin o

Dentro de un cierto mtodo podemos tener variables temporales. Es algo que ya e hemos usado ms de una vez en main, con variables como las t a picas i y j que emplebamos a para contar en los bucles. Estas variables auxiliares slo existen dentro del mtodo en el o e que las hemos denido. Por ejemplo, podr amos haber creado una variable auxiliar para calcular el rea: a
public int leeArea( ) { int valorArea; valorArea = altura * base; return valorArea; }

En este caso, hemos denido una variable llamada valorArea. Le damos el valor que nos interesa y devolvemos ese valor. Pero no tiene sentido mencionar la variable valorArea desde ninguna otra parte de nuestro programa, porque desde ningn otro sitio se conoce u esta variable, y obtendr amos un mensaje de error. Esto es lo que se conoce como una variable local (o una variable de mbito local). a Tambin podemos indicar parmetros (datos adicionales) para nuestros mtodos. e a e Es algo que tambin llevamos haciendo desde el principio, casi sin darnos cuenta. Por e ejemplo, siempre hemos indicado main con un extrao parmetro llamado args[], de tipo n a String, y que todav no hemos utilizado. De igual modo, cada vez que utilizamos println, a indicamos entre comillas el texto que queremos que aparezca en pantalla (y que tambin es e un parmetro). a En este ejemplo vamos teniendo parmetros ms fciles de comprender, como en a a a el caso de:
public void fijaAltura( int valor ) { altura = valor; }

Este mtodo jaAltura tiene un parmetro llamado valor, que es un nmero entero e a u (int), y que es el valor que queremos que tome la altura. Podemos indicar ms de un parmetro a un mtodo. En ese caso, los separaremos a a e empleando comas. Por ejemplo, nos podr interesar dar valores a la vez a la base y a la a altura, creando un mtodo como ste: e e

5.2. Mtodos, clases y estructura de programacin en Java e o

65

public void fijaAlturaYBase( int valorAlt, int valor Anc ) { altura = valorAlt; base = valorAnc; }

Todo esto es la base sobre cmo se usan las funciones en Java (que en este lenguaje o llamamos funciones miembro o mtodos, siguiendo la nomenclatura habitual en Programae cin Orientada a Objetos). Cada vez las iremos empleando con ms frecuencia, y eso ser lo o a a que ayude a terminar de comprender su empleo en la prctica... espero... a

5.2.1.

Programacin modular y Java o


Lo habitual en una aplicacin medianamente seria es que no tengamos una sola o

clase, como hasta ahora, sino que realmente existan varios objetos de distintas clases, que se relacionan entre s . En Java podemos denir varias clases dentro de un mismo chero, con la unica condicin de que slo una de esas clases sea declarada como pblica. En un caso general, lo o o u ms correcto ser denir cada clase en un chero. Aun as vamos a ver primero un ejemplo a a , que contenga dos clases en un solo chero
// DosClases.java // Primer ejemplo de una clase nuestra // que accede a otra tambin nuestra, e // ambas definidas en el mismo fichero // Introduccin a Java o class Principal {

public static void main( String args[] ) { Secundaria s = new Secundaria(); s.saluda(); saluda(); } // Saludo de "Secundaria" // Saludo de "Principal"

public static void saluda() { System.out.println( "Saludando desde <Principal>" ); } } // ---------------------------------------------------class Secundaria { public void saluda() { System.out.println( "Saludando desde <Secundaria>" );

66

Cap tulo 5: Funciones y la estructura de programacin o

} }

Como siempre, hay cosas que comentar: En este fuente hay dos clases, una llamada Principal y otra llamada Secundaria. La clase Secundaria slo tiene un mtodo, llamado saluda, mientras que la clase Principal o e tiene dos mtodos: main (el cuerpo de la aplicacin) y otro llamado saluda, al igual que e o el de Secundaria. Ambos mtodos saluda se limitan a mostrar un mensaje en pantalla, e que es distinto en cada caso. En el mtodo main, denimos y creamos un objeto de la e clase Secundaria, despus llamamos al mtodo saluda de dicho objeto (con al expresin e e o s.saluda()) y luego llamamos al mtodo Saluda de la propia clase Principal (escribiendo e solamente saluda()).. Para compilar este programa teclear amos, como siempre: javac DosClases.java y entonces se crear dos cheros llamados an Principal.class Secundaria.class que podr amos probar tecleando java Principal El resultado se mostrar en pantalla es: a Saludando desde PrincipalSaludando desde Secundaria Ahora vamos a ver un ejemplo en el que las dos clases estn en dos cheros distintos. a Tendremos una clase sumador que sea capaz de sumar dos nmeros (no es gran cosa, u sabemos hacerlo sin necesidad de crear clases a propsito, pero nos servir como ejemplo) o a y un programa principal que la utilice. La clase Sumador, con un unico mtodo calcularSuma, que acepte dos nmeros e u enteros y devuelva otro nmero entero, ser u a:
// Sumador.java // Segundo ejemplo de una clase nuestra // que accede a otra tambin nuestra. e // Esta es la clase auxiliar, llamada // desde "UsaSumador.java" // Introduccin a Java o class Sumador { public int calcularSuma( int a, int b ) { return a+b; } }

5.2. Mtodos, clases y estructura de programacin en Java e o

67

Por otra parte, la clase UsaSumador emplear un objeto de la clase Sumador, a llamado suma, desde su mtodo main, as e :
// UsaSumador.java // Segundo ejemplo de una clase nuestra // que accede a otra tambin nuestra. e // Esta es la clase principal, que // accede a "Sumador.java" // Introduccin a Java o class UsaSumador {

public static void main( String args[] ) { Sumador suma = new Sumador(); System.out.println( "La suma de 30 y 55 es" ); System.out.println( suma.calcularSuma (30,55) ); } }

Para compilar estos dos fuentes, si tecleamos directamente javac usaSumador.java recibir amos como respuesta un mensaje de error que nos dir que no existe la a clase Sumador:
UsaSumador.java:13: Class Sumador not found. Sumador suma = new Sumador(); ^ UsaSumador.java:13: Class Sumador not found. Sumador suma = new Sumador(); ^ 2 errors

La forma correcta ser compilar primero Sumador y despus UsaSumador, para a e despus ya poder probar el resultado: e javac Sumador.java javac UsaSumador.java java UsaSumador La respuesta, como es de esperar, ser a: La suma de 30 y 55 es 85 Tarea 10 Unidades, decenas y Centenas Hacer un programa que dado un numero entre 0 y 999 permita averiguar cuantas unidades, decenas y centena contiene. Implemente estas tres funciones llamada unidades, decenas y centenas las cuales en lugar de regresar el nmero arbigo, regresar su representacin en u a a o Romano.

68

Cap tulo 5: Funciones y la estructura de programacin o

5.3.

Ejemplo programacin modular Java C o


Hacer la implementacin de la funcin seno utilizando serie de Taylor. o o La funcin seno puede ser calculada utilizando la serie o x3 x5 x7 x9 + + .... 3! 5! 7! 9!

seno(x) = x

Para llevar a cabo la implementacin necesitamos de dos funciones mas, la funcin o o factorial y la funcin potencia. Comenzaremos por escribir la funcin factorial. El factorial o o de un nmero se dene como u

1! = 1 2! = 1 2 3! = 1 2 3 4! = 1 2 3 4

n! = 1 2 3 4 5 ... n 1 n y la implementacin queda como o


double factorial(int x) { int i; double fact = 1; for(i=1; i<=x; i++) fact *= i; return fact; }

Tenemos que elevar un nmero real a una potencia entera, as pues, si x es el u nmero real para elevarlo a cualquier potencia hacemos: u

x2 = x x

5.3. Ejemplo programacin modular Java C o

69

x3 = x x x

xn = x x x ... x La implementacin de esta funcin es: o o


double pow(double x, int n) { int i; double pow =1; if(x==0) return 0; for(i=1; i<=n; i++) pow = pow*x; return pow; }

5.3.1.

Implementacin en Java o
Finalmente para llevar a cabo la funcin seno, denimos una clase a la cual llamao

mos funciones. En esta clase se encuentra denida la funcin seno, pow y factorial, como o miembros estticos. a
/** * <p>Title: Funciones Trigonometricas</p> * <p>Description: Implementa la funcin seno utilizando series de Taylor</p> o * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class Mat_fun { public static double seno(double x) { int i; double s = 0; int signo = 1; for (i = 1; i < 10; i += 2) { s += signo * pow(x, i) / factorial(i); signo *= -1; } return s; } public static double factorial(int x) { int i; double fact = 1; for (i = 1; i <= x; i++) fact *= i;

70

Cap tulo 5: Funciones y la estructura de programacin o

return fact; } public static double pow(double x, int n) { int i; double pow = 1; if (x == 0)return 0; for (i = 1; i <= n; i++) pow = pow * x; return pow; } }

Para hacer uso de esta clase escribimos el siguiente programa.

/** * <p>Title: Uso de la funciones Mat_fun</p> * <p>Description: Utiliza las funciones creadas </p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej038 { static public void main(String args[]) { int i,N; double inicio = -3.1416, fin = 3.1416, incremento = 0.1; N = (int)((fin - inicio)/incremento) + 1; double x, y; for(i=0; i<N; i++) { x = inicio + incremento *i; y = funciones.seno(x); System.out.println(x + " " + y); } } }

Note, en la clase prueba se estn utilizando dos clases, la clase funciones y la clase a grca. En la primera no se hace declaracin de la clase, simplemente se utiliza ya que sus a o funciones fueron declarados como miembros estticos. En la segunda no se da esta situacin a o y se hace necesario hacer la declaracin para su uso. o

5.3. Ejemplo programacin modular Java C o

71

5.3.2.

Implementacin en C o
En este caso escribiremos dos archivos, el primero Mat fun.cpp y uno segundo

ec038.cpp. El cdigo del primero es o


//Ejemplo de Mat_fun.cpp /** * <p>Title: Funciones Trigonometricas</p> * <p>Description: Implementa la funcin seno utilizando series de Taylor</p> o * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ double seno(double x); double factorial(int x); double pow(double x, int n);

double seno(double x) { int i; double s = 0; int signo = 1; for (i = 1; i < 10; i += 2) { s += signo * pow(x, i) / factorial(i); signo *= -1; } return s; } double factorial(int x) { int i; double fact = 1; for (i = 1; i <= x; i++) fact *= i; return fact; } double pow(double x, int n) { int i; double pow = 1; if (x == 0)return 0; for (i = 1; i <= n; i++) pow = pow * x; return pow; }

Para probar el archivo tenemos que escribir el cdigo: o


//Ejemplo ec038.cpp /** * <p>Title: Uso de la funciones Mat_fun</p> * <p>Description: Utiliza las funciones creadas </p>

72

Cap tulo 5: Funciones y la estructura de programacin o

* <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> #include "Mat_fun.cpp" int main() { int i,N; double inicio = -3.1416, fin = 3.1416, incremento = 0.1; N = (int)((fin - inicio)/incremento) + 1; double x, y; for(i=0; i<N; i++) { x = inicio + incremento *i; y = seno(x); printf("%f %f \n", x, y); } return 0; }

Note que para incluir las funciones en C se utiliza la instruccin o


#include "Mat_fun.cpp"

la cual da a conocer al compilador en donde se localizan las funciones. Tarea 11 Funcin Coseno o Modicar los cdigos del ejemplo anterior para implementar la funcin coseno o o

5.4.

Recursividad
Un mtodo recursivo es un mtodo que se llama a si mismo directa o indirectamente e e

o a travs de otro mtodo. Un ejemplo interesante de recursion es la funcin factorial. La e e o denicin de factorial esta dada por el producto: o

n! = n (n 1) (n 2) ... 3 2 1 Note que esta denicin la podemos escribir de manera recursiva como: o n! = n*(n-1)!

5.4. Recursividad

73

Este mtodo lo podemos escribir en JAVA como: e


/** * <p>Title: factorial</p> * <p>Description: Calcula el factorial de un numero usando recursividad</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class factorial { static public void main(String args[]) { for (int i = 0; i < 10; i++) System.out.println(i + "! = " + factorial(i)); } static public double factorial(int N) { if (N == 0)return 1; else return (N * factorial(N - 1)); } }

Y su implementacin en C queda como o


// factorial.cpp /** * <p>Title: factorial</p> * <p>Description: Calcula el factorial de un numero usando recursividad</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> double factorial(int N) ; int main() { for (int i = 0; i < 10; i++) printf("%d! = %f\n", i, factorial(i)); return 0; } double factorial(int N) { if (N == 0)return 1; else return (N * factorial(N - 1)); }

Otro ejemplo de denicin recursiva es la multiplicacin de nmeros naturales. El o o u producto a*b, donde a y b son enteros positivos, puede denirse
/** * <p>Title: Multiplicacin</p> o * <p>Description: Multiplica dos numeros utilizando recursividad</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p>

74

Cap tulo 5: Funciones y la estructura de programacin o

* @author Dr. Felix Calderon Solorio * @version 1.0 */ public class multiplica { static public void main(String args[]) { int x=4, y=5; System.out.println(multiplica(4,5)); } static public double multiplica(int x, int y) { if(y == 1) return x; else return (x + multiplica(x,y-1)); } }

Y su implementacin en C es o
// Ejemplo multiplica.cpp /** * <p>Title: Multiplicacin</p> o * <p>Description: Multiplica dos numeros utilizando recursividad</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> double multiplica(int x, int y); int main() { int x=4, y=5; printf("%f\n", multiplica(4,5)); return 0; } double multiplica(int x, int y) { if(y == 1) return x; else return (x + multiplica(x,y-1)); }

5.5.
5.5.1.

Ejemplos de programas recursivos


mtodo de bisecciones e
Este mtodo es conocido tambin como de corte binario. de particin en dos ine e o

tervalos iguales o mtodo de Bolzano. Es un mtodo de bsqueda incremental donde el e e u intervalo de bsqueda se divide en dos. Si la funcin cambia de signo sobre un intervalo, u o se calcula el valor en el punto medio. El nuevo intervalo de bsqueda ser aquel donde el u a producto de la funcin cambie de signo. o

5.5. Ejemplos de programas recursivos

75

Considere la funcin f(x) = x-cosx, a priori sabemos que la funcin tiene un cruce o o por cero en el intervalo [0,1], as que nuestra bsqueda se concentrar en este. u a iter 0 1 2 3 4 5 6 7 8 9 inicio 0.0 0.5 0.5 0.625 0.6875 0.71875 0.734375 0.734375 0.73828125 0.73828125 mitad 0.5 0.75 0.625 0.6875 0.71875 0.734375 0.7421875 0.73828125 0.740234375 0.7392578125 n 1.0 1.0 0.75 0.75 0.75 0.75 0.75 0.7421875 0.7421875 0.740234375 f(ini) -1.0 -0.3775 -0.3775 -0.1859 -0.0853 -0.0338 -0.0078 -0.0078 -0.0013 -0.0013 f(mitad) -0.3775 0.0183 -0.1859 -0.0853 -0.0338 -0.0078 0.0051 -0.0013 0.0019 0.0002 f(n) 0.4596 0.4596 0.0183 0.0183 0.0183 0.0183 0.0183 0.0051 0.0051 0.0019

La implementacin recursiva de este algoritmo en C es: o


//Ejemplo ec039.cpp /** * <p>Title: Mtodo de Bisecciones</p> e * <p>Description: Calcula el cruce por cero de una funcin utlizando el o * metodo de bisecciones</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> #include <Math.h> double Biseccion(double ini, double fin); double funcion(double x); int main() { printf("La solucion esta en %f", Biseccion(0,1)); return 0; } double Biseccion(double ini, double fin) { double mitad; mitad = (fin + ini)/2.0; if((fin - ini) > 0.001) { if(funcion(ini)*funcion(mitad) < 0) return Biseccion(ini, mitad); else return Biseccion(mitad, fin); } else return (mitad); } double funcion(double x) { return (x - cos(x)); }

y en java es:

76

Cap tulo 5: Funciones y la estructura de programacin o

/** * <p>Title: Mtodo de Bisecciones</p> e * <p>Description: Calcula el cruce por cero de una funcin utlizando el o * metodo de bisecciones</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej039 { static public void main(String args[]) { System.out.println("La solucion estan en " + Biseccion(0,1)); } public static double Biseccion(double ini, double fin) { double mitad; mitad = (fin + ini)/2.0; if((fin - ini) > 0.001) { if(funcion(ini)*funcion(mitad) < 0) return Biseccion(ini, mitad); else return Biseccion(mitad, fin); } else return (mitad); } public static double funcion(double x) { return (x - Math.cos(x)); } }

5.5.2.

Torres de Hanoi
El ejemplo ms conocido, de recursividad entre los programadores, es el problema a

de las torres de Hanoi. Para este juego, se tienen tres postes (A, B, C) y un conjunto n de discos colocados de mayor a menor dimetro en alguno de los postes, por ejemplo el poste a A. La meta es mover todos los discos del poste A al poste C con las siguientes restricciones: en cada movimiento solo se puede tomar un disco y colocarlo en cualquier poste y no se debe colocar, un en un poste, un disco de dimetro mayor sobre un disco de dimetro menor. a a La implementacin en C queda o
//Ejemplo ec051.cpp /** * Title: Las Torres de Hanoi * Description: Este programa da los movimientos minimos para mover n discos * del poste A al B * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */

5.5. Ejemplos de programas recursivos

77

#include <stdio.h> void mover(char a, char b, char c, int n); int main() { mover(A, C, B, 3); return 0; } void mover(char a, char b, char c, int n) { if (n > 0) { mover(a, c, b, n - 1); printf("Mover un disco del poste %c al poste %c\n", a, c); mover(b, a, c, n - 1); } }

La implementacin en Java queda de la siguiente manera o


/** * Title: Las Torres de Hanoi * Description: Este programa da los movimientos minimos para mover n discos * del poste A al B * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ public class ej051 { public static void main(String[] args) { mover("A", "C", "B", 3); } public static void mover(String a, String b, String c, int n) { if (n > 0) { mover(a, c, b, n - 1); System.out.println("Mover un disco del poste " + a + " al poste " + c); mover(b, a, c, n - 1); } } }

La solucin con tres discos es: o


Mover un disco del poste A al poste B Mover un disco del poste A al poste C Mover un disco del poste B al poste C Mover un disco del poste A al poste B Mover un disco del poste C al poste A

78

Cap tulo 5: Funciones y la estructura de programacin o

Mover un disco del poste C al poste B Mover un disco del poste A al poste B

Tarea 12 Calculadora recursiva Hacer un conjunto de funciones que realice las cuatro operaciones bsicas de suma, resta, a multiplicacin y divisin utilizando recursividad. Estas funciones debern estar denidas en o o a un archivo diferente a donde se localiza la funcin main con el objeto de hacer programacin o o modular.

5.5.3.

Algoritmo de quicksort
Sea x un arreglo y n el nmero de elementos en arreglo que se debe ordenar. Elegir u

un elemento a de una posicin especica en el arreglo (por ejemplo, a puede elegirse como o el primer elemento del arreglo. Suponer que los elemento de x estn separados de manera a que a est colocado en la posicin j y se cumplen las siguientes condiciones. a o 1. Cada uno de los elementos en las posiciones de 0 a j-1 es menor o igual que a. 2. Cada uno de los elementos en las posiciones j+1 a n-1 es mayor o igual que a. Observe que si se cumplen esas dos condiciones para una a y j particulares, a es el j-simo menor elemento de x, de manera que a se mantiene en su posicin j cuando el e o arreglo est ordenado en su totalidad. Si se repite este procedimiento con los subarreglos a que van de x[0] a x[j-1] y de x[j+1] a x[n-1] y con todos los subarreglos creados mediante este proceso, el resultado nal ser un archivo ordenado. a Ilustremos el quicksort con un ejemplo. Si un arreglo esta dado por: x = [25 57 48 37 12 92 86 33] y el primer elemento se coloca en su posicin correcta, el arreglo resultante es: o x = [12 25 57 48 37 92 86 33] En este punto 25 esta en su posicin correcta por lo cual podemos dividir el arreglo o en x = [12] 25 [57 48 37 92 86 33]

5.5. Ejemplos de programas recursivos

79

Ahora repetimos el procedimiento con los dos subarreglos x = 12 25 [48 37 33] 57 [92 86] x = 12 25 33 [37 48] 57 [86] [92] x = 12 25 33 [37 48] 57 86 92 x = 12 25 33 37 48 57 86 92 El procedimiento es entonces. Buscar la particin del arreglo j. Ordenar el subarreglo x[0] a x[j-1] Ordenar el o subarreglo x[j+1] a x[n-1] Su implementacin en Java es: o
public void quiksort(int x[],int lo,int ho) { int t, l=lo, h=ho, mid; if(ho>lo) { mid=x[(lo+ho)/2]; while(l<=h) { while((l<ho)&&(x[l]<mid)) while((h>lo)&&(x[h]>mid)) if(l<=h) { t = x[l]; x[l] = x[h]; x[h] = t; ++l; --h; } } if(lo<h) quiksort(x,lo,h); if(l<ho) quiksort(x,l,ho); } }

++l; --h;

Cap tulo 6

Apuntadores y arreglos
6.1.
6.1.1.

Manejo de matrices y vectores


Los vectores
Imaginemos que tenemos que hallar el promedio de 10 nmeros que introduzca u

el usuario (o realizar cualquier otra operacin con ellos). Parece evidente que tiene que o haber una solucin ms cmoda que denir 10 variables distintas y escribir 10 veces las o a o instrucciones de avisar al usuario, leer los datos que teclee, y almacenar esos datos. Si necesitamos manejar 100, 1000 o 10000 datos, resulta todav ms claro que no es eciente a a utilizar una variable para cada uno de esos datos. Por eso se emplean los arrays (o arreglos). Un array es una variable que puede contener varios dato del mismo tipo. Para acceder a cada uno de esos datos emplearemos corchetes. Por ejemplo, si denimos una variable llamada m que contenga 10 nmeros u enteros, accederemos al primero de estos nmeros como m[0], el ultimo como m[9] y el u quinto como m[4] (se empieza a numerar a desde 0 y se termina en n-1). Veamos un ejemplo que halla la media de cinco nmeros (con decimales, double): u
/** * <p>Title: Ejemplo de creacion de un arreglo</p> * <p>Description: crea un arreglo e introduce numeros en el</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Flix Caldern SOlorio e o * @version 1.0 */

81

82

Cap tulo 6: Apuntadores y arreglos

public class ej040 { public static void main( String args[] ) { double a[] = { 10, 23.5, 15, 7, 8.9}; double total = 0; int i; for (i = 0; i < 5; i++) total += a[i]; System.out.println("La media es:"); System.out.println(total / 5); } }

La implementacin de este mismo programa en c es o


//ec040.cpp /** * <p>Title: Ejemplo de creacion de un arreglo</p> * <p>Description: crea un arreglo e introduce numeros en el</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Flix Caldern SOlorio e o * @version 1.0 */ #include <stdio.h> int main() { double a[] = { 10, 23.5, 15, 7, 8.9}; double total = 0; int i; for (i = 0; i < 5; i++) total += a[i]; printf("La media es: %f\n", total / 5); return 0; }

Para denir la variable podemos usar dos formatos: double a[] (que es la sintaxis habitual en C y C++) o bien double[] a (que es la sintaxis recomendada en Java, y posiblemente es una forma ms razonable de escribir la variable a es un array de doubles). a Nota: Quien venga de C y/o C++ tiene que tener en cuenta que en Java no son vlidas deniciones como oat a[5]; habr que asignar los valores como acabamos de hacer, a a o reservar espacio de la forma que veremos a continuacin. o

6.1. Manejo de matrices y vectores

83

Lo habitual no ser conocer los valores en el momento de teclear el programa, a como hemos hecho esta vez. Ser mucho ms frecuente que los datos los teclee el usuario a a o bien que los leamos de algn chero, los calculemos, etc. En este caso, tendremos que u reservar el espacio, y los valores los almacenaremos a medida que vayamos conocindolos. e Para ello, primero declarar amos que vamos a utilizar un array, as :
double[] datos;

y despus reservar e amos espacio (por ejemplo, para 1000 datos) con
datos = new double [1000];

Estos dos pasos se pueden dar en uno solo, as :


double[] datos = new double [1000];

y dar amos los valores de una forma similar a la que hemos visto en el ejemplo anterior:
datos[25] = 100 ; datos[0] = i*5 ; datos[j+1] = (j+5);

Vamos a ver un ejemplo algo ms completo, con tres arrays de nmeros enteros, a u llamados a, b y c. A uno de ellos (a) le daremos valores al denirlo, otro lo deniremos en dos pasos (b) y le daremos jos, y el otro lo deniremos en un paso y le daremos valores calculados a partir de ciertas operaciones:
/** * <p>Title: Arreglos</p> * * <p>Description: inicializa arreglos de varias formas</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */ public class ej041 { public static void main( String args[] ) { int i; // Para repetir con bucles "for"

// ------ Primer array de ejemplo int[] a = { 10, 12345, -15, 0, 7 }; System.out.println( "Los valores de a son:" ); for (i=0; i<5; i++)

84

Cap tulo 6: Apuntadores y arreglos

System.out.println( a[i] ); // ------ Segundo array de ejemplo int[] b; b = new int [3]; b[0] = 15; b[1] = 132; b[2] = -1; System.out.println( "Los valores de b son:" ); for (i=0; i<3; i++) System.out.println( b[i] ); // ------ Tercer array de ejemplo int j = 4; int[] c = new int[j]; for (i=0; i<j; i++) c[i] = (i+1)*(i+1); System.out.println( "Los valores de c son:" ); for (i=0; i<j; i++) System.out.println( c[i] ); } }

La implementacin en C es o
//ec041.cpp /** * <p>Title: Arreglos</p> * * <p>Description: inicializa arreglos de varias formas</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */ #include <stdio.h> #include <stdlib.h> int main( ) { int i; // Para repetir con bucles "for"

// ------ Primer array de ejemplo int a[] = { 10, 12345, -15, 0, 7 }; printf( "Los valores de a son:\n" ); for (i=0; i<5; i++) printf("%d\n", a[i]); // -----int *b Segundo array de ejemplo

= (int*) calloc(3, sizeof(int));

b[0] = 15; b[1] = 132; b[2] = -1; printf( "Los valores de b son:\n" ); for (i=0; i<3; i++)

6.1. Manejo de matrices y vectores

85

printf("%d\n", b[i] ); // ------ Tercer array de ejemplo int j = 4; int *c = new int[j]; for (i=0; i<j; i++) c[i] = (i+1)*(i+1); printf("Los valores de c son: \n" ); for (i=0; i<j; i++) printf("%d\n", c[i]); return 0; }

Ejercicio Hacer una funcin que regrese, los primeros 10 nmeros de la sucesin de Fibonacci. o u o

6.1.2.

Matrices
Las matrices se denen, como un arreglo bidimensional, en donde tenemos un

nmero de renglones N y un nmero de columnas M. La representacin matemtica de una u u o a matriz es : a1,1 a1,2 a1,M

a2,1 a2,2 aN,1 aN,2

a2,M aN,M

Para hacer la denicin en Java de este arreglo hacemos o


double A[][] = new double [N][M];

donde A es el nombre del arreglo N el nmero de renglones y M el nmero de u u columnas. Para hacer referencia al elemento en el i-esimo rengln y la j-esima columna haceo mos A[i][j]. Otra forma de hacer la denicin de un arreglo es mediante la siguiente instruccin o o
double a[][] = {{1,2,3}, {4,5,6}, {7,8,9}};

86

Cap tulo 6: Apuntadores y arreglos

esta instruccin crea un arreglo de 3 renglones con 3 columnas y los elementos lo o dispone de la siguiente manera 1 2 3

A= 4 5 6 7 8 9

6.1.3.

Ejemplo
Hacer un programa que almacene la matriz anterior en un arreglo, la eleve al

cuadrado e imprima el resultado en la pantalla.


/** * <p>Title: Arreglo bidimensional: Matriz</p> * * <p>Description: Declara una Matriz y almacena valores en ella</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */ public class ej042 { static public void main(String args[]) { double a[][] = {{1,2,3}, {4,5,6}, {7,8,9}}; double b[][] = new double [3][3]; int i, j; for(i=0; i< 3; i++) for(j=0; j<3; j++) b[i][j] = a[i][j] * a[i][j]; for(i=0; i< 3; i++) { for(j=0; j<3; j++) System.out.print(b[i][j] + " "); System.out.println(""); } } }

La misma implementacin pero en C es o


//ec042.cpp /** * <p>Title: Arreglo bidimensional: Matriz</p> * * <p>Description: Declara una Matriz y almacena valores en ella</p> *

6.1. Manejo de matrices y vectores

87

* <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */ #include <stdio.h> int main() { double a[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; double b[3][3] = {0,0,0,0,0,0,0,0,0} ; int i, j;

for(i=0; i< 3; i++) for(j=0; j<3; j++) b[i][j] = a[i][j] * a[i][j]; for(i=0; i< 3; i++) { for(j=0; j<3; j++) printf("%f ", b[i][j]); printf("\n"); } return 0; }

6.1.4.

Ejemplo
Hacer una funcin que reciba un nmero y regrese un cuadro de texto lleno de o u

asteriscos, del mismo tamao que el nmero que recibe y con el nmero en la diagonal. n u u As pues, esta funcin dado el nmero 4 regresara la informacin o u o
4*** *4** **4* ***4

La implementacin en C queda o
//Ejemplo ec043.cpp /** * <p>Title: Ejemplo de llenado de matrices</p> * * <p>Description: Llena una matriz con asteriscos</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Felix Calderon Solorio * @version 1.0 */

88

Cap tulo 6: Apuntadores y arreglos

#include <stdio.h> #include <stdlib.h> void imprime(char **a, int n); char ** llena(int n); int main() { char **a; int n = 2; a = llena(n); imprime(a, n); return 0; } char ** llena(int n) { char **aux; int i, j; aux = (char **) calloc(n, sizeof(char*)); for(i=0; i<n; i++) aux[i] = (char *) calloc(n, sizeof(char)); for(i=0; i<n; i++) for(j=0; j<n; j++) if(i==j) aux[i][j] = (char) (n+48); else aux[i][j] = *; return aux; } void imprime(char **a, int n) { int i, j; for(i=0; i<n; i++) { for (j = 0; j < n; j++) printf("%c", a[i][j]); printf("\n"); } }

Y la implementacin en Java o
/** * <p>Title: Ejemplo de llenado de matrices</p> * * <p>Description: Llena una matriz con asteriscos</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej043 { public static void main(String[] args) { char a[][];

6.2. Cadena de Texto

89

a = llena(10); imprime(a); } public static char[][] llena(int n) { char aux[][] = new char[n][n]; int i, j; for(i=0; i<n; i++) for(j=0; j<n; j++) if(i==j) aux[i][j] = (char) (n+48); else aux[i][j] = *; return aux; } public static void imprime(char a[][]) { int i, j, n = a.length; for(i=0; i<n; i++) { for (j = 0; j < n; j++) System.out.print(a[i][j]); System.out.println(); } } }

Tarea 13 Tablas de multiplicar Escribir una funcin que almacene en un arreglo bidimensional las tablas de multiplicar. La o funcin recibir el nmero y regresara el arreglo lleno. o a u

6.2.
6.2.1.

Cadena de Texto
En Java
Las cadenas de texto. Una cadena de texto (en ingls, string) es un bloque e

de letras, que usaremos para poder almacenar palabras y frases. En algunos lenguajes, podr amos utilizar un array de chars para este n, pero en Java no es necesario, porque tenemos un tipo cadena espec co ya incorporado en el lenguaje. Realmente en Java hay dos variantes de las cadenas de texto: existe una clase llamada String y otra clase llamada StringBuer. Un String ser una cadena de a caracteres constante, que no se podr modicar (podremos leer su valor, extraer parte de a

90

Cap tulo 6: Apuntadores y arreglos

l, etc.; para cualquier modicacin, realmente Java crear una nueva cadena), mientras e o a que un StringBuer se podr modicar con ms facilidad (podremos insertar letras, a a dar la vuelta a su contenido, etc) a cambio de ser ligeramente menos eciente (ms lento). a Vamos a ver las principales posibilidades de cada uno de estos dos tipos de cadena de texto y luego lo aplicaremos en un ejemplo. Podemos concatenar cadenas (juntar dos cadenas para dar lugar a una nueva) con el signo +, igual que sumamos nmeros. Por otra parte, los mtodos de la clase String son: u e length() : Devuelve la longitud (nmero de caracteres) de la cadena u charAt (int pos) : Devuelve el carcter que hay en una cierta posicin a o toLowerCase() : Devuelve la cadena convertida a minsculas u toUpperCase(): Devuelve la cadena convertida a maysculas u substring(int desde, int cuantos) : Devuelve una subcadena: varias letras a partir de una posicin dada o replace(char antiguo, char nuevo) : Devuelve una cadena con un carcter a reemplazado por otro trim() : Devuelve una cadena sin espacios de blanco iniciales ni nales startsWith(String subcadena) : Indica si la cadena empieza con una cierta subcadena endsWith(String subcadena) : Indica si la cadena termina con una cierta subcadena indexOf(String subcadena, [int desde]) : Indica la posicin en que se encueno tra una cierta subcadena (buscando desde el principio, a partir de una posicin opcional) o lastIndexOf(String subcadena, [int desde]) : Indica la posicin en que se o encuentra una cierta subcadena (buscando desde el nal, a partir de una posicin opcional) o valueOf( objeto ) : Devuelve un String que es la representacin como texto del o objeto que se le indique (nmero, boolean, etc.) u concat(String cadena) : Devuelve la cadena con otra aadida a su nal (concan tenada) Tambin se pueden concatenar cadenas con - e equals(String cadena) : Mira si las dos cadenas son iguales (lo mismo que = =)

6.2. Cadena de Texto

91

equals-IgnoreCase(String cadena) : Comprueba si dos cadenas son iguales, pero despreciando las diferencias entre maysculas y minsculas u u compareTo(String cadena2) : Compara una cadena con la otra (devuelve 0 si son iguales, negativo si la cadena es menor que cadena2 y positivo si es mayor). Como se ve, en ningn momento estamos modicando el String de partida. Eso s u , en muchos de los casos creamos un String modicado a partir del original. El mtodo compareTo se basa en el orden lexicogrco: una cadena que empiece e a por .Ase considerar menorque otra que empiece por la letra B; si la primera letra es a igual en ambas cadenas, se pasa a comparar la segunda, y as sucesivamente. Las maysculas u y minsculas se consideran diferentes. u Hay alguna otra posibilidad, de uso menos sencillo, que no veremos (al menos por ahora), como la de volcar parte del String en un array de chars o de bytes. Los mtodos de la clase StringBuer son: e length() : Devuelve la longitud (nmero de caracteres) de la cadena u setLength() : Modica la longitud de la cadena (la trunca si hace falta) charAt (int pos) : Devuelve el carcter que hay en una cierta posicin a o setCharAt(int pos, char letra) : Cambia el carcter que hay en una cierta a posicin o toString() : Devuelve el StringBuer convertido en String reverse() : Cambia el orden de los caracteres que forman la cadena append( objeto ) : Aade otra cadena, un nmero, etc. al nal de la cadena n u insert(int pos, objeto) : Aade otra cadena, un nmero, etc. en una cierta n u posicin o ver [Mark C Chan98] Al igual que ocurre con los strings, existe alguna otra posibilidad ms avanzada, a que no he comentado, como la de volcar parte del String en un array de chars, o de comprobar la capacidad (tamao mximo) que tiene un StringBuer o jar dicha capacidad. n a Un comentario extra sobre los Strings: Java convertir a String todo aquello que a indiquemos entre comillas dobles. As son vlidas expresiones como Prueba.length() y , a tambin podemos concatenar varias expresiones dentro de una orden System.out.println: e

92

Cap tulo 6: Apuntadores y arreglos

System.out.println( "Texto: " + texto1 + 5

+ 23.5 );

Vamos a ver un ejemplo que aplique la mayor de todo esto: a


// Strings1.java // Aplicacin de ejemplo con Strings o // Introduccin a Java, o class Strings1 { public static void main( String args[] ) { String texto1 = "Hola"; String texto2 = new String("Prueba"); // Forma "sencilla" // Usando un constructor

System.out.println( "La primera cadena de texto es :" ); System.out.println( texto1 ); System.out.println( "Concatenamos las dos: " + texto1 + texto2 ); System.out.println( "Concatenamos varios: " + texto1 + 5 + " " + 23.5 ); System.out.println( "La longitud de la segunda es: " + texto2.length() ); System.out.println( "La segunda letra de texto2 es: " + texto2.charAt(1) ); System.out.println( "La cadena texto2 en maysculas: " u + texto2.toUpperCase() ); System.out.println( "Tres letras desde la posicin 1: " o + texto2.substring(1,3) ); System.out.println( "Comparamos texto1 y texto2: " + texto1.compareTo(texto2) ); if (texto1.compareTo(texto2) < 0) System.out.println( "Texto1 es menor que texto2" ); StringBuffer texto3 = new StringBuffer("Otra prueba"); texto3.append(" mas"); System.out.println( "Texto 3 ahora es: " + texto3 ); texto3.insert(2, "1"); System.out.println( "Y ahora es: " + texto3 ); texto3.reverse(); System.out.println( "Y ahora: " + texto3 );

} }

El resultado de este programa ser el siguiente: a La primera cadena de texto es : Hola Concatenamos las dos: HolaPrueba Concatenamos varios: Hola5 23.5 La longitud de la segunda es: 6 La segunda letra de texto2 es: r La cadena texto2 en maysculas: PRUEBA Tres letras desde la posicin 1: ru Comparamos u o texto1 y texto2: -8 Texto1 es menor que texto2 Texto 3 ahora es: Otra prueba mas Y ahora es: Ot1ra prueba mas Y ahora: sam abeurp ar1tO

6.2. Cadena de Texto

93

6.2.2. 6.2.3.

En C Manejo de cadenas <string.h>


Recordando la presentacin de arreglos hecha en donde las cadenas estn denidas o a

como un arreglo de caracteres o un apuntador a una porcin de memoria conteniendo o caracteres ASCII. Una cadena en C es una secuencia de cero o ms caracteres seguidas por a un caracter NULL o
\0

: F A C U L T A D \0

La cual se puede declarar como


char a[] = "FACULTAD" char b[9] = ""; b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] = = = = = = = = = F; A; C; U; L; T; A; D; \0;

Es importante preservar el caracter de terminacin NULL, ya que con ste es como o e C dene y maneja las longitudes de las cadenas. Todas las funciones de la biblioteca estndar a de C lo requieren para una operacin satisfactoria. o En general, aparte de algunas funciones restringidas en longitud (strncat(), strncmp() y strncpy()), al menos que se creen cadenas a mano, no se debern encontrar problemas. Se a debern usar las funciones para manejo de cadenas y no tratar de manipular las cadenas en a forma manual desmantelando y ensamblando cadenas. Funciones bsicas para el manejo de cadenas a Todas las funciones para manejo de cadenas tienen su prototipo en:
#include <string.h>

94

Cap tulo 6: Apuntadores y arreglos

Las funciones ms comunes son descritas a continuacin: a o char *strcpy(const char *dest, const char *orig) Copia la cadena de caracteres apuntada por orig (incluyendo el carcter terminador a
\0

) al vector apuntado por dest. Las cadenas no deben solaparse, y la de destino, debe ser sucientemente grande como para alojar la copia. int strcmp(const char *s1, const char *s2) Compara las dos cadenas de caracteres s1 y s2. Devuelve un entero menor, igual o mayor que cero si se encuentra que s1 es, respectivamente, menor que, igual a, o mayor que s2. char *strerror(int errnum) Devuelve un mensaje de error que corresponde a un nmero u de error. int strlen(const char *s) Calcula la longitud de la cadena de caracteres. char *strncat(char *s1, const char *s2, size t n) Agrega n caracteres de s2 a s1. int strncmp(const char *s1, char *s2, size t n) Compara los primeros n caracteres de dos cadenas. char *strncpy(const char *s1, const char *s2, size t n) Copia los primeros n caracteres de s2 a s1. strcasecmp(const char *s1, const char *s2) versin que ignora si son maysculas o o u minsculas de strcmp(). u o u strncasecmp(const char *s1, const char *s2, size t n) versin insensible a maysculas o minsculas de strncmp() que compara los primeros n caracteres de s1. u El uso de muchas funciones es directo, por ejemplo:
char *s1 = "Hola"; char *s2; int longitud; longitud = strlen("Hola"); /* long = 4 */ (void) strcpy(s2,s1);

Observar que tanto strcat() y strcopy() regresan una copia de su primer argumento, el cual es el arreglo destino. Observar tambin que orden de los argumentos es arreglo destino e seguido por arreglo fuente lo cual a veces es una situacin para hacerlo incorrectamente. o La funcin strcmp() compara lexicogrcamente las dos cadenas y regresa: o a Menor que cero si s1 es lxicamente menor que s2; Cero si s1 y s2 son lxicae e mente iguales; Mayor que cero si s1 es lxicamente mayor que s2; Las funciones de copiado e

6.2. Cadena de Texto

95

strncat(), strncmp() y strncpy() son versiones ms restringidas que sus contrapartes ms a a generales. Realizan una tarea similar, pero solamente para los primeros n caracteres. Observar que el caracter de terminacin NULL podr ser violado cuando se usa estas funciones, o a por ejemplo:
char *s1 = "Hola"; char *s2 = 2; int longitud = 2; (void) strncpy(s2, s1, longitud); /* s2 = "Ho" */

donde s2 no tiene el terminador NULL. B squeda en cadenas u La biblioteca tambin proporciona varias funciones de bsqueda en cadenas e u char *strchr(const char *s, int c) Devuelve un puntero a la primera ocurrencia del carcter c en la cadena de caracteres s. a char *strrchr(const char *s, int c) Encuentra la ultima ocurrencia del caracter c en la cadena. char *strstr(const char *s1, const char *s2) Localiza la primera ocurrencia de la cadena s2 en la cadena s1. char *strpbrk(const char *s1, const char *s2) Regresa un apuntador a la primera ocurrencia en la cadena s1 de cualquier carcter de la cadena s2, o un apuntador nulo si no a hay un caracter de s2 que exista en s1. size t strspn(const char *s1, const char *s2) Calcula la longitud del segmento inicial de s1 que consta unicamente de caracteres en s2. size t strcspn(const char *s1, const char *s2) Regresa el nmero de caracteres al u principio de s1 que no coinciden con s2. char *strtok(char *s1, const char *s2) Divide la cadena apuntada a s1 en una secuencia de tokens, cada uno de ellos esta delimitado por uno o ms caracteres de la a cadena apuntada por s2. Las funciones strchr() y strrchr() son las ms simples de usar, por ejemplo: a
char *s1 = "Hola"; char *resp; resp = strchr(s1,l);

96

Cap tulo 6: Apuntadores y arreglos

Despus de la ejecucin, resp apunta a la localidad s1 + 2. e o La funcin strpbrk() es una funcin ms general que busca la primera ocurrencia o o a de cualquier grupo de caracteres, por ejemplo:
char *s1 = "Hola"; char *resp; res = strpbrk(s1,"aeiou");

En este caso, resp apunta a la localidad s1 + 1, la localidad de la primera o. La funcin strstr() regresa un apuntador a la cadena de bsqueda especicada o o u un apuntador nulo si la cadena no es encontrada. Si s2 apunta a una cadena de longitud cero (esto es, la cadena ), la funcin regresa s1. Por ejemplo: o
char *s1 = "Hola"; char *resp; resp = strstr(s1,"la");

la cual tendr resp = s1 + 2. a La funcin strtok() es un poco ms complicada en cuanto a operacin. Si el primer o a o argumento no es NULL entonces la funcin encuentra la posicin de cualquiera de los o o caracteres del segundo argumento. Sin embargo, la posicin es recordada y cualquier llamada o subsecuente a strtok() iniciar en sa posicin si en estas subsecuentes llamadas el primer a e o argumento no es NULL. Por ejemplo, si deseamos dividir la cadena s1 usando cada espacio e imprimir cada token en una nueva l nea har amos lo siguiente:
char s1[] = "Hola muchacho grande"; char *t1; for ( t1 = strtok(s1," "); t1 != NULL; t1 = strtok(NULL, " ") ) printf("%s\n",t1);

Se emplea un ciclo for en una forma no regular de conteo: En la inicializacin se llama a la funcin strtok() con la cadena s1. Se termina o o cuando t1 es NULL. Se esta asignando tokens de s1 a t1 hasta la terminacin llamando a o strtok() con el primer argumento NULL. Prueba de clasicacin de caracteres: <ctype.h> o El argumento de las funciones siguientes es un int cuyo valor debe ser EOF o representable por un unsigned char. El valor de retorno es un int. Las funciones regresan cero si el argumento satisface la condicin y un valor diferente de cero si no lo hace. o

6.2. Cadena de Texto

97

Descripcin o letra minscula u letra mayscula u letra mayscula o minscula u u d gito decimal letra mayscula o minscula o d u u gito decimal carcter de control a carcter de impresin excepto espacio a o carcter de impresin incluyendo espacio a o carcter de impresin excepto espacio, letra o d a o gito espacio, avance de l nea, nueva l nea, retorno de carro, tabulador, tabulador vertical isxdigit(c) d gito hexadecimal Funciones de conversin: o int tolower(int c) convierte c a letra minscula u int toupper(int c) convierte c a letra mayscula u Conversin de cadenas o Existen unas cuantas funciones para convertir cadenas a enteros, enteros largos y valores otantes, las cuales se encuentran en la librer <stdlib.h>. Estas son: a double atof(const char *cadena) : Convierte una cadena a un valor otante. int atoi(const char *cadena) : Convierte una cadena a un valor entero. int atol(const char *cadena) : Convierte una cadena a un valor entero largo. double strtod(const char *cadena, char **nap) : Convierte una cadena a un valor de punto otante. double strtol(const char *cadena, char *nap, int base) : Convierte una cadena a un entero largo de acuerdo a una base dada, la cual deber estar entre 2 y 36 inclusive. a unsigned long strtoul(const char *cadena, char *nap, int base) : Convierte una cadena a un entero largo sin signo. Varias de las funciones se pueden usar en forma directa, por ejemplo:
char char char char char char char *cad1 = *cad2 = *cad3 = *cad4 = *cad5 = *cad6 = *cad7; "100"; "55.444"; "1234"; "123cuatro"; "invalido123"; "123E23Hola";

Funcin o islower(c) isupper(c) isalpha(c) isdigit(c) isalnum(c) iscntrl(c) isgraph(c) isprint(c) ispunct(c) isspace(c)

98

Cap tulo 6: Apuntadores y arreglos

int i; float f: i f i i i f = = = = = = atoi(cad1); /* i = 100 */ atof(cad2); /* f = 55.44 */ atoi(cad3); /* i =1234*/ atoi(cad4); /* i = 123 */ atoi(cad5); /* i =0 */ strtod(cad6, &cad7); /* f=1.230000E+25 y cad7=hola*/

Nota: Los caracteres en blanco son saltados. Caracteres ilegales son ignorados. Si la conversin no puede ser hecha se regresa cero y errno es puesta con el valor ERANGE. o Tarea 14 Arbol de Navidad Hacer un programa que permita formar un pino de navidad, utilizando las letras de la palabra feliz Navidad. Utilice ciclos y las operaciones dadas para manejo de cadenas.

6.3.

Apuntadores en C
Un apuntador es una variable que contiene la direccin en memoria de otra variable. o

Se pueden tener apuntadores a cualquier tipo de variable. El operador unario o mondico & devuelve la direccin de memoria de una variable. a o El operador de indireccin o dereferencia * devuelve el contenido de un objeto o apuntado por un apuntador. Para declarar un apuntador para una variable entera hacer:
int *apuntador;

Se debe asociar a cada apuntador un tipo particular. Por ejemplo, no se puede asignar la direccin de un short int a un long int. o Para tener una mejor idea, considerar el siguiente cdigo: o
main() { int x = 1, y = 2; int *ap; ap = &x; y = *ap; x = ap; *ap = 3; }

6.3. Apuntadores en C

99

Cuando se compile el cdigo se mostrar el siguiente mensaje: warning: assignment o a makes integer from pointer without a cast. Con el objetivo de entender el comportamiento del cdigo supongamos que la o variable x esta en la localidad de la memoria 100, y en 200 y ap en 1000. Nota: un apuntador es una variable, por lo tanto, sus valores necesitan ser guardados en algn lado. u
int x = 1, y = 2; int *ap; ap = &x;

100 200 1000 x 1 y 2 ap 100 Las variables x e y son declaradas e inicializadas con 1 y 2 respectivamente, ap es declarado como un apuntador a entero y se le asigna la direccin de x (&x). Por lo que ap o se carga con el valor 100. y = *ap; 100 200 1000 x 1 y 1 ap 100 Despus y obtiene el contenido de ap. En el ejemplo ap apunta a la localidad de e memoria 100 la localidad de x. Por lo tanto, y obtiene el valor de x el cual es 1. x = ap; 100 200 1000 x 100 y 1 ap 100 Como se ha visto C no es muy estricto en la asignacin de valores de diferente tipo o (apuntador a entero). As que es perfectamente legal (aunque el compilador genera un aviso de cuidado) asigna el valor actual de ap a la variable x. El valor de ap en ese momento es 100. *ap = 3; 100 200 1000 x 3 y 2 ap 100 Finalmente se asigna un valor al contenido de un apuntador (*ap). Importante: Cuando un apuntador es declarado apunta a algn lado. Se debe u inicializar el apuntador antes de usarlo. Por lo que: main() int *ap; *ap = 100; puede generar un error en tiempo de ejecucin o presentar un comportamiento o errtico. a

100

Cap tulo 6: Apuntadores y arreglos

El uso correcto ser: a


main() { int *ap; int x; ap = &x; *ap = 100; }

Con los apuntadores se puede realizar tambin aritmtica entera, por ejemplo: e e
main() { float *flp, *flq; *flp = *flp + 10; ++*flp; (*flp)++; flq = flp; }

NOTA: Un apuntador a cualquier tipo de variables es una direccin en memoria la cual o es una direccin entera, pero un apuntador NO es un entero. o La razn por la cual se asocia un apuntador a un tipo de dato, es por que se debe o conocer en cuantos bytes esta guardado el dato. De tal forma, que cuando se incrementa un apuntador, se incrementa el apuntador por un bloque de memoria, en donde el bloque esta en funcin del tamao del dato. o n Por lo tanto para un apuntador a un char, se agrega un byte a la direccin y para o un apuntador a entero o a otante se agregan 4 bytes. De esta forma si a un apuntador a otante se le suman 2, el apuntador entonces se mueve dos posiciones oat que equivalen a 8 bytes. ver [Harvey M. Deitel05a]

6.3.1.

Apuntadores y arreglos
Existe una relacin estrecha entre los punteros y los arreglos. En C, un nombre de o

un arreglo es un ndice a la direccin de comienzo del arreglo. En esencia, el nombre de un o arreglo es un puntero al arreglo. Considerar lo siguiente:
int a[10], x; int *ap;

6.3. Apuntadores en C

101

ap = &a[0]; x = *ap; este caso) */

/* ap apunta a la direccion de a[0] */ /* A x se le asigna el contenido de ap (a[0] en

*(ap + 1) = 100; 100 usando ap*/

/* Se asigna al segundo elemento de a el valor

Como se puede observar en el ejemplo la sentencia a[t] es idntica a ap+t. Se debe e tener cuidado ya que C no hace una revisin de los l o mites del arreglo, por lo que se puede ir fcilmente ms all del arreglo en memoria y sobreescribir otras cosas. a a a C sin embargo es mucho ms sutil en su relacin entre arreglos y apuntadores. Por a o ejemplo se puede teclear solamente: ap = a; en vez de ap = &a[0]; y tambin *(a + i) en vez de a[i], esto es, &a[i] e es equivalente con a+i. Y como se ve en el ejemplo, el direccionamiento de apuntadores se puede expresar como: a[i] que es equivalente a *(ap + i) Sin embargo los apuntadores y los arreglos son diferentes: Un apuntador es una variable. Se puede hacer ap = a y ap++. Un arreglo NO ES una variable. Hacer a = ap y a++ ES ILEGAL. Este parte es muy importante, asegrese u haberla entendido. Con lo comentado se puede entender como los arreglos son pasados a las funciones. Cuando un arreglo es pasado a una funcin lo que en realidad se le esta pasando es la o localidad de su elemento inicial en memoria. Por lo tanto: strlen(s) es equivalente a strlen(&s[0]) Esta es la razn por la cual se declara la o funcin como: o int strlen(char s[]); y una declaracin equivalente es int strlen(char *s); ya que char o s[] es igual que char *s. La funcin strlen() es una funcin de la biblioteca estndar que regresa la longitud o o a de una cadena. Se muestra enseguida la versin de esta funcin que podr escribirse: o o a
int strlen(char *s) { char *p = s; while ( *p != \0 ) p++;

102

Cap tulo 6: Apuntadores y arreglos

return p - s; }

Se muestra enseguida una funcin para copiar una cadena en otra. Al igual que en o el ejercicio anterior existe en la biblioteca estndar una funcin que hace lo mismo. a o
void strcpy(char *s, char *t) { while ( (*s++ = *t++) != \0 ); }

En los dos ultimos ejemplos se emplean apuntadores y asignacin por valor. Nota: o Se emplea el uso del caracter nulo con la sentencia while para encontrar el n de la cadena.

6.3.2.

Aritmtica de apuntadores e
Como ya se mencion los apuntadores tienen asociado un tipo de datos, este es o

muy importante cuando necesitamos realizar operaciones con un apuntador. En esta seccin o analizaremos la aritmtica de apuntadores. e Sea:
int a[10], *ap; ap = a; /*direccin del primer elemento */ o

a es el nombre de un arreglo de enteros, recuerda que el nombre de un arreglo se dene como: a & a[0] por lo tanto el nombre de cualquier arreglo es un APUNTADOR CONSTANTE, esto implica que: ap & a[0] El siguiente esquema muestra la relacin existente entre los elementos del arreglo o a y del apuntador ap: a= a[0] 0008 a[1] a[2] ... .... a[n-1]

ap = 1000 1004 1008 ... 4*(n-1)+1000 Como se puede observar el apuntador ap ms un nmero entero, equivale a la a u direccin de alguno de los elementos del arreglo, esto es: o ( ap + 0 ) & a[0]

6.3. Apuntadores en C

103

( ap + 1 ) & a[1] .... ... ( ap + 8 ) & a[8] ( ap + 2 ) & a[0] + ( 2 * sizeof(int) ) ap ++; /* apunta a & a[1] */ ap += 3; /* apunta a & a[4] */ De la misma manera el contenido del apuntador hace referencia al contenido de alguno de los elementos del arreglo, es decir:
*( ap + 0 ) *( ap + 1 ) .... ... *( ap + 8 ) a[8] a[0] a[1]

*( ap + 2 )

*(a[0] + ( 2 * sizeof(int) ) )

*(ap ++); /* contenido del elemento a[1] */ *(ap += 3); /* contenido del elemento a[4] */

El nombre de un arreglo es un apuntador al primer elemento del mismo,1 por eso basta con asignrsele el nombre a un apuntador, para que este apunte al inicio del arreglo. a Cuando le sumamos un entero a un apuntador, este avanza tantas direcciones como bytes ocupen el tipo de dato del arreglo. En el ejemplo de arriba nota que los apuntadores se incrementan de 4 en 42 La resta de apuntadores es valida siempre y cuando ambos apunten a un mismo arreglo, el resultado es el numero de celda que existen entre las celdas apuntadas. Si restamos bp-ap obtenemos 93 Los apuntadores pueden compararse entre s siempre y cuando apunten a un , mismo arreglo. Las comparaciones se hacen en base a la posicin de las celdas apuntadas. o Por ejemplo:
if (ap == bp) /* es falsa */ if (ap != bp ) /* es cierta */ if (ap > bp ) /* es falsa */

104

Cap tulo 6: Apuntadores y arreglos

if (ap < bp ) /* es cierta */ if (ap >= bp ) /* es falsa */ if (ap <= bp ) /* es cierta */

Cualquier otra operacin con apuntadores NO ES VALIDA. o

6.3.3.

Parmetros por valor y por referencia a


En C++ el paso por valor signica que al compilar la funcin y el cdigo que llama o o

a la funcin, sta recibe una copia de los valores de los parmetros que se le pasan como o e a argumentos. Las variables reales no se pasan a la funcin, slo copias de su valor. o o Cuando una funcin debe modicar el valor de la variable pasada como parmetro o a y que esta modicacin retorne a la funcin llamadora, se debe pasar el parmetro por o o a referencia. En este mtodo, el compilador no pasa una copia del valor del argumento; en su e lugar, pasa una referencia, que indica a la funcin dnde existe la variable en memoria. o o La referencia que una funcin recibe es la direccin de la variable. Es decir, pasar o o un argumento por referencia es, simplemente, indicarle al compilador que pase la direccin o del argumento. Ejemplo:
void demo(int &valor) { valor=5; cout<<valor<<endl; } void main() { int n=10; cout<<n<<endl; demo(n); cout<<n<<endl; }

La salida de este programa ser 5; a

6.3.4.

Ejemplo de paso por referencia


Dados dos nmeros a y b hacer un programa que reciba como argumentos estos u

dos numeros y que independientemente de los valores siempre en la variable a este el mayor y en b el menor. La implementacin en C es: o

6.3. Apuntadores en C

105

//Ejemplo ec029.cpp /** * <p>Title: Paso por referencia</p> * * <p>Description: Cambia el valor de dos numeros en una funcin</p> o * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Felix Calderon Solorio * @version 1.0 */ #include <stdio.h> void cambia(float *x, float *y); int main() { float a = 2; float b = 3; printf("Antes cambia(&a, &b); printf("Despues %f %f\n", a, b); return 0; } void cambia(float *x, float *y) { float temp = *x; *x = *y; *y = temp; return; } %f %f\n", a, b);

Cuando en C se utiliza &a, se esta pasando la direccin de la variable a, en la o memoria donde reside el dato; y cuando *a es el apuntador de la memoria (apuntadores ser revisado en los siguientes cap a tulos). En Java se puede hacer algo similar aunque el concepto de apuntador no existe.
/** * <p>Title: Paso por referencia</p> * * <p>Description: Cambia el valor de dos numeros en una funcin</p> o * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class ej029 {

106

Cap tulo 6: Apuntadores y arreglos

public static void main(String[] args) { float a[] = {2}; float b[] = {3}; System.out.println("Antes cambia(a, b); System.out.println("Despues " + a[0] + " " + b[0]); } static public void cambia(float x[], float y[]) { float temp = x[0]; x[0] = y[0]; y[0] = temp; } } " + a[0] + " " + b[0]);

6.4.

Matrices, Operaciones bsicas a


Una matriz se dene como un arreglo bidimensional de datos, que tiene n renglones

y m columnas. Un elemento del arreglo puede ser identicado con aij a0,0 a1,0 a2,0 a0,1 a1,1 a2,1 a0,2 a1,2 a2,2 ... ... ... a0,n1 a1,n1 a2,n1

A=

am1,0 am1,1 am1,2 ... am1,n1

Algunas de las operaciones bsicas que pueden realizarse con matrices son suma, a resta y multiplicacin. La divisin de matrices como tal no existe y en su lugar se calcula o o la inversa.

6.4.1.

Suma de matrices
Para que la sumar las matrices A y B, se requiere que las matrices tengan el

mismo nmero de renglones y de columnas. Si queremos encontrar la suma C = A + B, u cada elemento de la matriz C lo calculamos de la siguiente forma:

ci,j = ai,j + bi,j

6.4. Matrices, Operaciones bsicas a

107

para todos lo i, j en la matriz C

6.4.2.

Resta de matrices
En este caso, se deben cumplir las mismas propiedades que la resta de matrices y

el calculo de los elemento de la matriz C se calculan como: ci,j = ai,j bi,j para todos lo i, j en la matriz C

6.4.3.

Multiplicacin de matrices o
Para realizar el producto C = A B tenemos que considerar que el producto existe

si 1.- El nmero de columnas de A es igual al nmero de renglones de B. u u

C(n, l) = A(n, m) B(m, l) 2.- Las dimensiones de la matriz resultante tendr el mismo numero de renglones a que la matriz A y el mismo nmero de columnas que la matriz B. u 3.- El clculo de los elementos de la matriz C se lleva a cabo haciendo : a
m1

ci,j =
k=0

ai,k bk,j

para todos lo i, j en la matriz C

6.4.4.

Solucin de sistemas de ecuaciones triangulares o


Considere el siguiente sistema de ecuaciones a0,0 a0,1 a0,2 a1,1 a1,2 0 a2,2 x0 b0

0 0

x1 = b1 x2 b2

108

Cap tulo 6: Apuntadores y arreglos

Podemos ver que la solucin para x2 es o x2 = para x1 es x1 = y para x0 x0 = en general tenemos que bk
n1 j=k+1 ak,j xj

b2 a2,2

b1 a1,2 x2 a1,1

b0 a0,1 x1 + a0,2 x2 a0,0

xk = Determinantes

ak,k

Podemos ver que el determinante de una matriz triangular superior o inferior es :

det(A) = a0,0 a1,1 a2,2 ... an1,n1

6.4.5.

Solucin de sistemas lineales de ecuaciones por el mtodo de Elio e minacin Gaussiana o


Consideremos que tenemos un sistema lineal Ax=b, donde la matriz A no tiene

las condiciones de ser triangular a 0,0 a1,0 a2,0

superior. a0,1 a0,2 a1,1 a1,2 a2,1 a2,2 x0 b0

x1 = b1 b2 x2

Comenzaremos por despejar x0 de la ecuacin (I) o b0 a0,1 x1 a0,2 x2 a0,0

x0 =

y sustituimos en las ecuaciones (II) b0 a0,1 x1 a0,2 x2 + a1,1 x1 + a1,2 x2 = b1 a0,0

a1,0

6.4. Matrices, Operaciones bsicas a

109

agrupando trminos semejantes tenemos: e a0,2 a1,0 a0,1 b0 )x1 + (a1,2 a1,0 )x2 = (b1 a1,0 ) a0,0 a0,0 a0,0

(a1,1

Ahora sustituimos en la ecuacin (III) o b0 a0,1 x1 a0,2 x2 + a2,1 x1 + a2,2 x2 = b2 a0,0 a0,2 a0,1 b0 )x1 + (a2,2 a2,0 )x2 = (b2 a2,0 ) a0,0 a0,0 a0,0

a2,0

(a2,1 a2,0

Lo cual nos da un nuevo sistema simplicado dada por a0,0 a0,1 a0,2 x0 b0

0 0

a a x1 = b 1,1 1,2 1 a a x2 b 2,1 2,2 2

donde los valores de a los calculamos como: i,j a = ai,j ai,k i,j ak,j bk bi = bi ai, k ak,k ak,k

Si repetimos el procedimiento, ahora para x1 , tendremos un sistema dado como: a0,0 a0,1 a0,2 x0 b0

0 0

a x1 = b a 1,2 1 1,1 0 a b x2 2 2,2

que corresponde a un sistema triangular superior que podemos solucionar utilizando sustitucin hacia atrs. o a Ejemplo. Calcular el sistema triangular superior utilizando eliminacin gaussiana. o

5x + 2y + 1z = 3 2x + 3y 3z = 10 1x 3y + 2z = 4

110

Cap tulo 6: Apuntadores y arreglos

Primer paso

5x + 2y + 1z = 3 0 + (11/5)y (17/5)z = (56/5) 0 (17/5)y + (9/5)z = (17/5) Segundo paso

5x + 2y + 1z = 3 0x + (11/5)y (17/5)z = (56/5) 0x 0y (38/11)z = (153/11) Ejemplo. Resolver el sistema de ecuaciones 3 1 1 1 0 x 0

1 1

0 y = 1 1 z 1

Aplicando eliminacin gaussiana nos queda. o 3 1 1 x 0 0 2/3 1/3 y = 1 0 0 1/2 z 3/2 Ejemplo. Un ejemplo de sistema donde es necesario hacer un cambio de rengln por rengln o o para que tenga solucin es el siguiente sistema. o 1 2 6

4 8 1 2 3 5 Aplicando el primer paso de la eliminacin gaussiana tenemos: o

6.4. Matrices, Operaciones bsicas a

111

1 2

0 0 25 0 7 17 note, que aparece un cero en el elemento 22, lo cual nos da un sistema sin solucin. o Permutando los renglones 2 y 3 el sistema tiene solucin. o 1 2 6

2 3 5 4 8 1

La implementacin de estos algoritmos en Java es: o


/** * <p>Title: Operaciones bsicas con Matrices</p> a * * <p>Description: Realiza las operaciones de suma, resta, multiplicacin y o * solucion de un sistema de equaciones</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */ public class ej044 { public static void main(String[] args) { double A[][] = new double[2][2]; double B[][] = new double[2][2]; A[0][0] = 1; A[0][1] = 2; A[1][0] = 3; A[1][1] = 4; imprime("A =", A, 2, 2); B[0][0] = 4; B[0][1] = 3; B[1][0] = -3; B[1][1] = 5; imprime("B =", B, 2, 2); double C[][] = suma(A, B, 2, 2, 2, 2); imprime("C = ", C, 2,2); double D[][] = resta(A, B, 2, 2, 2, 2); imprime("D = ",D, 2,2); double E[][] = multiplica(A, B, 2, 2, 2, 2); imprime("E = ",E, 2,2); double Z[] = new double[2]; Z[0] = 10; Z[1] = 5; double x[] = SolucionSL(A, Z, 2);

112

Cap tulo 6: Apuntadores y arreglos

imprime("X =", x, 2); } public static double[][] suma(double[][] A, double[][] B, int N, int M, int R, int S) { int i, j; if(N!=R || M!=S) return null; double[][] res = new double[N][M]; for (i = 0; i < N; i++) for (j = 0; j < M; j++) res[i][j] = A[i][j] + B[i][j]; return res; } public static double[][] resta(double[][] A, double[][] B, int N, int M, int R, int S) { int i, j; if(N!=R || M!=S) return null; double[][] res = new double[N][M]; for (i = 0; i < N; i++) for (j = 0; j < M; j++) res[i][j] = A[i][j] - B[i][j]; return res; } public static double[][] multiplica(double A[][], double B[][], int N, int M, int R, int S) { int i, j, k; if(M!=R) return null; double res[][] = new double[N][S]; for (i = 0; i < N; i++) { for (j = 0; j < S; j++) { res[i][j] = 0; for (k = 0; k < M; k++) res[i][j] += A[i][k] * B[k][j]; } } return res; } static public double [] SolucionSL(double a[][], double b[], int N) { int i, j, k; double suma; double x[] = new double[N]; for (k = 0; k <= N - 2; k++) { for (i = k + 1; i <= (N - 1); i++) { b[i] -= a[i][k] * b[k] / a[k][k]; for (j = N - 1; j >= k; j--) a[i][j] -= a[i][k] * a[k][j] / a[k][k];

6.4. Matrices, Operaciones bsicas a

113

} } for (k = N - 1; k >= 0; k--) { suma = 0; for (j = k + 1; j < N; j++) suma += a[k][j] * x[j]; x[k] = (b[k] - suma) / a[k][k]; } return x; } public static void imprime(String texto, double fuente[][], int N, int M) { System.out.println(texto); if(fuente == null) return; int i, j; for (i = 0; i < N; i++) { for (j = 0; j < M; j++) { System.out.print(fuente[i][j] + " " ); } System.out.println(""); } } public static void imprime(String texto, double fuente[], int N) { System.out.println(texto); if (fuente == null)return; int i; for (i = 0; i < N; i++) { System.out.println(fuente[i] + " "); } } }

En C
// ejemplo ec044.cpp /** * <p>Title: Operaciones bsicas con Matrices</p> a * * <p>Description: Realiza las operaciones de suma, resta, multiplicacin y o * solucion de un sistema de equaciones</p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: UMSNH</p> * * @author Dr. Flix Calderon Solorio e * @version 1.0 */

#include <stdio.h> #include <stdlib.h> double double double double double **Matriz(int N, int M); *vector(int N); double **suma(double ** A, double ** B, int N, int M, int R, int S) ; ** resta(double ** A, double ** B, int N, int M, int R, int S); ** multiplica(double **A, double **B, int N, int M, int R, int S); * SolucionSL(double **a, double *b, int N);

114

Cap tulo 6: Apuntadores y arreglos

void imprime(char texto[], double *fuente, int N) ; void imprime(char texto[], double **fuente, int N, int M);

int main() { double **A = Matriz(2,2); double **B = Matriz(2,2); A[0][0] = 1; A[0][1] = 2; A[1][0] = 3; A[1][1] = 4; imprime("A =", A, 2, 2); B[0][0] = 4; B[0][1] = 3; B[1][0] = -3; B[1][1] = 5; imprime("B =", B, 2, 2); double **C = suma(A, B, 2, 2, 2, 2); imprime("C = ", C, 2,2); double **D = resta(A, B, 2, 2, 2, 2); imprime("D = ",D, 2,2); double **E = multiplica(A, B, 2, 2, 2, 2); imprime("E = ", E, 2,2); double *Z = vector(2); Z[0] = 10; Z[1] = 5; double *x = SolucionSL(A, Z, 2); imprime("X =", x, 2); return 1; }

double **Matriz(int N, int M) { double **a; a = (double **) calloc (N, sizeof(double*)); for(int i=0; i<N; i++) a[i] = (double *) calloc(M, sizeof (double)); return a; } double *vector(int N) { double *a; a = (double *) calloc (N, sizeof(double)); return a; } double ** suma(double ** A, double ** B, int N, int M, int R, int S) { int i, j; if(N!=R || M!=S) return 0; double ** res = Matriz(N,M);

6.4. Matrices, Operaciones bsicas a

115

for (i = 0; i < N; i++) for (j = 0; j < M; j++) res[i][j] = A[i][j] + B[i][j]; return res; } double ** resta(double ** A, double ** B, int N, int M, int R, int S) { int i, j; if(N!=R || M!=S) return 0; double ** res = Matriz(N,M); for (i = 0; i < N; i++) for (j = 0; j < M; j++) res[i][j] = A[i][j] - B[i][j]; return res; } double ** multiplica(double **A, double **B, int N, int M, int R, int S) { int i, j, k; if(M!=R) return 0; double **res = Matriz(N,S); for (i = 0; i < N; i++) { for (j = 0; j < S; j++) { res[i][j] = 0; for (k = 0; k < M; k++) res[i][j] += A[i][k] * B[k][j]; } } return res; } double * SolucionSL(double **a, double *b, int N) { int i, j, k; double suma; double *x = vector(N); for (k = 0; k <= N - 2; k++) { for (i = k + 1; i <= (N - 1); i++) { b[i] -= a[i][k] * b[k] / a[k][k]; for (j = N - 1; j >= k; j--) a[i][j] -= a[i][k] * a[k][j] / a[k][k]; } } for (k = N - 1; k >= 0; k--) { suma = 0; for (j = k + 1; j < N; j++) suma += a[k][j] * x[j]; x[k] = (b[k] - suma) / a[k][k]; }

116

Cap tulo 6: Apuntadores y arreglos

return x; } void imprime(char texto[], double **fuente, int N, int M) { printf("%s\n", texto); if(fuente == 0) return; int i, j; for (i = 0; i < N; i++) { for (j = 0; j < M; j++) { printf("%f ", fuente[i][j]); } printf("\n"); } } void imprime(char texto[], double *fuente, int N) { printf("%s \n", texto); if (fuente == 0) return; int i; for (i = 0; i < N; i++) { printf("%f \n", fuente[i]); } }

Tarea 15 Matrices elevadas a una potencia entera Hacer una funcin que reciba una matriz y regrese otra matriz con la informacin de la o o matriz dada elevada a un entero dado

6.5.

Ejemplos

B squedas lineales u Secuencial La forma ms simple de bsqueda es la bsqueda secuencial. Esta bsqueda es a u u u aplicable a una tabla organizada, ya sea como un arreglo o como una lista ligada. Supongamos que x es un arreglo de N llaves, de x(0) a x(N 1) y y el termino que deseamos encontrar en el arreglo, el algoritmo de bsqueda queda como: u
static public int busqueda_secuencial(double x[], double y, int N) { int i; for(i=0; i<N; i++) if(x[i] == y) return i; return -1; }

6.5. Ejemplos

117

B squeda Binaria u El mtodo de bsqueda ms eciente en una tabla secuencial sin usar e u a ndices o tablas auxiliares es el mtodo de bsqueda binaria. Bsicamente, se compara el argumento e u a con la llave del elemento medio de la tabla. Sin son iguales, la bsqueda termina con xito; u e en caso contrario, se busca de manera similar en la mitad superior o inferior de la tabla, segn sea el caso. u
static public int busqueda_binaria(double x[], double y, int N) { int inicio = 0, fin = N, mitad; while(inicio <= fin) { mitad = (fin + inicio)/2; if(y == x[mitad]) return mitad; if(y < x[mitad]) fin = mitad -1; else inicio = mitad + 1; } return -1; }

El siguiente cdigo muestra la implementacin de ambos y un programa principal o o para hacer un llamado a cada uno de los mtodos de bsqueda antes mencionados. e u
class busqueda { static public void main(String args[]) { double x[] = {1,2,4,7, 10, 11, 20, 21, 32}; int N = 9, i; double y = 10; i = busqueda_secuencial(x, y, N); System.out.println("El valor "+ y + " se encuentra en la posicion " + i); System.out.println("El valor "+ x[i] + " se encuentra en la posicion " + busqueda_binaria(x, y, N)); } static public int busqueda_secuencial(double x[], double y, int N) { int i; for(i=0; i<N; i++) if(x[i] == y) return i; return -1; } static public int busqueda_binaria(double x[], double y, int N) { int inicio = 0, fin = N, mitad;

118

Cap tulo 6: Apuntadores y arreglos

while(inicio <= fin) { mitad = (fin + inicio)/2; if(y == x[mitad]) return mitad; if(y < x[mitad]) fin = mitad -1; else inicio = mitad + 1; } return -1; } }

Mtodo de ordenamiento (burbuja) e El primer ordenamiento que presentamos es quiz el ms ampliamente conocido a a entre los estudiantes que se inician en la programacin. Una de las caracter o sticas de este ordenamiento es que es fcil de entender y programar. Aunque, es uno de los algoritmos a mas ineciente. La idea bsica subyacente en el ordenamiento de burbuja es pasar a travs del a e arreglo de datos varias veces en forma secuencial. Cada paso consiste en la comparacin o de cada elemento en el arreglo con su sucesor (x[i] con x[i+1]) y el intercambio de los dos elementos si no estn en el orden correcto. Considrese el siguiente arreglo de datos: a e 25 57 48 37 12 92 86 33 En el primer paso se realizan las siguientes operaciones: x[0] con x[1] (25 con 57) no intercambio. x[1] con x[2] (57 con 48) intercambio. x[2] con x[3] (57 con 32) intercambio. x[3] con x[4] (57 con 12) intercambio. x[4] con x[5] (57 con 92) no intercambio. x[5] con x[6] (92 con 86) intercambio. x[6] con x[7] (92 con 33) intercambio. As despus del primer paso, el arreglo est en el siguiente orden: e a 25 48 37 12 57 86 33 92 Obsrvese que despus del primer paso, el elemento mayor (en este caso 92) est en e e a la posicin correcta dentro del arreglo. En general x[n-i] estar en su posicin correcta o a o

6.5. Ejemplos

119

despus de la iteracin i. El mtodo se lama ordenamiento de burbuja porque cada nmero e o e u burbujea con lentitud hacia su posicin correcta. El conjunto completo de iteraciones es: o iteracin 0: 25 57 48 37 12 92 86 33 o iteracin 1: 25 48 37 12 57 86 33 92 o iteracin 2: 25 37 12 48 57 33 86 92 o iteracin 3: 25 12 37 48 33 57 86 92 o iteracin 4: 12 25 37 33 48 57 89 92 o iteracin 5: 12 25 33 37 48 57 89 92 o La implementacin de este algoritmo en Java queda como: o
void Burbuja(int x[], int n) { int b, j, t; do { b = 0; for(j=0; j<n; j++) { if(x[j] > x[j+1]) { t = x[j]; x[j] = x[j+1]; x[j+1] = t; b++; } } n--; } while(b > 0); }

Cap tulo 7

Estructuras
Estructuras y Unin en C. Ejemplo Operaciones con nmeros complejos. o u

7.1.

Estructuras en C
Una Estructura es una coleccin de variables simples, que pueden contener difeo

rentes tipos de datos. Es un tipo de dato denido por el usuario. Son tambin conocidas e como Registros. Ayudan a organizar y manejar datos complicados en programas debido a que agrupan diferentes tipos de datos a las que se les trata como una sola unidad en lugar de ser vistas como unidades separadas. La Declaracin de estructuras en programas C es un nuevo tipo de datos denomio nado tipo Estructura y declarar una variable de este tipo. En la denicin del tipo de estructura, se especican los elementos que la componen o as como sus tipos. Cada elemento es llamado miembro (similar a un campo de un registro).
struct tipo_estructura { Declaracin de los miembros }; o

Despus de denir un tipo estructura, se puede declarar una o ms variables de e a ese tipo de la siguiente forma:
struct tipo_estructura [variables];

Ejemplo 121

122

Cap tulo 7: Estructuras

struct articulo { int codigo; char nombre[20]; float peso, longitud; };

Denicin de variables de esta estructura : struct a, b; O tambin se pueden denir o e la estructura y sus variables al mismo tiempo:
struct articulo { int codigo; char nombre[20]; float peso, longitud; } a, b;

El Acceso a los Miembros de la Estructura es por medio del operador Punto de la siguiente manera: \begin{verbatim} a.codigo = 1234; b.nombre = "escoba"; b.peso = 23;

Los miembros de las Estructuras tambin se pueden Inicializar individualmente o e bien, todos simultneamente. La inicializacin individual es por medio del operador punto, a o para la estructura completa es con caracteres llaves y los valores de los miembros separados por coma. Iniciando solo por miembros: a.codigo=1234; Iniciando Estructura completa:
articulo a={1234, "escoba", 23, 1.50};

7.1.1.

Ejemplo de manejo de estructuras

// Ejemplo ec045.cpp /** * Title: Manejo de estructuras en C * Description: Crea una estructura con datos * desde el teclado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> #include <conio.h> struct datos { char no_control[9]; char nombre[30]; int edad; char sexo;

7.1. Estructuras en C

123

char domicilio[50]; };

void imprime(struct datos a); int main() { struct datos alumno; printf("\nIntroduce los datos del alumno"); printf("\nNo Control : "); gets(alumno.no_control); printf("\nNombre : "); gets(alumno.nombre); printf("\nEdad : "); scanf("%d", &alumno.edad); printf("\nSexo : "); alumno.sexo = getchar(); alumno.sexo = getchar(); printf("\nDireccion : "); gets(alumno.domicilio); imprime(alumno); return 1; } void imprime(struct datos a) { printf("No de control %s\n", a.no_control); printf("Nombre %s\n", a.nombre); printf("Edad %d\n", a.edad); printf("Sexo %c\n", a.sexo); printf("Direccion %s\n", a.domicilio); }

7.1.2.

Arreglos de Estructuras
Arreglos de Estructuras pueden ser construidas, es decir, conceptuar a los elemen-

tos de un arreglo como estructuras, esto se puede hacer de la siguiente manera:


struct datos { char no_control[9]; char nombre[30]; int edad; char sexo; char domicilio[50]; }; struct datos alumnos[35];

Para tener acceso a una determinada estructura , se indexa el nombre de la estructura de la siguiente manera: alumnos[i].nombre; aqu sabemos el nombre del alumno que se encuentra en la posicin i del arreglo, y de esta manera para todos los datos. Si se desea o inicializar los valores, se podr hacer de la siguiente manera: a
struct datos.alumno[5]={96147523, "Luis", 22, "m", "pino 45"};

124

Cap tulo 7: Estructuras

7.1.3.

Estructuras Anidadas
El siguiente ejemplo muestra una estructura anidada. Las estructuras que hemos

visto han sido muy sencillas aunque utiles. Es posible denir estructuras conteniendo doce nas y an cientos miles de elementos pero ser ventajoso para el programador no denir u o a todos los elementos en una pasada sino utilizar una denicin de estructura jerrquica. o a
// Ejemplo ec046.cpp /** * Title: Manejo de estructuras en C * Description: Crea una estructura con datos * desde el teclado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <string.h> #include <stdio.h> struct persona { char nombre[25]; int edad; char estado; // C = casado, S = soltero }; struct datos { int calificacion; struct persona descripcion; char comida[25]; }; void imprime(struct datos a); int main() { struct datos estudiante[53]; struct datos maestro, sub; maestro.calificacion = 94; maestro.descripcion.estado = C; strcpy(maestro.descripcion.nombre, "Lisseth Gil"); strcpy(maestro.comida, "Chocolate de Ron"); sub.descripcion.edad = 87; sub.descripcion.estado = C; strcpy(sub.descripcion.nombre, "Abuela Pata"); sub.calificacion = 73; strcpy(sub.comida, "Maiz y agua"); estudiante[1].descripcion.edad = 15; estudiante[1].descripcion.estado = S; strcpy(estudiante[1].descripcion.nombre, "Bill, Griton"); strcpy(estudiante[1].comida, "Crema de cacahuate"); estudiante[1].calificacion = 77; estudiante[7].descripcion.edad = 14; estudiante[12].calificacion = 87;

7.1. Estructuras en C

125

imprime(sub); return 1; }

void imprime(struct datos a) { printf("Nombre %s\n", a.descripcion.nombre); printf("Edad %d\n", a.descripcion.edad); printf("Estado %c\n", a.descripcion.estado); printf("calificacion %d\n", a.calificacion); }

La primera estructura contiene tres elementos pero no le sigue ninguna variable denida, slo una estructura, pero como incluimos un nombre al principio de la estructura, o la estructura es llamada persona. La palabra persona puede utilizarse para referirse a la estructura pero no a cualquier variable de ste tipo de estructura, se trata por lo tanto de e un nuevo tipo que hemos denido y lo podemos utilizar de la misma manera en que usamos un int, char o cualquier otro tipo que existe en C. La unica restriccin es que ste nuevo o e tipo debe estar siempre asociado con la palabra clave struct. La siguiente denicin de estructura contiene tres campos siendo el segundo la o estructura previamente denida la cual llamamos persona. La variable de tipo persona se llama descripcin, as la nueva estructura contiene dos variables simples, calicacin y una o o cadena llamada comida, y la estructura llamada descripcin. Como descripcin contiene o o tres variables, la nueva estructura tiene entonces cinco variables, a sta estructura le hemos e dado el nombre de datos, lo cual es otro tipo denido. Finalmente, dentro de la funcin o main ( ) denimos un array de 53 variables cada una con la estructura denida por el tipo datos, y cada una con el nombre estudiante, en total hemos denido 53 veces 5 variables, cada una de las cuales es capaz de almacenar datos. Como tenemos la denicin de un o nuevo tipo podemos utilizarla para a su vez denir dos variables. Las variables maestro y sub estn denidas en la l a nea 20 como variables de tipo datos por lo que cada una de stas e dos variables contienen 5 campos en los cuales podemos almacenar datos. En las l neas 22 a 26 del programa asignamos valores a cada uno de los campos de maestro. El primero es el campo calicacin y es manejado como las otras estructuras o que hemos estudiado porque no forma parte de la estructura anidada. Enseguida deseamos asignar un valor a edad el cual es parte de la estructura anidada. Para acceder a ste e

126

Cap tulo 7: Estructuras

campo empezamos con el nombre de la variable maestro al cual le concatenamos el nombre del grupo descripcin, y entonces debemos denir en cul campo de la estructura anidada o a estamos interesados por lo que concatenamos el nombre de la variable edad. El estado de los maestros se manejan de la misma manera que su edad pero los ultimos dos campos son cadenas asignadas utilizando la funcin strcpy ( ). Observe que los nombres de las variables o en la funcin strcpy ( ) se consideran como una unidad aunque estn compuestas de varias o e partes. Compile y ejecute el programa, probablemente obtenga un aviso sea de error ado vertencia respecto a un desbordamiento de memoria. Lo que esto signica es que el programa requiere ms memoria que la asignada a por el compilador por lo que es necesario incrementar el tamao de stacks, el mtodo para n e hacer esto var de un compilador a otro. a

7.2.

Uniones en C
Uniones. Las uniones son similares a las estructuras, con la diferencia de que en las

uniones se almacenan en los campos solapndose unos con otros en la misma disposicin; a o al contrario que en las estructuras, al contrario que en las estructuras, donde los campos se almacenan unos a continuacin de otros. En esencia, las uniones sirven para ahorrar espacio o en memoria. Para Almacenar los miembros de una unin, se requiere una zona de memoria o igual a la que ocupa el miembro mas largo de la unin. Todos los miembros son almacenados o en el mismo espacio de memoria y comienzan en la misma direccin. El valor almacenado es o sobre escrito cada vez que se asigna un valor al mismo miembro o a un miembro diferente, aqu radica la diferencia con las estructuras. La Declaracin de Uniones es similar a la de las estructuras: o
union tipo_union { declaracion_de_miembros; } ; tipo_union

Despus de denir un tipo union, se puede declarar una o mas variables de ese e tipo de la siguiente forma:

7.2. Uniones en C

127

union tipo_union [variables];

Una declaracin union dene un tipo. La llave derecha que termina la lista de o miembros puede ser seguida por una lista de variables de la siguiente manera:
union tipo_union{ ... } variable;

Ejemplo
union datos { char a; int b; float c }; union datos p;

Dicho de una forma simple, una unin le permite manejar los mismos datos con o diferentes tipos, utilizar el mismo dato con diferente nombre, a continuacin le presento o o un ejemplo:
// Ejemplo ec047.cpp /** * Title: Manejo de uniones en C * Description: Crea una union de datos * desde el teclado * Copyright: Copyright (c) 2005 * Company: UMSNH * author Dr. Felix Calderon Solorio * version 1.0 */ #include <stdio.h> union { int valor; struct { char primero; char segundo; } mitad; } numero;

int main() { long indice = 34000L; numero.valor = indice; printf("%8x %6x %6x\n", numero.valor, numero.mitad.primero, numero.mitad.segundo); return 1; }

128

Cap tulo 7: Estructuras

La ejecucin muestra los siguientes resultados. o


84d0 ffffffd0 ffffff84

ver [Harvey M. Deitel05a] En ste ejemplo tenemos dos elementos en la unin, la primera parte es el entero e o llamado valor el cual es almacenado en algn lugar de la memoria de la computadora como u una variable de dos bytes. El segundo elemento est compuesto de dos variables de tipo char a llamadas primero y segundo. Estas dos variables son almacenadas en la misma ubicacin de o almacenamiento que valor porque esto es precisamente lo que una unin hace, le permite o almacenar diferentes tipos de datos en la misma ubicacin f o sica. En ste caso Usted puede e poner un valor de tipo entero en valor y despus recobrarlo en dos partes utilizando primero e y segundo, sta tcnica es utilizada a menudo para empaquetar bytes cuando, por ejemplo, e e combine bytes para utilizarlos en los registros del microprocesador. La unin no es utilizada o frecuentemente y casi nunca por programadores principiantes, en este momento no necesita profundizar en el empleo de la unin as que no dedique mucho tiempo a su estudio, sin o embargo no tome a la ligera el concepto de la unin, podr utilizarlo a menudo. o a Tarea 16 Estructuras Crea una estructura de datos que maneje la informacin de un directorio telefnico. El o o programa debe tener la posibilidad de buscar el nmero telefnico por el nombre de una u o persona .

Cap tulo 8

Programacin orientada a objetos o


Programacin orientada a objetos en C y Java Herencia. Applets en Java o El trmino de Programacin Orientada a Objetos indica ms una forma de diseo e o a n y una metodolog de desarrollo de software que un lenguaje de programacin, ya que en a o realidad se puede aplicar el Diseo Orientado a Objetos (En ingls abreviado OOD, Object n e Oriented Design), a cualquier tipo de lenguaje de programacin. o El desarrollo de la OOP empieza a destacar durante la dcada de lo 80 tomando e en cuenta la programacin estructurada, a la que engloba y dotando al programador de o nuevos elementos para el anlisis y desarrollo de software. a Bsicamente la OOP permite a los programadores escribir software, de forma que a est organizado en la misma manera que el problema que trata de modelizar. Los lenguajes e de programacin convencionales son poco ms que una lista de acciones a realizar sobre un o a conjunto de datos en una determinada secuencia. Si en algn punto del programa modiu camos la estructura de los datos o la accin realizada sobre ellos, el programa cambia. o La OOP aporta un enfoque nuevo, convirtiendo la estructura de datos en el centro sobre el que pivotan las operaciones. De esta forma, cualquier modicacin de la estructura o de datos tiene efecto inmediato sobre las acciones a realizar sobre ella, siendo esta una de la diferencias radicales respecto a la programacin estructurada. o La OOP proporciona las siguientes ventajas sobre otros lenguajes de programacin o Uniformidad. Ya que la representacin de los objetos lleva impl o citamente tanto el 129

130

Cap tulo 8: Programacin orientada a objetos o

anlisis como el diseo y la codicacin de los mismos. a n o Comprensin. Tanto los datos que componen los objetos, como los procedimientos o que los manipulan, estn agrupados en clases, que se corresponden con las estructuras de a informacin que el programa trata. o Flexibilidad. Al tener relacionados los procedimientos que manipulan los datos con los datos a tratar, cualquier cambio que se realice sobre ellos quedar reejado automticaa a mente en cualquier lugar donde estos datos aparezcan. Estabilidad. Dado que permite un tratamiento diferenciado de aquellos objetos que permanecen constantes en el tiempo sobre aquellos que cambian con frecuencia permite aislar las partes del programa que permanecen inalterables en el tiempo. Reusabilidad. La nocin de objeto permite que programas que traten las mismas o estructuras de informacin reutilicen las deniciones de objetos empleadas en otros proo gramas e incluso los procedimientos que los manipulan. De esta forma, el desarrollo de un programa puede llegar a ser una simple combinacin de objetos ya denidos donde estos o estn relacionados de una manera particular. a

8.1.
8.1.1.

Caracter sticas de los Objetos


Identidad del Objeto
La identidad expresa que aunque dos objetos sean exactamente iguales en sus

atributos, son distintos entre s De esta forma incluso una serie de Objetos coches, recin . e fabricados son distintos los unos de los otros. La armacin anterior, aunque parece obvia, tiene importancia cuando descendeo mos al nivel de programacin. En este mbito cada uno de los objetos tiene un controlador o a pro el cual se identica. Este puede ser una variable, una estructura de datos, una cadena de caracteres, etc. El controlador ser distinto para cada uno de los objeto, aunque las referena cias a stos sean uniformes e independientes del contenido, permitiendo crear agrupaciones e de objetos con el mismo tratamiento.

8.1. Caracter sticas de los Objetos

131

8.1.2.

Clasicacin o
Con la clasicacin comienza la verdadera programacin orientada a objetos. Ellos o o

nos obliga a una abstraccin del concepto de objeto denominada clase. o Las clases permiten la agrupacin de objetos que comparten las mismas propiedao des y comportamiento. Si bien clase y objeto suelen usarse como sinnimos, no lo son. o El esfuerzo del programador ante una aplicacin orientada a objetos se centra en o la identicacin de las clases, sus atributos y operaciones asociadas o Las propiedades de cada clase deben cumplir una serie de premisas Las propiedades deber ser signicativas dentro del entorno de la aplicacin es decir, o deben servir para identicar claramente y de una manera unica (y univoca) a cada uno de los objetos El nmero de propiedades de un objeto debe ser el m u nimo para realizar todas las operaciones que requiera la aplicacin. o Denamos una clase rectngulo. Esta clase puede tener como atributos un punto a (x,y), la anchura (a) y la longitud (l). Las operaciones a realizar son: mover, agrandar, reducir, et. Es posible realizarlas con las propiedades de la clase? Un anlisis posterior nos indica que es posible la realizacin de estas operaciones a o con los atributos denidos. Pero si incluimos la operacin girar , vemos que con las propieo dades denidas para la clase esta operacin no se puede realizar. Para incluir esta nueva o operacin debemos redenir las propiedades del objeto, en este caso las coordenadas de los o vrtices. e

8.1.3.

Encapsulacin y ocultamiento de datos o


La capacidad de presentacin de informacin dentro de un objeto se divide en dos o o

partes bien diferenciadas: Interna: La informacin que necesita el objeto para operar y que es innecesaria o para los dems objetos de la aplicacin. Estos atributos se denominada privados y tienen a o como marco de aplicacin unicamente a las operaciones asociadas al objeto. o Externa La que necesitan el resto de los objetos para interactuar con el objeto que

132

Cap tulo 8: Programacin orientada a objetos o

denimos . Estas propiedades se denominan pblicas y corresponde a la informacin que u o necesitan conocer los restantes objetos de la aplicacin respecto del objeto denido para o poder operar. Podemos imaginarla encapsulacin como introducir el objeto dentro de una caja o negra donde existen dos ranuras denominadas entrada y salida. Si introducimos datos por la entrada automticamente obtendr un resultado en la salida. No necesita conocer ningn a a u detalle del funcionamiento interno de la caja. El trmino encapsulacin indica la capacidad que tienen los objetos de construir e o una cpsula a su alrededor, ocultando la informacin que contienen (aqulla que es necesaria a o e para su funcionamiento interno, pero innecesaria para los dems objetos) a las otras clases a que componen la aplicacin. o Aunque a primera vista la encapsulacin puede parecer superua, tengamos en o cuenta que existen muchas variables utilizadas de forma temporal: contadores y variables que contienen resultados intermedios, etc. D no ser por la encapsulacin estas variables o ocupar memoria y podr interferir en el funcionamiento del resto de los objetos. an an La encapsulacin no es exclusiva de los lenguajes de programacin orientados a o o objetos. Aparece en los lenguajes basados en procedimientos (PASCAL, C, COBOL, ETC) como una forma de proteger los datos que se manipulan dentro de las funciones. Los lenguajes OOP incorporan la posibilidad de encapsular tambin las estructuras e de datos que sirven como base a las funciones. Aportan por tanto un nivel superior en cuanto a proteccin de informacin. o o La encapsulacin nos permite el uso de librer de objetos para el desarrollo de o as nuestros programas. Recordemos que las librer son deniciones de objetos de propsito as o general que se incorporan a los programas. Al ser el objeto parcialmente independiente en su funcionamiento del programa en donde est denido, ya que contiene y dene todo lo que a necesita para poder funcionar, es fcil utilizarlo en los mas variados tipos de aplicaciones. a Si aseguramos , depurando las propiedades y las operaciones dentro de la clase que el objeto funcin bien dentro de una aplicacin, con una correcta encapsulacin el objeto o o o podr funcionar en cualquier otra. a Otra de las ventajas de la encapsulacin es que , al denir el objeto como una o

8.1. Caracter sticas de los Objetos

133

caja negra con entradas y salida asociadas, en cualquier momento podemos cambiar el contenido de las operaciones del objeto, de manera que no afecte al funcionamiento general del programa. La encapsulacin est en el ncleo de dos grandes pilares de la construccin de o a u o sistemas; mantenibilidad y reusabilidad.

8.1.4.

Mantenibilidad
Cualidad que indica que un programa o sistema debe ser fcilmente modicable. Es a

decir que los cambios en las condiciones externas (como la denicin de una nueva variable) o implicarn modicaciones pequeas en el programa / sistema. El concepto de mantenibilia n dad implica que un programa, al igual que un ser vivo debe ser capaz de adaptarse a un medio ambiente siempre cambiante.

8.1.5.

Reusabilidad
Cualidad que nos indica que partes del programa ( en este caso objetos) pueden

ser reutilizados en la confeccin de otros programas. Ello implica que los objetos denidos o en un programa pueden ser extra dos del mismo e implantados en otro sin tener que realizar modicaciones importantes en el cdigo del objeto. El objeto nal es que el programador o construya una librer de objetos que le permita realizar programas basndose en la tcnia a e ca de cortar y pegar. Esta extrae (corta) cdigo de otras aplicaciones ya realizadas y las o implementa (pega) en la aplicacin a realizar donde, tras algunos retoques, la nueva aplicao cin estar lista para funcionar. Como podr observar el concepto de reusabilidad, permite o a a reducir el tiempo de realizacin , ganando en claridad, mantenibilidad y productividad. o La encapsulacin de datos se muestra como una herramienta poderosa que nos o permite ganar en tiempo de desarrollo y claridad, con el unico coste adicional de denir con precisin las entradas y salida de nuestras operaciones. o

134

Cap tulo 8: Programacin orientada a objetos o

8.1.6.

Polimorsmo
El polimorsmo es una nueva caracter stica aportada por la OOP. Esta propiedad

indica la posibilidad de denir varias operaciones con el mismo nombre, diferencindolas a unicamente en los parmetros de entrada. Dependiendo del objeto que se introduzca como a parmetro de entrada, se elegir automticamente cual de las operaciones se va a realizar. a a a Ya est habituado al operador ((suma)) que est presente en todos los lenguajes a a de programacin. Sin embargo, los operadores ((suma de fracciones)) y ((suma de nmeros o u complejos)) no existen en casi ningn lenguaje de programacin. u o Los lenguajes OOP permiten denir un operador ((suma)) tal que reconozca que tipo de objeto se le est aplicando, a travs de operaciones de objetos. Previamente deber denir a e a la fraccin y el nmero complejo como una clase y la operacin suma como una operacin o u o o de una clase. Deniendo adecuadamente las operaciones suma de fracciones y suma de nmeros u imaginarios, el operador suma devolver, en el caso que los operandos sean fracciones, una a fraccin y , en el caso de los nmeros imaginarios, otros nmero imaginario. o u u Es posible extender el concepto e incluso denir operaciones como suma de bases de datos El operador suma de base de datos. Aunque a primera vista la expresin C= o A+B, siendo A y B bases de datos, nos pudiera parecer una extraordinaria simplicacin, o nos conduce a la pregunta: Qu es la suma de una base d datos? e Consideremos varias posibilidades: Introduccin de registros: Lo que exige que A y B tengan la misma estructura. o Unin de campos: Aquellos campos que aparezcan en B pero no en A sern aadio a n dos a C Alguna de estas dos opciones es verdaderamente una suma? Es decir Cumple las propiedades conmutativa, asociativa, de elemento neutro, etc.? Qu ocurre si sumo dos e bases de datos con estructuras distintas? Como puede observar, la denicin de un operador sobre un tipo complejo de datos, o intentando utilizar identicadores de operadores de datos simples, puede tener resultados

8.1. Caracter sticas de los Objetos

135

impredecibles. Una de las ventajas ms importantes, sin entrar en la redenicin de operadoa o res es permitir la realizacin de las clases que denen un programa de forma totalmente o independiente al programa donde se utilizan. Gracias a la encapsulacin y el polimorso mo, aunque se utilicen los mismos nombre con las operaciones en dos clases distintas, el programa reconoce a que clase se aplica durante la ejecucin. o Como se podr observar el polimorsmo y la encapsulacin de datos estn a o a ntimamente ligados y nos permiten un mayor grado de mantenibilidad y reusabilidad que los lenguajes tradicionales Esta ese precisamente una de las causas de la revolucin que ha o supuesto la introduccin de los lenguajes orientados a objetos dentro de la programacin. o o

8.1.7.

Herencia
La herencia es la ultima de las propiedades relativas a la OOP, Consiste en la

propagacin de los atributos y las operaciones a travs de distintas sub-clases denidas a o e partir de una clase comn. u Introduce, por tanto, una posibilidad de renamiento sucesivo del concepto de clase. Nos permite denir una clase principal y , a travs de sucesivas aproximaciones, e cualquier caracter stica de los objetos. A partir de ahora deniremos como sub-clases todas aquellas clases obtenidas mediante renamiento de una (o varias) clases principales. La herencia nos permite crear estructuras jerrquicas de clases donde es posible la a creacin de sub-clases que incluyan nuevas propiedades y atributos. Estas sub-clases admiten o la denicin de nuevos atributos, as como crear, modicar o inhabilitar propiedades. o Para pensarlo de manera ms fcil podemos abstraernos al siguiente ejemplo. a a Pensemos en los distintos sub-modelo s asociados a un modelo bsico de automvil. a o A partir de este modelo bsico, los fabricantes introducen distintas caracter a sticas (aire acondicionado, ABS, distintas tapicer , acabados, etc.) que crean sub-clases. Todas estas as sub-clases tienen en comn la estructura bsica (chasis , direccin , etc.) u var slo en u a o an o algunos de sus componentes. Asociemos a este tipo bsico una clase cuyos atributos representen las piezas que a componen el coche. Las sub-clases aportarn sus propios atributos (en el caso de veh a culos

136

Cap tulo 8: Programacin orientada a objetos o

con aire acondicionado, todos aquellas piezas que lo componen), permitiendo la denicin o de todos los posibles modelos. Adems, es posible que una sub-clase herede atributos y propiedades de ms de a a una clase. Este proceso se denomina herencia mltiple y lo veremos con ms detalle en u a cap tulos posteriores. La herencia es, sin duda alguna, una de las propiedades ms importantes de la a OOP, ya que permite, a travs de la denicin de una clase bsica, ir aadiendo propiedades e o a n a medida que sean necesarias y, adems, en el sub-conjunto de objetos que sea preciso. a La herencia permite que los objetos pueden compartir datos y comportamientos a travs de las diferentes sub-clases, sin incurrir en redundancia. Ms importante que el e a ahorro de cdigo, es la claridad que aporta al identicar que las distintas operaciones sobre o los objetos son en realidad una misma cosa.

8.2.
8.2.1.

Ejemplo de la clase complejo


En Java
A continuacin se presenta un simple ejemplo en Java, que presenta como se lleva o

a cabo la implementacin del objeto que representar a los nmeros complejos. La clase o a u creada se llama complejo y tiene los mtodos de mas, menos, por, entre, imprime e igual. e
/** * <p>Title: Caculadora para numeros complejos</p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Felix Calderon Solorio y sus alumnos * @version 1.0 */ public class complejo { double real, imag; public complejo(double r, double x) { real = r; imag = x; } public complejo() { real = 0; imag = 0; }

8.2. Ejemplo de la clase complejo

137

public complejo mas(complejo b) { complejo resul = new complejo(); resul.real = this.real + b.real; resul.imag = this.imag + b.imag; return resul; } public complejo menos(complejo b) { complejo resul = new complejo(); resul.real = this.real - b.real; resul.imag = this.imag - b.imag; return resul; } public complejo por(complejo b) { complejo resul = new complejo(); resul.real = this.real * b.real - this.imag * b.imag; resul.imag = this.real * b.imag + this.imag * b.real; return resul; } public complejo entre(complejo b) { complejo resul = new complejo(); double den = b.real * b.real + b.imag * b.imag; resul.real = ( this.real * b.real + this.imag * b.imag)/den; resul.imag = (-this.real * b.imag + this.imag * b.real)/den; return resul; } void imprime() { if(this.imag >= 0) System.out.println("(" + this.real + " + j" + this.imag + ") "); else System.out.println("(" +this.real + " - j" + this.imag*-1+ ") "); } void igual(complejo a) { this.real = a.real; this.imag = a.imag; } }

El programa para utilizar esta clase es


/** * <p>Title: Operaciones con numeros complejos </p> * <p>Description: Utiliza las operaciones con complejos * implementadas en la clase complejos * <p>Copyright: Copyright (c) 2005</p> * <p>Company: </p> * @author not attributable * @version 1.0 */

138

Cap tulo 8: Programacin orientada a objetos o

public class ej070 { public static void main(String[] args) { complejo z = new complejo(1,1); z.imprime(); complejo a = new complejo(2, 30); a.imprime(); z.mas(a).imprime(); z.menos(a).imprime(); z.por(a).imprime(); z.entre(a).imprime(); } }

8.2.2.

En C
A continuacin se presenta la misma implementacin de los nmeros complejos o o u

utilizando C. Para hacer uso de este objeto es deseable escribir una nueva clase en donde se haga uso de las operaciones implementadas. Primeramente el archivo de cabecera es
//Archivo complejo.h #if !defined(AFX_complejoS_H__BE3E01D2_0EF7_4E75_B3B0_BAF842CBAB19__INCLUDED_) #define AFX_complejoS_H__BE3E01D2_0EF7_4E75_B3B0_BAF842CBAB19__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include <iostream> using namespace::std; class complejo { public: // Constructores y destructor complejo(double r,double i=0.0); complejo(); virtual ~complejo(); void asigna(double r,double i=0.0); // Asigna un valor a this double Real(void); // Parte real de this double Imag(void); // Parte imaginaria de this complejo conj(void); // Conjugado de this // Sobrecarga de operador * complejo operator*(const complejo &op); // this * op complejo operator*(const double &dop); // this * dop friend complejo operator*(const double &dop,const complejo &op); // Sobrecarga de operador / complejo operator/(const complejo &op); // this / op complejo operator/(const double &dop); // this / dop friend complejo operator/(const double &dop,const complejo &op); // Sobrecarga de operador + complejo operator+(const complejo &op); // this + op

// dop * this

// dop / this

8.2. Ejemplo de la clase complejo

139

complejo operator+(const double &dop); // this + dop friend complejo operator+(const double &dop,const complejo &op); // Sobrecarga de operador complejo operator-(const complejo &op); // this - op complejo operator-(const double &dop); // this - dop friend complejo operator-(const double &dop,const complejo &op); // Operador = sobrecargado completo complejo operator=(const complejo &op); // this=op, op es complejo complejo operator=(const double &dop); // this=dop, dop es double /* Operador << sobrecargado */ friend ostream &operator<<(ostream &os,const complejo &op); protected: double real; double imag; };

// dop + this

// dop - this

#endif // !defined(AFX_complejoS_H__BE3E01D2_0EF7_4E75_B3B0_BAF842CBAB19__INCLUDED_)

La clase completa es
// complejo.cpp: implementation of the complejos class. // ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// /////// /////// Autor: Luis Eduardo Gamboa Guzmn a ltima modificacin: 21 de Septiembre de 2005 /////// U o /////// /////// Facultad de Ingeniera Elctrica e /////// Universidad Michoacana de San Nicolas de Hidalgo /////// /////// ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #include "complejo.h" complejo::complejo(double r,double i) { real=r; imag=i; } complejo::complejo() { real=0.0; imag=0.0; } complejo::~complejo() { } void complejo::asigna(double r,double i) { real=r; imag=i; }

140

Cap tulo 8: Programacin orientada a objetos o

double complejo::Real(void) { return real; } double complejo::Imag(void) { return imag; } complejo complejo::conj(void) { complejo c; c.real=real; c.imag=-imag; return c; } complejo complejo::operator *(const complejo &op) { complejo prod; prod.real=this->real*op.real-this->imag*op.imag; prod.imag=this->real*op.imag+op.real*this->imag; return prod; } complejo complejo::operator*(const double &dop) { complejo prod; prod.real=this->real*dop; prod.imag=this->imag*dop; return prod; } complejo operator*(const double &dop,const complejo &op) { complejo prod; prod.real=op.real*dop; prod.imag=op.imag*dop; return prod; } complejo complejo::operator /(const complejo &op) { complejo divi; double den=op.real*op.real+op.imag*op.imag; divi.real=this->real*op.real + this->imag*op.imag; divi.imag=this->imag*op.real - this->real*op.imag; divi.real/=den; divi.imag/=den; return divi; } complejo complejo::operator/(const double &dop) { complejo divi; divi.real=real/dop; divi.imag=imag/dop; return divi; } complejo operator/(const double &dop,const complejo &op) { complejo divi; double den=op.real*op.real+op.imag*op.imag; divi.real=dop*op.real; divi.imag= -dop*op.imag; divi.real/=den; divi.imag/=den; return divi; } complejo complejo::operator +(const complejo &op) { complejo suma; suma.real=this->real+op.real;

8.2. Ejemplo de la clase complejo

141

suma.imag=this->imag+op.imag; return suma; } complejo complejo::operator+(const double &dop) { complejo suma; suma.real=this->real+dop; suma.imag=this->imag; return suma; } complejo operator+(const double &dop,const complejo &op) { complejo suma; suma.real=op.real+dop; suma.imag=op.imag; return suma; } complejo complejo::operator -(const complejo &op) { complejo resta; resta.real=this->real-op.real; resta.imag=this->imag-op.imag; return resta; } complejo complejo::operator-(const double &dop) { complejo resta; resta.real=this->real-dop; resta.imag=this->imag; return resta; } complejo operator-(const double &dop,const complejo &op) { complejo resta; resta.real=dop-op.real; resta.imag=-op.imag; return resta; } complejo complejo::operator=(const complejo &op) { this->real=op.real; this->imag=op.imag; return *this; } complejo complejo::operator=(const double &dop) { real=dop; imag=0.0; return *this; } ostream& operator<<(ostream & os, const complejo &op) { if(op.imag < 0.0) os << op.real << "-" << "j" << (-1.0)*op.imag; else os << op.real << "+" << "j" << op.imag; return os; }

En un tercer archivo podemos incluir este objeto y hacer uso simplemente de las funciones implementadas en C++.

142

Cap tulo 8: Programacin orientada a objetos o

//ec070.cpp /** * <p>Title: Operaciones con numeros complejos </p> * <p>Description: Utiliza las operaciones con complejos * implementadas en la clase complejos * <p>Copyright: Copyright (c) 2005</p> * <p>Company: </p> * @author not attributable * @version 1.0 */ #include "complejo.cpp" int main() { complejo a(1,1); cout << a << endl; complejo z(2,30); cout << z << endl; cout cout cout cout << << << << a a a a + * / z z z z << << << << endl; endl; endl; endl;

return 1; }

8.3.

La clase matriz
Las operaciones bsicas para le manejo de matrices, fueron denidas en la seccin a o

6.4. A continuacin mostramos el cdigo realizado para la implementacin de la misma. o o o


import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.*; public class Matriz { int nren, ncol; double datos[][]; /** * Crea una matriz nula * */ public Matriz() { nren = 0; ncol = 0; } /** * crea una matriz con n renglones y m columnas de puros ceros * @param n numero de renglones * @param m numero de columnas * */ public Matriz(int n, int m) {

8.3. La clase matriz

143

inicializa(n, m); } public Matriz(int r, int c, double val) { nren = r; ncol = c; datos = new double[nren][ncol]; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) datos[i][j] = val; }

/********************************************************************** * imprime el contenido en una matriz *********************************************************************/ public void imprime() { int i, j; double aux; if ( (nren == 0) && (ncol == 0)) { System.out.println("No tiene informacion la matriz"); return; } for (i = 0; i < this.nren; i++) { for (j = 0; j < this.ncol; j++) System.out.print(redondea(datos[i][j], 7) + " "); System.out.println(" "); } System.out.println("\n\n "); } /***************************************************** rutina para redondear un numero *****************************************************/ String redondea(double dato, int max) { String salida = "", aux = ""; float a; a = ( Math.round(dato * 10000)) / 10000.0f; aux += a; max -= aux.length(); for (int i = 0; i < max; i++) salida += " "; salida += aux; return salida; } /******************************************************* Algoritmo para suma de matrices ********************************************************/ public Matriz mas(Matriz b) { if ( (this.nren != b.nren) || (this.ncol != b.ncol)) return null; Matriz resul = new Matriz(b.nren, b.ncol); for (int i = 0; i < b.nren; i++)

144

Cap tulo 8: Programacin orientada a objetos o

for (int j = 0; j < b.ncol; j++) resul.datos[i][j] = this.datos[i][j] + b.datos[i][j]; return resul; }

/******************************************************* Algoritmo para resta de matrices ********************************************************/ public Matriz menos(Matriz b) { if ( (this.nren != b.nren) || (this.ncol != b.ncol)) return null; Matriz resul = new Matriz(b.nren, b.ncol); for (int i = 0; i < b.nren; i++) for (int j = 0; j < b.ncol; j++) resul.datos[i][j] = this.datos[i][j] - b.datos[i][j]; return resul; } /******************************************************* Algoritmo para multiplicacion de matrices ********************************************************/ public Matriz por(Matriz b) { int i, j; double suma; if (this.ncol == b.nren) { Matriz resul = new Matriz(this.nren, b.ncol); for (i = 0; i < resul.nren; i++) for (j = 0; j < resul.ncol; j++) { suma = 0; for (int k = 0; k < this.ncol; k++) suma += this.datos[i][k] * b.datos[k][j]; resul.datos[i][j] = suma; } return resul; } else System.out.println("Matrices con diferente tama~o"); n return null; } /******************************************************* Algoritmo de Sustitucion hacia atras para resolver sistemas triangulares superiores. ********************************************************/ public Matriz sustitucion_hacia_atras(Matriz a, Matriz b) { if ( (a.nren == a.ncol) && (b.ncol == 1)) { Matriz resul = new Matriz(b.nren, b.ncol); double suma; int k, j; int n = this.nren;

8.3. La clase matriz

145

for (k = n - 1; k >= 0; k--) { suma = 0; for (j = k + 1; j < n; j++) suma += (a.datos[k][j]) * (resul.datos[j][0]); resul.datos[k][0] = ( (b.datos[k][0]) - (suma)) / (a.datos[k][k]); } return resul; } else System.out.println("Las dimenciones de las matrices no son adecuadas"); return null; } // Solucin de un sistema de ecuaciones utilizando EG y S hacia atras o public Matriz entre(Matriz A) { Matriz Ar=null, br = null; Ar = Matriz.igual_a(A); br = Matriz.igual_a(this); Matriz.eliminacion_gaussiana(Ar, br); Matriz resul = sustitucion_hacia_atras(Ar, br); return resul; } /******************************************************* Algoritmo de Eliminacion Gaussiana Entrega una matriz diagonal superior ********************************************************/ public static void eliminacion_gaussiana(Matriz a, Matriz b) { if ( (a.nren == a.ncol) && (b.ncol == 1) && (a.nren == b.nren)) { int n = a.nren; for (int k = 0; k <= n - 2; k++) { for (int i = k + 1; i <= (n - 1); i++) { b.datos[i][0] -= ( (a.datos[i][k] * b.datos[k][0]) / a.datos[k][k]); for (int j = n - 1; j >= k; j--) a.datos[i][j] -= ( (a.datos[i][k] * a.datos[k][j]) / a.datos[k][k]); } } } } }

8.3.1.

Ejemplo
Un pequeo ejemplo de uso es el que se muestra a continuacin. En este se hace n o

se resuelve un sistema de ecuaciones y se realizan algunas operaciones matriciales.


/** * <p>Title: Ejemplo de manejo de la clase matriz</p> * <p>Description: Utiliza la clase matriz para realizar operaciones bsicas</p> a * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSNH</p> * @author Dr. Felix Calderon Solorio * @version 1.0

146

Cap tulo 8: Programacin orientada a objetos o

*/ public class ej073 { public static void main(String[] args) { double a[][] = {{1, 2, 3}, {4,5,6}}; double b[][] = {{1, 2}, {4,5}, {1, 2}}; Matriz C = new Matriz(); Matriz A = new Matriz(a); Matriz B = new Matriz(b); C = A.por(B); C.imprime(); double f[][] = {{4, 2, 1},{2, 6, 3},{1, 3, 10}}; A = new Matriz(f); A.imprime(); double e[] = {10, 0, 0}; B = new Matriz(e); B.imprime(); Matriz x = new Matriz(); x = B.entre(A); x.imprime(); } }

Tarea 17 Aplicacin de la clase matriz o Resolver un problema en donde se haga aplicaciones de la clase matriz. El problema deber ser explicado y dar los detalles de como se utilizar la clase. a a

8.3.2.

Ejemplo en C

8.4.

Herencia
Si se supone que somos buenos programando, cuando creemos una clase es posible

que sea algo util. De modo que cuando estemos haciendo un programa distinto y necesitemos esa clase podremos incluirla en el cdigo de ese nuevo programa. Es la manera ms sencilla o a de reutilizar una clase. Tambin es posible que utilicemos esa clase incluyendo instancias de la misma en e nuevas clases. A eso se le llama composicin. Representa una relacin tiene un. Es decir, o o

8.4. Herencia

147

si tenemos una clase Rueda y una clase Coche, es de esperar que la clase Coche tenga cuatro instancias de Rueda:
class Coche { Rueda rueda1, rueda2, rueda3, rueda4; ... }

Sin embargo, en ocasiones, necesitamos una relacin entre clases algo ms estrecha. o a Una relacin del tipo es un. Por ejemplo, sabemos bien que un gato es un mam o fero. Sin embargo es tambin un concepto ms espec e a co, lo que signica que una clase Gato puede compartir con Mam fero propiedades y mtodos, pero tambin puede tener algunas propias. e e
Herencia.java class Mamifero { String especie, color; } class Gato extends Mamifero { int numero_patas; }

public class Herencia { public static void main(String[] args) { Gato bisho; bisho = new Gato(); bisho.numero_patas = 4; bisho.color = "Negro"; System.out.println(bisho.color); } }

Como vemos en el ejemplo, el objeto bicho no slo tiene la propiedad numero patas, o tambin color que es una propiedad de Mam e fero. Se dice que Mam fero es la clase padre y Gato la clase hija en una relacin de herencia. Esta relacin se consigue en Java por medio o o de la palabra reservada extends. Pero, adems de heredad la funcionalidad de la clase padre, una clase hija puede a sobreescribirla. Podemos escribir un mtodo en la clase hija que tenga el mismo nombre y e los mismos parmetros que un mtodo de la clase padre: a e
Herencia.java class Mamifero { String especie, color; public void mover() { System.out.println("El mamfero se mueve"); } }

148

Cap tulo 8: Programacin orientada a objetos o

class Gato extends Mamifero { int numero_patas; public void mover() { System.out.println("El gato es el que se mueve"); } } public class Herencia { public static void main(String[] args) { Gato bisho = new Gato(); bisho.mover(); } }

Al ejecutar esta nueva versin veremos que se escribe el mensaje de la clase hija, o no el del padre. Conviene indicar que Java es una lenguaje en el que todas las clases son heredadas, an cuando no se indique expl u citamente. Hay una jerarqu de objetos unica, lo que signica a que existe una clase de la cual son hijas todas las dems. Este Adn se llama Object y, a a cuando no indicamos que nuestras clases hereden de nadie, heredan de l. Esto permite que e todas las clases tengan algunas cosas en comn, lo que permite que funcione, entre otras u cosas, el recolector de basura.

8.4.1.

Clases y mtodos abstractos e


Como vimos anteriormente, es posible que con la herencia terminemos creando

una familia de clases con un interfaz comn. En esos casos es posible, y hasta probable, que u la clase ra de las dems no sea una clase util, y que hasta deseemos que el usuario nunca z a haga instancias de ella, porque su utilidad es inexistente. No queremos implementar sus mtodos, slo declararlos para crear una interfaz comn. Entonces declaramos sus mtodos e o u e como abstractos:
public abstract void mi_metodo();

Como vemos, estamos declarando el mtodo pero no implementandolo, ya que e sustituimos el cdigo que deber ir entre llaves por un punto y coma. Cuando existe un o a mtodo abstracto deberemos declarar la clase abstracta o el compilador nos dar un error. e a Al declarar como abstracta una clase nos aseguramos de que el usuario no pueda crear instancias de ella:

8.4. Herencia

149

Abstractos.java abstract class Mamifero { String especie, color; public abstract void mover(); } class Gato extends Mamifero { int numero_patas; public void mover() { System.out.println("El gato es el que se mueve"); } } public class Abstractos { public static void main(String[] args) { Gato bisho = new Gato(); bisho.mover(); } }

En nuestro ejemplo de herencia, parece absurdo pensar que vayamos a crear instancias de Mam fero, sino de alguna de sus clases derivadas. Por eso decidimos declararlo abstracto.

8.4.2.

Ejemplo de la Clase punto


Consideremos que deseamos hacer una clase punto en dos dimensiones y despus e

hacer la representacin de la misma en tres dimensiones. La clase punto tendr un conso a tructor y calcular la distancia entre dos puntos. a
public class punto { double x, y; public punto() { x = 0; y = 0; } public punto(double a, double b) { x = a; y = b; } public void imprime(String a) { System.out.println(a +"(" + x + ", " + y +")"); } public double distancia(punto a, punto b) { double dx, dy; dx = a.x - b.x; dy = a.y - b.y;

150

Cap tulo 8: Programacin orientada a objetos o

return Math.sqrt(dx*dx + dy*dy); } }

La extensin de la clase punto a clase punto en tres dimensiones, utilizando heo rencia queda como:
public class punto3d extends punto { double z; public punto3d() { super(); z = 0; } public punto3d(double a, double b, double c) { super(a,b); z = c; } public void imprime(String a) { System.out.println(a +"(" + x + ", " + y + ", " + z +")"); } public double distancia(punto3d a, punto3d b) { double dx = super.distancia(a, b); double dz = a.z - b.z; return Math.sqrt(dx*dx + dz*dz); } }

8.4.3.

Ejemplo de la clase complejo


En este ejemplo dada la clase vector de dos dimensiones se realiza la implementa-

cin de la clase complejo utilizando herencia. o


public class vector { double x, y; vector(double a, double b) { x = a; y = b; } vector() { x = 0; y = 0;

8.4. Herencia

151

} void suma(vector a, vector b) { x = a.x + b.x; y = a.y + b.y; } void resta(vector a, vector b) { x = a.x - b.x; y = a.y - b.y; } double Producto_Punto(vector a, vector b) { return (a.x*b.x + a.y*b.y); } void imprime() { System.out.print("[" + x + ", " + y + "]"); } }

La implementacin de la clase complejo queda como o

public class complejo3 extends vector{ complejo3(double a, double b, boolean rec) { super(a,b); if(rec == false) polar_rect(a,b,rec); super.imprime(); } void polar_rect(double a, double b, boolean rec) { double mag, ang; mag = a; ang = b*Math.PI/180.0; x = mag * Math.cos(ang); y = mag * Math.sin(ang); } double Magnitud() { return(Math.sqrt(super.Producto_Punto(this,this))); } void multiplica(complejo3 a, complejo3 b) { this.x = a.x*b.x - a.y*b.y; this.y = a.x*b.y + a.y*b.x; } }

152

Cap tulo 8: Programacin orientada a objetos o

8.4.4.

Interfaces
Los interfaces tienen como misin, llevar el concepto de clase abstracta un poco o

ms lejos, amn de permitirnos algo parecido a la herencia mltiple. Pero vamos pasito a a e u pasito. Un interfaz es como una clase abstracta pero no permite que ninguno de sus mtodos e est implementado. Es como una clase abstracta pero en estado ms puro y cristalino. Se e a declaran sustituyendo class por interface:
interface Mamifero { String especie, color; public void mover(); } class Gato implements Mamifero { int numero_patas; public void mover() { System.out.println("El gato es el que se mueve"); } }

No tenemos que poner ningn abstract en ningn sitio porque ya se le supone. u u Hay que jarse tambin que ahora Gato no utiliza extends para hacer la herencia, sino e implements. Sin embargo, la mayor utilidad de los interfaces consiste en permitir la existencia de herencia mltiple, que consiste en que una clase sea heredera de ms de una clase (que u a tenga varios paps, vamos). En C++ exist pero daba enormes problemas, al poder estar a a implementado un mismo mtodo de distinta forma en cada una de las clases padre. En Java e no existe ese problema. Slo podemos heredar de una clase, pero podemos a su vez heredar o de uno o varios interfaces (que no tienen implementacin). Modiquemos nuestro adorado o ejemplo gatuno: ver [Harvey M. Deitel05b]
Interfaces.java interface PuedeMoverse { public void mover(); }

interface PuedeNadar { public void nadar(); } class Mamifero {

8.5. Applets

153

String especie, color; public void mover() { System.out.println("El mamfero se mueve"); } } class Gato extends Mamifero implements PuedeMoverse, PuedeNadar { int numero_patas; public void mover() { System.out.println("El gato es el que se mueve"); } public void nadar() { System.out.println("El gato nada"); } }

public class Interfaces { public static void main(String[] args) { Gato bisho = new Gato(); bisho.mover(); bisho.nadar(); } }

Vemos que Gato tiene la obligacin de implementar los mtodos mover() y nadar(), o e ya que sino lo hace provocar un error de compilacin. Podr no implementar mover(), ya a o a que hereda su implementacin de Mamifero. Pero si decidiramos no hacerlo no habr o e a problemas, ya que tomar la implementacin de su clase padre, ya que los interfaces no a o tienen implementacin. As nos quitamos los problemas que tra la herencia mltiple de o a u C++. Tarea 18 Aplicacin Herencia o Dada la clase punto escribir la clase tringulo la donde este estar denido por tres puna a tos. La clase tringulo tendr los mtodos de imprimir, per a a e metro, rea y obviamente su a constructor. Dada la clase tringulo derivar la clase cuadrado utilizando herencia a

8.5.

Applets
Qu es un applet? Un applet es una pequea aplicacin escrita en Java, pero que e n o

no est diseada para funcionar por s sola, como los ejemplos que hab a n amos visto en modo texto, sino para formar parte de una pgina Web, de modo que necesitaremos un visualizador a

154

Cap tulo 8: Programacin orientada a objetos o

de pginas Web (como Internet Explorer de Microsoft, o Netscape Navigator -parte de a Netscape Communicator-) para poder hacer funcionar dichos applets. Si no poseyramos e alguna utilidad de este tipo, en principio tampoco ser un problema grave, porque el entorno a de desarrollo de Java incluye una utilidad llamada appletviewer, que nos permitir probar a nuestros applets. Cmo se crea un applet? Tendremos que dar tres pasos: o El primer paso, similar a lo que ya hemos hecho, consiste en teclear el programa empleando un editor de texto (como Edit, que ya vimos) o un entorno integrado (que veremos ms adelante). El segundo paso es nuevo: tendremos que crear la pgina Web a a desde la que se acceder al applet (o modicarla, si se trata de una pgina que ya exist a a a pero que queremos mejorar). El ultimo paso ser, al igual que antes, probar el programa, a pero esta vez no emplearemos la utilidad llamada java, sino cualquier navegador Web o la utilidad AppletViewer. Vamos a verlo con un ejemplo. Crearemos un applet que escriba el texto Hola Mundo! en pantalla, al igual que hicimos en nuestra primera aplicacin de ejemplo. o Recordemos que lo que hab amos escrito en aquel momento fue:
// // Aplicacin HolaMundo de ejemplo o // class HolaMundo { public static void main( String args[] ) { System.out.println( "Hola Mundo!" ); } }

Esta vez tendremos que escribir ms. Primero vamos a ver cmo deber ser el a o a applet, y despus comentaremos los cambios (bastantes) con relacin a este programa: e o
import java.awt.Graphics; public class AppletHola extends java.applet.Applet { public void paint(Graphics g) { g.drawString( "Hola Mundo!", 100, 50); } }

Los cambios son los siguientes: Al principio aparece una orden import, porque vamos a emplear una serie de posibilidades que no son parte del lenguaje Java estndar, sino del paquete Graphics a

8.5. Applets

155

(funciones grcas) que a su vez forma parte del grupo llamado AWT (Abstract Windowing a Toolkit, herramientas abstractas para el manejo de ventanas). Despus no creamos una e clase nueva desde cero, sino a partir de una que ya existe, la clase Applet. Por eso aparece la palabra extends en la denicin de la clase, como ya vimos en el apartado sobre las o clases y Java. Slo utilizamos un mtodo de los que nos permite la clase Applet: el mtodo o e e paint, que es el que dibuja (o escribe) en pantalla la informacin que nos interese. Tiene un o parmetro de tipo Graphics, que es la pantalla en la que dibujaremos. En concreto, lo que a hacemos en esta pantalla es dibujar una cadena de texto (drawString), en las coordenadas 100 (horizontal), 50 (vertical). (Un poco ms adelante se ver el resultado de este Applet). a a Y vamos a ver los tres pasos que tenemos que dar, con mayor detalle. Primer paso: teclear el fuente. Repetimos bsicamente lo que ya vimos: a Tecleamos el fuente con Edit, el bloc de notas de Windows, o cualquier otro editor de textos. Lo guardamos, con el mismo nombre que tiene la clase. En nuestro caso ser AppletHola.java (si empleamos otro nombre, el compilador javac nos regaar). a n a Lo compilamos empleando javac. Si hay algn error, se nos informar de cual es; si u a no aparece ningn error, obtendremos un chero llamado AppletHola.class, listo para u utilizar. Segundo paso: crear la pgina Web. No pretendo formar maestros en el arte de a crear pginas Web. Apenas veremos lo necesario para poder probar nuestros Applets. a Las pginas Web normalmente son cheros escritos en un cierto lenguaje. El ms a a sencillo, y totalmente vlido para nuestros propsitos, es el lenguaje HTML. Los cheros a o HTML son cheros de texto, que podremos crear con cualquier editor de texto (ms trabaa joso, pero es como ms control se obtiene, de modo que eso es lo que haremos por ahora) o a con editores espec cos (como Netscape Composer, Microsoft Frontpage, Hot Dog, etc, que permiten crear ms rpido, aunque a veces eso supone perder en posibilidades). a a En nuestro caso, recurriremos nuevamente a Edit (o al bloc de notas de Windows, o cualquier otro editor de textos) y escribiremos lo siguiente:
<html> <head> <title>Prueba de applet</title> </head> <body> <h1>Prueba de applet</h1>

156

Cap tulo 8: Programacin orientada a objetos o

<hr> <applet code=AppletHola.class width=300 height=120> alt="El navegador esta no esta mostrando el APPLET" </applet> </body> </html>

Grabaremos este texto con el nombre prueba.html (servir cualquier otro nombre, a con la unica condicin de que termine en .htm o en .html) para utilizarlo un poco ms o a adelante. Vamos a ver qu hemos escrito: e Es un chero de texto, en el que aparecen algunas etiquetas encerradas entre < y >. El propio chero en s comienza por la etiqueta <html> y termina con <html> (esto ser habitual: la mayor de las etiquetas van por pares, la primera crea un bloque y la a a segunda -la que contiene una barra al principio- indica el nal del bloque). Despus aparece e otro bloque, opcional: la cabecera del chero, que empieza con <head> y termina con <head>. Dentro de la cabecera hemos incluido una informacin que tambin es opcional: o e el t tulo de la pgina, delimitado entre <title> y <title>. Este dato no es necesario, pero a puede resultar cmodo, porque aparecer en la barra de t o a tulo del men (ver las imgenes u a de ejemplo, un poco ms abajo). Despus va el cuerpo del chero html, que se delimita a e entre <body> y <body>. (El cuerpo s es obligatorio). Dentro del cuerpo, lo primero que aparece es un t tulo (en ingls, heading), tambin opcional, delimitado entre <h1> e e y <h1>. Tenemos distintos niveles de t tulos. Por ejemplo, podr amos poner un t tulo de menor importancia delimitndolo entre <h2> y <h2>, o ms pequeo an entre <h3> a a n u y </h3>, y as sucesivamente. La etiqueta <hr> muestra una l nea horizontal (en ingls, e horizontal ruler; claramente, tambin es opcional), y no necesita ninguna etiqueta de e cierre. Finalmente, la parte en la que se indica el applet comienza con <applet> y termina con <applet>. Tambin es opcional en un caso general, pero imprescindible en nuestro e caso. En la etiqueta de comienzo se pueden indicar una serie de opciones, que veremos despus con ms detalle. Nosotros hemos utilizado slo las tres imprescindibles: code sirve e a o para indicar cual es el nombre del applet a utilizar (en nuestro width y height indican la anchura y altura de un rectngulo, medida en puntos de pantalla (pixels). Este rectngulo a a ser la ventana de trabajo de nuestro applet. a

8.5. Applets

157

El resultado de todo esto se puede ver en el siguiente apartado... Tercer paso: probar el resultado. Si queremos usar la utilidad AppletViewer que incorpora el JDK, teclearemos: appletviewer prueba.html y al cabo de un momento, tendremos en pantalla algo parecido a lo que muestra la gura 8.1

Figura 8.1: Ejemplo de visualizacin del Applet con appletviewer. o Tambin podemos usar cualquier otro navegador que soporte Java (cualquiera e moderno deber permitirlo). Por ejemplo, Netscape Navigator 4.5 mostrar la gura 8.2 a a y el Internet Explorer 4 de Microsoft dar una imagen como la mostrada en la gura 8.3 a La vida de un applet. En los applets hay un detalle importante que hemos dejado pasar hasta ahora: no hemos utilizado una funcin main que represente el cuerpo o de la aplicacin. En su lugar, hemos empleado el mtodo paint para indicar qu se debe o e e mostrar en pantalla. Esto es porque un applet tiene un cierto ciclo de vida: Cuando el applet se carga en el navegador, se llama a su mtodo init (que e nosotros no hemos reutilizado). Hace las funciones de un constructor. Cuando el applet se hace visible, se llama a su mtodo start (que tampoco hemos empleado). Se volver a e a llamar cada vez que se vuelva a hacer visible (por ejemplo, si ocultamos nuestro navegador y luego lo volvemos a mostrar). Cuando el applet se va a dibujar en pantalla, se llama a su mtodo paint (como hemos hecho nosotros). El mtodo repaint se utiliza para redibujar e e el applet en pantalla. Es normalmente el que nosotros utilizaremos como programadores,

158

Cap tulo 8: Programacin orientada a objetos o

Figura 8.2: Ejemplo de visualizacin del Applet con Netscape. o

Figura 8.3: Ejemplo de visualizacin del Applet con Internet Explorer o

8.5. Applets

159

llamndolo cuando nos interese, en vez de paint, que ser el que se llame automticamente. a a a A su vez, repaint llama internamente a update, que en ciertos casos nos puede interesar redenir (por ejemplo, si no queremos que se borre toda la pantalla sino slo una parte). o Ambos los veremos con ms detalle un poco ms adelante. Cuando el applet se oculta a a (por ejemplo, si minimizamos la ventana de nuestro navegador), se llama a su mtodo e stop. Ser conveniente que desde l parsemos las animaciones o cualquier otra tarea que a e a consumiese recursos sin necesidad. Cuando se termina de utilizar el applet, se llama a su mtodo destroy. e De momento slo hemos empleado paint. Ms adelante iremos sacando partido o a a otros de estos mtodos (y a otros que nos permiten los applets). e ver [Harvey M. Deitel05b]

8.5.1.

Ejemplo
Hacer un applet que permita elevar un nmero al cuadrado y al cubo. La entrada u

ser desde un campo de texto y las operaciones se realizarn al momento de presionar un a a botn asociado con la operacin a realizar. o o
import java.awt.*; import java.awt.event.*; import java.applet.*;

public class ej016 extends Applet { TextField campo1 = new TextField("0", 15); int bandera = 0; Button boton1 = new Button("Uno"); Button boton2 = new Button("Dos"); public void init() { add(boton1); add(boton2); add(new Label("resultado", Label.RIGHT)); add(campo1); } public void paint(Graphics g) { switch(bandera) { case 1 : g.drawString("has precionado el boton 1", 20, 50); break; case 2 : g.drawString("has precionado el boton 2", 20, 50); break; default : g.drawString("No has precionado boton", 20, 50);

160

Cap tulo 8: Programacin orientada a objetos o

} } public boolean action(Event evt, Object arg) { if(evt.target instanceof Button) { if(arg.equals("Uno")) { campo1.setText(cuadrado(Double.valueOf(campo1.getText()).doubleValue())); } else if(arg.equals("Dos")) { campo1.setText(cubo(Double.valueOf(campo1.getText()).doubleValue())); } return true; } return false; } String cuadrado(double n) { String a = ""; a+= n*n; return a; } String cubo(double n) { String a = ""; a+= n*n*n; return a; } }

8.5.2.

Ejemplo que describe una interfaz de entrada salida

import java.awt.*; import java.awt.event.*; import java.applet.*; /** * <p>Title: Interfaz pspice</p> * <p>Description: Entrada salida de datos</p> * <p>Copyright: Copyright (c) 2005</p> * <p>Company: UMSN</p> * @author Dr. Felix Calderon Solorio * @version 1.0 */ public class Applet1 extends Applet { private boolean isStandalone = false; TextArea textArea1 = new TextArea(); TextArea textArea2 = new TextArea(); Label label1 = new Label(); Label label2 = new Label(); TextField textField1 = new TextField(); Label label3 = new Label();

8.5. Applets

161

Button button1 = new Button(); public void init() { textArea1.setText(""); textArea1.setBounds(new Rectangle(41, 222, 196, 198)); this.setLayout(null); textArea2.setBounds(new Rectangle(254, 223, 196, 198)); textArea2.setText(""); label1.setText("datos de entrada"); label1.setBounds(new Rectangle(96, 203, 92, 15)); label2.setText("datos de Salida"); label2.setBounds(new Rectangle(311, 204, 82, 15)); textField1.setText(""); textField1.setBounds(new Rectangle(187, 101, 118, 20)); label3.setText("Archivo de entrada"); label3.setBounds(new Rectangle(198, 82, 112, 15)); button1.setLabel("Ok"); button1.setBounds(new Rectangle(211, 141, 71, 25)); this.add(textArea1, null); this.add(textArea2, null); this.add(label1, null); this.add(label2, null); this.add(textField1, null); this.add(label3, null); this.add(button1, null); } public boolean action(Event evt, Object arg) { if(evt.target instanceof Button) { if (arg.equals("Ok")) { String aux = textField1.getText(); textArea1.setText("Entrada " + aux); textArea2.setText("salida"+ aux); } } return false; } }

Cap tulo 9

Archivos
9.1. Archivos secuenciales en C
Tipo FILE: C dene la estructura de datos FILE en el chero de cabecera stdio.h para el manejo de cheros. Nosotros siempre usaremos punteros a estas estructuras. La denicin de sta estructura depende del compilador, pero en general mantienen o e un campo con la posicin actual de lectura/escritura, un buer para mejorar las prestaciones o de acceso al chero y algunos campos para uso interno. Funcin fopen: o Sintaxis: FILE *fopen(char *nombre, char *modo); sta funcin sirve para abrir y crear cheros en disco. El valor de retorno es un e o puntero a una estructura FILE. Los parmetros de entrada son: a nombre: una cadena que contiene un nombre de chero vlido, esto depende del sistema a operativo que estemos usando. El nombre puede incluir el camino completo. modo: especica en tipo de chero que se abrir o se crear y el tipo de datos que puede a a contener, de texto o binarios: r: slo lectura. El chero debe existir. o w: se abre para escritura, se crea un chero nuevo o se sobreescribe si ya existe. 163

164

Cap tulo 9: Archivos

a: aadir, se abre para escritura, el cursor se sita al nal del chero. Si el chero no existe, n u se crea. r+: lectura y escritura. El chero debe existir. w+: lectura y escritura, se crea un chero nuevo o se sobreescribe si ya existe. a+: aadir, n lectura y escritura, el cursor se sita al nal del chero. Si el chero no existe, se crea. u t: tipo texto, si no se especica t ni b, se asume por defecto que es t b: tipo binario. Funcin fclose: o Sintaxis: int fclose(FILE *chero); Es importante cerrar los cheros abiertos antes de abandonar la aplicacin. Esta o funcin sirve para eso. Cerrar un chero almacena los datos que an estn en el buer o u a de memoria, y actualiza algunos datos de la cabecera del chero que mantiene el sistema operativo. Adems permite que otros programas puedan abrir el chero para su uso. Muy a a menudo, los cheros no pueden ser compartidos por varios programas. Un valor de retorno cero indica que el chero ha sido correctamente cerrado, si ha habido algn error, el valor de retorno es la constante EOF. El parmetro es un puntero a u a la estructura FILE del chero que queremos cerrar. ver [Harvey M. Deitel05a] Funcin fgetc: o Sintaxis: int fgetc(FILE *chero); Esta funcin lee un carcter desde un chero. o a El valor de retorno es el carcter le como un unsigned char convertido a int. Si a do no hay ningn carcter disponible, el valor de retorno es EOF. El parmetro es un puntero u a a a una estructura FILE del chero del que se har la lectura. a Funcin fputc: o Sintaxis: int fputc(int caracter, FILE *chero); Esta funcin escribe un carcter a un chero. o a

9.1. Archivos secuenciales en C

165

El valor de retorno es el carcter escrito, si la operacin fue completada con xito, a o e en caso contrario ser EOF. Los parmetros de entrada son el carcter a escribir, convertido a a a a int y un puntero a una estructura FILE del chero en el que se har la escritura. a Funcin feof: o Sintaxis: int feof(FILE *chero); Esta funcin sirve para comprobar si se ha alcanzado el nal del chero. Muy o frecuentemente deberemos trabajar con todos los valores almacenados en un archivo de forma secuencial, la forma que suelen tener los bucles para leer todos los datos de un archivo es permanecer leyendo mientras no se detecte el n de chero. Esta funcin suele o usarse como prueba para vericar si se ha alcanzado o no ese punto. El valor de retorno es distinto de cero slo si no se ha alcanzado el n de chero. o El parmetro es un puntero a la estructura FILE del chero que queremos vericar. a Funcin rewind: o Sintaxis: void rewind(FILE *chero); Es una funcin heredada de los tiempos de las cintas magnticas. Literalmente o e signica rebobinar, y hace referencia a que para volver al principio de un archivo almacenado en cinta, hab que rebobinarla. Eso es lo que hace sta funcin, sita el cursor de a e o u lectura/escritura al principio del archivo. El parmetro es un puntero a la estructura FILE del chero que queremos reboa binar. Ejemplos:
// ejemplo1.c: Muestra un fichero dos veces. #include <stdio.h> int main() { FILE *fichero; fichero = fopen("ejemplo1.c", "r"); while(!feof(fichero)) fputc(fgetc(fichero), stdout); rewind(fichero); while(!feof(fichero)) fputc(fgetc(fichero), stdout); fclose(fichero); getchar(); return 0; }

166

Cap tulo 9: Archivos

Funcin fgets: o Sintaxis: char *fgets(char *cadena, int n, FILE *chero); Esta funcin est diseada para leer cadenas de caracteres. Leer hasta n-1 cao a n a racteres o hasta que lea un retorno de l nea. En este ultimo caso, el carcter de retorno de a l nea tambin es le e do. El parmetro n nos permite limitar la lectura para evitar desbordar el espacio a disponible en la cadena. El valor de retorno es un puntero a la cadena le da, si se ley con xito, y es NULL o e si se detecta el nal del chero o si hay un error. Los parmetros son: la cadena a leer, el a nmero de caracteres mximo a leer y un puntero a una estructura FILE del chero del que u a se leer. a Funcin fputs: o Sintaxis: int fputs(const char *cadena, FILE *stream); La funcin fputs escribe una cadena en un chero. No se aade el carcter de o n a retorno de l nea ni el carcter nulo nal. a El valor de retorno es un nmero no negativo o EOF en caso de error. Los parmeu a tros de entrada son la cadena a escribir y un puntero a la estructura FILE del chero donde se realizar la escritura. a Funcin fread: o Sintaxis: size t fread(void *puntero, size t tamao, size t nregistros, FILE *chero); n Esta funcin est pensada para trabajar con registros de longitud constante. Es o a capaz de leer desde un chero uno o varios registros de la misma longitud y a partir de una direccin de memoria determinada. El usuario es responsable de asegurarse de que hay o espacio suciente para contener la informacin le o da. El valor de retorno es el nmero de registros le u dos, no el nmero de bytes. Los u parmetros son: un puntero a la zona de memoria donde se almacenarn los datos le a a dos, el tamao de cada registro, el nmero de registros a leer y un puntero a la estructura FILE n u

9.1. Archivos secuenciales en C

167

del chero del que se har la lectura. a Funcin fwrite: o Sintaxis: size t fwrite(void *puntero, size t tamao, size t nregistros, FILE *chero); n Esta funcin tambin est pensada para trabajar con registros de longitud conso e a tante y forma pareja con fread. Es capaz de escribir hacia un chero uno o varios registros de la misma longitud almacenados a partir de una direccin de memoria determinada. o El valor de retorno es el nmero de registros escritos, no el nmero de bytes. Los u u parmetros son: un puntero a la zona de memoria donde se almacenarn los datos le a a dos, el tamao de cada registro, el nmero de registros a leer y un puntero a la estructura FILE n u del chero del que se har la lectura. a Ejemplo:
// copia.c: Copia de ficheros // Uso: copia <fichero_origen> <fichero_destino> #include <stdio.h> int main(int argc, char **argv) { FILE *fe, *fs; unsigned char buffer[2048]; // Buffer de 2 Kbytes int bytesLeidos; if(argc != 3) { printf("Usar: copia <fichero_origen> <fichero_destino>\n"); return 1; } // Abrir el fichero de entrada en lectura y binario fe = fopen(argv[1], "rb"); if(!fe) { printf("El fichero %s no existe o no puede ser abierto.\n", argv[1]); return 1; } // Crear o sobreescribir el fichero de salida en binario fs = fopen(argv[2], "wb"); if(!fs) { printf("El fichero %s no puede ser creado.\n", argv[2]); fclose(fe); return 1; } // Bucle de copia: while((bytesLeidos = fread(buffer, 1, 2048, fe))) fwrite(buffer, 1, bytesLeidos, fs); // Cerrar ficheros: fclose(fe); fclose(fs); return 0; }

168

Cap tulo 9: Archivos

Funcin fprintf: o Sintaxis: int fprintf(FILE *chero, const char *formato, ...); La funcin fprintf funciona igual que printf en cuanto a parmetros, pero la salida o a se dirige a un chero en lugar de a la pantalla. Funcin fscanf: o Sintaxis: int fscanf(FILE *chero, const char *formato, ...); La funcin fscanf funciona igual que scanf en cuanto a parmetros, pero la entrada o a se toma de un chero en lugar del teclado. Funcin ush: o Sintaxis: int ush(FILE *chero); Esta funcin fuerza la salida de los datos acumulados en el buer de salida del o chero. Para mejorar las prestaciones del manejo de cheros se utilizan buers, almacenes temporales de datos en memoria, las operaciones de salida se hacen a travs del buer, e y slo cuando el buer se llena se realiza la escritura en el disco y se vac el buer. En o a ocasiones nos hace falta vaciar ese buer de un modo manual, para eso sirve sta funcin. e o El valor de retorno es cero si la funcin se ejecut con xito, y EOF si hubo algn o o e u error. El parmetro de entrada es un puntero a la estructura FILE del chero del que se a quiere vaciar el buer. Si es NULL se har el vaciado de todos los cheros abiertos. a Funciones C espec cas para cheros de acceso aleatorio Funcin fseek: o Sintaxis: int fseek(FILE *chero, long int desplazamiento, int origen); Esta funcin sirve para situar el cursor del chero para leer o escribir en el lugar o deseado. El valor de retorno es cero si la funcin tuvo xito, y un valor distinto de cero si o e hubo algn error. u Los parmetros de entrada son: un puntero a una estructura FILE del chero en el a

9.2. Archivos

169

que queremos cambiar el cursor de lectura/escritura, el valor del desplazamiento y el punto de origen desde el que se calcular el desplazamiento. a El parmetro origen puede tener tres posibles valores: a SEEK SET el desplazamiento se cuenta desde el principio del chero. El primer byte del chero tiene un desplazamiento cero. SEEK CUR el desplazamiento se cuenta desde la posicin actual del cursor. SEEK END el desplazamiento se cuenta desde el nal o del chero. Funcin ftell: o Sintaxis: long int ftell(FILE *chero); La funcin ftell sirve para averiguar la posicin actual del cursor de lecturaexcritura o o de un chero. El valor de retorno ser esa posicin, o -1 si hay algn error. a o u El parmetro de entrada es un puntero a una estructura FILE del chero del que a queremos leer la posicin del cursor de lecturaescritura. o

9.2.

Archivos
La clase le (archivo) de la biblioteca de entrada salida de Java, proporciona una

abstraccin independiente de la plataforma para obtener informacin sobre un archivo, tales o o como, su ruta, carcter de separacin, tamao y fecha. Para ello debe crear un objeto File a o n con alguno de los siguientes constructores.
File arch = new File(String ruta); File arch = new File(String ruta, String nombre,); File arch = new File(String dir, String nombre,);

Para saber si un archivo existe podemos utilizar el siguiente cdigo o


File f = new File("temp.txt"); if(f.exists()) System.out.println("El archivo temp.txt, si existe"); else System.out.println("El archivo temp.txt, no existe");

170

Cap tulo 9: Archivos

Muchos programas necesitan extraer informacin a partir de un objeto. La clase o RandomAccessFile (Archivo de acceso aleatorio) proporciona acceso a un archivo de manera secuencia. Para hacer la declaracin procedemos como o
String archivo = "algo.txt"; RandomAccessFile DIS = new RandomAccessFile(archivo, "r");

La variable archivo representa el nombre con el cual se almacena una archivo de texto y la r indica que se trata de solo lectura.
String linea; try { RandomAccessFile DIS = new RandomAccessFile(archivo, "r"); while((linea=DIS.readLine())!=null) { System.out.println(linea); } DIS.close(); } catch(IOException e) { System.out.println(" pude abrir el archivo"); }

Para escribir en un archivo hacemos


try { RandomAccessFile DIS = new RandomAccessFile("salida.txt", "rw"); DIS.writeBytes("hola mundo"); DIS.close(); } catch(IOException e) { System.out.println("no pude abrir el archivo"); }

9.2.1.

Separacin en chas (tokens) o


Al leer una l nea, hay veces que es necesario partir la cadena en piezas especicas

(conocidas como tokens). Para esto utilizaremos la clase StringTokenizer. Los constructores para esta case son:
StringTokenizer(String cadena, String delim, bolean devoverTokens); StringTokenizer(String cadena, String delim); StringTokenizer(String cadena);

9.2. Archivos

171

Con estos constructores podemos hacer la separacin de los elementos de una o cadena de la siguiente manera.
StringTokenizer st = new StringTokenizer("1001 Tips de Java", " "); while(st.hasMoreTokens()) { System.out.println("token:" + st.nextToken()); }

Nota: Es importante hacer el uso de las clases de entrada salida y de utiler de as java, las cuales invocamos haciendo :
import java.io.*; import java.util.*;

al principio del programa.

9.2.2.

Ejemplo
Uniendo las piezas podemos construir un constructor de la clase matriz que nos

permita leer de un archivo los valores de una matriz .


public Matriz(String archivo) { String linea = "", dato = ""; int i = 0, j = 0; StringTokenizer st; double x; Dimensiones(archivo) ; datos = new double[nren][ncol]; try { RandomAccessFile DIS = new RandomAccessFile(archivo, "r"); i = 0; while ( ( (linea = DIS.readLine()) != null) && i < nren) { st = new StringTokenizer(linea); if(st.countTokens() != 0) { st = new StringTokenizer(linea); for (j = 0; j < ncol; j++) { dato = st.nextToken(); x = Double.valueOf(dato).doubleValue(); this.datos[i][j] = x; } i++; } } DIS.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null, "Error" + e.toString(), "ERROR", JOptionPane.ERROR_MESSAGE); } }

172

Cap tulo 9: Archivos

Para leer las dimensiones de la matriz hacemos la funcin: o


public void Dimensiones(String archivo) { StringTokenizer st; String linea; int num_ren = 0, num_col = 0; try { RandomAccessFile DIS = new RandomAccessFile(archivo, "r"); while ( (linea = DIS.readLine()) != null) { st = new StringTokenizer(linea); if(st.countTokens() != 0) num_ren ++; if(num_col == 0) { while (st.hasMoreTokens()) { num_col++; st.nextToken(); } } } this.nren = num_ren; this.ncol = num_col; DIS.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null, "Error" + e.toString(), "ERROR", JOptionPane.ERROR_MESSAGE); } }

ver [Harvey M. Deitel05a] Tarea 19 Manejo de archivos En referencia a la tarea anterior, escribir el mtodo imprime que reciba como parmetro el e a nombre de un archivo de salida. En este archivo, este mtodo, debe escribir los puntos que e forman el cuadro, el rea y el per a metro de esta gura geomtrica. e 10.

Cap tulo 10

Aplicaciones
10.1. solucin de circuitos elctricos o e
Solucin de Circuitos. o Una posibilidad de solucin de un circuito elctrico, es la solucin utilizando anlio e o a sis de nodos la cual, consiste en solucionar un sistema de ecuaciones dada por

Gv = I

donde: G es la matriz de conductancias v el vector de voltajes nodales I el vector de corriente en cada nodo. La descripcin del circuito la haremos en un archivo de datos y consideraremos o que un elemento esta conectado a un par de nodos. Un nodo ser de salida y otro de entrada a tal como se muestra en la siguiente tabla: 173

174

Cap tulo 10: Aplicaciones

Elem. Nodo Nodo Conductancia Fuente No. salida entrada mho corriente k i j g F 1 0 1 1 1 2 1 2 2 0 3 2 0 3 0 4 2 3 2 0 5 3 0 4 -5 6 1 3 0 3 nota: la informacin en amarillo no es parte del archivo de datos. o De tabla anterior podemos ver que el circuito esta formado por cuatro nodos, numerados del 0 al 3 y que este tiene 6 elementos. Por lo tanto, solucionaremos un sistema de tres ecuaciones con tres incgnitas. o Para una conductancia g conectada entre el nodo i y el j con una fuente de Corriente F, tomadas de la tabla, llenaremos la matriz de conductancias G y el vector de corrientes utilizando las siguientes reglas. 1.- Si tanto los nodo i y j son diferentes de cero, hacemos:

Gi, j = Gi, j g Gj, i = Gj, i g 2.- Si el i-esimo nodo es diferente de cero, hacemos:

Gi, i = Gi, i + g Ii = Ii F 3.- Si el j-esimo nodo diferente de cero, hacemos:

Gj, j = Gj, j + g Ij = Ij + F Aplicando estos paso tenemos:

10.1. solucin de circuitos elctricos o e

175

Para el elemento 1 tendremos: 1 0 0 v1 1 0 0 0 v2 = 0 0 0 0 v3 0 Para el elemento 2:

2 0 Para el elemento 3

2 0 2 0

v1

0 v2 = 0 = 0 v3 0

2 0 Para 4

2 0 5 0

0 v2 = 0 = 0 v3 0

v1

2 7 2 v2 = 0 = 0 2 2 v3 0 Para 5 3 2 7 2 v2 = 0 = 0 2 6 v3 5 Finalmente para el elemento 6 2 0 v1 1

v1

2 7 2 v2 = 0 = v3 0 2 6 8 La solucin de este sistema es : o

v1

176

Cap tulo 10: Aplicaciones

v = 0.2667 = 1.4222 La implementacin en Java queda como: o


/** * Programa para resolver un circuito utilizando analisis nodal * Este programa lee la descripcin de un circuito y lo soluciona o * Copyright: Copyright (c) 2005</p> * UMSNH * Dr. Felix Calderon Solorio * @version 1.0 */ public class ej027 { public static void main(String[] args) { Matriz desc = new Matriz("cto.txt"); int i, j, k, nodos = 0; for(k=0; k<desc.nren; k++) { if (nodos < desc.datos[k][0]) nodos = (int) desc.datos[k][0]; if (nodos < desc.datos[k][1]) nodos = (int) desc.datos[k][1]; } Matriz G = new Matriz(nodos, nodos); Matriz v = new Matriz(nodos, 1); Matriz I = new Matriz(nodos, 1); for(k=0; k<desc.nren; k++) { i = (int) desc.datos[k][0]; j = (int) desc.datos[k][1]; if(i!=0 && j != 0) { G.datos[i - 1][j - 1] -= desc.datos[k][2]; G.datos[j - 1][i - 1] -= desc.datos[k][2]; } if(i!=0) { G.datos[i-1][i-1] += desc.datos[k][2]; I.datos[i-1][0] -= desc.datos[k][3]; } if(j!=0) { G.datos[j-1][j-1] += desc.datos[k][2]; I.datos[j-1][0] += desc.datos[k][3]; } } G.imprime(); I.imprime(); v = I.entre(G); v.imprime(); } }

0.4889

10.1. solucin de circuitos elctricos o e

177

10.1.1.

Formato Estndar de Pspice a


Un formato estndar muy utilizado es el del programa de Pspice. Para un circuito a

simple, formado por resistencias, fuentes de corriente y fuentes de voltaje, la descripcin se o hace de la siguiente manera: Tipo de Nodo Nodo Elemento salida entrada Valor V1 0 1 20 I2 1 2 2 R23 2 0 3.5 Para describir un elemento hacemos: 1.- Dar un nombre que comenzar con V, I o R si se trata de una fuente de voltaje, a corriente o resistencia respectivamente. 2.- Dar la informacin del par de nodos a los cuales esta conectado. El nodo de o salida indicar el nodo negativo del elemento y el nodo de entrada el nodo positivo del a elemento. 3.- Dar el valor de la fuente en unidades del Sistema internacional, por ejemplo, Volts, Amperes y ohms de acuerdo al tipo de elemento.
package ejemplos; import java.io.*; import java.util.*; import javax.swing.*; /** * Programa para leer Un archivo en formato Pspice * Lee los datos de un archivo y soluciona el circuito. * Copyright: Copyright (c) 2005 * Company: UMSNH * @author Dr. Felix Calderon Solorio. * @version 1.0 */ public class ej028 { public static void main(String[] args) { int nodos; String archivo = "resnick.txt"; nodos = NumNodos(archivo); Matriz G = new Matriz(nodos, nodos); Matriz I = new Matriz(nodos, 1); Matriz v = new Matriz(nodos, 1); LlenaSistema(G, I, archivo); G.imprime(); I.imprime(); v.eliminacion_gaussiana(G, I); G.imprime();

178

Cap tulo 10: Aplicaciones

v.sustitucion_hacia_atras(G, I); v.imprime(); } public static int NumNodos(String archivo) { StringTokenizer st; String linea, elemento, inicio, fin; int nodos = 0, val; try { RandomAccessFile DIS = new RandomAccessFile(archivo, "r"); while ( (linea = DIS.readLine()) != null) { st = new StringTokenizer(linea); if (st.countTokens() != 0) { elemento = st.nextToken(); inicio = st.nextToken(); fin = st.nextToken(); val = (int) Double.valueOf(inicio).doubleValue(); if(val > nodos) nodos = val; val = (int) Double.valueOf(fin).doubleValue(); if(val > nodos) nodos = val; } } DIS.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null, "Error" + e.toString(), "ERROR", JOptionPane.ERROR_MESSAGE); } return nodos; } // *********************************************************************** public static void LlenaSistema(Matriz G, Matriz I, String archivo) { StringTokenizer st; String linea, elemento, inicio, fin, valor; char tipo ; int i, j; double val; try { RandomAccessFile DIS = new RandomAccessFile(archivo, "r"); while ( (linea = DIS.readLine()) != null) { st = new StringTokenizer(linea); if (st.countTokens() != 0) { elemento inicio fin valor = = = = st.nextToken(); st.nextToken(); st.nextToken(); st.nextToken();

tipo = elemento.charAt(0); i = (int) Double.valueOf(inicio).doubleValue(); j = (int) Double.valueOf(fin).doubleValue(); val = Double.valueOf(valor).doubleValue();

10.1. solucin de circuitos elctricos o e

179

switch(tipo) { case R: case r: if(i!=0 && j != 0) { G.datos[i - 1][j - 1] -= G.datos[j - 1][i - 1] -= } if(i!=0) G.datos[i-1][i-1] if(j!=0) G.datos[j-1][j-1] break;

1.0/val; 1.0/val; += 1.0/val; += 1.0/val;

case I: case i: if(i!=0) I.datos[i-1][0] -= val; if(j!=0) I.datos[j-1][0] += val; break; case V: case v: val = val / 1e-06; if(i!=0) I.datos[i-1][0] -= val; if(j!=0) I.datos[j-1][0] += val; val = 1e+06; if(i!=0 && j != 0) { G.datos[i - 1][j - 1] -= G.datos[j - 1][i - 1] -= } if(i!=0) G.datos[i-1][i-1] if(j!=0) G.datos[j-1][j-1] } } } DIS.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null, "Error" + e.toString(), "ERROR", JOptionPane.ERROR_MESSAGE); } } }

val; val; += val; += val;

Referencias
[Harvey M. Deitel05a] Harvey M. Deitel, P. J. D. Como Programar en C/C++. Prentice
Hall, 5a edon., 2005.

[Harvey M. Deitel05b] Harvey M. Deitel, P. J. D. Como Programar en Java. Prentice Hall,


6a edon., 2005.

[Mark C Chan98]

Mark C Chan, S. W. G. y Iasi, A. F. 1001 Tips para Programa con Java. Mc Graw Hill, 1998.

181

You might also like