Explora Libros electrónicos
Categorías
Explora Audiolibros
Categorías
Explora Revistas
Categorías
Explora Documentos
Categorías
. Casilla 653, Correo 1, Santiago fono: 562 978 7276 fax: 562 271 2973 e-mail: secretaria@sica.ciencias.uchile.cl
Apuntes de un curso de
ii
Agradecimientos:
Xavier Andrade. Denisse Pastn. e De la promocin del 2004 a: Daniel Asenjo y Max Ram o rez. De la promocin del 2005 a: Alejandro Varas y Mar Daniela Cornejo. o a De la promocin del 2006 a: Nicols Verschueren y Paulina Chacn, o a o Sergio Valdivia y Elizabeth Villanueva.
iv
Indice
I Computacin o
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
3 3 4 4 5 5 6 6 7 9 9 10 11 11 12 12 13 16 23 23 23 24 25 26 27 27 27 29 29 29 31 31 33 33
1. Elementos del sistema operativo unix. 1.1. Introduccin. . . . . . . . . . . . . . . . . . . . . o 1.2. Ingresando al sistema. . . . . . . . . . . . . . . . 1.2.1. Terminales. . . . . . . . . . . . . . . . . . 1.2.2. Login. . . . . . . . . . . . . . . . . . . . . 1.2.3. Passwords. . . . . . . . . . . . . . . . . . . 1.2.4. Cerrando la sesin. . . . . . . . . . . . . . o 1.3. El Proyecto Debian. . . . . . . . . . . . . . . . . 1.4. Archivos y directorios. . . . . . . . . . . . . . . . 1.5. Ordenes bsicas. . . . . . . . . . . . . . . . . . . a 1.5.1. Ordenes relacionadas con archivos. . . . . 1.5.2. Ordenes relacionadas con directorios. . . . 1.5.3. Visitando archivos. . . . . . . . . . . . . . 1.5.4. Copiando, moviendo y borrando archivos. 1.5.5. Espacio de disco. . . . . . . . . . . . . . . 1.5.6. Links. . . . . . . . . . . . . . . . . . . . . 1.5.7. Proteccin de archivos. . . . . . . . . . . . o 1.5.8. Filtros. . . . . . . . . . . . . . . . . . . . . 1.5.9. Otros usuarios y mquinas . . . . . . . . . a 1.5.10. Fecha . . . . . . . . . . . . . . . . . . . . 1.5.11. Diferencias entre sistemas. . . . . . . . . . 1.6. Shells. . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1. Variables de entorno. . . . . . . . . . . . 1.6.2. Redireccin. . . . . . . . . . . . . . . . . . o 1.6.3. Ejecucin de comandos. . . . . . . . . . . o 1.6.4. Aliases. . . . . . . . . . . . . . . . . . . . 1.6.5. La shell bash. . . . . . . . . . . . . . . . . 1.6.6. Archivos de script. . . . . . . . . . . . . . 1.7. Ayuda y documentacin. . . . . . . . . . . . . . . o 1.8. Procesos. . . . . . . . . . . . . . . . . . . . . . . . 1.9. Editores. . . . . . . . . . . . . . . . . . . . . . . . 1.9.1. El editor vi. . . . . . . . . . . . . . . . . . 1.9.2. Editores modo emacs. . . . . . . . . . . . 1.10. El sistema X Windows. . . . . . . . . . . . . . . .
v
vi
INDICE 1.11. Uso del ratn. . . . . . . . . o 1.12. Internet. . . . . . . . . . . . 1.12.1. Acceso a la red. . . . 1.12.2. El correo electrnico. o 1.12.3. Ftp anonymous. . . . 1.12.4. WWW. . . . . . . . 1.13. Impresin. . . . . . . . . . . o 1.14. Compresin. . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 36 37 39 39 39 40 43 43 43 43 44 44 45 45 46 46 46 46 47 48 49 49 49 50 50 50 52 52 52 53 53 53 54 54 54 55 55 55 56 56 57
2. Introduccin a programacin. o o 2.1. Qu es programar? . . . . . . . . . . . . . . . e 2.2. Lenguajes de programacin. . . . . . . . . . . o 2.2.1. Cdigo de Mquina binario. . . . . . . o a 2.2.2. Lenguaje de Ensamblador (Assembler). 2.2.3. Lenguaje de alto nivel. . . . . . . . . . 2.2.4. Lenguajes interpretados. . . . . . . . . 2.2.5. Lenguajes especializados. . . . . . . . . 2.3. Lenguajes naturales y formales. . . . . . . . . 2.3.1. Lenguajes naturales. . . . . . . . . . . 2.3.2. Lenguajes formales. . . . . . . . . . . . 2.4. Desarrollando programas. . . . . . . . . . . . 2.5. La interfaz con el usuario. . . . . . . . . . . . 2.6. Sacar los errores de un programa. . . . . . . . 3. Una breve introduccin a Python. o 3.1. Python. . . . . . . . . . . . . . . . . . . . . . 3.1.1. Interactivo versus scripting. . . . . . . 3.1.2. Creando un script. . . . . . . . . . . . 3.2. Lenguaje Python. . . . . . . . . . . . . . . . . 3.2.1. Algunos tipos bsicos. . . . . . . . . . a 3.2.2. Imprimiendo en la misma l nea. . . . . 3.2.3. Imprimiendo un texto de varias l neas. 3.2.4. Variables. . . . . . . . . . . . . . . . . 3.2.5. Asignacin de variables. . . . . . . . . o 3.2.6. Reciclando variables. . . . . . . . . . . 3.2.7. Operaciones matemticas. . . . . . . . a 3.2.8. Operaciones con strings. . . . . . . . . 3.2.9. Composicin. . . . . . . . . . . . . . . o 3.2.10. Comentarios. . . . . . . . . . . . . . . 3.2.11. Entrada (input). . . . . . . . . . . . . 3.3. Condicionales. . . . . . . . . . . . . . . . . . . 3.3.1. Posibles condicionales. . . . . . . . . . 3.3.2. El if. . . . . . . . . . . . . . . . . . . 3.3.3. El if. . . else. . . . . . . . . . . . . . . 3.3.4. El if...elif...else. . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
INDICE 3.3.5. La palabra clave pass. . . . . . . . . . . . 3.3.6. Operadores lgicos. . . . . . . . . . . . . . o 3.3.7. Forma alternativa. . . . . . . . . . . . . . 3.4. Funciones Pre-hechas. . . . . . . . . . . . . . . . 3.4.1. Algunas funciones incorporadas. . . . . . . 3.4.2. Algunas funciones del mdulo math. . . . . o 3.4.3. Algunas funciones del mdulo string. . . o 3.4.4. Algunas funciones del mdulo random. . . o 3.4.5. Algunos otros mdulos y funciones. . . . . o 3.5. Funciones hechas en casa. . . . . . . . . . . . . . 3.5.1. Receta para una funcin. . . . . . . . . . . o 3.5.2. Variables globales. . . . . . . . . . . . . . 3.5.3. Pasando valores a la funcin. . . . . . . . o 3.5.4. Valores por defecto de una funcin. . . . . o 3.6. Argumentos Claves. . . . . . . . . . . . . . . . . . 3.7. DocStrings. . . . . . . . . . . . . . . . . . . . . . 3.7.1. La palabra clave return. . . . . . . . . . . 3.7.2. Funciones que tienen un valor de retorno. . 3.7.3. Recursin. . . . . . . . . . . . . . . . . . . o 3.8. Parmetros desde la l a nea de comando. . . . . . . 3.9. Iteraciones con while. . . . . . . . . . . . . . . . 3.10. Los strings. . . . . . . . . . . . . . . . . . . . . . 3.10.1. Indice negativos. . . . . . . . . . . . . . . 3.10.2. Cun largo es un string? . . . . . . . . . a 3.10.3. Recorriendo un string. . . . . . . . . . . . 3.10.4. El ciclo for. . . . . . . . . . . . . . . . . . 3.10.5. Comparando strings. . . . . . . . . . . . . 3.11. Listas. . . . . . . . . . . . . . . . . . . . . . . . . 3.11.1. Rebanando listas. . . . . . . . . . . . . . . 3.11.2. Mutabilidad. . . . . . . . . . . . . . . . . 3.11.3. Agregando a una lista. . . . . . . . . . . . 3.11.4. Operaciones con listas. . . . . . . . . . . . 3.11.5. Borrando items de una lista. . . . . . . . . 3.11.6. Qu contiene una lista? . . . . . . . . . . e 3.11.7. Un ciclo for y las listas. . . . . . . . . . . 3.11.8. Otros trucos con listas. . . . . . . . . . . . 3.11.9. Generando listas de nmeros. . . . . . . . u 3.12. Tuplas. . . . . . . . . . . . . . . . . . . . . . . . . 3.13. El comando break. . . . . . . . . . . . . . . . . . 3.14. Trabajando con archivos. . . . . . . . . . . . . . . 3.14.1. Funciones del mdulo os. . . . . . . . . . . o 3.14.2. Funciones del mdulo os.path. . . . . . . o 3.14.3. Ejemplo de un cdigo. . . . . . . . . . . . o 3.14.4. Abriendo un archivo. . . . . . . . . . . . . 3.14.5. Leyendo un archivo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vii
57 57 58 58 59 60 60 60 60 61 61 62 62 62 63 64 64 65 65 66 67 67 68 68 68 68 69 69 70 70 71 71 71 71 72 72 72 73 73 74 74 74 75 75 75
viii
INDICE 3.14.6. Escribiendo a un archivo. . . . . . . . . . . . 3.14.7. Cerrando un archivo. . . . . . . . . . . . . . 3.14.8. Archivos temporales. . . . . . . . . . . . . . 3.14.9. Ejemplo de lectura escritura. . . . . . . . . . 3.15. Excepciones. . . . . . . . . . . . . . . . . . . . . . . 3.16. Diccionarios. . . . . . . . . . . . . . . . . . . . . . . 3.16.1. Editando un diccionario. . . . . . . . . . . . 3.16.2. Un ejemplo de cdigo, un men. . . . . . . . o u 3.16.3. Tuplas y diccionarios como argumentos. . . 3.17. Modules y Shelve. . . . . . . . . . . . . . . . . . . . 3.17.1. Partiendo el cdigo. . . . . . . . . . . . . . . o 3.17.2. Creando un mdulo. . . . . . . . . . . . . . o 3.17.3. Agregando un nuevo directorio al path. . . . 3.17.4. Haciendo los mdulos fciles de usar. . . . . o a 3.17.5. Usando un mdulo. . . . . . . . . . . . . . . o 3.17.6. Trucos con mdulos. . . . . . . . . . . . . . o 3.17.7. Preservando la estructura de la informacin. o 3.17.8. Cmo almacenar? . . . . . . . . . . . . . . o 3.17.9. Ejemplo de shelve. . . . . . . . . . . . . . . 3.17.10.Otras funciones de shelve. . . . . . . . . . . 3.18. Clases y mtodos. . . . . . . . . . . . . . . . . . . . e 3.18.1. Clase de muestra LibretaNotas. . . . . . . . 3.18.2. Valores por defecto. . . . . . . . . . . . . . . 3.19. Sobrecarga de Operadores. . . . . . . . . . . . . . . 3.19.1. Funcin driver. . . . . . . . . . . . . . . . . o 3.19.2. Atributos de las clases. . . . . . . . . . . . . 3.19.3. Ejemplo de clase vectores. . . . . . . . . . . 3.20. Algunos mdulos interesantes. . . . . . . . . . . . . o 3.20.1. El mdulo Numeric. . . . . . . . . . . . . . o 3.20.2. El mdulo Tkinter. . . . . . . . . . . . . . o 3.20.3. El mdulo Visual. . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 76 76 76 77 77 78 79 79 79 79 79 80 80 80 81 81 81 82 82 82 83 84 84 85 85 86 86 86 87 87 89 89 89 90 92 92 94 95 95 95 96 98 98
4. Una breve introduccin a C++. o 4.1. Estructura bsica de un programa en C++. a 4.1.1. El programa ms simple. . . . . . . . a 4.1.2. Denicin de funciones. . . . . . . . o 4.1.3. Nombres de variables. . . . . . . . . 4.1.4. Tipos de variables. . . . . . . . . . . 4.1.5. Ingreso de datos desde el teclado. . . 4.1.6. Operadores aritmticos. . . . . . . . e 4.1.7. Operadores relacionales. . . . . . . . 4.1.8. Asignaciones. . . . . . . . . . . . . . 4.1.9. Conversin de tipos. . . . . . . . . . o 4.2. Control de ujo. . . . . . . . . . . . . . . . . 4.2.1. if, if... else, if... else if. . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
INDICE 4.2.2. Expresin condicional. . . . . . . . . . . . . . . o 4.2.3. switch. . . . . . . . . . . . . . . . . . . . . . . 4.2.4. for. . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5. while. . . . . . . . . . . . . . . . . . . . . . . . 4.2.6. do... while. . . . . . . . . . . . . . . . . . . . 4.2.7. goto. . . . . . . . . . . . . . . . . . . . . . . . 4.3. Funciones. . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1. Funciones tipo void. . . . . . . . . . . . . . . . 4.3.2. return. . . . . . . . . . . . . . . . . . . . . . . 4.3.3. Funciones con parmetros. . . . . . . . . . . . . a 4.3.4. Parmetros por defecto. . . . . . . . . . . . . . a 4.3.5. Ejemplos de funciones: ra cuadrada y factorial. z 4.3.6. Alcance, visibilidad, tiempo de vida. . . . . . . 4.3.7. Recursin. . . . . . . . . . . . . . . . . . . . . . o 4.3.8. Funciones internas. . . . . . . . . . . . . . . . . 4.4. Punteros. . . . . . . . . . . . . . . . . . . . . . . . . . 4.5. Matrices o arreglos. . . . . . . . . . . . . . . . . . . . . 4.5.1. Declaracin e inicializacin. . . . . . . . . . . . o o 4.5.2. Matrices como parmetros de funciones. . . . . a 4.5.3. Asignacin dinmica. . . . . . . . . . . . . . . . o a 4.5.4. Matrices multidimensionales. . . . . . . . . . . . 4.5.5. Matrices de caracteres: cadenas (strings). . . . . 4.6. Manejo de archivos. . . . . . . . . . . . . . . . . . . . . 4.6.1. Archivos de salida. . . . . . . . . . . . . . . . . 4.6.2. Archivos de entrada. . . . . . . . . . . . . . . . 4.6.3. Archivos de entrada y salida. . . . . . . . . . . 4.7. main como funcin. . . . . . . . . . . . . . . . . . . . . o 4.7.1. Tipo de retorno de la funcin main. . . . . . . . o 4.8. Clases. . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8.1. Denicin. . . . . . . . . . . . . . . . . . . . . . o 4.8.2. Miembros. . . . . . . . . . . . . . . . . . . . . . 4.8.3. Miembros pblicos y privados. . . . . . . . . . . u 4.8.4. Operador de seleccin (.). . . . . . . . . . . . . o 4.8.5. Implementacin de funciones miembros. . . . . o 4.8.6. Constructor. . . . . . . . . . . . . . . . . . . . . 4.8.7. Destructor. . . . . . . . . . . . . . . . . . . . . 4.8.8. Arreglos de clases. . . . . . . . . . . . . . . . . 4.9. Sobrecarga. . . . . . . . . . . . . . . . . . . . . . . . . 4.9.1. Sobrecarga de funciones. . . . . . . . . . . . . . 4.9.2. Sobrecarga de operadores. . . . . . . . . . . . . 4.9.3. Coercin. . . . . . . . . . . . . . . . . . . . . . o 4.10. Herencia. . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11. Ejemplo: la clase de los complejos. . . . . . . . . . . . . 4.12. Compilacin y debugging. . . . . . . . . . . . . . . . . o 4.12.1. Compiladores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ix
100 100 101 103 104 104 104 104 105 106 109 110 113 115 116 117 119 119 119 120 121 123 125 125 128 129 130 132 133 134 134 134 135 136 136 137 138 138 139 139 139 140 141 145 145
INDICE 147 . 147 . 148 . 148 . 149 . 149 . 150 . 151 153 . 153 . 153 . 154 . 154 . 154 . 155 . 155 . 156 . 157 . 157 . 157 . 158 . 159 . 160 . 160 . 161 . 162 . 163 . 164 . 164 . 164 . 165 . 165 . 166 . 166 . 166 . 168 . 169 . 171 . 172 . 172 . 172 . 173 . 173 . 174
5. Grca. a 5.1. Visualizacin de archivos grcos. . . o a 5.2. Modicando imgenes . . . . . . . . a 5.3. Conversin entre formatos grcos. . o a 5.4. Captura de pantalla. . . . . . . . . . 5.5. Creando imgenes. . . . . . . . . . . a 5.6. Gracando funciones y datos. . . . . 5.7. Gracando desde nuestros programas.
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
6. El sistema de preparacin de documentos TEX . o 6.1. Introduccin. . . . . . . . . . . . . . . . . . . . . o 6.2. Archivos. . . . . . . . . . . . . . . . . . . . . . . . 6.3. Input bsico. . . . . . . . . . . . . . . . . . . . . a 6.3.1. Estructura de un archivo. . . . . . . . . . 6.3.2. Caracteres. . . . . . . . . . . . . . . . . . 6.3.3. Comandos. . . . . . . . . . . . . . . . . . 6.3.4. Algunos conceptos de estilo. . . . . . . . . 6.3.5. Notas a pie de pgina. . . . . . . . . . . . a 6.3.6. Frmulas matemticas. . . . . . . . . . . . o a 6.3.7. Comentarios. . . . . . . . . . . . . . . . . 6.3.8. Estilo del documento. . . . . . . . . . . . . 6.3.9. Argumentos de comandos. . . . . . . . . . 6.3.10. T tulo. . . . . . . . . . . . . . . . . . . . . 6.3.11. Secciones. . . . . . . . . . . . . . . . . . . 6.3.12. Listas. . . . . . . . . . . . . . . . . . . . . 6.3.13. Tipos de letras. . . . . . . . . . . . . . . . 6.3.14. Acentos y s mbolos. . . . . . . . . . . . . . 6.3.15. Escritura de textos en castellano. . . . . . 6.4. Frmulas matemticas. . . . . . . . . . . . . . . . o a 6.4.1. Sub y supra ndices. . . . . . . . . . . . . . 6.4.2. Fracciones. . . . . . . . . . . . . . . . . . . 6.4.3. Ra ces. . . . . . . . . . . . . . . . . . . . . 6.4.4. Puntos suspensivos. . . . . . . . . . . . . . 6.4.5. Letras griegas. . . . . . . . . . . . . . . . . 6.4.6. Letras caligrcas. . . . . . . . . . . . . . a 6.4.7. S mbolos matemticos. . . . . . . . . . . . a 6.4.8. Funciones tipo logaritmo. . . . . . . . . . 6.4.9. Matrices. . . . . . . . . . . . . . . . . . . . 6.4.10. Acentos. . . . . . . . . . . . . . . . . . . . 6.4.11. Texto en modo matemtico. . . . . . . . . a 6.4.12. Espaciado en modo matemtico. . . . . . . a 6.4.13. Fonts. . . . . . . . . . . . . . . . . . . . . 6.5. Tablas. . . . . . . . . . . . . . . . . . . . . . . . . 6.6. Referencias cruzadas. . . . . . . . . . . . . . . . . 6.7. Texto centrado o alineado a un costado. . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
INDICE 6.8. Algunas herramientas importantes . . . . . . 6.8.1. babel . . . . . . . . . . . . . . . . . A 6.8.2. AMS-L TEX . . . . . . . . . . . . . . 6.8.3. fontenc . . . . . . . . . . . . . . . . 6.8.4. enumerate . . . . . . . . . . . . . . . 6.8.5. Color. . . . . . . . . . . . . . . . . . 6.9. Modicando el estilo de la pgina. . . . . . . a 6.9.1. Estilos de pgina. . . . . . . . . . . . a 6.9.2. Corte de pginas y l a neas. . . . . . . 6.10. Figuras. . . . . . . . . . . . . . . . . . . . . 6.10.1. graphicx.sty . . . . . . . . . . . . . 6.10.2. Ambiente figure. . . . . . . . . . . . 6.11. Cartas. . . . . . . . . . . . . . . . . . . . . . A 6.12. L TEX y el formato pdf. . . . . . . . . . . . . A 6.13. Modicando L TEX. . . . . . . . . . . . . . . 6.13.1. Denicin de nuevos comandos. . . . o 6.13.2. Creacin de nuevos paquetes y clases o 6.14. Errores y advertencias. . . . . . . . . . . . . 6.14.1. Errores. . . . . . . . . . . . . . . . . 6.14.2. Advertencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
xi
175 175 176 179 179 179 180 180 181 184 185 185 187 189 190 190 195 202 202 205
II
Mtodos Numricos. e e
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
207
209 . 209 . 221 . 221 . 223 225 225 225 227 228 229 229 230 232 232 234 235 237 241 241
7. Preliminares. 7.1. Programas y funciones. . . . 7.2. Errores numricos. . . . . . e 7.2.1. Errores de escala. . . 7.2.2. Errores de redondeo.
8. EDO: Mtodos bsicos. e a 8.1. Movimiento de un proyectil. . . . . . . . . . . . . . . . . . . 8.1.1. Ecuaciones bsicas. . . . . . . . . . . . . . . . . . . . a 8.1.2. Derivada avanzada. . . . . . . . . . . . . . . . . . . . 8.1.3. Mtodo de Euler. . . . . . . . . . . . . . . . . . . . . e 8.1.4. Mtodos de Euler-Cromer y de Punto Medio. . . . . e 8.1.5. Errores locales, errores globales y eleccin del paso de o 8.1.6. Programa de la pelota de baseball. . . . . . . . . . . . 8.2. Pndulo simple. . . . . . . . . . . . . . . . . . . . . . . . . . e 8.2.1. Ecuaciones bsicas. . . . . . . . . . . . . . . . . . . . a 8.2.2. Frmulas para la derivada centrada. . . . . . . . . . . o 8.2.3. Mtodos del salto de la rana y de Verlet. . . . . . . e 8.2.4. Programa de pndulo simple. . . . . . . . . . . . . . e 8.3. Listado de los programas en python. . . . . . . . . . . . . . 8.3.1. balle.py . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . tiempo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
xii
INDICE 8.3.2. pendulo.py . . . 8.4. Listado de los programas 8.4.1. balle.cc . . . . 8.4.2. pendulo.cc . . . . . . . . en c++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 245 245 246
9. EDO II: Mtodos Avanzados. e 9.1. Orbitas de cometas. . . . . . . . . . . . . . . . . . 9.1.1. Ecuaciones bsicas. . . . . . . . . . . . . . a 9.1.2. Programa orbita. . . . . . . . . . . . . . 9.2. Mtodos de Runge-Kutta. . . . . . . . . . . . . . e 9.2.1. Runge-Kutta de segundo orden. . . . . . . 9.2.2. Frmulas generales de Runge-Kutta. . . . o 9.2.3. Runge-Kutta de cuarto orden. . . . . . . . 9.2.4. Pasando funciones a funciones. . . . . . . 9.3. Mtodos adaptativos . . . . . . . . . . . . . . . . e 9.3.1. Programas con paso de tiempo adaptativo. 9.3.2. Funcin adaptativa de Runge-Kutta. . . . o 9.4. Listados del programa. . . . . . . . . . . . . . . . 9.4.1. orbita.cc . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
249 . 249 . 249 . 251 . 255 . 255 . 257 . 258 . 259 . 260 . 260 . 261 . 264 . 264 271 . 271 . 271 . 272 . 273 . 275 . 275 . 276 . 278 . 278 . 280 . 281 . 282 . 282 . 283 . 284 . 285 . 287 . 287 . 288 . 292 . 293 . 293 . 295
10.Resolviendo sistemas de ecuaciones. 10.1. Sistemas de ecuaciones lineales. . . . . . . . . . . . . . . . . . . 10.1.1. Estado estacionario de EDO. . . . . . . . . . . . . . . . . 10.1.2. Eliminacin Gaussiana. . . . . . . . . . . . . . . . . . . . o 10.1.3. Pivoteando. . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.4. Determinantes. . . . . . . . . . . . . . . . . . . . . . . . 10.1.5. Eliminacin Gaussiana en Octave. . . . . . . . . . . . . . o 10.1.6. Eliminacin Gaussiana con C++ de objetos matriciales. o 10.2. Matriz inversa. . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1. Matriz inversa y eliminacin Gaussiana. . . . . . . . . . o 10.2.2. Matrices singulares y patolgicas. . . . . . . . . . . . . . o 10.2.3. Osciladores armnicos acoplados. . . . . . . . . . . . . . o 10.3. Sistemas de ecuaciones no lineales. . . . . . . . . . . . . . . . . 10.3.1. Mtodo de Newton en una variable. . . . . . . . . . . . . e 10.3.2. Mtodo de Newton multivariable. . . . . . . . . . . . . . e 10.3.3. Programa del mtodo de Newton. . . . . . . . . . . . . . e 10.3.4. Continuacin. . . . . . . . . . . . . . . . . . . . . . . . . o 10.4. Listados del programa. . . . . . . . . . . . . . . . . . . . . . . . 10.4.1. Denicin de la clase Matrix. . . . . . . . . . . . . . . . o 10.4.2. Implementacin de la clase Matrix. . . . . . . . . . . . . o 10.4.3. Funcin de eliminacin Gaussiana ge. . . . . . . . . . . . o o 10.4.4. Funcin para inversin de matrices inv. . . . . . . . . . o o 10.4.5. Programa newtn en Octave. . . . . . . . . . . . . . . . . 10.4.6. Programa newtn en c++. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
INDICE 11.Anlisis de datos. a 11.1. Ajuste de curvas. . . . . . . . . . . . . . . . . . . . 11.1.1. El calentamiento global. . . . . . . . . . . . 11.1.2. Teor general. . . . . . . . . . . . . . . . . a 11.1.3. Regresin lineal. . . . . . . . . . . . . . . . . o 11.1.4. Ajuste general lineal de m nimos cuadrados. 11.1.5. Bondades del ajuste. . . . . . . . . . . . . . 12.Integracin numrica bsica o e a 12.1. Deniciones . . . . . . . . . . . . . . 12.2. Regla trapezoidal . . . . . . . . . . . 12.3. Interpolacin con datos equidistantes. o 12.4. Reglas de cuadratura . . . . . . . . . 12.5. Integracin de Romberg . . . . . . . o 12.6. Cuadratura de Gauss. . . . . . . . . 12.7. Bibliograf . . . . . . . . . . . . . . a 12.8. Listados del programa. . . . . . . . . 12.8.1. trapecio.cc . . . . . . . . . 12.8.2. romberg.cc . . . . . . . . . .
xiii
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
299 . 299 . 299 . 300 . 301 . 304 . 305 307 307 308 309 310 312 314 316 317 317 317
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
III
Apndices. e
321
323
A. Transferencia a diskettes.
B. Las shells csh y tcsh. 325 B.1. Comandos propios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 B.2. Variables propias del shell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 C. Editores tipo emacs. D. Una breve introduccin a Octave/Matlab o D.1. Introduccin . . . . . . . . . . . . . . . . . . . . . . . o D.2. Interfase con el programa . . . . . . . . . . . . . . . . D.3. Tipos de variables . . . . . . . . . . . . . . . . . . . . D.3.1. Escalares . . . . . . . . . . . . . . . . . . . . . D.3.2. Matrices . . . . . . . . . . . . . . . . . . . . . D.3.3. Strings . . . . . . . . . . . . . . . . . . . . . . D.3.4. Estructuras . . . . . . . . . . . . . . . . . . . D.4. Operadores bsicos . . . . . . . . . . . . . . . . . . . a D.4.1. Operadores aritmticos . . . . . . . . . . . . . e D.4.2. Operadores relacionales . . . . . . . . . . . . . D.4.3. Operadores lgicos . . . . . . . . . . . . . . . o D.4.4. El operador : . . . . . . . . . . . . . . . . . D.4.5. Operadores de aparicin preferente en scripts o D.5. Comandos matriciales bsicos . . . . . . . . . . . . . a 329 337 . 337 . 337 . 338 . 338 . 338 . 340 . 340 . 341 . 341 . 342 . 342 . 342 . 343 . 343
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
xiv
INDICE D.6. Comandos . . . . . . . . . . . . . . . . . . D.6.1. Comandos generales . . . . . . . . D.6.2. Como lenguaje de programacin . . o D.6.3. Matrices y variables elementales . . D.6.4. Polinomios . . . . . . . . . . . . . . D.6.5. Algebra lineal (matrices cuadradas) D.6.6. Anlisis de datos y transformada de a D.6.7. Grcos . . . . . . . . . . . . . . . a D.6.8. Strings . . . . . . . . . . . . . . . . D.6.9. Manejo de archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fourier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 343 344 347 349 350 350 351 355 356
E. Asignacin dinmica. o a 361 E.1. Arreglos dinmicos bidimensionales. . . . . . . . . . . . . . . . . . . . . . . . . 362 a F. make & Makele. G. Herramientas bsicas en el uso de L.A.M.P. a G.1. Objetivo. . . . . . . . . . . . . . . . . . . . . . . . . G.2. Prerequisitos . . . . . . . . . . . . . . . . . . . . . G.3. Breve referencia sobre paginas web. . . . . . . . . . G.3.1. Ejemplos . . . . . . . . . . . . . . . . . . . . G.4. Administrador de Bases de datos. . . . . . . . . . . G.5. Servidor Web. . . . . . . . . . . . . . . . . . . . . . G.6. Pginas Bsicas en html. . . . . . . . . . . . . . . . a a G.6.1. Estructura de una pgina en html. . . . . . . a G.6.2. Algo de estilo. . . . . . . . . . . . . . . . . . G.6.3. Formularios. . . . . . . . . . . . . . . . . . . G.7. MySql. . . . . . . . . . . . . . . . . . . . . . . . . . G.7.1. Iniciando sesin. . . . . . . . . . . . . . . . o G.7.2. Creando una base de datos. . . . . . . . . . G.7.3. Creando tablas. . . . . . . . . . . . . . . . . G.7.4. Interactuando con la Tabla. . . . . . . . . . G.8. Programacin en PHP. . . . . . . . . . . . . . . . . o G.8.1. Lenguaje PHP. . . . . . . . . . . . . . . . . G.8.2. Variables. . . . . . . . . . . . . . . . . . . . G.8.3. Recuperando variables desde un formulario. G.8.4. Control de ujo. . . . . . . . . . . . . . . . . G.8.5. Funcin require. . . . . . . . . . . . . . . . . o G.8.6. Sesin. . . . . . . . . . . . . . . . . . . . . . o G.8.7. PHP interactuando con MySql. . . . . . . . G.9. Ejemplo Final. . . . . . . . . . . . . . . . . . . . . G.9.1. Paso I: Estructura de las tablas. . . . . . . . G.9.2. Paso II: rbol de pginas. . . . . . . . . . . a a G.10.Conclusiones. . . . . . . . . . . . . . . . . . . . . . G.10.1.Mejoras al Ejemplo nal. . . . . . . . . . . . 363 367 . 367 . 367 . 367 . 368 . 369 . 369 . 369 . 370 . 370 . 373 . 376 . 376 . 376 . 377 . 377 . 380 . 380 . 381 . 381 . 382 . 383 . 383 . 385 . 387 . 387 . 388 . 392 . 392
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
INDICE
xv
xvi
INDICE
Indice de guras
6.1. Un sujeto caminando. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 7.1. Salida grca del programa interp. . . . . . . . . . . . . . . . . . . . . . . . . 216 a 7.2. Salida grca del programa interp. . . . . . . . . . . . . . . . . . . . . . . . . 219 a 7.3. Error absoluto (h), ecuacin (7.9), versus h para f (x) = x2 y x = 1. . . . . . 224 o 8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. 9.1. 9.2. 9.3. 9.4. 9.5. 9.6. 9.7. 9.8. Trayectoria para un paso de tiempo con Euler. . . . Movimiento de proyectil sin aire. . . . . . . . . . . Movimiento de proyectil con aire. . . . . . . . . . . Mtodo de Euler para m = 10 . . . . . . . . . . . . e Mtodo de Euler con paso del tiempo ms pequeo. e a n Mtodo de Verlet para m = 10 . . . . . . . . . . . e Mtodo de Verlet para m = 170 . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 231 232 239 240 240 241 250 253 254 254 255 260 263 263
Orbita el ptica alrededor del Sol. . . . . . . . . . . . . . . . . . . . . . . . . . . Trayectoria y energ usando el mtodo de Euler. . . . . . . . . . . . . . . . . a e Trayectoria y energ usando el mtodo de Euler-Cromer. . . . . . . . . . . . . a e Trayectoria y energ usando el mtodo de Euler-Cromer. . . . . . . . . . . . . a e Trayectoria y energ con el paso de tiempo ms pequeo en Euler-Cromer. . . a a n Trayectoria y energ usando el mtodo de Runge-Kutta. . . . . . . . . . . . . a e Trayectoria y energ usando el mtodo de Runge-Kutta adaptativo. . . . . . . a e Paso de tiempo en funcin de la distancia radial del Runge-Kutta adaptativo. o
10.1. Sistema de bloques acoplados por resortes anclados entre paredes. . . . . . . . 281 10.2. Representacin grca del mtodo de Newton. . . . . . . . . . . . . . . . . . . 283 o a e 11.1. Dixido de carbono medido en Hawai. . . . . . . . . . . . . . . . . . . . . . . . 300 o 11.2. Ajuste de datos a una curva. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 12.1. Subintervalos. . . . . . . . . . . . . . . . . . . . . 12.2. Sucesin de l o neas rectas como curva aproximante. 12.3. Aproximaciones, (a) lineal, (b) cuadrtica. . . . . a 12.4. Regla trapezoidal versus cuadratura de Gauss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 308 310 314
D.1. Grco simple. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 a D.2. Curvas de contorno. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 D.3. Curvas de contorno. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
xvii
xviii
INDICE DE FIGURAS G.1. Esquema de una tabla en html, utilizando los elementos de una matriz. . . . . 373 G.2. Los 256 colores posibles de desplegar en una pgina en html, con su respectivo a cdigo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 o
Parte I Computacin o
1.1.
Introduccin. o
En este cap tulo se intentar dar los elementos bsicos para poder trabajar en un ama a biente unix. Sin pretender cubrir todos los aspectos del mismo, nuestro inters se centra en e entregar las herramientas al lector para que pueda realizar los trabajos del curso bajo este sistema operativo. Como comentario adicional, conscientemente se ha evitado la traduccin o de gran parte de la terminolog tcnica teniendo en mente que documentacin disponible a e o se encuentre, por lo general, en ingls y nos interesa que el lector sea capaz de reconocer los e trminos. e El sistema operativo unix es el ms usado en investigacin cient a o ca, tiene una larga historia y muchas de sus ideas y mtodos se encuentran presentes en otros sistemas operativos. e Algunas de las caracter sticas relevantes del unix moderno son: Multitarea (Multitasking): Cada programa tiene asignado su propio espacio de memoria. Es imposible que un programa afecte a otro sin usar los servicios del sistema operativo. Si dos programas escriben en la misma direccin de memoria cada uno mano tiene su propia idea de su contenido. Multiusuario: Ms de una persona puede usar la mquina al mismo tiempo. Programas a a de otros usuarios continan ejecutndose a pesar de que un nuevo usuario entre a la u a mquina. a Memoria grande, lineal y virtual: Un programa en una mquina de 32 Bits puede acceder a y usar direcciones hasta los 4 GB en una mquina de slo 4 MB de RAM. El sistema a o slo asigna memoria autntica cuando le hace falta, en caso de falta de memoria de o e RAM, se utiliza el disco duro (swap). Casi todo tipo de dispositivo puede ser accedido como un archivo. Existen muchas aplicaciones diseadas para trabajar desde la l n nea de comandos. Adems, a la mayor de las aplicaciones permiten que la salida de una pueda ser la entrada de la a otra. Permite compartir dispositivos (como disco duro) entre una red de mquinas. a 3
Por su naturaleza de multiusuario, nunca se deber apagar impulsivamente una mquina a a 1 unix , ya que una mquina apagada sin razn puede matar trabajos de d perder los a o as, ultimos cambios de tus archivos e ir degradando el sistema de archivos en dispositivos como el disco duro. Entre los sistemas operativos unix actuales cabe destacar: Linux fue originalmente desarrollado primero para computadores personales PCs basados en x86 de 32 bits (386 o superiores). Hoy Linux corre sobre Intel x86/IA64, Motorola 68k, Sun SPARC, Alpha, Motorola/IBM PowerPC, Arm, MISP CPUs, HP PA-RISC, IA-64, ibm S/390, AMD64, ppc64, Hitachi SuperH, armeb y arquitecturas Renesas M32R. SunOS2 : disponible para la familia 68K as como para la familia sparc de estaciones de trabajo sun Solaris3 : disponible para la familia sparc de Sun as como para la familia x86. OSF14 : disponible para Alpha. Ultrix: disponible para vax de Digital SYSVR45 : disponible para la familia x86, vax. IRIX: disponible para mips. AIX6 : disponible para RS6000 de IBM y PowerPC.
1.2.
Ingresando al sistema.
En esta seccin comentaremos las operaciones de comienzo y n de una sesin en unix o o as como la modicacin de la contrasea (que a menudo no es la deseada por el usuario, y o n que por lo tanto puede olvidar con facilidad).
1.2.1.
Terminales.
Para iniciar una sesin es necesario poder acceder a un terminal. Pueden destacarse dos o tipos de terminales: Terminal de texto: consta de una pantalla y de un teclado. Como indica su nombre, en la pantalla slo es posible imprimir caracteres de texto. o Terminal grco: Consta de pantalla grca, teclado y mouse. Dicha pantalla suele ser a a de alta resolucin. En este modo se pueden emplear ventanas que emulan el comportao miento de un terminal de texto (xterm o gnome-terminal).
1
Incluyendo el caso en que la mquina es un PC normal corriendo Linux u otra versin de unix. a o SunOS 4.1.x tambin se conoce como Solaris 1. e 3 Tambin conocido como SunOS 5.x, solaris 2 o Slowaris :-). e 4 Tambin conocido como Dec Unix. e 5 Tambin conocido como Unixware y Novell-Unix. e 6 Tambin conocido como Aches. e
2
1.2.2.
Login.
El primer paso es encontrar un terminal libre donde aparezca el login prompt del sistema: Debian GNU/Linux 4.0 hostname tty2 hostname login: Tambin pueden ocurrir un par de cosas: e La pantalla no muestra nada. Comprobar que la pantalla est encendida. e Pulsar alguna tecla o mover el mouse para desactivar el protector de pantalla. Otra persona ha dejado una sesin abierta. En este caso existe la posibilidad de intentar o en otra mquina o bien nalizar la sesin de dicha persona (si sta no se halla en las a o e proximidades). Una vez que se haya superado el paso anterior de encontrar el login prompt se procede con la introduccin del Username al prompt de login y despus la contrasea (password) o e n adecuada.
1.2.3.
Passwords.
El password puede ser cualquier secuencia de caracteres a eleccin. Deben seguirse las o siguientes pautas: Debe ser fcil de recordar por uno mismo. Si se olvida, deber pasarse un mal rato a a dicindole al administrador de sistema que uno lo ha olvidado. e Para evitar que alguna persona no deseada obtenga el password y tenga libre acceso a los archivos de tu cuenta: Las maysculas y minsculas no son equivalentes, sin embargo se recomienda que u u se cambie de una a otra. Los caracteres numricos y no alfabticos tambin ayudan. Debe tenerse sin eme e e bargo la precaucin de usar caracteres alfanumricos que se puedan encontrar en o e todos los terminales desde los que se pretenda acceder. Las palabras de diccionario deben ser evitadas. Debe cambiarlo si cree que su password es conocido por otras personas, o descubre que algn intruso7 est usando su cuenta. u a El password debe ser cambiado con regularidad.
7
La instruccin para cambiar el password en unix es passwd. A menudo, cuando existen o varias mquinas que comparten recursos (disco duro, impresora, correo electrnico, . . . ), para a o facilitar la administracin de dicho sistema se unican los recursos de red (entre los que se o hayan los usuarios de dicho sistema) en una base de datos comn. Dicho sistema se conoce u 8 como NIS (Network Information Service) . Si el sistema empleado dispone de este servicio, la modicacin de la contrasea en una mquina supone la modicacin en todas las mquinas o n a o a que constituyan el dominio NIS.
1.2.4.
Cerrando la sesin. o
Es importante que nunca se deje abierta una sesin, pues algn intruso podr tener o u a libre acceso a archivos de propiedad del usuario y manipularlos de forma indeseable. Para evitar todo esto basta teclear logout o exit y habrs acabado la sesin de unix en dicha a o mquina9 . a
1.3.
El Proyecto Debian.
El proyecto Debian es una asociacin de personas que han creado un sistema operativo o gratis y de cdigo abierto (free). Este sistema operativo se denomina Debian GNU/Linux o o simplemente Debian. Actualmente Debian ocupa el kernel Linux desarrollado por Linus Torvalds apoyado por miles de programadores de todo el mundo. Tambin estn implementados otros kernels como e a Hurd, desarrollado por GNU, NetBSD y FreeBSD. La mayor de las herramientas del sistema operativo Debian provienen del proyecto a GNU y por ende son free. Cabe destacar que actualmente Debian tiene un total de ms de a 18733 paquetes (por paquetes entendemos software precompilado, para la versin estable, o en un formato que permite su fcil instalacin en nuestra mquina). Entre estos paquetes a o a encontramos desde las herramientas bsicas para procesar texto, hojas de clculo, edicin de a a o imgenes, audio, video, hasta aplicaciones de gran utilidad cient a ca. Es importante recordar que todo este software es free y por lo tanto est al alcance de todos sin la necesidad de a comprar licencias ni pagar por actualizaciones. Tambin existe la posibilidad de modicar el e software ya que tenemos acceso al cdigo fuente de los programas. Debian siempre mantiene o activas al menos tres versiones que tienen las siguientes clasicaciones: stable (estable): Es la ultima versin ocial de Debian que ha sido probada para asegurar o su estabilidad. Actualmente corresponde a la versin 4.0r0 cuyo nombre cdigo es etch. o o testing (en prueba): Esta es la versin que se est probando para asegurar su estabilidad o a y para luego pasar a ser versin estable. Nombre cdigo lenny. o o unstable (inestable): Aqu es donde los programadores verdaderamente desarrollan De bian y por esto no es muy estable y no se recomienda para el uso diario. Esta versin o se denomina siempre sid. Para informacin sobre Debian y cmo bajarlo visite la pgina ocial http://www.debian.org. o o a
Antiguamente se conoc como YP (Yellow Pages), pero debido a un problema de marca registrada de a United Kingdom of British Telecomunications se adoptaron las siglas nis. 9 En caso que se estuviera trabajando bajo X-Windows debes cerrar la sesin con Log Out Usuario de o Gnome.
8
1.4.
Archivos y directorios.
Aunque las diferentes distribuciones ubiquen sus programas en diferentes partes, la estructura bsica de directorios en una mquina Linux es ms o menos la misma: a a a /-|--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> bin boot cdrom dev emul etc home initrd lib lib32 lib64 media mnt opt proc root sbin selinux sys tmp usr--|--> |--> |--> |--> |--> |--> |-->
|--> |--> |--> |--> |--> var--|... |--> |--> |--> |--> |...
bin games include lib lib32 lib64 local -|--> bin |--> include |--> lib |... sbin share src --> linux X11R6 lock log mail www
El rbol que observamos muestra el t a pico rbol de directorios en Linux. Pueden haber a pequeas variaciones en algunos de los nombres de estos directorios dependiendo de la distrin bucin o versin de Linux que se est usando. Entre los directorios ms destacados tenemos: o o e a /home - Espacio reservado para las cuentas de los usuarios. /bin, /usr/bin - Binarios (ejecutables) bsicos de unix. a /etc, aqu se encuentran los archivos de conguracin de todo los diferentes softwares o de la mquina. a /proc, es un sistema de archivos virtuales. Contiene archivos que residen en memoria y no en el disco duro. Hace referencia a los programas que estn corriendo en este a momento en el sistema. /dev (device) (dispositivo). Aqu se guardan los archivos asociados a los dispositivos. Se usan para acceder los dispositivos f sicos del sistema y recursos tales como discos duros, modems, memoria, mouse, etc. Algunos dispositivos: hd: hda1 ser el disco duro IDE, primario (a), y la primera particin (1). a o fd: los archivos que empiecen con las letras fd se referirn a los controladores de a las disketteras: fd0 ser la primera diskettera, fd1 ser la segunda y as sucesia a vamente. ttyS: se usan para acceder a los puertos seriales como por ejemplo ttyS0, que es el puerto conocido como com1. sd: son los dispositivos SCSI y/o SATA. Su uso es muy similar al del hd. Tambin e se usa para denominar a los dispositivos de almacenamiento conectados v USB a (pendrives). lp: son los puertos paralelos. lp0 es el puerto conocido como LPT1. null: ste es usado como un agujero negro, ya que todo lo que se dirige all desae parece. tty: hacen referencia a cada una de las consolas virtuales. Como es de suponer, tty1 ser la primera consola virtual, tty2 la segunda, etc. a /usr/local - Zona con las aplicaciones no comunes a todos los sistemas unix, pero no por ello menos utilizadas. /usr/share/doc aqu se puede encontrar informacin relacionada con aplicaciones (en o forma de pginas de manual, texto, html o bien archivos dvi, Postscript o pdf). Tambin a e encontramos archivos de ejemplo, tutoriales, HOWTO, etc.
1.5.
Ordenes bsicas. a
Para ejecutar un comando, basta con teclear su nombre (tambin debes tener permiso para e hacerlo). Las opciones o modicadores empiezan normalmente con el caracter - (p. ej. ls -l). Para especicar ms de una opcin, se pueden agrupar en una sola cadena de caracteres a o (ls -l -h es equivalente a ls -lh). Algunos comandos aceptan tambin opciones dadas por e palabras completas, en cuyo caso usualmente comienzan con -- (ls --color=auto).
1.5.1.
En un sistema computacional la informacin se encuentra en archivos que la contienen o (tabla de datos, texto ASCII, fuente en lenguaje Python, Fortran o C++, ejecutable, imagen, mp3, gura, resultados de simulacin, . . . ). Para organizar toda la informacin se dispone de o o una entidad denominada directorio, que permite el almacenamiento en su interior tanto de archivos como de otros directorios10 . Se dice que la estructura de directorios en unix es jerrquica o arborescente, debido a a que todos los directorios nacen en un mismo punto (denominado directorio ra De hecho, z). la zona donde uno trabaja es un nodo de esa estructura de directorios, pudiendo uno a su vez generar una estructura por debajo de ese punto. Un archivo se encuentra situado siempre en un directorio y su acceso se realiza empleando el camino que conduce a l en el Arbol de e Directorios del Sistema. Este camino es conocido como el path. El acceso a un archivo se puede realizar empleando:
Path Absoluto, aqul que empieza con / e Por ejemplo : /etc/printcap Path Relativo, aqul que no empieza con / e Por ejemplo : ../examples/rc.dir.01 Los nombres de archivos y directorios pueden usar un mximo de 255 caracteres, cuala quier combinacin de letras y s o mbolos (el caracter / no se permite).
Los caracteres comod (wildcard ) pueden ser empleados para acceder a un conjunto n de archivos con caracter sticas comunes. El signo * puede sustituir cualquier conjunto de caracteres11 y el signo ? a cualquier caracter individual. Por ejemplo:12
Normalmente se acude a la imagen de una carpeta que puede contener informes, documentos o bien otras carpetas, y as sucesivamente. 11 Incluido el punto ., unix no es dos. 12 bash$ es el prompt en todos los ejemplos.
10
10
bash$ ls f2c.1 flexdoc.1 rcmd.1 rptp.1 zforce.1 face.update.1 ftptool.1 rlab.1 rxvt.1 zip.1 faces.1 funzip.1 robot.1 zcat.1 zipinfo.1 flea.1 fvwm.1 rplay.1 zcmp.1 zmore.1 flex.1 rasttoppm.1 rplayd.1 zdiff.1 znew.1 bash$ ls rp* rplay.1 rplayd.1 rptp.1 bash$ ls *e?? face.update.1 zforce.1 zmore.1 Los archivos cuyo nombre comiencen por . se denominan ocultos, as por ejemplo en el directorio de partida de un usuario. bash$ ls -a user . .alias .fvwmrc .login .xinitrc .. .cshrc .joverc .profile .Xdefaults .enviroment .kshrc .tcshrc Algunos caracteres especiales para el acceso a archivos son: . Directorio actual .. Directorio superior en el rbol a ~ Directorio $HOME ~user Directorio $HOME del usuario user
1.5.2.
ls (LiSt) Este comando permite listar los archivos de un determinado directorio. Si no se le suministra argumento, lista los archivos y directorios en el directorio actual. Si se aade el nombre de n un directorio el listado es del directorio suministrado. Existen varias opciones que modican su funcionamiento entre las que destacan: -l (Long listing) proporciona un listado extenso, que consta de los permisos13 de cada archivo, el usuario, el tamao del archivo, . . . , etc. Adicionalmente la opcin -h imprime n o los tamaos en un formato fcil de leer (Human readable). n a -a (list All) lista tambin los archivos ocultos. e -R (Recursive) lista recursivamente el contenido de todos los directorios que encuentre. -t ordena los archivos por tiempo de modicacin. o -S ordena los archivos por tamao. n -r invierte el sentido de un ordenamiento. -p agrega un caracter al nal de cada nombre de archivo, indicando el tipo de archivo (por ejemplo, los directorios son identicados con un / al nal).
13
11
pwd (Print Working Directory) Este comando proporciona el nombre del directorio actual. cd (Change Directory) Permite moverse a travs de la estructura de directorios. Si no se le proporciona argumento se e provoca un salto al directorio $HOME. El argumento puede ser un nombre absoluto o relativo de un directorio. cd - vuelve al ultimo directorio visitado. mkdir (MaKe DIRectory) Crea un directorio con el nombre (absoluto o relativo) proporcionado. rmdir (ReMove DIRectory) Elimina un directorio con el nombre (absoluto o relativo) suministrado. Dicho directorio debe de estar vac o.
1.5.3.
Visitando archivos.
Este conjunto de rdenes permite visualizar el contenido de un archivo sin modicar su o contenido. cat Muestra por pantalla el contenido de un archivo que se suministra como argumento. more Este comando es anlogo al anterior, pero permite la paginacin. a o less Es una versin mejorada del anterior. Permite moverse en ambas direcciones. Otra ventaja o es que no lee el archivo entero antes de arrancar.
1.5.4.
cp (CoPy) Copia un archivo(s) con otro nombre y/o a otro directorio, por ejemplo, el comando para copiar el archivo1.txt con el nombre archivo2.txt es: cp archivo1.txt archivo2.txt Veamos algunas opciones: -a copia en forma recursiva, no sigue los link simblicos y preserva los atributos de lo o copiado. -i (interactive), impide que la copia provoque una prdida del archivo destino si ste e e existe14 . -R (recursive), copia un directorio y toda la estructura que cuelga de l. e mv (MoVe) Mueve un archivo(s) a otro nombre y/o a otro directorio, por ejemplo, el comando para mover el archivo1.txt al nombre archivo2.txt es:
14
Muchos sistemas tienen esta opcin habilitada a travs de un alias, para evitar equivocaciones. o e
12
Este comando dispone de opciones anlogas al anterior. a rm (ReMove) Borra un archivo(s). En caso de que el argumento sea un directorio y se haya suministrado la opcin -r, es posible borrar el directorio y todo su contenido. La opcin -i pregunta antes o o de borrar.
1.5.5.
Espacio de disco.
El recurso de almacenamiento en el disco es siempre limitado. A continuacin se comentan o un par de comandos relacionados con la ocupacin de este recurso: o du (Disk Usage) Permite ver el espacio de disco ocupado (en bloques de disco15 ) por el archivo o directorio suministrado como argumento. La opcin -s impide que cuando se aplique recursividad en o un directorio se muestren los subtotales. La opcin -h imprime los tamaos en un formato o n fcil de leer (Human readable). a df (Disk Free) Muestra los sistemas de archivos que estn montados en el sistema, con las cantidades totales, a usadas y disponibles para cada uno. df -h muestra los tamaos en formato fcil de leer. n a
1.5.6.
Links.
ln (LiNk) Permite realizar un enlace (link) entre dos archivos o directorios. Un enlace puede ser: hard link : se puede realizar slo entre archivos del mismo sistema de archivos. El archivo o enlazado apunta a la zona de disco donde se ubica el archivo original. Por tanto, si se elimina el archivo original, el enlace sigue teniendo acceso a dicha informacin. Es el o enlace por omisin. o symbolic link : permite enlazar archivos/directorios16 de diferentes sistemas de archivos. El archivo enlazado apunta al nombre del original. As si se elimina el archivo original el enlace apunta hacia un nombre sin informacin asociada. Para realizar este tipo de o enlace debe emplearse la opcin -s. o Un enlace permite el uso de un archivo en otro directorio distinto del original sin necesidad de copiarlo, con el consiguiente ahorro de espacio. Veamos un ejemplo. Creemos un enlace clsico en Linux, al directorio existente linux-2.6.12.5 nombrmoslo sencillamente linux. a e mitarro:/usr/src# ln -s linux-2.6.12.5 linux
15 16
1 bloque normalmente es 1 Kbyte. Debe hacerse notar que los directorios slo pueden ser enlazados simblicamente. o o
13
1.5.7.
Proteccin de archivos. o
Dado que el sistema de archivos unix es compartido por un conjunto de usuarios, surge el problema de la necesidad de privacidad. Sin embargo, dado que existen conjuntos de personas que trabajan en comn, es necesaria la posibilidad de que un conjunto de usuarios puedan u tener acceso a una serie de archivos (que puede estar limitado para el resto de los usuarios). Cada archivo y directorio del sistema dispone de un propietario, un grupo al que pertenece y unos permisos. Existen tres tipos fundamentales de permisos: lectura (r-Read ): en el caso de un archivo, signica poder examinar el contenido del mismo; en el caso de un directorio signica poder entrar en dicho directorio. escritura (w-Write): en el caso de un archivo signica poder modicar su contenido; en el caso de un directorio es crear un archivo o directorio en su interior. ejecucin (x-eXecute): en el caso de un archivo signica que ese archivo se pueda o ejecutar (binario o archivo de procedimientos); en el caso de un directorio es poder ejecutar alguna orden dentro de l. e Se distinguen tres grupos de personas sobre las que se deben especicar permisos: user: el usuario propietario del archivo. group: el grupo propietario del archivo (excepto el usuario). Como ya se ha comentado, cada usuario puede pertenecer a uno o varios grupos y el archivo generado pertenece a uno de los mismos. other: el resto de los usuarios (excepto el usuario y los usuarios que pertenezcan al grupo) Tambin se puede emplear all que es la unin de todos los anteriores. Para visualizar las e o protecciones de un archivo o directorio se emplea la orden ls -l, cuya salida es de la forma: -rw-r--r-- ...otra informacin... nombre o Los 10 primeros caracteres muestran las protecciones de dicho archivo: El primer caracter indica el tipo de archivo de que se trata: archivo d directorio l enlace (link ) c dispositivo de caracteres (p.e. puerta serial) b dispositivo de bloques (p.e. disco duro) s socket (conexin de red) o Los caracteres 2, 3, 4 son los permisos de usuario Los caracteres 5, 6, 7 son los permisos del grupo
14
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. Los caracteres 8, 9, 10 son los permisos del resto de usuarios As en el ejemplo anterior -rw-r--r-- se trata de un archivo donde el usuario puede leer y escribir, mientras que el grupo y el resto de usuarios slo pueden leer. Estos suelen o ser los permisos por omisin para un archivo creado por un usuario. Para un directorio o los permisos por omisin suelen ser: drwxr-xr-x, donde se permite al usuario entrar o en el directorio y ejecutar rdenes desde l. o e chmod (CHange MODe) Esta orden permite modicar los permisos de un archivo. Con opcin -R es recursiva. o chmod permisos les Existen dos modos de especicar los permisos: Modo absoluto o modo numrico. Se realiza empleando un nmero que resulta de la OR e u binario de los siguientes modos: 400 200 100 040 020 010 004 002 001 4000 lectura por el propietario. escritura por el propietario. ejecucin (bsqueda) por el propietario. o u lectura por el grupo. escritura por el grupo. ejecucin (bsqueda) por el grupo. o u lectura por el resto. escritura por el resto. ejecucin (bsqueda) por el resto. o u Set User ID, cuando se ejecuta el proceso corre con los permisos del dueo del archivo. n
Por ejemplo: chmod 640 *.txt Permite la lectura y escritura por el usuario, lectura para el grupo y ningn permiso u para el resto, de un conjunto de archivos que acaban en .txt Modo simblico o literal. Se realiza empleando una cadena (o cadenas separadas por o comas) para especicar los permisos. Esta cadena se compone de los siguientes tres elementos: who operation permission
who : es una combinacin de: o u g o a : : : : user group others all (equivalente a ugo)
Si se omite este campo se supone a, con la restriccin de no ir en contra de la o mscara de creacin (umask). a o operation: es una de las siguientes operaciones: + : aadir permiso. n
1.5. ORDENES BASICAS. - : eliminar permiso. = : asignar permiso, el resto de permisos de la misma categor se anulan. a permission: es una combinacin de los caracteres: o r : read. w : write. x : execute. s : en ejecucin ja el usuario o el grupo. o Por ejemplo: chmod u+x tarea Permite la ejecucin por parte del usuario17 del archivo tarea. o
15
chmod u=rx, go=r *.txt Permite la lectura y ejecucin del usuario, y slo la lectura por parte del grupo y el o o resto de usuarios. umask Esta es una orden intr nseca del Shell que permite asignar los permisos que se desea tengan los archivos y directorios por omisin. El argumento que acompaa a la orden es un nmero o n u octal que aplicar una xor sobre los permisos por omisin (rw-rw-rw-) para archivos y a o (rwxrwxrwx) para directorios. El valor por omisin de la mscara es 022 que habilita al o a usuario para lectura-escritura, al grupo y al resto para lectura. Sin argumentos muestra el valor de la mscara. a chgrp (CHange GRouP) Cambia el grupo propietario de una serie de archivos/directorios chgrp grupo les El usuario que efecta esta orden debe pertenecer al grupo mencionado. u chown (CHange OWNer) Cambia el propietario y el grupo de una serie de archivos/directorios chown user:group les La opcin -r hace que la orden se efecte recursivamente. o u id Muestra la identicacin del usuario18 , as como el conjunto de grupos a los que el usuario o pertenece. user@hostname:~$ id uid=1000(user) gid=1000(group) groups=1000(group),25(floppy),29(audio) user@hostname:~$
Un error muy frecuente es la creacin de un archivo de rdenes (script le) y olvidar permitir la ejecucin o o o del mismo. 18 A pesar de que el usuario se identica por una cadena denominada username, tambin existe un nmero e u denominado uid que es un identicativo numrico de dicho usuario. e
17
16
1.5.8.
Filtros.
Existe un conjunto de rdenes en unix que permiten el procesamiento de archivos de texto. o Se denominan ltros (Unix Filters), porque normalmente se trabaja empleando redireccin o 19 20 recibiendo datos por su stdin y retornndolos modicados por su stdout . a Para facilitar la comprensin de los ejemplos siguientes supondremos que existen tres o archivos llamados mylist.txt, yourlist.txt y tercero.txt que tienen en su interior: mylist.txt 1 190 2 280 3 370 yourlist.txt 1 190 2 281 3 370 tercero.txt 11 b 33 c 222 a
echo Este no es propiamente un ltro, pero nos ser muy util ms adelante. Despliega sobre la a a pantalla un mensaje, sin argumento despliega una l nea en blanco. La opcin -n elimina el o cambio de l nea al nal del mensaje. user@hostname:~$ echo Hola Mundo Hola Mundo user@hostname:~$ echo ; echo chao; echo chao user@hostname:~$ Varias instrucciones pueden ser separadas por ; cat Es el ltro ms bsico, copia la entrada a la salida. a a user@hostname:~$ cat 1 190 2 280 3 370 user@hostname:~$ mylist.txt
Tambin lo podemos usar para crear un archivo e user@hostname:~$ cat Este es mi archivo con muchas lineas ^d user@hostname:~$
19 20
> myfile.txt
1.5. ORDENES BASICAS. El caracter nal ^d corresponde a n de archivo y termina el ingreso. seq Genera una secuencia de nmeros naturales consecutivos. u user@hostname:~$ seq 4 8 4 5 6 7 8
17
cut Para un archivo compuesto por columnas de datos, permite escribir sobre la salida cierto intervalo de columnas. La opcin -b N-M permite indicar el intervalo en bytes que se escribirn o a en la salida. user@hostname:~$ cut -b 3-4 mylist.txt 19 28 37 user@hostname:~$ paste Mezcla l neas de distintos archivos. Escribe l neas en el stdout pegando secuencialmente las l neas correspondientes de cada uno de los archivo separadas por tab. Ejemplo, supongamos que tenemos nuestros archivos mylist.txt y yourlist.txt y damos el comando user@hostname:~$ paste mylist.txt yourlist.txt 1 190 1 190 2 280 2 281 3 370 3 370 user@hostname:~$ sed Es un editor de ujo. Veamos algunos ejemplos user@hostname:~$ sed = mylist.txt 1 1 190 2 2 280 3 3 370 user@hostname:~$ Numera las l neas. user@hostname:~$ sed -n -e 3p mylist.txt 3 370 user@hostname:~$
18
Slo muestra la l o nea 3. El modicador -n suprime la impresin de todas las l o neas excepto aquellas especicadas por p. El modicador -e corre un script, secuencia de comandos. Separando por coma damos un rango en el nmero de l u neas. user@hostname:~$ sed -e 2q mylist.txt 1 190 2 280 user@hostname:~$ Muestra hasta la l nea 2 y luego se sale de sed. user@hostname:~$ sed -e s/0/a/g mylist.txt 1 19a 2 28a 3 37a user@hostname:~$ Reemplaza todos los 0 del archivo por la letra a. Este es uno de los usos ms comunes. a user@hostname:~$ sed -e /2 2/s/0/a/g mylist.txt 1 190 2 28a 3 370 user@hostname:~$ Busca las l neas con la secuencia 2 2 y en ellas reemplaza todos los 0 por la letra a. user@hostname:~$ sed -e s/1/XX/2 mylist.txt 1 XX90 2 280 3 370 user@hostname:~$ Reemplaza la segunda aparicin de un 1 en una l o nea por los caracteres XX. A continuacin mostramos otras posibilidades del comando sed o Para remover una l nea especica (X) de un archivo (file.txt) user@hostname:~$ sed -e Xd file.txt Para remover un intervalo de l neas de un archivo user@hostname:~$ sed -e X,Yd file.txt Para mostrar slo las l o neas X e Y de un archivo
1.5. ORDENES BASICAS. user@hostname:~$ sed -n -e Xp;Yp file.txt Para mostrar un archivo salvo las l neas que contengan key user@hostname:~$ sed -e /key/d file.txt Para mostrar de un archivo slo las l o neas que contengan key user@hostname:~$ sed -n -e /key/p file.txt Para mostrar un archivo salvo las l neas que comienzan con # user@hostname:~$ sed -e /^#/d file.txt Expresiones regulares: ^ Matches al comienzo de la l nea $ Matches al nal de la l nea, se pone despus del caracter a buscar. e . Matches cualquier caracter. [] Matches con todos los caracteres dentro de los parntesis e diff Permite comparar el contenido de dos archivos o directorios user@hostname:~$ diff mylist.txt yourlist.txt 2c2 < 2 280 --> 2 281 user@hostname:~$ Hay una diferencia entre los archivos en la segunda la. sort Permite ordenar alfabticamente e user@hostname:~$ sort tercero.txt 11 b 222 a 33 c user@hostname:~$ user@hostname:~$ sort -r tercero.txt 33 c 222 a 11 b user@hostname:~$
19
20
user@hostname:~$ sort -n tercero.txt 11 b 33 c 222 a user@hostname:~$ user@hostname:~$ sort -k 2 tercero.txt 222 a 11 b 33 c user@hostname:~$ La opcin -n considera los valores numricos y la opcin -r invierte el orden. La opcin -k o e o o permite especicar la columna a usar para hacer el sort. find Permite la bsqueda de un archivo en la estructura de directorios u find . -name file.dat -print Comenzando en el directorio actual(.) recorre la estructura de directorios buscando el archivo file.dat, cuando lo encuentre imprime el path al mismo, actualmente es innecesaria la opcin print. o find . -name *~ -exec rm {} \; Esta es otra aplicacin de find que busca en la estructura de directorios un archivo que o termine en ~ y lo borra. El comando xargs ordena repetir orden para cada argumento que se lea desde stdin. Este lo podemos combinar con find. find . -name *.dat -print | xargs mv ../data \; Logrando un comando que busca en la estructura de directorios todos los archivos que termines en .dat, y los mueve a un directorio ../data. grep Permite la bsqueda de una cadena de caracteres en uno o varios archivos, imprimiendo el u nombre del archivo y la l nea en que se encuentra la cadena. user@hostname:~$ grep 1 *list.txt mylist.txt:1 190 yourlist.txt:1 190 yourlist.txt:2 281 user@hostname:~$ Algunas opciones utiles -c Elimina la salida normal y slo cuenta el nmero de apariciones de la cadena en o u cada archivo. -i Ignora para la comparacin entre la cadena dada y el archivo, si la cadena est en o a maysculas o minsculas. u u -n Incluye el nmero de l u neas en que aparece la cadena en la salida normal.
21
-v Invierte la bsqueda mostrando todas las l u neas donde no aparece la cadena pedida. head Muestra las primeras diez l neas de un archivo. head -30 file Muestra las 30 primeras l neas de le. user@hostname:~$ head -1 1 190 user@hostname:~$ mylist.txt
tail Muestra las diez ultimas l neas de un archivo. tail -30 file Muestra las 30 ultimas l neas de le. tail +30 file Muestra desde la l nea 30 en adelante de le. user@hostname:~$ tail -1 3 370 user@hostname:~$ mylist.txt
La opcin -f permite que se actualice la salida cuando el archivo crece. o awk Es un procesador de archivos de texto que permite la manipulacin de las l o neas de forma tal que tome decisiones en funcin del contenido de la misma. Ejemplo, supongamos que tenemos o nuestro archivo mylist.txt con sus dos columnas user@hostname:~$ awk {print } 1 190 2 280 3 370 user@hostname:~$ Funciona como el comando cat user@hostname:~$ awk {print $2, $1 } 190 1 280 2 370 3 user@hostname:~$ Imprime esas dos columnas en orden inverso. user@hostname:~$ awk {print a, 8*$1, $2-1 } a 8 189 a 16 279 a 24 369 user@hostname:~$ mylist.txt mylist.txt mylist.txt
22
Permite operar sobre las columnas. user@hostname:~$ awk { if (NR>1 && NR < 3) print} mylist.txt 2 280 user@hostname:~$ Slo imprime la l o nea 2. tar Este comando permite la creacin/extraccin de archivos contenidos en un unico archivo o o denominado tarfile (o tarball). Este tarfile suele ser luego comprimido con gzip, la versin de compresin gnu,21 o bien con bzip2. o o La accin a realizar viene controlada por el primer argumento: o c (Create) creacin o x (eXtract) extraccin o t (lisT) mostrar contenido r aadir al nal n u (Update) aadir aquellos archivos que no se hallen en el tarle o que hayan sido n modicados con posterioridad a la versin que aparece. o A continuacin se colocan algunas de las opciones: o v Verbose (indica qu archivos son agregados a medida que son procesados) e z Comprimir o descomprimir el contenido con gzip. j Comprimir o descomprimir el contenido con bzip2. f File: permite especicar el archivo para el tarle. Veamos algunos ejemplos: tar cvf simul.tar *.dat Genera un archivo simul.tar que contiene todos los archivos que terminen en .dat del directorio actual. A medida que se va realizando indica el tamao en bloques de cada archivo n aadido modo verbose. n tar czvf simul.tgz *.dat Igual que en el caso anterior, pero el archivo generado simul.tgz ha sido comprimido empleando gzip. tar tvf simul.tar Muestra los archivos contenidos en el tarle simul.tar. tar xvf simul.tar Extrae todos los archivos contenidos en el tarle simul.tar.
gnu es un acrnimo recursivo, signica: gnus Not unix! gnu es el nombre del producto de la Free o Software Foundation, una organizacin dedicada a la creacin de programas compatibles con unix algunos o o mejorado respecto a los estndars, y de libre distribucin. La distribucin de Linux gnu es debian. a o o
21
1.5. ORDENES BASICAS. wc (Word Count) Contabiliza el nmero de l u neas, palabras y caracteres de un archivo. user@hostname:~$ wc 3 6 user@hostname:~$ mylist.txt 18 mylist.txt
23
El archivo tiene 3 l neas, 6 palabras, considerando cada nmero como una palabra i.e. 1 es la u primera palabra y 190 la segunda, y nalmente 18 caracteres. Cules son los 18 caracteres? a
1.5.9.
users who w Para ver quin est conectado en la mquina. e a a ping Verica si una mquina est conectada a la red y si el camino de Internet hasta la misma a a funciona correctamente. finger finger user, muestra informacin22 sobre el usuario user en la mquina local. o a finger user@hostname, muestra informacin sobre un usuario llamado user en una mquina o a hostname. finger @hostname, muestra los usuarios conectados de la mquina hostname. a Este comando suele estar desabilitado en las mquinas actuales. a
1.5.10.
Fecha
cal Muestra el calendario del mes actual. Con la opcin -y y el ao presenta el calendario del o n ao completo. n date Muestra el d y la hora actual. a
1.5.11.
Cuando se transeren archivos de texto entre windows y unix sin las precauciones adecuadas pueden aparecer los siguientes problemas: En unix no existe obligatoriedad respecto a que los archivos llevan extensin. Incluso o pueden tener ms de una extensin algo.v01.tar.gz, esto puede complicar a otros a o sistemas que usan slo una extensin de tres caracteres. o o
La informacin proporcionada es el nombre completo del usuario, las ultimas sesiones en dicha mquina, o a si ha le o no su correo y el contenido de los archivos .project y .plan del usuario. do
22
24
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. El cambio de l nea en un archivo de texto windows se compone de Carriage Return y Line Feed. Sin embargo, en unix slo existe el Carriage Return. As un archivo de o unix visto desde windows parece una unica l nea. El caso inverso es la aparicin del o caracter ^M al nal de cada l nea. Adems, el n de archivo en windows es ^Z y en a unix es ^D.
Usando el comando tr se puede transformar un archivo con cambios de l neas para DOS en uno para unix. Sabiendo que ^M es ascii 13 decimal, pero 15 en octal: tr -d \015 < datafile > TEMPFILE mv -f TEMPFILE datafile En Debian, instalando el paquete sysutils, queda instalado el comando dos2unix que tambin lo hace. e
1.6.
Shells.
El sistema operativo unix soporta varios intrpretes de comandos o shells, que ayudan a e que la interaccin con el sistema sea lo ms cmoda y amigable posible. La eleccin de cul o a o o a es la shell ms cmoda es algo personal; en este punto slo indicaremos algunos de los ms a o o a populares: sh : Bourne SHell, el shell bsico, no pensado para uso interactivo. a csh : C-SHell, shell con sintaxis como el lenguaje C. El archivo de conguracin es o .cshrc (en el directorio $HOME). ksh : Korn-SHell, shell diseada por David Korn en los Laboratorios AT&T Bell. Es n un intento para una shell interactiva y para uso en script. Su lenguaje de comandos es un superconjunto de el lenguaje de shell sh. tcsh : alTernative C-Shell (Tenex-CSHell), con editor de l nea de comando. El archivo de conguracin es .tcshrc, o en caso de no existir, .cshrc (en el directorio $HOME). o bash : Bourne-Again Shell, con lo mejor de sh, ksh y tcsh. El archivo de conguracin o es .bash_profile cuando se entra a la cuenta por primera vez, y despus el archivo de e conguracin es .bashrc siempre en el directorio $HOME. La l o nea de comando puede ser editada usando comandos (secuencias de teclas) del editor emacs. Es el shell por defecto de Linux. Si queremos cambiar de shell en un momento dado, slo ser necesario que tecleemos el o a nombre del mismo y estaremos usando dicho shell. Si queremos usar de forma permanente otro shell del que tenemos asignado por omisin23 podemos emplear la orden chsh que permite o realizar esta accin. o En los archivos de conguracin se encuentran las deniciones de las variables de entorno o (enviroment variables) como camino de bsqueda PATH, los aliases y otras conguraciones u personales. Veamos unos caracteres con especial signicado para el Shell:
23
1.6. SHELLS.
25
24 permite que el output de un comando reemplace al nombre del comando. Por ejemplo: echo pwd imprime por pantalla el nombre del directorio actual. user@hostname:~$ echo pwd /home/user user@hostname:~$ 25 preserva el signicado literal de cada uno de los caracteres de la cadena que delimita. user@hostname:~$ echo Estoy en pwd Estoy en pwd user@hostname:~$ 26 preserva el signicado literal de todos los caracteres de la cadena que delimita, salvo $, , \. user@hostname:~$ echo "Estoy en pwd" Estoy en /home/user user@hostname:~$ ; permite la ejecucin de ms de una orden en una sola l o a nea de comando. user@hostname:~$ mkdir textos; cd textos; cp ../*.txt . ; cd .. user@hostname:~$
1.6.1.
Variables de entorno.
Las variables de entorno permiten la conguracin, por defecto, de muchos programas o cuando ellos buscan datos o preferencias. Se encuentran denidas en los archivos de conguracin anteriormente mencionados. Para referenciar a las variables se debe poner el s o mbolo $ delante, por ejemplo, para mostrar el camino al directorio por defecto del usuario user: user@hostname:~$ echo $HOME /home/user user@hostname:~$ Las variables de entorno ms importantes son: a HOME - El directorio por defecto del usuario. PATH - El camino de bsqueda, una lista de directorios separados con : para buscar u programas.
Acento agudo o inclinado hacia atrs, backquote. a Acento usual o inclinado hacia adelante, single quote. 26 double quote.
25 24
26
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. EDITOR - El editor por defecto del usuario. DISPLAY - Bajo el sistema de X windows, el nombre de mquina y pantalla que est usana a do. Si esta variable toma el valor :0 el despliegue es local. TERM - El tipo de terminal. En la mayor de los casos bajo el sistema X windows se a trata de xterm y en la consola en Linux es linux. En otros sistemas puede ser vt100. SHELL - La shell por defecto. MANPATH - Camino para buscar pginas de manuales. a PAGER - Programa de paginacin de texto (less o more). o TMPDIR - Directorio para archivos temporales.
1.6.2.
Redireccin. o
Cuando un programa espera que se teclee algo, aquello que el usuario teclea se conoce como el Standard Input: stdin. Los caracteres que el programa retorna por pantalla es lo que se conoce como Standard Output: stdout (o Standard Error : stderr27 ). El signo < permite que un programa reciba el stdin desde un archivo en vez de la interaccin con el usuario. o Por ejemplo: mail root < file, invoca el comando mail con argumento (destinatario del mail) root, siendo el contenido del mensaje el contenido del archivo file en vez del texto que usualmente teclea el usuario. Ms a menudo aparece la necesidad de almacenar en un archivo a la salida de un comando. Para ello se emplea el signo >. Por ejemplo, man bash > file, invoca el comando man con argumento (informacin deseada) bash pero indicando que la o informacin debe ser almacenada en el archivo file en vez de ser mostrada por pantalla. o En otras ocasiones uno desea que la salida de un programa sea la entrada de otro. Esto se logra empleando los denominados pipes, para ello se usa el signo |. Este signo permite que el stdout de un programa sea el stdin del siguiente. Por ejemplo: zcat manual.gz | more Invoca la orden de descompresin de zcat y conduce el ujo de caracteres hacia el paginador o more, de forma que podamos ver pgina a pgina el archivo descomprimido. A parte de los a a s mbolos mencionados existen otros que permiten acciones tales como: >> Aadir el stdout al nal del archivo indicado (append ).28 n >& o &> (slo csh, tcsh y bash) Redireccionar el stdout y stderr. Con 2> redireco cion slo el stderr. o o >>& Igual que >& pero en modo append.
27 28
1.6. SHELLS.
27
1.6.3.
Ejecucin de comandos. o
Si el comando introducido es propio del shell (built-in), se ejecuta directamente. En caso contrario: Si el comando contiene /, el shell lo considera un PATH e intenta resolverlo (entrar en cada directorio especicado para encontrar el comando). En caso contrario el shell busca en una tabla hash table que contiene los nombres de los comandos que se han encontrado en los directorios especicados en la variable PATH, cuando ha arrancado el shell.
1.6.4.
Aliases.
Para facilitar la entrada de algunas rdenes o realizar operaciones complejas, los shells o interactivos permiten el uso de aliases. La orden alias permite ver qu aliases hay denidos e y tambin denir nuevos. Es corriente denir el alias rm =rm -i, de esta forma la orden e siempre pide conrmacin para borrar un archivo. Si alguna vez quieres usar rm sin alias, slo o o hace falta poner delante el s mbolo \, denominado backslash . Por ejemplo \rm elimina los alias aplicados a rm. Otro ejemplo, bastante frecuente podr ser (debido a la complejidad de la a orden): alias ffind =find . -name \!*. Para emplearlo: ffind tema.txt, el resultado es la bsqueda recursiva a partir del directorio actual de un archivo que se llame tema.txt, u mostrando el camino hasta el mismo.
1.6.5.
La shell bash.
Slo bash puede considerarse un shell interactivo, permitiendo la edicin de la l o o nea de comandos, y el acceso a la historia de rdenes (readline). En uso normal (historia y editor o de l nea de comandos) bash es compatible con otras shells como tcsh y ksh, ver apndice. e En bash el modo de completado (le completion) es automtico (usando TAB slo) si el shell a o est en modo interactivo. a Comandos del shell. help Ayuda interna sobre los comandos del shell. set Muestra el valor de todas las variables. VARIABLE=VALUE Permite asignar el valor de una variable de entorno. Para que dicha variable sea heredada es necesario emplear: export VARIABLE o bien combinarlas: export VARIABLE=VALUE. for var in wordlist do comandos done A la variable var, que puede llamarse de cualquier modo, se le asignan sucesivamente los
28
valores de la cadena wordlist, y se ejecuta el conjunto de comandos. El contenido de dicha variable puede ser empleado en los comandos: $var. Ejemplo: $ for i in 1 2 tres 4; do echo $i; done 1 2 tres 4 alias En bash, alias slo sirve para substitucin simple de una cadena por otra. Por ejemplo: o o alias ls=ls -F. Para crear alias con argumentos se usan funciones, ver la documentacin. o unalias name Elimina un alias asignado. history Muestra las ultimas rdenes introducidas en el shell. Algunos comandos relacionados con el o Command history son: !! Repite la ultima orden. !n Repite la orden n-sima. e !string Repite la orden ms reciente que empiece por la cadena string. a !?string Repite la orden ms reciente que contenga la cadena string. a str1 str2 o !!:s/str1/str2/ (substitute) Repite la ultima orden reemplanzando la primera ocurrencia de la cadena str1 por la cadena str2. !!:gs/str1/str2/ (global substitute) Repite la ultima orden reemplazando todas las ocurrencias de la cadena str1 por la cadena str2. !$ Es el ultimo argumento de la orden anterior que se haya tecleado. source file Ejecuta las rdenes del chero file en el shell actual. o umask value
1.7. AYUDA Y DOCUMENTACION. Asigna la mscara para los permisos por omisin. a o Los comandos umask , source , history , unalias y hash shell tcsh.
29
29
, funcionan igual en la
1.6.6.
Archivos de script.
Un archivo de script es una sucesin de comandos de la shell que se ejecutan secuencialo mente. Veamos un ejemplo simple: #!/bin/bash variable=/home/yo cp $1 /tmp/$2 rm $1 cd $variable # Hecho por mi La primera l nea declara la shell espec ca que se quiere usar. En la segunda l nea hay una declaracin de una variable interna. La tercera contiene los dos primeros argumentos con que o fue llamado el script. Por ejemplo, si el anterior script est en un archivo llamado ejemplo, a el comando ejemplo file1 file2 asocia $1 a file1 y $2 a file2. La l nea 5 hace uso de la variable interna dentro de un comando. La ultima l nea, que comienza con un # corresponde a un comentario. Notemos que la primera tambin es un comentario, pero la combinacin #! e o en la primera l nea fuerza a que se ejecute esa shell. Esto slo es una m o nima pincelada de una herramienta muy poderosa y util. Los comandos disponibles en la shell conforman un verdadero lenguaje de programacin en s y los scripts o , pueden disearse para realizar tareas montonas y complejas. Este es un tema que le ser util n o a profundizar.
1.7.
Ayuda y documentacin. o
Para obtener ayuda sobre comandos de unix, se puede emplear la ayuda on-line, en la forma de pginas de manual. As man comando proporciona la ayuda sobre el comando dea seado. Por ejemplo, para leer el manual de los shells, puedes entrar: man sh csh tcsh bash, la orden formatea las pginas y te permite leer los manuales en el orden pedido. En el caso a de bash se puede usar el comando help, por ejemplo, help alias. Adems, para muchos a comandos y programas se puede obtener informacin tipeando info comando. Finalmeno te, algunos comandos tienen una opcin de ayuda (--help), para recordar rpidamente las o a opciones ms comunes disponibles (ls --help). a
1.8.
Procesos.
En una mquina existen una multitud de procesos que pueden estar ejecutndose sia a multneamente. La mayor de ellos no corresponden a ninguna accin realizada por el usuaa a o
En bash y sh la hash table se va generando dinmicamente a medida que el usuario va empleando las a o rdenes. As el arranque del shell es ms rpido, y el uso de orden equivalente hash -r casi nunca hace falta. a a
29
30
rio y no merecen que se les preste mayor atencin. Estos procesos corresponden a programas o ejecutados en el arranque del sistema y tienen que ver con el funcionamiento global del servidor. En general, los programas suelen tener uno de estos dos modos de ejecucin: o foreground: Son aquellos procesos que requieren de la interaccin y/o atencin del o o usuario mientras se estn ejecutando, o bien en una de sus fases de ejecucin (i.e. a o introduccin de datos). As por ejemplo, la consulta de una pgina de manual es un o a proceso que debe ejecutarse claramente en foreground. background: Son aquellos procesos que no requieren de la interaccin con el usuario o para su ejecucin. Si bien el usuario desear estar informado cuando este proceso o a termine. Un ejemplo de este caso ser la impresin de un archivo. a o Sin embargo, esta divisin que a primera vista pueda parecer tan clara y concisa, a menudo o en la prctica aparece la necesidad de conmutar de un modo al otro, detencin de tareas a o indeseadas, etc. As por ejemplo, puede darse el caso de que estemos leyendo una pgina de a manual y de repente necesitemos ejecutar otra tarea. Un proceso viene caracterizado por: process number job number Veamos algunas de las rdenes ms frecuentes para la manipulacin de procesos: o a o comando & Ejecucin de un comando en el background. o
30
Ctrl-Z Detiene el proceso que estuviera ejecutndose en el foreground y lo coloca a detenido en el background. Ctrl-C Termina un proceso que estaba ejecutndose en foreground. a Ctrl-\ Termina de forma denitiva un proceso que estaba ejecutndose en foreground. a ps x Lista todos los procesos que pertenezcan al usuario, incluyendo los que no estn a asociados a un terminal. jobs Lista los procesos que se hayan ejecutado desde el shell actual, mostrando el job number. fg (job number) Pasa a ejecucin en foreground un proceso que se hallase en backo ground. bg (job number) Pasa a ejecucin en background un proceso que se hallase detenido o con Ctrl-Z. kill (process number) Env una seal31 a un proceso unix. En particular, para a n enviar la seal de trmino a un programa, damos el comando kill -KILL, pero no n e hace falta al ser la seal por defecto. n
30 31
Por omisin un comando se ejecuta siempre en el foreground. o Para ver las seales disponibles entra la orden kill -l (l por list). n
1.9. EDITORES.
31
Cuando se intenta abandonar una sesin con algn proceso an detenido en el background o u u del shell, se informa de ello con un mensaje del tipo: There are stopped jobs si no importa, el usuario puede intentar abandonar de nuevo el shell y ste matar los jobs, o puedes utilizar e a fg para traerlos al foreground y ah terminar el mismo.
1.9.
Editores.
Un editor es un programa que permite crear y/o modicar un archivo. Existen una multitud de editores diferentes, y al igual que ocurre con los shells, cada usuario tiene alguno de su predileccin. Mencionaremos algunos de los ms conocidos: o a vi - El editor standard de unix. emacs (xemacs) - Editor muy congurable escrito en lenguaje Lisp. Existen muchos modos para este editor (lector de mail, news, www,. . . ) que lo convierten en un verdadero shell para multitud de usuarios. Las ultimas versiones del mismo permiten la ejecucin desde X-windows o terminal indistintamente con el mismo binario. Posee un o tutorial en l nea, comando C-H t dentro del editor. El archivo de conguracin persoo nalizada es: $HOME/.emacs. jove - Basado en Emacs, (Jonathans Own Version of Emacs). Posee tutorial en una utilidad asociada: teachjove. El archivo de conguracin personalizada es: $HOME/.joverc. o jed - Editor congurable escrito en S-Lang. Permite la emulacin de editores como o emacs y Wordstar. Posee una ayuda en l nea C-H C-H. El archivo de conguracin o personalizada es: $HOME/.jedrc. gedit - Un pequeo y liviano editor de texto para Gnome n xjed - Versin de jed para el X-windows system. Presenta como ventaja que es capaz o de funcionar en muchos modos: lenguaje C, Fortran, TeX, etc., reconociendo palabras clave y signos de puntuacin, empleando un colorido distinto para ellos. El archivo de o conguracin personalizada es el mismo que el de jed. o Dado que los editores del tipo de gedit disponen de mens auto explicativos, daremos a u continuacin unas ligeras nociones slo de vi y emacs. o o
1.9.1.
El editor vi.
El vi es un editor de texto muy poderoso pero un poco dif de usar. Lo importante cil de este editor es que se puede encontrar en cualquier sistema unix y slo hay unas pocas o diferencias entre un sistema y otro. Explicaremos lo bsico solamente. Comencemos con el a comando para invocarlo: localhost:/# vi
32
~ ~ ~ /tmp/vi.9Xdrxi: new file: line 1 La sintaxis para editar un archivo es: localhost:/# vi nombre.de.archivo ~ ~ ~ nombre.de.archivo: new file: line 1
Insertar y borrar texto en vi. Cuando se inicia el vi, editando un archivo, o no, se entra en un modo de rdenes, es decir, o que no se puede empezar a escribir directamente. Si se quiere entrar en modo de insercin o de texto se debe presionar la tecla i. Entrando en el modo de insercin, se puede empezar a o escribir. Para salir del modo de insercin de texto y volver al modo de rdenes se apreta ESC. o o Aqui ya estamos escribiendo porque apretamos la tecla i al estar en modo ordenes. ~ ~
La tecla a en el modo de rdenes tambin entra en modo de insercin de texto, pero en o e o vez de comenzar a escribir en la posicin del cursor, empieza un espacio despus. o e La tecla o en el modo de rdenes inserta texto pero desde la l o nea que sigue a la l nea donde se est ubicado. a Para borrar texto, hay que salir al modo rdenes, y presionar la tecla x que borrar el o a texto que se encuentre sobre el cursor. Si se quiere borrar las l neas enteras, entonces se debe presionar dos veces la tecla d sobre la l nea que deseo eliminar. Si se presionan las teclas dw se borra la palabra sobre la que se est ubicado. a La letra R sobre una palabra se puede escribir encima de ella. Esto es una especie de modo de insercin de texto pero slo se podr modicar la palabra sobre la que se est situado. La o o a a tecla ~ cambia de mayscula a minscula la letra sobre la que se est situado. u u a Moverse dentro de vi. Estando en modo rdenes podemos movernos por el archivo que se est editando usando o a las echas hacia la izquierda, derecha, abajo o arriba. Con la tecla 0 nos movemos al comienzo de la l nea y con la tecla $ nos movemos al nal de la misma.
33
Con las teclas w y b nos movemos al comienzo de la siguiente palabra o al de la palabra anterior respectivamente. Para moverme hacia la pantalla siguiente la combinacin de teclas o CTRL F y para volver a la pantalla anterior CTRL B. Para ir hasta el principio del archivo se presiona la tecla G. Opciones de comandos. Para entrar al men de comandos se debe presionar la tecla : en el modo de rdenes. u o Aparecern los dos puntos (:). Aqu se pueden ingresar ordenes para guardar, salir, cambiar a de archivo entre otras cosas. Veamos algunos ejemplos: :w Guardar los cambios. :w otherfile.txt Guardar con el nuevo nombre otherfile.txt :wq Guardar los cambios y salir. :q! Salir del archivo sin guardar los cambios. :e file1.txt Si deseo editar otro archivo al que se le pondr por nombre file1.txt. a :r file.txt Si se quiere insertar un archivo ya existente, por ejemplo file.txt. :r! comando Si se quiere ejecutar algn comando del shell y que su salida aparezca en u el archivo que se est editando. a
1.9.2.
El editor GNU Emacs, escrito por Richard Stallman de la Free Software Foundation, es uno de los que tienen mayor aceptacin entre los usuarios de unix, estando disponible bajo o 32 e o licencia GNU GPL para una gran cantidad de arquitecturas. Tambin existe otra versin de emacs llamada XEmacs totalmente compatible con la anterior pero presentando mejoras signicativas respecto al GNU Emacs. Dentro de los inconvenientes que presenta es que no viene por defecto incluido en la mayor de los sistemas unix. Las actuales distribuciones a de Linux y en particular Debian GNU/Linux contienen ambas versiones de emacs, tanto GNU Emacs como XEmacs, como tambin versiones de jove, jed, xjed y muchos otros editores. e Para mayor informacin ver Apndice. o e
1.10.
El sistema X Windows.
El X Windows system es el sistema estndar de ventanas en las estaciones de trabajo. Lo a usual actualmente es que el sistema de ventanas sea arrancado automticamente cuando la a mquina parte. En el sistema X Windows deben distinguirse dos conceptos: a
La licencia de GNU, da el permiso de libre uso de los programas con sus fuentes, pero los autores mantienen el Copyright y no es permitido distribuir los binarios sin acceso a sus fuentes. Los programas derivados de dichos fuentes heredan la licencia GNU.
32
34
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. server : Es un programa que se encarga de escribir en el dispositivo de video y de capturar las entradas (por teclado, ratn, etc.). Asimismo se encarga de mantener o los recursos y preferencias de las aplicaciones. Slo puede existir un server para cada o pantalla. client : Es cualquier aplicacin que se ejecute en el sistema X Windows. No hay l o mite (en principio) en el nmero de clientes que pueden estarse ejecutando simultneamente. u a Los clientes pueden ser locales o remotos.
Window Manager (WM) Es un cliente con privilegios especiales: controla el comportamiento (forma, tamao,. . . ) del resto de clientes. Existen varios, destacando: n icewm : Ice Window Manager, uno de los window managers gnome compatible. sawsh : Window managers gnome compatible, altamente congurable y muy integrado al gnome desktop. Metacity : Window managers gnome 2 compatible. El look and feel (o GUI) de X Windows es extremadamente congurable, y puede parecer que dos mquinas son muy distintas, pero esto se debe al WM que se est usando y no a que a e las aplicaciones sean distintas. Para congurar tu sesin es necesario saber qu programas ests usando y ver las pginas o e a a de manual. Los archivos principales son: .xinitrc o .xsession archivo le al arrancar X Windows. Aqu se pueden denir do los programas que aparecen al inicio de tu sesin. o .fvwmrc archivo de conguracin del fvwm. Ver las pginas del manual de fvwm. o a .olwmrc archivo de conguracin del olwm. Ver las pginas del manual de olwm. o a .Xdefaults Conguracin general de las aplicaciones de X Windows. Aqu puedes o denir los resources que encontrars en los manuales de las aplicaciones de X. a En caso de que tengas que correr una aplicacin de X que no est disponible en la mquina o e a que ests usando, eso no representa ningn problema. Las rdenes necesarias son (por ejemplo, a u o para arrancar un gnome-terminal remoto): user@hostname1:~$ ssh -XC userB@hostname2 userB@hostname2s password: userB@hostname2:~$ gnome-terminal & Las opciones XC en el comando ssh corresponden a que exporte el DISPLAY y que comprima, respectivamente. La forma antigua
1.11. USO DEL RATON. userA@hostname1:~$ xhost +hostname2 hostname2 being added to access control list user@hostname1:~$ ssh userB@hostname2 userB@hostname2s password: userB@hostname2:~$ export DISPLAY=hostname1:0 userB@hostname2:~$ gnome-terminal &
35
Si todo est previamente congurado, es posible que no haga falta dar el password. a Cuando quieres salir, normalmente puedes encontrar un cono con la opcin Log out, en o un men o panel de la pantalla. u
1.11.
El ratn es un dispositivo esencial en el uso de programas X, sin embargo, la funcin que o o realiza en cada uno de ellos no est normalizada. a Comentaremos la pauta seguida por la mayor de las aplicaciones, pero debe tenerse a presente que es muy frecuente encontrar aplicaciones que no las respetan.33 Botn izquierdo (LB): Seleccionar. Comienza el bloque de seleccin. o o Botn central (MB): Pegar. Copia la seleccin en la posicin del cursor. o o o Botn derecho (RB): Habitualmente ofrece un men para partir aplicaciones. o u Existen dos modos para determinar cul es la ventana activa, aqulla que recibe las a e entradas de teclado: Focus Follows Mouse: La ventana que contenga al ratn es la que es activa. No usado o por defecto actualmente. Click To Focus: La ventana seleccionada es la activa. El modo que est activo depende e de la conguracin del Window Manager. o
1.12.
Internet.
En esta seccin denominaremos unix1 a la mquina local (desde donde ejecutamos la o a orden) y unix2 a la mquina remota (con la que interaccionamos). Ambos son los hostnames a de las respectivas mquinas. Existen algunos conceptos que previamente debemos comentar: a IP-number: es un conjunto de 4 nmeros separados por puntos (p.e. 200.89.74.6) que u se asocia a cada mquina. No puede haber dos mquinas conectadas en la misma red a a con el mismo nmero. u
Las aplicaciones que son conscientes de un uso anormal y estn realizadas por programadores inteligentes, a muestran en pantalla la funcin de cada botn cuando son posibles varias alternativas. o o
33
36
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. hostname: es el nombre que tiene asociada la mquina (p.e. macul). A este nombre se a le suelen aadir una serie de sujos separados por puntos que constituye el denominado n dominio (p.e. macul.ciencias.uchile.cl). Una mquina por tanto puede tener ms a a de un nombre reconocido (se habla en este caso de alias). Se denomina resolucin o a la identicacin entre un hostname y el IP-number correspondiente. La consulta o se realiza inicialmente en el archivo /etc/hosts, donde normalmente se guardan las identicaciones de las mquinas ms comnmente empleadas. En caso de que no se a a u logre se accede al servicio DNS (Domain Name Service), que permite la identicacin o (resolucin) entre un hostname y un IP-number. o mail-address: es el nombre que se emplea para enviar correo electrnico. Este nombre o puede coincidir con el nombre de una mquina, pero se suele denir como un alias, con a objeto de que la direccin no deba de cambiarse si la mquina se estropea o se cambia o a por otra.
1.12.1.
Acceso a la red.
Existen muchos programas para la conexin de la red, los ms usados son: o a telnet unix2, hace un login en la mquina unix2, debe ingresarse el usuario y su a respectiva passwd. Adems, permite especicar el puerto en conexin en la mquina a o a remota. ssh nombre@unix2, muy similar a telnet pero se puede especicar el usuario, si no se especica se usa el nombre de la cuenta local. Adems, el passwd pasa encriptado a a travs de la red. ssh nombre@unix2 comando, muy similar a rsh, el passwd pasa e encriptado y ejecuta el comando en la mquina remota, mostrando el resultado en la a mquina local. a scp file1 usuario2@unix2:path/file, copia el archivo file1, del usuario1, que se encuentra en el directorio local en la mquina unix1, en la cuenta del usuario2 en la a mquina unix2 en $HOME/path/file. Si no se especica el nombre del usuario se usa el a nombre de la cuenta local. Si se quiere copiar el archivo file2 del usuario3 en unix2 en la cuenta actual de unix1 el comando ser scp usuario3@unix2:file2 .. Antes a: de realizar cualquiera de las copias el sistema preguntar por el passwd del usuario en a cuestin en la mquina unix2. Nuevamente, el passwd pasa encriptado a travs de la o a e red. talk usuario1@unix2, intenta hacer una conexin para hablar con el usuario1 en la o mquina unix2. Existen varias versiones de talk en los diferentes sistemas operativos, a de forma que no siempre es posible establecer una comunicacin entre mquinas con o a sistemas operativos diferentes. ftp unix2, (le transfer protocol) aplicacin para copiar archivos entre mquinas de o a una red. ftp exige un nombre de cuenta y password para la mquina remota. Algunas a de las opciones ms empleadas (una vez establecida la conexin) son: a o
1.12. INTERNET.
37
bin: Establece el modo de comunicacin binario. Es decir, transere una imagen o exacta del archivo. asc: Establece el modo de comunicacin ascii. Realiza las conversiones necesarias o entre las dos mquinas en comunicacin. Es el modo por defecto. a o cd: Cambia directorio en la mquina remota. a lcd: Cambia directorio en la mquina local. a ls: Lista el directorio remoto. !ls: Lista el directorio local. prompt : No pide conrmacin para transferencia mltiple de archivos. o u get rfile [lfile]: transere el archivo rfile de la mquina remota a la mquia a na local denominndolo lfile. En caso de no suministrarse el segundo argumento a supone igual nombre en ambas mquinas. a put lfile [rfile] : transere el archivo lfile de la mquina local a la mquina a a remota denominndolo rfile. En caso de no suministrarse el segundo argumento a supone igual nombre en ambas mquinas. Tambin puede usarse send. a e mget rfile : igual que get, pero con ms de un archivo (rfile puede contener a caracteres comodines). mput lfile : igual que put, pero con ms de un archivo (lfile puede contener a caracteres comodines). Existen versiones mejoradas de ftp con muchas ms posibilidades, por ejemplo, ncftp. a Tambin existen versiones grcas de clientes ftp donde la eleccin de archivo, el sentido e a o de la transferencia y el modo de sta, se elige con el mouse (p.e. wxftp). e rlogin -l nombre unix2, (remote login), hace un login a la mquina unix2 como el a usuario nombre por defecto, sin los argumentos -l nombre rlogin usa el nombre de la cuenta local. Normalmente rlogin pide el password de la cuenta remota, pero con el uso del archivo .rhosts o /etc/hosts.equiv esto no es siempre necesario. rsh -l nombre unix2 orden, (remote shell ), ejecuta la orden en la mquina unix2 a como usuario nombre. Es necesario que pueda entrar en la mquina remota sin password a para ejecutar una orden remota. Sin especicar orden acta como rlogin. u
1.12.2.
El correo electrnico. o
El correo electrnico (e-mail) es un servicio para el env de mensajes entre usuarios, o o tanto de la misma mquina como de diferentes mquinas. a a Direcciones de correo electrnico. o Para mandar un e-mail es necesario conocer la direccin del destinatario. Esta direccin o o consta de dos campos que se combinan intercalando entre ellos el @ (at): user@domain
38
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. user : es la identicacin del usuario (i.e. login) en la mquina remota. o a domain : es la mquina donde recibe correo el destinatario. A menudo, es frecuente a que si una persona tiene acceso a un conjunto de mquinas, su direccin de correo no a o corresponda con una mquina sino que corresponda a un alias que se resolver en un a a nombre espec co de mquina en forma oculta para el que env a a. Si el usuario es local, no es necesario colocar el campo domain (ni tampoco el @).
Nomenclatura. Veamos algunos conceptos relacionados con el correo electrnico: o Subject : Es una parte de un mensaje que piden los programas al comienzo y sirve como t tulo para el mensaje. Cc (Carbon Copy) : Permite el env de copias del mensaje que est siendo editado a o a terceras personas. Reply : Cuando se env un mensaje en respuesta a otro se suele aadir el comienzo a n del subject: Re:, con objeto de orientar al destinatario sobre el tema que se responde. Es frecuente que se incluya el mensaje al que se responde para facilitar al destinatario la comprensin de la respuesta. o Forward : Permite reenviar un mensaje completo (con modicaciones o sin ellas) a una tercera persona. Notando que Forward env tambin los archivos adjuntos, mientras a e que la opcin Reply no lo hace. o Forwarding Mail : Permite a un usuario que disponga de cuentas en varias mquinas a 34 no relacionadas, de concentrar su correo en una cuenta unica . Para ello basta con tener un archivo $HOME/.forward que contenga la direccin donde desea centralizar su o correo. Mail group : Un grupo de correo es un conjunto de usuarios que reciben el correo dirigido a su grupo. Existen rdenes para responder a un determinado correo recibido o por esa v de forma que el resto del grupo sepa lo que ha respondido un miembro del a mismo. In-Box : Es el archivo donde se almacena el correo que todav no ha sido le por el a do usuario. Suele estar localizado en /var/spool/mail/user. Mailer-Daemon : Cuando existe un problema en la transmisin de un mensaje se o recibe un mensaje proveniente del Mailer-Daemon que indica el problema que se ha presentado.
Este comando debe usarse con conocimiento pues en caso contrario podr provocar un loop indenido y a no recibir nunca correo.
34
39
Es posiblemente la aplicacin ms simple. Para la lectura de mail teclear simplemente: o a mail y a continuacin aparece un o ndice con los diferentes mensajes recibidos. Cada mensaje tiene una l nea de identicacin con nmero. Para leer un mensaje basta teclear su nmero y a o u u continuacin return. Para enviar un mensaje: mail (address) se pregunta por el Subject: o y a continuacin se introduce el mensaje. Para acabar se teclea slo un punto en una l o o nea o bien Ctr-D. Por ultimo, se pregunta por Cc:. Es posible personalizar el funcionamiento me diante el archivo $HOME/.mailrc. Para enviar un archivo de texto a travs del correo se suele e emplear la redireccin de entrada: mail (address) < file. Si queremos enviar un archivo o binario en forma de attach en el mail, el comando es mpack archivo-binario address.
1.12.3.
Ftp anonymous.
Existen servidores que permiten el acceso por ftp a usuarios que no disponen de cuenta en dichas mquinas. Para ello se emplea como login de entrada el usuario anonymous y como a passwd la direccin de e-mail personal. Existen servidores que no aceptan conexiones desde o mquinas que no estn declaradas correctamente en el servicio de nombre (dns), as como a a algunas que no permiten la entrada a usuarios que no se identican correctamente. Dada la sobrecarga que existe, muchos de los servidores tienen limitado el nmero de usuarios que u pueden acceder simultneamente. a
1.12.4.
WWW.
WWW son las siglas de World-Wide Web. Este servicio permite el acceso a informacin o entrelazada (dispone de un texto donde un trmino puede conducir a otro texto): hyperlinks. e Los archivos estn realizados en un lenguaje denominado html. Para acceder a este servicio a es necesario disponer de un lector de dicho lenguaje conocido como browser o navegador. Destacan actualmente: Iceweasel, Iceape, Opera, Camino (para MAC) y el simple pero muy rpido Lynx. a
1.13.
Impresin. o
Cuando se quiere obtener una copia impresa de un archivo se emplea el comando lpr. lpr file - Env el archivo file a la cola de impresin por defecto. Si la cola est activaa o a da, la impresora lista y ningn trabajo por encima del enviado, nuestro trabajo ser procesado u a de forma automtica. a A menudo existen varias posibles impresoras a las que poder enviar los trabajos. Para seleccionar una impresora en concreto (en vez de la por defecto) se emplea el modicador: lpr -Pimpresora, siendo impresora el nombre lgico asignado a esta otra impresora. Para o recibir una lista de las posibles impresoras de un sistema, as como su estado, se puede em plear el comando /usr/sbin/lpc status. La lista de impresoras y su conguracin tambin o e est disponible en el archivo /etc/printcap. a Otras rdenes para la manipulacin de la cola de impresin son: o o o
40
CAP ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. lpq [-Pimpresora], permite examinar el estado de una determinada cola (para ver la cantidad de trabajos sin procesar de sta, por ejemplo). e lprm [-Pimpresora] jobnumber, permite eliminar un trabajo de la cola de impresin. o
Uno de los lenguajes de impresin grca ms extendidos en la actualidad es PostScript. o a a La extensin de los archivos PostScript empleada es .ps. Un archivo PostScript puede ser o visualizado e impreso mediante los programas: gv, gnome-gv o ghostview. Por ello muchas de las impresoras actuales slo admiten la impresin en dicho formato. o o En caso de desear imprimir un archivo ascii deber previamente realizarse la conversin a o a PostScript empleando la orden a2ps: a2ps file.txt Esta orden env a la impresora a el archivo ascii file.txt formateado a 2 pginas por hoja. Otro programa que permite a convertir un archivo ascii en postscript es enscript. Otro tipo de archivos ampliamente difundido y que habitualmente se necesita imprimir es el conocido como Portable Document Format. Este tipo de archivo poseen una extensin o .pdf y pueden ser visualizados e impresos usando aplicaciones tales como: xpdf, acroread o gv.
1.14.
Compresin. o
A menudo necesitamos comprimir un archivo para disminuir su tamao, o bien crear un n respaldo (backup) de una determinada estructura de directorios. Se comentan a continuacin o una serie de comandos que permiten ejecutar dichas acciones. u El compresor compress est relativamente fuera de uso35 pero an podemos encontrarnos a con archivos comprimidos por l. e uncompress file.Z : descomprime el archivo, creando el archivo file. Destruye el archivo original. zcat file.Z : muestra por el stdout el contenido descomprimido del archivo (sin destruir el original). compress file : comprime el archivo, creando el archivo file.Z. Destruye el archivo original. Otra alternativa de compresor mucho ms usada es gzip, el compresor de GNU que posee a una mayor razn de compresin que compress. Veamos los comandos: o o gzip file : comprime el archivo, creando el archivo file.gz. Destruye el archivo original. gunzip file.gz : descomprime el archivo, creando el archivo file. Destruye el archivo original. zless file.gz : muestra por el stdout el contenido descomprimido del archivo paginado por less.
35
Este comando no se incluye en la instalacin bsica. Debemos cargar el paquete ncompress para tenerlo o a
1.14. COMPRESION.
41
La extensin empleada en los archivos comprimidos con gzip suele ser .gz, pero a veces o se usa .gzip. Adicionalmente el programa gunzip tambin puede descomprimir archivos e creados con compress. La opcin con mayor tasa de compresin que gzip es bzip2 y su descompresor bunzip2. o o bzip2 file : comprime el archivo, creando el archivo file.bz2. Destruye el archivo original. bunzip2 file.bz2 : descomprime el archivo, creando el archivo file. Destruye el archivo original. bzcat file.bz2 : muestra por el stdout el contenido descomprimido del archivo. Debemos usar un paginador, adicionalmente, para verlo por pginas. a La extensin usada en este caso es .bz2. El kernel de Linux se distribuye en formao to bzip2. Tambin existe una versin paralelizada llamada pbzip2. Uno de los mejores e o algoritmos de compresin est disponible para Linux en el programa p7zip. Veamos un o a ejemplo: un archivo linux-2.6.18.tar que contiene el kernel 2.6.18 de Linux que tiene un tamao de 230 Mb. Los resultados al comprimirlo con compress, gzip, bzip2 y 7za son: n linux-2.6.18.tar.Z 91 Mb, linux-2.6.18.tar.gz 51 Mb, linux-2.6.18.tar.bz2 40 Mb y linux-2.6.18.tar.7z 33 Mb.36 Existen tambin versiones de los compresores compatibles con otros sistemas operativos: e zip, unzip, unarj, lha, rar y zoo. En caso que se desee crear un archivo comprimido con una estructura de directorios debe ejecutarse la orden: tar cvzf nombre.tgz directorio o bien tar cvjf nombre.tbz directorio En el primer caso comprime con gzip y en el segundo con bzip2. Para descomprimir y restablecer la estructura de directorio almacenada se usan los comandos: tar xvzf nombre.tgz directorio si se realiz la compresin con gzip o bien o o tar xvjf nombre.tbz directorio si se realiz la compresin con bzip2. o o
Los comandos gzip y bzip2 fueron dados con la opcin --best para lograr la mayor compresin. El o o comando usado para la compresin con 7z fue: 7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on o file.tar.7z file.tar, note la nueva extensin 7z. Para descomprimir con 7z basta 7z e file.tar.7z o
36
42
En este cap tulo se intentar dar los elementos bsicos de lo que es un lenguaje de proa a gramacin y lo que es programar. o
2.1.
Qu es programar? e
A continuacin, presentamos algunas alternativas de respuesta a esta pregunta: o Hacer un programa. Hacer que un computador haga una secuencia de instrucciones que uno le pide. Darle, de alguna forma, una secuencia de pasos lgicos para que un computador los o ejecute con la intencin de alcanzar algn objetivo. o u Escribir una precisa secuencia de comandos o instrucciones, en algn lenguaje que el u computador entienda (a este tipo de lenguaje lo llamaremos lenguaje de programacin) o para que luego el computador las realice exactamente, paso a paso. Un programa es un archivo que puede ser tan corto como una sola l nea de cdigo, o tan o largo como varios millones de l neas de cdigo. o
2.2.
Lenguajes de programacin. o
Existen diferentes tipos de lenguajes de programacin, algunos ms cercanos a la mquina o a a y menos al programador; otros ms cercanos al programador y distantes de la mquina. a a Realmente existe toda una jerarqu entre los lenguajes de programacin. Veamos algunos a o ejemplos:
2.2.1.
Es el lenguaje de la CPU, y el lenguaje de ms bajo nivel. Compuesto de 0 y 1 binario, a lo que est muy cerca de la mquina pero muy lejos del programador. Una de sus grandes a a desventajas es que no es fcil de escribir o de leer para el programador. a Un programa simple, como Hola mundo, se ver en cdigo binario algo as como: a o 43
2.2.2.
El paso siguiente es reeplazar los 1 y 0 por una secuencia de abreviaturas del lenguaje de mquina, este tipo de lenguaje se conoce como lenguaje de Ensamblador o Assembler. a Est cerca de la mquina pero no tanto como el anterior y esta un poco ms cerca del a a a programador. Veamos el programa Hola mundo en lenguaje de Ensamblador para la familia de procesadores X86. title Programa Hola Mundo (hello.asm) ; Este programa muestra "Hola, Mundo!" dosseg .model small .stack 100h .data hello_message db Hola, Mundo!, 0dh, 0ah, $ .code main proc mov ax, @ .data mov ds,ax mov ah,9 mov dx, offset hello_message int 21h mov ax,4C00h int 21h main endp end main
2.2.3.
Utilizan declaraciones en los programas, sentencias como palabras y expresiones algebraicas. Estos lenguajes fueron desarrollados en las dcadas del 50 y 60. Son lenguajes que estn e a ms cerca del programador que de la mquina, por lo tanto, necesitan una etapa de traducin a a o para que los entienda la mquina. Este proceso se puede hacer de dos maneras: compilando a o interpretando el programa fuente. Lenguajes Compilados. En este caso, otro programa (el compilador) lee el programa fuente, un archivo en ASCII donde se encuentran el listado de instruciones y lo reescribe en un archivo binario, en lenguaje de mquina para que la CPU pueda entenderlo. Esto se hace de una sola vez y el programa a nal se guarda en esta nueva forma (un ejecutable). El ejecutable de un programa que es compilado se estima que ser considerablemente ms largo que el original, programa fuente. a a
45
Algunos de los lenguajes compilados ms notables son Fortran, C y C++. Un ejemplo del a programa Hola mundo escrito en C++ es dado a continuacin: o // // Programa Hola Mundo // #include <iostream> using namespace std; int main() { cout << "Hola mundo" << endl; return 0; }
2.2.4.
Lenguajes interpretados.
En este caso otro programa (el intrprete) traduce las declaraciones del programa original e a lenguaje de mquina, l a nea por l nea, a medida que va ejecutando el programa original. Un programa interpretado suele ser ms pequeo que uno compilado pero tardar ms tiempo en a n a a ser ejecutado. Existe gran cantidad de este tipo de lenguajes, Python, Perl, Bash, por nombrar algunos. Un ejemplo del programa Hola mundo escrito en Python es dado a continuacin: o # Programa Hola mundo print "Hola Mundo"
2.2.5.
Lenguajes especializados.
Desde el punto de vista de la funcionalidad de los lenguajes podemos separarlos en lenguajes de carcter general y lenguajes especializados. Los lenguajes de carcter general son a a aquellos que sirven para programar una gran nmero de problemas, por ejemplo C o C++, u Python. Los lenguajes especializados han sido diseados para realizar tareas espec n cas. Ejemplos de ello son PHP y JavaScript, especializados en crear pginas web, o SQL, creado para a manipular informacin en bases de datos. o Una lista de lenguajes. A continuacin, damos una lista, probablemente muy incompleta, de los lenguajes de o programacin ms comunes en la actualidad: o a ABC, Ada, ASP, Awk, BASIC, C, C++, C#, Caml, Cobol, cdigo de mquina, Corba, o a Delphi, Eiel, Erlang, Fortran, Haskell, Java, JavaScript, Lisp, Logo, Modula, Modula 2, Mozart, Mumps, Oberon, Objetive C, Oz, Pascal, Perl, PHP, Python, Realbasic, Rebol, Rexx, RPG, Ruby, Scheme, Smaltalk, SQL, Squeak, TCL, Visual Basic.
46
2.3.
2.3.1.
Son lenguajes hablados por la gente (por ejemplo: Espaol, Ingls, Alemn o Japons). n e a e Una de sus caracteristicas es que son ambiguos, por ejemplo: Dame esa cosa o Oh, seguro, Grande!. En ambos ejemplos no es claro a que se estn reriendo y se necesita un contexto a para entenderlos. Muchas veces estos lenguajes son redundantes y estn llenos de expresiones a idiomticas las cuales no deben ser tomadas literalmente, por ejemplo: Me podr comer a a una vaca, Me mataste, o Andate a la punta del cerro.
2.3.2.
Lenguajes formales.
Hecho por el hombre, como las matemticas, la notacin en qu a o mica o los lenguajes de programacin de computadores. Se caracterizan por ser inambiguos. Por ejemplo, una o expresin matemtica: 1 + 4 = 5; o una expresin en qu o a o mica: CH4 +2O2 2H2 O+CO2 ; o, nalmente, una expresin en lenguaje de programacin print "Hola mundo". Los lenguajes o o formales son adems concisos y estrictamente literales. a Sintaxis. Los lenguajes, tanto naturales como formales, tienen reglas de sintaxis. Por una parte, estn los tokens, que corresponden a los elementos bsicos (i.e. letras, palabras, s a a mbolos) del lenguaje: Tokens correctos: 1+3=4; gato, H2 O. Tokens incorrectos: 2@+#=!;C;Hh O. Por otro lado, tenemos las estructuras, esto es la manera en que los tokens son organizados: Estructuras correctas: 1 + 3 = 4, gato, H2 O. Estructuras incorrectas: 13+ = 4, gtoa, 2 HO.
2.4.
Desarrollando programas.
Para desarrollar sus primeros programas parta escribiendo en sus propias palabras lo que el programa deber hacer. Convierta esta descripcin en una serie de pasos en sus propias a o palabras. Para cada uno de los pasos propuestos traduzca sus palabras en un cdigo (Python o o C++). Dentro del cdigo incluya instrucciones que impriman los valor de las variables para o probar que el programa est haciendo lo que usted esperaba. a
47
2.5.
Siempre que escriba un programa debe tener presente que alguien, que puede no ser usted mismo, lo puede usar alguna vez. Lo anterior signica, en particular, que el programa debe tener documentacin, ya que un programa sin documentacin es muy dif de usar. Pero o o cil adems es importante cuidar la parte del programa con la que el usuario interacta, es decir a u la interfaz con el usuario. Esta interfaz podr ser tanto mensajes simples de texto como soan sticadas ventanas grcas. Lo importante es que ayuden al usuario a ejecutar correctamente a el programa. Revisemos una mala interfaz con el usuario. Tenemos un programa que no sabemos lo que hace, pero al ejecutarse resulta lo siguiente: Entre un numero 5 Entre otro numero 7 La respuesta es 12 Hay una evidente falta de instrucciones de parte del programador para el usuario, que primero no sabe para qu se le pide cada nmero, y luego no sabe qu hizo con ellos, slo la respuesta, e u e o 12, sin mayor explicacin de lo que signica. o Como contraparte, una buena interfaz con el usuario tiene documentacin anexa, o bien, o alguna ayuda en el mismo programa. Esta documentacin debiera explicar que hace el proo grama, los datos que necesitar y el o los resultados que entregar cuando nalice. a a Cada vez que se le pide algo al usuario deber estar claras las siguientes preguntas: an qu es exactamente lo que se supone que yo tipee?; los nmeros que ingreso deben tener e u decimales?; o deben ser sin decimales?; en qu unidades de medidas debo ingresarlos?; los e nmeros que se piden son grandes o son nmeros pequeos? Si se trata de palabras, debo u u n ingresarlas en minsculas o maysculas? u u Algunos lineamientos bsicos que deber observar para construir interfaces con el usuario a a que sea claras son los siguientes: Parta con un t tulo e indicaciones dentro del programa. Cuando pregunte por un dato que quiere que el usuario ingrese, dele la ayuda necesaria, por ejemplo Entre el largo en metros (0-100): Que las preguntas tengan sentido. Use espacios y caracteres especiales para mantener la pantalla despejada. Ind quele al usuario que el programa termin. o Una versin mejorada del programa anterior podr ser la siguiente: o a Calculo Ingrese Ingrese La suma de la suma de dos numeros un numero entero: 5 otro numero entero: 7 es 12
48
2.6.
Los errores en un programa son llamados bugs. Al proceso de rastrear los errores y corregirlos se le conoce como debugging. Un programa especializado en hacer debugging es llamado debugger. El debugging es una de las ms importantes habilidades en programaa cin. Los tres principales tipos de errores o bugs y sus consecuencias para la ejecucin del o o programa son: 1. Errores de sintaxis Usar un token o estructuralos en forma incorrecta El programa termina con un mensaje de error. 2. Errores de ejecucin (run-time error ) o Errores que ocurren durante la ejecucin. o El programa deja de correr abruptamente. 3. Errores lgicos o Errores en cmo el programa est lgicamente construido. o a o El programa corre, pero hace cosas mal.
En este cap tulo se intentar dar los elementos ms bsicos del lenguaje de programacin a a a o Python. No se pretende ms que satisfacer las m a nimas necesidades del curso, sirviendo como un ayuda de memoria de los tpicos abordados, para futura referencia. Se debe consignar que o no se consideran todas las posibilidades del lenguaje y las explicaciones estn reducidas al a m nimo.
3.1.
Python.
El Lenguaje Python fue inventado alrededor de 1990 por el cient co en computacin o holands Guido van Rossem y su nombre es un tributo a la grupo cmico Monty Python del e o cual Guido es admirador. El sitio ocial del lenguage en la web es http://www.python.org.
3.1.1.
El programa Python (como programa, no como lenguaje) posee un ambiente interactivo que nos permite ejecutar instrucciones del lenguaje Python directamente. Para ello, basta dar el comando: username@host:~$ python Python 2.4.4 (#2, Apr 5 2007, 20:11:18) [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> El programa ofrece un prompt (>>>), esperando instrucciones del usuario. Las instrucciones son interpretadas y ejecutadas de inmediato. Esta forma de usar Python tiene la ventaja de la retroalimentacin inmediata; de inmediato el programador sabe si la instruccin o o est correcta o incorrecta. Sin embargo, tiene la desventaja de que el cdigo no es guardado, a o y no puede por tanto ser reutilizado. Por otra parte, cuando escribimos un archivo de instrucciones en Python (script), tenemos la ventaja de que el cdigo s es almacenado, pudiendo ser reutilizado. En este caso las o desventajas son que la retroalimentacin no es inmediata y que habitualmente requiere ms o a debugging para que el cdigo funcione correctamente. o 49
50
3.1.2.
Creando un script.
Para crear un script de Python requerimos de un editor (vi, jed, xemacs, gedit. . . elija su favorito). Para ser ordenado, grbelo con extensin (supongamos que lo grabamos como a o archivo.py), para poder identicarlo rpidamente ms adelante. Recuerde darle los permia a sos de ejecucin adecuados (chmod u+x archivo.py). Para ejecutarlo basta ubicarse en el o directorio donde est el archivo y dar el comando a jrogan@manque:~/InProgress/python$ ./archivo.py
3.2.
3.2.1.
Lenguaje Python.
Algunos tipos bsicos. a
Cadenas de caracteres (strings): Usualmente un conjunto de caracteres, i.e. un texto. Estn delimitados por "comillas" simples o dobles. a N meros enteros: Los nmeros, que pertenecen al conjunto Z, es decir, sin decimales. u u No pueden ser mayores que un tamao jo, en torno a dos billones (2 1012 ) en un n sistema de 32 bits usando signo . Cuando se dividen entre ellos slo dan valores o enteros. Por ejemplo: 4/3=1. N meros con punto otante: Los nmeros, que pertenecen al conjunto R, es decir, u u con decimales (un nmero nito de ellos). u Enteros largos: Nmeros enteros mayores que 2 1012 . Los distinguimos por una L u al nal del nmero, por ejemplo: 23434235234L. u Varios de los otros tipos sern explicados ms adelante en el cap a a tulo Tipo bool int long int oat complex str tuple list dict le Descripcin o booleano entero entero largos nmero con punto otante u nmero complejo u string tuplas listas diccionario archivo Ejemplo True o False 117 23434235234L 1.78 0.5 +2.0j abc (1, hum, 2.0) [1, hum, 2.0] a:7.0, 23: True le(stu.dat, w)
51
Use el tipo de nmero en el cual quiere obtener su resultado. Es decir, si usted desea un u valor con decimales, use al menos un nmero con decimales en el clculo. Por ejemplo: 15/2.0 u a producir 7.5 y 15/2 producir 7, porque son ambos enteros. Si desea enteros largos, use al a a menos un entero largo en su expresin, por ejemplo: 23434235234L/2. o N mero complejos. u Los nmeros complejos son tambin soportados en Python. Los nmeros imaginarios puros u e u son escritos con un sujo j o J. Los nmeros complejos con parte real no nula son escritos u como real +imagj, o pueden ser creados con la funcin complex(real,imag). Ejemplos o >>> 1j*1J (-1+0j) >>> 1j*complex(0,1) (-1+0j) >>> 3+1j*3 (3+3j) >>> (1+2j)/(1+1j) (1.5+0.5j) >>> a=1.5+0.5j >>> a.real 1.5 >>> a.imag 0.5 Cadenas de caracteres (strings). Una cadena de caracteres debe estar entre apstrofes o comillas simples o dobles. Por o ejemplo: nombre = "Este es tu nombre" nombre2= Este es tambien su nombre Si una cadena de caracteres necesita un apstrofe dentro de ella, anteponga un \ al o apstrofe extra. Ejemplos: o titulo = "Ella dijo: \"Te amo\"" titulo2 = I\m a boy Algunas cadenas de caracteres con signicado especial empiezan con el caracter \ (String Backslash Characters). \\ = Incluya \. \ = Apstrofe simple. o
52
CAP ITULO 3. UNA BREVE INTRODUCCION A PYTHON. \" = Apstrofe doble. o \n = L nea nueva.
3.2.2.
Agregando una coma (,) al nal de una instruccin print har que el prximo comando o a o print aparezca en la misma l nea. Ejemplo print num1,"+", num2, "=", print respuesta
3.2.3.
Si queremos imprimir un texto que tenga varias l neas podemos usar dos formas distintas de la funcin print usando el caracter \n o bien usando un texto entre triple comilla o >>> print "primera linea\nsegunda linea" primera linea segunda linea >>> print """primera linea ... segunda linea""" primera linea segunda linea
3.2.4.
Variables.
Las variable son un nombre, usado dentro del programa, para referirse a un objeto o valor. Las limitaciones y consideraciones que hay que tener en cuenta para darle nombre a una variable son: No puede ser una palabra reservada del lenguaje (i.e. print, and, or, not). No puede comenzar por un nmero. u Las maysculas y las minsculas son diferentes. u u No puede incluir caracteres ilegales (i.e. $,%,+,=). Cree variables cuyos nombres signiquen algo: MAL : diy=365 BIEN: days_in_year=365
53
3.2.5.
Asignacin de variables. o
Para asignarle un valor a una variable, digamos num, basta poner el nombre de la variable a la izquierda un signo igual y al lado derecho el valor o expresin que queremos asignarle o num=8.0 num=pi*3.0**2 Un mismo valor puede ser asignado a varias variables simultaneamente >>> x=y=z=0 # Todas las variables valen cero >>> print x,y,z 0 0 0 O bien podemos hacer asignasiones diferentes valores a diferentes variables en una misma asignacin o >>> >>> 0 1 >>> >>> 1 1 >>> >>> 0 1 a,b=0,1 print a,b a,b=b,a+b print a,b a,b,c=0,1,2 print a,b,c 2
3.2.6.
Reciclando variables.
Una vez que una variable es creada su valor puede ser reasignado. Veamos un ejemplo donde la variable card_value es reutilizada card_value=card1+card2 print card_value card_value=card1+card2+card3 print card_value
3.2.7.
Operaciones matemticas. a
Con Python podemos realizar las operaciones bsicas: suma (+), resta (), multiplicacin a o () y divisin (/). Operaciones menos bsicas tambin estn disponibles: el exponente (), o a e a el mdulo ( %). o Entre las operaciones hay un orden de precedencia, unas se realizarn primero que otras. a A continuacin damos el orden de precedencia, partiendo por lo que se hace primero: o Parntesis, exponentes, multiplicacin y divisin, e o o Suma y resta.
54
Como ejemplo de la importancia de saber el orden de precedencia veamos los siguiente ejemplos: 2 (3 1) = 4 y 231=5
3.2.8.
Dos de las operaciones ms comunes con strings: a Concatenacin: se pueden concatenar dos strings al sumarlos, veamos un ejemplo: o >>> >>> >>> >>> x = "Hola" y = "Mundo" print x+y HolaMundo
3.2.9.
Composicin. o
Se pueden combinar sentencias simples en una compuesta, a travs del operador ,: e >>> x = "Elizabeth" >>> print "Tu nombre es : ",x >>> Tu nombre es : Elizabeth En el ejemplo, x fue asignado expl citamente a una variable, pero naturalmente cualquier tipo de asignacin es posible, por ejemplo: o >>> promedio=(nota+extra_creditos)/posibles >>> print "Tu promedio es : ",promedio
3.2.10.
Comentarios.
Los comentarios son anotaciones que usted escribe para ayudar a explicar lo que est haa ciendo en el programa. Los comentarios comienzan con #. Lo escrito despus de #, hasta el e nal de la l nea, es ignorado por el intrprete. Por ejemplo: e dias = 60 #disponibles para el proyecto Naturalmente, los comentarios no son muy utiles cuando se trabaja interactivamente con Python, pero s lo son cuando se escribe un script. De este modo se pueden insertar explicaciones en el cdigo que ayuden a recordar qu hace el programa en cada una de sus o e secciones, o explicarlo a terceros. Es buena costumbre de programacin que las primeras o l neas de un cdigo sean comentarios que incluyan el nombre del programador y una breve o descripcin del programa. o
3.3. CONDICIONALES.
55
3.2.11.
Entrada (input).
Para leer strings del stdin use la instruccin raw_input(), por ejemplo o nombre = raw_input("Cual es tu nombre?") Si necesita leer nmeros del stdin use la instruccin input(): u o numero=input("Cuantos?") En ambos casos, el mensaje entre comillas dentro de los parntesis es opcional, sin embare go, aclara al usuario lo que el programa le est solicitando. En el siguiente par de ejemplos, el a programa solicita informacin al usuario, salvo que en el primero, el programa queda esperano do una respuesta del usuario, quien, a menos que sepa de antemano qu quiere el programa, e no tiene modo de saber por qu le programa no se contina ejecutando. e u Ejemplo sin mensaje (queda esperando para siempre una respuesta): >>> nombre = raw_input() Ejemplo con mensaje: >>> nombre = raw_input("Cual es tu nombre?") Cual es tu nombre? Pedro >>>
3.3.
Condicionales.
Los condicionales son expresiones que puede ser ciertas o falsas. Por ejemplo, el usuario tipe la palabra correcta? o El nmero es mayor que 10? El resultado de la condicin decide o u o que suceder, por ejemplo, a todos los nmeros mayores que 100 rstele 20, cuando la palabra a u e ingresada sea la correcta, imprima Bien
3.3.1.
Posibles condicionales.
x == y x es igual a y. x != y x no es igual a y. x >y x es mayor que y. x <y x es menor que y. x >= y x es mayor igual a y.
A continuacin, algunos ejemplos de los anteriores condicionales: o x == 125: passwd == "nix": num >= 0: letter >"L": num/2 == (num1-num): num %5 != 0:
3.3.2.
El if.
A continuacin, estudiemos la instruccin if, partamos de la forma general de la instruco o cin: o if condition: statements Primero la palabra clave if, luego la condicin condition, que puede ser algo como x<y o o x==y, etc. La l nea termina con : requerido por la sintaxis del if. En las l neas siguientes statements, viene las instrucciones a seguir si la condicin es cierta. Estas instrucciones o deben ir con sangr (indent). a Un ejemplo de una construccin if simple. o num = input("Entre su edad") if num >= 30: old-person(num) print print "Gracias"
3.3.3.
El if. . . else.
La forma general de la construccin if...else a continuacin: o o if condition: statements_1 else: statements_2 El else debe de estar despus de una prueba condicional. Slo se ejecutar cuando condie o a cin evaluada en el if sea falsa. Use esta construccin cuando tenga dos conjuntos diferentes o o de instrucciones a realizar dependiendo de la condicin. Un ejemplo o
3.3. CONDICIONALES. if x%2 == 0: print "el numero es par" else: print "el numero es impar"
57
3.3.4.
El if...elif...else.
La forma general de la construccin if...elif...else, a continuacin: o o if condition_1: statements_1 elif condition_2: statements_2 else: statements_3 Para ms de dos opciones use la construccin con elif. elif es la forma acortada de las a o palabras else if. Las instrucciones asociadas a la opcin else se ejecutarn si todas las otras o a fallan. Un ejemplo concreto if x<0 : print x," elif x==0 : print x," elif x>0 : print x," else: print x," es negativo" es cero" es positivo" Error, no es un numero"
3.3.5.
El comando pass no realiza accin alguna, es decir, no hace nada. Un ejemplo o if x<0: HagaAlgo() else: pass
3.3.6.
Operadores lgicos. o
Los condicionales pueden ser unidos usando las palabras reservadas and, or o not. Si ocupamos un and para unir dos condiciones lgicas tenemos que ambas condiciones deben o satisfacerse para que el condicional sea cierto. En el caso de ocupar or para unir dos condiciones lgicas una de ellas debe ser satisfecha para que el condicional sea cierto. Finalmente o el not se antepone a una condicin y la niega, es decir, ser cierto si la condicin no es o a o satisfecha. En todos los caso se aplica que falso == 0 y cierto == 1 (en realidad cierto ! = 0). A continuacin, algunos ejemplos de operadores lgicos: o o
58 if x>0 and x<10: if y>0 and x>0: if pwd=="code" if y>0 or x<0: if not(x<y):
or pwd=="monster":
if x>y or not(x<0):
3.3.7.
Forma alternativa.
Cuando pruebe valores para < o >, estas pruebas pueden ser escritas como un slo condio cional sin usar el and. Veamos ejemplos if 0<x<100: if 1000>=x >=0:
3.4.
Funciones Pre-hechas.
Una funcin dene un conjunto de instrucciones. Es un conjunto de cdigo que puede ser o o usado una y otra vez. Puede ser creado por usted o importado desde algn mdulo. Ejemplos u o de funciones: De clculo matemtico a a log, sen, cos, tan, exp, hypot. Funciones que generan nmeros al azar, funciones de ingreso, funciones que hacen u cambios sobre un string. Cdigo hecho por el usuario que puede ser reciclado. o Hay un grupo de funciones que vienen hechas, es decir, listas para usar. Para encontrar qu funciones estn disponibles tenemos la documentacin del Python y un sitio web e a o http://www.python.org/doc/current/modindex.html Estas funciones pre-hechas vienen en grupos llamados mdulos. Para importar en nuestro o cdigo el mdulo apropiado, que contiene la funcin que nos interesa, usamos el comando o o o import modulo name Una vez importado el mdulo, cuando queremos llamar a la funcin para usarla, debemos o o dar el comando modulo name.function(arguments)
3.4. FUNCIONES PRE-HECHAS. Veamos un ejemplo com la funcin hypot del mdulo matemtico o o a import math math.hypot(8,9)
59
Si analizamos las l neas anteriores de cdigo debemos decir que el mdulo que contiene las o o funciones matemticas se llama math y ste incluye la funcin hypot que devuelve el largo a e o de la hipotenusa. El s mbolo . separa el nombre del mdulo del de la funcin. Por supuesto o o hypot es el nombre de la funcin y () es el lugar para los argumentos. Una funcin podr o o a no tener argumentos, pero an as deben ir los parntesis, son obligatorios. Los nmeros 8,9 u e u son enviados a la funcin para que los procese. En el ejemplo, estos nmeros corresponden a o u los dos catetos de un tringulo rectngulo. a a En las secciones anteriores vimos funciones especializadas en el ingreso de strings y de nmeros. Nos referimos a input() para nmeros y a raw input() para strings. En este caso, u u input e raw input corresponden al nombre de las funciones, y entre los parntesis se acepta e un string como argumento, el cual es desplegado como prompt cuando se da el comando. Como vimos, este argumento es opcional en ambas funciones, sin embargo, lo incluyan o no, siempre se deben poner los parntesis. e a Funciones como input() y raw input() estn incorporadas al lenguaje y no necesitamos importar ningn mdulo para usarlas. u o
3.4.1.
float(obj) Convierte un string u otro nmero a un nmero de punto otante. Con u u decimales. int(obj) Convierte un string u otro nmero a un nmero entero. Sin decimales. u u long(obj) Convierte un string u otro nmero a un nmero entero largo. Sin decimales. u u str(num) Convierte un nmero a un string. u divmod(x,y) Devuelve los resultados de x/y y x %y. len(s) Retorna el largo de un string u otro tipo de dato (una lista o diccionario). pow(x,y) Retorna x a la potencia y. range(start,stop,step) Retorna un conjunto de nmeros desde start hasta stop, u con un paso igual a step. round(x,n) Retorna el valor del punto otante x redondeado a n digitos despus del e punto decimal. Si n es omitido el valor por defecto es cero.
60
3.4.2.
acos(x), asin(x), atan(x) El arcocoseno, el arcoseno y la arcotangente de un nmeu ro. cos(x), sin(x), tan(x) El coseno, el seno y la tangente de un nmero. u log(x), log10(x) El logaritmo natural y el logaritmo en base 10 de un nmero. u pow(x,y) Retorna x a la potencia y. hypot(x,y) Retorna el largo de la hipotenusa de un tringulo rectngulo de catetos x a a e y.
3.4.3.
capitalize(string) Pone en mayscula la primera letra de la primera palabra. u capwords(string) Pone en mayscula la primera letra de todas las palabras. u lower(string) Todas las letras en minsculas. u upper(string) Todas las letras en maysculas. u replace(string,old,new) reemplaza todas las palabras old en string por las palabras new. center(string, width) Centra el string en un campo de un ancho dado por width. rjust(string, width) Justica a la derecha el string en un campo de un ancho dado por width. ljust(string, width) Justica a la izquierda el string en un campo de un ancho dado por width.
3.4.4.
randrange(start, stop, step) Da un nmero al azar entre el nmero start y el u u nmero stop. El nmero step es opcional. u u choice(sequence) Elige al azar un objeto que pertenece a la sequencia sequence (una lista). Por ejemplo sequence=["a", "b", "c", "d", "e"].
3.4.5.
Una funcin del mdulo time: o o sleep(x) El computador queda en pausa por x segundos. Un par de funciones del mdulo calendar: o
3.5. FUNCIONES HECHAS EN CASA. prcal(year) Imprime un calendario para el ao year. n prmoth(year, month) Imprime un calendario para el mes month del ao year. n
61
3.5.
Una funcin dene un conjunto de instrucciones. A menudo son almacenadas en conjuntos o llamados mdulos. Pueden o no necesitar argumentos. Pueden o no retornar un valor al o programa.
3.5.1.
Para crear una funcin primero hay que denir la funcin, darle un nombre y escribir el o o conjunto de instrucciones que la constituyen. La funcin realizar las instrucciones cuando o a es llamada. Despus, en el programa, llame la funcin que ya deni. A continuacin veamos e o o o la denicin formal de una funcin hecha por nosotros o o def nombre(argumentos): comandos Comenzamos con la palabra def, la cual es un palabra requerida. Debe ir en minsculas. u Luego nombre es el nombre que uno le da a la funcin. Despus vienes los argumentos o e (argumentos) que corresponden a las variables que se le pasan a la funcin para que las o utilice. Finalmente, :, requeridos al nal de la l nea que dene una funcin. El bloque de o commandos asociados a la funcin deben tener sangr para identicarlos como parte de la o a misma. A continuacin, un ejemplo concreto: o # Definiendo la funcion def mi_function(): print "Nos gusta mucho la Fisica" # Usando la funcion mi_function() La denicin de una funcin puede ser en cualquier parte del programa con la salvedad o o que debe ser antes de que la funcin misma sea llamada. Una vez denida la funcin ellas se o o ejecutarn cuando sean llamadas. Cuando enviamos valores a nuestras funciones se crean las a variables nombradas en la denicin. Por ejemplo: o def mi_function(nombre1, nombre2): print nombre1+nombre2 Los nombres de las variables slo sern vlidos dentro de la funcin (es decir, las variables o a a o son locales). Las funciones usan variables locales.
62
3.5.2.
Variables globales.
Si desea asignar una variable denida fuera de la funcin en la funcin, tiene que utilizar o o la sentencia global. Esta se emplea para declarar que la variable es global es decir que no es local. Puede utilizar los valores de las variables denidas fuera de la funcin (y no hay variables o con el mismo nombre dentro de la misma). Sin embargo, esto es inapropiado y debe ser evitado puesto que llega a ser confuso al lector del programa, en cuanto a donde se ha realizado dicha denicin de variables. Usando la sentencia global queda claro que la variable se dene en o un bloque externo. #!/usr/bin/python def func(): global x print x es, x x = 2 print x cambiada a, x #main x = 50 func() print El valor de x es, x La salida del programa x es 50 Cambiada a 2 El valor de x es 2
3.5.3.
Para enviar los valores a nuestra funcin ponga los valores en la llamada de la funcin. El o o tipo de los valores debe estar de acuerdo con lo que la funcin espera. Las funciones pueden o tomar variables u otras funciones como argumentos. Veamos un ejemplo: def mi_function(nombre1, nombre2): print nombre1,nombre2 mi_function("azul","rojo")
3.5.4.
En algunas funciones, se puede hacer que el uso de algunos parmetros sean opcionales a y usar valores predeterminados si el usuario no desea proporcionarlos (los valores de dichos parmetros). Esto se hace con la ayuda de valores pre-denidos. Puedes especicar los valores a por defecto despus del nombre del parmetro en la denicin de la funcin con el operador e a o o de asignacin (=) seguido por el argumento a denir. o
3.6. ARGUMENTOS CLAVES. #!/usr/bin/python def say(s, times = 1): print s * times say(Hola) say(Mundo, 5) Salida del programa Hola MundoMundoMundoMundoMundo
63
Solamente los parmetros que estn en el extremo de la lista de parmetros pueden tener a a a valores por defecto; es decir, no puedes tener un parmetro con un valor por defecto antes a de uno sin un valor, en el orden de los parmetros declarados, en la lista del parmetro de la a a funcin. Esto se debe a que los valores son asignados a los parmetros por la posicin. Por o a o ejemplo def func(a, b=5) es vlido, pero def func(a=5, b) no lo es a
3.6.
Argumentos Claves.
Si se tiene funciones con muchos parmetros y se quiere especicar solamente algunos de a ellos, entonces se puede asignar los valores para tales parmetros con solo nombrarlos, a esto a se denomina argumentos claves. Utilizamos el nombre en vez de la posicin que se ha estado o utilizando. Esto tiene dos ventajas: la primera, es que usar la funcin es ms fcil puesto que o a a no se necesita preocuparnos del orden de los argumentos. La segunda, es que podemos dar valores solamente a los parmetros que deseamos, a condicin de que los otros tengan valores a o por defecto. Usando Argumentos Claves #!/usr/bin/python def func(a, b=5, c=10): print a es, a, y b es, b, y c es, c func(3, 7) func(25, c=24) func(c=50, a=100) La salida es: a es 3 y b es 7 y c es 10 a es 25 y b es 5 y c es 24 a es 100 y b es 5 y c es 50
64
3.7.
DocStrings.
Python tiene una caracter stica interesante llamada cadenas de documentacin que geo neralmente son llamadas por su nombre corto: docstrings. DocStrings es una herramienta importante de la que se puede hacer uso puesto que ayuda a documentar mejor el programa. Podemos incluso ubicar docstring en una funcin a tiempo de ejecucin, es decir cuando el o o programa est funcionando. Usando DocStrings a #!/usr/bin/python def printMax(x, y): Imprime el maximo de 2 numeros. Los dos valores deben ser enteros. Si hubieran decimales, son convertidos a enteros. x = int(x) # Convierte a enteros, si es posible y = int(y) if x > y: print x, es maximo else: print y, es maximo printMax(3, 5) print printMax.__doc__ La salida 5 es maximo Imprime el maximo de 2 numeros. Los dos valores deben ser enteros. Si hubieran decimales, son convertidos a enteros.
3.7.1.
El comando return termina la ejecucin de una funcin. Un ejemplo o o import math def raiz(num): if num<0: print "Ingrese un numero positivo" return print math.sqrt(num)
3.7. DOCSTRINGS.
65
Los condicionales como el if son especialmente util para atrapar y manejar errores. Use el else para atrapar el error cuando la condicin no es satisfecha. o Los if pueden ser anidados. Sea cuidadoso, ya que la anidacin puede producir confusin o o y deber ser usada con moderacin y mesura. a o
3.7.2.
Podemos crear funciones que retornen un valor al programa que las llam. Por ejemplo o def sumalos(x,y): new = x+y return new # Llamada a la funcion sum = sumalos(5,6)
3.7.3.
Recursin. o
Se llama recursin cuando una funcin se llama a si misma. La recursin permite repetir o o o el uso de una funcin incluso dentro de la misma funcin. Un ejemplo es o o def count(x): x=x+1 print x count(x) Si la funcin nunca para, esta recursin es llamada recursin innita. Para prevenir este o o o situacin creamos un caso base. El caso base es la condicin que causar que la funcin pare o o a o de llamarse a si misma. Un ejemplo def count(x): if x<100: x=x+1 print x count(x) else: return time.sleep(1) Un programa que calcula el factorial de un nmero en forma recursiva u #!/usr/bin/env python def fact(n): if n<2: return 1 else:
66
3.8.
Python puede recibir parmetros directamente de la l a nea de comando. La lista sys.argv los contiene. Supongamos que el programa se llama main.py y es como sigue: #!/usr/bin/python import sys for i in sys.argv: print i print sys.argv[0] Si ejecutamos el programa con la l nea de comando jrogan@huelen:~$ ./main.py h -l --mas xvzf La salida ser a ./main.py h -l --mas xvzf ./main.py Otro ejemplo, un programa que suma dos nmeros desde la l u nea de comando, #!/usr/bin/python import sys if len(sys.argv)>2): n1=float(sys.argv[1]) n2=float(sys.argv[2]) print n1+n2 else: pass Si ejecutamos el programa con la l nea de comando jrogan@huelen:~$ suma.py 1.2 3.5 La salida ser a 4.7 Si se llama el programa con menos argumentos, el programa no har nada. a
67
3.9.
La palabra reservada while puede ser usada para crear una iteracin. La instruccin o o while necesita un contador que se incremente. Ejemplo while x < 10: print x x = x+1 Para hacer una seccin de cdigo reusable, en vez de usar valores contantes use variables. o o Primero un ejemplo no generalizado while x < 12: print 2*x x = x+1 Ahora el mismo ejemplo generalizado while x < max_num: print num*x x = x+1 Utilicemos la instruccin while para hacer una salida ordenada para un programa. El o cdigo de escape del tabulador (\t) en un string permite hacer tabulaciones. Los tabuladores o mantienen los items alineados dando una salida ordenada. Ejemplo, en este caso combinando la instruccin while y el cdigo de escape del tabulador haremos una tabla: o o while x < 10: print item1, "\t", item2 x = x+1
3.10.
Los strings.
Los strings son hechos de pequeas unidades, cada caracter individual. Cada uno de los n caracteres tiene una direccin numrica dentro del string, donde el primer caracter tiene la o e direccin cero (0). Cada caracter individual, o conjunto de caracteres, en un string puede ser o acccesado usando sus direcciones numricas. Use [ ] para accesar caracteres dentro de un e string. Veamos un ejemplo palabra = "computador" letra = palabra[0] Para acceder un conjunto de caracteres dentro de un string lo podemos hacer como sigue: Use [#:#] para obtener un conjunto de letras. parte = palabra[1:3] Para tomar desde el comienzo a un punto dado en el string. parte = palabra[:4] Para tomar desde un punto dado al nal del string. parte = palabra[3:]
68
3.10.1.
Indice negativos.
Veamos que pasa cuando usamos ndices negativos >>> a="hola" >>> a[0] h >>> a[-1] a >>> a[-2] l >>> a[-3] o >>> a[-4] h >>> a[-5] Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: string index out of range
3.10.2.
Para encontrar cuntos caracteres tiene un string usamos la funcin len(string). La a o funcin len requiere un string como argumento. Un ejemplo: o palabra = "computador" largo = len(palabra)
3.10.3.
Recorriendo un string.
Uno puede desear hacer una prueba sobre cada una de las letras que componen el string todas de una vez. Hay dos maneras de hacer esto usando una instruccin while o una o instruccin for para realizar el ciclo o loop. Primero veamos el ciclo con while: o palabra = "computador" indice = 0 while indice < len(palabra): letra = palabra[indice] print letra indice=indice +1
3.10.4.
El ciclo for.
Una manera ms compacta de escribir el ciclo while anterior es usando un ciclo for, a veamos cmo queda el cdigo o o
69
Notemos que hemos creado la variable letra cuando creamos el ciclo for. A continuacin, o un ejemplo ms completo del ciclo for: a #!/usr/bin/env python # -*- coding: iso-8859-1 -*# Programa que cuenta vocales import string palabra = raw_input("Entre una palabra : ") palabra_min = string.lower(palabra) vocales="aeiou" aeou contador = 0 for letra in palabra_min: if letra in vocales: contador=contador +1 else: pass print "El nmero de vocales en la palabra que ingres fueron : ", contador u o Notemos la segunda l nea de este programa que nos permite ingresar e imprimir strings con caracteres acentuados y caracteres especiales.
3.10.5.
Comparando strings.
Los strings pueden ser usados en comparaciones. Ejemplo if palabra < "cebu": print palabra De acuerdo a Python, todas las letras maysculas son mayores que las letras minsculas. u u As a>Z. Una buena idea es convertir todos los strings a mayscula o minscula, segn sea el caso, u u u antes de hacer comparaciones. Recordemos que el mdulo string contiene varias funciones o utiles incluyendo: lower(string), upper(string) y replace(string,string,string). Re vise la documentacin. o
3.11.
Listas.
Una lista es un conjunto ordenado de elementos. Las listas estn encerradas entre parntea e sis [ ]. Cada item en una lista est separado por una coma. Veamos ejemplos de listas a
70
mascotas = ["perros", "gatos", "canarios", "elefantes"] numeros = [1,2,3,4,5,6] cosas = [ 1, 15, "gorila", 23.9, "alfabeto"] Un elemento de una lista puede ser otra lista. Una lista dentro de otra lista es llamada lista anidada. A continuacin un ejemplo de listas anidadas o para_hacer = ["limpiar", ["comida perro", "comida gato","comida pez"], "cena"]
3.11.1.
Rebanando listas.
Una lista puede ser accesada al igual que un string usando el operador [ ]. Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> print lista[0] Pedro >>> print lista[1:] [Andres, Jaime, Juan] Para accesar un item en una lista anidada hay que proveer dos ndices. Ejemplo >>> lista_palabras = ["perro", ["fluffy", "mancha", "toto"], "gato"] >>> print lista_palabras[1][2] toto
3.11.2.
Mutabilidad.
A diferencia de los strings las listas son mutables, lo que signica que se pueden cambiar. Ejemplo >>> string = "perro" >>> string [2] = "d" # Traceback (most recent File "<stdin>", line TypeError: object does En cambio en una lista >>> lista = ["p", "e", "r", "r", "o"] >>> lista [2] = "d" >>> print lista [p, e, d, r, o] Como se muestra en la comparacin anterior una lista puede ser cambiada usando el o operador [ ]. Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> lista[0]="Matias" >>> print lista [Pedro, Andres, Jaime, Juan, Matias] Esta NO es un instruccion VALIDA call last): 1, in ? not support item assignment
3.11. LISTAS.
71
3.11.3.
Para agregar items al nal de una lista use list.append(item). Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> lista.append("Matias") >>> print lista [Pedro, Andres, Jaime, Juan, Matias]
3.11.4.
las listas se pueden sumar resultando una solo lista que incluye ambas lista iniciales. Adems, podemos multiplicar una lista por un entero n obteniendo una lista con n replicas a de la lista inicial. Veamos ejemplos de ambas operaciones en forma interactiva >>> lista1=["Pedro", "Andres", "Jaime", "Juan"] >>> lista2=["gato", 2] >>> print lista1+lista2 [Pedro, Andres, Jaime, Juan, gato, 2] >>> print lista2*2 [gato, 2, gato, 2] >>> print 2*lista2 [gato, 2, gato, 2]
3.11.5.
Use el comando del para remover items basado en el ndice de posicin. Ejemplo en forma o interactivo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> del lista[1] >>> print lista [Pedro, Jaime, Juan] Para remover items desde una lista sin usar el ndice de posicin, use el siguiente comano do nombre_lista.remove("item") que borra la primera aparicin del item en la lista. Un o ejemplo interactivo >>> jovenes = ["Pancho", "Sole", "Jimmy", "Pancho"] >>> jovenes.remove("Pancho") >>> print jovenes [Sole, Jimmy, Pancho]
3.11.6.
Con la palabra reservada in podemos preguntar si un item est en la lista, veamos un a ejemplo
72
lista = ["rojo", "naranjo", "verde", "azul"] if "rojo" in lista: haga_algo() La palabra clave not puede ser combinada con in para hacer la pregunta contraria, es decir, si un item no est en un lista. Veamos un ejemplo a lista = ["rojo", "naranjo", "verde", "azul"] if "purpura" not in lista: haga_algo()
3.11.7.
Los ciclos for pueden ser usados con listas de la misma manera que lo eran con strings, un ejemplo para mostrarlo email = ["oto@mail.com", "ana@mail.com"] for item in email: envie_mail(item)
3.11.8.
len(list_name) Da el largo de la lista, su nmero de elementos. u list_name.sort() Pone la lista en orden alfabtico y numrico. e e random.choice(list_name) Escoge un elemento al azar de la lista. string.split(list_name) Convierte un string, como una frase, en una lista de palabras. string.join(list_name) Convierte una lista de palabras en una frase dentro de un string.
3.11.9.
La funcin range(num_init, num_fin, num_paso) toma tres argumentos enteros, el o nmero de partida, el numero nal y el paso, para generar una lista de enteros que comienu za en el nmero de partida, termina con un nmero menor que el nal saltandose el paso u u sealado, si se omite el paso el salto ser de uno en uno. Veamos ejemplos n a range(10) = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range(2,10) = [2, 3, 4, 5, 6, 7, 8, 9] range(0,11,2) = [0, 2, 4, 6, 8, 10]
3.12. TUPLAS.
73
3.12.
Tuplas.
Una tupla es una lista inmutable. Una tupla no puede modicarse de ningn modo despus u e de su creacin. o >>> t = ("a", "b", 8) >>> t[0] a Una tupla se dene del mismo modo que una lista, salvo que el conjunto se encierra entre parntesis ( ), en lugar de entre corchetes [ ]. Los elementos de la tupla tienen un orden e denido, como los de la lista. Las tuplas tienen primer ndice 0, como las listas, de modo que el primer elemento de una tupla t, no vac es siempre t[0]. Los a ndices negativos cuentan desde el nal de la tupla, como en las listas. Las porciones funcionan como en las listas. Advierta que al extraer una porcin de una lista, se obtiene una nueva lista; al extraerla o de una tupla, se obtiene una nueva tupla. No hay mtodos asociados a tuplas ( tal como e append() en una lista). No pueden aadirse elementos a una tupla, no pueden eliminarse elementos de una tupla, n no pueden buscarse elementos en una tupla, se puede usar in para ver si un elelmento existe en la tupla. Las tuplas son ms rpidas que las listas. Si est deniendo un conjunto constante de a a a valores y todo lo que va ha hacer con l es recorrerlo, utilice una tupla en lugar de una e lista. Una tupla puede utilizarse como clave en un diccionario, pero las listas no. Las tuplas pueden convertirse en listas y vice versa. La funcin incorporada tuple(lista) toma una o lista y devuelve una tupla con los mismos elementos. La funcin list(tupla) toma una o tupla y devuelve una lista.
3.13.
El comando break.
El comando break es capaz de salirse de un ciclo for o while. Un ciclo puede tener una seccin else esta es ejecutada cuando el ciclo termina por haber agotado la lista en un ciclo o for o cuando la comparacin llega a ser falsa en un ciclo while, pero no cuando el ciclo o es ternimado con break. A continuacin, un programa que muestra este hecho y sirve para o encontrar nmeros primos u for n in range(2,10): for x in range(2,n): if n % x ==0: print n, "igual a", x,"*", n/x break else: print n,"es un numero primo"
74
3.14.
El lenguaje Python puede ser usado para crear programas que manipulan archivos sobre un sistema de archivos en un computador. El mdulo os contiene las funciones necesarias o para buscar, listar, renombrar y borrar archivos. El mdulo os.path contiene unas pocas o funciones especializadas para manipular archivos. Las funciones necesarias para abrir, leer y escribir archivos son funciones intr nsecas de Python.
3.14.1.
Funciones que slo dan una mirada. o getcwd() Retorna el nombre el directorio actual. listdir(path) Retorna una lista de todos los archivos en un directorio. chdir(path) Cambia de directorio. Mueve el foco a un directorio diferente. Funcin que ejecuta un comando del sistema operativo. o system(comando) Ejecuta el comando Funciones que agregan. mkdir(path) Hace un nuevo directorio con el nombre dado. mkdirs(path) Hace un subdirectorio y todos los directorios del path requeridos. Funciones que borran o remueven. remove(path) Borra un archivo. rmdir(path) Borra un directorio vac o. removedirs(path) Borra un directorio y todo dentro de l. e Funciones que cambian. rename(viejo,nuevo) Cambia el nombre de un archivo de viejo a nuevo renames(viejo,nuevo) Cambia el nombre de un archivo de viejo a nuevo cambiando los nombres de los directorios cuando es necesario.
3.14.2.
Funciones que verican. exists(file) Retorna un booleano si el archivo file existe. isdir(path) Retorna un booleano si el path es un directorio. isfile(file) Retorna un booleano si el file es un archivo.
75
3.14.3.
Ejemplo de un cdigo. o
Un programa que borra todo un directorio import os, os.path path = raw_input("Directorio a limpiar : ") os.chdir(path) files= os.listdir(path) print files for file in files: if os.path.isfile(file): os.remove(file) print "borrando", file elif os.path.isdir(file): os.removedirs(file) print "removiendo", file else: pass
3.14.4.
Abriendo un archivo.
Para abrir un archivos debemos dar la instruccin open(filename,mode) donde filename o es el nombre del archivo y el mode corresponde a una de tres letras "r" para lectura solamente del archivo, "w" para escritura y "a" para agregar al nal del archivo. para poder manejar un archivo abierto hay que crear una variable con l. Ejemplo e salida= open("datos.txt","w") salidaAppend= open("programa.log","a") entrada= open("archivo.txt","r")
3.14.5.
Leyendo un archivo.
entrada.read() Lee el archivo completo como un string. entrada.readline() Lee una l nea en un string. entrada.readlines() Lee el archivo completo, cada l nea llega a ser un item tipo string en una lista.
3.14.6.
Escribiendo a un archivo.
salida.write(string) Escribe el string al archivo. Cmo se escribira este depende o de en qu modo el archivo fue abierto. e salida.writelines(list) Escribe todos los items tipo string en la lista list. Cada elemento en la lista estar en la misma l a nea a menos que un elemento contenga una caracter de newline
76
Si queremos usar la instruccion print para escribir sobre un archivo abierto, digamos salida, podemos usar la instruccin o salida = open("resultados.txt", "w") print >> salida, datos # Imprime datos en el archivo datos.txt print >> salida # Imprime una linea en blanco en el archivo datos.txt salida.close()
3.14.7.
Cerrando un archivo.
3.14.8.
Archivos temporales.
Las funciones en el mdulo tempfile puede ser usadas para crear y manejar archivos o temporales. La instruccin tempfile.mkstemp() devuelve una lista en el que el segundo o item es un nombre al azar que no ha sido usado. Los archivos temporales estarn localizados a en el directorio temporal por defecto.
3.14.9.
# Programa que reemplaza una palabra vieja por otra nueva import string, tempfile, os # Preguntarle al usuario por Informacion filename = raw_input("Nombre del archivo: ") find = raw_input("Busque por: ") replace = raw_input("Reemplacelo por: ") # Abra el archivo del usuario, lealo y cierrelo file = open(filename, "r") text = file.readlines() file.close() # Edite la informacion del archivo del usuario nueva = [] for item in text: line = string.replace(item, find, replace) nueva.append(line) # Cree un nuevo archivo temporal newname=tempfile.mkstemp() temp_filename=newname[1] newfile = open(temp_filename, "w") newfile.writelines(nueva)
3.15. EXCEPCIONES. newfile.close() # Cambie los nombres de los archivos y borra los temporales oldfile=filename+"~" os.rename(filename, oldfile) os.system(" cp "+temp_filename+" "+filename) os.remove(temp_filename)
77
3.15.
Excepciones.
Las palabras reservadas try y except pueden ser usadas para atrapar errores de ejecucin o en el cdigo. Primero en el bloque try se ejecutan un grupo de instrucciones o alguna funcin. o o Si estas fallan o devuelven un error, el bloque de comandos encabezados por except se ejecutar. Lo anterior, puede ser usado para manejar programas que pueden fallar bajo a alguna circunstancia de una forma muy elegante. # Sample Try / Except def open_file(): filename = raw_input("Entre el nombre del archivo: ") try: file = open(filename) except: print "Archivo no encontrado." open_file() return file
3.16.
Diccionarios.
Las listas son colecciones de items (strings, nmeros o incluso otras listas). Cada item en u la lista tiene un ndice asignado. >>> lista >>> print primero >>> print segundo >>> print tercero = ["primero", "segundo", "tercero"] lista[0] lista[1] lista[2]
Para acceder a un valor de la lista uno debe saber su ndice de posicin. Si uno remueve o un item desde la lista, el ndice puede cambiar por el de otro item en la lista. Un diccionario es una coleccin de items que tiene una llave y un valor. Ellos son parecidos o a las listas, excepto que en vez de tener asignado un ndice uno crea los ndices. lista = ["primero", "segundo", "tercero"] diccionario = {0:"primero", 1:"segundo", 2:"tercero"}
78
Para crear un diccionario debemos encerrar los item entre parntesis de llave {}. Debemos e proveer una llave y un valor, un signo : se ubica entre la llave y el valor (llave:valor). cada llave debe ser unica. Cada par llave:valor est separado por una coma. Veamos un a par de ejemplos con diccionarios ingles = {one:uno, two:dos} Uno en japons e nihon_go = {} nihon_go["ichi"] = "uno" nihon_go["ni"] = "dos" nihon_go["san"] = "tres" print nihon_go { ichi:uno, ni:dos, san:tres} Para acceder el valor de un item de un diccionario uno debe entrar la llave. Los diccionarios slo trabajan en una direccin. Uno debe dar la llave y le devolvern el valor. Uno no puede o o a dar el valor y que le devuelvan la llave. Ejemplo nihon_go = { ichi:uno, ni:dos, san:tres} print nihon_go[ichi] uno Notemos que este diccionario traduce del japons al espaol pero no del espaol al japons. e n n e
3.16.1.
Editando un diccionario.
Para cambiar un valor de un par, simplemente reas gnelo nihon_go["ichi"]=1 Para agregar un par valor:llave, ntrelo e nihon_go["shi"]=cuatro Para remover un par use del del nihon_go["ichi"] Para ver si una llave ya existe, use la funcin has_key() o nihon_go.has_key("ichi") Para copiar el diccionario entero use la funcin o mtodo copy(). o e japones= nihon_go.copy() Los diccionarios son mutables. Uno no tiene que reasignar el diccionario para hacer cambios en l. e Los diccionarios son utiles cada vez que usted tiene items que desea ligar juntos. Tambin e son utiles haciendo subtituciones (reemplace todos los x por y). Almacenando resultados para una inspeccin rpida. Haciendo mens para programas. Creando mini bases de datos o a u de informacin. o
79
3.16.2.
import string def add(num1,num2): print num1+num2 def mult(num1,num2): print num1*num2 # Programa num1 = input("Entre el primer numero: ") num2 = input("Entre el segundo numero: ") menu = {S:add, M:mult} print "[S] para sumar, [M] para multiplicar: " choice = string.upper(raw_input()) menu[choice] (num1,num2)
3.16.3.
Si un parmetro formal de la forma **name est presente, la funcin recibe un diccionario. a a o Si un parmetro formal de la forma *name est presente, la funcin recibe una tupla. Los a a o parmetros formales *name deben ir antes que los **name. Ejemplo a def funcion(*mi_tupla, **nihon_go): ..
3.17.
Modules y Shelve.
Algunos problemas que se presentan a medida que los cdigos crecen son: con cientos o de l neas es muy fcil perderse; trabaja en equipo se hace dif con cdigos muy grandes. a cil o Entonces, ser bueno poder separar el cdigo en pequeos archivos independientes. Por otra a o n parte, se nos presenta otra dicultad, no podemos salvar estructuras de datos, es decir, si creamos un diccionario, sabemos como salvarlo como un archivo de texto, pero no podemos leerlo como un diccionario. Ser bueno poder salvar las listas como listas, los diccionarios a como diccionarios y as luego poder leerlos e incorporarlos a nuestro cdigo en forma fcil. o a
3.17.1.
Partiendo el cdigo. o
El cdigo puede ser dividido en archivos separados llamados modules. Ya hemos usado o varios de estos mdulos trabajando en Python (string, math, random, etc.). Para crear un o mdulo slo tipee su cdigo Python y slvelo de la manera usual. Su mdulo salvado puede o o o a o ser importado y usado tal como cualquier otro mdulo de Python. o
3.17.2.
Creando un mdulo. o
Lo principal para almacenar nuestro cdigo en un mdulo es escribir cdigo reusable. El o o o cdigo debe ser principalmente funciones y clases. Evite tener variables o comandos fuera de o
80
la denicin de funciones. Las funciones pueden requerir valores desde el programa quien las o llama. Salve el cdigo como un archivo regular .py. Luego en el programa principal, importe o el mdulo y uselo. o
3.17.3.
Cuando Python busca mdulos slo lo hace en ciertos directorios. La mayor de los o o a mdulos que vienen con Python son salvados en /usr/lib/python. Cuando salve sus proo pios mdulos seguramente lo har en un lugar diferente, luego es necesario agregar el nuevo o a directorio a sys.path. Hay que consignar que el directorio desde el cual se invoca Python, si est en el path. Para editar el sys.path, en el modo interactivo tipee a >>> import sys >>> sys.path #imprime los actuales directorios en el path >>> sys.path.append(/home/usuario/mis_modulos) Dentro de un script usamos para importar mi mdulos mis_funciones que est salvado en o a mi directorio de mdulos o import sys sys.path.append(/home/usuario/mis_modulos) import mis_funciones
3.17.4.
Como ya vimos los comentarios con triple comilla son usados para agregar documentacin o al cdigo, ejemplo o def mi_funcion(x,y): """mi_funcion( primer nombre, ultimo nombre) """ Use al principio y al nal triple comilla. El texto en triple comilla deber explicar lo que a la funcin, clase o mdulo hace. Estas l o o neas de documentacin las podr ver, en el modo o e interactivo, si da el comando help(module.mi_funcion).
3.17.5.
Usando un mdulo. o
En el programa principal incluya el comando import y el nombre del mdulo. Cuando o llame a una funcin del mdulo debe incluir el nombre del mdulo . el nombre de la funcin, o o o o esta no es la unica manera de importarlos, veamos unos ejemplo, primero la forma habitual: # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff import stuff print stuff.f(1,2) print stuff.C(1).m(2)
81
# Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff from stuff import f, C print f(1,2) print C(1).m(2) una tercera forma # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff from stuff import * print f(1,2) print C(1).m(2) una ultima manera # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff import stuff as st print st.f(1,2) print st.C(1).m(2)
3.17.6.
Un mdulo puede ser corrido como programa independiente si inclu o mos las siguientes l neas en el nal if __name__ == __main__: funcion_a_correr() Sustituya funcion_a_correr() por el nombre de la funcin principal en el mdulo. o o
3.17.7.
Existen dos mtodos de preservar la data: e El mdulo pickle almacena una estructura de datos de Python en un archivo binario. o Est limitado a slo una estructura de datos por archivo. a o El mdulo shelve almacena estructuras de datos de Python pero permite ms de una o a estructura de datos y puede ser indexado por una llave.
3.17.8.
Cmo almacenar? o
Importe el mdulo shelve, abra un archivo shelve, asigne un item, por llave, al archivo o shelve. Para traer la data de vuelta al programa, abra el archivo shelve y accese el item por llave. Los shelve trabajan como un diccionario, podemos agregar, accesar y borrar items usando sus llaves.
82
3.17.9.
Ejemplo de shelve.
import shelve colores = ["verde", "rojo", "azul"] equipos = ["audax", "union", "lachile"] shelf = shelve.open(mi_archivo) # Almacenendo items shelf[colores] = colores shelf[equipos] = equipos # trayendolos de vuelta newlist = shelf[colores] # Cerrando shelf.close()
3.17.10.
Para tomar una lista de todas las llaves disponibles en un archivo shelve, use la funcin o keys(): lista = shelf.keys() Para borrar un item, use la funcin del: o del shelf(ST) Para ver si una llave existe, use la funcin has_key(): o if shelf.has_key(ST): print "si"
3.18.
Clases y mtodos. e
Las clases son colecciones de data y funciones que pueden ser usadas una y otra vez. Para crear una clase parta con la palabra reservada class, luego necesita un nombre para la clase. Los nombres de las clases, por convencin, tiene la primera letra en mayscula. Despus del o u e nombre termine la l nea con un : y entonces cree el cuerpo de la clase, las instrucciones que forman el cuerpo deben ir con sangr En el cuerpo cree las deniciones de las funciones, a. cada funcin debe tomar self como parmetro. o a class MiClase: def hola(self): print "Bienvenido. " def math(self,v1,v2): print v1+v2 Declarando y luego usando la clase class MiClase: def hola(self): print "Bienvenido. " def math(self,v1,v2):
83
Creamos una instancia de una clase al asignarla a una variable, fred = MiClase(). Para aplicar una funcin o mtodo a una nueva instancia debemos especicar en forma completa o e la instancia y el mtodo fred.hola(). Si el mtodo toma argumentos debemos estar seguro e e de incluir todos los valores necesitados, por ejemplo fred.math(2,4).
3.18.1.
class LibretaNotas: def __init__(self, name, value): self.nombre = name self.puntaje = value self.evaluaciones = 1 def sumanota(self, puntos): self.evaluaciones += 1 self.puntaje += puntos self.promedio = self.puntaje/float(self.evaluaciones) def promedio(self) print self.nombre, ": promedio =", self.promedio Las variables dentro de una clase deben ser accesadas poniendo el prejo a su nombre la palabra self. La funcin __init__ es la que correr si una nueva instancia de la clase es creada. Esta o a funcin es especial y se conoce como el constructor de la clase. o Usando la clase LibretaNotas eli = LibretaNota(Elizabeth, 6.5) mario = LibretaNota(Mario, 6.0) carmen = LibretaNota(Carmen, 6.1) eli.sumanota(6.2) mario.sumanota(6.1) carmen.sumanota(6.3) eli.sumanota(6.8) mario.sumanota(6.7) carmen.sumanota(6.6) eli.promedio() mario.promedio() carmen.promedio()
84
Cada nueva instancia de la clase LibretaNotas debe tener un nombre y una primera nota porque as lo requiere la funcin constructor __init__. Notemos que cada instancia tiene su o propio promedio.
3.18.2.
Una funcin puede tener valores por defecto, estos valores son usados slo cuando la o o funcin es llamada sin especicar un valor. Ejemplo o def potencia(voltaje, corriente=0): return voltaje*corriente # Podemos llamarla potencia(220) potencia(voltaje=110, corriente=5) Veamos un ejemplo de valores por defecto en una clase class Dinero: def __init__(self, amount = 0) : self.amount=amount def print(self): print "Tienes", self.amount, "de dinero" # Llamadas posibles mi_dinero = Dinero(100) tu_dinero = Dinero() mi_dinero.print() tu_dinero.print()
3.19.
Sobrecarga de Operadores.
Las clases pueden redenir comandos regulares de Python. Cambiar como los comandos regulares trabajan en una clase se llama sobrecarga de operadores. Para denir la sobrecarga, debemos usar nombres especiales cuando denimos los mtodos. Las deniciones sobrecargae das deben retornar un valor. Veamos un ejemplo de sobrecarga class Loca: def __init__(self, num1=2): self.num1=num1 def __del__(self): print "%d Destruido!" % self.num1 def __repr__(self): return "Su numero es %d" % self.num1 def __add__(self, newnum): return newnum*self.num1
85
Notemos que tenemos un mtodo nuevo el destructor que el la funcin que se invoca cuane o do una variable se destruye. A continuacin, una lista de nombre especiales para sobrecargar o los operadores __add__ La suma +. __sub__ La resta . __mul__ La multiplicacin . o __div__ La divisin /. o __pow__ La exponenciacin . o __repr__ El comando print. __len__ El comando len(x). __call__ El comando de llamada x(). __init__ El mtodo constructor. e __del__ El mtodo destructor. e
3.19.1.
Funcin driver. o
Una funcin driver es puesta al nal de la clase para probarla. La funcin toma la forma o o if __name__ == __main__: funcion_a_correr() Cuando una clase o mdulo es llamado como programa principal, correr este cdigo. o a o
3.19.2.
La informacin que necesita acceder una clase en cada una de sus instancias u objetos o puede ser almacenada en atributos de la clase. Los valores sern creados fuera de las dea niciones de las funciones de la clase. La data ser accesada dentro de las denicin de las a o funciones o mtodos de la clase usando la notacin NombredelaClase.NombredelaVariable. e o Un ejemplo class Cuentas: alumnos=[] def __init__(self,nombre): self.nombre=nombre Cuentas.alumnos.append(self.nombre) def __del__(self) Cuentas.alumnos.remove(self.nombre) Notese que la lista de alumnos es siempre llamada por su nombre completo Cuentas.alumnos. Para acceder a la lista fuera de la clase, use su nombre completo Cuentas.alumnos.
86
3.19.3.
Escribamso un mdulo vec2d.py con una clase de vectores bidimensionales sobrecargando o la suma, la resta, el producto, la impresin, entre otros mtodos o e from math import sqrt class Vec2d: def __init__(self, x=0, y=0): self.x = x self.y = y def module(self): return sqrt(self.x**2+self.y**2) def __repr__(self): return "(%11.5f,%11.5f)" % (self.x,self.y) def __add__(self,newvec): return Vec2d(self.x+newvec.x,self.y+newvec.y) def __sub__(self,newvec): return Vec2d(self.x-newvec.x,self.y-newvec.y) def __mul__(self,newvec): return self.x*newvec.x+self.y*newvec.y Ahora un programa que ocupa el mdulo o #!/usr/bin/env python from vec2d import * a=Vec2d(1.3278,2.67) b=Vec2d(3.1,4.2) print print print print print a, b a+b a-b a*b a.module(),b.module()
3.20.
Hay muchos mdulos que le pueden ser utiles, aqu le sugerimos unos pocos particularo mente importantes.
3.20.1.
El mdulo Numeric. o
3.20. ALGUNOS MODULOS INTERESANTES. >>> import Numeric as num >>> a = num.zeros((3,2), num.Float) >>> a array([[ 0., 0.], [ 0., 0.], [ 0., 0.]]) >>> a[1]=1 >>> a array([[ 0., 0.], [ 1., 1.], [ 0., 0.]]) >>> a[0][1]=3 >>> a array([[ 0., 3.], [ 1., 1.], [ 0., 0.]]) >>> a.shape (3, 2)
87
3.20.2.
El mdulo Tkinter. o
Un mdulo para escribir aplicaciones grcas portables con Phyton y Tk. o a #!/usr/bin/env python from Tkinter import * root = Tk() root.title("Mi ventana") btn = Button(root, text="Salir") btn.grid() def stop(event): root.destroy() btn.bind(<Button-1>, stop) root.mainloop()
3.20.3.
El mdulo Visual. o
88
En este cap tulo se intentar dar los elementos bsicos del lenguaje de programacin a a o C++. No se pretende ms que satisfacer las m a nimas necesidades del curso, sirviendo como un ayuda de memoria de los tpicos abordados, para futura referencia. Se debe consignar que o no se consideran todas las posibilidades del lenguaje y las explicaciones estn reducidas al a m nimo.
4.1.
4.1.1.
El primer ejemplo de todo manual es el que permite escribir Hola en la pantalla. // // Los comentarios comienzan con // // #include <iostream> using namespace std; int main() { cout << "Hola." << endl; return 0 ; } Las tres primeras l neas corresponden a comentarios, todo lo que est a la derecha de a los caracteres // son comentarios y no sern considerados en la compilacin. En la l a o nea siguiente se incluye un archivo de cabecera, o header, con la instruccin de preprocesador o #include. El nombre del archivo se puede escribir como <nombre> o bien "nombre.h". En el primer caso el archivo nombre ser buscado en el path por defecto para los include, a t picamente /usr/include o /usr/include/c++/3.x/ en el caso de headers propios de C++; en el segundo caso la bsqueda se hace en el directorio local. Tambin podr u e amos incluir un path completo cuando se ocupan las comillas. En nuestro ejemplo se incluye el archivo iostream, en el cual se hacen las deniciones adecuadas para el manejo de la entrada y salida en C++. Este archivo es necesario para enviar luego un mensaje a pantalla. 89
90
La funcin int main es donde comienza a ejecutarse el programa; siempre debe haber una o funcin main en nuestro programa. Debido a imposiciones del sistema operativo la funcin o o main devuelve un entero y por tanto debe ser declarada int. Los parntesis vac () indican e os que el main no tiene argumentos de entrada (ms adelante se ver que puede tenerlos). Lo a a que est encerrado entre llaves {} corresponde al cuerpo de la funcin main. Cada una de a o las l neas termina con el carcter ;. El identicador predenido cout representa la salida a a pantalla. El operador << permite que lo que est a su derecha se le d salida por el dispositivo a e que est a su izquierda, en este caso cout. Si se quiere enviar ms de un objeto al dispositivo a a que est al inicio de la l a nea agregamos otro operador <<, y en este caso lo que est a la a derecha del operador se agregar a lo que est a la izquierda y todo junto ser enviado al a a a dispositivo. En nuestro caso se ha enviado endl, un objeto predenido en el archivo iostream que corresponde a un cambio de l nea, el cual ser agregado al nal del mensaje. La l a nea nal contiene la instruccin de retorno del entero cero, return 0. o Si escribimos nuestro primer programa en el editor xemacs con el nombre de primero.cc las instrucciones para editarlo, compilarlo y correrlo sern: a jrogan@pucon:~/tmp$ xemacs primero.cc jrogan@pucon:~/tmp$ g++ -Wall -o primero primero.cc jrogan@pucon:~/tmp$ ./primero Hola. jrogan@pucon:~/tmp$ Luego de la compilacin, un archivo ejecutable llamado primero es creado en el directoo rio actual. Si el directorio actual no est en el PATH, nuestro programa debe ser ejecutado a anteponiendo ./. Si est en el PATH, para ejecutarlo basta escribir primero. (Para agrea gar el directorio local al PATH basta editar el archivo ~/.bashrc agregarle una l nea como PATH="${PATH}:." y ejecutar en la l nea de comando source ~/.bashrc para que los cambios tengan efecto.)
4.1.2.
Denicin de funciones. o
Las funciones en C++ son muy importantes, pues permiten aislar parte del cdigo en o una entidad separada. Esto es un primer paso a la modularizacin de nuestro programa, o es decir, a la posibilidad de escribirlo en partes que puedan ser editadas de modo lo ms a independiente posible. Ello facilita enormemente la creacin de cdigo complicado, pues simo o plica su modicacin y la localizacin de errores. Nos encontraremos frecuentemente con o o este concepto. Aprovecharemos de introducir las funciones modicando el primer programa de manera que se delegue la impresin del mensaje anterior a una funcin independiente: o o // // Segunda version incluye funcion adicional // #include <iostream> using namespace std;
4.1. ESTRUCTURA BASICA DE UN PROGRAMA EN C++. void PrintHola() { cout << "Hola." << endl; } int main() { PrintHola(); return 0; }
91
La funcin debe estar denida antes de que sea ocupada, por eso va primero en el cdigo o o fuente. Como ya se dijo antes, la ejecucin del programa comienza en la funcin main a o o pesar de que no est primera en el cdigo fuente. Los parntesis vac indican que la funcin a o e os o PrintHola no tiene argumentos y la palabra delante del nombre de la funcin indica el tipo o de dato que devuelve. En nuestro caso la palabra void indica que no devuelve nada a la funcin main. o Una alternativa al cdigo anterior es la siguiente: o #include <iostream> using namespace std; void PrintHola(); int main() { PrintHola(); return 0 ; } void PrintHola() { cout << "Hola." << endl; } En esta versin se ha separado la declaracin de la funcin de su implementacin. En o o o o la declaracin se establece el nombre de la funcin, los argumentos que recibe, y el tipo de o o variable que entrega como resultado. En la implementacin se da expl o citamente el cdigo o que corresponde a la funcin. Hab o amos dicho que una funcin debe estar denida antes que o sea ocupada. En verdad, basta con que la funcin est declarada. La implementacin puede o e o ir despus (como en el ejemplo anterior), o incluso en un archivo distinto, como veremos ms e a adelante. La separacin de declaracin e implementacin es otro paso hacia la modularizacin o o o o de nuestro programa.
92
4.1.3.
Nombres de variables.
Nuestros datos en los programas sern almacenados en objetos llamados variables. Para a referirnos a ellas usamos un nombre que debe estar de acuerdo a las siguientes reglas: Deben comenzar con una letra (maysculas y minsculas son distintas). u u Pueden contener nmeros, pero no comenzar por uno. u Pueden contener el s mbolo _ (underscore). Longitud arbitraria. No pueden corresponder a una de las palabras reservadas de C++1 : asm auto break case catch char class const continue default delete do double else enum extern float for friend goto if inline int long new operator private protected public register return short signed sizeof static struct switch template this throw try typedef union unsigned virtual void volatile while
4.1.4.
Tipos de variables.
Todas las variables a usar deben ser declaradas de acuerdo a su tipo. Por ejemplo, si usamos una variable i que sea un nmero entero, debemos, antes de usarla, declararla, y slo u o entonces podemos asignarle un valor: int i; i=10; Esta necesidad de declarar cada variable a usar se relaciona con la caracter stica de C++ de 2 ser fuertemente tipeado . Algunos de los errores ms habituales en programacin se deben a o al intento de asignar a variables valores que no corresponden a sus tipos originales. Si bien esto puede no ser muy grave en ciertos contextos, a medida que los programas se vuelven ms complejos puede convertirse en un verdadero problema. El compilador de C++ es capaz a de detectar los usos indebidos de las variables pues conoce sus tipos, y de este modo nuestro cdigo se vuelve ms seguro. o a Es posible reunir las acciones de declaracin e inicializacin en una misma l o o nea: int i=10;
A esta tabla hay que agregar algunas palabras adicionales, presentes en versiones ms recientes de C++, a como namespace y using 2 Una traduccin libre del trmino ingls strongly typed. o e e
1
93
o declarar ms de una variable del mismo tipo simultneamente, e inicializar algunas en la a a misma l nea: int r1, r2, r3 = 10; A veces se requiere que una variable no var una vez que se le asigna un valor. Por ejemplo, e podr amos necesitar denir el valor de = 3.14159..., y naturalmente no nos gustar que, a por un descuido, a esa variable se le asignara otro valor en alguna parte del programa. Para asegurarnos de que ello no ocurra, basta agregar el modicador const a la variable: const float pi = 3.14159; Para nmeros reales se puede usar la notacin exponencial. Por ejemplo, 1.5e-3 repreu o senta el nmero 1.5 103 . u Una variable puede ser declarada slo una vez, pero naturalmente se le pueden asignar o valores en un nmero arbitrario de ocasiones. u Los 15 tipos de datos aritmticos fundamentales disponibles son3 : e Booleanos y caracteres bool char signed char unsigned char Booleanas true o false. Caracteres de 0 a 255 o -128 a 127, usa 8 bits, Caracteres 128 a 127, Caracteres de 0 a 255. Enteros short Enteros entre 215 = 32768 y 215 1 = 32767 unsigned short Enteros entre 0 y 65535 int Enteros entre 231 = 2147483648 y 231 1 = 2147483647 unsigned int Enteros entre 0 y 232 = 4294967295 long (32 bits) Entero entre 2147483648 y 2147483647, long (64 bits) Entero entre 9223372036854775808 y 9223372036854775807, unsigned long (32 bits) Enteros entre 0 y 4294967295, unsigned long (64 bits) Enteros entre 0 y 18446744073709551615, long long Enteros entre 9223372036854775808 y 9223372036854775807 unsigned long long Enteros entre 0 y 18446744073709551615 Float float Reales x tal que 1.17549435 1038 |x| 3.40282347 1038 , (Precisin de 7 d o gitos decimales.) double Reales x tal que 2.2250738585072014 10308 |x| 1.7976931348623157 10308 , (Precisin de 15 d o gitos decimales.) long double Reales x tal que 3.36210314311209350626 104932 |x| 1.18973149535723176502 104932 , (Precisin de 18 d o gitos decimales.)
Los valores de los rangos indicados son simplemente representativos y dependen de la mquina utilizada a (32 bits o 64 bits). Adems, estos valores no corresponden exactamente a las versiones ms recientes de C++. a a
94
CAP ITULO 4. UNA BREVE INTRODUCCION A C++. Las variables tipo char alojan caracteres, debiendo inicializarse en la forma:
char c = a; Adems de las letras maysculas y minsculas, y s a u u mbolos como &, (, :, etc., hay una serie de caracteres especiales (escape codes) que es posible asignar a una variable char. Ellos son: newline horizontal tab vertical tab backspace carriage return form feed alert (bell) backslash single quote double quote \n \t \v \b \r \f \a \\ \ \"
Por ejemplo, la l nea: cout << "Primera columna\t Segunda columna\n Segunda linea" << endl; corresponde al output Primera columna Segunda linea Segunda columna
4.1.5.
El header iostream dene un objeto especial llamado cin que est asociado al teclado o a stdin. Con el operador >> asignamos la entrada en el dispositivo de la izquierda a la variable de la derecha; una segunda entrada requiere de otro operador >> y de otra variable. En el siguiente ejemplo veremos una declaracin simultnea de dos variables del mismo tipo i y o a j, un mensaje a pantalla con las instrucciones a seguir, el ingreso de dos variables desde el teclado y luego su escritura en la pantalla. #include <iostream> using namespace std; int main() { int i, j ; cout << "Ingrese dos numeros enteros: " ; cin >> i >> j ; cout << "Los dos numeros ingresados fueron: " << i <<" "<< j << endl ; return 0; }
95
4.1.6.
Operadores aritmticos. e
Existen operadores binarios (i.e., que actan sobre dos variables, una a cada lado del u operador) para la suma, la resta, la multiplicacin y la divisin: o o + * /
4.1.7.
Operadores relacionales.
Los s mbolos para los operadores relacionales de igualdad, desigualdad, menor, menor o igual, mayor y mayor o igual son: == != < <= > >=
4.1.8.
Asignaciones.
a) Asignacin simple. Podemos asignar a una variable un valor expl o cito, o el valor de otra variable: i = 1; j = k; Una prctica habitual en programacin es iterar porciones del cdigo. La iteracin a o o o puede estar determinada por una variable cuyo valor aumenta (disminuye) cada vez, hasta alcanzar cierto valor mximo (m a nimo), momento en el cual la iteracin se detiene. o Para que una variable x aumente su valor en 2, por ejemplo, basta escribir: x = x + 2; Si x fuera una variable matemtica normal, esta expresin no tendr sentido. Esta a o a expresin es posible porque el compilador interpreta a x de modo distinto a cada lado o del signo igual: a la derecha del signo igual se usa el valor contenido en la variable x (por ejemplo, 10); a la izquierda del signo igual se usa la direccin de memoria en la o cual est alojada la variable x. De este modo, la asignacin anterior tiene el efecto de a o colocar en la direccin de memoria que contiene a x, el valor que tiene x ms 2. En o a general, todas las variables tienen un rvalue y un lvalue: el primero es el valor usado a la derecha (right) del signo igual en una asignacin, y el segundo es el valor usado a la o izquierda (left), es decir, su direccin de memoria. o b) Asignacin compuesta. o La expresin o x = x + 2 se puede reemplazar por += -= *= /= x += 2. Existen los operadores
96
CAP ITULO 4. UNA BREVE INTRODUCCION A C++. c) Operadores de incremento y decremento. La expresin o x = x + 1 se puede reescribir x += 1 o bien x++.
Anlogamente, existe el operador --. Ambos operadores unarios, ++ y -- pueden ocua parse como prejos o sujos sobre una variable y su accin diere en ambos casos. o Como prejo la operacin de incremento o decremento se aplica antes de que el valor o de la variable sea usado en la evaluacin de la expresin. Como sujo el valor de la vao o riable es usado en la evaluacin de la expresin antes que la operacin de incremento o o o o decremento. Por ejemplo, supongamos que inicialmente x = 3. Entonces la instruccin o y=x++ hace que y = 3, x = 4; por su parte, y=++x hace que y = 4, x = 4. Con estas consideraciones, deber amos poder convencernos de que la salida del siguiente programa es 3 2 2-1 1 1 : // Ejemplo de operadores unarios ++ y --. #include <iostream> using namespace std; int main() { int y ; int x = (y = 1) ; int w = ++x + y++; cout << w <<" " << x << " " << y << "-" ; w = x-- - --y; cout << w << " " << x << " " << y << endl ; return 0; } Los operadores para asignacin compuesta, y los de incremento y decremento, no son slo o o abreviaciones. En realidad hay que preferirlas porque implican optimizaciones en el ejecutable resultante.
4.1.9.
Conversin de tipos. o
Una consecuencia de que C++ sea fuertemente tipeado es que no se pueden hacer operaciones binarias con objetos de tipos distintos. En la siguiente expresin, o int i = 3; float x = 43.8; cout << "Suma = " << x + i << endl; el computador debe sumar dos variables de tipos distintos, y en principio la operacin es o imposible. La estrategia para resolver este problema es convertir ambas variables a un tipo comn antes de efectuar la suma (en ingls, decimos que hacemos un cast de un tipo a otro). u e Existen dos modos de proceder:
97
Si i es un int, por ejemplo, entonces float(i) la convierte en float. As el programa , anterior se puede reescribir: int i = 3; float x = 43.8; cout << "Suma = " << x + float(i) << endl; Ahora la suma es claramente entre dos variables float, y se puede realizar. Sin embargo, esto es bastante tedioso, por cuanto el programador debe realizar el trabajo de conversin personalmente cada vez que en su cdigo se desee sumar un real con un o o nmero entero. u b) Conversin impl o cita. En este caso, el compilador realiza las conversiones de modo automtico, preriendo a siempre la conversin desde un tipo de variable de menor precisin a uno de mayor o o precisin (de int a double, de short a int, etc.). As a pesar de lo que dijimos, el o , cdigo anterior habr funcionado en su forma original. Evidentemente esto es muy o a cmodo, porque no necesitamos hacer una conversin expl o o cita cada vez que sumamos un entero con un real. Sin embargo, debemos estar conscientes de que esta comodidad slo es posible porque ocurren varias cosas: primero, el compilador detecta el intento de o operar sobre dos variables que no son del mismo tipo; segundo, el compilador detecta, en sus reglas internas, la posibilidad de cambiar uno de los tipos (int en este caso) al otro (float); tercero, el compilador realiza la conversin, y nalmente la operacin se o o puede llevar a cabo. Entender este proceso nos permitir aprovechar las posibilidades a de la conversin impl o cita de tipos cuando nuestro cdigo involucre tipos de variables o ms complicados, y entender varios mensajes de error del compilador. a Es interesante notar cmo las conversiones impl o citas de tipos pueden tener consecuencias insospechadas. Consideremos las tres expresiones: i) x = (1/2) * (x + a/x) ; ii) x = (0.5) * (x + a/x) ; iii) x = (x + a/x)/2 ; Si inicialmente x=0.5 y a=0.5, por ejemplo, i) entrega el valor x=0, mientras ii) y iii) entregan el valor x=1.5. Lo que ocurre es que 1 y 2 son enteros, de modo que 1/2 = 0. De acuerdo a lo que dijimos, uno esperar que en i), como conviven nmeros reales a u con enteros, los nmeros enteros fueran convertidos a reales y, por tanto, la expresin u o tuviera el resultado esperado, 1.5. El problema es la prioridad de las operaciones. No todas las operaciones tienen igual prioridad (las multiplicaciones y divisiones se realizan antes que las sumas y restas, por ejemplo), y esto permite al compilador decidir cul a operacin efectuar primero. Cuando se encuentra con operaciones de igual prioridad o (dos multiplicaciones, por ejemplo), se procede a efectuarlas de izquierda a derecha. Pues bien, en i), la primera operacin es 1/2, una divisin entre enteros, i.e. cero. En o o ii) no hay problema, porque todas son operaciones entre reales. Y en iii) la primera
98
CAP ITULO 4. UNA BREVE INTRODUCCION A C++. operacin es el parntesis, que es una operacin entre reales. Al dividir por 2 ste es o e o e convertido a real antes de calcular el resultado. i) an podr utilizarse, cambiando el prefactor del parntesis a 1.0/2.0, una prctica u a e a que ser conveniente adoptar como standard cuando queremos utilizar enteros dena tro de expresiones reales, para evitar errores que pueden llegar a ser muy dif ciles de detectar.
4.2.
4.2.1.
Control de ujo.
if, if... else, if... else if.
Las construcciones siguientes permiten controlar el ujo del programa en base a si una expresin lgica es verdadera o falsa. o o a) En el caso de la sentencia if se evaluar la expresin (a==b), si ella es cierta ejecutar la a o a o las l neas entre los parntesis de llave y si la expresin es falsa el programa se salta e o esa parte del cdigo. o if (a==b) { cout << "a es igual a b" << endl; } En este y en muchos de los ejemplos que siguen, los parntesis cursivos son opcionales. e Ellos indican simplemente un grupo de instrucciones que debe ser tratado como una sola instruccin. En el ejemplo anterior, los parntesis cursivos despus del if (o despus de o e e e un while, for, etc. ms adelante) indican el conjunto de instrucciones que deben o no a ejecutarse dependiendo de si cierta proposicin es verdadera o falsa. Si ese conjunto de o instrucciones es una sola, se pueden omitir los parntesis: e if (a==b) cout << "a es igual a b" << endl; b) En el caso if... else hay dos acciones mutuamente excluyentes. La sentencia if (c!=b) evaluar la expresin (c!=b). Si ella es cierta ejecutar la o las l a o a neas entre los parntesis de llave que le siguen, saltndose la o las l e a neas entre los parntesis de e llave que siguen a la palabra clave else. Si la expresin es falsa el programa se salta la o primera parte del cdigo y slo ejecuta la o las l o o neas entre los parntesis de llave que e siguen a else. if (c!=d) { cout << "c es distinto de d" << endl; } else { cout << "c es igual a d" << endl; }
99
c) En el ultimo caso se evaluar la expresin que acompaa al if y si ella es cierta se a o n ejecutar la o las l a neas entre los parntesis de llave que le siguen, saltndose todo el e a resto de las l neas entre los parntesis de llave que siguen a las palabras claves else if e y else. Si la primera expresin es falsa el programa se salta la primera parte del cdigo o o y evala la expresin que acompaa al primer else if y si ella es cierta ejecutar la u o n a o las l neas entre los parntesis de llave que le siguen, saltndose todo el resto de las e a l neas entre los parntesis que siguen a otros eventuales else if o al else. Si ninguna e de las expresiones lgicas resulta cierta se ejecutar la o las l o a neas entre los parntesis e que siguen al else. if (e > f) { cout << "e es mayor que f" << endl; } else if (e == f) { cout << "e es igual a f" << endl; } else { cout << "e es menor que f" << endl; } Para C++, una expresin verdadera es igual a 1, y una falsa es igual a 0. Esto es, cuando o escribimos if(e>f), y e>f es falsa, en realidad estamos diciendo if(0). A la inversa, 0 es considerada una expresin falsa, y cualquier valor no nulo es considerado una expresin o o verdadera. As podr , amos hacer que una porcin del cdigo siempre se ejecute (o nunca) o o poniendo directamente if(1) o if(0), respectivamente. Naturalmente, lo anterior no tiene mucho sentido, pero un error habitual (y particularmente dif de detectar) es escribir a = b en vez de a == b en una expresin lgica. Esto cil o o normalmente trae consecuencias indeseadas, pues la asignacin a = b es una funcin que se o o evala siempre al nuevo valor de a. En efecto, una expresin como a=3 siempre equivale a u o verdadero, y a=0 siempre equivale a falso. Por ejemplo, en el siguiente programa: #include <iostream> using namespace std; int main(){ int k=3; if (k==3){ cout << "k es igual a 3" << endl; } k=4; if (k=3){ cout << "k es igual a 3" << endl; } return 0; }
4.2.2.
Expresin condicional. o
Una construccin if else simple, que slo asigna un valor distinto a una misma variable o o segn si una proposicin es verdadera o falsa, es muy comn en programacin. Por ejemplo: u o u o if (a==b) { c = 1; } else { c = 0; } Existen dos maneras de compactar este cdigo. Este se puede reemplazar por o if (a==b) c = 1; else c = 0; Sin embargo, esto no es recomendable por razones de claridad al leer el cdigo. Una expresin o o ms compacta y clara, se consigue usando el operador ternario ? : a c = (a==b) ? 1 : 0; Como en el caso de los operadores de incremento y decremento, el uso del operador ? es preferible para optimizar el ejecutable resultante.
4.2.3.
switch.
La instruccin switch permite elegir mltiples opciones a partir del valor de una variable o u entera. En el ejemplo siguiente tenemos que si i==1 la ejecucin continuar a partir del caso o a case 1:, si i==2 la ejecucin continuar a partir del caso case 2: y as sucesivamente. Si o a i toma un valor que no est enumerado en ningn case y existe la etiqueta default, la a u ejecucin continuar a partir de ah Si no existe default, la ejecucin contina luego del o a . o u ultimo parntesis cursivo. e switch (i) { case 1: { cout << "Caso 1." << endl; } break; case 2:
4.2. CONTROL DE FLUJO. { cout << "Caso 2." << endl; } break; default: { cout << "Otro caso." << endl; } break; }
101
La instruccin break permite que la ejecucin del programa salte a la l o o nea siguiente despus e de la serie de instrucciones asociadas a switch. De esta manera slo se ejecutarn las l o a neas correspondientes al case elegido y no el resto. Por ejemplo, si i==1 ver amos en pantalla slo la l o nea Caso 1. En el otro caso, si no existieran los break, y tambin i==1, entonces e ver amos en pantalla las l neas Caso 1., Caso 2. y Otro caso. La instruccin default es o opcional.
4.2.4.
for.
Una instruccin que permite repetir un bloque de instrucciones un nmero denido de o u veces es el for. Su sintaxis comienza con una o varias inicializaciones, luego una condicin o lgica de continuacin mientras sea verdadera, y nalmente una o ms expresiones que se o o a evalan vuelta por vuelta no incluyendo la primera vez. Siguiendo al for(...) viene una u instruccin o un bloque de ellas encerradas entre parntesis de llave. En el ejemplo siguiente o e la variable entera i es inicializada al valor 1, luego se verica que la condicin lgica sea o o cierta y se ejecuta el bloque de instrucciones. A la vuelta siguiente se evala la expresin a u o la extrema derecha (suele ser uno o ms incrementadores), se verica que la condicin lgica a o o se mantenga cierta y se ejecuta nuevamente el bloque de instrucciones. Cuando la condicin o lgica es falsa se termina el loop, saltando la ejecucin a la l o o nea siguiente al parntesis que e indica el n del bloque de instrucciones del for. En este ejemplo, cuando i=4 la condicin o de continuacin ser falsa y terminar la ejecucin del for. o a a o for (int i = 1; i < 4; i++) { cout << "Valor del indice: " << i << endl; } El output correspondiente es: Valor del indice: 1 Valor del indice: 2 Valor del indice: 3 Cualquier variable declarada en el primer argumento del for es local al loop. En este caso, la variable i es local, y no interere con otras posibles variables i que existan en nuestro cdigo. o
102
for es una instruccin particularmente exible. En el primer y tercer argumento del for o se puede colocar ms de una instruccin, separadas por comas. Esto permite, por ejemplo, a o involucrar ms de una variable en el ciclo. El cdigo: a o for (int i=0, k=20; (i<10) && (k<50); i++, k+=6) { cout << "i + k = " << i + k << endl; } resulta en el output: i i i i i + + + + + k k k k k = = = = = 20 27 34 41 48
Adems, la condicin de continuacin (segundo argumento del for), no tiene por qu dea o o e pender de las variables inicializadas en el primer argumento. Y el tercer argumento no tiene por qu ser un incremento o decremento de las variables del loop; puede ser cualquier expree sin que queramos ejecutar cada vez que un ciclo termina. En el siguiente ejemplo, adems o a de incrementar los contadores en cada ciclo, se env un mensaje a pantalla: a for (int i=1, k=2;k<5 && i<20;k++, i+=2, cout << "Fin iteracion" << endl){ cout << " i = " << i <<,; cout << " k = " << k << endl; } El resultado de las iteraciones: i = 1, k = 2 Fin iteracion i = 3, k = 3 Fin iteracion i = 5, k = 4 Fin iteracion Todos los argumentos del for son opcionales (no los ;), por lo cual se puede tener un for que carezca de inicializacin y/o de condicin de continuacin y/o de una expresin que se o o o o evale en cada iteracin. u o Un caso t pico en que se aprovecha la opcionalidad de los argumentos del for es para tener un loop innito, que puede servir para dejar el programa en pausa indenida. Para salir del loop (y en general, para detener cualquier programa en C++), hay que presionar ^C: for (; ; ) cout << "Este es un loop infinito, ^C para detenerlo"<< endl; Se puede adems, salir abruptamente del loop con break. El cdigo: a o
4.2. CONTROL DE FLUJO. for(int indice=0; indice<10; indice++) { int cuadrado = indice*indice ; cout << indice << " " ; if(cuadrado > 10 ) break ; } cout << endl; da la salida a pantalla: 0 1 2 3 4
103
aun cuando la condicin de continuacin permite que indice llegue hasta 9. o o Finalmente, las variables involucradas en el for pueden ser modicadas dentro del ciclo. Por ejemplo, modiquemos uno de los ejemplos anteriores, cambiando la variable k en medio del ciclo: for (int i=1, k=2;k<5 && i<8;k++, i+=2, cout << "Fin iteracion" << endl){ cout << " i = " << i << ", k = " << k << endl; k = k+5; } El resultado es: i = 1, k = 2 Fin iteracion En vez de pasar por el ciclo tres veces, como ocurr originalmente, el programa sale del loop, a al cabo del primer ciclo, k = 2 + 5 = 7 > 5. En general no es una buena prctica modicar las variables internas del ciclo en medio a de l, porque no es muy ordenado, y el desorden normalmente conduce a los errores en e programacin, pero ocasionalmente puede ser util hacer uso de esta libertad que proporciona o el lenguaje. Los ciclos for pueden anidarse, tal que uno contenga a otro completamente.
4.2.5.
while.
La instruccin while permite repetir un bloque de instrucciones encerradas entre parnteo e sis de llave mientras la condicin lgica que acompaa al while se mantenga cierta. La cono o n dicin es evaluada antes de que comience la primera iteracin; si es falsa en sta o en una o o e posterior evaluacin no se ejecuta el bloque de instrucciones que le siguen y se contina la o u ejecucin en la l o nea siguiente al parntesis que indica el n del bloque asociado al while. e Hay que notar que la instruccin while podr no ejecutarse ni una sola vez si la condicin o a o no se cumple inicialmente. Un ejemplo simple: int i=1; while (i < 3) { cout << i++ << " "; }
104
que da por resultado: 1 2. En el siguiente loop, la salida ser: 5 4 3 2 1 (Por qu?) a e int k=5 ; while(k) { cout << k-- <<" "; }
4.2.6.
do... while.
La instruccin do... while es anloga a while, salvo que la condicin lgica es evaluada o a o o despus de la primera iteracin. Por tanto, el bloque se ejecuta al menos una vez, siempre. e o Un ejemplo simple: do { cout << i++ << endl; } while (i<=20); Podemos construir de otra manera un loop innito usando do while do { cout << "Este es un segundo loop infinito, ^C para detenerlo"<< endl; } while (1);
4.2.7.
goto.
Existe tambin en C++ una instruccin goto que permite saltar de un punto a otro del e o programa (goto salto; permite saltar a la l nea que contiene la instruccin salto:). Sin o embargo, se considera una mala tcnica de programacin usar goto, y siempre se puede die o sear un programa evitndolo. Es altamente no recomendable, pero si su utilizacin simplica n a o el cdigo se puede usar. o
4.3.
Funciones.
Las funciones nos permiten programar partes del procedimiento por separado. Un ejemplo simple de ellas lo vimos en la subseccin 4.1.2. o
4.3.1.
Un caso especial de funciones es aquel en que el programa que llama la funcin no espera o que sta le entregue ningn valor al terminar. Por ejemplo, en la subseccin 4.1.2, la funcin e u o o PrintHola simplemente imprime un mensaje en pantalla. El resto del programa no necesita de ningn resultado parcial proveniente de la ejecucin de dicha funcin. La denicin de u o o o estas funciones debe ir precedida de la palabra void, como en el ejemplo citado.
4.3. FUNCIONES.
105
4.3.2.
return.
Si deseamos denir una funcin que calcule una ra cuadrada, evidentemente esperamos o z que la funcin nos entregue un resultado: el valor de la ra cuadrada. En este caso hay que o z traspasar el valor de una variable desde la funcin al programa que la llam. Esto se consigue o o con return. Veamos un ejemplo muy simple: int numero(){ int i = 3; return i; } int main(){ cout << "Llamamos a la funcion" << endl; cout << "El numero es: " << numero() << endl; int i = 5; i = i + numero(); cout << "El numero mas 5 es: " << i << endl; return 0; } En este caso, la funcin simplemente entrega el valor de la variable interna i, es decir 3, el o cual puede ser usado para salida en pantalla o dentro de operaciones matemticas corrientes. a Separando declaracin e implementacin de la funcin, el ejemplo anterior se escribe: o o o int numero(); int main(){ ... } int numero(){ int i = 3; return i; } Dos observaciones utiles: a) La declaracin de la funcin lleva antepuesto el tipo de variable que la funcin entrega. o o o En el ejemplo, la variable entregada es un entero, i, y la declaracin debe ser, por tanto, o int numero(). Podemos tener funciones tipo double, char, long, etc., de acuerdo al tipo de variable que corresponde a return. b) La variable i que se usa dentro de main() y la que se usa dentro de numero() son distintas. A pesar de que tienen el mismo nombre, se pueden usar independientemente como si se llamaran distinto. Se dice que i es una variable local. Despus de return debe haber una expresin que se evale a una variable del tipo correse o u pondiente, ya sea expl citamente o a travs de un cast impl e cito. Las siguientes funciones devuelven un double al programa:
106 double f1(){ double l = 3.0; return l; } double f2(){ double l = 3.0, m = 8e10; return l*m; } double f3(){ int l = 3; return l; }
Sin embargo, la siguiente funcin har que el compilador emita una advertencia, pues se o a est tratando de devolver un double donde deber ser un int, y la conversin implica una a a o prdida de precisin: e o int f4(){ double l=3.0; return l; } Naturalmente, podemos modicar la funcin anterior haciendo una conversin expl o o cita antes de devolver el valor: return int(l).
4.3.3.
Volviendo al ejemplo de la ra cuadrada, nos gustar llamar a esta funcin con un z a o parmetro (el nmero al cual se le va a calcular la ra cuadrada). Consideremos por ejemplo a u z una funcin que necesita un solo parmetro, de tipo int, y cuyo resultado es otro int: o a int funcion(int i){ i+=4; return i; } int main(){ int i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; return 0 ; } El resultado en pantalla es:
107
La funcin funcion entrega el valor del parmetro ms 4. Usamos el mismo nombre (i) o a a para las variables en main y funcion, pero son variables locales, as que no intereren. Lo importante es notar que cuando se llama a la funcin, la reasignacin del valor de i (i+=4) o o ocurre slo para la variable local en funcion; el parmetro externo mantiene su valor. o a Separando declaracin e implementacin el ejemplo anterior se escribe: o o int funcion(int); int main(){...} int funcion(int i){ i+=4; return i; } Si nuestra funcin necesita ms parmetros, basta separarlos con comas, indicando para o a a cada uno su tipo: int funcion2(int,double); void funcion3(double,int,float); double funcion4(float); El compilador verica cuidadosamente que cada funcin sea llamada con el nmero de o u parmetros adecuados, y que cada parmetro corresponda al tipo especicado. En los ejema a plos anteriores, funcion2 debe ser llamada siempre con dos argumentos, el primero de los cuales es int y el segundo double. Como siempre, puede ser necesario un cast impl cito (si se llama funcion2 con el segundo argumento int, por ejemplo), pero si no existe una regla de conversin automtica (llamando a funcion2 con el primer argumento double, por ejemplo), o a el compilador enviar una advertencia. Adems, el compilador verica que el valor de retorno a a de la funcin sea usado como corresponde. Por ejemplo, en las dos l o neas: double m = funcion2(2,1e-3); int k = funcion4(0.4); la primera compilar exitosamente (pero hay un cast impl a cito), y la segunda dar una a advertencia. Existen dos modos de transferir parmetros a una funcin: a o a) Por valor. Se le pasan los parmetros para que la funcin que es llamada copie sus a o valores en sus propias variables locales, las cuales desaparecern cuando la funcin a o termine y no tienen nada que ver con las variables originales. Hasta ahora, en todos los ejemplos de esta subseccin el traspaso de parmetros ha sido o a por valor. En la funcin int funcion(int), en el cdigo de la pgina 106, lo que ha o o a ocurrido es que la funcin copia el valor de la variable externa i en una nueva variable o (que tambin se llama i, pero est en otra direccin de memoria). El valor con el que e a o trabaja la funcin es la copia, manteniendo inalterada la variable original. o
108
b) Por referencia. Se le pasa la direccin de memoria de los parmetros. La funcin llamada o a o puede modicar el valor de tales variables. La misma funcin de la pgina 106 puede ser modicada para que el paso de parmetros o a a sea por referencia, modicando la declaracin: o int funcion(int &); int main() { int i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; return 0; } int funcion(int & i) { i+=4; return i; } En vez de traspasarle a funcion el valor del parmetro, se le entrega la direccin a o de memoria de dicha variable. Debido a ello, funcion puede modicar el valor de la variable. El resultado en pantalla del ultimo programa ser: a El valor de la funcion es 7 El valor del parametro es 7 Debido a que las variables dejan de ser locales, el paso de parmetros por referencia a debe ser usado con sabidur De hecho el ejemplo presentado es poco recomendable. a. Peor an, el problema es no slo que las variables dejan de ser locales, sino que es u o imposible saber que no lo son desde el main. En efecto, el main en ambas versiones de funcion es el mismo. Lo unico que cambi es la declaracin de la funcin. Puesto que un o o o usuario normal usualmente no conoce la declaracin e implementacin de cada funcin o o o que desea usar (pues pueden haber sido hechas por otros programadores), dejamos al usuario en la indefensin. o Por otro lado, hay al menos dos situaciones en que el paso de referencia es la unica opcin viable para entregar los parmetros. Un caso es cuando hay que cuidar el uso o a de la memoria. Supongamos que una funcin necesita un parmetros que es una matriz o a de 10 millones de las por 10 millones de columnas. Seguramente estaremos llevando al l mite los recursos de nuestra mquina, y ser una torpeza pasarle la matriz por valor: a a ello involucrar primero, duplicar la memoria utilizada, con el consiguiente riesgo de a, que nuestro programa se interrumpa; y segundo, har el programa ms lento, porque a a la funcin necesitar llenar su versin local de la matriz elemento por elemento. Es o a o decir, nada de eciente. En esta situacin, el paso por referencia es lo adecuado. o
4.3. FUNCIONES.
109
Un segundo caso en que el paso por referencia es recomendable es cuando efectivamente nuestra intencin es cambiar el valor de las variables. El ejemplo t o pico es el intercambio de dos variables entre s digamos a1=1 y a2=3. Luego de ejecutar la funcin queremos , o que a1=3 y a1=1. El siguiente cdigo muestra la denicin y el uso de una funcin para o o o esta tarea, y por cierto requiere el paso de parmetros por referencia: a #include <iostream> void swap(int &,int &); using namespace std; int main(){ int i = 3, k=10; swap(i,k); cout << "Primer argumento: " << i << endl; cout << "Segundo argumento: " << k << endl; return 0 ; } void swap(int & j,int & p){ int temp = j; j = p; p = temp; } El output es: Primer argumento: 10 Segundo argumento: 3 En el ejemplo de la matriz anterior, ser interesante poder pasar el parmetro por refea a rencia, para ahorrar memoria y tiempo de ejecucin, pero sin correr el riesgo de que nuestra o matriz gigantesca sea modicada por accidente. Afortunadamente existe el modo de hacerlo, usando una palabra que ya hemos visto antes: const. En el siguiente cdigo: o int f5(const int &); int main(){...} int f5(const int & i){...}; f5 recibir su unico argumento por referencia, pero, debido a la presencia del modicador a const, el compilador avisar si se intenta modicar el argumento en medio del cdigo de la a o funcin. o
4.3.4.
C++ permite que omitamos algunos parmetros de la funcin llamada, la cual reema o plaza los valores omitidos por otros predeterminados. Tomemos por ejemplo la funcin o
110
int funcion(int); de la subseccin 4.3.3, y modiqumosla de modo que si no le entregao e mos parmetros, asuma que el nmero entregado fue 5: a u int funcion(int i = 5){ i+=4; return i; } int main(){ cout << "El resultado default es " << funcion() << endl; int i = 3; cout << "Cuando el parametro vale " << i << " el resultado es " << funcion(i) << endl; return 0; } El output correspondiente es: El resultado default es 9 Cuando el parametro vale 3 el resultado es 7 Separando declaracin e implementacin: o o int funcion(int = 5); main(){...} int funcion(int i){ i+=4; return i; } Si una funcin tiene n argumentos, puede tener m n argumentos opcionales. La unica o restriccin es que, en la declaracin e implementacin de la funcin, los parmetros opcionales o o o o a ocupen los ultimos m lugares: void f1(int,int = 4); int f2(double,int = 4, double = 8.2); double f3(int = 3,double = 0.0, int = 0); En este caso, f1(2), f1(2,8), f2(2.3,5), f3(3), f3(), y muchas otras, son todas llamadas vlidas de estas funciones. Cada vez, los parmetros no especicados son reemplazados por a a sus valores predeterminados.
4.3.5.
Ra cuadrada. z Con lo visto hasta ahora, ya podemos escribir un programa que calcule la ra cuadrada z de una funcin. Para escribir una funcin, debemos tener claro qu se espera de ella: cuntos o o e a
4.3. FUNCIONES.
111
y de qu tipo son los argumentos que recibir, qu tipo de valor de retorno deber tener, e a e a y, por cierto, un nombre adecuado. Para la ra cuadrada, es claro que el argumento es un z nmero. Pero ese nmero podr ser un entero o un real, y eso al compilador no le da lo u u a mismo. En este punto nos aprovechamos del cast impl cito: en realidad, basta denir la ra z cuadrada con argumento double; de este modo, si se llama la funcin con un argumento int, o el compilador convertir automticamente el int en double y nada fallar. En cambio, si la a a a deniramos para int y la llamamos con argumento double, el compilador se quejar de que e a no sabe efectuar la conversin. Si el argumento es double, evidentemente esperamos que el o valor de retorno de la funcin sea tambin un double. Llamando a la funcin raiz, tenemos o e o la declaracin: o double raiz(double); Debido a la naturaleza de la funcin ra cuadrada, raiz() no tendr sentido, y por tanto o z a no corresponde declararla con un valor default. Ahora debemos pensar en cmo calcular la ra cuadrada. Usando una variante del mtodo o z e de Newton-Raphson, se obtiene que la secuencia xn+1 = 1 2 xn + a xn
converge a a cuando n . Por tanto, podemos calcular la ra cuadrada con aproximaz ciones sucesivas. El clculo terminar en el paso N , cuando la diferencia entre el cuadrado a a de la aproximacin actual, xN , y el valor de a, sea menor que un cierto nmero pequeo: o u n 1. El valor de determinar la precisin de nuestro clculo. Un ejemplo de a o a | x2 a | < N cdigo lo encontramos a continuacin: o o #include <iostream> #include <cmath> using namespace std; double raiz(double); int main(){ double r; cout.precision(20); cout << "Ingrese un numero: " << endl; cin >> r; cout << raiz(r) << endl; return 0 ; } double raiz(double a){ double x =a/2.0 ; // para comenzar double dx = 1e3, epsilon = 1e-8;
112
while (fabs(dx)>epsilon){ x = (x + a/x)/2; dx = x*x - a; cout << "x = " << x << ", precision = " << dx << endl; } return x; } Luego de la declaracin de la funcin raiz, est main, y al nal la implementacin de o o a o raiz. En main se pide al usuario que ingrese un nmero, el cual se aloja en la variable r, u y se muestra en pantalla el valor de su ra cuadrada. La instruccin cout.precision(20) z o permite que la salida a pantalla muestre el resultado con 20 cifras signicativas. En la implementacin de la funcin hay varios aspectos que observar. Se ha llamado x a la o o variable que contendr las sucesivas aproximaciones a la ra Al nal del ciclo, x contendr el a z. a valor (aproximado) de la ra cuadrada. dx contiene la diferencia entre el cuadrado de x y el z valor de a, epsilon es el nmero (pequeo) que determina si la aproximacin es satisfactoria u n o o no. El ciclo est dado por una instruccin while, y se ejecuta mientras dx>epsilon, es decir, a o termina cuando dx es sucientemente pequeo. El valor absoluto del real dx se obtiene con la n funcin matemtica fabs, disponible en el header cmath incluido al comienzo del programa. o a Observar que inicialmente dx=1e3, esto es un valor muy grande; esto permite que la condicin o del while sea siempre verdadera, y el ciclo se ejecuta al menos una vez. Dentro del ciclo, se calcula la nueva aproximacin, y se env a pantalla un mensaje con o a la aproximacin actual y la precisin alcanzada (dada por dx). Eventualmente, cuando la o o aproximacin es sucientemente buena, se sale del ciclo y la funcin entrega a main el valor o o de x actual, que es la ultima aproximacin calculada. o Factorial. Otro ejemplo util es el clculo del factorial, denido para nmeros naturales: a u n! = n (n 1) 2 1 , 0! 1 .
La estrategia natural es utilizar un ciclo for, determinado por una variable entera i, que va desde 1 a n, guardando los resultados en una variable auxiliar que contiene el producto de todos los nmeros naturales desde 1 hasta i: u #include <iostream> using namespace std; int factorial(int); int main(){ int n=5 ; cout << "El factorial de " << n << " es: " << factorial(n) << endl;
4.3. FUNCIONES. return 0 ; } int factorial(int i) { int f =1; for (int j=1;j<=i;j++){ f = f*j; } return f; }
113
Observar que la variable auxiliar f, que contiene el producto de los primeros i nmeros u naturales, debe ser inicializada a 1. Si se inicializara a 0, factorial(n) ser 0 para todo n. a Esta funcin no considera el caso n=0, pero al menos para el resto de los naturales funo cionar bien. a
4.3.6.
Con el concepto de funcin hemos apreciado que es posible que coexistan variables con el o mismo nombre en puntos distintos del programa, y que signiquen cosas distintas. Conviene entonces tener en claro tres conceptos que estn ligados a esta propiedad: a Alcance (scope) La seccin del cdigo durante la cual el nombre de una variable puede ser o o usado. Comprende desde la declaracin de la variable hasta el nal del cuerpo de la o funcin donde es declarada. o Si la variable es declarada dentro de una funcin es local . Si es denida fuera de todas o las funciones (incluso fuera de main), la variable es global. Visibilidad Indica cules de las variables, actualmente al alcance, pueden ser accesadas. En a u a nuestros ejemplos (subseccin 4.3.3), la variable i en main an est al alcance dentro o de la funcin funcion, pero no es visible, y por eso es posible reutilizar el nombre. o Tiempo de vida Indica cundo las variables son creadas y cundo destruidas. En general a a este concepto coincide con el alcance (las variables son creadas cuando son declaradas y destruidas cuando la funcin dentro de la cual fueron declaradas termina), salvo porque o es posible denir: (a) variables dinmicas, que no tienen alcance, sino slo tiempo de a o vida; (b) variables estticas, que conservan su valor entre llamadas sucesivas de una a funcin (estas variables tienen tiempo de vida mayor que su alcance). Para declarar o estas ultimas se usa un modicador static. El efecto del modicador static se aprecia en el siguiente ejemplo: #include <iostream> int f();
114 using namespace std; int main(){ cout << f() << endl; cout << f() << endl; return 0; } int f(){ int x=0; x++; return x; }
La funcin f simplemente toma el valor inicial de x y le suma 1. Como cada vez que la o funcin es llamada la variable local x es creada e inicializada, el resultado de este programa o es siempre un 1 en pantalla: 1 1 Ahora modiquemos la funcin, haciendo que x sea una variable esttica: o a #include <iostream> int f(); using namespace std; int main(){ cout << f() << endl; cout << f() << endl; return 0 ; } int f(){ static int x=0; x++; return x; } Ahora, al llamar a f por primera vez, la variable x es creada e inicializada, pero no destruida cuando la funcin termina, de modo que conserva su valor cuando es llamada por o segunda vez: 1 2
4.3. FUNCIONES. Veamos un ejemplo de una variable esttica en el clculo del factorial: a a int factorial2(int i=1){ static int fac = 1; fac*=i; return fac ; } int main (){ int n=5; int m=n; while(n>0) factorial2(n--); cout << "El factorial de "<< m << " es = " << factorial2() << endl; return 0 ; }
115
La idea, si se desea calcular el factorial de 5, por ejemplo, es llamar a la funcin factorial2 o una vez, con argumento n = 5, y despus disminuir n en 1. Dentro de la funcin, una variable e o esttica (fac) aloja el valor 1 5 = 5. Luego se llama nuevamente con n = 4, con lo cual a fac=1*5*4, y as sucesivamente, hasta llegar a n = 1, momento en el cual fac=1*5*4*3*2*1. Al disminuir n en 1 una vez ms, la condicin del while es falsa y se sale del ciclo. Al llamar a o una vez ms a factorial2, esta vez sin argumentos, el programa asume que el argumento a tiene el valor predeterminado 1, y as el resultado es 1*5*4*3*2*1*1, es decir 5!. Observemos el uso del operador de decremento en este programa: factorial2(n--) llama a la funcin con argumento n y despus disminuye n en 1. Esto es porque el operador de o e decremento est actuando como sujo, y es equivalente a las dos instrucciones: a factorial2(n); n--; Si fuera un prejo [factorial2(n--)], primero disminuir n en 1, y llamar luego a factorial2 a a con el nuevo valor de n Este ejemplo de clculo del factorial ilustra el uso de una variable esttica, que aloja los a a productos parciales de los nmeros enteros, pero no es un buen ejemplo de una funcin que u o calcule el factorial, porque de hecho esta funcin no lo calcula: es main quien, a travs de o e sucesivas llamadas a factorial2, calcula el factorial, pero la funcin en s no. o
4.3.7.
Recursin. o
C++ soporta un tipo especial de tcnica de programacin, la recursin, que permite que e o o una funcin se llame a s misma (esto es no trivial, por cuanto si denimos, digamos, una o funcin f, dentro del cuerpo de la implementacin no hay ninguna declaracin a una funcin o o o o f, y por tanto en principio no se podr usar f porque dicho nombre no estar en scope; a a C++ permite soslayar este hecho). La recursin permite denir de modo muy compacto una o funcin que calcule el factorial de un nmero entero n. o u
116
int factorial3(int n){ return (n<2) ? 1: n * factorial3(n-1); } int main(){ int n=5; cout << "El factorial de "<< n << " es = " << factorial3(n) << endl; return 0; } En este tercer ejemplo, el factorial de n es denido en funcin del factorial de n 1. o Se ha usado la expresin condicional (operador ?) para compactar an ms el cdigo. Por o u a o ejemplo, al pedir el factorial de 5 la funcin se pregunta si 5 < 2. Esto es falso, luego, la o funcin devuelve a main el valor 5*factorial3(4). A su vez, factorial3(4) se pregunta si o 4 < 2; siendo falso, devuelve a la funcin que la llam (es decir, a factorial3(5)), el valor o o 4*factorial3(3). El proceso sigue hasta que factorial(2) llama a factorial3(1). En ese momento, 1 < 2, y la funcin factorial3(1), en vez de llamar nuevamente al factorial, o devuelve a la funcin que la llam el valor 1. No hay ms llamadas a factorial3, y el o o a proceso de recursin se detiene. El resultado nal es que main recibe el valor factorial3(5) o = 5*factorial3(4) = = 5*4*3*2*factorial3(1) = 5*4*3*2*1= 120. Este tercer cdigo para el clculo del factorial s considera el caso n = 0, y adems es ms o a a a eciente, al ser ms compacto. a La recursin debe ser empleada con cuidado. Es importante asegurarse de que existe o una condicin para la cual la recursin se detenga, de otro modo, caer o o amos en una recursin o innita que har intil nuestro programa. En el caso del factorial, pudimos vericar que dicha a u condicin existe, por tanto el programa es nito. En situaciones ms complicadas puede no o a ser tan evidente, y es responsabilidad del programador como siempre revisar que todo est bajo control. e
4.3.8.
Funciones internas.
Existen muchas funciones previamente implementadas en C++ almacenadas en distintas bibliotecas. Una de las bibliotecas importante es la matemtica. Para usarla uno debe incluir a el archivo de header <cmath> y luego al compilar agregar al nal del comando de compilacin o -lm:
si se desea crear un ejecutable <salida> a partir del cdigo en <fuente>.cc. o Veamos algunas de estas funciones:
4.4. PUNTEROS. pow(x,y) fabs(x) sqrt(x) sin(x) cos(x) tan(x) atan(x) atan2(y, x) exp(x) log(x) log10(x) floor(x) ceil(x) fmod(x,y) Eleva a potencia, xy Valor absoluto Ra cuadrada z Seno y coseno Tangente Arcotangente de x en [, ] Arcotangente de y/x en [, ] Exponencial Logaritmo natural y logaritmo en base 10 Entero ms cercano hacia abajo (e.g. floor(3.2)=3) a Entero ms cercano hacia arriba (e.g. ceil(3.2)=4) a El resto de x/y (e.g. fmod(7.3, 2)=1.3)
117
Para elevar a potencias enteras, es ms conveniente usar la forma expl a cita en vez de la funcin pow, i.e. calcular x^3 como x*x*x es ms eciente computacionalmente que pow(x,3), o a debido a los algoritmos que usa pow para calcular potencias. Estos son ms convenientes a cuando las potencias no son enteras, en cuyo caso no existe una forma expl cita en trminos e de productos.
4.4.
Punteros.
Una de las ventajas de C++ es permitir el acceso directo del programador a zonas de memoria, ya sea para crearlas, asignarles un valor o destruirlas. Para ello, adems de los tipos a de variables ya conocidos (int, double, etc.), C++ proporciona un nuevo tipo: el puntero. El puntero no contiene el valor de una variable, sino la direccin de memoria en la cual dicha o variable se encuentra. Un pequeo ejemplo nos permite ver la diferencia entre un puntero y la variable a la cual n ese puntero apunta: int main(){ int i = 42; int * p = &i; cout << "El valor del puntero es: " << p << endl; cout << "Y apunta a la variable: " << *p << endl; return 0; } En este programa denimos una variable i entera. Al crear esta variable, el programa reserv un espacio adecuado en algn sector de la memoria. Luego pusimos, en esa direccin o u o de memoria, el valor 42. En la siguiente l nea creamos un puntero a i, que en este caso denominamos p. Los punteros no son punteros a cualquier cosa, sino punteros a un tipo particular de variable. Ello es maniesto en la forma de la declaracin: int * p. En la o misma l nea asignamos a este puntero un valor. Ese valor debe ser tambin una direccin de e o memoria, y para eso usamos &i, que es la direccin de memoria donde est i. Ya hemos visto o a antes el uso de & para entregar una direccin de memoria, al estudiar paso de parmetros a o a funciones por referencia (4.3.3).
118
Al ejecutar este programa vemos en pantalla los mensajes: El valor del puntero es: 0xbffff9d8 Y apunta a la variable: 42 Primero obtenemos un nmero hexadecimal imposible de determinar a priori , y que corresu ponde a la direccin de memoria donde qued ubicada la variable i. La segunda l o o nea nos da el valor de la variable que est en esa direccin de memoria: 42. Puesto que * aplicado a o a un puntero entrega el contenido de esa direccin de memoria, se le denomina operador de o desreferenciacin. o En este ejemplo, hemos creado un puntero que contiene la direccin de memoria de una o variable preexistente: declaramos una variable, esa variable queda en alguna direccin de o memoria, y despus asignamos esa direccin de memoria a un puntero. En este caso, podemos e o referirnos a la variable tanto por su nombre (i) como por su puntero asociado (p_i). Tambin es posible crear directamente una direccin de memoria, sin necesidad de crear e o una variable antes. En este caso, la unica forma de manipular este objeto es a travs de su e puntero, porque no existe ninguna variable y por tanto ningn nombre asociado a l. Esto se u e hace con el operador new. El mismo ejemplo anterior puede ser reescrito usando slo punteros: o int main(){ int * p = new int; *p = 42; cout << "El valor del puntero es: " << p << endl; cout << "Y apunta a la variable: " << *p << endl; delete p; return 0;
} La primera l nea crea un nuevo puntero a int llamado p. new verica que haya suciente memoria para alojar un nuevo int, y si es as reserva ese espacio de memoria. En p queda la direccin de la memoria reservada. Esto es equivalente a la declaracin int i; del programa o o anterior, salvo que ahora la unica manera de accesar esa direccin de memoria es a travs o e del puntero p. A continuacin se coloca dentro de esa direccin (observar la presencia del o o operador de desreferenciacin *) el nmero 42. El programa manda a pantalla la misma o u informacin que la versin anterior, salvo que seguramente el valor de p ser distinto. o o a Finalmente, ya que el puntero no volver a ser usado, la direccin de memoria debe ser a o liberada para que nuestro u otros programas puedan utilizarla. Ello se realiza con el operador delete. Todo puntero creado con new debe ser, cuando ya no se utilice, borrado con delete. Ello evitar desagradables problemas en nuestro programa debido a fuga de memoria (memory a leak ). Los punteros tienen gran importancia cuando de manejar datos dinmicos se trata, es a decir, objetos que son creados durante la ejecucin del programa, en nmero imposible de o u predecir al momento de compilar. Por ejemplo, una aplicacin X-windows normal que crea o una, dos, tres, etc. ventanas a medida que uno abre archivos. En este caso, cada ventana es un objeto dinmico, creado durante la ejecucin, y la unica forma de manejarlo es a travs a o e de un puntero a ese objeto, creado con new cuando la ventana es creada, y destruido con delete cuando la ventana es cerrada.
119
4.5.
4.5.1.
Matrices o arreglos.
Declaracin e inicializacin. o o
Podemos declarar (e inicializar inmediatamente) matrices de enteros, reales de doble precisin, caracteres, etc., segn nuestras necesidades. o u int a[5]; double r[3] = {3.5, 4.1, -10.8}; char palabra[5]; Una vez declarada la matriz (digamos a[5]), los valores individuales se accesan con a[i], con i desde 0 a 4. Por ejemplo, podemos inicializar los elementos de la matriz as : a[0] = 3; a[3] = 5; ... o si queremos ingresarlos desde el teclado: for (i = 0; i < 5; i++){ cin >> a[i]; } Y si deseamos escribirlos en pantalla: for (i = 0; i < 5; i++){ cout << a[i] ; }
4.5.2.
Si deseamos, por ejemplo, disear una funcin que mande los elementos de una matriz n o a pantalla, necesitamos entregarle como parmetro la matriz que va a utilizar. Para ello se a agrega [] luego del nombre de la variable, para indicar que se trata de una matriz: void PrintMatriz(int, double []); int main(){ double matriz[5] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(5, matriz); return 0; } void PrintMatriz(int i, double a[]){ for (int j = 0; j < i; j++){ cout << "Elemento " << j << " = " << a[j] << endl; } }
120
Observemos que la funcin debe recibir dos parmetros, uno de los cuales es la dimensin o a o de la matriz. Esto se debe a que cuando las matrices son usadas como parmetros la infora macin de su dimensin no es traspasada, y debe ser comunicada independientemente. Una o o ligera optimizacin al programa anterior es modicar main a: o int main() { int dim = 5; double matriz[dim] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(dim, matriz); return 0; } De este modo, si eventualmente cambiamos de opinin y deseamos trabajar con matrices o de longitud distinta, slo hay que modicar una l o nea de cdigo (la primera) en todo el o programa, el cual puede llegar a ser bastante largo por cierto. (En el ejemplo, tambin habr e a que cambiar la l nea de inicializacin de la matriz, porque asume que la matriz requiere slo 5 o o elementos, pero de todos modos deber ser clara la enorme conveniencia.) Podemos reescribir a este programa con un comando de preprocesador para hacer la denicin de la dimensin: o o #include <iostream> #define DIM 5 using namespace std; int main(){ double matriz[DIM] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(DIM, matriz); return 0; }
4.5.3.
Asignacin dinmica. o a
La reserva de memoria para la matriz podemos hacerla en forma dinmica ocupando el a operador new que pedir al sistema la memoria necesaria, si est disponible el sistema se a a la asignar. Como con cualquier puntero, una vez desocupado el arreglo debemos liberar la a memoria con el comando delete. #include <iostream> using namespace std; int main() { cout<<"Ingrese la dimension deseada :" ; int dim ; cin >> dim ; double * matriz = new double[dim] ; // Reserva la memoria for(int i=0; i < dim; i++) {
4.5. MATRICES O ARREGLOS. cout << "Ingrese elemento "<< i <<" : "; cin >> matriz[i] ; } for (int i=0;i<dim;i++){ cout << matriz[i] << ", "; } cout << endl; delete [] matriz; return 0; } // Libera la memoria reservada
121
Este ejemplo permite apreciar una gran ventaja del uso de punteros, al permitirnos liberarnos de denir la dimensin de una matriz como una constante. Aqu dim es simplemente un int. o , La asignacin dinmica permite denir matrices cuya dimensin se determina recin durante o a o e la ejecucin. o Observemos nalmente que la liberacin de memoria, en el caso de arreglos, se hace con o el operador delete [], no delete como en los punteros usuales.
4.5.4.
Matrices multidimensionales.
Es fcil declarar e inicializar matrices de ms de una dimensin: a a o double array[10][8]; int array[2][3] = {{1, 2, 3}, {4, 5, 6}}; Una operacin usual es denir primero las dimensiones de la matriz, y luego llenar sus o elementos uno por uno (o desplegarlos en pantalla), recorriendo la matriz ya sea por las o por columnas. Hay que tener cuidado del orden en el cual uno realiza las operaciones. En el siguiente cdigo, denimos una matriz de 10 las y 3 columnas, la llenamos con ceros o elemento por elemento, y luego inicializamos tres de sus elementos a nmeros distintos de u cero. Finalmente desplegamos la matriz resultante en pantalla: #include <iostream> using namespace std; int main(){ int dimx=3, dimy=10; double a[dimy][dimx]; for (int i=0;i<dimy;i++){ for (int j=0;j<dimx;j++){ a[i][j]=0;
for (int i=0;i<dimy;i++){ for (int j=0;j<dimx;j++){ cout << a[i][j] << ", "; } cout << endl; } return 0; } Inicializar los elementos a cero inicialmente es particularmente relevante. Si no, la matriz se llenar con elementos aleatorios. Veamos un ejemplo a continuacin que ilustra el paso de a o arreglos multidimensionales como un parmetro a una funcin y la necesidad de inicializar a a o cero los elementos de un arreglo #include <iostream> #define NROWS 3 #define NCOLUMNS 2 using namespace std; void f(int, int, int [][NCOLUMNS]); int main() { int array[NROWS][NCOLUMNS]; f(NROWS, NCOLUMNS, array); for(int i=0;i<NROWS;i++) { for(int j=0;j<NCOLUMNS;j++) array[i][j]=0; } f(NROWS, NCOLUMNS, array); return 0; } void f(int n, int m, int a[][NCOLUMNS]) { for(int i=0;i<n;i++) { for(int j=0;j<m;j++) cout <<a[i][j]<<" "; cout << endl; } }
123
4.5.5.
Una palabra, frase o texto ms largo es representado internamente por C++ como una a matriz de chars. A esto se le llama cadena (string). Sin embargo, esto ocasiona un problema, pues las matrices deben ser denidas con dimensin constante (a menos que sean denidas o dinmicamente), y las palabras pueden tener longitud arbitraria. La convencin de C++ para a o resolver el problema es aceptar que una cadena tiene longitud arbitraria, pero debe indicar dnde termina. Esto se hace con el char nulo: \0. As para asignar a la variable palabra o , el valor Hola, debe denirse como una matriz de dimensin 5 (una ms que el nmero de o a u letras): char palabra[5] = {H, o, l, a, \0}; Para escribir Hola en pantalla basta recorrer los elementos de palabra uno a uno: for (i = 0; i < 5; i++) { cout << palabra[i]; } Si tuviramos que hacer esto cada vez que queremos escribir algo a pantalla no ser muy e a cmodo. Por ello, tambin podemos escribir Hola en pantalla simplemente con cout << "Hola", o e y de hecho se fue el primer ejemplo de este cap e tulo. De hecho, la declaracin de palabra o podr haberse escrito: a char palabra[5] = "Hola"; Esto ya es bastante ms cmodo, aunque persiste la inconsistencia de denir palabra con a o dimensin 5, cuando en realidad al lado derecho de la asignacin hay un objeto con slo 4 o o o elementos (visibles). Este y otros problemas asociados con el manejo convencional de cadenas en C++ se resuelven incluyendo el header string. Usando string. El cdigo anterior se puede reescribir: o #include <iostream> #include <string> using namespace std; int main(){ string palabra = "Hola"; cout << palabra << endl; return 0; }
124
Observar que la l nea a incluir es #include <string>, sin la extensin .h. Al incluir o string, las cadenas pueden ser declaradas como objetos tipo string en vez de arreglos de char. El hecho de que ya no tengamos que denir a priori la dimensin de la cadena o es una gran ventaja. De hecho, permite ingresar palabras desde el teclado trivialmente, sin preocuparse de que el input del usuario sea demasiado grande (tal que supere la dimensin del o arreglo que podamos haber declarado inicialmente) o demasiado corto (tal que se traduzca en un despilfarro de memoria por reservar ms memoria para el arreglo de la que realmente a se necesita): #include <iostream> #include <string> using namespace std; int main(){ string palabra; cin >> palabra; return 0; } Adems, este nuevo tipo string permite acceder a un sin nmero de funciones adicionales a u que facilitan enormemente el manejo de cadenas. Por ejemplo, las cadenas se pueden sumar, donde la suma de cadenas a y b est denida (siguiendo la intuicin) como la cadena que a o resulta de poner b a continuacin de a: o #include <iostream> #include <string> using namespace std; int main(){ string texto1 = "Primera palabra"; string texto2 = "Segunda palabra"; cout << texto1 << endl << texto2 << endl; cout << texto1 + ", " + texto2 << endl; // La ultima linea es equivalente a: // string texto3 = texto1 + ", " + texto2; // cout << texto3 << endl; return 0 ; } El output de este programa ser: a Primera palabra Segunda palabra Primera palabra, Segunda palabra
125
Dijimos que es muy fcil ingresar una cadena desde el teclado, pues no es necesario a denir la dimensin desde el comienzo. Sin embargo, el cdigo anterior, usando cin, no o o es muy general, porque el input termina cuando el usuario ingresa el primer cambio de l nea o el primer espacio. Esto es muy cmodo cuando queremos ingresar una serie de vao lores (por ejemplo, para llenar un arreglo), pues podemos ingresarlos ya sea en la forma: 1<Enter> 2<Enter> 3<Enter>, etc., o 1 2 3, etc, pero no es ptimo cuando deseamos ino gresar texto, que podr constar de ms de una palabra y, por tanto, necesariamente incluir a a a espacios (por ejemplo, al ingresar el nombre y apellido de una persona). Sin explicar demasiado por qu, digamos que la solucin a este problema es utilizar una funcin asociada a cin e o o llamada get, y leer desde el teclado hasta que el usuario d el primer cambio de l e nea. Un ejemplo simple lo encontramos en el siguiente cdigo: o #include <iostream> #include <string> using namespace std; int main(){ string texto1 = "El resultado es: " ; string texto2 =""; char ch; cout << "Entre un string:" << endl; while( ( ch = cin.get() ) != \n ) cout << texto1 + texto2 << endl; return 0; } Observamos que cin.get() no necesita argumento y devuelve un char el cual es primero comparado con el caracter de n de l nea y luego acumulado en texto2.
4.6.
Manejo de archivos.
Una operacin usual en todo tipo de programas es la interaccin con archivos. Ya sea que o o el programa necesite conocer ciertos parmetros de conguracin, hacer anlisis estad a o a stico sobre un gran nmero de datos generados por otro programa, entregar las coordenadas de u los puntos de una trayectoria para gracarlos posteriormente, etc., lo que se requiere es un modo de ingresar datos desde, o poner datos en, archivos. En C++ ello se efecta incluyendo u el header fstream.
4.6.1.
Archivos de salida.
int main(){ ofstream nombre_logico("nombre_fisico.dat"); int i = 3, j; cout << i << endl; nombre_logico << i << endl; cout << "Ingrese un numero entero: "; cin >> j; cout << j << endl; nombre_logico << j << endl; nombre_logico.close(); return 0; } La primera l nea de main dene un objeto de tipo ofstream (output le stream). Esto corresponde a un archivo de salida. Dentro de main este archivo ser identicado por a una variable llamada nombre_logico, y corresponder a un archivo en el disco duro llamaa do nombre_fisico.dat. Naturalmente, el identicador nombre_logico puede ser cualquier nombre de variable vlido para C++, y nombre_fisico.dat puede ser cualquier nombre de a archivo vlido para el sistema operativo. En particular, se pueden tambin dar nombres que a e incluyan paths absolutos o relativos: ofstream nombre_logico_1("/home/vmunoz/temp/nombre_fisico.dat"); ofstream nombre_logico_2("../nombre_fisico.dat"); Cuando creamos un objeto del tipo archivo, sin importar si es de salida o de entrada, podemos inicializarlo con un nombre de archivo f sico. Este nombre lo podemos almacenar previamente en una variable de string, llamemosla mi_nombre_archivo. En este caso, cuando creamos el objeto ofstream debemos usar un mtodo del objeto string que devuelve un e puntero a char, para poder inicializar el objeto ofstream. Veamos la sintxis expl a citamente string mi_nombre_archivo=archivo.txt; ofstream nombre_logico_1( mi_nombre_archivo.c_str()); Las l neas tercera y sexta de main env an a nombre_logico (es decir, escribe en nombre_fisico.dat), las variables i y j. Observar la analog que existe entre estas operaa ciones y las que env la misma informacin a pantalla.4 Si ejecutamos el programa y en an o el teclado ingresamos el nmero 8, al nalizar la ejecucin el archivo nombre_fisico.dat u o tendr los dos nmeros escritos: a u 3 8
Esta analog no es casual y se entiende con el concepto de clases (Sec. 4.8). fstream e iostream denen a clases que heredan sus propiedades de un objeto abstracto base, comn a ambas, y que en el caso de iostream u se concreta en la salida estndar pantalla, y en el de fstream en un archivo. a
4
127
Finalmente, el archivo creado debe ser cerrado (nombre_logico.close()). Si esta ultima operacin se omite en el cdigo, no habr errores de compilacin, y el programa se encaro o a o gar de cerrar por s solo los archivos abiertos durante su ejecucin, pero un buen programador a o debiera tener cuidado de cerrarlos expl citamente. Por ejemplo, un mismo programa podr a desear utilizar un mismo archivo ms de una vez, o varios programas podr querer acceder a an al mismo archivo, y si no se ha insertado un close en el punto adecuado esto podr provocar a problemas. El archivo indicado al declarar la variable de tipo ofstream tiene modo de escritura, para permitir la salida de datos hacia l. Si no existe un archivo llamado nombre_fisico.dat es e creado; si existe, los contenidos antiguos se pierden y son reemplazados por los nuevos. No siempre deseamos este comportamiento. A veces deseamos agregar la salida de un programa a un archivo de texto ya existente. En ese caso la declaracin del archivo es diferente, para o crear el archivo en modo append: #include <iostream> #include <fstream> using namespace std; int main(){ ofstream nombre_logico("nombre_fisico.dat",ios::app); int i = 3; nombre_logico << i << endl; nombre_logico.close(); return 0; } Si ejecutamos este programa y el archivo nombre_fisico.dat no existe, ser creado. El a resultado ser un archivo con el nmero 3 en l. Al ejecutarlo por segunda vez, los datos se a u e ponen a continuacin de los ya existentes, resultando el archivo con el contenido: o 3 3 La l nea del tipo ofstream a("b") es equivalente a una del tipo int i=3, declarando una variable (a/i) de un cierto tipo (ofstream/int) y asignndole un valor simultneamente a a "b"/3. Como para los tipos de variables predenidos de C++, es posible separar declaracin o y asignacin para una variable de tipo ofstream: o ofstream a; a.open("b"); es equivalente a ofstream a("b"). Esto tiene la ventaja de que podr amos usar el mismo nombre lgico para identicar dos archivos f o sicos distintos, usados en distintos momentos del programa:
128
ofstream a; a.open("archivo1.txt"); // Codigo en que "archivo1.txt" es utilizado a.close(); a.open("archivo2.txt"); // Ahora "archivo2.txt" es utilizado a.close(); Observar la necesidad del primer close, que permitir liberar la asociacin de a a un nombre a o f sico dado, y reutilizar la variable lgica en otro momento. o En los ejemplos hemos escrito solamente variables de tipo int en los archivos. Esto por cierto no es restrictivo. Cualquiera de los tipos de variables de C++ float, double, char, etc. se puede enviar a un archivo del mismo modo. Dicho esto, en el resto de esta seccin o seguiremos usando como ejemplo el uso de int.
4.6.2.
Archivos de entrada.
Ya sabemos que enviar datos a un archivo es tan fcil como enviarlos a pantalla. Cmo a o hacemos ahora la operacin inversa, de leer datos desde un archivo? Como es de esperar, es tan o fcil como leerlos desde el teclado. Para crear un archivo en modo de lectura, basta declararlo a de tipo ifstream (input le stream). Por ejemplo, si en nombre_logico.dat tenemos los siguientes datos: 3 6 9 12 el siguiente programa, #include <iostream> #include <fstream> using namespace std; int main(){ ifstream nombre_logico("nombre_fisico.dat"); int i, j,k,l; nombre_logico >> i >> j >> k >> l; cout << i << "," << j << "," << k << "," << l << endl; nombre_logico.close(); return 0; }
129
ser equivalente a asignar i=3, j=6, k=9, l=12, y luego enviar los datos a pantalla. Observar a que la sintaxis para ingresar datos desde un archivo, nombre_logico >> i, es idntica a e cin >> i, para hacerlo desde el teclado. Al igual que cin, espacios en blanco son equivalentes a cambios de l nea, de modo que el archivo podr haber sido tambin: a e 3 6 9 12 Por cierto, el ingreso de datos desde un archivo se puede hacer con cualquier tcnica, por e ejemplo, usando un for: ifstream nombre_logico("nombre_fisico.dat"); int i; for (int j=0;j<10;j++){ nombre_logico >> i; cout << i << ","; } nombre_logico.close(); } Como con ofstream, es posible separar declaracin e implementacin: o o ifstream a; a.open("b"); a.close();
4.6.3.
Ocasionalmente nos encontraremos con la necesidad de usar un mismo archivo, en el mismo programa, a veces para escribir datos, y otras veces para leer datos. Por ejemplo, podr amos tener una secuencia de datos en un archivo, leerlos, y de acuerdo al anlisis de a esos datos agregar ms datos a continuacin del mismo archivo, o reemplazar los datos ya a o existentes con otros. Necesitamos entonces un tipo de variable exible, que pueda ser usado como entrada y salida. Ese tipo es fstream. Todo lo que hemos dicho para ofstream y ifstream por separado es cierto simultneamente para fstream.5 Para especicar si el archivo a debe ser abierto en modo de escritura o lectura, open contiene el argumento ios::out o ios::in, respectivamente. Por ejemplo, el siguiente cdigo escribe el nmero 4 en un archivo, o u y luego lo lee desde el mismo archivo: #include <iostream> #include <fstream> using namespace std; int main(){ fstream nombre_logico;
Nuevamente, este hecho se debe al concepto de clases que subyace a las deniciones de estos tres tipos de variables; fstream es una clase derivada a la vez de ofstream y de ifstream, heredando las propiedades de ambas.
5
130
nombre_logico.open("nombre_fisico.dat",ios::out); int i = 4,j; nombre_logico << i << endl; nombre_logico.close(); nombre_logico.open("nombre_fisico.dat",ios::in); nombre_logico >> j; cout << j << endl; nombre_logico.close(); return 0; } Las dos primeras l neas de main separan declaracin y asignacin, y son equivalentes a o o fstream nombre_logico("nombre_fisico.dat",ios::out);, pero lo hemos escrito as pa ra hacer evidente la simetr entre el uso del archivo como salida primero y como entrada a despus. e De lo anterior, se deduce que: fstream archivo_salida("salida.dat",ios::out); fstream archivo_entrada("entrada.dat",ios::in); es equivalente a ofstream archivo_salida("salida.dat"); ifstream archivo_entrada("entrada.dat");
4.7.
Para ejecutar un programa compilado en C++, escribimos su nombre en el prompt: user@host:~/$ programa Si el mismo usuario desea ejecutar alguno de los comandos del sistema operativo, debe hacer lo mismo: user@host:~/$ ls Sin embargo, ls es en realidad el nombre de un archivo ejecutable en el directorio /bin, de modo que en realidad no hay diferencias entre nuestro programa y un comando del sistema operativo en ese sentido. Sin embargo, stos pueden recibir argumentos y opciones. Por e ejemplo, para ver todos los archivos que comienzan con l en el directorio local basta con darle a ls el argumento l*: ls l*. Si queremos ordenar los archivos en orden inverso de modicacin, basta dar otro argumento, en forma de opcin: ls -tr l*. Se ve entonces que o o los argumentos de un archivo ejecutable permiten modicar el comportamiento del programa de modos espec cos.
131
Es posible hacer lo mismo con archivos ejecutables hechos por el usuario? La respuesta es s y para eso se usan los argumentos del main. Recordemos que main es una funcin, , o pero hasta el momento no hemos aprovechado esa caracter stica. Simplemente sabemos que el programa empieza a ejecutarse en la l nea donde est la funcin main. Adems, siempre a o a hemos escrito esa l nea como main(). Sin embargo, main, como cualquier funcin, es capaz de o aceptar argumentos. Espec camente, acepta dos argumentos, el primero es un entero (que cuenta el nmero de argumentos que main recibi), y el segundo es un puntero a un arreglo u o de caracteres (que contiene los distintos argumentos, en forma de cadenas de caracteres, que se le entregaron). Por ejemplo: #include <iostream> using namespace std; int main( int argc, char * argv[]) { for(int i = 0; i < argc; i++) { cout << argv[i] << endl ; } return 0; } Si llamamos a este programa argumentos, obtenemos distintas salidas al llamarlo con distintos argumentos: user@host:~/$ argumentos argumentos user@host:~/$ argumentos ap k 5 argumentos ap k 5 user@host:~/$ argumentos -t -s 4 arg1 argumentos -t -s 4 arg1 Observar que el primer argumento del programa es siempre el nombre del propio programa. Naturalmente, ste es un ejemplo muy simple. Es tarea del programador decidir cmo manejar e o cada una de las opciones o argumentos que se le entregan al programa desde la l nea de comandos, escribiendo el cdigo correspondiente. o
132
4.7.1.
Un segundo aspecto con el cual no hemos sido sistemticos es que main, como toda funcin, a o tiene un tipo de retorno. En el caso de main, ese tipo debe ser int. Este int es entregado al sistema operativo, y puede servir para determinar si el programa se ejecut con normalidad o o si ocurri algo anormal. Podr o amos hacer ese valor de retorno igual a 0 o 1, respectivamente. As la siguiente estructura es correcta: , int main(){ // Codigo
return 0; } En este caso, el programa entrega siempre el valor 0 al sistema operativo. Los cdigos del tipo: o main(){ // Codigo
} tambin compilan, pero el compilador emite una advertencia si es llamado con la opcin e o -Wall (Warning all ). En el primer caso, la advertencia es: warning: ANSI C++ forbids declaration main with no type En el segundo: return type for main changed to int En general, siempre es conveniente compilar con la opcin -Wall, para lograr que nuestro o cdigo est realmente correcto (g++ -Wall <archivo>.cc -o <archivo>). o e
4.8. CLASES.
133
4.8.
Clases.
C++ dispone de una serie de tipos de variables con las cuales nos est permitido operar: a int, double, char, etc. Creamos variables de estos tipos y luego podemos operar con ellas: int x = y = int x, y; 3; 6; z = x + y;
No hay, sin embargo, en C++, una estructura predenida que corresponda a nmeros u complejos, vectores de dimensin n o matrices, por ejemplo. Y sin embargo, nos agradar o a disponer de nmeros complejos que pudiramos denir como u e z = (3,5); w = (6,8); y que tuvieran sentido las expresiones a b c d e f = = = = = = z + w; z * w; z / w; z + 3; modulo(z); sqrt(z);
Todas estas expresiones son completamente naturales desde el punto de vista matemtico, a y ser bueno que el lenguaje las entendiera. Esto es imposible en el estado actual, pues, por a ejemplo, el signo + es un operador que espera a ambos lados suyos un nmero. Sumar cualquier u cosa con cualquier cosa no signica nada necesariamente, as que slo est permitido operar o a con nmeros. Pero los humanos sabemos que los complejos son nmeros. Cmo dec u u o rselo al computador? Cmo convencerlo de que sumar vectores o matrices es tambin posible o e matemticamente, y que el mismo signo + deber servir para todas estas operaciones? a a La respuesta es: a travs del concepto de clases. Lo que debemos hacer es denir una clase e de nmeros complejos. Llammosla Complejo. Una vez denida correctamente, Complejo u e ser un tipo ms de variable que el compilador reconocer, igual que int, double, char, etc. a a a Y ser tan fcil operar con los Complejos como con todos los tipos de variables preexistentes. a a Esta facilidad es la base de la extensibilidad de que es capaz C++, y por tanto de todas las propiedades que lo convierten en un lenguaje muy poderoso. Las clases responden a la necesidad del programador de construir objetos o tipos de datos que respondan a sus necesidades. Si necesitamos trabajar con vectores de 5 coordenadas, ser natural denir una clase que corresponda a vectores con 5 coordenadas; si se trata de a un programa de administracin de personal, la clase puede corresponder a un empleado, con o sus datos personales como elementos. Si bien es cierto uno puede trabajar con clases en el contexto de orientacin al procedio miento, las clases muestran con mayor propiedad su potencial con la orientacin al objeto, o donde cada objeto corresponde a una clase. Por ejemplo, para efectuar una aplicacin para o X-windows, la ventana principal, las ventanas de los archivos abiertos, la barra de men, las u cajas de dilogo, los botones, etc., cada uno de estos objetos estar asociado a una clase. a a
134
4.8.1.
Denicin. o
Digamos que queremos una clase para representar a los empleados de una empresa. Llammosla Persona. La convencin aceptada es que los nombres de las clases comiencen e o con mayscula. Esto es porque las clases, recordemos, correspondern a tipos de variables u a tan vlidos como los internos de C++ (int, char, etc.). Al usar nombres con mayscula a u distinguimos visualmente los nombres de un tipo de variable interno y uno denido por el usuario. La estructura m nima de la denicin de la clase Persona es: o class Persona { }; Todas las caracter sticas de la clase se denen entre los parntesis cursivos. e
4.8.2.
Miembros.
Se denomina miembros de una clase a todas las variables y funciones declaradas dentro de una clase. Por ejemplo, para personas, es natural caracterizarlas por su nombre y su edad. Y si se trata de empleados de una empresa, es natural tambin tener una funcin que entregue e o su sueldo: class Persona { string nombre; fecha nacimiento; int rut; double edad(); }; Los miembros de una clase pueden tener cualquier nombre, excepto el nombre de la propia clase dentro de la cual se denen, ese nombre est reservado. a
4.8.3.
Una clase distingue informacin (datos o funciones) privada (accesible slo a otros miemo o bros de la misma clase) y pblica (accesible a funciones externas a la clase). La parte privada u corresponde a la estructura interna de la clase, y la parte pblica a la implementacin (t u o picamente funciones), que permite la interaccin de la clase con el exterior. o Consideremos ahora nuestro deseo de tener una clase que represente nmeros complejos. u Un nmero complejo tiene dos nmeros reales (parte real e imaginaria), y sos son elementos u u e privados, es decir, parte de su estructura interna. Sin embargo, nos gustar poder modicar a y conocer esas cantidades. Eso slo puede hacerse a travs de funciones pblicas. o e u
4.8. CLASES. class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); };
135
En este ejemplo, los miembros privados son slo variables, y los miembros pblicos son slo o u o funciones. Este es el caso t pico, pero puede haber variables y funciones de ambos tipos.
4.8.4.
Hemos denido una clase de nmeros complejos y funciones que nos permiten conocer u y modicar las partes real e imaginaria. Cmo se usan estos elementos? Consideremos el o siguiente programa de ejemplo: using namespace std; class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); }; int main() { Complejo z, w; z.setreal(3); z.setimag(2.8); w.setreal(1.5); w.setimag(5); cout << "El primer numero complejo es: " << z.getreal() << " + i*" << z.getimag() << endl; cout << "El segundo es: " << w.getreal() << " + i*" << z.getimag() << endl; return 0; }
136
Vemos en la primera l nea de main cmo la clase Complejo se usa del mismo modo que o usar amos int o double. Ahora Complejo es un tipo de variable tan vlido como los tipos a predenidos por C++. Una vez denida la variable, el operador de seleccin (.) permite o acceder a las funciones pblicas correspondientes a la clase Complejo, aplicadas a la variable u particular que nos interesa: z.setreal(3) pone en la parte real del Complejo z el nmero u 3, y w.setreal(1.5) hace lo propio con w.
4.8.5.
Ya sabemos cmo declarar funciones miembros en el interior de la clase y cmo usarlas. o o Ahora veamos cmo se implementan. o void Complejo::setreal(double x) { real = x; } void Complejo::setimag(double x) { imaginaria = x; } double Complejo::getreal() { return real; } double Complejo::getimag() { return imaginaria; } Como toda funcin, primero va el tipo de la funcin (void o double en los ejemplos), luego o o el nombre de la funcin y los argumentos. Finalmente la implementacin. Lo diferente es que o o el nombre va precedido del nombre de la clase y el operador :: .
4.8.6.
Constructor.
Al declarar una variable, el programa crea el espacio de memoria suciente para alojarla. Cuando se trata de variables de tipos predenidos en C++ esto no es problema, pero cuando son tipos denidos por el usuario, C++ debe saber cmo construir ese espacio. La funcin o o que realiza esa tarea se denomina constructor. El constructor es una funcin pblica de la clase, que tiene el mismo nombre que ella. o u Agreguemos un constructor a la clase Complejo: class Complejo
4.8. CLASES. { private: double real,imaginaria; public: Complejo(double,double); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y) : real(x), imaginaria(y) {}
137
Denir el constructor de esta manera nos permite crear en nuestro programa variables de tipo Complejo y asignarles valores sin usar setreal() o setimag(): Complejo z (2, 3.8); Complejo w = Complejo(6.8, -3); En el constructor se inicializan las variables internas que nos interesa inicializar al momento de crear un objeto de esta clase. Si una de las variables internas a inicializar es una cadena de caracteres, hay que inicializarla de modo un poco distinto. Por ejemplo, si estamos haciendo una clase OtraPersona que slo tenga el nombre de una persona, entonces podemos denir la clase y su constructor o en la forma: class OtraPersona { private: char nombre[20]; public: Persona(char []); }; Persona::Persona(char a[]) { strcpy(nombre,a); } Si uno no especica el constructor de una clase C++ crea uno default, pero en general ser insuciente para cualquier aplicacin realmente prctica. Es una mala costumbre ser a o a descuidado y dejar estas decisiones al computador.
4.8.7.
Destructor.
As como es necesario crear espacio de memoria al denir una variable, hay que deshacerse de ese espacio cuando la variable deja de ser necesaria. En otras palabras, la clase necesita
138
tambin un destructor . Si la clase es Complejo, el destructor es una funcin pblica de ella, e o u llamada ~Complejo. class Complejo { private: double real, imaginaria; public: Complejo(double,double); ~Complejo(); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y): real(x), imaginaria(y) { } Complejo::~Complejo() { } Como con los constructores, al omitir un destructor C++ genera un default, pero es una mala costumbre. . . , etc.
4.8.8.
Arreglos de clases.
Una clase es un tipo de variable como cualquier otra de las predenidas en C++. Es posible construir matrices con ellas, del mismo modo que uno tiene matrices de enteros o caracteres. La unica diferencia con las matrices usuales es que no se pueden slo declarar, o sino que hay que inicializarlas simultneamente. Por ejemplo, si queremos crear una matriz a que contenga 2 nmeros complejos, la l u nea Complejo z[2]; es incorrecta, pero s es aceptable la l nea Complejo z[2] = {Complejo(3.5,-0.8), Complejo(-2,4)};
4.9.
Sobrecarga.
Para que la denicin de nuevos objetos sea realmente util, hay que ser capaz de hacer o con ellos muchas acciones que nos ser naturales. Como ya comentamos al introducir el an concepto de clase, nos gustar sumar nmeros complejos, y que esa suma utilizara el mismo a u
4.9. SOBRECARGA.
139
signo + de la suma usual. O extraerles la ra cuadrada, y que la operacin sea tan fcil z o a como escribir sqrt(z). Lo que estamos pidiendo es que el operador + o la funcin sqrt() o sean polimrcos, es decir, que acten de distinto modo segn el tipo de argumento que o u u se entregue. Si z es un real, sqrt(z) calcular la ra de un nmero real; si es complejo, a z u calcular la ra de un nmero complejo. a z u La tcnica de programacin mediante la cual podemos denir funciones polimrcas se e o o llama sobrecarga.
4.9.1.
Sobrecarga de funciones.
Digamos que la ra cuadrada de un nmero complejo a + ib es (a/2) + i(b/2). (Es ms z u a complicado en realidad, pero no queremos escribir las frmulas ahora.) o Para sobrecargar la funcin sqrt() de modo que acepte nmeros complejos basta denirla o u as : Complejo sqrt(Complejo z) { return Complejo (z.getreal()/2, z.getimag()/2); } Observemos que denimos una funcin sqrt que acepta argumentos de tipo Complejo, y que o entrega un nmero del mismo tipo. Cuando pidamos la ra de un nmero, el computador u z u se preguntar si el nmero en cuestin es un int, double, float o Complejo, y segn eso a u o u escoger la versin de sqrt que corresponda. a o Con la denicin anterior podemos obtener la ra cuadrada de un nmero complejo o z u simplemente con las instrucciones: Complejo z(1,3); Complejo raiz = sqrt(z);
4.9.2.
Sobrecarga de operadores.
Cmo le decimos al computador que el signo + tambin puede aceptar nmeros compleo e u jos? La respuesta es fcil, porque para C++ un operador no es sino una funcin, y la accin a o o de sobrecargar que ya vimos sirve en este caso tambin. La sintaxis es: e Complejo operator + (Complejo z, Complejo w) { return Complejo (z.getreal() + w.getreal(), z.getimag() + w.getimag()); }
4.9.3.
Coercin. o
Sabemos denir a + b, con a y b complejos. Pero qu pasa si a o b son enteros? O reales? e Pareciera que tendr amos que denir no slo o
140
Complejo operator + (Complejo a, Complejo b); sino tambin todas las combinaciones restantes: e Complejo operator + (Complejo a, int b); Complejo operator + (Complejo a, float b); Complejo operator + (int a, Complejo b); etctera. e En realidad esto no es necesario. Por cierto, un nmero real es un nmero complejo con u u parte imaginaria nula, y es posible hacerle saber esto a C++, usando la posibilidad de denir funciones con parmetros default. Basta declarar (en el interior de la clase) el constructor de a los nmeros complejos como u Complejo (double, double = 0); Esto permite denir un nmero complejo con la instruccin: u o Complejo c = Complejo(3.5); resultando el nmero complejo 3.5 + i 0. Y si tenemos una l u nea del tipo: Complejo c = Complejo(3,2.8) + 5; el computador convertir impl a citamente el entero 5 a Complejo (sabe cmo hacerlo porque o el constructor de nmeros complejos acepta tambin un solo argumento en vez de dos), y u e luego realizar la suma entre dos complejos, que es entonces la unica que es necesario denir. a
4.10.
Herencia.
Herencia es el mecanismo mediante el cual es posible denir clases a partir de otras, preservando parte de las propiedades de la primera y agregando o modicando otras. Por ejemplo, si denimos la clase Persona, toda Persona tendr una variable miembro a que sea su nombre. Si denimos una clase Hombre, tambin ser Persona, y por tanto deber e a a tener nombre. Pero adems puede tener esposa. Y ciertamente no toda Persona tiene esposa. a Slo un Hombre. o C++ provee mecanismos para implementar estas relaciones lgicas y poder denir una o clase Hombre a partir de Persona. Lo vemos en el siguiente ejemplo: class Persona { private: string nombre; public: Persona(string = ""); ~Persona(); string getname(); }
141
class Hombre : public Persona { private: string esposa; public: Hombre(string a) : Persona(a) { }; string getwife(); void setwife(string); }; Primero denimos una clase Persona que tiene nombre. Luego denimos una clase Hombre a partir de Persona (con la l nea class Hombre : public Persona). Esto permite de modo automtico que Hombre tenga tambin una variable nombre. Y nalmente, dentro de la clase a e Hombre, se denen todas aquellas caracter sticas adicionales que una Persona no tiene pero un Hombre s esposa, y funciones miembros para modicar y obtener el nombre de ella. : Un ejemplo de uso de estas dos clases: Persona cocinera("Maria"); Hombre panadero("Claudio"); panadero.setwife("Estela"); cout << cocinera.getname() << endl; cout << panadero.getname() << endl; cout << panadero.getwife() << endl