C
C
C
>> DESARROLL DESARROLLO / MICROSOFT PGINAS >> 400 PGINA >> ISBN 978-987-1347-74-2 978-98
>> DESARROLLO DESARROLL / INTERNET PGINAS >> 400 PGINA >> ISBN 978-987-1347-70-4 978-98
>> DESARROLL DESARROLLO / INTERNET >> 368 PGINAS PGINA 978-987-663-039-9 >> ISBN 978-98
>> DESARROLLO DESARROLL PGINAS >> 336 PGINA 978-987-1347-97-1 >> ISBN 978-98
C#
GUA TOTAL DEL PROGRAMADOR
por Nicols Arrioja Landa Cosio
Copyright MMX. Es una publicacin de Fox Andina en coedicin con Gradi S.A. Hecho el depsito que marca la ley 11723. Todos los derechos reservados. No se permite la reproduccin parcial o total, el almacenamiento, el alquiler, la transmisin o la transformacin de este libro, en cualquier forma o por cualquier medio, sea electrnico o mecnico, mediante fotocopias, digitalizacin u otros mtodos, sin el permiso previo y escrito del editor. Su infraccin est penada por las leyes 11723 y 25446. La editorial no asume responsabilidad alguna por cualquier consecuencia derivada de la fabricacin, funcionamiento y/o utilizacin de los servicios y productos que se describen y/o analizan. Todas las marcas mencionadas en este libro son propiedad exclusiva de sus respectivos dueos. Impreso en Argentina. Libro de edicin argentina. Primera impresin realizada en Sevagraf, Costa Rica 5226, Grand Bourg, Malvinas Argentinas, Pcia. de Buenos Aires en VIII, MMX.
ISBN 978-987-26013-5-5
Landa Cosio, Nicols Arrioja C#. - 1a ed. - Buenos Aires : Fox Andina; Gradi; Banfield - Lomas de Zamora, 2010. 400 p. ; 24x17 cm. - (Manual Users; 195) ISBN 978-987-26013-5-5 1. Informtica. I. Ttulo CDD 005.3
PRELIMINARES
Dedicatoria
A Mara Eugenia Prez Duarte por todo su apoyo y gran amistad.
Agradecimientos
A todas aquellas personas que hace 25 aos me introdujeron a la programacin de computadoras y me ensearon las bases de esta disciplina. De Sistem Club al Ing. Alfonso Fernndez de la Fuente y a Jacky, Annie y David Fox, Herbert Schildt y Kris Jamsa. Un agradecimiento especial a mis alumnos y al equipo de la editorial.
www.redusers.com
Prlogo
PRLOGO
La facilidad con que hoy en da se tiene acceso a una computadora ha llevado a las personas a emplearlas en gran cantidad de actividades, usando para ello software que realiza tareas especficas. Cuando se requiere que la computadora realice otro tipo de acciones y los programas con los que se cuenta no lo hacen, es necesario decirle en su propio idioma cmo deber actuar, y para esto se recurre a los lenguajes de programacin. Los lenguajes de programacin intentan parecerse a nuestra propia forma de expresarnos, para ello cuentan con caractersticas propias de sintaxis y semntica, as como smbolos que permiten decirle a la computadora qu procesos y qu datos debe manejar, cmo almacenarlos, qu acciones realizar con ellos y cmo presentarlos al usuario. Por esta razn es importante contar con una metodologa que permita aprender hbitos correctos y efectivos para resolver problemas, los cuales, al ser subdivididos para su mejor comprensin, facilitarn su resolucin. Una vez que se ha comprendido el problema, se construye una secuencia de los pasos a realizar, mejor conocida como algoritmo, el cual permitir probar si la lgica es correcta y si los resultados que se obtendrn sern los adecuados. El potencial de los actuales lenguajes de programacin es enorme, ya que permiten automatizar muy diversos tipos de actividades, disminuyendo de ese modo el tiempo que se invierte al hacerlo de forma manual y, si se aprende a usarlos correctamente, se podr hacer ms sencilla la vida de los usuarios que emplean dichos programas. La experiencia adquirida en el desarrollo de sistemas por parte del Dr. Nicols Arrioja lo ha convertido en una autoridad en cuanto a programacin y buenas prcticas, compartindolas y enseando a alumnos de diferentes instituciones de nivel superior, con resultados excelentes. Es por eso que esta nueva versin del libro podr guiar paso a paso al lector en el uso del poderoso lenguaje de programacin C# del Visual Studio 2010, de modo que al finalizar su aprendizaje, est listo para hacer sus propios programas. Aprender a programar es una tarea que requiere prctica y paciencia, pero tambin es una actividad fascinante, y si adems se cuenta con un excelente libro y la constancia necesaria, los resultados sern excelentes. Felicidades por este nuevo reto que est por comenzar! Mara Eugenia Prez Duarte Maestra en Administracin de Tecnologas de Informacin Coordinadora de Ingenieras en Sistemas Computacionales y Desarrollo de Software Universidad Madero de Mjico
www.redusers.com
PRELIMINARES
EL LIBRO DE UN VISTAZO
El desarrollo de aplicaciones con C# se ha visto modificado en los ltimos tiempos, y este libro apunta a afianzar los conocimientos indispensables que nos permitirn generar aplicaciones profesionales de nivel. Cada captulo est dedicado a una tcnica especfica e ilustrado mediante ejemplos prcticos listos para implementar.
Captulo 1
C# Y .NET Este capitulo nos introduce a la historia del desarrollo de los programas para Windows y cmo el Framework de .NET ayuda a resolver muchos problemas. Aprenderemos cmo crear y ejecutar nuestro primer programa.
Captulo 5
FUNCIONES Y MTODOS Las funciones y los mtodos nos brindan flexibilidad y la capacidad de poder volver a utilizar cdigo fcilmente, y tambin nos ayudan a ordenar nuestros desarrollos, y facilitan su mantenimiento.
Captulo 2
LOS ELEMENTOS BSICOS DE UN PROGRAMA Aprender cmo resolver problemas en la computadora es an ms importante que conocer la sintaxis de un lenguaje. Aqu aprenderemos los elementos bsicos de un programa, pero tambin la metodologa para disear buenos programas desde el inicio.
Captulo 6
LOS ARREGLOS Los arreglos, muy tiles en todos los casos, nos permiten administrar la informacin de una manera fcil y prctica, como si trabajsemos con una planilla de clculo. En este captulo estudiaremos arreglos de una y dos dimensiones, y por supuesto no dejaremos de lado los arreglos de tipo jagged.
Captulo 3
EL PROGRAMA TOMA DECISIONES Los programas de computadora necesitan lgicas complejas, por lo que es importante conocer las estructuras necesarias que nos permitirn decirle a la computadora cmo tomar una decisin.
Captulo 7
LAS COLECCIONES Las colecciones son estructuras de datos que nos permiten trabajar con grupos de informacin. Veremos aquellas ms importantes, como el ArrayList, Stack, Queue y Hashtable.
Captulo 4
CREACIN DE CICLOS Los ciclos nos permiten repetir algo un nmero de veces. Los diferentes tipos de ciclos, sus partes y aplicaciones sern enseados en este captulo. 6
Captulo 8
LAS CADENAS Las cadenas permiten guardar y manipular texto o frases. C# nos provee de stas para su manejo. Aprenderemos cmo hacer uso de las cadenas y trabajar con ellas. www.redusers.com
El libro de un vistazo
Captulo 9
ESTRUCTURAS Y ENUMERACIONES En este captulo aprenderemos cmo crear nuestros propios tipos por medio de las estructuras y enumeraciones. Las estructuras tambin nos permiten agrupar la informacin de una manera ptima, lo cual nos ayuda a manejarla ms fcilmente.
Captulo 11
FLUJOS Y ARCHIVOS Es muy frecuente que necesitemos guardar informacin desde un programa al disco. Por medio de los flujos y los archivos lo podemos hacer. Guardaremos y leeremos cadenas, y veremos que la manipulacin de archivos tambin es posible.
Captulo 10
CMO CREAR NUESTRAS PROPIAS CLASES En este captulo empezaremos a conocer los conceptos de la programacin orientada a objetos, lo ms utilizado hoy en da. Podremos crear nuestras propias clases y nuestros propios objetos, y tambin trabajaremos con mtodos definidos en las clases.
Captulo 12
DEPURACIN La depuracin nos permite corregir los problemas que tiene un programa. Conoceremos los tipos de errores y cmo usar el depurador para eliminarlos. Tambin aprenderemos cmo administrar las excepciones de la mejor manera .
INFORMACIN COMPLEMENTARIA
A lo largo de este manual encontrar una serie de recuadros que le brindarn informacin complementaria: curiosidades, trucos, ideas y consejos sobre los temas tratados. Cada recuadro est identificado con uno de los siguientes iconos:
CURIOSIDADES E IDEAS ATENCIN DATOS TILES Y NOVEDADES SITIOS WEB
www.redusers.com
PRELIMINARES
CONTENIDO
Sobre el autor Prlogo El libro de un vistazo Introduccin 4 5 6 12
Captulo 2
LOS ELEMENTOS BSICOS DE UN PROGRAMA Los lenguajes de programacin Los programas de computadora Las variables Operaciones aritmticas Cmo pedirle datos al usuario 32 32 42 49 56 60 64 69 70
Captulo 1
C# Y .NET Breve historia de la programacin para Windows Descubrir .NET Cmo crear una aplicacin .NET Conseguir un compilador de C# El ambiente de desarrollo Crear nuestra primera aplicacin Resumen Actividades 14 15 17 18 18 19 29 30
Inicio
Pedir ancho
Pedir alto
Mostrar rea
Mostrar permetro
Fin
www.redusers.com
Contenido
Captulo 3
EL PROGRAMA TOMA DECISIONES La toma de decisiones Expresiones relacionales El uso de if El uso de else Cmo usar if anidados Escalera de if-else Expresiones lgicas El uso de switch Resumen Actividades 72 72 76 84 89 92 96 105 109 110
NO Condicin Cdigo S
Captulo 5
Inicio
FUNCIONES Y MTODOS
Pedir dividendo
Las funciones Funciones que ejecutan cdigo Funciones que regresan un valor Funciones que reciben valores Funciones que reciben parmetros y regresan un valor
Resultado = dividendo/divisor
Pedir divisor
Divisor!=0
Optimizar con funciones Paso por copia y paso por referencia Resumen Actividades
NO
Mostrar resultado
Fin
Inicio
Captulo 4
CREACIN DE CICLOS El ciclo for El valor de inicio El lmite de conteo del ciclo Control del incremento Ejemplos con el ciclo for El ciclo do while El ciclo while Resumen Actividades 112 117 119 121 128 134 141 145 146
Pedimos a
Pedimos b
R=a+b
Mostramos r
Fin
www.redusers.com
PRELIMINARES
Captulo 6
LOS ARREGLOS Los arreglos Declaracin de los arreglos de una dimensin Asignacin y uso de valores Arreglos de dos dimensiones Arreglos de tipo jagged Los arreglos como parmetros a funciones Resumen Actividades 212 215 216 189 191 196 205 188
Captulo 8
LAS CADENAS El uso de las cadenas Cmo declarar la cadena El mtodo ToString() Cmo convertir y formatear fechas a cadenas Para darles formato a valores numricos Cmo concatenar cadenas Uso de StringBuilder Comparacin de cadenas Para encontrar una subcadena Para obtener una subcadena Para determinar si una cadena 218 218 232 241 249 253 254 finaliza en una subcadena Cmo copiar una parte de la cadena Cmo insertar una cadena Para encontrar la posicin de una subcadena Justificacin del texto Para eliminar caracteres de la cadena Cmo reemplazar una subcadena
Inicio
256 256 256 257 259 260 261 263 264 265 266 267 268 269 270 271 271 272 275 277 278
Captulo 7
LAS COLECCIONES Las colecciones ms importantes El ArrayList El Stack El Queue El Hashtable Resumen Actividades
Inicializacin
Condicin S Cdigo NO
'H'
'o'
'l'
'a'
''
'm'
'u'
'n'
'H'
'o'
'l'
'a'
Incremento
'm'
'u'
'n'
'd'
'o'
Fin
'r'
'e'
'd'
'o'
'n'
'd'
'o'
10
www.redusers.com
Contenido
Captulo 9
ESTRUCTURAS Y ENUMERACIONES Las estructuras Cmo definir una estructura Cmo acceder a los campos de la estructura Cmo mostrar los campos de la estructura Creacin de un constructor para la estructura Estructuras enlazadas Las enumeraciones Resumen Actividades 286 299 309 315 316 283 283 280 280
Convertir un objeto a cadena El constructor en las clases Sobrecarga del constructor Resumen Actividades
Cubo + lado: int + rea: int + volumen: int + CalculaArea() : void + CalculaVolumen() : void
Captulo 11
FLUJOS Y ARCHIVOS
Agenda Nombre: String Direccin: String Telfono: String Edad: Int
Los flujos Los stream en la memoria El uso de archivos Resumen Actividades P . Actual
Captulo 10
CMO CREAR NUESTRAS PROPIAS CLASES La programacin orientada a objetos Las clases Cmo declarar la clase y los datos Cmo crear la instancia de nuestra clase Cmo asignarles valores a datos publicos Cmo invocar mtodos de un objeto Cmo imprimir un dato pblico Proteccin de datos y creacin de propiedades Cmo acceder a las propiedades Mtodos pblicos y privados 329 333 333 324 325 325 324 318 318 320
Tamao H O L A A T O D O
Capacidad
Captulo 12
DEPURACIN Cmo empezar a depurar un programa 374 Corregir los errores de compilacin Cmo corregir los errores en tiempo de ejecucin Cmo manejar los errores Resumen Actividades 379 383 391 392 374
www.redusers.com
11
PRELIMINARES
INTRODUCCIN
La programacin de computadoras es una actividad fascinante, el poder hacer una aplicacin a la medida y de acuerdo a nuestras necesidades es una actividad interesante y llena de recompensas. Mucha gente llega a pensar que solamente con aprender la sintaxis de un lenguaje de programacin es suficiente para poder hacer programas, pero se equivocan. Aun ms importante que la sintaxis del lenguaje es la tcnica de resolucin del problema y el anlisis adecuado. El tener buenos hbitos de anlisis y programacin desde el inicio es fundamental para convertirnos en buenos programadores. Una de los lenguajes que est adquiriendo gran popularidad es C#, un lenguaje sencillo, amigable y poderoso. Con C# se pueden crear todo tipo de aplicaciones, desde programas de consola para Windows y para pginas web en unin con ASP, hasta video juegos para Xbox 360 con XNA. El presente libro introduce a cualquier persona, aun sin conocimientos de programacin, al lenguaje C#. Esta obra est actualizada para Visual Studio 2010 y el Framework de .NET 4.0. En un inicio veremos la forma de realizar el anlisis de un problema e iremos construyendo el conocimiento hasta llegar a las bases de la programacin orientada a objetos y, por supuesto, la depuracin. El convertirse en un buen programador requiere de mucha prctica y experimentacin, pero tambin de una gua adecuada que vaya construyendo paso a paso las habilidades necesarias. Esperamos que este libro sea de utilidad a todos aquellos que, aun sin experiencia en programacin, tengan el deseo de aprender como hacer sus propios programas.
12
www.redusers.com
C#
Captulo
C#.NET
Este libro est dirigido a todas aquellas personas que desean aprender el lenguaje de programacin C# y tienen conocimientos bsicos de programacin o no tienen ninguna experiencia previa programando computadoras. El enfoque del libro es guiar paso a paso en el aprendizaje del lenguaje y aunque C# es un lenguaje orientado a objetos, en los primeros captulos tomaremos una filosofa estructurada con el fin de hacer todava ms fcil el aprendizaje para todos nosotros.
Breve historia de la programacin para Windows 14 Comprendiendo .NET 15 Cmo se crea una aplicacin .NET 16 Cmo conseguir un compilador de C# 17 El ambiente de desarrollo 18 Cmo crear nuestra primera aplicacin 19 Resumen 29 Actividades 30
1. C#.NET
delo conocido como COM, ste nos permite crear componentes binarios, esto quiere decir que es posible programar un componente en Visual Basic y un programador de C++ puede tomarlo y hacer uso de l. Esto se debe a que el componente ya es cdigo compilado y no cdigo fuente en el lenguaje de origen; la programacin de COM tambin tena sus complejidades y surge ATL para ayudar en su desarrollo. Con todo esto, llega el momento en el cual es necesario ordenar, facilitar y organizar el desarrollo de las aplicaciones para Windows, con esta filosofa surge .NET.
Descubrir .NET
El Framework de .NET es una solucin a toda la problemtica en torno al desarrollo de aplicaciones, brinda grandes beneficios no solamente al desarrollador, sino tambin al proceso de desarrollo. En primer lugar .NET permite trabajar con cdigo ya existente, podemos hacer uso de los componentes COM, e incluso, si lo necesitramos usar el API de Windows. Cuando el programa .NET est listo es mucho ms fcil de instalar en la computadora de los clientes, que las aplicaciones tradicionales ya que se tiene una integracin fuerte entre los lenguajes. Un programador de C# puede entender fcilmente el cdigo de un programador de Visual Basic .NET y ambos pueden programar en el lenguaje con el que se sienten ms cmodos. Esto se debe a que todos los lenguajes que hacen uso de .NET comparten las libreras de .NET, por lo que no importa en qu lenguaje programemos, las reconocemos en cualquiera. A continuacin conoceremos los diferentes componentes de .NET: CLR, assembly y CIL.
CLR
El primer componente de .NET que conoceremos es el Common Language Runtime, tambin denominado CLR. Este es un programa de ejecucin comn a todos los lenguajes. Este programa se encarga de leer el cdigo generado por el compilador y empieza su ejecucin. Sin importar si el programa fue creado con C#, con Visual Basic .NET o algn otro lenguaje de .NET el CLR lo lee y ejecuta.
Assembly
Cuando tenemos un programa escrito en un lenguaje de .NET y lo compilamos se genera el assembly. El assembly contiene el programa compilado en lo que conocemos como CIL y tambin informacin sobre todos los tipos que se utilizan en el programa.
CIL
Los programas de .NET no se compilan directamente en cdigo ensamblador del compilador, en su lugar son compilados a un lenguaje intermedio conocido como CIL. Este lenguaje es ledo y ejecutado por el runtime. El uso del CIL y el runtime es lo que le da a .NET su gran flexibilidad y su capacidad de ser multiplataforma.
www.redusers.com 15
1. C#.NET
El Framework de .NET tiene lo que se conoce como las especificaciones comunes de lenguaje o CLS por sus siglas en ingls, estas especificaciones son las guas que cualquier lenguaje que desee usar .NET debe de cumplir para poder trabajar con el runtime. Una ventaja de esto es que si nuestro cdigo cumple con las CLS podemos tener interoperabilidad con otros lenguajes, por ejemplo, es posible crear una librera en C# y un programador de Visual Basic .NET puede utilizarla sin ningn problema. Uno de los puntos ms importantes de ests guas es el CTS o sistema de tipos comunes. En los lenguajes de programacin, cuando deseamos guardar informacin, sta se coloca en una variable, las variables van a tener un tipo dependiendo del la informacin a guardar, por ejemplo, el tipo puede ser para guardar un nmero entero, otro para guardar un nmero con decimales y otro para guardar una frase o palabra. El problema con esto es que cada lenguaje guarda la informacin de manera diferente, algunos lenguajes guardan los enteros con 16 bits de memoria y otros con 32 bits; incluso algunos lenguajes como C y C++ no tienen un tipo para guardar las cadenas o frases. Para solucionar esto el Framework de .NET define por medio del CTS cmo van a funcionar los tipos en su entorno. Cualquier lenguaje que trabaje con .NET debe de usar los tipos tal y como se sealan en el CTS. Ahora que ya conocemos los conceptos bsicos, podemos ver cmo es que todo esto se une.
.NET ES MULTIPLATAFORMA
El Framework de .NET se puede ejecutar en muchas plataformas, no solo en Windows. Esto significa que podemos programar en una plataforma en particular y si otra plataforma tiene el runtime, nuestro programa se ejecutar sin ningn problema. Un programa .NET desarrollado en Windows puede ejecutarse en Linux, siempre y cuando se tenga el runtime correspondiente.
16
www.redusers.com
Cuando nosotros deseamos invocar al programa, entonces el runtime entra en accin, lee el assembly y crea para nosotros todo el entorno necesario. El runtime empieza a leer las instrucciones CIL del assembly y conforme las va leyendo las compila para el microprocesador de la computadora en la que corre el programa; esto se conoce como JIT o compilacin justo a tiempo. De esta manera conforme se avanza en la ejecucin del programa se va compilando; todo esto ocurre de manera transparente para el usuario. El Framework de .NET provee, para los programas que se estn ejecutando, los servicios de administracin de memoria y recolector de basura. En lenguajes no administrados como C y C++ el programador es responsable de la administracin de memoria, en programas grandes esto puede ser una labor complicada, que puede llevar a errores durante la ejecucin del programa. Afortunadamente lenguajes administrados como C# tienen un modelo en el cual nosotros como programadores ya no necesitamos ser responsables por el uso de la memoria. El recolector de basura se encarga de eliminar todos los objetos que ya no son necesarios, cuando un objeto deja de ser til el recolector lo toma y lo elimina. De esta forma se liberan memoria y recursos. El recolector de basura trabaja de forma automtica para nosotros y ayuda a eliminar toda la administracin de recursos y memoria que era necesaria en Win32. En algunos casos especiales como los archivos, las conexiones a bases de datos o de red se tratan de recursos no administrados, para estos casos debemos de indicar explcitamente cuando es necesario que sean destruidos.
EL COMPILADOR JIT
Al compilador JIT tambin se le conoce como Jitter. Forma parte del runtime y es muy eficiente, si el programa necesita volver a ejecutar un cdigo que ya se ha compilado, el Jitter en lugar de volver a compilar, ejecuta lo ya compilado, mejorando de esta forma el desempeo y los tiempos de respuesta de cara al usuario.
www.redusers.com
17
1. C#.NET
Una mejor opcin, en caso de que no podamos conseguir la versin profesional de Visual Studio 2010, es la versin Express. Esta versin es gratuita y se puede descargar directamente de Internet, lo nico que se necesita es llevar a cabo un pequeo registro por medio de cualquier cuenta de Hotmail o passport. Para descargar el compilador de C# Express de forma completamente gratuita, podemos acceder al sitio web que se encuentra en la direccin www.microsoft. com/express, dentro del portal de Microsoft. Para realizar esta descarga slo ser necesario completar un formulario de registro. Una vez que hemos descargado el compilador, podemos proceder a llevar a cabo la instalacin; esta tarea es muy similar a la instalacin de cualquier otro programa de Windows, pero no debemos olvidar registrarlo antes de 30 das.
El ambiente de desarrollo
Una vez finalizada la instalacin podemos iniciar el programa seleccionndolo desde el men Inicio de Windows, veremos una ventana como la que aparece a continuacin, que muestra la interfaz de uso de la aplicacin.
Figura 1. Aqu vemos la ventana principal de C# Express 2010. Esta interfaz aparece cada vez que iniciamos el programa.
Bsicamente la interfaz est dividida en dos partes, en el centro tenemos la pgina de inicio, aqu encontramos enlaces a nuestros proyectos ms recientes, pero tambin
18 www.redusers.com
podemos recibir comunicados y noticias sobre el desarrollo de software usando C#. En esta misma parte de la interfaz pero como pginas diferentes, tendremos las zonas de edicin. Estas zonas de edicin nos permitirn editar el cdigo del programa, editar la interfaz de usuario, iconos y dems recursos. Editar el cdigo del programa es una actividad muy sencilla que no debe preocuparnos, si sabemos utilizar cualquier tipo de editor de textos como Microsoft Word o el Bloc de notas de Windows, entonces podemos editar el cdigo del programa. Los dems editores tambin son bastante amigables para el usuario, pero no los necesitaremos para realizar los ejemplos mostrados en este libro. Del lado derecho tenemos una ventana que se conoce como Explorador de soluciones, en esta misma rea aparecern otras ventanas que nos dan informacin sobre el proyecto que estamos desarrollando. Veremos los detalles mostrados por algunas de estas ventanas un poco ms adelante en este libro. En la parte inferior encontramos otra ventana, en esta zona generalmente aparecen los apartados que utilizar el compilador para comunicarse con nosotros. Por ejemplo, en esta zona veremos la ventana que nos indica los errores que tiene nuestro programa, en la parte superior aparecen los mens y las barras de herramientas.
www.redusers.com
19
1. C#.NET
Figura 2. ste es el cuadro de dialogo que usamos para crear un nuevo proyecto, gracias a sus opciones podemos generar diferentes tipos de proyectos.
En unos pocos segundos C# Express crea el proyecto para nosotros. Visual Studio y la versin Express hacen uso de soluciones y proyectos, una solucin puede tener varios proyectos, por ejemplo, Office tiene diferentes productos como Word, Excel y PowerPoint. Office es una solucin y cada producto es un proyecto. El proyecto puede ser un programa independiente o una librera, y puede tener uno o varios documentos, estos documentos pueden ser el cdigo fuente y recursos adicionales. Podemos observar que nuestra interfaz de usuario ha cambiado un poco, las ventanas ya nos muestran informacin y tambin podemos ver que en la zona de edicin se muestra el esqueleto para nuestro programa.
Figura 3. Esta figura nos muestra el panel derecho denominado Solution Explorer.
20 www.redusers.com
El Explorador de soluciones nos muestra la informacin de la solucin de forma lgica, si observamos es como un pequeo rbol. En la raz encontramos a la solucin, cada proyecto que tengamos en esa solucin ser una rama, cada proyecto, a su vez, tendr tambin sus divisiones. En nuestro caso vemos tres elementos, dos de esos elementos son carpetas, en una se guardan las propiedades del proyecto y en la otra las referencias (durante este libro no haremos uso de estas carpetas). El tercer elemento es un documento llamado Program.cs, ste representa al documento donde guardamos el cdigo fuente de nuestra aplicacin. Vemos que la extensin de los programas de C# es .CS. En el rea de edicin podemos observar que tenemos un esqueleto para que, a partir de ah, podamos crear nuestro propio programa. Para entender lo que tenemos ah es necesario conocer un concepto: namespace. El namespace es una agrupacin lgica, por ejemplo, todo el cdigo que podemos tener relacionado con matemticas puede quedar agrupado dentro del namespace de Math. Otro uso que tiene el namespace es el de resolver conflictos con los nombres, por ejemplo, supongamos que tenemos un proyecto muy grande y varios programadores trabajando en l. Es posible que ambos programadores crearan un mtodo que tuviera el mismo nombre, esto nos genera un conflicto ya que el programa no podra saber cual versin utilizar. La forma de resolver esto es que cada programador tenga su propio namespace y hacer referencia al namespace correspondiente segn la versin que deseramos utilizar. El Framework de .NET nos provee de varios namespaces donde tenemos miles de clases y mtodos ya creados para nuestro uso. Cuando deseamos utilizar los recursos que se encuentran en un namespace programado por nosotros o por otros programadores, debemos hacer uso de un comando de C# conocido como using. Como podemos ver en la parte superior del cdigo, tenemos varios using haciendo referencia a los namespace que necesita nuestra aplicacin; si necesitramos adicionar ms namespaces, lo haramos en esta seccin. Ms abajo se est definiendo el namespace propio de nuestro proyecto, esto se hace de la siguiente manera:
namespace MiProyecto { }
El namespace que estamos creando se llama MiProyecto, como podemos ver el namespace usa { } como delimitadores, esto se conoce como un bloque de cdigo, todo lo que se coloque entre { } pertenecer al namespace; ah es donde ser necesario escribir el cdigo correspondiente a nuestra aplicacin.
www.redusers.com 21
1. C#.NET
Dentro del bloque de cdigo encontramos la declaracin de una clase, C# es un lenguaje orientado a objetos y por eso necesita que declaremos una clase para nuestra aplicacin. La clase tiene su propio bloque de cdigo y en nuestra aplicacin se llamar Program. El concepto de clase se ver en el Captulo 10 de este libro. Todos los programas necesitan de un punto de inicio, un lugar que indique dnde empieza la ejecucin del programa, en C#, al igual que en otros lenguajes, el punto de inicio es la funcin Main(); esta funcin tambin tiene su propio bloque de cdigo. Dentro de esta funcin generalmente colocaremos el cdigo principal de nuestra aplicacin, aunque es posible tener ms funciones o mtodos y clases. Las partes y caractersticas de las funciones se ven en el Captulo 5 de este libro. Ahora es el momento de crear nuestra primera aplicacin. Vamos a modificar el cdigo de la funcin tal y como se muestra a continuacin. Cuando estemos adicionando la sentencia dentro de Main(), debemos fijarnos que sucede inmediatamente despus de colocar el punto.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MiProyecto { class Program { static void Main(string[] args) { Console.WriteLine(Hola Mundo!); } } }
Si logramos observar, cuando se escribi la palabra Console y luego el punto, apareci un recuadro listando diferentes elementos. Este cuadro se llama autocompletar y nos permite trabajar rpidamente y reducir la cantidad de errores de sintaxis. El cuadro de autocompletar nos muestra sugerencia de la palabra, comando, variable, etc. que se podra usar a continuacin. Si lo deseamos, lo seleccionamos de esa lista, y l lo escribe por nosotros, conforme avancemos y nos familiaricemos con la programacin de C# veremos que es de gran ayuda. En nuestro ejemplo hemos colocado una sentencia que escribir el mensaje Hola Mundo en la consola. Es un programa muy sencillo, pero nos permitir aprender cmo llevar a cabo la compilacin de la aplicacin y ver el programa ejecutndose.
22 www.redusers.com
Figura 4. Para compilar nuestra aplicacin, primero debemos construirla, seleccionando la opcin adecuada desde el men.
INTERFAZ GRFICA
ste es un libro de inicio a la programacin con C#, por eso todos los programas se ejecutarn en la consola. Una vez comprendidos los conceptos principales que se ensean, es posible aprender cmo se programan las formas e interfaz grfica en C#. Este tipo de programacin no es difcil, pero si requiere tener los conocimientos bsicos de programacin orientada a objetos.
www.redusers.com
23
1. C#.NET
uso de la ejecucin con depuracin nicamente cuando realmente la necesitemos. Ahora ejecutaremos nuestra aplicacin, para esto oprimimos las teclas CTRL+F5.
Cuando el programa se ejecuta, aparece una ventana, a ella la llamamos consola y se encarga de mostrar la ejecucin del programa. De esta forma podremos leer el mensaje que habamos colocado en nuestro ejemplo.
En el programa hemos cambiado Console por Consola, esto provocar un error; ahora podemos tratar de compilar nuevamente y ver lo que sucede.
Figura 7. En esta imagen vemos que el programa tiene un error y por lo tanto no se puede compilar.
www.redusers.com 25
1. C#.NET
Como ya sabemos, la ventana que aparece en la parte inferior de nuestra interfaz de usuario es utilizada por el compilador para comunicarse, vemos que aparece una ventana que nos entrega un listado de errores; en el Captulo 12, dedicado a la depuracin, aprenderemos a utilizarla, ahora simplemente debemos saber que siempre es necesario resolver el primer problema de la lista y que podemos ir directamente al error haciendo doble clic con el mouse sobre l.
La vista de clases
Ahora revisaremos la vista de clases. En esta vista podemos obtener informacin sobre la solucin que estamos creando, pero a diferencia del Explorador de soluciones, la informacin se encuentra ordenada en forma lgica. Con esta vista podemos encontrar rpidamente los namespace de nuestra solucin y dentro de ellos las clases que contienen; si lo deseamos, podemos ver los mtodos que se encuentran en cada clase. Esta vista no solamente permite observar la informacin lgica, tambin nos da la posibilidad de navegar rpidamente en nuestro cdigo. En la versin Express no viene la opcin previamente configurada, por lo que es necesario adicionar el comando al men Vista. Para mostrar la vista de clases debemos de ir al men Vista y luego seleccionar Vista de Clases, una ventana aparecer en nuestra interfaz de usuario.
La ventana de la vista de clases est divida en dos secciones, la seccin superior nos muestra la relacin lgica y jerrquica de los elementos mientras que en la parte inferior vemos los mtodos que componen a alguna clase en particular.
.NET EN LINUX
Si deseamos trabajar bajo Linux, es posible utilizar Mono. Solamente debemos recordar que no siempre la versin .NET que maneja Mono es la ms reciente de Microsoft. El sitio de este proyecto lo encontramos en la direccin web www.mono-project.com/Main_Page, desde ella podemos descargarlo en forma completamente gratuita.
26
www.redusers.com
Figura 9. Aqu podemos observar a la vista de clases en el lado derecho. El rbol est abierto para poder ver los elementos que lo componen.
En la raz del rbol encontramos al proyecto, ste va a contener las referencias necesarias y el namesapace de MiProyecto. Si tuviramos ms namespaces estos apareceran ah, al abrir el namespace de Miproyecto encontramos las clases que estn declaradas dentro de l. En este caso solamente tenemos la clase Program, si la seleccionamos veremos que en la parte inferior se muestran los elementos que estn declarados en su interior. En nuestro ejemplo tenemos el mtodo Main(). Si en este momento damos doble clic en cualquiera de los mtodos, nos dirigiremos automticamente al cdigo donde se define, como nuestro programa es muy pequeo, posiblemente no vemos la ventaja de esto, pero en programas con miles de lneas de cdigo, el poder navegar rpidamente es una gran ventaja.
MSDN
Uno de los sitios ms importantes que tenemos que visitar cuando desarrollamos para .NET es el llamado MSDN. En este sitio encontraremos toda la documentacin y variados ejemplos para todas las clases y mtodos que componen a .NET. El sitio se encuentra en la direccin web www.msdn.com.
www.redusers.com
27
1. C#.NET
Nos aparece un cuadro de dilogo, en el cual debemos seleccionar Commands, en esta seccin podemos elegir el men al cual queremos adicionar un comando, por ejemplo el men View.
Figura 11. En esta ventana debemos seleccionar el men que deseamos modificar.
28 www.redusers.com
Aparecen listados los comandos actuales del men, damos clic en la zona donde deseamos que se inserte el nuevo comando y oprimimos el botn Add Command. Con esto aparece un nuevo cuadro de dialogo que muestra todos los posibles comandos que podemos adicionar clasificados en categoras. En las categoras seleccionamos View y en los comandos Class View, este comando es el que nos permite tener la vista de clases. El comando de Iniciar Sin Depurar se encuentra en la categora Debug.
Hasta aqu hemos analizado los conceptos bsicos ms importantes necesarios para comprender el funcionamiento de .NET, a partir del prximo captulo comenzaremos con nuestro aprendizaje de programacin y del lenguaje C#.
RESUMEN
Hace algunos aos la programacin para Windows resultaba complicada y requera de un alto grado de especializacin. El Framework de .NET soluciona muchos de los problemas relacionados con la programacin en Windows y la interoperabilidad, las aplicaciones de .NET se compilan a un assembly que contiene el programa escrito en CIL; ste es un lenguaje intermedio que lee el runtime cuando se ejecuta la aplicacin. El CLR compila el CIL para el microprocesador segn va siendo necesario, el uso de un runtime le da a .NET la flexibilidad de ser multiplataforma. Todos los lenguajes .NET deben cumplir con los lineamientos que encontramos en el CLS.
www.redusers.com
29
EJERCICIOS PRCTICOS
1 Cree un proyecto nuevo que imprima su nombre en la ventana de la consola. 2 Coloque un error a propsito y vea cmo se comporta el compilador.
30
www.redusers.com
C#
Captulo
32
www.redusers.com
Cualquier persona puede pensar en una actividad y mencionar la lista de pasos y el orden en el que se deben cumplir. Podemos hacer sin problema la lista de pasos para cambiar el neumtico del automvil o para alimentar a los peces del acuario. Con esto vemos que no encontraremos problema alguno para listar los pasos de cualquier actividad que hagamos. Ahora, seguramente nos preguntamos: qu tiene esto que ver con la programacin de computadoras? y la respuesta es simple. Cualquier persona que pueda hacer una lista de pasos puede programar una computadora. El programa de la computadora no es otra cosa que una lista de los pasos que la computadora tiene que seguir para hacer alguna actividad. A esta lista de pasos la llamamos algoritmo. Un algoritmo son los pasos necesarios para llevar a cabo una accin. Una caracterstica importante del algoritmo es que tiene un punto de inicio y un punto de fin, lo que indica que los pasos se llevan a cabo de forma secuencial, uno tras otro. El algoritmo sera equivalente a la receta de la torta y los ingredientes necesarios generalmente sern los datos o la informacin que usaremos. Hagamos un pequeo programa para ver cmo funcionara esto. Para esto creamos un proyecto, tal y como vimos en el Captulo 1. Nuestro programa mostrar los pasos para hacer una torta o un pastel. Colocamos el siguiente cdigo en nuestro programa y veremos cmo se corresponde con lo que hemos aprendido.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args)
LAS FUNCIONES EN C#
Las funciones son secciones del programa en las que podemos tener cdigo especializado. La funcin Main() es invocada por el sistema operativo cuando queremos que nuestro programa se inicie. Es la nica funcin que deben tener todos los programas que desarrollemos.
www.redusers.com
33
{ Console.WriteLine(1Console.WriteLine(2Console.WriteLine(3Console.WriteLine(4Console.WriteLine(5Console.WriteLine(6Console.WriteLine(7} } } Precalentar el horno); Batir margarina con azucar); Agregar huevos); Cernir harina); Agregar a la mezcla y leche); Hornear por 40 minutos); Decorar y comer);
C# es un lenguaje orientado a objetos y necesita que definamos una clase para poder crear un programa. En este momento no veremos las clases, pero regresaremos a ellas en un captulo posterior. Lo primero que debemos encontrar es una funcin que se llama Main(), que es muy importante, como vimos en el Captulo 1. Ya sabemos que los algoritmos necesitan un inicio y un fin. En nuestro programa el punto donde siempre inicia es la funcin Main(). Esta funcin indica el punto de arranque de nuestro programa y aqu colocaremos los pasos que debe seguir nuestro programa en el orden adecuado. Para indicar todos los pasos que pertenecen a Main() necesitamos colocarlos adentro de su bloque de cdigo. Un bloque de cdigo se define entre llaves { }. Todo lo que se encuentre en ese bloque de cdigo pertenece a Main(), lo que se encuentre afuera de l, no pertenece. Es importante que notemos que la clase tambin tiene un bloque de cdigo y Main() se encuentra adentro de l. De igual forma, el namespace tambin tiene su propio bloque de cdigo y la clase se encuentra adentro, aunque por ahora slo nos concentraremos en el bloque de cdigo de Main(). Un error comn cuando se crean bloques de cdigo es olvidar cerrarlos. Como recomendacin, una vez que abrimos un bloque de cdigo con {, inmediatamente debemos de colocar el cierre con } y luego programar su contenido. De esta forma, no
34
www.redusers.com
olvidaremos cerrarlo. Dentro de Main() encontramos los pasos de nuestro algoritmo. En este momento nos pueden parecer extraos, pero aprenderemos qu significan. Tenemos que recordar que debemos aprender el idioma de la computadora y stas son una de sus primeras frases. Lo que encontramos adentro de la funcin Main() es una serie de sentencias. Las sentencias nos permiten colocar instrucciones que nuestro programa pueda ejecutar, que son utilizadas para mostrar un mensaje en la pantalla. El mensaje que nosotros queremos mostrar en la pantalla se muestra al invocar el mtodo WriteLine(). Los mtodos son similares a las funciones, existen adentro de las clases y nos permiten hacer uso de las funcionalidades internas. Este mtodo pertenece a la clase Console, y en esa clase encontraremos todo lo necesario para que podamos trabajar con la consola, ya sea colocando mensajes o leyendo la informacin proporcionada por el usuario. Como WriteLine() pertenece a Console cuando queremos utilizarlo, debemos escribir:
Console.WriteLine(Hola);
necesita cierta informacin para poder trabajar. Esta informacin es el mensaje que deseamos mostrar. A los mtodos se les pasa la informacin que necesitan para trabajar por medio de sus parmetros. Los parmetros necesarios se colocan entre parntesis(). WriteLine() necesitar un parmetro de tipo cadena. Una cadena es una coleccin de caracteres, es decir, letras, nmeros y signos. La cadena se delimita con comillas dobles . En el ejemplo, el mensaje que queremos que se muestre es: Hola. Por eso pasamos el parmetro de tipo cadena Hola. Las sentencias se finalizan con punto y coma ;. Esto es importante y no debemos olvidarlo ya que este carcter en particular es reconocido por C# para indicar que la sentencia escrita hasta all, ha finalizado. En cada una de las sentencias invocadas hasta aqu por nuestro programa, hemos enviado un mensaje tras otro con cada paso necesario para cocinar nuestro pastel o nuestra torta. Por ltimo, slo resta que ejecutemos el programa escrito y veamos el resultado que aparece en la pantalla.
WriteLine()
www.redusers.com
35
Figura 1. Podemos observar los mensajes que enviamos a la pantalla por medio del mtodo WriteLine().
Podemos observar que la ejecucin ha mostrado los mensajes en el orden en el que los hemos puesto. Ahora podemos hacer un pequeo experimento. Cambiaremos el orden de las sentencias y observaremos qu es lo que sucede. El programa quedar de la siguiente forma:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { Console.WriteLine(1- Precalentar el horno);
36
www.redusers.com
Console.WriteLine(2Console.WriteLine(6Console.WriteLine(5Console.WriteLine(7Console.WriteLine(3Console.WriteLine(4} } }
Batir margarina con azucar); Hornear por 40 minutos); Agregar a la mezcla y leche); Decorar y comer); Agregar huevos); Cernir harina);
Figura 2. Aqu vemos que los mensajes se colocan en el orden en que se encuentran en la funcin main() y no en el orden en que esperbamos.
Podemos observar que cuando se ejecuta, las sentencias se ejecutan en el mismo orden como estn en el cdigo del programa, no se ejecutan como nosotros sabemos que se deben de ejecutar. Este punto es importante, ya que nos muestra que colocar las sentencias del programa en el orden de ejecucin correcto es responsabilidad del programador. La computadora no puede leernos la mente y saber qu es lo que realmente deseamos, sta slo ejecuta fielmente las sentencias
www.redusers.com 37
en el orden en que las colocamos. Si en la vida real primero horneamos y luego batimos, no podemos esperar obtener un pastel o una torta. Por lo tanto, si en la computadora no ponemos las sentencias del programa en el orden adecuado, no podemos esperar tener un programa funcional.
38
www.redusers.com
Figura 3. Podemos ver la ventana con la lista de errores y el error de sintaxis encontrado por el compilador.
La lista de errores nos da una descripcin del error y tambin nos permite ver el nmero de lnea donde se encuentra el error. Una forma sencilla de llegar a ste es simplemente hacer doble clic sobre la descripcin del error, as el entorno C# nos llevar directamente a dnde se encuentra ste. Coloquemos nuevamente el punto y coma en el lugar donde estaba en un principio y compilemos. En esta ocasin, el programa puede compilar y ejecutar sin problemas, en base a la correcin que hemos realizado con antelacin. El error se encuentra solucionado. La solucin que nos brinda C# para corregir errores es prctica y sencilla de implementar. Ahora experimentemos otro error. A la primera sentencia le borramos el parntesis de cierre y luego compilamos para ver qu ocurre:
www.redusers.com
39
Corrijamos el error y compilemos de nuevo. Todo debe de estar bien. Pero lo que haremos ahora es borrar las comillas de cierre de la cadena en la primera sentencia. Este error nos presenta un escenario ms interesante y nos conviene entender qu es lo que sucede. Compilemos el programa y veamos nuestra lista de errores. sta ser mucho ms extensa que las anteriores: Aqu ha sucedido algo interesante, a pesar de que solamente hemos creado un error: en la lista de errores aparecen tres errores. Esto se debe a que un error puede ocasionar errores extras en el cdigo siguiente. Al no cerrar la cadena, el compilador no sabe dnde termina la sentencia y cree que el parntesis de cierre y el punto y coma forman parte de la cadena. Por eso tambin nos muestra que faltan el parntesis y el punto y coma. Debido a que los errores pueden ser en cadena, como en este ejemplo, siempre necesitamos corregir el error que se encuentra en primer lugar. Si nosotros intentramos corregir primero el error del punto y coma, no resultara evidente ver cul es el error en esa lnea, ya que veramos que el punto y coma s est escrito. A veces sucede que nuestro programa muestra muchos errores, pero cuando corregimos el primer error, la gran mayora desaparece. Esto se debe a factores similares a los que acabamos de ver.
www.redusers.com
41
Al ejecutarlo, vemos cmo en efecto despus de usar Write() lo siguiente que se escribe se coloca en el mismo rengln, pero al usar WriteLine() lo siguiente aparece en el rengln siguiente. Esto es un ejemplo claro de lo explicado anteriormente:
Las variables
Las computadoras no solamente escriben mensajes en la pantalla, sino que deben hacer cosas tiles y para poder hacerlas necesitan informacin. La informacin debe almacenarse y manipularse de alguna forma. Cuando queremos guardar algo en la vida cotidiana podemos utilizar cajas, por lo que cualquier cosa que deseamos almacenar puede ser colocada en una caja de
42 www.redusers.com
cartn, por ejemplo. Sin embargo, el tamao de la caja depender de lo que deseamos almacenar. Unos zapatos pueden caber en una caja pequea, pero en esa caja no podemos colocar un televisor. Si empezamos a almacenar muchas cosas en cajas, pronto tendremos demasiadas y ser difcil poder encontrar lo que hemos guardado. Entonces, una forma de solucionar esto es por medio de etiquetas. A cada caja le ponemos una etiqueta con el contenido y de esta forma podemos encontrar rpidamente lo que buscamos. Las variables en la computadora funcionan de manera similar a nuestras cajas de almacenaje. Las podemos imaginar como pequeas cajas que existen en la memoria de la computadora y su tamao depender de la informacin que deben guardar. Esto se conoce como tipo de la variable. Para poder acceder a esa caja o variable le ponemos un nombre que sera la etiqueta con la que la identificamos. Para hacer uso de una variable, lo primero que tenemos que hacer es declararla. La declaracin de stas es algo muy sencillo. Como primer paso tenemos que colocar el tipo y luego el nombre. Las variables en C# deben nombrarse de acuerdo con unas recomendaciones sencillas: Los nombres de las variables deben empezar con letra. Es posible colocar nmeros en los nombres de las variables, pero no empezar el nombre con ellos. Los nombres de las variables no pueden llevar signos a excepcin del guin bajo _ . Las variables no pueden llevar acentos en sus nombres. Cuando nombramos las variables, hay que tener en cuenta que C# es sensible a las maysculas y minsculas, por lo que una variable llamada costo no es la misma que otra variable llamada COSTO u otra llamada Costo. Es recomendable nombrar a las variables con nombres que hagan referencia a la informacin que guardarn. Si nos acostumbramos a hacer esto desde que empezamos a programar, evitaremos muchos problemas en el futuro y ser mucho ms sencillo corregir nuestros programas cuando tengan errores. Veamos un ejemplo de cmo podemos declarar una variable que guarde valores numricos enteros. El tipo que guarda estos valores se conoce como int.
www.redusers.com
43
int costo;
Vemos que al final de la sentencia hemos colocado el punto y coma. Si necesitamos declarar ms variables lo podemos hacer de la siguiente forma:
int costo; int valor; int impuesto;
Pero tambin es posible declarar las variables en una sola lnea. Para esto simplemente separamos los nombres de las variables con comas. No hay que olvidar colocar el punto y coma al final de la sentencia.
int costo, valor, impuesto;
C# nos provee de muchos tipos para poder usar con nuestras variables, que podemos conocer en la siguiente tabla:
TIPO bool byte sbyte char decimal double INFORMACIN QUE GUARDA Es una variable booleana, es decir que solamente puede guardar los valores verdadero o falso (true o false) en trminos de C#. Puede guardar un byte de informacin. Esto equivale a un valor entero positivo entre 0 y 255. Guarda un byte con signo de informacin. Podemos guardar un valor entero con signo desde 128 hasta 127. Puede guardar un carcter de tipo Unicode. Este tipo puede guardar un valor numrico con decimales. Su rango es desde 1.0 ? 10?28 hasta 7.9 ? 1028. Tambin nos permite guardar valores numricos que tengan decimales. El rango aproximado es desde 5.0 ? 10?324 hasta 1.7 ? 10 308.
44
www.redusers.com
INFORMACIN QUE GUARDA Otro tipo muy utilizado para guardar valores numricos con decimales. Para este tipo el rango es desde 1.5 ? 10?45 hasta 3.4 ? 1038. Cuando queremos guardar valores numricos enteros con signo, en el rango de -2,147,483,648 hasta 2,147,483,647. Para valores numricos enteros positivos, su rango de valores es desde 0 hasta 4,294,967,295. Guarda valores numricos enteros realmente grandes con un rango desde 9,223,372,036,854,775,808 hasta 9,223,372,036,854,775,807. Guarda valores numricos enteros positivos. Su rango de valores vara desde 0 hasta 18,446,744,073,709,551,615. Guarda valores numricos enteros, pero su rango es menor y vara desde -32,768 hasta 32,767. Puede guardar valores numricos enteros positivos con un rango desde 0 hasta 65,535. Este tipo nos permite guardar cadenas.
Tabla 1. sta es la tabla de los tipos ms utilizados en C#. Es til para seleccionar el tipo adecuado para las variables.
Una vez que hemos declarado la variable, debemos inicializarla. Inicializar una variable es asignarle un valor por primera vez. Esto nos permite darle un valor inicial que puede ser til en la ejecucin de nuestro programa (no slo podemos asignarle a una variable un valor fijo, sino tambin puede ser desde un texto ingresado por el usuario o desde el registro de una base de datos). Para asignarle un valor a una variable, ya sea durante la inicializacin o durante el transcurso del programa, usamos un operador de asignacin, el signo igual. Veamos a continuacin un ejemplo de cmo asignar valores:
costo = 50; valor = 75; impuesto = 10;
En este caso, la variable costo almacena el valor de 50, la variable valor almacena el 75, y la variable impuesto guarda el valor 10 .
www.redusers.com
45
En este caso nada queda asignado a la variable costo. Siempre la variable que recibe el valor se coloca a la izquierda del signo igual. Si lo necesitamos, es posible inicializar la variable al momento de declararla. Esto es muy cmodo y si lo hacemos as evitamos olvidar la inicializacin de la variable. Para hacerlo colocamos el tipo de la variable seguido del nombre a usar en la variable e inmediatamente con el operador de asignacin colocamos el valor.
int costo = 50;
Comentarios en el programa
Los programas de computadora pueden ser muy grandes, por lo que es necesario colocar comentarios de codigo en el programa. Los comentarios sirven para documentar las partes del programa, explicar lo que hace cierta parte del cdigo o simplemente colocar un recordatorio. Podemos hacer comentarios de una sola lnea, que se colocan por medio de la doble barra // seguido del texto del comentario. El texto que se encuentre a partir de la doble barra // y hasta el fin del rengln es ignorado por el compilador. Algunos ejemplos de comentarios pueden ser:
// Declaro mis variables int ancho, alto; int tarea; // Esta variable guarda el rea calculada. // La siguiente sentencia nunca se ejecuta // Console.WriteLine(Hola);
Si llegramos a necesitar colocar mucha informacin en nuestros comentarios, puede ser til explayarla en varios renglones, es decir, hacer un bloque de comentarios. Para esto, abrimos nuestro bloque de comentarios con una barra seguida de un asterisco, /*, y finalizamos ste con un asterisco en primer lugar, seguido de una barra */. Todo lo que se encuentre entre estos delimitadores ser tomado como un comentario y el compilador lo pasar por alto. Veamos un ejemplo de un comentario de mltiples lneas:
46 www.redusers.com
/* La siguiente seccin calcula el rea y usa las variables alto para guardar la altura del rectngulo ancho para guardar la base del rectngulo */
As vemos cmo los comentarios colocados en varios renglones, se toman como un solo comentario. Esto es algo muy til para recordatorios futuros.
Como solamente tenemos una variable en nuestra lista de variables entonces colocamos {0}. Pero tambin podemos mostrar el valor de dos variables o ms, como lo muestra el siguiente ejemplo:
Console.WriteLine(La primera es {0} y la segunda es {1}, costo, valor);
www.redusers.com
47
using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Declaramos variables int costo; int valor, precio; // Inicializamos las variables costo = 50; valor = 75; precio = 125; // Declaramos e inicializamos int impuesto = 10; // Mostramos un valor Console.WriteLine(El valor adentro de costo es {0}, costo); // Varias variables Console.WriteLine(Valor es {0} y precio es {1}, valor, precio); // Dos veces la misma variable Console.WriteLine(Valor es {0} y precio es {1} con valor de {0}, valor, precio); /* No olvidemos mostrar el valor de la variable impuesto */ Console.WriteLine(Y el valor que nos faltaba mostrar {0},impuesto);
48
www.redusers.com
} } }
Una vez que hemos compilado la aplicacin, obtendremos el resultado que mostramos en la figura a continuacin.
Figura 7. En la consola observamos que los valores guardados en las variables fueron desplegados de acuerdo con lo colocado en la cadena de formato.
Operaciones aritmticas
Poder guardar la informacin es muy importante, pero es mucho ms importante que podamos recuperar y manipular esa informacin para hacer algo til con ella. Para esto, debemos comenzar a realizar las operaciones aritmticas bsicas: suma, resta, multiplicacin y divisin, algo muy comn en cualquier sistema informtico. Cuando queremos o necesitamos realizar una operacin aritmtica debemos hacer uso de un operador. Cada operacin tiene su propio operador, que es el encargado de procesar los nmeros, realizando el determinado clculo, para luego devolvernos el resultado deseado.
www.redusers.com 49
OPERADOR = + * / %
DESCRIPCIN Asignacin. Este operador ya es conocido por nosotros. Suma. Nos permite sumar los valores de las variables o los nmeros Resta. Para restar los valores de las variables o los nmeros. Multiplicacin. Multiplica los valores de las variables o los nmeros. Divisin. Divide los valores de las variables o los nmeros. Mdulo. Nos da el residuo de la divisin.
Veamos algunos ejemplos de cmo utilizar estos operadores. Imaginemos que ya hemos declarado e inicializado las variables. Para guardar en la variable resultado la suma de dos nmeros, hacemos lo siguiente:
resultado = 5 + 3;
Como hemos visto, la expresin a la derecha se le asigna a la variable, por lo que en este caso la expresin 5 + 3 se evala y su resultado que es 8 es almacenado en la variable resultado. Al finalizar esta sentencia, la variable resultado tiene un valor de 8, que podr ser utilizado dentro de la misma funcin o en el procedimiento donde fue declarado. Las operaciones tambin se pueden realizar con las variables y los nmeros. Supongamos que la variable a ha sido declarada y se le ha asignado el valor de 7.
resultado = a 3;
De nuevo se evala primero la expresin a-3, como el valor adentro de a es 7, entonces la evaluacin da el valor de 4, que se le asigna a la variable resultado. Si queremos podemos trabajar nicamente con variables. Ahora supondremos que la variable b ha sido declarada y que le hemos asignado el valor 8.
resultado = a * b;
Entonces, se evala la expresin a*b que da el valor 56, que queda asignado a la variable resultado al finalizar la expresin. Si lo que deseamos es la divisin, podemos hacerla de la siguiente forma:
resultado = a / b;
50
www.redusers.com
En este caso, se divide el valor de a por el valor de b. El resultado es 0,875. Como el nmero tiene valores decimales, debemos usar variables de algn tipo que nos permita guardarlos como float o double. Y por ltimo nos queda el mdulo.
resultado = a % b;
En este caso recibimos en resultado el valor del residuo de dividir a por b. Veamos un pequeo programa donde se muestra lo aprendido en esta seccin.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Declaramos las variables, ahora de tipo flotante float a, b, resultado; // Inicializamos las variables a = 7; b = 8;
www.redusers.com
51
resultado = 0; // Sumas Console.WriteLine(Sumas); resultado = 3 + 5; Console.WriteLine(Resultado = {0},resultado); resultado = a + 3; Console.WriteLine(Resultado = {0}, resultado); resultado = a + b; Console.WriteLine(Resultado = {0}, resultado); // Restas Console.WriteLine(Restas); resultado = a - b; Console.WriteLine(Resultado = {0}, resultado); resultado = b - 5; Console.WriteLine(Resultado = {0}, resultado); resultado = b - a; // A la variable b se le resta a Console.WriteLine(Resultado = {0}, resultado); // Multiplicaciones Console.WriteLine(Multiplicaciones); resultado = a * 5; Console.WriteLine(Resultado = {0}, resultado); resultado = a * 3.5f; Console.WriteLine(Resultado = {0}, resultado); resultado = a * b; Console.WriteLine(Resultado = {0}, resultado); // Divisiones Console.WriteLine(Divisiones);
52
www.redusers.com
resultado = a / 3; Console.WriteLine(Resultado = {0}, resultado); resultado = a / b; Console.WriteLine(Resultado = {0}, resultado); resultado = b / 2.5f; Console.WriteLine(Resultado = {0}, resultado); // Modulo Console.WriteLine(Modulo); resultado = a % b; Console.WriteLine(Resultado = {0}, resultado); } } }
Figura 8. Vemos los resultados de las operaciones aritmticas sobre nuestras variables.
www.redusers.com 53
Precedencia de operadores
Hasta el momento hemos utilizado expresiones aritmticas sencillas, pero en la vida real se pueden necesitar expresiones ms complicadas. Entonces, si estas expresiones no se colocan adecuadamente, esto nos puede ocasionar problemas. Por ejemplo, veamos la siguiente expresin.
resultado = 3 * 5 + 2;
Esta expresin presenta un problema para nosotros en este momento. No sabemos si primero hace 3*5 y le suma 2, que da como resultado 17, o si suma 5+2 y luego lo multiplica por 3, lo que da como resultado 21. Cul es la respuesta correcta? La forma de saberlo es por medio de la precedencia de operadores. sta nos indica el orden en el que se llevan a cabo las operaciones. Este orden depende del tipo de operador que se utiliza. Algunos operadores tienen ms precedencia que otros, es decir, se ejecutan primero. La siguiente tabla muestra la precedencia de los operadores que hemos visto hasta el momento en C#. Se encuentran listados de mayor a menor precedencia.
OPERADOR * / % + DESCRIPCIN Multiplicacin Divisin Mdulo Adicin Sustraccin
Tabla 3. Esta tabla nos muestra la precedencia de operadores en C#. La multiplicacin tiene ms precedencia y se ejecuta primero.
Esto quiere decir que cuando tenemos una expresin aritmtica como la del ejemplo, primero se llevara a cabo la multiplicacin y luego la suma, entonces con esto podemos deducir cmo C# evaluara la expresin. Pero algunas veces sera mejor si nosotros pudiramos organizar nuestra expresin con el fin de hacerla ms fcil de leer para nosotros o para que podamos indicar de forma precisa cmo hacer la operacin. Para que podamos organizar una expresin hacemos uso de los parntesis. Cada seccin que tengamos en los parntesis se evala como una expresin y el resultado se pasa al resto de la expresin. Supongamos que tenemos la siguiente expresin:
resultado = (3*5) + 2;
54
www.redusers.com
Vemos que por medio de los parntesis se ha agrupado una parte de la expresin, por lo que se evala y equivale a:
resultado = 15 + 2;
Veamos otro ejemplo de cmo podemos usar los parntesis para indicar cmo deseamos que se evale la expresin.
resultado = 3 * (5+2);
Veamos qu sucede:
resultado = 10 * (36 + 4 * 7);
www.redusers.com
55
Y al final obtenemos:
resultado = 640;
Afortunadamente, C# hace todas estas evaluaciones y todos estos clculos por nosotros, pero ahora sabemos cmo sucede y sabemos que podemos usar los parntesis para organizar nuestras expresiones aritmticas.
56
www.redusers.com
En este fragmento de programa es importante notar cmo el valor obtenido por ReadLine() se le asigna a la variable de tipo cadena entrada. Si no colocamos una variable que recibe el valor de lo escrito por el usuario, ste se perder. Cuando usemos ReadLine() debemos hacerlo como se muestra. Una vez que recibimos la entrada del usuario podemos trabajar con ella sin problemas.
Conversin de variables
El mtodo de ReadLine() nos presenta una limitacin en este momento ya que slo regresa el valor como cadena, pero no podemos utilizar una cadena en operaciones aritmticas o asignarla directamente a una variable numrica. Lo que debemos hacer es convertir ese dato numrico guardado como cadena a un valor numrico til para nuestros propsitos. C# nos provee de una clase que permite hacer conversiones entre los diferentes tipos de variables. Esta clase se conoce como convert y tiene una gran cantidad de mtodos para la conversin. Aqu slo veremos cmo convertir a enteros y flotantes, ya que son los tipos con los que trabajaremos en este libro principalmente. Sin embargo, los dems mtodos se usan de forma similar y podemos encontrar la informacin necesaria sobre stos en MSDN (MicroSoft Developer Network). Si queremos convertir del tipo string al tipo int usaremos el mtodo ToInt32(). ste necesita un parmetro, que es la cadena que deseamos convertir. El mtodo regresa un valor de tipo int, por lo que es necesario tener una variable que lo reciba. Un ejemplo de esto es:
a = Convert.ToInt32(entrada);
MSDN
MSDN es un sitio web donde encontraremos informacin tcnica sobre todas las clases y funciones, y todos los mtodos que conforman los lenguajes que componen Visual Studio. Tambin es posible encontrar ejemplos y descripciones de los errores de compilacin. Tiene un buen sistema de bsquedas que resulta muy til. La direccin es www.msdn.com.
www.redusers.com
57
De forma similar podemos convertir la cadena a una variable de tipo float. En este caso usaremos el mtodo ToSingle(). ste tambin necesita un parmetro, que es la cadena que contiene el valor a convertir. Como regresa un valor flotante, entonces debemos tener una variable de tipo float que lo reciba.
valor = Convert.ToSingle(entrada);
Ya que tenemos los valores convertidos a nmeros, entonces podemos hacer uso de ellos. Veamos un ejemplo donde le pedimos informacin al usuario.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Declaramos variables string entrada = ; int a = 0, b = 0, resultado = 0; // Leemos una cadena Console.WriteLine(Escribe tu nombre); entrada = Console.ReadLine(); Console.WriteLine(Hola {0}, como estas?, entrada); // Leemos dos valores y los sumamos. Console.Write(Dame un entero:); entrada = Console.ReadLine(); // Convertimos la cadena a entero a = Convert.ToInt32(entrada);
58
www.redusers.com
Console.Write(Dame otro numero entero:); entrada = Console.ReadLine(); // Convertimos la cadena a entero b = Convert.ToInt32(entrada); // Sumamos los valores resultado = a + b; // Mostramos el resultado Console.WriteLine(El resultado es {0}, resultado); } } }
Ahora compilemos y ejecutemos la aplicacin. Para introducir los datos, simplemente los escribimos con el teclado y al finalizar oprimimos la tecla ENTER o RETURN.
Figura 9. ste es el resultado de la ejecucin, donde vemos que la suma se lleva a cabo con los valores introducidos por el usuario.
www.redusers.com 59
60
www.redusers.com
El ltimo paso consiste en pasar el algoritmo a programa de computadora. Si todo se ha realizado correctamente, el programa deber ejecutarse al primer intento. Mucha gente se sorprende que para hacer un programa de computadora, el ltimo paso sea colocarlo en la computadora, pero sta es la forma correcta. Algunos programadores no profesionales intentan hacer el programa directamente en la computadora, pero esto acarrea muchos errores de lgica y datos, y el tiempo en que resuelve el mismo problema es mayor y es difcil que se ejecute correctamente al primer intento. Aunque la metodologa que acabamos de presentar parece larga, en realidad puede ahorrar hasta un 50% del tiempo de resolucin en comparacin con alguien que programe directamente en la computadora. Ahora que empezamos, es bueno adquirir hbitos correctos de programacin desde el inicio. En el futuro, en especial cuando los problemas que se resuelvan sean complicados, se apreciarn los beneficios.
Inicio
Final
Figura 10. En esta figura podemos observar el terminador tanto en su papel como punto de inicio como punto final del algoritmo.
www.redusers.com 61
El siguiente elemento se conoce como proceso. ste tiene la forma de un rectngulo y nos sirve para indicar que precisamente un proceso debe llevarse a cabo en ese lugar. La descripcin del proceso se indica en su interior.
A=b+c
Figura 11. El proceso se indica por medio de un rectngulo. En su interior indicamos lo que se tiene que procesar.
Similar al proceso, tenemos el proceso predefinido. Su forma tambin es un rectngulo, pero ste tiene dos franjas a los lados. Se usa para indicar que haremos uso de un proceso que ya ha sido definido en otra parte. Un ejemplo de esto sera un mtodo, como los que ya hemos usado. Principalmente lo usaremos para indicar llamadas a funciones o mtodos definidos por nosotros mismos. En un captulo posterior aprenderemos cmo hacer nuestros propios mtodos.
Tolnt32()
Nuestro prximo elemento es conocido como condicin. Utilizaremos este elemento cuando aprendamos cmo hacer que el programa tome sus propias
DATOS DE TRABAJO
Algunas veces necesitaremos variables que nos apoyen para resolver algn clculo o proceso. A stas las llamaremos datos de trabajo. Los datos de trabajo se descubren cuando hacemos el anlisis del problema. Si llegamos a omitir alguno durante el anlisis siempre es posible agregarlo durante el desarrollo, pero esto debe ser la excepcin a la regla.
62
www.redusers.com
decisiones. Bsicamente, sirve para hacer una seleccin entre las posibles rutas de ejecucin del algoritmo, que depender del valor de la expresin evaluada. Su forma es la de un rombo y a partir de las esquinas de ste surgirn las flechas hacia las posibles rutas de ejecucin del algoritmo.
A>B
Luego nos encontramos con un componente conocido como datos. Su forma es la de un paralelogramo y podemos usarlo para indicar la salida o la entrada de los datos. Un ejemplo de esto sera cuando llevamos a cabo la peticin de un valor al usuario o cuando mostramos un valor en pantalla. Adentro de l indicamos qu dato se pide o se presenta.
Pedir A
Figura 14. En este caso usamos el dato para indicar la peticin del valor de una variable.
Hemos visto los elementos principales del diagrama de flujo. Ahora podemos hacer un ejercicio que muestre la solucin de un problema en la computadora.
C# EXPRESS...
Es una versin gratuita de C# con las herramientas bsicas para programar en este lenguaje. Esta versin nos provee todo lo necesario para los temas que aprenderemos en este libro. Aunque la versin es gratuita, es necesario registrarla para poder utilizarla por ms de treinta das. La podemos descargar de http://msdn2.microsoft.com/en-us/express/aa700756.aspx.
www.redusers.com
63
Pedir datos
Calcular rea
Calcular permetro
Mostrar resultados
Pedir ancho
Pedir alto
Mostrar rea
Mostrar permetro
Figura 15. Aqu tenemos nuestro problema subdividido en problemas menores y fciles de resolver.
Ya que conocemos el problema y lo hemos subdividido en varios subproblemas, podemos identificar de manera ms clara los datos que nos hacen falta para poder trabajar en l. La descripcin del problema nos proporciona dos datos explcitos: el
MSDN
Si queremos encontrar informacin sobre cualquier clase o mtodo de C#, el lugar apropiado para hacerlo es el sitio web MSDN que nos provee Microsoft. Cuando realicemos la bsqueda debemos filtrar para buscar nicamente contenidos del lenguaje C# y as evitar confusiones con informacin de otros lenguajes. La direccin es www.msdn.com.
64
www.redusers.com
y el permetro. Pero tambin reconocemos inmediatamente dos datos implcitos que son necesarios: el alto y el ancho del rectngulo. Nosotros sabemos que necesitamos una cadena para recibir el valor escrito por el usuario, pero como tal, esta cadena no forma parte del problema. Sin embargo, nos ayuda a resolverlo, por lo que la cadena ser un dato de trabajo. Los datos que hemos identificados sern colocados en una tabla de la siguiente forma:
rea
NOMBRE rea permetro ancho alto valor TIPO Float Float Float Flota String VALOR INICIAL 0.0 0.0 1.0 1.0
Hemos decidido usar el tipo float, ya que podemos tener valores decimales en el clculo del permetro. Como un rectngulo con ancho o alto de 0 no tiene sentido, hemos seleccionado como valor inicial para estas variables a 1. Ahora viene el paso ms importante: la creacin del algoritmo. Sin embargo, si observamos la forma como subdividimos el problema, podemos ver que nos da una indicacin de los pasos que son necesarios colocar en el algoritmo.
Pedir datos
Calcular rea
Calcular permetro
Mostrar resultados
Pedir ancho
Pedir alto
Mostrar rea
Mostrar permetro
Figura 16. La subdivisin nos muestra una lista de los pasos posibles necesarios en la subdivisin del algoritmo.
Con esta informacin creamos el algoritmo con el diagrama de flujo. En ste aparece la secuencia de pasos en el orden correcto. Veamos cmo queda el diagrama.
www.redusers.com 65
Inicio
Pedir ancho
Pedir alto
Mostrar rea
Mostrar permetro
Fin
Figura 17. El diagrama de flujo muestra el algoritmo. Las diferentes figuras nos indican el tipo de actividad que se realiza.
Podemos observar cmo hemos utilizado el trapezoide cuando es necesario pedirle o mostrarle un dato al usuario. Los clculos con la frmula correspondiente estn en los rectngulos, ya que son procesos, y el inicio y fin del algoritmo estn representados por los terminadores.
66 www.redusers.com
Con las variables definidas, entonces procedemos a codificar cada uno de los pasos del algoritmo. Recorremos paso por paso y en el mismo orden en que se encuentran, y vemos que lo primero es pedir el ancho del rectngulo.
Console.Write(Dame el ancho del rectngulo: ); valor = Console.ReadLine(); ancho = Convert.ToSingle(valor); // Convertimos a flotante
Lo siguiente que hace el algoritmo es pedir el alto del rectngulo, entonces el cdigo necesario es el siguiente.
Console.Write(Dame el alto del rectngulo: ); valor = Console.ReadLine(); alto = Convert.ToSingle(valor); // Convertimos a flotante
EXPERIMENTANDO
Aprender a programar requiere de mucha prctica y mucha experimentacin. Es bueno probar con los programas y ver qu es lo que sucede. No debemos temer en cometer errores cuando estamos aprendiendo. Tambin es bueno verificar la documentacin para las funciones, las clases y los mtodos ya que es posible encontrar utilidades en stas para el futuro.
www.redusers.com
67
Una vez que hemos obtenido todos los datos de entrada, podemos decir que ya tenemos un proceso. Este proceso ser el encargado de calcular el rea que ocupa el rectngulo. Veamos el ejemplo a continuacin:
area = ancho * alto;
Si vemos con detenimiento el algoritmo y tambin su paso siguiente, encontraremos que volvemos a trabajar con datos nuevamente, pero en este ltimo caso slo mostramos en pantalla el valor de rea calculado. Veamos para comprender mejor de qu hablamos.
Console.WriteLine(El rea es : {0} unidades cuadradas, area);
Como ltimo paso del algoritmo que se est ejecutando, slo queda que mostremos en nuestra aplicacin de consola, el valor calculado del permetro. A continuacin escribamos el ltimo cdigo necesario en nuestra aplicacin:
Console.WriteLine(El permetro es : {0} unidades, perimetro);
Hemos visto hasta aqu una forma completa y compleja de cmo manejar desde una aplicacin de consola, la manipulacin de datos, variables y operaciones matemticas, con un claro ejemplo estudiado paso a paso. Con esto ya hemos finalizado el cdigo de la aplicacin. Ahora lo podemos compilar y probar, y todo debe funcionar correctamente, si no hemos olvidado de colocar nada en l.
68
www.redusers.com
Figura 18. Aqu podemos ver la ejecucin de nuestro programa, la forma como pide los datos y los resultados calculados.
RESUMEN
Para programar software para computadoras necesitamos conocer un lenguaje de programacin. Uno de estos lenguajes es C#. Los programas deben ser ordenados e indicar paso a paso lo que se debe hacer, y para esto hacemos uso de los algoritmos. La informacin se guarda en variables y el tipo indica la informacin que puede tener en su interior por lo que es posible mostrar datos en la consola y tambin pedrselos al usuario. Los operadores aritmticos nos permiten llevar a cabo operaciones matemticas, siempre que usemos una metodologa correcta de resolucin de problemas.
www.redusers.com
69
EJERCICIOS PRCTICOS
1 Hacer un programa que calcule el permetro de cualquier polgono regular.
70
www.redusers.com
C#
Captulo
LA TOMA DE DECISIONES
No todos los problemas se resuelven linealmente, a veces es necesario tener que tomar una decisin o ejecutar determinadas acciones cuando una condicin se cumple, y otras cuando no lo hace. Supongamos que nuestro problema consiste en mantener la temperatura de un balde con agua tibia. Para hacerlo nosotros podemos agregar agua caliente o agua fra. En este problema necesitaramos tomar una decisin sobre qu tipo de agua agregar. De igual forma, hay muchos problemas en los que para poder resolverlos necesitamos conocer una condicin o tomar una decisin. En C# es sencillo poder lograr esto, ya que el lenguaje nos provee diferentes herramientas para poder lograrlo. Tendremos que utilizar expresiones y stas se evaluarn. En este caso usaremos expresiones relacionales y expresiones lgicas, que se evaluarn, y dependiendo del resultado de esa evaluacin, se llevarn a cabo ciertos pasos del algoritmo u otros. Empecemos por conocer las expresiones que necesitamos.
Expresiones relacionales
Las expresiones relacionales se usan para expresar la relacin que existe entre dos valores. Los valores pueden estar contenidos adentro de variables o ser colocados explcitamente. Estas expresiones, al igual que las expresiones aritmticas, tienen sus propios operadores. La expresin ser evaluada, pero el resultado de la evaluacin tendr nicamente dos valores posibles: true o false. Ambos valores son de tipo bool y true es usado para indicar que la expresin evaluada es verdadera. El valor de false por su parte se utiliza para indicar que la expresin evaluada es falsa. Empecemos por conocer primero a los operadores relacionales y luego veremos ejemplos de expresiones relacionales con su resolucin.
Operadores relacionales
En la tabla 1 podemos apreciar los operadores relacionales en C#. La forma como estn escritos sus signos es la forma como debemos colocarlos en nuestro programa.
72
www.redusers.com
La toma de decisiones
OPERADOR Igualdad No igual Mayor que Menor que Mayor que igual Menor que igual
Tabla 1. Esta tabla nos muestra los diferentes operadores relacionales de C#.
El operador de igualdad se representa con dos signos igual juntos y sin espacio. Colocar un solo signo igual, indica que el operador ser de asignacin. Esto puede derivar en errores de lgica, porque una asignacin siempre evala a verdadero, pero una igualdad no. Este operador es el ms sencillo. Supongamos que ya tenemos las variables y las inicializamos con los siguientes valores:
int int int int a b c d = = = = 5; 7; 5; 4;
Como el valor contenido en a es 5 y el valor contenido en c tambin es 5, vemos que se cumple 5 igual a 5, por lo que la expresin se evala como true. Veamos qu sucede en la siguiente expresin:
a == d
En este caso el valor contenido en d es 4, por lo que la expresin 5 igual a 4 no se cumple y el valor de la expresin es false. En el lado derecho y en el lado izquierdo de la expresin podemos colocar cualquier valor, variable o expresin. Si colocsemos una expresin, primero se evaluara sta y luego se procedera a evaluar la expresin relacional principal.
a == (3 + 2)
www.redusers.com
73
En este caso 3 + 2 se evala como 5 y luego 5 igual a 5, lo que nos da como valor final de la expresin true. Otro ejemplo es el siguiente:
(b 2) == d
Al evaluar b - 2 obtenemos 5, entonces la expresin es 5 igual a 4, lo que evidentemente nos da como resultado final false. sta es la forma como se evalan las expresiones relacionales y ahora veremos ms ejemplos con otros operadores. Tambin tenemos al operador de desigualdad, que se crea por medio de un signo de admiracin y luego el signo de igual.
a != 7
En este caso tenemos 5 no es igual a 7, lo cual es cierto, y obtenemos el valor true como resultado de la evaluacin.
a != c
Para esta expresin tenemos 5 no es igual a 5, y se evala la expresin como falsa, lo que nos da false como valor final. El operador > sirve para evaluar una relacin del tipo mayor que. Si el valor del lado izquierdo es mayor que el valor del lado derecho, regresar true, en caso contrario regresar false.
b > a
Este expresin nos da 6 mayor que 6, lo cual, si analizamos todos los pasos hasta aqu, nos indica que es falso tambin y obtenemos false como resultado.
74 www.redusers.com
La toma de decisiones
En el operador < evaluamos una relacin del tipo menor que. sta da true como resultado si el valor del lado izquierdo es menor que el valor que encontramos en el lado derecho. Si esto no se cumple, entonces el valor regresado ser false.
d < a
Esta expresin tambin da como resultado false, ya que 4 menor que 4 no es verdadera. Para poder evaluar si un valor es mayor que o igual a otro valor usamos el operador >=. Su forma de trabajo es similar a la de los otros operadores.
b >= a
Para esta expresin tenemos 7 mayor que igual a 5, es cierta y da true de resultado.
b >= (a + c)
En este caso obtendramos 7 mayor que igual a 10, lo cual sabemos que es falso y y, por lo cual, como resultado obtendramos false.
www.redusers.com
75
b >= b
Aqu comparamos la diferencia de resultado con relacin a usar >= en lugar de >. Para esta expresin evaluamos 7 mayor que igual a 7. Esto es verdadero y el resultado final es true. De igual manera tenemos al operador <=, pero ste evala a la inversa.
a <= b
En esta ltima expresin 7 menor que igual a 7 es verdadero y nuevamente obtenemos true como resultado.
El uso de if
Ya aprendimos a usar las expresiones relacionales y el tipo de valor devuelto. Es el momento de hacer algo prctico con ellas. Este tipo de expresiones se usa en diferentes casos, pero generalmente en las estructuras selectivas o repetitivas. Las estructuras selectivas sern estudiadas en este captulo, las repetitivas en un captulo posterior. Las estructuras selectivas son aquellas que nos permiten hacer una seleccin entre dos o varias rutas de ejecucin posibles. La seleccin se llevar a cabo segn el valor de una expresin. Esta expresin puede ser una expresin relacional. Nuestra primera estructura selectiva se conoce como if, que es un si condicional. Si tal cosa sucede, entonces haz tal cosa. El uso del if es sencillo:
if(expresin) Sentencia a ejecutar
El uso de if requiere que coloquemos una expresin a evaluar entre parntesis. Si el resultado de esta expresin es true, entonces la sentencia a ejecutar se lleva a cabo.
76 www.redusers.com
La toma de decisiones
Si el resultado de la evaluacin es false, entonces la sentencia a ejecutar nunca se lleva a cabo, o dicho de otra forma, es ignorada. En el diagrama de flujo if se representa por medio de un rombo. En el interior del rombo colocamos la expresin a evaluar, de las esquinas sacamos una ruta de ejecucin en el caso de que s se cumpla la condicin o en el caso de que no se cumpla.
Expresin
SI
NO
Veamos un primer ejemplo donde nos puede servir if y las expresiones. Crearemos un programa que le pida al usuario un nmero, y la computadora debe decir si el nmero es positivo o negativo. Para ver el algoritmo de este programa, creamos su diagrama de flujo e incluimos los if necesarios.
Inicio
Pedir nmero
Figura 2. ste es el diagrama de flujo del algoritmo para resolver el problema. Podemos observar que tenemos dos rutas de ejecucin en cada if.
www.redusers.com 77
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { int numero = 0; // Donde guardamos el nmero string valor = ; // Para guardar la cadena dada por el usuario // Pedimos el nmero Console.Write(Dame un numero entero:); Valor = Console.ReadLine(); numero = Convert.ToInt32(valor); // Convertimos la cadena a entero // Hacemos uso de if con la expresin para el caso de los positivos if (numero >= 0) Console.WriteLine(El numero {0} es positivo, numero); // se ejecuta si se cumple numero>=0 // Hacemos uso de if con la expresin para el caso de los negativos if (numero < 0) Console.WriteLine(El numero {0} es negativo, numero); // se ejecuta si se cumple numero<0 }
78
www.redusers.com
La toma de decisiones
} }
La primera parte el programa es de muy fcil comprensin. Luego de sta, nos encontramos con la primera sentencia if. Para este if se tiene la expresin numero >= 0. Si esa expresin se evala como true, entonces la siguiente sentencia se ejecuta, de lo contrario ser ignorada y continuar el programa. Supongamos que el valor guardado en numero es 3, entonces la expresin relacional regresa un valor de true. Al obtener true, if lleva a la ejecucin y el mensaje que dice que se ejecuta un nmero positivo. Luego se contina con el siguiente if. Para ste, la expresin es numero < 0, como en este ejemplo numero vale 3, entonces la expresin se evala como false, por lo que, mientras el valor de la expresin sea false, if no ejecutar en ningn momento el mensaje que dice que el nmero es negativo. Esto es exactamente lo que deseamos que realice desde un principio este programa.
ste es un buen momento para comenzar a experimentar en nuestros desarrollos, cambiando los valores, tanto negativos como positivos, incluido el cero y ver cmo responder nuestro programa.
www.redusers.com 79
Figura 4. En este caso damos un nmero negativo y podemos observar el comportamiento del programa.
80
www.redusers.com
La toma de decisiones
Veamos un ejemplo donde hacemos uso de esto. Sabemos que la divisin entre cero no est definida, entonces debemos hacer un programa que le pregunte al usuario el dividendo y el divisor, pero que cuando el divisor sea cero no lleve a cabo la divisin. Como siempre, primero hacemos nuestro anlisis y creamos el algoritmo en forma de diagrama de flujo.
Inicio
Pedir dividendo
Pedir divisor
Divisor!=0
NO
Resultado = dividendo/divisor
Mostrar resultado
Fin
Figura 5. ste es el diagrama de flujo del algoritmo. Podemos pensar que lo que hemos agrupado es lo que se encuentra adentro del bloque de cdigo de if.
www.redusers.com
81
// Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias float dividendo = 0.0f; float divisor = 1.0f; float resultado = 0.0f; string valor = ; // Pedimos el dividendo Console.WriteLine(Dame el dividendo:); valor = Console.ReadLine(); dividendo = Convert.ToInt32(valor); // Pedimos el divisor Console.WriteLine(Dame el divisor:); valor = Console.ReadLine(); divisor = Convert.ToInt32(valor); // Si el divisor es vlido, entonces hacemos la divisin if (divisor != 0.0f) { // Hacemos la operacin resultado = dividendo / divisor; // Mostramos el resultado Console.WriteLine(El resultado de la divisin es {0}, resultado); } } } }
Podemos observar que hemos colocado un bloque de cdigo para if. Si la expresin de divisor != 0.0f es verdadera, entonces se ejecuta el bloque de cdigo donde tenemos la operacin y el desplegado del resultado. Si la expresin se evala como falsa, todo el bloque de cdigo es ignorado y no ejecutan las sentencias que estn en su interior. Ahora podemos compilar el programa y dar valores para hacer pruebas y observar el comportamiento. Vemos que efectivamente cuando el divisor tiene un valor de cero, la operacin y el mensaje no se ejecutan.
82 www.redusers.com
La toma de decisiones
Figura 6. En este caso visto aqu, es ejecutada la divisin y a continuacin se muestra el resultado.
Figura 7. Como hemos colocado el valor de cero en el divisor, la divisin no se lleva a cabo.
www.redusers.com 83
El uso de else
Con los programas anteriores con los que estuvimos trabajando, donde utilizamos la sentencia if, hemos visto que podemos indicar que determinada sentencia se ejecute cuando deseamos que una condicin se cumpla. Sin embargo, puede ocurrir que a veces necesitamos que una sentencia se ejecute cuando se cumple la condicin y que otra sentencia se ejecute cuando esa condicin no se cumpla. Si nos encontramos en este caso, una forma de resolverlo sera colocar un if con una condicin y luego otro if con una condicin que sea complemento de la primera. Esto ya lo hemos hecho anteriormente en el programa de los nmeros positivos y negativos. Sin embargo, existe otra forma ms sencilla que la utilizada en este programa para hacerlo. Esta forma puede sernos de mucha utilidad para simplificar la lgica y que no nos veamos obligados de tener que colocar tantos if dentro de una sentencia. Para lograr esto haremos uso de else. Siempre utilizaremos else a continuacin de una sentencia if, ya que else no se puede usar slo. Tenemos que colocar nuestro cdigo de la siguiente forma:
if(condicin) Sentencia1; else Sentencia2;
Si la condicin es evaluada como verdadera, entonces se ejecuta la sentencia 1, en cambio, cuando la condicin se evala como falsa, se ejecuta la sentencia 2. A continuacin analizaremos cmo hacer uso de este caso para simplificar nuestro cdigo. Para esto elegimos para representar este ejemplo el programa de los nmeros positivos y negativos. Lo primero que tenemos para analizar es el grfico del diagrama de flujo, y, como utilizamos una estructura o sentencia de tipo if-else, una de las salidas del rombo corresponde al cdigo que se ejecuta cuando la expresin es evaluada como verdadera (if) y la otra salida es la que utilizamos para la sentencia que se ejecuta cuando la expresin es evaluada como falsa (else).
VERIFICAR EL PROGRAMA
Siempre es conveniente verificar la ejecucin del programa y colocar valores que puedan provocar problemas con el fin de detectar cualquier error de lgica. Podemos probar valores positivos, negativos, el cero, fraccionarios, etctera. Si encontramos problemas con los valores, podemos hacer uso del if para validar los valores antes de usarlos.
84
www.redusers.com
La toma de decisiones
Inicio
Pedir nmero
NO
Nmero>=0
Fin
www.redusers.com
85
{ int numero = 0; // Donde guardamos el nmero string valor = ; // Para guardar la cadena dada por el usuario // Pedimos el numero Console.Write(Dame un nmero entero:); valor = Console.ReadLine(); numero = Convert.ToInt32(valor); // Convertimos la cadena a entero // Hacemos uso de if con la expresin para el caso de los positivos if (numero >= 0) Console.WriteLine(El nmero {0} es positivo, numero); // se ejecuta si se cumple numero>=0 else Console.WriteLine(El numero {0} es negativo, numero); // se ejecuta si NO se cumple numero>=0 } } }
Podemos ver que el programa es ms sencillo, se ha simplificado la lgica y esto lo hace ms fcil de leer y mantener. Esto no significa que siempre debamos usar ifelse. Hay que hacer uso de l cuando tenemos algo que deseamos ejecutar cumpliendo previamente la condicin especificada, y algo que deseamos ejecutar cuando sta no se cumpla. Abusar de if-else o usarlo sin sentido complicar la lgica del programa, pero usarlo bien nos ayuda.
La toma de decisiones
Inicio
Pedir dividendo
Pedir divisor
Divisor==0
NO
Resultado = dividendo/divisor
Mostrar resultado
Fin
Figura 9. Aqu podemos ver el diagrama de flujo con las dos rutas de ejecucin posibles, una para if y la otra para else.
www.redusers.com
87
float divisor = 1.0f; float resultado = 0.0f; string valor = ; // Pedimos el dividendo Console.WriteLine(Dame el dividendo:); valor = Console.ReadLine(); dividendo = Convert.ToInt32(valor); // Pedimos el divisor Console.WriteLine(Dame el divisor:); valor = Console.ReadLine(); divisor = Convert.ToInt32(valor); if (divisor == 0) Console.WriteLine(El divisor no es vlido); else { // Hacemos la operacion resultado = dividendo / divisor; // Mostramos el resultado Console.WriteLine(El resultado de la divisin es {0}, resultado); } } } }
De esta forma podemos manejar dos opciones, una para el divisor con el valor de cero y otra para cuando el divisor es vlido.
88
www.redusers.com
La toma de decisiones
www.redusers.com
89
valor = Console.ReadLine(); a = Convert.ToSingle(valor); // Pedimos el segundo nmero Console.Write(Dame el segundo numero:); valor = Console.ReadLine(); b = Convert.ToSingle(valor); // Verificamos para suma if (opcion == 1) resultado = a + b; // Verificamos para resta if (opcion == 2) resultado = a - b; // Verificamos para division if (opcion == 3) if (b != 0) // este if esta anidado resultado = a / b; else // Este else pertenece al segundo if Console.WriteLine(Divisor no valido); // Verificamos para la multiplicacion if (opcion == 4) resultado = a * b; // Mostramos el resultado Console.WriteLine(El resultado es: {0}, resultado); } } }
El programa es sencillo, solamente necesitamos if para cada operacin, pero para el caso de la divisin necesitaremos colocar otro if para verificar que el divisor no sea cero. Es decir que para la divisin tendremos if anidados. El diagrama de flujo de la aplicacin se muestra en la siguiente figura.
UN IF ADENTRO DE OTRO IF
Cuando colocamos un if adentro del cdigo que puede ejecutar un if anterior, estamos diciendo que tenemos if anidados. Este tipo de estructura es muy til y puede ayudarnos a optimizar los programas, pero debemos tener cuidado de usarla correctamente para evitar errores de lgica. Cuando se codifica hay que hacerlo en forma ordenada.
90
www.redusers.com
Mostrar Men
Pedir opcin
Pedir a
Pedir b
Resultado = a + b NO
Resultado = a - b NO
B!= 0 S
NO
NO
Resultado = a/b
Resultado = a b NO
Fin
Figura 10. ste es el diagrama de flujo. Es fcil observar en la divisin el anidamiento de if.
www.redusers.com 91
En el programa anterior observamos cmo se ha usado if anidado para la divisin, slo tenemos que ser cuidadosos con else para poder saber a qu if pertenece. Si en nuestros programas hacemos uso de la indentacin, es decir colocar espacios antes de la sentencia, podemos facilitar reconocer qu parte del cdigo pertenece a qu seccin. Algunos editores de cdigo hacen esto por nosotros de forma automtica y visualmente es ms fcil reconocer el cdigo.
Escalera de if-else
Otra estructura que se puede utilizar es la escalera de if-else. Una de sus funciones principales es optimizar la ejecucin del cdigo. Algunas veces son necesarias porque as lo requiere la lgica del programa. Al igual que con los if anidados, no hay que utilizarlos sin planeacin, ya que al no programarlos correctamente, nos puede llevar a errores de lgica que pueden resultar difciles de solucionar. Ahora aprendamos cmo los podemos usar para que nuestro cdigo se vuelva ms eficiente. Si observamos el programa de las operaciones matemticas, tenemos un if para cada operacin. Esto significa que cuando nuestro programa se ejecuta, sin importar si se ha seleccionado la suma o la multiplicacin, siempre se tienen que ejecutar al menos cuatro if. Los if pueden ser operaciones costosas ya que se tienen que evaluar expresiones. La forma de optimizar esto es con una cadena de if-else. El concepto es sencillo y consiste en colocar un if en la sentencia del else. Esto quedara como muestra el siguiente cdigo:
if(expresin 1) Sentencia 1 else if(expresin 2) Sentencia 2 else if(expresin 3) Sentencia 3
92
www.redusers.com
La toma de decisiones
Como podemos ver se genera una figura que parece una escalera y por eso su nombre. Modifiquemos el programa de las operaciones matemticas. En primer lugar su diagrama de flujo queda de la forma que se muestra en la figura.
Inicio
Mostrar Men
Pedir opcin
Pedir a
Pedir b
Opcin==1 NO
Resultado = a + b
Opcin==2
Resultado = a - b
NO Opcin==3
B!= 0 S
NO
NO Resultado = a/b
Opcin==4 NO
Resultado = a b
Mostrar resultado
Fin
Figura 11. En este diagrama de flujo podemos observar nuestra escalera de if-else.
www.redusers.com 93
94
www.redusers.com
La toma de decisiones
// Verificamos para suma if (opcion == 1) resultado = a + b; // Verificamos para resta else if (opcion == 2) resultado = a - b; // Verificamos para division else if (opcion == 3) if (b != 0) // este if esta anidado resultado = a / b; else // Este else pertenece al segundo if Console.WriteLine(Divisor no vlido); // Verificamos para la multiplicacion else if (opcion == 4) resultado = a * b; // Mostramos el resultado Console.WriteLine(El resultado es: {0}, resultado); } } }
Si ejecutamos el programa, veremos que hace exactamente lo mismo que la versin anterior. Pero dnde est la optimizacin? Si observamos el cdigo, podemos encontrarla. Supongamos que el usuario ha seleccionado la opcin 1, es decir la suma.
www.redusers.com
95
Con esto se cumple la condicin del primer if y se ejecuta la operacin de suma. Pero nosotros sabemos que se ejecuta if o else, nunca ambos. Si observamos, vemos que todas las dems operaciones estn en la ruta de else, por lo que son ignoradas. Antes tenamos que hacer cuatro if siempre, ahora solamente se hizo uno y los dems se evitaron, ah es donde est la optimizacin. En otras palabras, en el programa anterior siempre eran cuatro if y en el nuevo, en el mejor de los casos tenemos un solo if, pero en el peor de los casos tenemos cuatro. As es cmo se llevo a cabo la optimizacin.
Expresiones lgicas
Al igual que las expresiones aritmticas y relacionales, las expresiones lgicas tienen sus propios operadores. stos son: y, o y no. En ingls los conocemos como: and, or y not.
OPERADOR && || ! SIGNIFICADO y o no
El uso de la conjuncin
Empecemos a conocerlos. El primer operador es y, conocido como conjuncin. Para usar este operador es necesario tener dos expresiones. Una expresin a la izquierda y la otra a la derecha. Las expresiones se evalan devolviendo valores true o false. Con la conjuncin, la expresin se evala como verdadera nicamente cuando ambas expresiones son verdaderas. La siguiente es la tabla de verdad para este operador:
P true false true false Q true true false false P&&Q true false false true
RECORDAR LA CONJUNCIN
Recordar la conjuncin es fcil, nicamente es verdadera cuando ambas expresiones son verdaderas. Podemos recordar la regla o simplemente tener una impresin de la tabla a mano. Debemos recordar que se necesitan dos operandos, uno a la derecha y el otro a la izquierda. Con un solo operando no es posible hacerlo.
96
www.redusers.com
La toma de decisiones
Supongamos que tenemos que decidir si debemos llenar el tanque de gasolina del vehculo. Esto lo hacemos si el tanque tiene menos del 50% y si la distancia a recorrer es de ms de 200 km. Como vemos, tenemos que usar la conjuncin ya que tenemos dos condiciones y ambas se deben cumplir para que suceda la carga de la gasolina. Si colocamos esto como expresin quedara:
if(tanque < 50 && distancia > 200) Cargar gasolina
Supongamos que tanque es 25 y distancia es 350, al evaluar 25 < 50 y 350 > 200 tenemos lo siguiente.
if(true && true) Cargar gasolina
En nuestra tabla sabemos que cuando ambas expresiones son verdaderas, entonces se cumple la conjuncin y la expresin lgica nos evala a true.
if(true) Cargar gasolina
Por lo que cargaremos gasolina. Ahora supongamos que tanque tiene el valor de 90 y distancia es nuevamente 350. Las primeras evaluaciones nos daran:
if(false && tue) Cargar gasolina
RECORDAR LA DISYUNCIN
Es fcil recordar la tabla de verdad de la disyuncin. sta es verdadera cuando cualquiera de las expresiones es verdadera. Ya que si una es verdadera o la otra es verdadera, entonces la expresin total es verdadera. Tambin es bueno que tengamos esta tabla a mano hasta que aprendamos la disyuncin de memoria.
www.redusers.com
97
Al ver nuestra tabla, vemos que false y true se evalan como false, por lo que no realizaremos la carga de gasolina.
El uso de la disyuncin
Para la disyuncin hacemos uso del operador o. ste tambin necesita dos expresiones, una en el lado derecho y otra en el lado izquierdo. Esta disyuncin tiene la siguiente tabla de verdad:
P true false true false Q true true false false P||Q true true true false
Veamos un ejemplo con la disyuncin. Tenemos que tomar la sombrilla si llueve o si hay mucho sol. La expresin podra quedar de la siguiente manera:
if(lluvia == true || muchosol == true) Tomar sombrilla
En este caso, si vemos la tabla de verdad, podemos observar que el resultado de evaluar la expresin nos da true, por lo que s debemos tomar la sombrilla. Ahora veamos qu sucede si no hay lluvia y no hay sol. La expresin quedara como:
RECORDAR LA NEGACIN
La negacin simplemente intercambia true por false y false por true. Resulta fcil recordarla. Se invierte el valor del operando del lado derecho. No debemos olvidar que este operador solamente necesita un operando y siempre se encuentra del lado derecho. No hacerlo as puede originar problemas con nuestro programa.
98
www.redusers.com
La toma de decisiones
El uso de la negacin
Nos falta conocer un operador ms, el de la negacin. Ese operador es muy sencillo y solamente necesita hacer uso de un operando del lado derecho. Con estas condiciones dadas, esta expresin ser negada por el operador.
p true false Negacin false true
Esto quiere decir que si el operando del lado derecho es true, el operador regresa false. Y si el operando del lado derecho es false, el operador regresa true. Veamos un ejemplo para poder comprender mejor esto. Tenemos una habitacin con una bombilla elctrica y supongamos que tenemos que prender la luz del cuarto cuando no es de da. Entonces nuestra expresin queda de la siguiente forma:
if(!dia == true) Prender la luz
Veamos qu sucede cuando la expresin dia tiene como valor verdadero. La expresin dia == true se evala como true y luego ste se niega, lo que al final nos da como resultado un valor false. Como if recibe el valor false, se ejecutar la orden o el mtodo prender la luz. Pero si dia es false, entonces la expresin dia == true se evala como false, que es negado e if recibe true. Como if recibe true, se ejecuta prender la luz. Ahora podemos analizar un ejemplo de cmo hacer uso de una expresin lgica. Esto podemos aplicarlo en nuestro programa de las operaciones matemticas. Podemos observar que la divisin se debe hacer cuando el usuario ha seleccionado entre las opciones presentadas, la nmero 3, y el divisor tiene un valor diferente de cero. ste es un caso en el que podemos hacer uso de la conjuncin. Si procedemos a modificar la aplicacin para realizar esto, nuestro diagrama de flujo debera modificarse, quedando similar a la forma que vemos a continuacin:
www.redusers.com 99
Inicio
Mostrar Men
Pedir opcin
Pedir a
Pedir b
Opcin==1 NO
Resultado = a + b
Opcin==2
SI S
Resultado = a - b
NO
Resultado = a/b
Opcin==4 NO
Resultado = a b
Mostrar resultado
Fin
Figura 12. Podemos observar cmo la expresin lgica se encuentra dentro del rombo en la condicin de la divisin.
100
www.redusers.com
La toma de decisiones
namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias float a = 0.0f; float b = 0.0f; float resultado = 0.0f; string valor = ; int opcion = 0; // Mostramos el men Console.WriteLine(1- Suma); Console.WriteLine(2- Resta); Console.WriteLine(3- Divisin); Console.WriteLine(4- Multiplicacin); Console.Write(Que operacin deseas hacer: ); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor); // Pedimos el primer nmero Console.Write(Dame el primer numero:); valor = Console.ReadLine(); a = Convert.ToSingle(valor); // Pedimos el segundo nmero Console.Write(Dame el segundo numero:); valor = Console.ReadLine(); b = Convert.ToSingle(valor); // Verificamos para suma if (opcion == 1) resultado = a + b; // Verificamos para resta else if (opcion == 2)
www.redusers.com
101
resultado = a - b; // Verificamos para divisin else if (opcion == 3 && b!=0) // Aqu usamos una expresin lgica resultado = a / b;
// Verificamos para la multiplicacin else if (opcion == 4) resultado = a * b; // Mostramos el resultado Console.WriteLine(El resultado es: {0}, resultado); } } }
Veamos otro ejemplo. Supongamos que tenemos que hacer un programa que nos indique si una persona puede conducir un automvil, y las condiciones para que lo conduzca son que tenga ms de 15 18 aos y que tenga permiso de sus padres. Si observamos el problema vemos que necesitamos dos variables, una para la edad y otra para el permiso de los padres. La expresin lgica podra quedar de la siguiente forma:
if(edad > 18 || (edad > 15 && permiso == true)) Puede conducir
Vemos que en este caso usamos una expresin ms compleja y al igual que con las expresiones aritmticas, hemos utilizado los parntesis para ayudarnos y hacer que
EXPRESIONES COMPLEJAS
Cuando tenemos expresiones complejas, para evitar errores es til hacer una tabla de verdad de la expresin y probar todos sus casos. De esta forma podemos ver si funciona tal y como lo esperbamos. La tabla de verdad debe ser similar a las que hemos utilizado y nos podemos apoyar en ella para encontrar el valor final de la expresin.
102
www.redusers.com
La toma de decisiones
la lgica sea ms fcil de leer. Nuestra expresin es una disyuncin, en el lado izquierdo del or tenemos edad > 18, en el lado derecho tenemos una expresin (edad > 15 && permiso == true). La segunda expresin es una conjuncin y deber evaluarse primero. El resultado que se obtenga ser usado por la disyuncin. Ahora podemos hacer el programa de ejemplo para esta expresin. Primero, observemos el diagrama de flujo a continuacin:
Inicio
Pedir edad
Pedir permiso
Fin
Figura 13. Al igual que en el caso anterior, debemos colocar la expresin dentro del rombo sin importar su complejidad.
www.redusers.com
103
namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias int edad = 0; bool permiso = false; string valor = ; // Obtenemos los datos Console.Write(Dame la edad: ); valor = Console.ReadLine(); edad = Convert.ToInt32(valor); Console.Write(Tiene permiso de los padres (true/false): ); valor = Console.ReadLine(); permiso = Convert.ToBoolean(valor); // Verificamos que se cumpla la regla if(edad > 18 || (edad > 15 && permiso == true)) Console.WriteLine(Es posible conducir); else Console.WriteLine(No puedes conducir);
104
www.redusers.com
La toma de decisiones
} } }
El uso de switch
En uno de los ejemplos anteriores, en los que realizamos las operaciones matemticas, hemos observado que para cada operacin debemos utilizar un if. Esto es correcto, y en varias ocasiones veremos que es necesario tomar diferentes opciones dependiendo del valor de una variable. Como esto puede ocurrir frecuentemente, tenemos una estructura selectiva que nos ayuda y nos permite colocar el cdigo para estos casos con facilidad. Esta estructura se conoce como switch. Para sta necesitamos una variable y varios casos. Por ejemplo, en el programa de las operaciones, cada una de ellas es un caso. El valor de la variable se compara con un valor para cada caso. Si el valor coincide, entonces se empieza a ejecutar el cdigo a partir de esa lnea. Cuando usamos switch es necesario colocar entre parntesis la variable que utilizaremos para llevar a cabo las comparaciones. Luego tenemos que crear un bloque de cdigo y colocar adentro de l los casos y el cdigo a ejecutar para cada caso. Para indicar un caso, usamos case seguido del valor de comparacin y dos puntos. Existe un caso llamado default, que podemos utilizar si lo deseamos. Este caso siempre debe ser el ltimo caso definido. Cuando la variable de comparacin no ha encontrado su valor en ninguno de los casos, entonces se ejecuta el cdigo del caso default. En los casos podemos colocar cualquier cdigo C# que sea vlido. Para indicar dnde termina el cdigo de un caso debemos hacer uso de break, que nos permitir salir de la ejecucin de una estructura selectiva o repetitiva. Esto lo veremos con ms detalle en otro captulo. Si no hacemos uso de break y el caso est vaco, entonces el programa continuar ejecutando el cdigo del prximo caso y as sucesivamente hasta el final del bloque del cdigo que pertenece al switch.
www.redusers.com
105
puede ser representado en el diagrama de flujo por medio del rombo. En su interior colocamos la variable de comparacin y de las esquinas o los lados podemos sacar las diferentes rutas de ejecucin que puede tener. Como ejemplo modificaremos el programa de las operaciones aritmticas para que haga uso del switch. La variable de comparacin ser la variable opcin, ya que el valor de sta ser comparado para cada operacin.
Switch
Inicio
Mostrar men
Pedir opcin
Pedir a
Pedir b
Opcin 1 Resultado = a+b 2 Resultado = a-b 3 B!= 0 S Resultado = a/b Mostrar "Divisor no vlido" NO 4 Resultado = ab Default Mostrar "Opcin no vlida"
Mostrar resultado
Fin
Figura 14. En este caso las diferentes rutas de ejecucin del switch salen de los lados y las esquinas del rombo.
La toma de decisiones
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias float a = 0.0f; float b = 0.0f; float resultado = 0.0f; string valor = ; int opcion = 0; // Mostramos el men Console.WriteLine(1- Suma); Console.WriteLine(2- Resta); Console.WriteLine(3- Divisin); Console.WriteLine(4- Multiplicacin); Console.Write(Que operacin deseas hacer: ); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor); // Pedimos el primer nmero Console.Write(Dame el primer numero:); valor = Console.ReadLine();
DIAGRAMAS DE FLUJO
Es posible encontrar diferentes programas de computadora que nos permitan crear diagramas de flujo. Estos programas nos pueden ayudar a hacer nuestros programas ms rpido. Un programa que hace esto es Visio de Microsoft, pero tambin se pueden encontrar programas gratuitos en varios sitios web en Internet como www.download.com.
www.redusers.com
107
a = Convert.ToSingle(valor); // Pedimos el segundo nmero Console.Write(Dame el segundo numero:); valor = Console.ReadLine(); b = Convert.ToSingle(valor); switch (opcion) { // Verificamos para suma case 1: resultado = a + b; break; // Verificamos para resta case 2: resultado = a - b; break; // Verificamos para divisin case 3: if (b != 0) // este if esta anidado resultado = a / b; else // Este else pertenece al segundo if Console.WriteLine(Divisor no valido); break; // Verificamos para la multiplicacin case 4: resultado = a * b; break; // Si no se cumple ninguno de los casos anteriores default: Console.WriteLine(Opcin no valida); break; }
108
www.redusers.com
La toma de decisiones
Con esto hemos visto las estructuras selectivas bsicas en C# y cmo podemos usarlas.
RESUMEN
Las estructuras selectivas nos sirven para llevar a cabo la toma de decisiones. Tenemos varias de estas estructuras: if, if-else y switch. Podemos hacer uso de las expresiones relacionales y lgicas en if. Esto nos permite indicar de forma precisa la condicin que se debe cumplir para que se ejecute determinado cdigo. El uso de else nos permite tener cdigo que se puede ejecutar cuando la condicin no se cumple. Para comparar una variable contra diferentes valores y ejecutar un cdigo en particular cuando su contenido es igual a un determinado valor hacemos uso del switch. Es importante no olvidar el uso del break al finalizar el cdigo de cada caso.
www.redusers.com
109
EJERCICIOS PRCTICOS
1 Hacer un programa que le pida al usuario un nmero y la computadora responda si es par o impar. 2 Hacer un programa que transforme de grados a radianes o de radianes a grados dependiendo de lo que necesite el usuario.
110
www.redusers.com
C#
Captulo
Creacin de ciclos
En la vida real a veces repetimos la misma actividad muchas veces. Tambin en los programas de computadora veremos que es necesario repetir algo un nmero de veces. Para esto haremos uso de los ciclos, que harn que nuestro cdigo sea ms sencillo al mismo tiempo que podemos repetir una actividad cuantas veces sea necesario.
El ciclo for El valor de inicio El lmite de conteo del ciclo Control del incremento Ejemplos con el ciclo for El ciclo do while El ciclo while Resumen Actividades 112 117 119 121 128 134 141 145 146
4. CREACIN DE CICLOS
EL CICLO FOR
El primer ciclo que aprenderemos en este captulo se llama ciclo for, pero para poder entenderlo mejor necesitamos ver un problema donde sea necesario utilizarlo. Imaginemos que tenemos que crear un programa para una escuela, y este programa debe sacar el promedio de las calificaciones para tres alumnos. Si recordamos, el promedio se calcula al sumar todas las cantidades y el resultado de la suma se divide por la cantidad de cantidades que hemos sumado. El programa es sencillo, debido a que en el saln de clases solamente hay tres alumnos. El diagrama para resolver este programa es el que se muestra en la siguiente figura:
Inicio
Inicializacin
Condicin S Cdigo NO
Incremento
Fin
112
www.redusers.com
El ciclo for
using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias float cal1 = 0.0f, cal2 = 0.0f, cal3 = 0.0f; float promedio = 0.0f; string valor = ; // Pedimos los datos Console.WriteLine(Dame la primera calificacin:); valor = Console.ReadLine(); cal1 = Convert.ToSingle(valor); Console.WriteLine(Dame la segunda calificacin:); valor = Console.ReadLine(); cal2 = Convert.ToSingle(valor); Console.WriteLine(Dame la tercera calificacin:); valor = Console.ReadLine(); cal3 = Convert.ToSingle(valor); // Calculamos el promedio promedio = (cal1 + cal2 + cal3) / 3;
www.redusers.com
113
4. CREACIN DE CICLOS
Vemos que el programa es muy sencillo. Pedimos tres valores y calculamos el promedio. Al final simplemente desplegamos el resultado. No hay ningn problema con el programa, de hecho es correcto. Sin embargo, nuestro programa tiene un defecto: es poco flexible. Ahora imaginemos que la escuela desea el promedio para un grupo con cinco alumnos. Al parecer esto no es difcil, simplemente podramos agregar dos peticiones de variables ms y modificar la frmula. Esto no parece problemtico. Pero qu sucede si el grupo es de quince alumnos? Esta solucin de agregar ms peticiones, aunque es viable, no es cmoda. Si nos piden el promedio para toda la escuela con 2500 alumnos? Entonces es evidente que no podemos seguir con este tipo de solucin. Sin embargo, de este problema podemos observar algo. Todas las peticiones de calificaciones se hacen de la misma forma y pedir las calificaciones es algo que tenemos que repetir un nmero de veces. Cuando tenemos cdigo que se debe repetir un nmero de veces podemos utilizar el ciclo for. ste nos permite repetir la ejecucin de un cdigo un nmero determinado de veces. Antes de resolver nuestro problema con el ciclo for, lo primero que tenemos que hacer es aprender a utilizar el ciclo. La sentencia del ciclo se inicia con la palabra clave for seguida de parntesis. Adentro de los parntesis colocaremos expresiones que sirven para controlar el ciclo. El ciclo for tiene cuatro partes principales:
for( inicializacion; condicion; incremento) cdigo
El ciclo for necesitar una o varias variables de control, aunque en la mayora de los casos usaremos nicamente una variable. Veamos las diferentes partes del ciclo for. En primer lugar encontramos la inicializacin. En esta seccin le damos a la variable de control su valor inicial. El valor inicial se lleva a cabo por medio de una asignacin normal, tal y como las que hemos trabajado. La segunda seccin lleva una condicin en forma de una expresin relacional. sta nos sirve para controlar cundo termina el ciclo y generalmente aqu indicamos la cantidad de vueltas que da el ciclo. Luego tenemos el cdigo. En esta seccin colocamos la parte del cdigo que deseamos que se repita. Esta seccin puede ser una sentencia o un bloque de cdigo. Por
114 www.redusers.com
El ciclo for
ltimo, se ejecuta la seccin del incremento. Aqu indicamos cmo se modificar el valor de la variable de control para cada vuelta del ciclo. Cuando se ejecuta el ciclo for, lo primero que se lleva a cabo es la inicializacin y luego la condicin. Si la condicin es verdadera, entonces se pasa al cdigo y despus al incremento. Seguido del incremento vamos nuevamente a la condicin y se repite el proceso. Si la condicin no se cumple, entonces decimos que el ciclo finaliza, se salta al cdigo y contina la ejecucin del programa con lo que sea que encontremos despus del ciclo. Esto lo podemos apreciar mejor en el siguiente diagrama de flujo.
Inicio
Inicializacin
Condicin S Cdigo NO
Incremento
Fin
Figura 2. Este diagrama de flujo nos muestra los pasos de la ejecucin del ciclo for.
El poder comprender el ciclo for requiere de mucha experimentacin, por lo que haremos varias pruebas para conocer sus caractersticas principales. Empecemos con un programa sencillo. Usaremos el ciclo para mostrar un mensaje, que nicamente imprimir el valor de la variable de control del ciclo. Para saber cul es el trabajo que realiza el ciclo, colocaremos un mensaje antes y despus del ciclo.
www.redusers.com 115
4. CREACIN DE CICLOS
Para iniciar con facilidad, queremos que el ciclo se lleve a cabo diez veces. Primero veamos el programa y luego analicemos cada una de las partes del ciclo. Nuestro programa queda de la siguiente forma:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias int n = 0; // variable de control Console.WriteLine(- Antes del ciclo -); for (n = 1; n <= 10; n = n + 1) Console.WriteLine({0}, n); Console.WriteLine(- Despus del ciclo -); } } }
Antes de ejecutar el programa, veamos cmo est construido. En primer lugar declaramos nuestra variable de control. sta se llama n. El programa imprimir los nmeros del 1 al 10 y n cambiar su valor segn se repita el ciclo. Adentro del ciclo for encontramos inmediatamente que a n se le asigna el valor 1. Esto quiere decir que nuestro conteo empezar con el nmero 1. Si deseramos iniciar en otro valor, en esta parte es dnde lo asignaramos. Luego tenemos la condicin. La condicin limita hasta donde contaremos con n. En este caso es hasta 10. Mientras n tenga un valor menor o igual a 10 el mensaje se muestra. Como en este caso 1 <= 10 se cumple, ya que n vale 1, entonces el mensaje se escribe. El mensaje es muy sencillo ya que simplemente muestra el valor contenido en la variable n. Despus de esto, vamos al incremento. El incremento aumenta el valor
116 www.redusers.com
El ciclo for
de n en uno. Despus del primer incremento n valdr 2. Esto se repite y se incrementa en 1 el valor de n cada vez que se repite el ciclo. En el ltimo incremento, n tendr el valor de 11 y en este caso la condicin ya no se cumplir y se termina con el ciclo. Veamos la ejecucin del programa y observaremos cmo n cambia de valor y efectivamente el ciclo se lleva a cabo solamente 10 veces.
Figura 3. Aqu podemos observar cmo el ciclo se repiti y el valor de n fue modificado en cada vuelta.
El valor de inicio
Ahora ya podemos empezar a experimentar con el ciclo. Lo primero que haremos ser colocar el valor de inicio del ciclo y ver cmo se modifica la ejecucin del
www.redusers.com
117
4. CREACIN DE CICLOS
programa. Esto es til ya que no siempre es necesario empezar a contar a partir de 1, a veces necesitamos empezar a contar a partir de otros nmeros. Supongamos que ahora tenemos que contar del 3 al 10. Para lograr esto, simplemente modificamos el valor de inicio en la seccin de inicializacin del ciclo:
for (n = 3; n <= 10; n = n + 1) Console.WriteLine({0}, n);
Ejecutemos el programa.
Figura 4. ste es el resultado. Efectivamente, la variable de control empieza con 3. Desde luego, el nmero de repeticiones es menor.
Es posible que la variable de control tenga un valor negativo en la inicializacin. Esto es til cuando necesitamos contar desde un nmero negativo. Modifiquemos el cdigo del ciclo for de la siguiente manera:
for (n = -10 n <= 10; n = n + 1) Console.WriteLine({0}, n);
118
www.redusers.com
El ciclo for
Figura 5. Podemos ver que el recorrido inicia en -10. No hay que pasar por alto que la variable de control tambin pasa por el valor de cero.
En este ejemplo pudimos ver que el lmite de conteo est siendo controlado en la condicin y que no hay una nica forma de escribirla. Podemos ver que la siguiente condicin n <= 10 tambin podra ser escrita como n < 11 sin que se afecte en lo ms mnimo la ejecucin del ciclo.
for (n = 1; n <11; n = n + 1) Console.WriteLine({0}, n);
www.redusers.com
119
4. CREACIN DE CICLOS
Figura 6. Podemos observar que aunque la condicin es diferente, an se cumple lo que deseamos.
Esto hay que tenerlo en cuenta para evitar confusiones en el futuro, en especial cuando veamos cdigo de otras personas que utilicen un estilo diferente al nuestro. Ahora modifiquemos el ciclo para que cuente del 1 al 15, en este caso usaremos el operador < en lugar de <=.
for (n = 1; n < 16; n = n + 1) Console.WriteLine({0}, n);
120
www.redusers.com
El ciclo for
Como vemos, ahora hemos colocado n = n + 2. Con esto indicamos que se sumar 2 al valor de n con cada vuelta del ciclo. Esto es ms fcil de entender si vemos la ejecucin del programa y vemos el desplegado de los valores de n.
www.redusers.com 121
4. CREACIN DE CICLOS
Figura 8. Podemos observar que efectivamente el valor de n se incrementa de dos en dos por cada vuelta del ciclo.
Los ciclos que hemos utilizado siempre han contado de manera progresiva, es decir del menor valor al valor ms alto, pero tambin es posible hacer un ciclo regresivo. Por ejemplo, podramos hacer que el ciclo cuente del 10 al 1. Para esto necesitamos modificar no solamente el incremento sino que tambin es necesario colocar las expresiones correctas en la inicializacin y la condicin. Veamos cmo lograr esto con la siguiente sentencia:
for (n = 10; n>=1; n = n - 1)
122
www.redusers.com
El ciclo for
Console.WriteLine({0}, n);
El contador y el acumulador
Ahora aprenderemos dos conceptos nuevos. Existen dos categoras de variables dependiendo de cmo guardan la informacin, en primer lugar tenemos el contador. El contador es una variable que ser incrementada o disminuir su valor de uno en uno. En la mayora de los ejemplos anteriores n ha funcionado como contador. Por su parte, el acumulador es una variable que puede incrementar o disminuir su valor en cualquier nmero. An no hemos hecho uso de un acumulador, pero lo veremos cuando debamos resolver el problema de los promedios de los alumnos. Por el momento, veamos un pequeo ejemplo de estas dos clasificaciones de variables explicadas hasta aqu:
using System; using System.Collections.Generic; using System.Text;
www.redusers.com
123
4. CREACIN DE CICLOS
namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias int n = 0; // variable de control int contador = 0, acumulador = 0; Console.WriteLine(- Antes del ciclo -); for (n = 10; n >= 1; n = n - 1) { contador = contador + 1; acumulador = acumulador + contador; Console.WriteLine({0}, {1}, contador, acumulador); } Console.WriteLine(- Despus del ciclo -); } } }
Hemos creado dos variables: contador y acumulador. La variable contador incrementa su valor de uno en uno. Por su parte, la variable acumulador incrementar el valor en base al nmero contenido en contador. A continuacin, para comprender mejor lo explicado, ejecutemos el programa y veamos el funcionamiento de las dos variables:
124
www.redusers.com
El ciclo for
Figura 10. Vemos cmo cambian los valores de las variables con cada vuelta del ciclo.
Incrementos y decrementos
Cuando trabajamos el C# con el ciclo for es muy comn que tengamos que incrementar o disminuir siempre de uno en uno. Para facilitarnos esto, tenemos operadores nuevos que son el operador de incremento y el operador de decremento.
OPERADOR Incremento Decremento SIGNO ++
Estos operadores pueden ser usados como sufijos o prefijos en la variable. En el caso de los sufijos lo escribimos como variable++ y para el prefijo como ++variable. El valor contenido en la variable en ambos casos se incrementar en uno. Lo que cambia es cmo se evala la expresin que contienen los operadores. Cuando tenemos el caso del sufijo, se evala la expresin con el valor actual de la variable y luego se incrementa a la variable. En el caso del prefijo, se incrementa primero el valor de la variable y posteriormente se evala la expresin. Quizs esto no quede muy claro en la primer explicacin, pero no debemos preocuparnos por ello. Para poder entender esto, veremos un ejemplo a continuacin:
www.redusers.com 125
4. CREACIN DE CICLOS
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { int numero = 5; Console.WriteLine(Valor inicial {0}, numero); // incrementamos numero++; Console.WriteLine(Despus del incremento {0}, numero); // Decrementamos numero; Console.WriteLine(Despus del decremento {0}, numero); // Incremento en la sentencia Console.WriteLine(Incremento en la sentencia {0}, numero++); Console.WriteLine(Valor despus de la sentencia {0}, numero); // Incremento en la sentencia como prefijo Console.WriteLine(Incremento en la sentencia {0}, ++numero); Console.WriteLine(Valor despus de la sentencia {0}, numero); } } }
126
www.redusers.com
El ciclo for
Podemos ejecutar el cdigo escrito y ver qu es lo que ha ocurrido, y la razn por la que obtenemos esos valores desplegados.
Figura 11. Aqu vemos los valores obtenidos por los operadores y la diferencia en usarlos como sufijos o prefijos.
Empezamos con una variable llamada numero a la que le asignamos el valor inicial de cinco. Desplegamos su valor en la pantalla. Luego usamos el operador e incrementamos el valor de la variable. En este caso vale 6, ya que el incremento es en uno. Esto lo comprobamos al imprimir el valor de la variable. Despus llevamos a cabo el decremento. En este caso, numero guarda el valor de 5, ya que lo hemos decrementado en uno. La impresin del mensaje nos muestra que estamos en lo correcto. Ahora que ya hemos visto cmo funciona, podemos tratar de colocar el operador adentro de una sentencia. La sentencia ser el mismo mensaje que deseamos mostrar con el fin de observar cmo se evala y las diferencias entre el uso como sufijo y prefijo. No olvidemos que el ltimo valor en numero es 5. Empezamos por colocar el incremento adentro de la sentencia y lo usamos como sufijo. Esto incrementa el valor a 6, pero si vemos la ejecucin del programa, el valor que aparece es 5. Por qu? La razn ya la conocemos: cuando se usa como sufijo, se evala la expresin con el valor actual y luego se incrementa. La siguiente impresin del valor de la variable nos muestra cmo efectivamente la variable s fue incrementada despus de la sentencia anterior. Ahora podemos experimentar con el sufijo. Nuestro valor actual es de 6 e ingresamos la
www.redusers.com 127
4. CREACIN DE CICLOS
sentencia. En este caso, primero se incrementa el valor y tenemos 7 en la variable nmero y luego la imprimimos. Por eso, en este caso obtenemos 7 en la pantalla. Con esto ya hemos visto el comportamiento de estos operadores y podemos integrarlos en nuestro ciclo for. En el caso de incremento:
for (n = 1; n <16; n++) Console.WriteLine({0}, n);
Existen otros operadores que tambin podemos utilizar cuando deseamos calcular un valor con la variable y guardar el mismo valor en la variable.
OPERADOR += -= *= /= EJEMPLO numero+=5 numero-=5 numero*=5 numero/=5 EQUIVALE A numero=numero+5 numero=numero-5 numero=numero*5 numero=numero/5
Es bueno conocer estos operadores ya que los veremos y deberemos utilizar frecuentemente en muchos programas de cmputo. Por ejemplo, para hacer el incremento de cinco en cinco en un ciclo for, realizamos lo siguiente:
for (n = 1; n <16; n+=5) Console.WriteLine({0}, n);
El ciclo for
alumnos y ste se presenta en la pantalla. Veamos el diagrama de flujo de nuestro algoritmo para resolver este problema.
Inicio
Pedimos cantidad
N 1
Suma=+calif
NO
N++
Promedio= Suma/calif
Mostrar promedio
Fin
Figura 12. Podemos observar fcilmente el ciclo for y lo que se realiza adentro de l.
www.redusers.com 129
4. CREACIN DE CICLOS
130
www.redusers.com
El ciclo for
Figura 13. Vemos cmo la peticin de la calificacin se repite el nmero de veces indicado.
Un punto importante sobre este programa, en comparacin al primer intento que hicimos al inicio del captulo, es que puede funcionar con cualquier cantidad de alumnos. No importa si son 5, 10 5000, el programa llevar a cabo su cometido. Vemos cmo el uso del ciclo no solamente nos da flexibilidad, sino que tambin evita que tengamos que repetir mucho cdigo. Veamos otro ejemplo. Podemos utilizar el ciclo for en cualquier problema que necesite algo que se repita: una operacin, un conteo, algn proceso. Pero tambin el nmero de repeticiones debe ser conocido, ya sea por medio de un valor colocado explcitamente o un valor colocado adentro de una variable.
www.redusers.com 131
4. CREACIN DE CICLOS
Ahora tenemos que calcular el factorial de un nmero. Por ejemplo, el factorial de 5 es 5*4*3*2*1 que da 120. De igual forma, debemos calcular el valor factorial de cualquier nmero dado por el usuario. Si observamos el problema y cmo se resuelve, podemos apreciar que hay un ciclo y este ciclo es con conteo regresivo. Podemos resolver fcilmente con un ciclo for que lleve a cabo la multiplicacin con la variable de control como producto.
Inicio
Pedimos nmero
N=nmero
N>=1 S Factorial*=nmero NO
N--
Mostrar factorial
Fin
Figura 14. ste es el diagrama de flujo del algoritmo para calcular el factorial de un nmero.
132 www.redusers.com
El ciclo for
Cuando ejecutamos el programa, nos encontramos con que podemos llevar a cabo el clculo factorial sin problema alguno.
www.redusers.com 133
4. CREACIN DE CICLOS
El ciclo do while
Hemos visto que el ciclo for es muy til para repetir algo cuando sabemos el nmero de repeticiones previamente. Sin embargo, algunas veces no es posible saber el nmero de repeticiones que tendremos. Pensemos que una carpintera nos ha contratado para hacer un programa que transforme de pies y pulgadas a centmetros, ya que ellos lo usan para calcular el tamao de las tablas. El programa es muy sencillo, pero no podemos dejarlo as ya que sera muy incmodo para ellos ejecutar el programa cada vez que necesitan hacer un corte. Pensamos que esto se puede resolver con un ciclo for. De cuntas vueltas el ciclo? Si colocamos 10 vueltas podemos pensar que es suficiente. Pero hay das que necesitan 15 conversiones y es necesario ejecutar el programa dos veces. Y los das que slo necesitan 5 conversiones tienen que escribir 5 ms tan slo para finalizar el programa. Podemos deducir del problema que efectivamente necesitamos un ciclo. Sin embargo, no sabemos el nmero de repeticiones previamente, por lo que el ciclo for no es adecuado. Necesitamos un ciclo que pueda ser controlado por una condicin, y la evaluacin de esta condicin depender del estado del programa en un momento dado. El ciclo do while nos permite hacer esto. Permite que cierto cdigo se repita mientras una condicin se evale como verdadera. El valor de la evaluacin depender del estatus del programa en un momento dado.
134 www.redusers.com
El ciclo for
Si observamos el diagrama de flujo de la figura 16, podemos ver el funcionamiento interno del ciclo do while de una manera simple y clara.
Cdigo
Condicin NO
Figura 16. ste es el diagrama del ciclo do while. Podemos observar su comportamiento interno.
Empecemos a recorrer el ciclo. En primer lugar encontramos el cdigo que hay que llevar a cabo. Este cdigo es definido adentro de un bloque de cdigo aunque sea solamente una sentencia. Generalmente, en el cdigo se modificar de alguna forma el valor de la variable o las variables que usamos para la expresin en la condicin. Esta modificacin de valor puede llevarse a cabo por medio de un clculo, proceso o incluso una peticin al usuario. Despus tenemos la condicin a evaluar. En la condicin colocamos una expresin lgica o relacional. Si al evaluarse la condicin obtenemos el valor true, entonces se repite el cdigo. En caso de que la condicin del valor de false ya no se repite y se contina con el programa. Hay que tener en cuenta que a veces sucede que la condicin se evala como falsa desde la primera vez. En este caso, solamente se habr ejecutado el cdigo una vez. Veamos un ejemplo. Crearemos el programa para la carpintera y usaremos el ciclo do while para que el programa se repita el nmero de veces necesarias, aun sin saber cuntas veces son. Para lograr esto tenemos que pensar bien en nuestra condicin y cul es el estado del programa que evaluaremos en ella.
www.redusers.com 135
4. CREACIN DE CICLOS
La forma ms sencilla de hacerlo es preguntarle al usuario si desea hacer otra conversin. Si lo afirma, se repite el cdigo para convertir. En caso de que el usuario no lo desee, el programa finaliza. De esta forma, es controlada la repeticin del ciclo pudindola repetir, aun sin saber cuntas veces hay que hacerlo. Nuestro programa tendr el siguiente diagrama de flujo.
Inicio
Pedimos pulgadas
Mostramos centmetros
Mostramos centmetros
Respuesta==S NO Fin
El ciclo for
www.redusers.com
137
4. CREACIN DE CICLOS
Console.WriteLine(Deseas hacer otra conversin (si/no)?); respuesta = Console.ReadLine(); } while (respuesta == si); } } }
Ejecutemos el programa.
Figura 18. En la ejecucin podemos verificar que tenemos un ciclo, pero puede terminar cuando lo deseemos.
Podemos observar que hemos colocado adentro del ciclo la parte de conversin de pies y pulgadas a centmetros. Despus de mostrar el resultado le preguntamos al usuario si desea realizar otra conversin. En caso afirmativo, repetimos el ciclo. Si el usuario no desea hacer otra conversin, el ciclo finaliza. Esto nos permite que a veces se repita cinco veces, cuando sea necesario diez, y as dependiendo de las necesidades del usuario. Hemos resuelto el problema.
138 www.redusers.com
El ciclo for
El ciclo do while nos da flexibilidad extra, pero siempre es necesario usar el tipo de ciclo adecuado al problema que tenemos. Veamos otro ejemplo donde podemos utilizar este ciclo. En uno de los programas anteriores le preguntbamos al usuario qu operacin deseaba realizar y luego los operandos. El programa tal y como est solamente se ejecuta una vez, pero si usamos el ciclo do while y colocamos una nueva opcin en el men, entonces el usuario puede realizar las operaciones que sean necesarias o solamente una como se usaba anteriormente. Este tipo de comportamiento es muy til y fcil de implementar con el ciclo do while. Si modificamos el programa quedar de la siguiente manera:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias float a = 0.0f; float b = 0.0f; float resultado = 0.0f; string valor = ; int opcion = 0; // Tenemos el ciclo do { // Mostramos el men Console.WriteLine(1Console.WriteLine(2Console.WriteLine(3Console.WriteLine(4Console.WriteLine(5-
www.redusers.com
139
4. CREACIN DE CICLOS
Console.Write(Que operacin deseas hacer: ); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor); if (opcion != 5) { // Pedimos el primer nmero Console.Write(Dame el primer nmero:); valor = Console.ReadLine(); a = Convert.ToSingle(valor); // Pedimos el segundo nmero Console.Write(Dame el segundo nmero:); valor = Console.ReadLine(); b = Convert.ToSingle(valor); switch (opcion) { // Verificamos para suma case 1: resultado = a + b; break; // Verificamos para resta case 2: resultado = a - b; break; // Verificamos para divisin case 3: if (b != 0) // este if esta anidado resultado = a / b; else // Este else pertenece al segundo if Console.WriteLine(Divisor no vlido); break; // Verificamos para la multiplicacin case 4: resultado = a * b; break;
140
www.redusers.com
El ciclo for
// Si no se cumple ninguno de los casos anteriores default: Console.WriteLine(Opcin no vlida); break; } // Mostramos el resultado Console.WriteLine(El resultado es: {0}, resultado); } } while (opcion != 5); } } }
El ciclo while
Habiendo comprendido el ciclo Do While, estamos en condiciones de ver otro tipo de ciclo. Este ciclo se conoce como while y en cierta forma se asemeja al anterior, pero tiene sus propias caractersticas que debemos conocer para utilizarlo correctamente. El ciclo while tambin puede ser utilizado cuando tenemos algo que se debe repetir pero no conocemos el nmero de repeticiones previamente. La repeticin del ciclo tiene que ver con el cumplimiento de una condicin. A diferencia del ciclo do while, este ciclo puede no ejecutarse ni siquiera una vez. Su estructura es la siguiente:
while(condicion) { Cdigo }
www.redusers.com
141
4. CREACIN DE CICLOS
Condicin S NO Cdigo
Figura 19. Este ciclo inicia con una condicin y esto lo debemos de tener en cuenta en nuestros algoritmos.
Si observamos el diagrama de flujo lo primero que encontramos es una condicin. Adentro de esta condicin colocaremos una expresin lgica o relacional. Si la condicin se evala como verdadera, entonces se procede a ejecutar el cdigo. Despus del cdigo se regresa a la condicin. Si la condicin no se cumple, entonces no se ejecuta el cdigo y se contina con el resto del programa. El tener la condicin al inicio del ciclo nos lleva a un punto importante. Si la condicin no se cumple desde el inicio, entonces el ciclo nunca se lleva a cabo. Si nuestro algoritmo est bien diseado, esto es deseable. Ahora podemos hacer un ejemplo de programa que utilice el ciclo while. En este ejemplo utilizaremos la caracterstica del ciclo que puede repetirse o no repetirse ni siquiera una vez. Imaginemos que tenemos que hacer un programa de control para enfriar una caldera. La caldera debe ser enfriada a 20 grados centgrados. El ciclo while ser usado para reducir la temperatura de uno en uno para cada vuelta del ciclo hasta que lleguemos a 20 grados centgrados. La ventaja que nos da este ciclo
142
www.redusers.com
El ciclo for
es que si la temperatura es menor a 20 grados, ni siquiera se entra al ciclo y no se lleva a cabo ningn enfriamiento. En este caso, aprovechamos las propiedades del ciclo. Veamos el cdigo de este programa:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacin static void Main(string[] args) { // Variables necesarias int temperatura = 0; string valor = ; // Pedimos la temperatura Console.WriteLine(Dame la temperatura actual:); valor = Console.ReadLine(); temperatura = Convert.ToInt32(valor); // El ciclo reduce la temperatura while (temperatura > 20) { // Disminuimos la temperatura temperatura;
CICLOS ANIDADOS
Al igual que con los if, es posible tener ciclos anidados. Como adentro de los ciclos podemos colocar cualquier cdigo vlido, entonces tambin podemos colocar otro ciclo. Cuando un ciclo se encuentra adentro de otro, decimos que estn anidados. Hay que tener mucho cuidado con las variables de control y las condiciones para evitar problemas de lgica.
www.redusers.com
143
4. CREACIN DE CICLOS
Console.WriteLine(Temperatura->{0}, temperatura); } // Mostramos la temperatura final Console.WriteLine(La temperatura final es {0}, temperatura); } } }
Para comprobar que efectivamente el ciclo acta como hemos dicho, debemos correr el programa dos veces. La primera vez colocaremos la temperatura en valor mayor a 20C. Esto debe hacer que el ciclo se lleve a cabo. La segunda vez colocaremos un valor menor que 20. En este caso, el programa no deber entrar al ciclo. Veamos el resultado de la primera ejecucin:
Figura 20. Podemos observar que se ha entrado al ciclo y que se lleva a cabo mientras la temperatura es mayor a 20.
144 www.redusers.com
El ciclo for
Con esto hemos visto los tres ciclos principales disponibles en C# y de qu forma podemos utilizarlos dentro de nuestros desarrollos.
RESUMEN
Los ciclos nos permiten repetir la ejecucin de cierto cdigo. El ciclo for es usado para repetir algo un nmero determinado de veces. Este ciclo necesita de una variable de control con valor inicial, una condicin y un incremento. El ciclo do while nos permite repetir cierto cdigo un nmero de veces desconocido y se ejecuta al menos una vez. El nmero de veces depende de una condicin. El ciclo while tambin nos permite repetir el cdigo un nmero desconocido de veces, pero en este caso el ciclo puede o no puede ejecutarse dependiendo de su condicin.
www.redusers.com
145
EJERCICIOS PRCTICOS
1 Hacer un programa que muestre la tabla de multiplicar del 1 al 10 de cualquier nmero. 2 Hacer un programa que calcule el resultado de un nmero elevado a cualquier potencia.
146
www.redusers.com
C#
Captulo
Funciones y mtodos
Las funciones y los mtodos son elementos muy importantes de programacin. En C# estaremos utilizndolos frecuentemente, en especial cuando avancemos hacia la programacin orientada a objetos. Las funciones nos dan muchas ventajas y nos permiten desarrollar de forma ms rpida y ms ordenada nuestras aplicaciones.
Las funciones Funciones que ejecutan cdigo Funciones que regresan un valor Funciones que reciben valores Funciones que reciben parmetros y regresan un valor Optimizar con funciones Paso por copia y paso por referencia Uso de parmetros de default Resumen Actividades 148 150 156 159 163 171 178 183 185 186
5. FUNCIONES Y MTODOS
LAS FUNCIONES
Empecemos a conocer las funciones. Veamos un ejemplo de un problema y luego la forma cmo la utilizacin de la funcin nos puede ayudar. La funcin es un elemento del programa que contiene cdigo y se puede ejecutar, es decir, lleva a cabo una operacin. La funcin puede llamarse o invocarse cuando sea necesario y entonces el cdigo que se encuentra en su interior se va a ejecutar. Una vez que la funcin termina de ejecutarse el programa contina en la sentencia siguiente de donde fue llamada.
Main() Funcin() Sentencia 1 Sentencia 2 ... Sentencia n
Figura 1. Podemos observar cmo la ejecucin del programa se dirige a la funcin y luego regresa a la sentencia siguiente de donde fue invocada.
Las funciones, para que sean tiles, deben estar especializadas. Es decir que cada funcin debe hacer solamente una cosa y hacerla bien. Nosotros ya hemos utilizado una funcin, es la funcin Main() y podemos crear ms funciones conforme las necesitemos. Dentro de la programacin orientada a objetos las clases tienen cdigo y este cdigo se encuentra adentro de funciones llamadas mtodos. Por ejemplo, cuando hemos convertido de cadena a un entero, hacemos uso de una funcin llamada ToIn32() que se encuentra adentro de la clase Convert. Las funciones constan de cinco partes:
modificador tipo Nombre(parmetros) { cdigo }
Veremos ahora las cinco partes, pero conforme estudiemos a las funciones sabremos cmo son utilizadas. Las funciones pueden regresar informacin y esta informacin
148 www.redusers.com
Las funciones
puede ser cadena, entero, flotante o cualquier otro tipo. En la seccin de tipo tenemos que indicar precisamente la clase de informacin que regresa. Si la funcin no regresa ningn valor entonces tenemos que indicar a su tipo como void. Todas las funciones deben identificarse y lo hacemos por medio de su nombre. Las funciones que coloquemos adentro de las clases deben de tener un nombre nico. El nombre tambin es utilizado para invocar o ejecutar a la funcin. Las funciones pueden necesitar de datos o informacin para poder trabajar. Nosotros le damos esta informacin por medio de sus parmetros. Los parmetros no son otra cosa que una lista de variables que reciben estos datos. Si la funcin no necesita usar a los parmetros, entonces simplemente podemos dejar los parntesis vacos. Nunca debemos olvidar colocar los parntesis aunque no haya parmetros. El cdigo de la funcin se sita adentro de un bloque de cdigo. En esta seccin podemos colocar cualquier cdigo vlido de C#, es decir, declaracin de variables, ciclos, estructuras selectivas e incluso invocaciones a funciones. Las funciones al ser declaradas pueden llevar un modificador antes del tipo. Los modificadores cambian la forma como trabaja la funcin. Nosotros estaremos utilizando un modificador conocido como static. Este modificador nos permite usar a la funcin sin tener que declarar un objeto de la clase a la que pertenece. Tenemos cuatro tipos bsicos de funciones: las que solo ejecutan cdigo, las que reciben parmetros, las que regresan valores y las que reciben parmetros y reciben valores. Durante este captulo iremos conocindolas. Ahora que ya conocemos los elementos bsicos de las funciones, podemos ver un ejemplo de donde su uso sera adecuado. Supongamos que tenemos un programa en el cual en diferentes secciones tenemos que escribir el mismo cdigo, pero debido a su lgica no podemos usar un ciclo, ya que est en diferentes partes del programa. En este caso nuestra nica solucin hasta el momento sera simplemente escribir nuevamente el cdigo. Otra forma de resolverlo y que nos evitara tener cdigo repetido es usar la funcin. El cdigo que se va a utilizar repetidamente se coloca adentro de la funcin, y cada vez que necesitemos usarlo, simplemente se invoca a la funcin. En nuestro ejemplo del carpintero, el cual analizamos en el captulo anterior, nos
EL NOMBRE DE LA FUNCIN
Es importante seleccionar correctamente el nombre de la funcin. El nombre debe hacer referencia al tipo de trabajo que lleva a cabo la funcin; en muchos casos podemos hacer uso de verbos. El nombre de la variable puede llevar nmeros, pero debe empezar con una letra.
www.redusers.com
149
5. FUNCIONES Y MTODOS
encargamos de realizar conversiones de pies y pulgadas a centmetros. La conversin se haca con una frmula sencilla pero un poco larga. Si ahora nuestro carpintero necesita un programa para transformar las medidas de una mesa completa a centmetros, entonces tendramos que usar la frmula adecuada en varios lugares. Para no copiar el mismo cdigo varias veces, lo ms conveniente sera colocar la frmula en una funcin y simplemente invocarla donde fuera necesario. Empecemos a conocer cmo programar e invocar a las funciones.
150
www.redusers.com
Las funciones
Inicio
Mostrar men
Pedir opcin
Suma
Resta
Multiplicacin
Divisin
Figura 2. Aqu podemos ver el diagrama de flujo y encontrar los lugares donde se invocan a las funciones.
Vemos que nuestro diagrama es muy sencillo y tambin podemos localizar inmediatamente el lugar donde invocamos a las funciones. Cada una de las operaciones tendr su propia funcin. En este momento no programaremos todo, iremos haciendo crecer el programa poco a poco. Empecemos por construir el programa, dejando la administracin de la lgica a Main(), tal y como aparece en el diagrama de flujo.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase
www.redusers.com
151
5. FUNCIONES Y MTODOS
{ class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { // Variables necesarias int opcion = 0; string valor = ;
// Mostramos el menu Console.WriteLine(1-Suma); Console.WriteLine(2-Resta); Console.WriteLine(3-Multiplicacion); Console.WriteLine(4-Division); // Pedimos la opcion Console.WriteLine(Cual es tu opcion:); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor);
// Checamos por la suma if (opcion == 1) { } // Checamos por la resta if (opcion == 2) { } // Checamos por la multiplicacion if (opcion == 3) { } // Checamos por la division
152
www.redusers.com
Las funciones
if (opcion == 4) { } } } }
Como vemos en nuestra funcin Main() tenemos la lgica principal del programa. Hemos dejado en este momento los bloques de cdigo de los if vacos para ir colocando el cdigo correspondiente segn vallamos avanzando. Empecemos a crear la funcin para la suma. Como esta funcin no va a recibir datos ni a regresar valores, todo se llevar a cabo en su interior. Ser responsable de pedir los operandos, realizar la suma y mostrar el resultado. Entonces colocamos la declaracin de la funcin. Esto lo hacemos despus de la funcin Main(), hay que recordar tener cuidado con los { }. Tambin les debemos crear su diagrama de flujo y resolverlas de la forma usual. El diagrama de flujo es el siguiente.
Inicio
Pedimos a
Pedimos b
R=a+b
Mostramos r
Fin
www.redusers.com
153
5. FUNCIONES Y MTODOS
{ // Variables necesarias float a=0; float b=0; float r=0; string numero=; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); a = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); b = Convert.ToSingle(numero); // Calculamos el resultado r = a + b; // Mostramos el resultado Console.WriteLine(El resultado es {0},r); }
Observamos que la funcin es static. Como la funcin no regresa ningn valor su tipo es void, el nombre de la funcin es Suma. Escogemos este nombre porque describe la actividad que lleva a cabo la funcin. Como no recibe ningn dato del programa principal no colocamos ningn parmetro y los parntesis estn vacos. En el cdigo tenemos todos los pasos para resolver la suma y ya los conocemos. Como podemos observar es posible declarar variables. Debemos saber que las variables que se declaran adentro de la funcin se conocen como variables locales y
NOMBRE EN LA INVOCACIN
Un error muy comn cuando se empieza a programar las funciones es equivocarse al escribir el nombre de la funcin de forma diferente durante la invocacin. Por ejemplo, si nuestra funcin se declara como Suma() cuando la invocamos no podemos usar suma(). La invocacin debe usar el nombre de la funcin exactamente como fue declarado.
154
www.redusers.com
Las funciones
solamente sern conocidas adentro de esa funcin, de esta forma solo podrn ser invocadas dentro de la funcin correspondiente. Con esto la funcin est lista, sin embargo, si ejecutamos el programa nada diferente sucede. Esto se debe a que no hemos invocado la funcin. Cuando invocamos a la funcin su cdigo se ejecuta. Para invocar a una funcin que solamente ejecuta cdigo simplemente colocamos su nombre seguido de () y punto y coma en el lugar donde queremos que se ejecute. En nuestro caso sera el bloque de cdigo del if para la suma, de la siguiente manera:
// Checamos por la suma if(opcion==1) { Suma(); }
Ahora si ejecutamos el programa y seleccionamos la opcin de suma, veremos que efectivamente se ejecuta el cdigo propio de la funcin.
5. FUNCIONES Y MTODOS
En cuanto la ejecucin del programa encuentra un return, la funcin es finalizada aun si no ha llegado a su fin. Al mismo tiempo que finaliza la funcin el valor colocado despus del return es regresado a quien hizo la invocacin. El valor puede ser colocado con una variable o explcitamente con un valor en particular. No hay que olvidar colocar el punto y coma al finalizar la sentencia. La finalizacin de la funcin se lleva a cabo aunque tengamos cdigo escrito despus del return. Como la funcin regresa un valor, del lado del invocador necesitamos tener alguien que pueda recibir el valor regresado. Generalmente usaremos una variable, pero en algunos casos puede ser una expresin que ser evaluada con el valor regresado por la funcin. Supongamos que nuestra funcin regresa un valor entero. Entonces podemos tener un cdigo como el siguiente.
int n; n=funcin();
De esta forma el valor regresado por la funcin queda guardado en la variable n y podemos hacer uso de l. El cdigo lo entendemos de la siguiente forma. Tenemos una variable entera n. Luego tenemos una asignacin para n. Si recordamos, la asignacin siempre se lleva a cabo de derecha a izquierda. Se evala la expresin y la funcin se ejecuta y calcula un valor, el cual es regresado por medio de return. Este valor se considera como la evaluacin de la expresin y es asignado a n. A partir de este momento podemos usar el valor segn lo necesitemos.
156 www.redusers.com
Las funciones
Ahora ya podemos empezar a usar este tipo de funciones en nuestra aplicacin. Para la operacin de la resta haremos uso de ella. El cdigo en la parte del Main() no ser tan sencillo, ya que no solamente necesitamos una invocacin, debemos de recibir un valor y hacer algo con l. De esta forma en el if para la resta, obtendremos el valor regresado por la funcin y luego lo presentaremos al usuario. La funcin Resta() tiene el siguiente diagrama de flujo.
Inicio
Pedimos a
Pedimos b
R=a-b
Regresamos R
Fin
Figura 5. Podemos observar la forma cmo se crea el diagrama de esta funcin, no hay que olvidar el retorno del valor.
www.redusers.com
157
5. FUNCIONES Y MTODOS
// Variables necesarias float a=0; float b=0; float r=0; string numero=; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); a = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); b = Convert.ToSingle(numero); // Calculamos el resultado r = a - b; // Retornamos el resultado return r; }
Podemos observar que la funcin Resta() es de tipo float y al final hemos colocado el return indicando la variable cuyo valor deseamos regresar, en nuestro caso r. Pero no solamente debemos adicionar la funcin, tambin es necesario colocar nuevo cdigo en el if que corresponde a la resta.
// Checamos por la resta if(opcion==2) {
158
www.redusers.com
Las funciones
// Variable para nuestro resultado float resultado=0; // Invocamos y obtenemos el resultado resultado=Resta(); // Mostramos el resultado Console.WriteLine(El resultado de la resta es {0},resultado); }
Figura 6. Vemos cmo el valor regresado por la funcin es desplegado en quien lo invoc, en nuestro caso Main().
5. FUNCIONES Y MTODOS
pueden recibir valores en el momento que son invocadas. De esta forma trabajarn con los valores pasados por el programa en lugar de pedirlos al usuario. Estos valores son conocidos como parmetros. Los parmetros pueden ser de cualquier tipo, ya sea de los tipos nativos de C# como entero, flotante, cadena o de tipos definidos por el programador como clases y estructuras. Los parmetros deben llevar su tipo y su nombre. El nombre nos permite acceder a los datos que contiene y de hecho van a trabajar como si fueran variables locales a la funcin. Adentro de la funcin los usamos como variables normales. Los parmetros se definen en la declaracin de la funcin. Adentro de los parntesis de la funcin los listamos. La forma de listarlos es colocando primero en tipo seguido del nombre. Si tenemos ms de un parmetro para la funcin, entonces debemos separarlos por medio de comas. La invocacin de la funcin es muy sencilla, simplemente debemos colocar el nombre de la funcin y, entre los parntesis, los datos que vamos a enviar como parmetros. Los datos pueden ser situados por medio de variables o un valor colocado explcitamente. Podemos hacer ahora la funcin que se encargar de la multiplicacin. Esta funcin recibir los operandos desde Main() por medio de los parmetros, realizar el clculo y lo mostrar al usuario. Como la funcin Main() manda la informacin, entonces ser responsabilidad de ella pedirlos a los usuarios. El diagrama de flujo de la funcin Multiplicacion() se muestre a continuacin.
Inicio
R=a*b
Mostramos R
Fin
Figura 7. La funcin Multiplicacion() es ms sencilla, pues no pide los datos directamente al usuario.
160 www.redusers.com
Las funciones
Como podemos observar la funcin va a tener dos parmetros. Los parmetros son de tipo flotante y se llaman a y b. No olvidemos que estn separados por una coma. Los parmetros a y b funcionarn como variables y su contenido sern los valores pasados en la invocacin. El otro lugar donde debemos de adicionar cdigo es la funcin Main(), en este caso el if para la multiplicacin.
// Checamos por la multiplicacion if(opcion==3) { // Variables necesarias float n1=0; float n2=0; string numero=;
www.redusers.com
161
5. FUNCIONES Y MTODOS
// Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); n1 = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); n2 = Convert.ToSingle(numero); // Invocamos a la funcion Multiplicacion(n1, n2); }
En el interior del if creamos dos variables flotantes y le pedimos al usuario los valores con los que vamos a trabajar. Estos valores quedan guardados adentro de las variables n1 y n2. Veamos ahora la invocacin de la funcin. Como la funcin fue definida para recibir parmetros entonces debemos de pasar datos en su invocacin. Los parmetros son colocados entre los parntesis. De la forma como lo tenemos el parmetro a recibir una copia del valor contenido en n1 y el parmetro b recibir una copia del valor contenido en n2. Ya con esto la funcin puede llevar a cabo su trabajo. Las variables usadas en la invocacin no necesitan llamarse igual que los parmetros declarados en la funcin. Si lo necesitramos la invocacin podra llevar un valor colocado explcitamente, por ejemplo:
// Invocamos a la funcion Multiplicacion(n1, 4.0f);
Cuando la funcin se invoca el parmetro a recibe una copia del valor contenido en n1 y el parmetro b recibe el valor de 4. Veamos cmo funciona.
162
www.redusers.com
Las funciones
Figura 8. Vemos que la funcin imprime el resultado correcto, lo que nos muestra que est recibiendo la informacin pasada en los parmetros.
5. FUNCIONES Y MTODOS
Adentro de la funcin tenemos dos return. Esto significa que vamos a regresar dos valores? En realidad no. nicamente podemos regresar un valor con este tipo de funciones. Lo que sucede es que cada uno de nuestros return se encuentra en una ruta de ejecucin diferente. Observemos que una se lleva a cabo cuando el if se cumple y el otro se ejecuta cuando el if no se cumple. Para la funcin, solamente uno de ellos podr ser ejecutado. Tambin podemos notar que uno de los return est regresando un valor colocado explcitamente, en este caso 0.0. Si colocamos valores de retorno explcitos, stos deben de ser del mismo tipo que el tipo de la funcin. ste es un concepto importante que nos da flexibilidad en nuestro cdigo. Podemos regresar bajo diferentes condiciones, siempre y cuando solamente tengamos un return por ruta de ejecucin. Si nuestra funcin debe regresar valores y tenemos varias rutas de ejecucin, por ejemplo, varios if o if anidados, entonces debemos de colocar un return en cada ruta. No es posible dejar una ruta sin la posibilidad de regresar un valor. Debemos tomar en cuenta estas caractersticas para evitar problemas de lgica dentro de nuestro programa. En el lado de la funcin Main() tambin debemos adicionar cdigo. El cdigo lo colocaremos en el bloque de cdigo que corresponde al if de la divisin.
164 www.redusers.com
Las funciones
// Checamos por la division if(opcion==4) { // Variables necesarias float n1=0.0f; float n2=0.0f; float resultado=0.0f; string numero=; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); n1 = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); n2 = Convert.ToSingle(numero); // Invocamos a la funcion resultado=Division(n1, n2); // Mostramos el resultado Console.WriteLine(El resultado es {0},resultado); }
Al igual que en casos anteriores, primero declaramos las variables necesarias y pedimos los valores. Luego invocamos a la funcin. En la invocacin pasamos como parmetros a nuestras variables n1 y n2. Se lleva a cabo la ejecucin de la funcin y recibimos de regreso un valor. Este valor es asignado a la variable resultado y luego utilizado por Main() al mostrar el resultado.
www.redusers.com
165
5. FUNCIONES Y MTODOS
Figura 10. La divisin se lleva a cabo y el valor de regreso es utilizado para mostrar el resultado.
166
www.redusers.com
Las funciones
// Mostramos el menu Console.WriteLine(1-Suma); Console.WriteLine(2-Resta); Console.WriteLine(3-Multiplicacion); Console.WriteLine(4-Division); // Pedimos la opcion Console.WriteLine(Cual es tu opcion:); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor);
// Checamos por la suma if (opcion == 1) { Suma(); } // Checamos por la resta if (opcion == 2) { // Variable para nuestro resultado float resultado = 0; // Invocamos y obtenemos el resultado resultado = Resta(); // Mostramos el resultado Console.WriteLine(El resultado de la resta es {0}, resultado); } // Checamos por la multiplicacion if (opcion == 3) { // Variables necesarias float n1 = 0; float n2 = 0;
www.redusers.com
167
5. FUNCIONES Y MTODOS
string numero = ; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); n1 = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); n2 = Convert.ToSingle(numero); // Invocamos a la funcion Multiplicacion(n1, n2); } // Checamos por la division if (opcion == 4) { // Variables necesarias float n1 = 0.0f; float n2 = 0.0f; float resultado = 0.0f; string numero = ; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); n1 = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); n2 = Convert.ToSingle(numero); // Invocamos a la funcion resultado = Division(n1, n2); // Mostramos el resultado Console.WriteLine(El resultado es {0}, resultado);
168
www.redusers.com
Las funciones
} } // Cierre de Main static void Suma() { // Variables necesarias float a = 0; float b = 0; float r = 0; string numero = ; // Pedimos los valores Console.WriteLine(Dame el primer numero); numero = Console.ReadLine(); a = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); b = Convert.ToSingle(numero); // Calculamos el resultado r = a + b; // Mostramos el resultado Console.WriteLine(El resultado es {0}, r); } static float Resta() { // Variables necesarias float a = 0; float b = 0; float r = 0; string numero = ; // Pedimos los valores Console.WriteLine(Dame el primer numero);
www.redusers.com
169
5. FUNCIONES Y MTODOS
numero = Console.ReadLine(); a = Convert.ToSingle(numero); Console.WriteLine(Dame el segundo numero); numero = Console.ReadLine(); b = Convert.ToSingle(numero); // Calculamos el resultado r = a - b; // Retornamos el resultado return r; } static void Multiplicacion(float a, float b) { // Variables necesarias float r = 0; // Calculamos el valor r = a * b; // Mostramos el resultado Console.WriteLine(El resultado es {0}, r); } static float Division(float a, float b) { // Variables necesarias float r = 0; // Verificamos por division entre cero if (b == 0) { Console.WriteLine(No es posible dividir entre cero); return 0.0f; }
170
www.redusers.com
Las funciones
else { r = a / b; return r; } } } }
5. FUNCIONES Y MTODOS
static float PideFlotante(string mensaje) { // Variables necesarias float numero=0.0f; string valor=; // Mostramos el mensaje Console.WriteLine(mensaje); // Obtenemos el valor valor = Console.ReadLine(); numero = Convert.ToSingle(valor); // Regresamos el dato return numero; }
Empecemos a ver cmo trabaja esta funcin que hemos creado. El nombre es PideFlotante ya que como sabemos el nombre de la funcin tiene que indicar una referencia al tipo de trabajo que realiza. Como nuestra funcin regresa un valor de tipo flotante, entonces colocamos como su tipo a float. La funcin tiene un nico parmetro que es el mensaje que deseamos mostrar al usuario en la peticin. Como es un mensaje de texto entonces el tipo que ms conviene usar es string. A nuestro parmetro le nombramos mensaje. En el interior de la funcin declaramos dos variables. Una es el nmero que vamos a recibir del usuario y la otra variable es la cadena que usamos con ReadLine(). Luego mostramos el mensaje de peticin. De la forma habitual obtenemos el valor dado por el usuario. Ya para finalizar simplemente regresamos el nmero. Para invocar a esta funcin, lo haremos de la siguiente manera:
n1 = PideFlotante(Dame el primer numero);
Ahora vemos que en lugar de utilizar las tres lneas de cdigo por peticin, simplemente hacemos una invocacin a nuestra funcin. Pero este no es el nico cambio que tenemos que hacer. En el programa original habamos colocado variables de trabajo para apoyarnos en la peticin del valor, pero ya no son necesarias. Si cambiamos el programa para hacer uso de nuestra nueva funcin quedar como en el ejemplo que vemos a continuacin:
172 www.redusers.com
Las funciones
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { // Variables necesarias int opcion = 0; string valor = ; // Mostramos el menu Console.WriteLine(1-Suma); Console.WriteLine(2-Resta); Console.WriteLine(3-Multiplicacion); Console.WriteLine(4-Division); // Pedimos la opcion Console.WriteLine(Cual es tu opcion:); valor = Console.ReadLine(); opcion = Convert.ToInt32(valor); // Checamos por la suma if (opcion == 1) { Suma(); } // Checamos por la resta if (opcion == 2) { // Variable para nuestro resultado float resultado = 0; // Invocamos y obtenemos el resultado
www.redusers.com
173
5. FUNCIONES Y MTODOS
resultado = Resta(); // Mostramos el resultado Console.WriteLine(El resultado de la resta es {0}, resultado); } // Checamos por la multiplicacion if (opcion == 3) { // Variables necesarias float n1 = 0; float n2 = 0; // Pedimos los valores n1 = PideFlotante(Dame el primer numero); n2 = PideFlotante(Dame el segundo numero); // Invocamos a la funcion Multiplicacion(n1, n2); } // Checamos por la division if (opcion == 4) { // Variables necesarias float n1 = 0.0f; float n2 = 0.0f; float resultado = 0.0f; // Pedimos los valores n1 = PideFlotante(Dame el primer numero); n2 = PideFlotante(Dame el segundo numero); // Invocamos a la funcion resultado = Division(n1, n2); // Mostramos el resultado Console.WriteLine(El resultado es {0},
174
www.redusers.com
Las funciones
resultado); } } // Cierre de Main static void Suma() { // Variables necesarias float a = 0; float b = 0; float r = 0; // Pedimos los valores a = PideFlotante(Dame el primer numero); b = PideFlotante(Dame el segundo numero); // Calculamos el resultado r = a + b; // Mostramos el resultado Console.WriteLine(El resultado es {0}, r); } static float Resta() { // Variables necesarias float a = 0; float b = 0; float r = 0; // Pedimos los valores a = PideFlotante(Dame el primer numero); b = PideFlotante(Dame el segundo numero); // Calculamos el resultado r = a - b; // Retornamos el resultado return r;
www.redusers.com
175
5. FUNCIONES Y MTODOS
} static void Multiplicacion(float a, float b) { // Variables necesarias float r = 0; // Calculamos el valor r = a * b; // Mostramos el resultado Console.WriteLine(El resultado es {0}, r); } static float Division(float a, float b) { // Variables necesarias float r = 0; // Verificamos por division entre cero if (b == 0) { Console.WriteLine(No es posible dividir entre cero); return 0.0f; } else { r = a / b; return r; } } static float PideFlotante(string mensaje) { // Variables necesarias float numero = 0.0f; string valor = ;
176
www.redusers.com
Las funciones
// Mostramos el mensaje Console.WriteLine(mensaje); // Obtenemos el valor valor = Console.ReadLine(); numero = Convert.ToSingle(valor); // Regresamos el dato return numero; } } }
Si observamos el cdigo, podemos notar que es ms fcil de leer y luce ms ordenado. Tambin hemos reducido los lugares donde podemos tener un error de sintaxis o lgica. Ejecutemos el programa para verificar si trabaja correctamente. Podemos seleccionar cualquier operacin.
Figura 11. El programa se ejecuta correctamente con nuestra funcin para pedir flotantes al usuario.
www.redusers.com 177
5. FUNCIONES Y MTODOS
Otro punto que debemos de tener en cuenta es que las funciones estn invocando a nuestra funcin sin problema. Las funciones pueden invocar a las funciones.
178
www.redusers.com
Las funciones
numero = 17; } } }
En el programa tenemos dos funciones, la funcin Main() y la funcin Cambiar(). En Main() estamos declarando una variable y le asignamos el valor de 5. Luego imprimimos un mensaje que muestra el valor de nuestra variable antes de invocar a la funcin. En seguida invocamos a la funcin y despus de sta imprimimos otro mensaje que nos muestra el valor de la variable. Esto lo hacemos para poder verificar si la variable se ve afectada por la funcin. La funcin es muy sencilla, simplemente recibe un parmetro y le asigna un nuevo valor. Este programa podra parecer que presentara un valor diferente antes y despus de la funcin, pero ejecutmoslo y veamos qu ocurre.
Al ejecutar notamos que el valor de la variable es igual antes y despus de invocar a la funcin. Es decir que la funcin no alter el valor de la variable, aunque pareca que lo iba a hacer. Veamos la razn de esto.
www.redusers.com 179
5. FUNCIONES Y MTODOS
La primera razn de por qu esto sucede es que la variable fue declarada en la funcin Main(), es decir que solamente esta funcin la conoce y puede utilizarla directamente. Main() es el mbito de la variable. Luego tenemos que cuando el parmetro se pasa de esta forma, en realidad no es la variable lo que se est pasando, sino una copia del valor de ella. Por eso cuando nuestra funcin trata de cambiar el valor, cambia a la copia y no a la variable original. Cuando pasamos los parmetros de esta forma decimos que pasan por copia. Pero existe otra forma de pasar los parmetros y se conoce como paso por referencia. Cambiemos nuestro programa para que quede de la siguiente manera:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { // Variables necesarias int numero = 5; // Valor antes de funcion Console.WriteLine(Valor antes de funcion {0}, numero); // Invocamos funcion Cambiar(ref numero); // Valor despues de funcion Console.WriteLine(Valor despues de funcion {0}, numero); } static void Cambiar(ref int numero) { // Cambiamos el valor numero = 17;
180
www.redusers.com
Las funciones
} } }
Figura 13. En este caso el valor de la variable si es cambiado. Esto se debe a que se pas la referencia a la variable.
En este caso estamos pasando el parmetro por referencia. Cuando esto sucede, en lugar de pasar una copia del valor, lo que pasamos es una referencia al lugar donde se encuentra la variable en memoria. De esta forma cualquier asignacin a la variable se realiza sobre la variable original y su valor puede ser cambiado aunque haya sido definida en otro mbito. Para poder indicar que un parmetro necesita pasarse por referencia es necesario usar la instruccin ref, tanto en la invocacin de la funcin como en su declaracin. Podemos tener ms de una variable pasada por referencia en una funcin. El paso por referencia es muy til, en especial para casos cuando es necesario que una funcin regrese ms de un valor. Como sabemos, return solamente puede regresar un valor, pero al usar referencias podemos tener una funcin que regrese ms de un valor por medio de la modificacin de las variables pasadas.
www.redusers.com 181
Veamos un ejemplo de esto. Vamos a crear una funcin que permita intercambiar los valores de dos variables. Esto problema puede parecer sencillo, pero sin el uso de las referencias es imposible resolverlo con una sola funcin. A continuacin veremos cmo queda nuestra programa.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { // Variables necesarias int a = 5; int b = 3; // Valor antes de funcion Console.WriteLine(Valores antes de funcion a={0}, b={1}, a,b); // Invocamos funcion Cambiar(ref a, ref b); // Valor despues de funcion Console.WriteLine(Valores despues de funcion a={0}, b={1}, a, b); } static void Cambiar(ref int x, ref int y) { // Variable de trabajo int temp = 0;
182
www.redusers.com
Las funciones
Como vemos, hacemos uso de una variable de trabajo para ayudarnos en el intercambio de los valores. El paso por referencia nos permite modificar ambas variables.
5. FUNCIONES Y MTODOS
Con los parmetros de default es posible colocar un valor predeterminado al parmetro, de tal forma que si en la invocacin de la funcin no se da explcitamente el valor, entonces se usa el valor predeterminado. Esto puede resultar til cuando tenemos parmetros que en la gran mayora de los casos usan el mismo valor. De esta forma cuando invocamos a la funcin lo hacemos usando solamente los valores que cambien, lo cual nos permite escribir menos y solamente cuando es necesario colocamos el valor en el parmetro. Esto lo podemos ver en el siguiente ejemplo. El cual tiene una funcin con parmetros de default y es invocada de forma tradicional y luego haciendo uso del parmetro de default. Cuando hace uso del parmetro de default impuesto usa el valor de 0.16.
using using using using System; System.Collections.Generic; System.Linq; System.Text;
namespace Cap5_5 { class Program { static void { double double double Main(string[] args) costo = 50.0; imp = 0.0; total = 0.0;
// Hacemos uso de la funcion de manera tradicional imp = CalculaImpuesto(costo, 0.25); total = costo + imp; // Imprimimos resultado Console.WriteLine(El total es ${0}, total); // Hacemos uso de la funcion con parametro de default // Hay que notar que solamente pasamos un parametro, el otro usa // el valor predeterminado
184
www.redusers.com
Las funciones
imp = CalculaImpuesto(costo); total = costo + imp; // Imprimimos resultado Console.WriteLine(El total es ${0}, total); } public static double CalculaImpuesto(double cantidad, double impuesto = 0.16f) { double impuestoCalculado; impuestoCalculado = cantidad * impuesto; return impuestoCalculado; } } }
Con esto hemos visto los principios y los usos fundamentales de las funciones. Las funciones son muy tiles y las continuaremos utilizando frecuentemente.
RESUMEN
Las funciones nos permiten tener secciones especializadas de cdigo en nuestra aplicacin, reducir la cantidad de cdigo necesario y reutilizar el cdigo de manera eficiente. Las funciones constan de cinco partes y hay cuatro tipos de ellas. La funcin puede recibir informacin por medio de los parmetros y regresar informacin por medio de return. Es posible pasar los parmetros por copia o por referencia.
www.redusers.com
185
EJERCICIOS PRCTICOS
1 Hacer una funcin para transformar de grados a radianes.
186
www.redusers.com
C#
Captulo
Los arreglos
En los captulos anteriores hemos utilizado las variables. Colocamos informacin en stas para luego procesarlas. Nuestros programas pueden tener muchas variables, en especial cuando la cantidad de informacin a guardar es mucha. Los arreglos nos brindan una forma de poder administrar la informacin fcilmente, y son especialmente tiles cuando necesitamos muchas variables y el trabajo que se realiza sobre ellas es el mismo.
Los arreglos Declaracin de los arreglos de una dimensin Asignacin y uso de valores Arreglos de dos dimensiones Arreglos de tipo jagged Los arreglos como parmetros a funciones Resumen Actividades 188 189 191 196 205 212 215 216
6. LOS ARREGLOS
LOS ARREGLOS
Pensemos en un problema donde los arreglos nos pueden ser tiles. En el Captulo 4 creamos un programa donde se calculaba el promedio de un grupo de alumnos. En l usamos un ciclo for, mediante el cual se peda la calificacin constantemente. Para la calificacin siempre se usaba la misma variable. Pensemos ahora, que nos encontramos con la necesidad de que nuestro programa no solamente muestre el promedio, sino tambin la calificacin ms alta y ms baja del saln. Estos clculos requieren ser utilizados en diferentes partes del programa, por lo que no es posible colocar todo adentro del ciclo for con el que fue diseado en un principio. El problema al que nos estamos enfrentando es que, como slo hemos hecho uso de una variable para las calificaciones, cuando necesitemos procesar nuevamente la informacin desde nuestro software, ya no tendremos almacenado el valor de la calificacin anterior en la variable, slo tendremos la ltima calificacin capturada. Cmo podemos resolver esto? Una forma de hacerlo sera crear y utilizar muchas variables como: calif1, calif2, calif3, etctera. Al principio esta idea puede parecer correcta, pero manejar muchas variables de forma independiente, luego de un tiempo puede tornarse engorroso, y tambin podremos encontrar un caso en el que no sabemos cuntas variables necesitaremos. Sin embargo, esto nos puede dar una idea sobre lo que necesitamos. Si observamos el nombre de las variables, vemos que todas llevan en su nombre calif, es decir que todas se refieren a la calificacin. Podemos pensar que estn conceptualmente agrupadas para la calificacin. Otro punto que notamos es que las variables estn numeradas, como si tuvieran un ndice que nos sirve para identificarlas. Los arreglos son similares a estos conceptos ya que son grupos de variables y estas variables sern referenciadas por el mismo nombre. Para poder acceder a una variable del arreglo usaremos un nmero de ndice, ya que todas las variables adentro de un arreglo sern de un mismo tipo. Un punto muy importante que no debemos olvidar cuando trabajemos con los arreglos es que stos estn basados en ndice cero, esto quiere decir que el primer elemento del arreglo se encuentra en la posicin 0, no en la posicin 1 como podramos pensar. No olvidar este punto nos evitar muchos problemas de lgica en el futuro.
188
www.redusers.com
Los arreglos
a0
1 a1 a 2 a2 3
a3
Figura 1. En esta figura vemos la comparacin entre tener varias variables y un arreglo.
www.redusers.com
189
6. LOS ARREGLOS
La declaracin puede parecer un poco extraa, por lo que a continuacin haremos un ejemplo ms claro y real, y lo explicaremos a fondo.
float[] calificaciones= new float[10];
En C# los arreglos son objetos, y deberemos usar new al declararlos. El arreglo ser de tipo flotante, y usaremos [ ] para indicar su declaracin. Luego debemos colocar el nombre con el que lo identificaremos. En nuestro ejemplo se llama: calificaciones. Del lado derecho de la sentencia tenemos la instanciacin del arreglo. Indicaremos entre [ ] la cantidad de elementos que deseamos tener. La cantidad puede ser colocada de forma explcita, tal como est en el ejemplo, o por medio del contenido de una variable. Podemos ejemplificar esto de la siguiente forma:
int n = 10; float[] calificaciones = new float[n];
En este caso se tendr la cantidad de elementos igual al valor guardado en la variable n. En algunas ocasiones podemos conocer los valores que colocaremos adentro del arreglo, por lo que podemos declararlo y asignarle sus valores en la misma sentencia. Esto lo hacemos indicando primero el tipo y los [ ] seguidos del nombre del arreglo y en el lado derecho de la sentencia colocamos entre { } los elementos que se le desean asignar al arreglo. Estos elementos debern estar separados por comas. Vemoslo ejemplificado de manera ms clara:
float[] valores = { 1.5f, 3.78f, 2.1f };
En este caso hemos creado un arreglo llamado valores y tendr tres elementos con los valores colocados. La siguiente figura nos muestra cmo quedara.
190
www.redusers.com
Los arreglos
0-
1.5
valores
1-
3.78
2-
2.1
Lo primero es usar el nombre del arreglo, tal y como con las variables, pero entre [ ] colocamos el ndice del elemento al que se lo queremos asignar. El tercer alumno se encuentra en el ndice 2. Esto se debe a que empezamos a contar desde cero: 0, 1, 2. Luego del lado derecho de la asignacin colocamos el valor a asignar. El control del ndice tambin se puede hacer por medio de una variable de tipo entero. El valor contenido en la variable ser usado para acceder al elemento del arreglo.
calificaciones[indice] = 8.5f;
Para el ndice, tener la capacidad de utilizar una variable es muy til, ya que esto nos permitir recorrer el arreglo con alguno de los ciclos estudiados en los primeros captulos del libro. Los valores contenidos adentro del arreglo pueden usarse como variables normales, por ejemplo en un clculo.
impuesto = costo[n] * 01.5f;
www.redusers.com
191
6. LOS ARREGLOS
Ahora que ya tenemos los conceptos bsicos de los arreglos podemos hacer nuestro programa, donde se pedir la cantidad de alumnos y las calificaciones. El programa encontrar el promedio, la calificacin ms alta y la calificacin ms baja. Para demostrar que los datos no se pierden al ser guardados en el arreglo haremos cada clculo en un ciclo diferente, y para comprender mejor esto, veamos a continuacin el diagrama de flujo correspondiente:
Inicio
n=0
n=0
n=0
Creamos arreglo
suma+= calif[n]
Calif[n] <mnima
NO
Calif[n] >mxima
NO
S n=0 S n<cantidad NO Pedimos calificacin Promedio= suma/ cantidad S n<cantidad S NO mnima= calif[n]
S mxima= calif[n]
n<cantidad NO
n<cantidad NO
Fin
Figura 3. El diagrama nos muestra las diferentes partes donde usamos la informacin del arreglo. using System; using System.Collections.Generic;
192
www.redusers.com
Los arreglos
using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacion static void Main(string[] args) { // Variables necesarias int cantidad = 0; // Cantidad de alumnos int n = 0; // Variable de control de ciclo string valor = ; // Variables para el promedio float suma = 0.0f; float promedio = 0.0f; float minima = 10.0f;// Variable para la calificacin mnima float mxima = 0.0f; // Variable para la calificacin maxima // Pedimos la cantidad de alumnos Console.WriteLine(Dame la cantidad de alumnos); valor = Console.ReadLine(); cantidad = Convert.ToInt32(valor); // Creamos el arreglo float[] calif = new float[cantidad]; // Capturamos la informacin for (n = 0; n < cantidad; n++) { Console.Write(Dame la calificacin ); valor = Console.ReadLine(); calif[n] = Convert.ToSingle(valor); } // Encontramos el promedio
www.redusers.com
193
6. LOS ARREGLOS
for (n = 0; n < cantidad; n++) { suma += calif[n]; } promedio = suma / cantidad; // Encontramos la calificacin mnima for (n = 0; n < cantidad; n++) { if (calif[n] < minima) minima = calif[n]; } // Encontramos la calificacin maxima for (n = 0; n < cantidad; n++) { if (calif[n] > maxima) mxima = calif[n]; } // Desplegamos los resultados Console.WriteLine(El promedio es {0}, promedio); Console.WriteLine(La calificacin mnima es {0}, minima); Console.WriteLine(La calificacin mxima es {0}, maxima); } // Cierre de main } // Cierre de la clase }
Inicialmente declaramos las variables que necesitar la aplicacin. Sin embargo, an no hemos declarado el arreglo. Esto se debe a que el tamao del arreglo depender de la cantidad de alumnos. Una vez que tenemos esa cantidad creamos el arreglo. Luego, por medio de un ciclo for capturamos la informacin. Debemos notar que el ciclo inicia en 0. Esto se debe a que el primer elemento del arreglo se encuentra en el ndice 0. El ciclo se recorre tantas veces como elementos tenga el arreglo. Para calcular el promedio, recorremos el arreglo de nuevo por medio de un ciclo for con la variable suma para obtener la sumatoria de todas las calificaciones. Luego simplemente calculamos el promedio, dividiendo la suma entre la cantidad de alumnos.
194 www.redusers.com
Los arreglos
Para poder calcular la calificacin menor declaramos una variable llamada minima. A esta variable la inicializamos con el valor ms alto posible para las calificaciones (la razn de esto tendr sentido enseguida). Creamos nuevamente un ciclo for y recorremos el arreglo. Para cada elemento del arreglo comparamos su valor con el valor de nuestra variable. Si el valor del elemento del arreglo es menor que minima, eso significa que hemos encontrado un valor menor, por lo que minima se actualiza con este nuevo valor menor. Esto se repite hasta que hemos terminado con todos los elementos del arreglo y minima en cada caso tendr el valor ms pequeo encontrado hasta esa vuelta del ciclo. De igual forma encontramos la calificacin ms alta del arreglo pero en este caso creamos una variable llamada mxima. Esta variable se inicializa con el valor ms pequeo que puede tener una calificacin. Hacemos un ciclo y recorremos todo el arreglo, y a cada elemento contenido en ste lo comparamos con el valor de mxima. Si es mayor eso significa que hemos encontrado un nuevo mximo, por lo que actualizamos la variable. Si lo anterior se cumple, al finalizar el ciclo tendremos la calificacin ms grande para ese grupo de alumnos. Para finalizar el programa, simplemente mostramos en la consola o lnea de comandos, los resultados que hemos obtenido. Ejecutemos y probemos cmo funciona la teora hasta aqu explicada.
Figura 4. El programa guarda la informacin en un arreglo y podemos utilizarla cuando sea necesario.
www.redusers.com 195
6. LOS ARREGLOS
(1,1) Renglones
Figura 5. El diagrama nos muestra un arreglo de dos dimensiones y cmo podemos localizar una celda por medio de su rengln y de su columna.
Al igual que con los arreglos de una sola dimensin, los ndices estn basados en 0. Esto es tanto para los renglones como para las columnas.
196 www.redusers.com
Los arreglos
En este caso, hemos creado una matriz de valores flotantes llamada tabla. Hay que notar que hemos colocado una coma entre los [ ] para indicar que sern dos dimensiones. En el lado derecho indicamos el tamao de cada dimensin. Para este ejemplo tenemos cinco columnas y tres renglones. Tambin es posible declarar la matriz por medio de variables.
float[,] tabla = new float[n, m];
En este caso se toma el valor de la celda (3,2) del arreglo producto, se multiplica por 0.15 y el valor resultante se asigna a impuesto. De igual forma podemos hacer la asignacin al arreglo.
producto[3,2] = 17.50;
No debemos olvidar que los ndices siempre se inician en cero, y que no es posible colocar ndices ms grandes que la cantidad de elementos contenidos en el arreglo. Con este conocimiento podemos comenzar a trabajar en un ejemplo. Tomaremos
www.redusers.com 197
6. LOS ARREGLOS
el cdigo del ejemplo de la escuela y ahora haremos posible que trabaje para varios salones. Para este caso pediremos la cantidad de salones y la cantidad de alumnos. Cada columna representar el saln y los renglones guardarn la informacin de los alumnos. De esta forma podemos capturar toda la informacin de la escuela y calcular el promedio, y la calificacin mnima y mxima de toda la escuela. Para que este programa funcione de forma eficiente utilizaremos la sentencia for y tambin un tipo de ciclo mencionado en un captulo anterior. stos son los ciclos enlazados, o simplemente, un ciclo dentro de otro ciclo. La forma de utilizarlo es la siguiente: tendremos un ciclo para recorrer cada uno de los salones y dentro de ste tendremos otro ciclo que se dedicar a recorrer los estudiantes. De esta forma podemos cubrir todos los salones y todos los estudiantes de cada saln. A continuacin un ejemplo prctico de ciclos enlazados.
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacion static void Main(string[] args) { // Variables necesarias int n = 0; // Ciclo exterior int m = 0; // Ciclo interior // Ciclos enlazados for (n = 0; n < 3; n++) { for (m = 0; m < 5; m++) { Console.WriteLine(Ciclo exterior {0}, ciclo interior {1}, n, m); } // fin del ciclo m } // fin del ciclo n
198
www.redusers.com
Los arreglos
} } }
Figura 6. Vemos cmo se recorren los ciclos. Para cada paso del ciclo exterior tenemos una vuelta completa del ciclo interior.
Al primer ciclo lo llamaremos ciclo exterior y al ciclo que se coloca adentro lo llamaremos ciclo interior. Cada vez que el ciclo exterior avanza un paso, el ciclo interior da una vuelta completa. Este tipo de comportamiento es el que nos
EL MTODO CLEAR()
Los arreglos tienen un mtodo conocido como Array.Clear(). Este mtodo limpia el arreglo y al hacerlo coloca todos sus elementos en 0, false o null dependiendo del tipo del arreglo. El mtodo tiene tres parmetros. El primero es el arreglo a borrar. Luego debemos colocar el ndice a partir de donde deseamos borrar y por ltimo la cantidad de elementos a limpiar.
www.redusers.com
199
6. LOS ARREGLOS
permite recorrer toda la tabla. Para cada columna recorremos todos los renglones. Veamos en el diagrama de flujo del programa cmo sera:
Inicio
n=0
n=0
n=0
m=0
m=0
m=0
Creamos arreglo
suma+= calif[n,m]
Calif[n,m] <mnima
NO
Calif[n,m] >mxima
NO
S n=0 S m<cantidad NO m=0 S n<salones NO Pedimos calificacin Promedio= suma/ cantidad S n<salones NO S S m<cantidad S mnima= calif[n,m]
S mxima= calif[n,m]
m<cantidad
n<salones
m<cantidad NO
n<salones NO
Fin
Figura 7. El diagrama muestra cmo podemos localizar los ciclos enlazados fcilmente.
200
www.redusers.com
Los arreglos
using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacion static void Main(string[] args) { // Variables necesarias int cantidad = 0; // Cantidad de alumnos int salones = 0; // Cantidad de salones int n = 0; // Variable de control de ciclo salones int m = 0; // Variable de control del ciclo alumnos string valor = ; // Variables para el promedio float suma = 0.0f; float promedio = 0.0f; float minima = 10.0f;// Variable para la calificacin mnima float mxima = 0.0f; // Variable para la calificacin maxima // Pedimos la cantidad de salones Console.WriteLine(Dame la cantidad de salones); valor = Console.ReadLine(); salones = Convert.ToInt32(valor); // Pedimos la cantidad de alumnos
ARREGLOS DE MS DIMENSIONES
Podemos tener arreglos de ms de dos dimensiones. El mecanismo para declararlos y utilizarlos es el mismo. Simplemente debemos tener cuidado con el manejo de los ndices para cada dimensin y si el arreglo es de tres dimensiones necesitaremos tres ndices, si es de cuatro, cuatro ndices y as sucesivamente.
www.redusers.com
201
6. LOS ARREGLOS
Console.WriteLine(Dame la cantidad de alumnos por salon); valor = Console.ReadLine(); cantidad = Convert.ToInt32(valor); // Creamos el arreglo float[,] calif = new float[salones, cantidad]; // Capturamos la informacin for (n = 0; n < salones; n++) // Ciclo salones { Console.WriteLine(Salon {0}, n); for (m = 0; m < cantidad; m++) // Ciclo alumnos { Console.Write(Dame la calificacin ); valor = Console.ReadLine(); calif[n, m] = Convert.ToSingle(valor); } } // Encontramos el promedio for (n = 0; n < salones; n++) // Ciclo salones { for (m = 0; m < cantidad; m++) // Ciclo alumnos { suma += calif[n, m]; } } promedio = suma / (cantidad * salones); // Encontramos la calificacin mnima
202
www.redusers.com
Los arreglos
for (n = 0; n < salones; n++) // Ciclo salones { for (m = 0; m < cantidad; m++) // Ciclo alumnos { if (calif[n, m] < minima) minima = calif[n, m]; } } // Encontramos la calificacin maxima for (n = 0; n < salones; n++) // Ciclo salones { for (m = 0; m < cantidad; m++) // Ciclo alumnos { if (calif[n, m] > maxima) mxima = calif[n, m]; } } // Desplegamos los resultados Console.WriteLine(El promedio es {0}, promedio); Console.WriteLine(La calificacin mnima es {0}, minima); Console.WriteLine(La calificacin mxima es {0}, maxima); } // Cierre de main } }
Lo primero que necesitamos es obtener las dimensiones de nuestra matriz. Para esto debemos saber cuntos salones o cuntas columnas y qu cantidad de alumnos o renglones necesitaremos. Como podemos observar, en el cdigo tenemos los ciclos enlazados. Un ciclo recorre los salones y el otro recorre los alumnos. Cuando hacemos la peticin de la informacin, es posible asignarla a la celda adecuada por medio de las variables m y n. De esta forma capturamos toda la informacin y queda guardada en las celdas del arreglo. Teniendo esta informacin, podemos procesarla. Como trabajamos sobre toda la tabla, nuevamente usamos los ciclos anidados, desplegando al final slo los resultados. Ejecutemos el programa y veamos cmo funciona:
www.redusers.com 203
6. LOS ARREGLOS
Figura 8. Observemos que capturamos la informacin y luego la procesamos en diferentes partes del programa para obtener los resultados finales.
Es posible que nosotros hayamos procesado una columna en particular. Para esto simplemente mantenemos fijo el valor de la columna y recorremos los renglones con un ciclo. Un ejemplo de esto sera el siguiente:
for (n = 0; n < 10; n++) { Console.WriteLine(El valor es {0}, producto[5,n]); }
En este caso recorremos la columna 5 de la matriz producto. El ndice del rengln es colocado por la variable de control del ciclo. Tambin es posible mantener fijo el rengln y recorrer todas las columnas. Para esto nuevamente es necesario un solo ciclo.
for (n = 0; n < 10; n++) {
204
www.redusers.com
Los arreglos
Renglones
Figura 9. Tenemos un arreglo y cada elemento del arreglo es a su vez otro arreglo.
www.redusers.com 205
6. LOS ARREGLOS
Al arreglo que contiene los dems arreglos lo llamaremos arreglo contenedor para que podamos reverenciarnos a l fcilmente.
Lo que declaramos es un arreglo jagged de tipo entero que se llamar Costos. Como observamos, junto al int tenemos [ ][ ]. Esto indica que es un arreglo de arreglos y no una matriz. En el lado derecho de la asignacin tenemos algo similar. Aqu indicamos que nuestro arreglo tiene 3 columnas, pero inmediatamente dejamos [ ] vacos. Esto es lo que nos permite tener la flexibilidad de darle un tamao propio a cada rengln. Ya tenemos inicializado el arreglo contenedor. Ahora necesitamos inicializar cada uno de los arreglos internos. Primero indicamos cul es la columna a inicializar. En el ejemplo tenemos Costos[0], es decir, que inicializaremos el arreglo que se encuentra en la primera columna. Del lado derecho est int[15], con lo que indicamos que tendr quince elementos, es decir, 15 renglones para la columna 0. De forma similar la columna 1 tendr 20 renglones y la columna 2 tendr 10 renglones. Podemos ver que ahora tenemos diferente cantidad de renglones para cada columna. Al igual que con los arreglos tradicionales, la cantidad de elementos que tendr el arreglo puede ser colocada de forma explcita o por medio de
206
www.redusers.com
Los arreglos
una variable. Si conocemos con anterioridad la informacin que tendr el arreglo jagged podemos hacer lo siguiente:
int[][] valores = new int[3][]; valores[0] = new int[] { 9, 3, 1, 7, 2, 4 }; valores[1] = new int[] { 2, 9 }; valores[2] = new int[] { 3, 5, 2, 9 };
En este caso creamos un arreglo jagged de tres columnas y luego, al momento de crear cada uno de los arreglos internos, los instanciamos colocando los valores directamente. En este caso cada columna tendr la cantidad de renglones segn la cantidad de valores utilizados en su instanciacin. La columna 0 tendr seis renglones, la columna 1 tendr dos renglones y la columna 2 tendr cuatro renglones. A continuacin se muestra otra forma para inicializar este tipo de arreglos cuando conocemos previamente los elementos que utilizaremos adentro de l:
int[][] valores = new int[][] { new int[] { 9, 3, 1, 7, 2, 4 }, new int[] { 2, 9 }, new int[] { 3, 5, 2, 9 } };
En el ejemplo listado no indicamos directamente la cantidad de columnas. C# encontrar este valor dependiendo de la cantidad de arreglos que se declaren adentro del bloque de cdigo. En este caso declaramos tres arreglos internos, por lo que la cantidad de columnas es de tres. Al igual que en el caso anterior, la cantidad de renglones por columnas depender de la cantidad de elementos que declaramos en cada inicializacin, entonces tendremos las mismas cantidades que en el ejemplo anterior.
www.redusers.com
207
6. LOS ARREGLOS
En este ejemplo vemos que se selecciona el elemento 6 del arreglo contenedor, o si lo preferimos la columna 6. Adentro de esa columna seleccionamos el elemento 7 y ah es dnde se coloca el valor 5.7. Si lo que necesitamos es mostrar el contenido de un elemento, el esquema es similar a lo que ya conocemos.
Console.WriteLine(El valor es {0}, productos[5][n]);
Ahora modificaremos algunas partes del programa de la escuela para usar el arreglo de tipo jagged. Lo que haremos es tener salones con diferente cantidad de alumnos y luego simplemente mostraremos las calificaciones de cada saln. El diagrama es el siguiente:
Inicio
Pedimos salones
n=0
n=0
Creamos arreglo
m=0
m=0
n=0
Pedimos calificacin
Despliega calificacin
Pedimos alumnos
m<tamao arreglo NO
m<tamao arreglo NO
NO n<salones
n<salones NO
Fin
Figura 10. Hemos agregado un ciclo para la creacin de cada uno de los arreglos internos.
Los arreglos
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcin principal del programa // Aqu inicia la aplicacion static void Main(string[] args) { // Variables necesarias int cantidad=0; // Cantidad de alumnos int salones=0; // Cantidad de salones int n=0; // Variable de control de ciclo salones int m=0; // Variable de control del ciclo alumnos string valor=; // Variables para el promedio float suma=0.0f; float promedio=0.0f; float minima=10.0f; //Variable para la calificacin mnima float maxima=0.0f; //Variable para la calificacin maxima // Pedimos la cantidad de salones Console.WriteLine(Dame la cantidad de salones); valor=Console.ReadLine(); salones=Convert.ToInt32(valor); // Creamos el arreglo float[][] calif= new float [salones][]; // Pedimos los alumnos por salon
www.redusers.com
209
6. LOS ARREGLOS
for(n=0;n<salones;n++) // Ciclo salones { Console.WriteLine(Dame la cantidad de alumnos para el salon {0},n); valor=Console.ReadLine(); cantidad=Convert.ToInt32(valor); // Instanciamos el arreglo calif[n]=new float[cantidad]; } // Capturamos la informacin for(n=0;n<salones;n++) // Ciclo salones { Console.WriteLine(Salon {0},n); for(m=0;m<calif[n].GetLength(0);m++) // Ciclo alumnos { Console.Write(Dame la calificacin ); valor=Console.ReadLine(); calif[n][m]=Convert.ToSingle(valor); } }
// Desplegamos la informacin Console.WriteLine( Informacin ); for (n = 0; n < salones; n++) // Ciclo salones { Console.WriteLine(Salon {0}, n); for (m = 0; m < calif[n].GetLength(0); m++) // Ciclo alumnos { Console.WriteLine(El alumno {0} tiene {1} , m, calif[n][m]); }
210
www.redusers.com
Los arreglos
} } } }
Podemos observar que como primera medida hemos creado el arreglo contenedor de acuerdo con la cantidad de salones que tendremos, luego, por medio de un ciclo, recorremos cada uno de los salones preguntando en cada uno la cantidad de alumnos, entonces ah creamos el arreglo interno con el tamao obtenido. Debemos tener cuidado y prestar mucha atencin en el uso de la sintaxis para procesar cada arreglo que manejaremos. Veamos que del lado derecho de la sentencia tenemos el ndice del arreglo que crearemos y en el lado izquierdo indicamos el tamao. De esta forma, quedar creado un arreglo de ese tamao en tal posicin del arreglo contenedor. Ya creado el arreglo jagged procedemos a colocar la informacin en su interior. Al igual que antes usamos ciclos enlazados, y solamente deberemos cambiar la asignacin de acuerdo con la sintaxis del arreglo jagged. Lo mismo ocurre cuando queremos imprimir los contenidos de arreglo jagged en la consola.
Figura 11. Podemos observar que efectivamente cada saln tiene un nmero diferente de alumnos.
www.redusers.com 211
6. LOS ARREGLOS
Para verificar que efectivamente podemos crear columnas con diferentes tamaos cada vez, ejecutemos el programa de nuevo con otros valores.
Figura 12. En esta ocasin hemos creado un arreglo jagged de diferente tamao.
212
www.redusers.com
Los arreglos
Nuestra funcin debe estar definida de forma similar, como se muestra a continuacin:
static void Imprime(int[] arreglo) { ... }
Como podemos ver, en la lista de parmetros indicamos que el parmetro es un arreglo al colocar [ ] y es de tipo int. El nombre del parmetro en este caso es arreglo y lo podremos utilizar internamente dentro de la funcin como variable local. La invocacin se llevara a cabo de la siguiente forma:
int[] numeros = new int[5]; ... ... Imprime(numeros);
Vemos que tenemos un arreglo de enteros que se llama nmeros. En el momento de invocar la funcin lo hacemos por medio del nombre de la funcin y colocamos como parmetro solamente el nombre del arreglo, es decir, pasamos el arreglo pero sin colocarle [ ]. Esto se debe a que pasamos un arreglo completo y no solamente un elemento que se encuentra adentro del arreglo. Ahora veremos un ejemplo donde podamos hacer uso de esto. En la funcin Main() crearemos un arreglo y capturaremos los datos necesarios. Luego tendremos una funcin especializada en imprimir los contenidos del arreglo. Nuestro cdigo queda de la siguiente forma:
using System; using System.Collections.Generic; using System.Text; namespace AplicacionBase { class Program {
www.redusers.com
213
6. LOS ARREGLOS
// Esta es la funcin principal del programa // Aqu inicia la aplicacion static void Main(string[] args) { // Variables necesarias int[] numeros = new int[5]; int n = 0; string valor = ; // Pedimos los numeros for (n = 0; n < 5; n++) { Console.Write(Dame un numero ); valor = Console.ReadLine(); numeros[n] = Convert.ToInt32(valor); } // Invocamos a la funcion Imprime(numeros); } // Esta es la funcin de impresion static void Imprime(int[] arreglo) { int n = 0; for (n = 0; n < 5; n++) { Console.WriteLine(El numero es {0}, arreglo[n]); } } } }
Vemos que es muy sencillo llevar a cabo el paso del arreglo como parmetro y la funcin Imprime() puede usar la informacin que contiene sin problemas.
214 www.redusers.com
Los arreglos
Figura 13. Podemos observar que la informacin capturada efectivamente es pasada a la funcin y sta la utiliza.
Con esto hemos visto los puntos ms importantes de los arreglos y cmo utilizarlos.
RESUMEN
Los arreglos nos permiten guardar informacin adentro de un grupo de variables que son todas del mismo tipo y a las que se puede acceder por un nombre en comn. Para acceder a un elemento en particular necesitamos usar su nmero de ndice. En los arreglos el ndice est basado en cero, es decir que el primer elemento se encuentra en la posicin cero, a diferencia de los arreglos, que pueden tener varias dimensiones dependiendo de nuestras necesidades. Los arreglos de tipo jagged en realidad son arreglos de arreglos. stos nos permiten tener columnas con diferente cantidad de renglones. Al ser clases, los arreglos tienen funciones de apoyo que nos facilitan su uso y pueden ser pasados como parmetros a funciones.
www.redusers.com
215
EJERCICIOS PRCTICOS
1 Agregar el clculo del promedio para el programa con arreglo jagged.
216
www.redusers.com
C#
Captulo
Las colecciones
Hemos aprendido a utilizar los arreglos para guardar grupos de informacin y trabajar ms fcilmente. Si bien los arreglos son muy tiles y sencillos de usar, en algunas ocasiones estn limitados en su funcionamiento y son poco flexibles para guardar grupos de datos dinmicos. En este captulo aprenderemos a utilizar las colecciones. stas nos brindan muchos de los beneficios de los arreglos y nos dan la flexibilidad necesaria para guardar datos dinmicos.
Las colecciones ms importantes El ArrayList El Stack El Queue El Hashtable Resumen Actividades 218 218 232 241 249 253 254
7. LAS COLECCIONES
El ArrayList
La primera coleccin que aprenderemos se conoce como ArrayList, que guarda la informacin como si fuera una lista. Y sobre esta lista es posible realizar diferentes actividades con los elementos almacenados. Entendemos al ArrayList como un arreglo que puede cambiar su tamao segn lo necesitemos. Puede guardar cualquier tipo de dato, por lo que lo podemos usar para enteros, cadenas, flotantes o incluso para tipos definidos por nosotros mismos. ArrayList es una clase en C#, por lo que va a tener mtodos o funciones que nos permitirn trabajar con los datos. El ArrayList tiene una propiedad que llamamos capacidad, que indica el tamao que ocupa la lista. Tambin tenemos el conteo, el cual nos dice cuntos elementos est guardando en su interior. Para entender cmo funciona ArrayList crearemos una pequea aplicacin y en ella realizaremos las operaciones ms importantes.
218
www.redusers.com
Declaracin de un ArrayList
En nuestro programa podemos tener tantos ArrayList como sean necesarios, pero es necesario declararlos primero. La declaracin se lleva a cabo de la siguiente manera:
ArrayList datos = new ArrayList();
Lo primero que necesitamos es indicar ArrayList, ya que ste es el nombre de la clase. Luego colocamos el nombre que va a tener, en nuestro caso es datos. Posteriormente pasamos a la instanciacin, la cual se lleva a cabo por medio de new. En este ejemplo el constructor de la clase no recibe ningn parmetro. Si bien el ArrayList aumenta su tamao dinmicamente, es posible instanciar el arreglo con algn valor de capacidad inicial. Esto es til si sabemos inicialmente cuantos elementos puede contener el ArrayList. para hacerlo simplemente colocamos la capacidad inicial entre los parntesis de la siguiente forma:
ArrayList datos = new ArrayList(32);
Aqu, datos tiene una capacidad inicial de 32, aunque se encuentre vaco.
Adicin de informacin
Nosotros podemos adicionar cualquier tipo de informacin al ArrayList. Hacerlo es muy sencillo y requiere que usemos un mtodo conocido como Add().
Antes 4 Elemento a insertar 7 Despus de insercin 4
10
10
Figura 1. Aqu podemos ver cmo el nuevo elemento es colocado al final del ArrayList existente.
www.redusers.com 219
7. LAS COLECCIONES
Siempre que se adiciona un elemento al ArrayList, este nuevo elemento se agrega al final. Si incorporamos otro elemento, se colocar despus del anterior. La adicin siempre se lleva a cabo despus del ltimo elemento que se encuentre en el ArrayList. El mtodo Add() va a necesitar de un nico parmetro y este es el dato que queremos guardar. Por ejemplo para guardar un dato de tipo entero podemos hacer lo siguiente
datos.Add(7);
El dato a guardar tambin puede ser pasado por medio de una variable:
datos.Add(n);
El uso de foreach
En la programacin orientada a objetos existe un patrn conocido como iterador o iterator, segn su sintaxis en el idioma ingls. La principal caracterstica del iterador es permitirnos realizat un recorrido por todos los elementos que existen en una estructura de datos. El recorrido lo hace de forma sequencial, uno por uno. Esto resulta muy til cuando sabemos que debemos recorrer todos los elementos de la estructura, como un ArrayList, y hacer algo con ellos. En C# encontramos un iterador en el foreach. Con l es posible que recorramos los elementos, luego ejecutamos alguna accin con ellos y finalizamos cuando la coleccin ya no tiene ms elementos que entregarnos. La sintaxis es la siguiente:
LA CAPACIDAD Y EL CONTEO
En varias ocasiones vamos a encontrar que la capacidad del ArrayList es mayor que su conteo, pero nunca menor. La capacidad tiende a ser mayor para que las operaciones de insercin de datos sean rpidas. El arreglo guarda los datos hasta que llega a su capacidad y si la cantidad de datos pasa cierto lmite, el arreglo crece en su capacidad dejando espacio libre para nuevas inserciones.
220
www.redusers.com
El tipo est relacionado con la clase de informacin que guarda la coleccin. Si nuestra coleccin guarda enteros, entonces el tipo debe de ser int y as sucesivamente para cada tipo de dato. Luego tenemos que tener una variable que represente al elemento que se encuentra en la lista, esta variable es el identificador y luego por medio de esta variable identificador podremos hacer algo con la informacin de ese elemento. La expresin simplemente es la coleccin o el arreglo que vamos a recorrer con el ciclo. La sentencia es el cdigo que se va a repetir para cada vuelta del ciclo. La sentencia puede ser sencilla o se puede colocar un bloque de cdigo en caso de ser necesario. Como ya conocemos bien los arreglos, veamos cmo podemos utilizar este ciclo para mostrar los contenidos de un arreglo. Supongamos que tenemos un arreglo de enteros que se llama costo y al que hemos introducido valores. Para mostrarlo con este ciclo, haremos lo siguiente:
foreach(int valor in costo) { Console.WriteLine(El valor es {0}, valor); }
En este caso estamos indicando que el tipo de dato con el que vamos a trabajar es entero. La variable valor cambiar su contenido dependiendo del elemento del arreglo que estemos recorriendo en ese momento. Luego simplemente indicamos que el arreglo a recorrer es costo. Adentro del ciclo mostramos un mensaje indicando el contenido de valor para esa vuelta del ciclo. Ahora es posible continuar nuestro aprendizaje sobre C#, ms especificamente seguiremos revisando las caractersticas de las colecciones.
www.redusers.com
221
7. LAS COLECCIONES
En este caso la variable elementos tendr la cantidad de elementos en el arreglo datos. No debemos olvidar que si elementos tiene el valor de 5, los ndices irn de 0 a 4.
Insertar elementos
Hemos visto que podemos adicionar elementos y que stos son colocados al final del ArrayList, sin embargo tambin es posible llevar a cabo una insercin. La insercin permite colocar un elemento nuevo en cualquier posicin vlida del arreglo. Para lograr esto usamos el mtodo Insert(). Este mtodo necesita de dos parmetros, el primer parmetro es el ndice donde deseamos insertar el elemento y
222 www.redusers.com
el segundo parmetro es el elemento a insertar. La figura que se muestra a continuacin, se encarga de mostrar cmo trabaja la insercin.
Elemento a insertar Despus de insercin
10
10
Figura 2. Podemos observar cmo se lleva a cabo la insercin del elemento, debemos notar cmo algunos elementos cambian de ndice.
www.redusers.com
223
7. LAS COLECCIONES
ndice es un valor entero y debe ser vlido. El mtodo que se encarga de llevar a cabo la eliminacin es RemoveAt().
Elemento a eliminar Despus de eliminacin
10
10
Figura 3. Al eliminar el elemento, desaparece del ArrayList. Los dems elementos se reorganizan y sus ndices pueden modificarse.
Este mtodo solamente necesita de un parmetro, que es el ndice del objeto que deseamos eliminar. Por ejemplo si queremos eliminar el elemento que se encuentra en el ndice 7, podemos hacer lo siguiente:
datos.RemoveAt(7);
ndice = datos.IndexOf(7);
// Adicionamos valores al ArrayList datos.Add(7); datos.Add(5); datos.Add(1); Console.WriteLine(Tenemos inicialmente los datos:); Imprime(datos); }
Para que nuestra aplicacin muestre el arreglo crearemos una pequea funcin llamada Imprime. Esta funcin recibe el ArrayList a imprimir y hace uso del foreach para mostrar cada elemento del ArrayList.
static void Imprime(ArrayList arreglo) { foreach (int n in arreglo)
www.redusers.com
225
7. LAS COLECCIONES
Figura 4. Podemos observar cmo se han mostrado los elementos del ArrayList.
Vamos a experimentar un poco y haremos crecer al arreglo insertando tres nuevos valores. Para el ltimo valor obtendremos el ndice donde fue colocado.
// Hacemos crecer el ArrayList datos.Add(4); datos.Add(5); // Obtenemos el indice indice=datos.Add(10); Console.WriteLine(Despues de hacerlo crecer:);
226
www.redusers.com
Figura 5. Podemos verificar que el ArrayList ha crecido y vemos cmo hemos obtenido el ndice de la ltima insercin.
Ahora utilizaremos el ndice para leer el valor de un elemento y modificar el valor de otro. En este caso la sintaxis es muy similar a la de los arreglos.
// Imprimimos un elemento en particular Console.WriteLine(El valor en el indice 2 es {0},datos[2]); Console.WriteLine(\n); // Modificamos un dato datos[3]=55;
www.redusers.com
227
7. LAS COLECCIONES
Si compilamos este ejemplo, podremos observar cmo se llev a cabo el cambio del elemento adentro del arreglo correspondiente.
En este momento obtendremos la cantidad de elementos que contiene el arreglo y la desplegaremos en la pantalla.
// Obtenemos la cantidad
228
www.redusers.com
www.redusers.com
229
7. LAS COLECCIONES
Figura 8. La insercin puede llevarse a cabo en cualquier lugar del ArrayList, la adicin solo al final.
230
www.redusers.com
Lo ltimo que nos falta en la generacin de nuestra aplicacin, es dotarla de la capacidad de encontrar el ndice donde se encuentra un elemento en particular. Para ello debemos agregar el cdigo que se muestra a continuacin.
// Encontramos el indice donde se encuentra el primer 5 indice=datos.IndexOf(5); Console.WriteLine(Elprimer 5 se encuentra en {0},indice); Console.WriteLine(\n);
Luego de agregar el trozo de cdigo propuesto en el bloque anterior, nuestra aplicacin ser capaz de encontrar el ndice; y como ya se halla completa lucir similar al ejemplo que podemos ver en la imagen mostrada a continuacin:
www.redusers.com 231
7. LAS COLECCIONES
El Stack
Ahora empezaremos a conocer otro tipo de coleccin. A esta coleccin se la conoce como Stack o pila, nos permite guardar elementos y cambia su tamao de forma dinmica, sin embargo trabaja en forma diferente al arreglo y al ArrayList. El Stack es una estructura de tipo LIFO. LIFO es el acrnimo en ingls para Lastin-first-out, es decir el primero que entra, el ltimo que sale. Para entender su funcionamiento podemos imaginar una pila de platos. El primer plato que colocamos queda hasta la base, el siguiente se colocar encima y as sucesivamente. Como el primer plato queda hasta abajo, no lo podemos sacar directamente pues la pila se derrumbara. Al sacar los platos, debemos tomar el que se encuentre hasta arriba de la pila primero y as continuar.
232
www.redusers.com
El efecto de colocar nuevos elementos en la parte superior del Stack se conoce como Push. Esto se muestra en la siguiente figura:
Antes Push Despus de Push
10
10
Figura 11. Podemos observar cmo Push inserta nuevos elementos en la parte superior.
Cuando tomamos un elemento de la parte superior del Stack se conoce como Pop. En la figura podemos observar cmo esto sucede.
Antes Elemento de Pop Despus de Pop
10
10
Figura 12. Pop toma el elemento que se encuentra en la parte superior del Stack.
www.redusers.com 233
7. LAS COLECCIONES
Debido a este comportamiento con Push y Pop podemos entender cmo el primer objeto que se coloca adentro del Stack es el ltimo en poder salir.
Hemos creado un Stack llamado miPila. Nosotros podemos usar cualquier nombre que sea vlido. Una vez instanciado podemos empezar a colocar informacin en l.
En este ejemplo se introduce primero el elemento 7 y luego sobre l se coloca el elemento 11. En seguida se coloca un nuevo elemento en la parte superior, que en este caso es 8. El Stack resultante se muestra en la siguiente figura:
11
Figura 13. El Stack resultante nos muestra como el elemento 7 ha quedado en la base.
234 www.redusers.com
Siguiendo el ejemplo anterior la variable valor ahora tendr en su interior 8. Esto lo vemos en la siguiente figura:
Antes Despus
11
11
Figura 14. Se ha tomado el elemento de la parte superior del Stack. Hay que notar que el elemento no contina siendo parte de l.
EL CASTING
Existe una clase a partir de la cual descienden todas las dems clases en C#, esta clase se conoce como Object. Muchos mtodos regresan objetos de tipo Object, por lo que es necesario indicar el tipo correcto bajo el cual debemos de usarlo. Para hacer esto hacemos uso del casting. Por ejemplo para hacer un casting a entero hacemos lo siguiente: Valor = (int)fila.Dequeue();
www.redusers.com
235
7. LAS COLECCIONES
236
www.redusers.com
// Variables necesarias int opcion=0; string valor=; int numero=0; bool encontrado=false; // Creamos el stack Stack miPila= new Stack(); do { // Mostramos menu Console.WriteLine(1- Push); Console.WriteLine(2- Pop); Console.WriteLine(3- Clear); Console.WriteLine(4- Contains); Console.WriteLine(5- Salir); Console.WriteLine(Dame tu opcion); valor=Console.ReadLine(); opcion=Convert.ToInt32(valor); if(opcion==1) { // Pedimos el valor a introducir Console.WriteLine(Dame el valor a introducir); valor=Console.ReadLine(); numero=Convert.ToInt32(valor); // Adicionamos el valor en el stack miPila.Push(numero); } if(opcion==2) { // Obtnemos el elemento numero=(int)miPila.Pop();
www.redusers.com
237
7. LAS COLECCIONES
// Mostramos el elemento Console.WriteLine(El valor obtenido es: {0},numero); } if(opcion==3) { // Limpiamos todos los contenidos del stack miPila.Clear(); } if(opcion==4) { // Pedimos el valor a encontrar Console.WriteLine(Dame el valor a encontrar); valor=Console.ReadLine(); numero=Convert.ToInt32(valor); // Vemos si el elemento esta encontrado=miPila.Contains(numero); // Mostramos el resultado Console.WriteLine(Encontrado {0},encontrado); } // Mostramos la informacion del stack Console.WriteLine(El stack tiene {0} elementos,miPila.Count); foreach(int n in miPila) Console.Write( {0},, n); Console.WriteLine(); Console.WriteLine();
}while(opcion!=5); }
238
www.redusers.com
} }
El programa es muy sencillo, en primer lugar declaramos las variables necesarias. Una variable es para la opcin seleccionada por el usuario. Otra variable llamada numero ser usada para los casos en los que tengamos que obtener o colocar un valor numrico en el Stack. La variable llamada encontrado es de tipo bool y tendr el valor de true o false dependiendo si el elemento a buscar se encuentra o no en el Stack. Como siempre tenemos una variable de trabajo de tipo cadena que nos ayuda a obtener el valor dado por el usuario. Luego simplemente creamos un Stack llamado miPila. Tenemos un ciclo do que estar repitindose hasta que el usuario decida finalizar el programa. En el ciclo lo primero que hacemos es mostrar el men con las posibles acciones que podemos hacer con el Stack. Luego de acuerdo a cada opcin manipulamos el Stack. Despus de la opcin hacemos uso del foreach para mostrar los contenidos del Stack y poder verificar los cambios realizados. Tambin aprovechamos para mostrar la cantidad de elementos que existen en el Stack. Compilemos y ejecutemos la aplicacin. Lo primero que haremos es insertar algunos valores en el Stack, para esto seleccionaremos la opcin 1. Coloquemos los valores 5, 7, 3.
Figura 15. Podemos observar cmo el ltimo valor introducido se encuentra al inicio del Stack, el primer valor se encuentra al final.
www.redusers.com 239
7. LAS COLECCIONES
Si en este momento hacemos un Pop, el Stack debe de regresarnos el elemento que se encuentra en la parte superior del Stack, en nuestro ejemplo debe ser 3.
Figura 16. Vemos que el valor obtenido es 3 y el Stack ahora solamente tiene dos elementos.
Ahora podemos ver si el Stack tiene un elemento en particular. Para realizar esta operacin, nos encargaremos de seleccionar la opcin nmero 4 y para continuar tendremos que preguntar por el elemento nmero 9. Si ahora preguntamos por el elemento 5 obtendremos una respuesta diferente y la variable encontrado deber tener el valor true. Lo ltimo que nos queda por hacer es limpiar el Stack y para esto seleccionamos la opcin 3.
240
www.redusers.com
Figura 17. El Stack nos regresa el valor de false en la variable encontrado pues el elemento no se halla en el Stack.
El Queue
La siguiente coleccin que aprenderemos se conoce como Queue, algunas veces tambin denominada cola. Al igual que en el Stack, nosotros ya no necesitamos programarla, pues C# nos provee una clase con toda la funcionalidad necesaria para poder utilizarla. La clase que debemos de utilizar para poder tener una cola es Queue. La forma como trabaja es diferente al Stack, ya que el Queue es una estructura de tipo FIFO. Su comportamiento es diferente al Stack. Para entender el Queue, podemos imaginar una fila para comprar los boletos o las entradas al cine. La primera persona en llegar se coloca junto a la taquilla y conforme van llegando otras perso-
EL COMPORTAMIENTO DE FIFO
Cuando nosotros trabajamos con una estructura de datos que funcione bajo el esquema de FIFO debemos tomar en cuenta su comportamiento. FIFO es el acrnimo para First In First Out, que en espaol significa: Primero en Entrar, Primero en Salir. En estas estructuras el primer elemento que colocamos, es el primer elemento que podemos extraer.
www.redusers.com
241
7. LAS COLECCIONES
nas se colocan atrs de ella y as sucesivamente. Sin embargo, en cuanto se habr la taquilla, la primera persona en pasar es la primera que se encuentra en la fila. Esto nos indica que cuando insertamos elementos en el Queue, stos se colocan atrs del ltimo elemento insertado o en la parte posterior de ste. Al momento de leer elementos, se toma el que se encuentre en la parte superior del Queue. Esto lo podemos ver ms fcilmente en la siguiente figura:
Antes Enqueue Dequeue Final
10
10
10
Figura 18. Aqu podemos observar el proceso de adicin de un elemento y tambin qu es lo que sucede cuando se extrae un elemento.
El proceso por medio del cual nosotros insertamos un elemento nuevo al Queue se conoce como Enqueue y no debemos olvidar que lo hace al final. El acto de extraer un elemento del Queue se llama Dequeue y siempre toma el elemento que se encuentra en la parte superior.
Una vez instanciado ya es posible hacer uso de fila y tambin de los mtodos que nos provee la clase correspondiente para trabajar con l.
242 www.redusers.com
Otra altrenativa posible es colocar variables en el parmetro adecuado, si realizamos esto, una copia del valor se ubicar en el Queue.
PRDIDA DE PRECISIN
Algunos tipos de datos, en especial los numricos, pueden llegar a ser compatibles entre s. Pero debemos tener algo en cuenta. Cuando convertimos de un tipo mayor a uno menor, por ejemplo de double a float, es posible que tengamos perdida de informacin. Esto se debe a que el tipo menor no puede guardar tantos dgitos como el mayor.
www.redusers.com
243
7. LAS COLECCIONES
EL CONSTRUCTOR DE LA CLASE
Las clases tienen un mtodo especial llamado constructor. Este mtodo es invocado automticamente en el momento que un objeto de esa clase se instancia. Los constructores pueden o no recibir parmetros y siempre se nombran igual que la clase, se usan principalmente para inicializar correctamente al objeto.
244
www.redusers.com
Si queremos aprovecharla para hacer una operacin en particular y evitar algn error con el Queue, puede ser algo como lo siguiente:
if(miFila.Count>0) valor = (int)miFila.Dequeue();
7. LAS COLECCIONES
Ahora podemos ver un ejemplo que haga uso del Queue. En este ejemplo llevaremos a cabo las operaciones ms comunes sobre ste. Mostraremos al usuario un men y dependiendo de la opcin seleccionada ser la operacin a realizar.
using System; using System.Collections; using System.Text; namespace AplicacionBase { class Program { // Esta es la funcion principal del programa // Aqui inicia la aplicacion static void Main(string[] args) { // Variables necesarias int opcion=0; string valor=; int numero=0; bool encontrado=false; // Creamos el Queue Queue miFila= new Queue();
OPERACIONES INVLIDAS
Si el Queue se encuentra vaco, es decir, sin elementos; cuando intentemos hacer una operacin como Dequeue() o Peek() se generar un error. Una forma de evitar esto, es llevar a cabo estas operaciones solamente cuando la cantidad de elementos sea mayor que cero. Un simple if nos puede ayudar con esto y evitar que el programa ocasione problemas.
246
www.redusers.com
do { // Mostramos menu Console.WriteLine(1- Enqueue); Console.WriteLine(2- Dequeue); Console.WriteLine(3- Clear); Console.WriteLine(4- Contains); Console.WriteLine(5- Salir); Console.WriteLine(Dame tu opcion); valor=Console.ReadLine(); opcion=Convert.ToInt32(valor); if(opcion==1) { // Pedimos el valor a introducir Console.WriteLine(Dame el valor a introducir); valor=Console.ReadLine(); numero=Convert.ToInt32(valor); // Adicionamos el valor en el queue miFila.Enqueue(numero); } if(opcion==2) { // Obtnemos el elemento numero=(int)miFila.Dequeue();
www.redusers.com
247
7. LAS COLECCIONES
// Mostramos el elemento Console.WriteLine(El valor obtenido es: {0},numero); } if(opcion==3) { // Limpiamos todos los contenidos del Queue miFila.Clear(); } if(opcion==4) { // Pedimos el valor a encontrar Console.WriteLine(Dame el valor a encontrar); valor=Console.ReadLine(); numero=Convert.ToInt32(valor); // Vemos si el elemento esta encontrado=miFila.Contains(numero); // Mostramos el resultado Console.WriteLine(Encontrado {0},encontrado); } // Mostramos la informacion del stack Console.WriteLine(El Queue tiene {0} elementos,miFila.Count); foreach(int n in miFila) Console.Write( {0},, n); Console.WriteLine(); Console.WriteLine(); }while(opcion!=5);
248
www.redusers.com
} } }
El Hashtable
La ltima coleccin que aprenderemos en este captulo se conoce como Hashtable. Es una estructura de datos un poco compleja de implementar, pero afortunadamente C# nos provee de una clase que nos da toda la funcionalidad necesaria y podemos utilizarla tan fcilmente como las colecciones anteriores. El Hashtable es una coleccin indexada. Es decir que vamos a tener un ndice y un valor referenciado a ese ndice. Sin embargo, la indexacin no se lleva a cabo como en el arreglo o el ArrayList. El lugar adentro del Hashtable donde se coloca el elemento va a depender de un valor conocido como key o llave. El valor contenido en key es usado para calcular la posicin del elemento en el Hashtable. El elemento que vamos a colocar se conoce como value. En el Hashtable siempre utilizaremos una pareja de key y value para trabajar con l. La forma como trabaja el Hashtable puede parecer extraa, pero en realidad es una estructura muy eficiente al momento de leer la informacin. El comprender el funcionamiento interno del Hashtable pertenece a un libro de nivel ms avanzado, por lo que no tocaremos este tema aqu. La clase se llama Hashtable y pertenece al igual que las dems colecciones al namespace System.Collections.
OTRAS COLECCIONES
Tenemos otras colecciones que no veremos en el captulo pero resultan interesantes y tiles de aprender. El conocer cmo trabajan otras colecciones puede ahorrarnos mucho cdigo y tiempo ya que posiblemente existe lo que estamos tratando de hacer. Para poder conocerlas, como siempre, es recomendable visitar MSDN. Algunas de estas colecciones son: BitArray, Dictionary y SortedList.
www.redusers.com
249
7. LAS COLECCIONES
Si lo que deseamos es declarar e instanciar un Hashtable llamado miTabla, es posible realizarlo prosiguiendo de la siguiente manera:
Hashtable miTabla = new Hashtable();
El nombre del Hashtable puede ser cualquier nombre vlido de variable para C#. Ahora ya podemos aprender a utilizarlo.
El lugar donde quedaron colocados estos elementos adentro del Hashtable depende del algoritmo de hashing que se use. Realmente a nosotros no nos interesa, ya que cualquier acceso que necesitemos lo haremos por medio de key.
NDICES VLIDOS
Para el ArrayList un ndice se considera vlido si no es menor que cero y es menor que la cantidad de elementos que contiene el ArrayList. Si se coloca un ndice fuera de este rango se producir un error. Si estos errores no se manejan adecuadamente, podemos tener prdida de informacin o la finalizacin inesperada de la aplicacin. Lo mejor es evitarlos.
250
www.redusers.com
Recorriendo el Hashtable
Para poder recorrer el Hashtable, haremos uso del ciclo foreach. Si queremos obtener la pareja key-value, nos apoyaremos en una clase conocida como DictionaryEntry. El diccionario tambin guarda parejas de datos. Por ejemplo, si deseamos proseguir con la impresin de los contenidos del Hashtable, podemos colocar el cdigo que se muestra a continuacin:
foreach(DictionaryEntry datos in miTabla) Console.WriteLine(Key {0}, Value {1}, datos.Key, datos.Value);
Si lo deseamos podemos extraer solamente los valores y colocar una copia de ellos en una coleccin. Esto nos permitira trabajar con los valores de una forma ms parecida a lo que hemos aprendido anteriormente.
ICollection valores = miTabla.Values; foreach(double valor in valores) Console.WriteLine(El valor es {0},valor);
ICollection es una interfase usada para implementar las colecciones, de tal forma que
valores puede actuar como cualquier coleccin vlida que tengamos, en este caso la coleccin que representa los valores extrados del Hashtable.
www.redusers.com
251
7. LAS COLECCIONES
252
www.redusers.com
cantidad = miTabla.Count;
Con esto finalizamos los mtodos principales del Hashtable y las colecciones ms usadas en C#.
RESUMEN
Las colecciones nos permiten guardar elementos, a diferencia de los arreglos, stas son dinmicas y pueden modificar su tamao segn sea necesario. Las colecciones tienen diferentes comportamientos, segn la estructura de datos en la que estn basadas. Las que hemos aprendido en este capitulo son: ArrayList, Stack, Queue y Hashtable. Cada coleccin tiene su propia clase y necesitamos instanciarla para poder utilizarla. Tambin nos proveen de diversos mtodos para poder llevar a cabo las operaciones necesarias con los elementos a guardar.
www.redusers.com
253
EJERCICIOS PRCTICOS
1 Hacer el programa que calcula el promedio, calificacin mxima y mnima de un saln de clases usando el ArrayList. 2 Hacer un programa que funcione como un diccionario, con palabra y definicin, usando el Hashtable.
254
www.redusers.com
C#
Captulo
Las cadenas
Las cadenas son un elemento muy importante en la programacin de software, ya que nos permiten guardar y manipular informacin escrita. Algunos lenguajes no tienen un tipo de cadena predefinido, pero C# nos da una clase con diversos mtodos que nos ayudan a trabajar con ellas.
El uso de las cadenas Cmo declarar la cadena El mtodo ToString() Cmo convertir y formatear fechas a cadenas Para darles formato a valores numricos Cmo concatenar cadenas Uso de StringBuilder Comparacin de cadenas Para encontrar una subcadena Para obtener una subcadena Para determinar si una cadena finaliza en una subcadena Cmo copiar una parte de la cadena Cmo insertar una cadena Para encontrar la posicin de una subcadena Justificacin del texto Para eliminar caracteres de la cadena Cmo reemplazar una subcadena Cmo dividir la cadena Intercambiar maysculas y minsculas Cmo podar la cadena Resumen Actividades 256 256 256 257 259 260 261 263 264 265 266 267 268 269 270 271 271 272 273 275 277 278
8. LAS CADENAS
En este caso la variable miCadena contendr la frase Hola a todos y la variable dato contendra una cadena vaca. Siempre representaremos las cadenas entre comillas. Podemos imaginarlas como se muestra en la Figura 1. Esto hace fcil poder visualizarlas y entender las operaciones que podemos realizar sobre ellas.
'H'
'o'
'l'
'a'
''
't'
''
'd'
'o'
's'
Figura 1. Una cadena puede ser representada de esta forma y se puede ver cada uno de sus elementos.
El mtodo ToString()
Un mtodo comn para muchas clases que existen en C# y .NET es ToString(). ste es usado para convertir el tipo de dato o su representacin a una cadena y es muy til cuando necesitamos desplegar esa informacin para que el usuario la pueda leer.
256 www.redusers.com
Si nosotros hacemos nuestras propias clases tambin lo podemos implementar. El mtodo siempre regresar una cadena, que puede ser formateada para nuestras necesidades. Imaginemos que tenemos una variable de tipo entero llamada valor y queremos desplegrsela al usuario. Para esto podemos convertir la cadena agregando el cdigo que se muestra a continuacin:
String Cadena = valor.ToString();
La propiedad Now de DateTime contiene el tiempo actual del sistema en su interior. Ahora lo nico que necesitamos es poder pasar esa informacin a un formato til y prctico de trabajar para nosotros. Podemos hacer uso del mtodo Format() de String. Este mtodo nos permite reemplazar los contenidos de la cadena por una cadena con un formato en particular. Para llevar a cabo un formato debemos usar los especificadores de formato. DateTime contiene un conjunto de estos especificadotes. A continuacin veamos los ms importantes de estos, presentados en la tabla 1 de una forma clara de leer y comprender.
EL CONSTRUCTOR DE LA CADENA
Es importante visitar MSDN y obtener ms informacin sobre la clase String. Una de las cosas que podemos descubrir es que tiene muchas sobrecargas a su constructor, lo que nos permite tener un control muy preciso sobre la forma y las caractersticas con las que ser creada la cadena a utilizar. En este libro usaremos la forma ms sencilla.
www.redusers.com
257
8. LAS CADENAS
DESCRIPCIN Da del mes. Da del mes, pero los primeros das se representan con 01, 02, 03, etctera. Presenta el nombre del da abreviado. Presenta el nombre del da completo. Hora en el rango de 1 a 12. Hora en el rango de 1 a 12. Las primeras horas se presentan como 01, 02, 03, etctera. Hora en el rango de 0 a 23. Hora en el rango de 0 a 23. Las primeras horas se presentan como 01, 02, 03, etctera. Minuto. Minuto. Los primeros minutos se muestran como 01, 02, 03, etctera. Mes. Mes. Los primeros meses se presentan como 01, 02, 03, etctera. Nombre del mes abreviado. Nombre del mes completo. Segundos. Segundos. Los primeros segundos se presentan como 01, 02, 03, etctera. Despliega A o P segn AM o PM. Despliega AM o PM. Muestra el ao.
Tabla 1. Lista de los especificadores ms importantes para DateTime. Una vez que conocemos los especificadores simplemente debemos indicar el formato deseado para que la informacin de DateTime quede guardada en nuestra cadena.
Por ejemplo, si deseamos tener una cadena en la que se muestre la informacin de la fecha de forma tal que primero est escrito el da de la semana, seguido del ao y por ltimo el mes en nmero, podemos hacerlo de la siguiente manera:
String formato; formato=String.Format(La fecha es: {0:dddd yyyy M},DateTime.Now);
LA INFORMACIN ALFANUMRICA
Nosotros podemos guardar informacin alfanumrica adentro de las cadenas. Este tipo de informacin se refiere a los caracteres como letras, nmeros y signos. Lo nico que debemos tener en cuenta es que se guardan como caracteres dentro de la cadena, no como valores de otro tipo. Esto es especialmente importante con los nmeros.
258
www.redusers.com
Adentro de Format colocamos la cadena de formato y como solamente debemos desplegar un valor, hacemos uso de {0}, pero este valor tendr un formato en particular. Ponemos el formato al colocar : y los especificadores necesarios adentro de {}. De esta forma, ese valor tendr el formato correspondiente. Nosotros podemos usar los especificadores que queramos siempre y cuando sean vlidos para el tipo que deseamos formatear en la cadena.
Tabla 2. stos son los especificadores de formato para los valores numricos ms importantes.
Cuando especificamos un formato podemos tener diferentes secciones. Por ejemplo, podemos utilizar un formato en particular para cuando los nmeros sean positivos y otro formato para cuando los nmeros sean negativos. Estas secciones se separan por medio del carcter ;. Si usamos dos secciones, el formato colocado en la primera ser utilizado para los nmeros positivos y el cero. El formato que coloquemos en la segunda seccin ser el que se utilizar para los nmeros negativos. En el caso que definamos tres secciones, el formato colocado en la primera seccin ser utilizado para los nmeros positivos. En la segunda seccin colocaremos el formato que se
www.redusers.com
259
8. LAS CADENAS
utilizar cuando el valor sea negativo. La tercera seccin tendr el formato usado para cuando el valor sea cero. Por ejemplo, podemos colocar el siguiente formato para un valor numrico:
Console.WriteLine(String.Format({0:$#,###0.00;Negativo $#,###0.00;Cero}, valor));
En este caso, si el nmero contenido adentro de valor es positivo se presentar normalmente y con un signo de moneda antes de l, pero si el valor es negativo aparecer con la palabra Negativo y el signo de moneda antes de l. Si el contenido de valor fuera cero, aparecera la palabra Cero.
De esta forma, obtendremos una cadena que tendr en su interior Juan Lopez. Al hacer la concatenacin, hemos incluido otra cadena. En este caso contiene un espacio. De no hacerlo, el nombre y el apellido hubieran quedado juntos y la cadena sera: JuanLopez.
OPTIMIZAR LA CONCATENACIN
Cuando llevamos a cabo la concatenacin por medio del operador +, puede suceder que muchas cadenas se guarden en la memoria y algunas de ellas no sean necesarias, como en el caso de las cadenas que insertan espacios. Para mejorar el uso de la memoria se puede utilizar StringBuilder, una clase que nos da funcionalidades para facilitar la concatenacin.
260
www.redusers.com
'J'
'u'
'a'
'n'
''
'L'
''
'p'
'e'
'z'
'J'
'u'
'a'
'n'
''
'L'
''
'p'
'e'
'z'
Otra forma de concatenar es hacer uso del mtodo Concat(). Este mtodo pertenece a String, es muy sencillo de utilizar y solamente requiere de dos parmetros, que sern las cadenas que deseamos concatenar. El mtodo regresa una cadena, que es la cadena resultante de la concatenacin de los parmetros. Veamos un ejemplo de cmo podemos concatenar:
NombreCompleto = String.Concat(nombre, apellido);
El mtodo Concat() es esttico, por eso es posible usarlo sin tener que declarar un objeto de la clase String. Para llevar a cabo una concatenacin mltiple, podemos hacerlo de la siguiente manera:
NombreCompleto =String.Concat(nombre, String.Concat( , apellido));
Uso de StringBuilder
es una clase que provee .NET y podemos utilizar con C#. Nos permite construir cadenas de forma eficiente y a su vez podemos utilizarla en lugar de las concatenaciones si fuera necesario. Aqu slo veremos los mtodos ms importantes. Invitamos a los lectores a investigar el resto de los mtodos con la ayuda de MSDN. Su constructor tiene varias versiones. Podemos utilizar el constructor de default que no necesita de ningn parmetro. Hay una versin en la que podemos pasar como parmetro una cadena con la que podemos inicializar el objeto StringBuilder. La clase tiene varias propiedades que podemos usar, como la propiedad Capacity, que nos indica la capacidad actual, que puede o no ser igual a la cantidad de caracteres que tenemos guardados en su interior, aunque generalmente ser mayor. Otra opcin es la propiedad Chars, mediante la que podemos obtener o modificar un carcter en particular. La modificacin se hace indicando el ndice donde se encuentra ese carcter. Lo podemos hacer de la siguiente manera:
StringBuilder
www.redusers.com 261
8. LAS CADENAS
Si leemos la propiedad de Length obtenemos la longitud que tiene el StringBuilder. Si colocamos un valor en esta propiedad entonces el StringBuilder tendr el tamao que indicamos. Si el nuevo tamao es menor que el actual, entonces se trunca el contenido del StringBuilder. Para llevar a cabo una concatenacin, debemos usar el mtodo Append(). Este mtodo tiene muchas sobrecargas ya que no solamente puede concatenar cadenas. El mtodo necesita solamente un parmetro y es el valor a concatenar en la cadena. Hay que recordar que Append() es eficiente.
StringBuilder sb = new StringBuilder(Hola a todos); ... ... sb.Append( Hola mundo);
En sb ahora tendremos el contenido de Hola a todos Hola mundo. Tambin podemos agregar una cadena de formato construida de forma similar a la forma como trabajamos con los formatos de WriteLine(). Para esto usamos el mtodo AppendFormat(). Este mtodo necesitar dos parmetros, pero puede llevar ms si fuera necesario. En el primero colocamos la cadena de forma y en el segundo y/o los siguientes la lista de variables a utilizar. Por ejemplo:
StringBuilder sb = new StringBuilder(); int valor = 5; ... ... sb.AppendFormat(El valor es {0}, valor);
Un mtodo importante en esta clase es ToString(), que permitir convertir Stringen una cadena, y de esta manera poder utilizar los contenidos creados por medio de esta clase. Para usarlo simplemente hacemos una asignacin:
Builder
String cadena = ;
262
www.redusers.com
cadena = sb.ToString();
De esta forma, la cadena tendr en su interior la cadena creada por medio del StringBuilder. Existen otros mtodos ms que pertenecen a esta clase y pueden llegar a sernos tiles en el futuro.
Comparacin de cadenas
En algunas de nuestras aplicaciones es posible que lleguemos a necesitar llevar a cabo una comparacin entre algunas cadenas. Esto nos puede servir para determinar si una cadena en especial ha sido introducida por el usuario. Pero la comparacin tambin nos puede ayudar a organizar alfabticamente una serie de cadenas que nosotros seleccionemos, o tambin, simplemente para resolver algn problema que requiera saber si una cadena es mayor, igual o menor que otra. La comparacin de cadenas es una herramienta muy importante para solucionar diversos problemas y lograr resultados que de otra forma seran muy complejos. La clase String nos da el mtodo Compare(). Este mtodo es esttico, por lo que podemos hacer uso de ste sin necesidad de declarar un objeto de tipo String. El mtodo necesitar dos parmetros, que son las cadenas a comparar. Los llamaremos en nuestro ejemplo Cadena1 y Cadena2. El mtodo regresar luego del anlisis, un valor entero y el valor de este entero ser el que se encargue de indicarnos la relacin que existe entre las cadenas que acabamos de comparar. Si el valor regresado es igual a 0, esto significa que Cadena1 y Cadena2 son iguales. En el caso de que el valor sea menor que 0, es decir, un nmero negativo, Cadena1 es menor que Cadena2. Si se recibe un nmero mayor que 0 significa que Cadena1 es mayor que Cadena2. A continuacin veamos la forma utilizar este mtodo:
int comparacin=0; String nombre=Juan; ... ... comparacin=String.Compare(Pedro,nombre); if(comparacin==0) Console.WriteLine(Los nombres son iguales); else Console.WriteLine(Los nombres son diferentes);
www.redusers.com
263
8. LAS CADENAS
'P'
'e'
'd'
'r'
'o'
P>J
'J'
'u'
'a'
'n'
Figura 3. En este ejemplo P es mayor que J, por lo que Pedro es ms grande que Juan.
Otra forma que podemos utilizar para saber si dos cadenas son iguales es hacer uso del mtodo Equals(), que solamente dir si dos cadenas son iguales, no realiza ninguna otra comparacin. Existen varias sobrecargas del mtodo Equals(), por lo que es conveniente aprender el resto con la ayuda de MSDN. La versin que veremos aqu es esttica y requiere dos parmetros. Los parmetros son las cadenas a comparar. El mtodo regresa un bool con el valor de true si las cadenas son iguales y el valor de false si son diferentes. Podemos usarlo de la siguiente manera:
String cadena1 = Hola; String cadena2 = Todos!; ... ... if( String.Equals(cadena1,cadena2) == true) Console.WriteLine(Las cadenas son iguales);
El mtodo Contains() slo necesita un parmetro. Este parmetro es la subcadena a buscar. sta puede ser dada explcitamente o por medio de una variable de tipo String que la contenga. El mtodo regresa un bool. Si la subcadena se encontr, el valor regresado es true y si no se encontr el valor regresado es false. El uso de Contains() puede ser como se muestra a continuacin:
String NombreCompleto = Juan Pedro Lopez; String NombreBuscar = Pedro; ... ... if (NombreCompleto.Contains(NombreBuscar) == true) Console.WriteLine(El nombre se encuentra);
Cadena original 'J' 'u' 'a' 'n' '' 'P' 'e' 'd' 'r' 'o' '' 'L' '' 'p' 'e' 'z'
Cadena a buscar
'P'
'e'
'd'
'r'
'o'
www.redusers.com
265
8. LAS CADENAS
Para poder usar este mtodo necesitamos contar con dos parmetros, que son valores de tipo entero. El primero indica el ndice adentro de la cadena original donde inicia la subcadena que nos interesa obtener y el segundo es la cantidad de caracteres que tiene la subcadena. El mtodo regresa una cadena que contiene a la subcadena que hemos obtenido. El siguiente ejemplo nos muestra cmo podemos usar este mtodo:
String cadena=Hola mundo redondo; String resultado=; ... ... resultado=cadena.Substring(5,5);
Ahora la cadena resultado tendr en su interior a mundo, que es la subcadena que hemos obtenido de la variable cadena.
5 'H' 'o' 'l' 'a' '' 'm' 5 'u' 'n' 'd' 'o' '' 'r' 'e' 'd' 'o' 'n' 'd' 'o'
'm'
'u'
'n'
'd'
'o'
266
www.redusers.com
String cadena2 = Lopez; ... ... if(cadena1.EndsWith(cadena2) == true) Console.WriteLine(La cadena finaliza en Lopez);
Cadena original 'J' 'u' 'a' 'n' '' 'P' 'e' 'd' 'r' 'o' '' 'L' '' 'p' 'e' 'z'
'L'
''
'p'
'e'
'z'
www.redusers.com
267
8. LAS CADENAS
Figura 7. Los caracteres son copiados al arreglo a partir del ndice indicado.
268
www.redusers.com
String cadena1 = Hola a todos; String cadena2 = hola ; String resultado = ; ... ... resultado = cadena1.Insert(5, cadena2);
Cadena original 'H' 'o' 'l' 'a' '' 'a' '' 't' 'o' 'd' 'o' 's'
Cadena resultante 'H' 'o' 'l' 'a' '' 'h' 'o' 'l' 'a' '' 'a' '' 't' 'o' 'd' 'o' 's'
www.redusers.com
269
8. LAS CADENAS
ndice=cadena.LastIndexOf(Hola);
Cadena resultante '' '' '' '' '' '' 'H' 'o' 'l' 'a'
Figura 9. El texto ha sido justificado a la derecha al insertar los espacios del lado izquierdo.
De forma similar, podemos hacer una justificacin hacia la izquierda. En este caso, los caracteres en blanco sern insertados a la derecha de la cadena. Se insertarn tantos caracteres como sean necesarios hasta llegar al tamao deseado.
270 www.redusers.com
Para esto usaremos un mtodo equivalente a PadLeft(), pero hacia la derecha. Este mtodo es conocido como PadRight(). El mtodo necesita un parmetro, que es un valor entero que indica la cantidad total de caracteres de la cadena final. Este total debe ser igual a los caracteres de la cadena original ms los caracteres vacos. El mtodo regresa la cadena justificada.
8. LAS CADENAS
El mtodo es sencillo de utilizar y necesita dos parmetros. El primero es la cadena que simboliza la palabra que deseamos reemplazar. El segundo es la cadena con la que la reemplazaremos. El mtodo regresa una cadena, que es la resultante con los reemplazos ya llevados a cabo. Veamos un ejemplo de la utilizacin de este mtodo:
String cadena1=Hola a todos. Hola mundo; String cadena2=Adios; String resultado=; ... ... resultado=cadena1.Replace(Hola,cadena2);
Por el ejemplo, vemos que es posible colocar el parmetro ya sea de forma explcita o por medio de una variable.
272
www.redusers.com
Como podemos ver en el ejemplo, usamos los caracteres punto, coma y punto y coma como delimitadores. Adentro de resultado estarn las cadenas que han sido recortadas de cadena1.
'H'
'o'
'l'
'a'
''
'm'
'u'
'n'
'd'
'o'
''
'r'
'e'
'd'
'o'
'n'
'd'
'o'
'H'
'o'
'l'
'a'
'm'
'u'
'n'
'd'
'o'
'r'
'e'
'd'
'o'
'n'
'd'
'o'
Figura 10. La cadena ha sido subdividida. Al ser el delimitador, el espacio no aparece en las cadenas resultantes.
www.redusers.com
273
8. LAS CADENAS
Esto nos puede ayudar a reducir la cantidad de comparaciones o bsquedas que necesitamos hacer. Si lo que deseamos hacer es convertir la cadena a minscula, entonces debemos hacer uso del mtodo ToLower(). Este mtodo no necesita ningn parmetro. La fuente de informacin para hacer la conversin es la misma cadena que lo invoca, pero en esta ocasin nos daremos cuenta de que el mtodo s se encargar de regresar un valor, el valor que se devuelve ser la cadena convertida totalmente a letras minsculas. Por ejemplo, podemos tener lo siguiente:
String cadena=Hola Hola; String resultado=; ... ... resultado=cadena.ToLower();
Al finalizar el cdigo la variable resultado tendr en su interior a la cadena hola hola. De forma similar, podemos pasar la cadena a mayscula. La forma de hacer esto es con el mtodo ToUpper(), que toma la cadena y pasa todas sus letras a mayscula. El mtodo no necesita ningn parmetro, ya que al igual que ToLower(), toma la informacin directamente de la cadena que lo invoca y regresa una cadena, que es la resultante con todas las letras en mayscula. Veamos un ejemplo de cmo aplicar esto:
String cadena=Hola Hola; String resultado=; ... ... resultado=cadena.ToUpper();
274
www.redusers.com
La variable resultado tendr en su interior HOLA HOLA. Los dos mtodos tienen otra versin que tiene en cuenta las reglas culturales para poder llevar a cabo la conversin. En ese caso tendramos que pasar como parmetro el identificador de la cultura que se usar como base para convertir los caracteres. En MSDN podemos encontrar la informacin sobre los diferentes identificadores de cultura que puede manejar .NET. Para hacer uso del identificador de cultura debemos usar un objeto de tipo CultureInfo. En su constructor debemos pasar el ID de la cultura correspondiente. Por ejemplo, para pasar a mayscula con las reglas de la cultura en Mxico podemos colocar lo siguiente:
String cadena=Hola Hola; String resultado=; ... ... resultado=cadena.ToUpper(new CultureInfo(es-MX));
www.redusers.com
275
8. LAS CADENAS
En la cadena resultado tendremos Hola a todos, que es la cadena sin los espacios extras. El mtodo Trim() poda los espacios tanto del inicio como del final de la cadena. Sin embargo, puede haber ocasiones en las que necesitemos podar nicamente el inicio de la cadena. El mtodo para lograr esto es TrimStart(). Este mtodo es un poco ms complejo que Trim() ya que necesita un parmetro. Este parmetro es un arreglo de caracteres y en l tenemos que colocar los caracteres que nos interesa extraer del inicio de la cadena. El mtodo regresar otra cadena, que es la resultante de la cadena original sin los caracteres podados a su inicio. Es posible que creemos el arreglo de caracteres o tambin que lo coloquemos explcitamente. Es conveniente pensar bien cules sern los caracteres a podar para evitar la eliminacin de caracteres que s pueden ser tiles. Veamos cmo podemos utilizar este mtodo:
String cadena=x x x x x x Hola a todos. String resultado=; ... ... resultado=cadena.TrimStart( , x); ;
En este ejemplo se podan los caracteres espacio y x. La cadena final resultante es Hola a todos. . Debemos notar que los caracteres al final no han sido podados, ya que solamente trabaja sobre los caracteres al inicio de la cadena. Si lo que necesitamos es podar el final de la cadena, entonces tenemos que usar el mtodo TrimEnd(). Este mtodo es equivalente a TrimStart(), pero funciona nicamente al final de la cadena. Recordemos que el mtodo necesita un parmetro. El parmetro es un arreglo de caracteres. En este arreglo es necesario que coloquemos los caracteres que deseamos eliminar del final de la cadena con la que trabajamos. El mtodo correspondiente se encargar de regresar una cadena, est ser el resultado sin los caracteres que fueron eliminados al final de la cadena original.
276 www.redusers.com
En la cadena de resultado tendremos x x x x x x Hola a todos, el espacio fue eliminado al final ya que se encuentra dentro de la lista de caracteres a podar. Con esto hemos visto el uso y la manipulacin de las cadenas, as como los mtodos ms importantes que nos permiten trabajar con ellas.
RESUMEN
En este captulo hemos aprendido muchas cosas sobre las cadenas y su manipulacin. Aprendimos cmo obtener la hora y fecha del sistema y colocar esa informacin con formato adentro de una cadena. Tambin aprendimos cmo darles formato a los valores numricos que podemos presentarle al usuario. La concatenacin nos sirve para unir dos cadenas o ms y tenemos varias formas de poder llevarla a cabo. StringBuilder es una clase que nos da apoyo para la creacin de cadenas. Podemos comparar las cadenas por medio del mtodo Compare() o Equals(). Podemos saber si una subcadena se encuentra adentro de la cadena principal y tambin obtener una subcadena extrada de la cadena principal, la justificacin del texto es posible, as como su contraparte que consiste en eliminar espacios extras al inicio o al final de la cadena. Es posible pasar la cadena enteramente a mayscula o minscula.
www.redusers.com
277
EJERCICIOS PRCTICOS
1 Hacer un programa que le pida al usuario una cadena y muestre cada una de las palabras de la cadena en una lnea.
278
www.redusers.com
C#
Captulo
Estructuras y enumeraciones
En este captulo aprenderemos un tema muy til. Empezaremos por cmo utilizar los tipos definidos por el programador, es decir, los tipos de datos definidos por nosotros. Estos tipos nos darn la flexibilidad de poder guardar lo que nosotros necesitemos en nuestra aplicacin y poder utilizarlos de forma similar a las variables.
Las estructuras Cmo definir una estructura Cmo crear una variable del nuevo tipo Cmo acceder a los campos de la estructura Cmo mostrar los campos de la estructura Creacin de un constructor para la estructura Estructuras enlazadas Las enumeraciones Resumen Actividades 280 280 282 283 283 286 299 309 315 316
9. ESTRUCTURAS Y ENUMERACIONES
Las estructuras
Las estructuras son tipos definidos por el programador y son un conjunto de datos agrupados. Supongamos que programamos una agenda telefnica. Desde luego, la agenda necesita guardar mucha informacin, por lo que ya hemos pensado en usar arreglos. Pero tambin necesitamos pensar en los datos que debe contener como: nombre, edad, telfono. Esto nos lleva a tener tres arreglos. Si necesitamos ms datos, entonces ms arreglos sern necesarios. Al final es posible que sea un poco complicado administrar tantos arreglos y esto reduce la flexibilidad de nuestro software. Lo mejor sera poder agrupar esa informacin, de forma tal que solamente tengamos que administrar un solo arreglo. La forma de poder agrupar la informacin es por medio del uso de las estructuras. Cuando creamos una estructura, definimos un nuevo tipo y adentro de este tipo podremos colocar datos. Estos datos se conocen como campos. Cada campo est representado por una variable, que puede ser de cualquier tipo. Luego que hemos terminado de definir la estructura podemos crear variables de esta estructura y guardar la informacin que necesitemos en ellas.
Agenda
280
www.redusers.com
Las estructuras
El acceso indica si la estructura puede verse por afuera del mbito donde ha sido definida o no. Si el acceso es de tipo pblico, se puede acceder a la estructura por afuera del mbito. Para esto pondremos como acceso public. Si no deseamos que el exterior pueda acceder a la estructura, entonces la colocamos como privada. Para esto colocamos el acceso como private. En este libro siempre trabajaremos con acceso de tipo public. Para indicar que definimos una estructura usamos struct seguido del nombre de la estructura. ste puede ser cualquier nombre vlido en C#. No hay que confundir el nombre de la estructura con la o las variables que usaremos de ella. Con este nombre identificaremos el nuevo tipo. Luego tenemos que crear un bloque de cdigo. Dentro de este bloque definiremos los campos que necesitamos. stos se definen igual que las variables, pero es necesario colocar el acceso. En este libro utilizaremos un acceso de tipo public, de forma tal que podamos leer la informacin contenida adentro de la estructura. Por ejemplo, la estructura de nuestra agenda puede ser definida de la siguiente forma:
public struct Agenda { public String Nombre; public int Edad; public String Telefono; }
As de sencilla es la definicin. Ya tenemos una estructura llamada Agenda que contiene los campos: Nombre, Edad y Telefono.
www.redusers.com
281
9. ESTRUCTURAS Y ENUMERACIONES
Nosotros podemos definir tantas estructuras como sean necesarias y tambin cada estructura puede tener la cantidad necesaria de campos.
Ahora, adentro del nuevo tipo de variable declarada llamada amigo, se encuentran los campos Nombre, Edad y Telefono. Es posible declarar varias variables de Agenda.
Agenda amigo1, amigo2, amigo3;
En el caso de necesitar hacer uso de ste, podemos crear un arreglo de la estructura. Este arreglo puede ser del tamao que necesitemos para nuestra aplicacin, y es entonces de esta forma que para la estructura agenda podemos tener un arreglo donde guardamos la informacin de los amigos, y otro arreglo donde se guardar la informacin de los clientes.
Agenda []amigos=new Agenda[15]; Agenda []clientes=new Agenda[5];
282
www.redusers.com
Las estructuras
Esto quiere decir que primero debemos indicar cul es la variable con la que deseamos trabajar. Luego necesitamos utilizar el operador punto y seguido de l colocamos el nombre del campo a acceder. Veamos un ejemplo de esto:
amigo.Edad = 25;
En este caso decimos que al campo Edad de la variable amigo le colocamos en su interior el valor 25. Podemos utilizar los campos en cualquier tipo de expresin vlida, tal y como una variable:
if(amigo.Edad>18) ... diasVividos=amigo.Edad * 365; ... Console.WriteLine(El nombre es {0},amigo.Nombre);
CAMPOS OLVIDADOS
Es posible que tengamos una estructura y que slo utilicemos determinados campos, sin embargo, los dems campos continan existiendo. Algunos de stos pueden inicializarse automticamente a 0 o null si usamos new para crear la variable. Pero si se hace de forma tradicional y no se han inicializado, entonces ese campo no tiene instancia y originar problemas si se intenta usar.
www.redusers.com
283
9. ESTRUCTURAS Y ENUMERACIONES
Esta forma es sencilla y til en los casos en los que solamente necesitamos mostrar un campo de la estructura. Sin embargo, de necesitar mostrar todos los campos, deberemos colocar WriteLine() para cada campo, o uno solo con una cadena de formato larga. En cualquier caso resulta incmodo. La mejor forma de mostrar todos los datos contenidos en los campos sera mediante la conversin de la estructura a una cadena. Sabemos que existe un mtodo llamado ToString() que hemos usado con las variables numricas. Sin embargo, C# no se lo puede dar directamente a nuestra estructura porque no puede saber cules son los campos que contiene ni cmo los deseamos mostrar. Por esto, cae en nuestra responsabilidad programar el mtodo ToString() de nuestra estructura. Veamos esto en el siguiente ejemplo:
public struct { public public public Agenda String Nombre; int Edad; String Telefono;
public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); } }
Podemos observar que adentro del bloque de cdigo de la estructura hemos colocado nuestra versin del mtodo ToString(). El acceso debe ser pblico para que se pueda invocar desde el exterior de la estructura. Este mtodo debe regresar un objeto de tipo String y no necesita ningn parmetro. En el interior del mtodo simplemente colocamos el cdigo necesario para darle formato a la cadena y en nuestro caso hacemos uso de StringBuilder, aunque es vlido usar cualquier otro mtodo. Al finalizar ya tenemos la cadena con la informacin de nuestros campos y la regresamos por medio de return.
284 www.redusers.com
Las estructuras
Ahora que ya tenemos implementado ToString() mostrar la informacin contenida ser tan sencillo como:
Console.WriteLine(amigo.ToString());
public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); } } static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin //
www.redusers.com
285
9. ESTRUCTURAS Y ENUMERACIONES
Como parte del ejemplo creamos un arreglo de la estructura Agenda que se llama amigos y tiene 5 elementos, luego, para el elemento en el ndice 1 colocamos los datos. Para finalizar simplemente imprimimos el elemento 1 del arreglo amigos, pero usamos el mtodo ToString() programado por nosotros. Si compilamos y ejecutamos el programa obtendremos lo siguiente:
Figura 2. Podemos observar cmo por medio de ToString() obtenemos la cadena con la informacin de la estructura y la mostramos en la consola.
Las estructuras
Adentro del constructor podemos colocar cualquier cdigo vlido de C#, pero es evidente que colocaremos cdigo dedicado a la inicializacin de los campos. Veamos un primer ejemplo de cmo podemos crear un constructor. El constructor siempre va adentro del bloque de cdigo de la estructura.
public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=pTelefono; }
En el cdigo del constructor vemos que el acceso es pblico. Esto es necesario y siempre debemos dejarlo as. Si observamos luego se coloca directamente el nombre del constructor. El nombre es Agenda, ya que pertenece a la estructura Agenda. A continuacin tenemos la lista de parmetros. Los valores pasados como parmetros sern asignados a los campos correspondientes. En la declaracin de la variable lo tendremos que usar de la siguiente forma:
Agenda amigo=new Agenda(Juan,25,(555) 123-4567);
Aqu vemos que declaramos la variable amigo que es de tipo Agenda. Al hacer la instanciacin por medio de new vemos que pasamos los parmetros. stos sern los datos que quedarn guardados en los campos de la variable amigo. La cadena Juan quedara adentro del campo Nombre, el valor de 25 adentro del campo Edad y la cadena (555) 123-4567 en el campo Telefono. Veamos cmo quedara un programa completo con el constructor:
EL USO DE OVERRIDE
El mtodo ToString() se defini en la clase Object, de la cual desciende todo en C#, pero al estar definiendo una versin nueva para nuestra estructura usamos override, que le indica al compilador que creamos una nueva implementacin que usar nuestra estructura. As, al invocar ToString() se usar la versin implementada por nosotros en lugar de la versin base.
www.redusers.com
287
9. ESTRUCTURAS Y ENUMERACIONES
public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=pTelefono; } public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); } } static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin //
TUTORA DE ESTRUCTURAS
En la direccin web que listaremos a continuacin, encontraremos una pequea tutora sobre la utilizacin de las estructuras en C#. Recordemos siempre buscar informacin, tutoriales y cualquier otro material que nos sea de utilidad, para poder ampliar nuestros conocimientos: www.devjoker.com/asp/ver_contenidos.aspx?co_contenido=161.
288
www.redusers.com
Las estructuras
Figura 3. Vemos cmo efectivamente los datos han sido colocados en los campos de la variable por medio del constructor.
9. ESTRUCTURAS Y ENUMERACIONES
public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; if(pTelefono.Length>8) Telefono=pTelefono; else Telefono=Telfono no vlido; }
Como vemos, hacemos uso de if y verificamos la longitud de la cadena pTelefono. Si es mayor a 8 entonces le asignamos pTelefono al campo Telefono. En caso contrario, colocamos un mensaje que dice que el telfono no es vlido. El programa completo es el siguiente:
public struct Agenda { public String Nombre; public int Edad; public String Telefono; public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre;
TUTORA DE ENUMERACIN
El mismo sitio web que nombramos anteriormente presenta una tutora sobre el uso de la enumeracin en C# que complementa los conceptos que hemos aprendido en este captulo: www.devjoker.com/contenidos/Tutorial-C/164/Enumeraciones.aspx.
290
www.redusers.com
Las estructuras
Edad=pEdad; if(pTelefono.Length>8) Telefono=pTelefono; else Telefono=Telefono no valido; } public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); }
static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin // Agenda amigo=new Agenda(Juan,25,(555) 123-4567); Agenda amigo1=new Agenda(Pedro,32,(555)); Console.WriteLine(amigo.ToString()); Console.WriteLine(amigo1.ToString());
www.redusers.com
291
9. ESTRUCTURAS Y ENUMERACIONES
Figura 4. Podemos ver cmo el constructor no slo ha asignado el valor sino que tambin ha validado la informacin.
LA SOBRECARGA
Sobrecarga es una tcnica de programacin que permite tener varias versiones de una funcin o un mtodo. El compilador selecciona la versin a utilizar basndose en la cantidad de parmetros y los tipos. Esto nos permite agrupar mtodos diferentes bajo un mismo nombre o concepto, facilitando la programacin, solamente recordando un nombre, y no los nombres para cada versin.
292
www.redusers.com
Las estructuras
necesite el nombre y la edad, y podemos hacer que esta versin coloque un mensaje que indique que no tiene telfono. Para hacer la sobrecarga colocamos la segunda versin debajo de la que ya tenemos. Por ejemplo, nuestra segunda versin queda de la siguiente forma:
public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telfono; }
Como podemos ver, solamente recibimos dos parmetros, pero aun as los tres campos son asignados con un valor. Ningn campo se queda sin asignar. Para declarar la variable le pasamos los 2 parmetros necesarios.
public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; if(pTelefono.Length>8)
www.redusers.com
293
9. ESTRUCTURAS Y ENUMERACIONES
Telefono=pTelefono; else Telefono=Telfono no vlido; } public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telefono; } public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); } } static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin // Agenda amigo=new Agenda(Juan,25,(555) 123-4567); Agenda amigo1=new Agenda(Pedro,32,(555)); Agenda amigo2=new Agenda(Luis,28); Console.WriteLine(amigo.ToString()); Console.WriteLine(amigo1.ToString()); Console.WriteLine(amigo2.ToString()); }
294
www.redusers.com
Las estructuras
Figura 5. En esta figura podemos observar cmo el constructor sobrecargado tambin ha asignado la informacin necesaria en los campos.
Incluso podemos hacer que el constructor le solicite la informacin directamente al usuario. Hay que recordar que podemos colocar cualquier cdigo vlido en su interior. Esto lo logramos al crear una nueva sobrecarga. Veamos cmo puede quedar esta nueva versin del constructor:
public Agenda(String pNombre) { // Asignamos el nombre Nombre=pNombre; // Pedimos la edad Console.WriteLine(Dame la edad:); Edad=Convert.ToInt32(Console.ReadLine());
www.redusers.com
295
9. ESTRUCTURAS Y ENUMERACIONES
Lo primero que hacemos es asignar el nombre que hemos recibido por parmetro. Luego de la forma usual pedimos la edad, notando cmo est colocada la sentencia. Sabemos que ToInt32() necesita un parmetro que es la cadena a convertir y ReadLine() regresa una cadena. De esta forma, aprovechamos y colocamos todo el cdigo adentro de una sola lnea. Otra opcin que podramos haber utilizado es una funcin que pida el dato, tal y como lo vimos en un captulo anterior. Enseguida solicitamos el telfono y aprovechamos para validar la informacin. El programa completo queda de la siguiente manera:
public struct { public public public Agenda String Nombre; int Edad; String Telefono;
public Agenda(String pNombre, int pEdad, String pTelefono) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad;
CONSTRUCTOR EN LA ESTRUCTURA
Cuando utilizamos el constructor con nuestra estructura o cuando tenemos sobrecargas, tenemos que tener cuidado con la cantidad de parmetros. Dentro de las estructuras el constructor necesita tener al menos un parmetro ya que no es vlido colocar un constructor sin parmetros. Si olvidamos colocar los parmetros, tendremos un error durante la compilacin del programa.
296
www.redusers.com
Las estructuras
if(pTelefono.Length>8) Telefono=pTelefono; else Telefono=Telfono no valido; } public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telfono; } public Agenda(String pNombre) { // Asignamos el nombre Nombre=pNombre; // Pedimos la edad Console.WriteLine(Dame la edad:); Edad=Convert.ToInt32(Console.ReadLine()); // Pedimos el telfono Console.WriteLine(Dame el telfono:); Telefono=Console.ReadLine(); if(Telefono.Length<8) Telefono=Sin telfono;
EL MODIFICADOR OVERRIDE
Si deseamos conocer ms sobre el modificador override en C#, podemos hacerlo directamente en el sitio MSDN. Este sitio de Microsoft siempre es una muy buena referencia y podemos encontrar toda la informacin que necesitemos. La direccin electrnica es: http://msdn2.microsoft.com/es-es/library/ebca9ah3(VS.80).aspx.
www.redusers.com
297
9. ESTRUCTURAS Y ENUMERACIONES
} public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telfono); return (sb.ToString()); } } static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin // Agenda Agenda Agenda Agenda amigo=new Agenda(Juan,25,(555) 123-4567); amigo1=new Agenda(Pedro,32,(555)); amigo2=new Agenda(Luis,28); amigo3=new Agenda(Maria);
298
www.redusers.com
Las estructuras
Figura 6. Vemos que el constructor efectivamente nos pide los datos por medio de la consola y luego son asignados.
Estructuras enlazadas
Las estructuras nos dan la facilidad de poder agrupar informacin que est relacionada adentro de un mismo elemento. Ya vimos que se puede colocar como dato a cualquier tipo que sea vlido en C#. Estos tipos vlidos tambin corresponden a tipos definidos por el programador, es decir otras estructuras. Tenemos una estructura que se llama Agenda, pero esta agenda est un poco incompleta, debido a que nos hace falta colocar la direccin o el domicilio de la persona. Esto lo podemos resolver de una manera prctica, colocando dos campos nuevos como la calle y el nmero de la casa, pero tambin podramos pensar en otra estructura llamada Direccion que contenga esta informacin. Por ejemplo, la estructura podra quedar de la siguiente forma:
public struct Direccion { public String Calle;
www.redusers.com
299
9. ESTRUCTURAS Y ENUMERACIONES
public int Numero; public Direccion(String pCalle, int pNumero) { Calle=pCalle; Numero=pNumero; } }
Como vemos, los campos son Calle y Numero. Se ha creado un constructor para ayudarnos a colocar la informacin fcilmente cuando se instancie una variable de este nuevo tipo. Ahora que ya tenemos definido el nuevo tipo Direccion, podemos usarlo en nuestra estructura Agenda, pero sern necesarios algunos cambios. Primero veamos cmo agregar un campo de tipo Direccion a la estructura:
public struct { public public public public Agenda String Nombre; int Edad; String Telefono; Direccion Domicilio;
Agregar un campo es muy sencillo, simplemente definimos la variable. Sin embargo, si dejamos la estructura con ese cambio tendremos problemas, ya que el campo Domicilio no estar instanciado. Esta instanciacin se puede llevar a cabo cuando se asignan los datos, por ejemplo, en el constructor. Cambiemos el primer constructor para instanciar y asignarle datos al campo Domicilio:
public Agenda(String pNombre, int pEdad, String pTelefono, String pCalle, int pNumero) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; if(pTelefono.Length>8)
300
www.redusers.com
Las estructuras
Vemos que hemos llevado a cabo algunos cambios. En primer lugar, el constructor de Agenda recibe todos los datos necesarios, incluidos los de la estructura Direccion. En el interior del constructor asignamos los datos que le corresponden a Agenda y en la parte final hacemos la instanciacin de Domicilio por medio de new y le pasamos a su constructor los datos que le corresponden. Tambin puede suceder que el constructor de Agenda no reciba los datos de Domicilio. En ese caso, debemos instanciar tambin al campo domicilio y pasar algunos datos de default al constructor.
public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telfono; Domicilio=new Direccion(Sin direccin,0); }
En este caso, vemos que la instanciacin se lleva a cabo, pero simplemente pasamos algunos parmetros de default. Si continuamos con estos cambios, el programa quedar de la siguiente manera:
public struct Direccion { public String Calle; public int Numero; public Direccion(String pCalle, int pNumero) {
www.redusers.com
301
9. ESTRUCTURAS Y ENUMERACIONES
Calle=pCalle; Numero=pNumero; } } public struct { public public public public Agenda String Nombre; int Edad; String Telefono; Direccion Domicilio;
public Agenda(String pNombre, int pEdad, String pTelefono, String pCalle, int pNumero) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; if(pTelefono.Length>8) Telefono=pTelefono; else Telefono=Telfono no valido; Domicilio=new Direccion(pCalle, pNumero); } public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telfono; Domicilio=new Direccion(Sin direccin,0); } public Agenda(String pNombre)
302
www.redusers.com
Las estructuras
{ // Asignamos el nombre Nombre=pNombre; // Pedimos la edad Console.WriteLine(Dame la edad:); Edad=Convert.ToInt32(Console.ReadLine()); // Pedimos el telfono Console.WriteLine(Dame el telfono:); Telefono=Console.ReadLine(); if(Telefono.Length<8) Telefono=Sin telfono; Domicilio=new Direccion(Sin direccin,0);
} public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); return (sb.ToString()); } }
static void Main(string[] args) { // // TODO: agregar aqu cdigo para iniciar la aplicacin // Agenda amigo=new Agenda(Juan,25,(555) 123-4567,Av. Principal,105);
www.redusers.com
303
9. ESTRUCTURAS Y ENUMERACIONES
Agenda amigo1=new Agenda(Pedro,32,(555),Calle Bolivar,350); Agenda amigo2=new Agenda(Luis,28); Agenda amigo3=new Agenda(Maria); Console.WriteLine(amigo.ToString()); Console.WriteLine(amigo1.ToString()); Console.WriteLine(amigo2.ToString()); Console.WriteLine(amigo3.ToString()); }
Podemos observar que en las variables amigo y amigo1 ya hemos colocado previamente los parmetros necesarios por el constructor modificado. Slo queda que compilemos y ejecutemos el programa.
Al parecer tenemos un problema ya que obtenemos el mismo resultado que el programa anterior a pesar de los cambios. Esto sucede debido a que no hemos actualizado el mtodo ToString() de Agenda ni creado el propio de Direccion.
304 www.redusers.com
Las estructuras
Para Direccion:
public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Direccion: {0} #{1}, Calle, Numero); return (sb.ToString()); } Para Agenda: public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); // Adicionamos la cadena que viene de Domicilio sb.Append(Domicilio.ToString()); return (sb.ToString()); }
Vemos que adentro del ToString() de Agenda agregamos la cadena que nos regresa el ToString() de Domicilio. De esta forma, cuando se impriman los contenidos de Agenda tambin se imprimirn los del campo Domicilio. El programa completo queda de la siguiente forma:
public struct Direccion { public String Calle; public int Numero; public Direccion(String pCalle, int pNumero) { Calle=pCalle; Numero=pNumero;
www.redusers.com
305
9. ESTRUCTURAS Y ENUMERACIONES
} public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Direccion: {0} #{1}, Calle, Numero); return (sb.ToString()); } } public struct { public public public public Agenda String Nombre; int Edad; String Telefono; Direccion Domicilio;
public Agenda(String pNombre, int pEdad, String pTelefono, String pCalle, int pNumero) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; if(pTelefono.Length>8) Telefono=pTelefono; else Telefono=Telfono no valido; Domicilio=new Direccion(pCalle, pNumero); } public Agenda(String pNombre, int pEdad) { // Llevamos a cabo la asignacin Nombre=pNombre; Edad=pEdad; Telefono=Sin telfono;
306
www.redusers.com
Las estructuras
Domicilio=new Direccion(Sin direccin,0); } public Agenda(String pNombre) { // Asignamos el nombre Nombre=pNombre; // Pedimos la edad Console.WriteLine(Dame la edad:); Edad=Convert.ToInt32(Console.ReadLine()); // Pedimos el telefono Console.WriteLine(Dame el telfono:); Telefono=Console.ReadLine(); if(Telefono.Length<8) Telefono=Sin telfono; Domicilio=new Direccion( Sin direccin,0);
} public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat(Nombre: {0}, Edad: {1}, Telefono: {2}, Nombre, Edad, Telefono); // Adicionamos la cadena que viene de Domicilio sb.Append(Domicilio.ToString()); return (sb.ToString()); } } static void Main(string[] args)
www.redusers.com
307
9. ESTRUCTURAS Y ENUMERACIONES
{ // // TODO: agregar aqu cdigo para iniciar la aplicacin // Agenda amigo=new Agenda(Juan,25,(555) 123-4567,Av. Principal,105); Agenda amigo1=new Agenda(Pedro,32,(555),Bolivar,350); Agenda amigo2=new Agenda(Luis,28); Agenda amigo3=new Agenda(Maria); Console.WriteLine(amigo.ToString()); Console.WriteLine(amigo1.ToString()); Console.WriteLine(amigo2.ToString()); Console.WriteLine(amigo3.ToString()); }
Las estructuras
Las enumeraciones
Ya hemos aprendido las estructuras y ahora conoceremos otro nuevo tipo que puede ser definido por el programador. Este nuevo tipo se conoce como enumeraciones. stas son tipos que nosotros podemos definir, pero tendrn un nmero finito de valores posibles, es decir, que podemos definir el tipo y los valores a guardar. Las enumeraciones son tiles cuando tenemos informacin que sabemos que solamente puede tener uno de una serie de posibles valores. Por ejemplo, sabemos que la semana tiene siete das. Entonces, un da no puede tener un valor que no sea el de un da de la semana. La semana sera una enumeracin. Esto lo podemos utilizar para cualquier otro ejemplo donde sepamos los valores posibles a utilizar. Otro ejemplo, supongamos que estamos haciendo un programa para una empresa que vende quesos. Tendremos un nmero finito de posibles tipos de queso. Entonces, podemos colocarlos adentro de una enumeracin. Al parecer, las enumeraciones son muy sencillas, pero podemos correr el riesgo de pensar que no son muy tiles. Sin embargo, nos dan grandes beneficios. Tambin nos sirven para reducir la cantidad de errores que podemos tener en nuestra aplicacin al asignar y utilizar valores. Como beneficio, reducen la lgica que debemos utilizar e incluso mejoran el desempeo de nuestra aplicacin. Por eso es til aprender a usarlas correctamente.
Martes Mircoles
Veamos un ejemplo donde podemos utilizar la enumeracin para mejorar nuestra aplicacin. Si nuestro programa necesita guardar por algn motivo el da de la semana podemos pensar en diferentes opciones. La primera puede ser la utilizacin de una variable de tipo entero, ya que cada da de la semana puede ser definido por un nmero del 1 al 7. Sin embargo, esto nos presenta algunos problemas. El primer problema es que usamos un tipo que puede guardar miles de valores posibles, pero slo usamos 7, entonces tenemos un desperdicio de memoria. El segundo problema es que el tipo, al poder guardar muchos valores, puede guardar datos que no correspondan a la realidad como el da 8 de la semana. Para evitar esto necesitamos agregar lgica de control con el uso de uno o varios if. De
www.redusers.com 309
9. ESTRUCTURAS Y ENUMERACIONES
esta manera, se complica nuestra aplicacin. Otro problema que esto nos presenta es el despliegue de la informacin. Cada vez que queremos mostrar el da tenemos que poner lgica para transformar 1 a Lunes, 2 a Martes, y as sucesivamente para poder listar cada da de la semana. Quizs otra solucin sera el uso de una cadena para guardar el da de la semana, pero tambin presenta problemas. Un problema que podemos tener es que si nuestra lgica funciona con Lunes, cuando el usuario introduzca un valor como lunes ya no funcionar. Para corregir esto podemos usar el mtodo ToUpper(), pero agrega ms lgica y proceso extra a nuestra aplicacin que no es necesario. Tambin gastamos memoria de ms ya que guardar una cadena requiere ms memoria que guardar un simple nmero. Desde luego, la impresin sera ms sencilla, pero la administracin de la informacin ms complicada. Nuestra mejor opcin es el uso de las enumeraciones. Ahora aprenderemos cmo usarlas y cmo el problema anterior se resolvera fcilmente con ellas.
En primer lugar, tenemos que colocar la palabra clave enum seguida del nombre con el que identificaremos al nuevo tipo de enumeracin. Luego entre {} debemos colocar los valores que puede tener este tipo. Hay que recordar que los valores son finitos. Veamos cmo declarar una enumeracin para nuestro ejemplo de la semana:
enum semana {Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo};
En este caso, hemos declarado la enumeracin con el nombre de semana. Cada uno de los das que hemos listado entre {} sern los posibles valores que puede tener. Con
310
www.redusers.com
Las estructuras
esto, el siguiente paso sera simplemente la creacin de una variable de tipo semana. La declaracin y asignacin de la variable la hacemos de la forma tradicional.
semana miDia;
Aqu declaramos la variable miDia que es de tipo semana, por lo que solamente podr tener los valores listados en la enumeracin. Si lo hubiramos deseado, tambin podramos haber declarado e inicializado la variable con algn valor.
semana miDia=semana.Martes;
La asignacin del valor en esta variable se puede llevar a cabo en cualquier momento, dentro de nuestra aplicacin, despus de su declaracin, como en cualquier otra variable, pero con uno de los valores contenidos en semana.
miDia=semana.Viernes;
Otro mecanismo que podemos utilizar para desplegar la informacin de una variable de tipo enumeracin es la cadena de formato. En este caso, simplemente colocamos la variable en nuestra lista de variables:
Console.WriteLine(El dia es {0}, miDia);
www.redusers.com
311
9. ESTRUCTURAS Y ENUMERACIONES
De esta forma, Lunes tendr un valor de 3, Martes de 4 y as sucesivamente hasta Domingo con un valor de 9.
La enumeracin en expresiones
Como nosotros trabajamos con una variable de tipo enumeracin, podemos utilizarla en cualquier tipo de expresin. Slo debemos ser cuidadosos con los tipos con los que interactuamos en la expresin. Si fuera necesario, podemos hacer uso de type cast para que la expresin quede correctamente escrita.
IMPORTANCIA EN EL APRENDIZAJE
Puede que en muchas oportunidades, a lo largo de los captulos del libro, hayamos encontrado algunas trabas, o ejercicios con cierta complejidad. el caso de este captulo puede llegar a ser uno. La recomendacin es volver a repasar cada uno de los temas en los que hemos encontrado estas trabas para lograr una mejor comprensin.
312
www.redusers.com
Las estructuras
En las expresiones aritmticas es muy comn que usemos type cast. Si lo deseamos, podemos hacer uso de los parntesis para ayudarnos a leer la expresin. En una expresin relacional tambin podemos hacer uso de la enumeracin. Si comparamos hacia el mismo tipo no es necesario hacer uso de un type cast.
if(miDia == semana.Martes)
Pero en el caso que necesitemos realizar una comparacin hacia otro tipo, entonces s ser conveniente hacer utilizacin de type cast.
if((int)miDia==3)
Ejemplo de aplicacin
Ahora que ya conocemos los conceptos ms importantes de las enumeraciones, es momento de hacer una aplicacin. Nuestra aplicacin ser sencilla y simplemente probar los conceptos que hemos aprendido. Nuestra aplicacin puede quedar de la siguiente manera:
// Declaramos la enumeracin enum semana {Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo}; enum colores { Rojo = 1, Verde, Azul, Amarillo }; static void Main(string[] args)
www.redusers.com
313
9. ESTRUCTURAS Y ENUMERACIONES
{ int numerico = 0; // Creamos una variable de tipo semana semana miDia; // Asignamos un valor miDia = semana.Lunes; // Pasamos de enumeracin a entero numerico = (int)miDia; // Mostramos la informacin Console.WriteLine(El dia es {0} con valor {1}, miDia, numerico); // Creamos una variable de color colores miColor = colores.Rojo; // Pasamos a nmero entero numerico = (int)miColor; // Mostramos la informacin Console.WriteLine(El color es {0} con valor {1}, miColor, numerico); }
En primer lugar, declaramos dos enumeraciones. La primera es semana y Lunes tendr como valor 0. La segunda enumeracin se llama colores y la iniciaremos con un valor inicial Rojo que ser 1. Dentro de la funcin Main() declaramos una variable de tipo entero, que usaremos para nuestros experimentos de convertir las enumeraciones a valores numricos. Posteriormente, declaramos una variable de tipo semana llamada miDia. En la lnea siguiente le damos el valor de Lunes contenido en la enumeracin semana. A continuacin convertimos miDia a entero y se lo asignamos a la variable numrico. Luego mostramos los valores de las variables. Creamos una variable de tipo colores e inmediatamente le asignamos el valor de Rojo de la enumeracin colores. La convertimos a valor numrico y luego la mostramos. Si ejecutamos el programa, obtendremos la siguiente salida en la consola:
314 www.redusers.com
Las estructuras
Figura 10. Podemos ver cmo la variable tiene el valor de la enumeracin y su equivalente numrico.
Con esto ya hemos aprendido a lo largo de este captulo, en complemento con otros, las bases del manejo de las estructuras y las enumeraciones. Su uso es recomendable y debemos utilizarlas cuando tengamos programas grandes ya que nos ayudan a administrar la informacin y reducir la cantidad de errores.
RESUMEN
Las estructuras nos permiten crear un tipo nuevo y agrupar informacin que est relacionada adentro de una unidad. Los datos adentro de la estructura se llaman campos. Tambin es posible crear variables del tipo estructura y poder asignarles informacin a sus campos. El constructor nos ayuda a introducir la informacin original y a verificar que sea vlida. Las estructuras pueden estar enlazadas. En las enumeraciones nosotros creamos un tipo que tendr un nmero finito de valores posibles. Podemos darle un valor inicial a la enumeracin e incluso convertirla a valores numricos.
www.redusers.com
315
EJERCICIOS PRCTICOS
1 Crear una estructura para guardar los productos de una tienda.
316
www.redusers.com
C#
Captulo
10
Las clases
El componente principal de la programacin orientada a objetos es la clase. Nosotros podemos pensar en la clase como si fuera un plano por medio del cual podemos crear objetos, por ejemplo, pensemos en una casa. Para hacer una casa lo primero que hacemos es pensar en los cuartos que deseamos que tenga y luego diseamos un plano. El plano no es la casa, ya que no podemos vivir ni actuar en l. Sin embargo, ste nos proporciona las caractersticas de la casa. Por medio del plano podemos construir la casa y en esta construccin s podemos llevar a cabo nuestras actividades.
318 www.redusers.com
El plano sera equivalente a la clase y la casa construida al objeto. La clase es un plano, una descripcin, y el objeto tiene esas caractersticas y puede llevar a cabo trabajo concreto. Si necesitsemos hacer otra casa igual, no sera necesario hacer un nuevo plano, simplemente tomaramos el plano ya realizado y crearamos otra casa. Una clase nos puede servir para crear muchos objetos independientes pero que tienen las mismas caractersticas. El proceso de crear un objeto a partir de una clase es lo que conocemos como instanciacin. Adentro de la clase, nosotros colocaremos informacin y ms importante an, los mtodos que trabajan sobre esta informacin, es decir, que los datos y los mtodos que los procesan estn contenidos dentro de una sola unidad. A esto lo llamamos encapsulamiento. Al encapsular datos y mtodos los protegemos contra la corrupcin de informacin. Los objetos se comunicarn por medio del uso de mensajes. En estos mensajes es posible solicitarle un dato a otro objeto, pedirle que lleve a cabo un proceso, etctera.
Los datos
Los datos son la informacin con la que trabajar la clase. La clase solamente debe tener los datos que necesita para poder llevar a cabo su trabajo. Declarar un dato es muy similar a declarar una variable, pero al igual que en las estructuras, necesitamos indicar el acceso ya que tenemos bsicamente tres tipos de acceso: pblico, privado y protegido. Cuando nosotros tenemos un dato con acceso pblico cualquier elemento del exterior, como la funcin Main() o algn otro objeto, puede acceder al dato, leerlo y modificarlo. Cuando tenemos el acceso privado solamente los mtodos definidos dentro de la clase podrn leerlo o modificarlo. El acceso protegido es un poco ms avanzado y est por afuera de los lmites de este libro. Un punto muy importante con relacin a los datos que no debemos olvidar es que los datos definidos en la clase son conocidos por todos los mtodos de la misma clase. Es decir, actan como si fueran globales para la clase. Cualquier mtodo puede acceder a ellos directamente sin necesidad de que los pasemos como parmetro. En algunos casos podremos colocar el acceso a nuestros datos como pblico, aunque preferentemente no lo haremos. Si nos excedemos o usamos el acceso pblico en un mal diseo, corremos el riesgo de corrupcin de informacin. Por lo general,
LA HERENCIA
Es una caracterstica de la programacin orientada a objetos. sta permite crear una nueva clase que hereda las caractersticas (datos y mtodos) de otra clase, de forma tal que solamente tengamos que agregar los elementos necesarios para la nueva. Es una gran forma de reutilizacin de cdigo si se usa en forma adecuada.
www.redusers.com
319
nuestros datos sern privados, aunque esto puede parecer un problema ya que si el exterior necesita alguna informacin calculada por el objeto no podr tener acceso a ella. Para resolver esto hacemos uso de las funciones de interfaz. Una funcin de interfaz es aquella que puede ser invocada desde el exterior y que regresa una copia del valor de algn dato dentro del objeto. Tambin podemos usarla para colocar un valor determinado en un dato. La ventaja que nos da la funcin de interfaz es que podemos administrar el acceso a nuestra informacin, y podemos colocar dentro de sta cdigo de seguridad que verifique o valide la informacin que entra o sale. De esta forma evitamos la corrupcin de informacin.
Los mtodos
Los mtodos son las funciones que llevan a cabo el proceso o la lgica de la clase, y crear un mtodo dentro de la clase es muy parecido a la forma que hemos utilizado anteriormente. Los mtodos tambin tendrn un tipo de acceso, al igual que los datos. Trabajarn sobre los datos de la clase. No hay que olvidar que todos los mtodos conocen todos los datos definidos dentro de la clase, y pueden recibir parmetros y regresar valores. A un dato definido dentro de la clase no necesitamos pasarlo como parmetro ya que el mtodo lo conoce. Solamente los mtodos que necesiten ser invocados desde el exterior deben tener acceso pblico. Si el mtodo slo se invoca desde el mismo interior de la clase su acceso debe ser privado. Esto lo hacemos con fines de seguridad y para mantener el encapsulamiento correctamente.
320
www.redusers.com
El nombre de la clase puede ser cualquier nombre vlido dentro de C#. El nombre debe ser nico para el namespace, es decir no podemos tener dos clases que se llamen igual adentro del mismo namespace. La clase necesita un bloque de cdigo y en su interior llevamos a cabo las declaraciones de los elementos que la componen. Generalmente, declaramos primero los datos. Esto nos permite tener un programa organizado y luego facilita la lectura. Adems, es posible declarar los mtodos implementados antes. La mejor forma de hacer esto es por medio de un ejemplo. Supongamos que crearemos un programa que calcula el rea y el volumen de cubos y prismas rectangulares. Como en esta ocasin lo hacemos va programacin orientada a objetos, lo primero que hacemos es pensar en los objetos que componen el problema. Los objetos son: cubo y prisma rectangular. Ahora que ya conocemos los objetos, debemos pensar en los datos y las operaciones que se realizan sobre stos. Para el cubo necesitaremos como datos primordiales la longitud de su lado, el rea y su volumen. En el caso del prisma requerimos an ms datos, que son el ancho, el alto, el espesor, el rea y el volumen. Enseguida debemos pensar en las operaciones que se realizan sobre estos datos. El cubo es ms sencillo de resolver, ya que solamente necesitamos dos mtodos, uno llamado CalculaArea() y el otro llamado CalculaVolumen(). Para comprender mejor las clases y por motivos ilustrativos el prisma necesitar tres mtodos. El primero se llamar CalculaArea(), el segundo CalculaVolumen() y el tercero AreaRectangulo(). Como el rea del prisma es igual a la suma de los rectngulos de sus caras nos apoyaremos en este mtodo para calcularla. Podemos diagramar las clases si hacemos uso de UML. La clase del cubo quedar como se muestra en la siguiente figura:
Cubo + lado: int + rea: int + volumen: int + CalculaArea() : void + CalculaVolumen() : void
Figura 1. ste es el diagrama de clases para el cubo. Podemos ver todos los elementos que lo conforman.
www.redusers.com 321
Los diagramas anteriores se pueden leer fcilmente. Hay un rectngulo que representa a la clase. El rectngulo est dividido en tres secciones. La seccin superior, que es utilizada para colocar el nombre de la clase, la seccin intermedia, que se usa para indicar los datos que tendr la clase y la seccin inferior, que es para indicar cules son los mtodos a utilizar. El acceso se muestra por medio de los signos + o -. Cuando usamos el signo ms estamos indicando que ese dato o mtodo tiene un acceso del tipo pblico. En el caso de que coloquemos el signo menos, el acceso es del tipo privado. El formato de los datos lleva primero el acceso seguido del nombre del dato. Luego se coloca : y el tipo que tiene este dato. El tipo puede ser nativo o definido por el programador. En el caso de los mtodos, primero indicamos el acceso seguido del nombre del mtodo. Como ninguno de nuestros mtodos necesita parmetros, entonces los dejamos vacos. El tipo del mtodo, es decir el tipo de valor que regresa, se indica por medio de : seguido del tipo. En nuestro ejemplo hasta el momento ningn mtodo regresa algo, por lo que todos son de tipo void. Ahora podemos comenzar a declarar nuestras clases:
EL USO DE UML
UML es un lenguaje unificado de modelado, un lenguaje visual que nos sirve para llevar a cabo diagramas y modelado de sistemas. Resulta muy til en la programacin y el diseo orientado a objetos, ya que facilita el diseo y la depuracin de la aplicacin aun antes de que se escriba una lnea de cdigo. Es recomendable buscar informacin adicional sobre ste y aprenderlo.
322
www.redusers.com
class cubo { // Declaramos los datos public int lado; public int area; public int volumen; } class prisma { // Declaramos los datos public int ancho; public int alto; public int espesor; public int area; public int volumen; }
Como podemos observar, declaramos dos clases. En cada una hemos declarado los datos que le corresponden. La declaracin de los datos es muy similar a la declaracin de variables, y si prestamos atencin, podemos notar que ambas clases tienen nombres que se repiten en sus datos como area y volumen. Esto es posible porque cada clase es una entidad diferente, y estos nombres nunca se confundirn entre s. Continuemos con nuestra clase cubo. Ahora lo que necesitamos hacer es colocar los mtodos de la clase. Las operaciones son muy sencillas. Nuestra clase cubo quedar como se muestra en el siguiente bloque de cdigo:
class cubo { // Declaramos los datos public int lado; public int area; public int volumen; // Mtodo para calcular el rea public void CalculaArea() { area = (lado * lado) * 6; }
www.redusers.com
323
// Mtodo para calcular el volumen public void CalculaVolumen() { volumen = lado * lado * lado; } }
La declaracin de los mtodos se hace adentro del bloque de cdigo de la clase y cada uno de ellos tiene su propio bloque de cdigo. Como podemos observar, usan los datos directamente. Esto se debe a que cualquier dato declarado en la clase es conocido por todos los mtodos de esa clase. Ms adelante continuaremos con la clase prisma.
Quien realiza realmente la instanciacin es new y esa instancia queda referenciada como miCubo. A partir de miCubo podremos empezar a trabajar con l.
EL ACCESO PROTEGIDO
El acceso privado es utilizado cuando hacemos uso de la herencia. Si declaramos un dato como protegido, la propia clase y las clases que hereden de ellas podrn acceder a l, leerlo y modificarlo. Todas las dems clases lo vern como si su acceso fuera privado y no podrn acceder a l directamente.
324
www.redusers.com
operador punto. Por ejemplo, asignemos el valor de 5 al lado, realizando esto como vemos en el cdigo a continuacin:
miCubo.lado = 5;
www.redusers.com
325
// Mtodo para calcular el rea public void CalculaArea() { area = (lado * lado) * 6; } // Mtodo para calcular el volumen public void CalculaVolumen() { volumen = lado * lado * lado; } } class prisma { // Declaramos los datos public int ancho; public int alto; public int espesor; public int area; public int volumen; } class Program { static void Main(string[] args) { // Instanciamos a la clase cubo cubo miCubo = new cubo(); // Asignamos el valor del lado miCubo.lado = 5; // Invocamos los mtodos miCubo.CalculaArea(); miCubo.CalculaVolumen(); // Desplegamos los datos Console.WriteLine(Area={0}, Volumen={1}, miCubo.area, miCubo.volumen);
326
www.redusers.com
} }
Una de las ventajas que tiene la programacin orientada a objetos es la reutilizacin de cdigo. Si necesitramos dos cubos o ms, simplemente creamos nuevas instancias. Cada una de ellas tendra en su interior sus propias variables y podra llevar a cabo los clculos que fueran necesarios. Por ejemplo, modifiquemos el programa para que se tengan dos cubos. El segundo cubo estar en la instancia tuCubo y tendr un valor de lado de 8.
static void Main(string[] args) { // Instanciamos a la clase cubo cubo miCubo = new cubo(); cubo tuCubo = new cubo();
www.redusers.com
327
// Asignamos el valor del lado miCubo.lado = 5; tuCubo.lado = 8; // Invocamos los mtodos miCubo.CalculaArea(); miCubo.CalculaVolumen(); tuCubo.CalculaArea(); tuCubo.CalculaVolumen(); // Desplegamos los datos Console.WriteLine(Mi cubo Area={0}, Volumen={1}, miCubo.area, miCubo.volumen); Console.WriteLine(Tu cubo Area={0}, Volumen={1}, tuCubo.area, tuCubo.volumen); }
Este cambio solamente fue necesario en Main(), ya que todo el comportamiento que necesitamos se encuentra en la clase. Ejecutemos el programa y veamos el resultado.
Las propiedades son funciones de interfaz. Nos permiten acceder a los datos privados de una manera segura y controlada, pero van ms all de simples funciones ya que tambin nos brindan una forma de acceso intuitiva y sencilla. La propiedad puede ser de varios tipos: lectura, escritura y la combinacin de ambas(lectura-escritura). Una propiedad de lectura solamente nos permite leer el dato, pero no podemos agregarle informacin. Una propiedad que es de tipo escritura slo nos permite colocar informacin en el dato, pero no podemos leerlo. La propiedad de lectura-escritura permite llevar a cabo ambas acciones. Para lograr esto, la propiedad tendr dos mtodos. El mtodo relacionado con la lectura se conoce como get y el relacionado con la escritura es set. Dependiendo de cul mtodo coloquemos en la propiedad, ser su tipo. La propiedad de ste tiene la siguiente forma de declaracin:
public tipo nombre { get { return x;
www.redusers.com
329
} set { x=value; } }
Las propiedades son pblicas para poder llamarlas desde el exterior de la clase. El tipo est referenciado al tipo del valor que leer o colocar, ya sea entero, flotante, doble, etctera. En su interior tenemos get, donde colocamos el cdigo para sacar un valor de la clase por medio de return, y a set, donde ponemos el cdigo necesario para introducir un valor en la clase. Empecemos por crear propiedades para la clase prisma. Lo primero que tenemos que preguntarnos es a qu datos se necesita acceder por el exterior y qu tipo de acceso requieren. Podemos ver que los datos ancho, alto y espesor necesitarn de escritura, pero tambin de lectura. Esto es en caso de que necesitemos saber las dimensiones. A sus propiedades las llamaremos: Ancho, Alto y Espesor. Los otros datos que necesitan tener una propiedad son area y volumen, pero en este caso solamente necesitamos leerlos. No tiene sentido escribir sobre esos datos, ya que la clase calcular sus propios valores. Ahora que ya sabemos cules son las propiedades necesarias podemos decidir si es necesario algn tipo de validacin. Sabemos que no podemos tener prismas con cualquiera de sus lados con valor de 0 o negativos y se es un buen punto para validar. Si el usuario diera un valor incorrecto, entonces colocaremos por default el valor 1. Hay que recordar que esto lo hacemos como ejemplo y cada aplicacin puede tener sus propias reglas de validacin para la informacin. Cuando usemos el mtodo set tendremos una variable previamente definida por el lenguaje que se llama value. Esta variable representa el valor que el usuario asigna y podemos usarlo en la lgica que necesitemos. Nuestras propiedades de lectura y escritura quedan de la siguiente forma:
// Definimos las propiedades public int Ancho {
330
www.redusers.com
get { return ancho; } set { if (value <= 0) ancho = 1; else ancho = value; } } public int Alto { get { return alto; } set { if (value <= 0) alto = 1; else alto = value; }
www.redusers.com
331
} public int Espesor { get { return espesor; } set { if (value <= 0) espesor = 1; else espesor = value; } }
Como estas propiedades son de slo lectura nicamente llevan el mtodo get.
332 www.redusers.com
www.redusers.com
333
{ return (a * b); }
tangulo()
Los mtodos son muy sencillos, lo importante es notar que el mtodo CalculaRectiene acceso privado, por lo que nadie del exterior puede invocarlo. Sin embargo, CalculaArea() lo invoca sin problemas ya que pertenece a la misma clase.
En este ejemplo hacemos uso de la concatenacin para poder generar la cadena que el mtodo regresar. Hacemos esto para comparar con el uso de StringBuilder, que se
334 www.redusers.com
ha utilizado en el captulo donde hablamos de las estructuras. La concatenacin suele utilizarse para agrupar registros obtenidos de una base de datos. Podemos hacer uso de cualquiera de estos mtodos segn necesitemos de ellos. La impresin de los contenidos del objeto apoyndonos en este mtodo puede ser de la siguiente forma:
Console.WriteLine(miPrisma.ToString());
Si lo deseamos, podemos probar a ste en nuestro programa, y ver que obtendremos el resultado de la siguiente figura:
Figura 5. Podemos observar cmo hemos impreso los contenidos del objeto apoyndonos en el mtodo ToString().
Como observamos, el cdigo del mtodo es muy sencillo. Igualmente podemos probarlo en nuestra aplicacin y obtener el siguiente resultado en la consola.
Figura 6. Ahora podemos comparar la impresin con la ayuda de ToString() y del mtodo especializado.
Su primera caracterstica es que tiene el mismo nombre de la clase y su segunda caracterstica ms importante es que no tiene tipo, es decir, que no solamente no regresa nada, sino que no tiene tipo alguno. El constructor es invocado en forma automtica cuando el objeto es instanciado, ya que esto nos da la oportunidad de llevar a cabo cosas en el instante que se instancia el objeto, como por ejemplo, hacer inicializaciones. El constructor puede tener en su interior cualquier cdigo vlido de C# y tambin puede tener parmetros o no. Si utilizamos los parmetros tendremos que pasar los valores necesarios en el momento en el que instanciamos el objeto. Veamos un ejemplo de constructor para nuestra clase prisma. En este constructor no utilizaremos parmetros, veamos el siguiente ejemplo:
public prisma() { // Datos necesarios String valor=; // Pedimos los datos Console.WriteLine(Dame el ancho); valor=Console.ReadLine(); ancho=Convert.ToInt32(valor); Console.WriteLine(Dame el alto); valor=Console.ReadLine(); alto=Convert.ToInt32(valor); Console.WriteLine(Dame el espesor); valor=Console.ReadLine(); espesor=Convert.ToInt32(valor); }
www.redusers.com
337
Como podemos observar dentro del ejemplo, el constructor tiene acceso de tipo pblico. Esto es importante, ya que como se invoca automticamente, el exterior necesitar tener acceso a l. El constructor se encargar de solicitarle al usuario los datos necesarios. Cuando llevemos a cabo la instanciacin, ser de la siguiente forma:
prisma miPrisma = new prisma();
Figura 7. Podemos observar cmo se ejecuta el constructor y nos solicita los datos necesarios.
CONSTRUCTORES PRIVADOS
En las tcnicas avanzadas de programacin, como por ejemplo la programacin de patrones, podemos encontrar constructores privados. Uno de los patrones que lo utilizan se conoce como singleton . Generalmente, haremos uso de constructores pblicos hasta que aprendamos este tipo de tcnicas avanzadas.
338
www.redusers.com
Observemos cmo los valores fueron pasados al momento de la instanciacin. El valor 5 ser colocado en el dato ancho, 3 en el dato alto y 7 en el dato espesor. Si tenemos el dato contenido en una variable, tambin es posible utilizarla cuando instanciamos el objeto. Solamente debemos asegurarnos de que el tipo de la variable sea el mismo que el tipo del parmetro que colocamos. Si no fueran del mismo tipo, lo recomendable es utilizar type cast. Supongamos que tenemos lo siguiente:
int miNumero=11; prisma miPrisma4 = new prisma(5,3,miNumero);
Como vemos, pasamos una copia del valor de miNumero y ahora en el interior del objeto miPrimsa4 en dato espesor tendr el valor de 11.
www.redusers.com 339
Podemos continuar llevando a cabo ms sobrecargas del constructor, tantas como sean necesarias. La cantidad de sobrecargas depender del anlisis y las necesidades del programa. No debemos exagerar en las sobrecargas, debemos colocar solamente aquellas que sean realmente necesarias. El programa completo que tenemos luce de la siguiente manera:
class cubo { // Declaramos los datos public int lado; public int area; public int volumen; // Mtodo para calcular el rea public void CalculaArea() { area = (lado * lado) * 6; } // Mtodo para calcular el volumen public void CalculaVolumen() { volumen = lado * lado * lado; } } class prisma { // Declaramos los datos private int ancho; private int alto; private int espesor; private int area; private int volumen; // Definimos las propiedades public int Ancho { get
340
www.redusers.com
{ return ancho; } set { if (value <= 0) ancho = 1; else ancho = value; } } public int Alto { get { return alto; } set { if (value <= 0) alto = 1; else alto = value; } } public int Espesor { get { return espesor; }
www.redusers.com
341
set { if (value <= 0) espesor = 1; else espesor = value; } } public int Area { get { return area; } } public int Volumen { get { return volumen; } } // Definimos los constructores public prisma() {
342
www.redusers.com
// Datos necesarios String valor = ; // Pedimos los datos Console.WriteLine(Dame el ancho); valor = Console.ReadLine(); ancho = Convert.ToInt32(valor); Console.WriteLine(Dame el alto); valor = Console.ReadLine(); alto = Convert.ToInt32(valor); Console.WriteLine(Dame el espesor); valor = Console.ReadLine(); espesor = Convert.ToInt32(valor); } // Version sobrecargada public prisma(int pancho, int palto, int pespesor) { // Asignamos los valores ancho = pancho; alto = palto; espesor = pespesor; }
www.redusers.com
343
public void CalculaVolumen() { volumen = ancho * alto * espesor; } public void CalculaArea() { int a1 = 0, a2 = 0, a3 = 0; a1 = 2 * CalculaRectangulo(ancho, alto); a2 = 2 * CalculaRectangulo(ancho, espesor); a3 = 2 * CalculaRectangulo(alto, espesor); area = a1 + a2 + a3; } private int CalculaRectangulo(int a, int b) { return (a * b); } public override string ToString() { String mensaje = ; mensaje += Ancho + ancho.ToString() + Alto + alto.ToString() + Espesor + espesor.ToString(); mensaje += Area + area.ToString() + Volumen + volumen.ToString(); return mensaje; } public void ImprimeResultado() { Console.WriteLine(El rea es {0}, el volumen es {1}, area, volumen); } } class Program
344
www.redusers.com
{ static void Main(string[] args) { // Instanciamos a la clase cubo cubo miCubo = new cubo(); cubo tuCubo = new cubo(); // Instanciamos el prisma prisma miPrisma = new prisma(); // Instanciamos con la versin sobrecargada prisma miPrisma2 = new prisma(3, 5, 7); // Asignamos el valor del lado miCubo.lado = 5; tuCubo.lado = 8; // Invocamos los mtodos miCubo.CalculaArea(); miCubo.CalculaVolumen(); tuCubo.CalculaArea(); tuCubo.CalculaVolumen(); // Asignamos los valores al prisma // Quitar comentarios para versin sin constructor //miPrisma.Ancho = 10; //miPrisma.Alto = 3; //miPrisma.Espesor = 5; // Invocamos los mtodos del prisma miPrisma.CalculaArea();
www.redusers.com
345
miPrisma.CalculaVolumen(); miPrisma2.CalculaArea(); miPrisma2.CalculaVolumen(); // Desplegamos los datos Console.WriteLine(Mi cubo Area={0}, Volumen={1}, miCubo.area, miCubo.volumen); Console.WriteLine(Tu cubo Area={0}, Volumen={1}, tuCubo.area, tuCubo.volumen); Console.WriteLine(miPrisma.ToString()); miPrisma.ImprimeResultado(); Console.WriteLine(miPrisma2.ToString()); } }
Hemos escrito bastante cdigo para el funcionamiento de esta aplicacin. Ejecutemos el programa y nuestro resultado es el siguiente:
Si revisamos el cdigo que hemos presentado en el bloque anterior, podemos darnos cuenta del funcionamiento de las sobrecargas del constructor que hemos agregado, es importante reafirmar la idea que ya explicbamos en en prrafos anteriores, tenemos la posibilidad de agregar cuantas sobrecargas sean necesarias pero siemre debemos tener en cuenta la necesidad de no exagerar. A travs de este captulo hemos analizado la importancia del uso de clases para la generacin de nuestros programas, utilizando C#. Con esto hemos visto el inicio de los elementos para programar clases. An queda mucho por aprender sobre la programacin orientada a objetos y su programacin en C#, pero stos sern temas de un libro ms avanzado y especializado en la programacin del experto en el lenguaje C#.
RESUMEN
La programacin orientada a objetos es un paradigma de programacin diferente a la programacin estructurada. Tenemos que reconocer los objetos que componen el sistema as como la comunicacin que tienen entre ellos. La clase es el elemento fundamental de este tipo de programacin y acta como el plano sobre el que los objetos son construidos. Los objetos o las instancias son los que realmente llevan a cabo el trabajo. Los datos y los mtodos pueden tener diferentes tipos de acceso: pblico, privado o protegido. Las propiedades nos sirven como funciones de interfaz para poder acceder a los datos privados de forma segura. Las clases pueden tener un constructor que nos ayuda a inicializar la informacin. Es posible hacer uso de la sobrecarga en el constructor.
www.redusers.com
347
EJERCICIOS PRCTICOS
1 Crear el diseo de una clase para llevar el inventario de una tienda. 2 Crear una clase para llevar la informacin de los estudiantes de una escuela. 3 Crear una clase para polgonos con sobrecarga del constructor. 4 Crear propiedades para la clase polgono que solamente permitan colocar valores vlidos.
348
www.redusers.com
C#
Captulo
11
Flujos y archivos
A lo largo del libro hemos realizado muchos programas, y cada vez que usamos un programa, debemos introducirle informacin. Esto no ha sido un gran problema en los ejemplos realizados hasta aqu, porque generalmente manipulamos pocos datos. Sin embargo, en muchas aplicaciones reales necesitaremos tener alguna metodologa para poder guardar la informacin y recuperarla cuando la aplicacin se ejecute nuevamente. Para resolver esto, tenemos acceso a los archivos y los flujos.
Los flujos Los stream en la memoria El uso de archivos Resumen Actividades 350 351 363 371 372
LOS FLUJOS
Los flujos tambin son conocidos como streams por su nombre en ingls. Se los llama de esta forma porque nos recuerdan como fluye el agua, pero en este caso se tratar de flujos de informacin. El stream es utilizado para poder mover informacin de un lugar a otro. A veces, moveremos la informacin de la memoria a otra parte de la memoria, pero generalmente lo que haremos ser mover la informacin de la memoria a un dispositivo de almacenamiento como el disco duro o del dispositivo nuevamente a la memoria. Cuando hacemos uso de los flujos, la informacin no es enviada en un solo movimiento, sino que se enva byte por byte de forma ordenada. Como el envo es de esta forma, tenemos que tener cuidado sobre qu byte procesamos en ese momento.
O H
Figura 1. Los flujos nos permiten mover la informacin de un lugar a otro de la memoria, byte por byte.
Para poder tener control sobre el byte a enviar, imaginaremos que tenemos un apuntador o indicador en nuestro flujo. Este indicador siempre nos seala cul es el siguiente byte a enviar. Cada vez que enviamos un byte a su nuevo lugar por medio del flujo, el indicador se actualiza y nos seala el siguiente byte. Esta forma de trabajo funciona muy bien si el envo de datos es secuencial, pero tambin debemos tener un mecanismo que nos permita seleccionar a nosotros mismos el byte a enviar. Para hacer esto tenemos que indicar de alguna manera el byte y esto solamente lo podemos llevar a cabo si tenemos un punto de referencia dentro del flujo. En el flujo encontramos tres puntos de referencia. El primero es el inicio del flujo. Si queremos colocarnos en un byte en particular para enviar, simplemente tenemos que decir a cuntos bytes de distancia desde el inicio se encuentra el byte que deseamos procesar. El segundo punto de referencia ser el final del flujo. De manera similar tenemos que decir a cuntos bytes de distancia se encuentra el byte a procesar desde el final del flujo. El tercer punto de referencia es la posicin actual dentro del flujo, de igual forma a los casos anteriores, debemos dar la distancia desde nuestra posicin actual al byte que nos interesa procesar. En todos los casos, este byte se volver nuestro nuevo byte actual.
350 www.redusers.com
Los flujos
Desde final
Figura 2. Aqu vemos cmo un mismo byte del stream puede estar referenciado de formas diferentes.
Esta clase crea un stream, pero el lugar donde guarda la informacin es un sitio en memoria. La informacin es guardada como un arreglo de bytes sin signo. La clase MemoryStream tiene sobrecargado su constructor y seguramente podemos encontrar una versin de acuerdo con nuestras necesidades.El constructor puede crear el arreglo en la memoria vaco o puede inicializarlo a un tamao en particular. Hay que recordar que el tamao est en bytes.
www.redusers.com
351
Nosotros usaremos la versin en la que podemos indicar el tamao inicial del arreglo y para instanciar MemoryStream podemos hacerlo de la siguiente manera:
// Creamos el stream en memory // La iniciamos con una capacidad de 50 bytes MemoryStream ms = new MemoryStream(50);
El objeto se llama ms, pero puede tener cualquier nombre vlido de C#. El tamao inicial que le asignamos es 50 bytes.
Capacidad
Figura 3. En este diagrama podemos observar las tres propiedades del stream.
La capacidad nos indica cuntos bytes puede almacenar el stream. En el ejemplo anterior es de 50, ya que le hemos colocado ese tamao en su instanciacin. El valor de la capacidad se guarda en la propiedad Capacity y sta es de tipo entero. Si deseamos obtener la capacidad lo podemos hacer de la siguiente forma:
int capacidad = 0;
352
www.redusers.com
Los flujos
El siguiente dato que podemos obtener es la longitud. sta nos indica el tamao de la informacin actual que tiene el stream. El tamao est dado en bytes. La propiedad relacionada con esta informacin es Length. Esta propiedad es de tipo long. A continuacin veamos un ejemplo de cmo podemos obtener este dato:
long longitud = 0; ... ... longitud = ms.Length;
Por ltimo tenemos la posicin. Este dato es sumamente importante ya que nos indica el lugar donde se encuentra el byte actual, es decir el siguiente a ser procesado. Esta posicin est referenciada con relacin al inicio del stream. La propiedad para este dato se llama Position y al igual que la anterior tambin es de tipo long. La forma de obtener estos datos es similar a las anteriores.
long posicion = 0; ... ... posicion = ms.Position;
En este caso, indicamos que nos encontramos a 0 distancia desde el inicio del stream. Si lo que deseamos es encontrarnos a 10 bytes de distancia desde el inicio, la forma de usar Seek() es la siguiente:
ms.Seek(10, SeekOrigin.Begin);
Pero tambin podemos colocarnos desde otro punto de referencia. Por ejemplo, para colocarnos a 10 bytes de distancia desde el final del stream usaremos:
ms.Seek(-10, SeekOrigin.End);
Hay que observar que el valor usado es -10, ya que, como vimos anteriormente, en la plaqueta de la pgina 251, las distancias que se miden hacia la izquierda del punto de referencia son negativas. Por ltimo, si lo que deseamos es movernos con relacin a nuestra posicin actual, por ejemplo avanzar 5 bytes, lo que usaremos es:
ms.Seek(5, SeekOrigin.Current);
Y si lo que deseamos es retroceder 10 bytes desde nuestra posicin actual, usaremos el cdigo que veremos a continuacin:
ms.Seek(-10, SeekOrigin.Current);
354
www.redusers.com
Los flujos
En este caso lo llamamos bfer y tendr capacidad para 50 bytes. Supongamos que deseamos leer cinco bytes a partir de la posicin actual donde nos encontramos. Para ello hacemos uso de Read() de la siguiente manera:
ms.Read(buffer, 0, 5);
Despus de ejecutarse esta lnea, buffer contendr los cinco bytes ledos y los podemos encontrar al inicio de buffer.
www.redusers.com
355
el uso de este mtodo utilizaremos tres parmetros. En el primer parmetro tenemos que colocar el bfer o el arreglo de bytes desde el que tomaremos la informacin para colocarla en el stream. El segundo parmetro es la posicin en el stream desde donde empezaremos a escribir. Generalmente utilizaremos el valor de cero, y de esta forma empezar a escribirse desde el inicio del stream. El ltimo parmetro es la cantidad mxima de bytes que se escribirn. Un ejemplo prctico de esto es el siguiente:
// Escribimos los datos en la cadena ms.Write(miBuffer, 0, 15);
Programa de ejemplo
Ahora podemos crear un pequeo programa de ejemplo que utilice lo que hemos realizado con los streams. El programa ser sencillo, ya que nicamente nos interesa conocer y experimentar con el cdigo. Nuestro programa le pedir al usuario una cadena que ser colocada en el stream y luego podremos leer diferentes partes del stream con los mtodos que hemos aprendido. Como siempre, tenemos que empezar por definir las variables que son necesarias.
// Creamos el stream en memory // La iniciamos con una capacidad de 50 bytes MemoryStream ms = new MemoryStream(50); // Cadena con informacin String informacion = ; // Variables necesarias int capacidad = 0;
356
www.redusers.com
Los flujos
En primer lugar tenemos un objeto llamado ms que es de tipo MemoryStream y que puede guardar hasta 50 bytes en su interior. Luego creamos la cadena que utilizaremos para guardar la frase escrita por el usuario. Como experimentaremos con el stream creamos tres variables. Cada una de ellas se usa para guardar la capacidad, la longitud y la posicin, respectivamente. Al final creamos un arreglo de bytes llamado buffer y de tamao 50. Pedir los datos ser de la forma usual y no necesitamos explicarlo en este momento.
// El usuario da los datos Console.WriteLine(Dame la cadena para el flujo); informacion = Console.ReadLine();
Ahora que ya tenemos una cadena, podemos escribirla adentro del stream.
ms.Write(ASCIIEncoding.ASCII.GetBytes(informacion), 0, informacion.Length);
Lo primero que hacemos es obtener los bytes de la cadena, pero stos estarn codificados como ASCII. Luego indicamos que escribiremos en el stream desde su inicio. Por ltimo, indicamos la cantidad de bytes a escribir, que lo obtenemos por medio de la longitud de la cadena. Ahora mostraremos la informacin que podemos obtener sobre el stream.
// Obtenemos informacin de la cadena capacidad = ms.Capacity; longitud = ms.Length; posicion = ms.Position; // Mostramos la informacin Console.WriteLine(Capacidad {0}, longitud {1}, posicion {2}, capacidad, longitud, posicion);
Ahora podemos empezar a experimentar con stream. Nos colocaremos en diferentes posiciones y leeremos informacin desde ah. Empecemos por lo ms sencillo. Leeremos los primeros cinco bytes que se encuentran en el stream.
// Colocamos y leemos datos basndonos en el inicio ms.Seek(0, SeekOrigin.Begin); // nos colocamos a 0 distancia desde el inicio ms.Read(buffer, 0, 5); // desde donde nos encontramos, 5 caracteres // Mostramos la informacin Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer));
Lo primero que hacemos es usar el mtodo Seek(). Con este mtodo decimos que queremos encontrarnos a distancia cero desde el inicio del stream. Evidentemente sta es la primera posicin disponible. Como nuestra posicin actual ya est definida, procedemos a hacer uso del mtodo Read(). En este caso leemos cinco bytes desde donde nos encontramos. Los bytes ledos desde el stream ahora se encuentran guardados en el arreglo de bytes que llamamos bfer.
358 www.redusers.com
Los flujos
Para mostrar lo que acabamos de obtener usamos el mtodo WriteLine(), y como solamente tenemos una coleccin de bytes, debemos codificarlas adecuadamente con GetString(). La codificacin que deseamos es ASCII. En la consola aparecen los primeros cinco caracteres de la frase que escribimos.
Figura 5. Podemos observar que los primeros cinco caracteres son mostrados.
En el cdigo que veremos a continuacin, haremos una prueba, realizando otra lectura en una posicin diferente.
// Otra lectura desde el inicio ms.Seek(10, SeekOrigin.Begin); // nos colocamos a 10 distancia desde el inicio ms.Read(buffer, 0, 5); // desde donde nos encontramos, 5 caracteres Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer));
En este caso, por medio del mtodo Seek() nos posicionamos a 10 bytes de distancia desde que es iniciado el stream. Nuevamente procedemos a leer cinco bytes desde esa posicin que sern colocados en el buffer. Para poder comprobar que esto es ptimo y que funciona en forma adecuada lo mostramos en la consola.
www.redusers.com 359
Figura 6. En este caso podemos observar los bytes ledos desde la posicin donde nos encontramos.
Pero sabemos que no solamente podemos utilizar el inicio del stream como referencia para indicar la posicin actual. Ahora realizaremos otra prueba con el final del stream como punto de referencia.
// Lectura relativa al final del flujo ms.Seek(-10, SeekOrigin.End); // nos colocamos a 10 distancia desde el final ms.Read(buffer, 0, 5); // desde donde nos encontramos, 5 caracteres Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer));
Para este ejemplo usamos nuevamente el mtodo Seek(), pero con la diferencia que ahora indicaremos que el punto de referencia es el final del stream. Nuestra nueva posicin actual se encontrar a una distancia de diez bytes desde el final del stream. Por esta razn, vamos a colocar el valor -10 en el primer parmetro. Ya colocados en esta distancia simplemente procedemos a leer slo cinco bytes. Al final de la lectura mostramos lo que hemos obtenido en la consola.
360 www.redusers.com
Los flujos
Figura 7. Ahora observamos los bytes ledos con referencia al punto final del stream.
Debemos recordar que cuando se lleva a cabo una lectura o escritura en el stream, la posicin actual se modifica. La ltima posicin colocada explcitamente se encontraba a diez bytes del final del stream, pero despus de la lectura se ha modificado en cinco bytes. Comprobemos esto de forma sencilla:
// Obtenemos nuestra posicin actual posicion = ms.Position; Console.WriteLine(La posicion es {0}, posicion);
www.redusers.com
361
Simplemente obtenemos nuestra posicin actual y la mostramos en la consola. Esto lo podemos hacer en cada operacin y verificar cmo se altera la posicin actual. Desde nuestra nueva posicin actual podemos continuar leyendo.
// Lectura relativa desde la posicin actual ms.Read(buffer, 0, 5); // desde donde nos encontramos, 5 caracteres Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer));
Ahora no hemos utilizado el mtodo Seek() ya que deseamos continuar leyendo desde donde nos encontramos. Por ltimo, no debemos olvidar cerrar el stream.
// Cerramos el flujo, no olvidar ms.Close();
Los flujos
El uso de archivos
Como hemos aprendido, los streams no solamente funcionan en la memoria, sino que tambin nos pueden servir para mover informacin de la memoria a un dispositivo de almacenamiento masivo. Este dispositivo generalmente ser el disco duro. Nosotros podemos crear, escribir y leer archivos en el disco duro apoyndonos en los streams. En esta seccin del libro haremos dos programas, uno que escriba datos en el disco, y otro que los lea y los presente en la consola. Todas las operaciones que hemos aprendido para los streams sern vlidas y veremos que es sencillo llevar esto a cabo.
www.redusers.com
363
agregada al archivo sin modificar lo anterior. En el caso de que el archivo no exista, ser creado un nuevo archivo. El modo Truncate es especial y debemos tener cuidado con l ya que abre el archivo. Entonces, los contenidos se eliminan hasta que el archivo tenga una longitud de 0 bytes. Por ejemplo, podemos crear un stream a disco en modo de creacin, como podemos ver en el cdigo a continuacin:
FileStream fs = new FileStream(miTexto.txt, FileMode.Create);
El archivo a crear se llama miTexto.txt y ser creado en el mismo directorio que el ejecutable de nuestra aplicacin. El nombre del stream es fs y ya podemos llevar a cabo las operaciones necesarias sobre l.
El mtodo necesita tres parmetros, el primer parmetro es el arreglo de bytes que escribiremos, el segundo es la posicin a partir de donde empezaremos a escribir con respecto a nuestra posicin actual, y el ltimo parmetro nos sirve para indicar la cantidad de bytes que colocaremos. Es importante no olvidar que esta posicin se actualiza despus de hacer uso del mtodo Write(). En nuestro ejemplo a realizar vamos a suponer que una cadena ser escrita al archivo. A esta cadena la tenemos que colocar como un arreglo de bytes, pero stos deben estar codificados como ASCII, para lo cual usaremos la clase ASCIIEncoding. Para poder obtener los bytes de la cadena deberemos hacer uso del mtodo GetBytes() por el que se pasa la cadena escrita como parmetro. La cantidad de bytes que deseamos colocar ser la longitud de la cadena, que obtenemos al hacer uso de la propiedad Length.
Los flujos
Luego, podemos hacer uso de un ciclo do while, que se repetir constantemente hasta que el usuario d una cadena vaca. En el interior del ciclo llevaremos a cabo la peticin de la cadena y la escritura de sta a disco.
// Capturamos cadenas do { // Leemos la cadena del usuario cadena = Console.ReadLine(); // Escribimos al stream la cadena capturada fs.Write(ASCIIEncoding.ASCII.GetBytes(cadena), 0, cadena.Length); } while (cadena != );
namespace Cap11_2 { class Program { static void Main(string[] args) { // Variables necesarias String cadena = ; // Creamos el stream al archivo // Experimentar con append y create FileStream fs = new FileStream(miTexto.txt, FileMode.Create); // Capturamos cadenas do { // Leemos la cadena del usuario cadena = Console.ReadLine(); // Escribimos al stream la cadena capturada fs.Write(ASCIIEncoding.ASCII.GetBytes(cadena), 0, cadena.Length); } while (cadena != ); // Cerramos el stream fs.Close();
366
www.redusers.com
Los flujos
} } }
Una vez escrito el programa, slo nos queda compilar a ambos y ejecutarlos. Es posible escribir varias cadenas y luego simplemente presionar la tecla ENTER para finalizar. Toda la informacin que se ha escrito en el programa ser almacenada en el archivo. Luego con el Bloc de Notas podemos abrir el archivo y ver que efectivamente se encuentra la informacin que escribimos.
www.redusers.com
367
Figura 10. Con el bloc de notas podemos verificar que la informacin ha sido escrita.
368
www.redusers.com
Los flujos
Para esto creamos una instancia de la clase FileStream y la nombramos fs. En el constructor indicamos que nuestro archivo es miTexto.txt. Debemos notar que el modo del stream en este caso es Open ya que consideramos que el archivo existe y lo abriremos para trabajar con l. Como el archivo fue creado por el programa anterior, deberemos copiarlo de la carpeta donde se encuentra a la carpeta correspondiente de este proyecto. La ruta es similar, solamente que est referenciada a nuestro proyecto actual. Si no existe la carpeta Debug o Release, deberemos compilar nuestra aplicacin para que sean creadas. Hay que copiar el archivo antes de ejecutar el programa. Otra solucin es colocar el nombre del archivo a abrir con su ruta completa. Si el archivo que queremos abrir no existe o no est donde indicamos, el programa generar una excepcin. El siguiente paso consiste en leer los contenidos del archivo:
// Leemos el contenido del archivo fs.Read(infoArchivo, 0, (int)fs.Length);
El mtodo que utilizamos para la lectura es Read(). Este mtodo pertenece al stream. El primer parmetro que colocamos es el arreglo de bytes donde se guardarn los bytes ledos. En el segundo parmetro indicamos que leeremos desde el inicio del stream y por ltimo indicamos la cantidad de bytes a leer. En este caso leemos la totalidad de los bytes en el archivo, por eso indicamos como valor la longitud del stream. Con esto, ahora nuestro arreglo contiene una copia de los bytes del stream y desplegaremos la informacin en la consola como cadena.
// Mostramos el contenido leido Console.WriteLine(ASCIIEncoding.ASCII.GetString(infoArchivo));
www.redusers.com
369
Para mostrar la informacin tenemos que colocar los bytes como cadena y esta cadena tendr el formato ASCII. Para esto nos apoyamos nuevamente en ASCIIEncoding y el mtodo GetString(), y pasamos nuestro arreglo de bytes como parmetro. La escritura en consola es como siempre, por medio de WriteLine(). Para finalizar, debemos cerrar el stream de la forma habitual con el uso del mtodo Close().
// Cerramos el stream fs.Close();
namespace Cap11_3 { class Program { static void Main(string[] args) { // Variables necesarias byte[] infoArchivo = new byte[100]; // Creamos el stream de lectura FileStream fs = new FileStream(miTexto.txt, FileMode.Open); // Leemos el contenido del archivo fs.Read(infoArchivo, 0, (int)fs.Length); // Mostramos el contenido leido Console.WriteLine(ASCIIEncoding.ASCII.GetString(infoArchivo)); // Cerramos el stream fs.Close(); } } }
370
www.redusers.com
Los flujos
Ahora ya podemos compilar y ejecutar la aplicacin. En la consola podemos leer las cadenas que guardamos con el otro programa.
Figura 11. Podemos observar que nuestro programa efectivamente ha ledo la informacin del archivo.
Con esto hemos aprendido el trabajo bsico de los flujos y los archivos en C#. Tambin hemos llevado a cabo una serie de manipulaciones sobre los archivos.
RESUMEN
Los flujos o streams permiten mover informacin de un lugar a otro. Puede moverse entre diferentes partes de la memoria o entre la memoria y los dispositivos de almacenamiento. Para ello necesitamos el namespace System.IO para poder utilizarlo. Para trabajar correctamente con el stream podemos colocarnos en cualquier parte de ste referente al inicio, fin o posicin actual. Una vez en la posicin adecuada podemos llevar a cabo la lectura de los bytes en el stream. Una vez abierto el stream, y despus de trabajar con l, es necesario cerrarlo para liberar cualquier recurso utilizado. Los streams tambin se pueden utilizar para el acceso al disco con los archivos, podemos abrir el archivo de diferentes formas y llevar a cabo manipulaciones de los archivos como borrarlos, renombrarlos, copiarlos o moverlos.
www.redusers.com
371
EJERCICIOS PRCTICOS
1 Hacer un programa que genere un stream en la memoria y coloque la informacin de una cadena escrita por el usuario. Luego leer esa cadena en orden inverso y mostrarla. Es decir hola se mostrar como aloh. 2 Hacer un programa que le pida al usuario el nombre y la ruta de un archivo de texto a leer y muestre sus contenidos en la consola.
372
www.redusers.com
C#
Captulo
12
Depuracin
Hemos llegado al ltimo captulo del libro y en este captulo aprenderemos las tcnicas bsicas de depuracin. La depuracin es utilizada para corregir problemas en el programa. Algunas veces los programas tienen errores de sintaxis, pero principalmente de lgica. Al depurarlos podemos observar su comportamiento de mejor forma y detectar el comportamiento que est dando problemas.
Cmo empezar a depurar un programa Para corregir los errores de compilacin Cmo corregir los errores en tiempo de ejecucin Cmo manejar los errores Resumen Actividades
12. DEPURACIN
374
www.redusers.com
{ // Variables necesarias int a = 5 int b = 10; int c = 0; int r = 0; // Hacemos la division r = b / c; // Mostramos el resultado Console.WrteLine(El resultado es {},r); // Mostramos el resultado 5 veces for (int n = 0; n < 5; n++) { Console.WriteLine(El resultado es {0}, r); } // Invocamos la funcion MuestraValor(); } static void MuestraValor(int n) { Console.WriteLine(El resultado es {0}, n); } }
www.redusers.com
375
12. DEPURACIN
El programa tiene varios errores, algunos de ellos muy comunes, por lo que es importante aprender a reconocerlos y resolverlos. Para comenzar, lo primero que hacemos es llevar a cabo una compilacin. Si hay un error de compilacin, inmediatamente aparece una ventana. Esta ventana se conoce como lista de errores. Podemos observar esta ventana en la siguiente figura.
La ventana de la lista de errores contiene informacin importante que nos permite encontrar el error rpidamente. La lista tiene varias columnas. La primera columna nos indica si el elemento listado es un error o una advertencia. Esto depende del icono mostrado. Un icono con seal amarilla es una advertencia y el icono rojo un error. En la segunda columna tenemos el nmero secuencial de error. La tercera lnea es muy importante, ya que es una descripcin del error. Esta descripcin nos da pistas sobre la posible causa del error. La siguiente columna indica el documento en el cual ocurri el error. Esto es til cuando tenemos programas que se constituyen en varios documentos. Las dos siguientes lneas nos dicen el lugar donde est el posible error indicando la lnea y la columna. Un punto importante a tomar en cuenta es que la posicin es solamente un indicador. Nuestra ltima columna indica el proyecto en el cual ocurri el error, esto llega a ser til cuando tenemos aplicaciones con mltiples proyectos.
376 www.redusers.com
Si observamos el editor, veremos que hay texto que aparece con un subrayado rojo. Esto indica el texto que est relacionado con la lista de errores y facilita su localizacin. Empecemos a corregir los errores. La depuracin es un proceso iterativo, por lo que tenemos que ir corrigiendo errores hasta que no quede ninguno. En algunas ocasiones, cuando corrijamos un error aparecern listados nuevos errores. No debemos preocuparnos por esto y tenemos que continuar corrigiendo los errores listados hasta que no quede ninguno. Cuando corregimos los problemas de nuestro programa, debemos referirnos a la lista de errores. Siempre tenemos que empezar con el primer problema. Esto se debe a que a veces un error en la parte superior del programa puede ocasionar que lneas que sean correctas parezcan que tienen problemas. En la lista debemos dar doble clic al primer error. Esto nos lleva automticamente al cdigo y seala la parte con el problema. Esto lo podemos observar en el ejemplo que se muestra en la siguiente figura.
Figura 2. Podemos observar que la lnea donde se encuentra el problema ha sido sealada.
El problema sealado indica que se tiene una nueva lnea en una constante. Esto generalmente ocurre cuando usamos una cadena y olvidamos cerrarla. Si observamos la lnea veremos que efectivamente la cadena de formato no se ha cerrado. Procedamos a cerrar la cadena. De tal forma que la lnea quede de la siguiente forma:
www.redusers.com 377
12. DEPURACIN
Siempre que corregimos un problema, es bueno realizar una compilacin. Esto actualizar la lista de errores y podemos proceder con el siguiente. Despus de la compilacin nuestra lista de errores se ha reducido a nicamente dos. El siguiente error que corregiremos es muy comn. Si vemos la descripcin nos indica que se estaba esperando }. Este error ocurre cuando hemos olvidado cerrar un bloque de cdigo. Puede ser a nivel de namespace, clase, mtodo, ciclo, etc. La mejor forma de resolverlo es verificar nuestros bloques de cdigo y adicionar el cierre donde corresponde. En muchas ocasiones el cierre no necesariamente es donde lo seala el editor, por lo que se necesita revisar correctamente dnde colocar el cierre. En nuestro caso es muy sencillo y lo adicionamos al final. Ya cerrado el bloque de cdigo, podemos compilar y ver la lista de errores. Ahora nicamente nos aparece un error en la lista. Inicialmente tenamos cinco, hemos corregido dos y solo queda uno. Estos cambios en la cantidad de errores son muy comunes. Esto se debe a que los errores pueden suceder en cascada, como comentbamos, un error en la parte superior puede crear errores fantasma en otras partes. El error que tenemos que corregir en este momento es muy sencillo y ocurre cuando olvidamos terminar la sentencia con ;. Simplemente lo adicionamos en la lnea que corresponde. Al parecer ya hemos terminado de corregir los problemas. Compilemos y veamos qu sucede. Despus de corregir el ltimo error, han aparecido dos errores ms. Como mencionbamos la depuracin es iterativa y podemos pensar que el compilador hace varias pasadas. En este caso se nos presentan dos problemas en los mtodos. El primer error que tenemos nos indica que no se tiene una definicin para WrteLine. Este tipo de error ocurre generalmente en dos casos. El primero es cuando estamos intentando usar algo, ya sea mtodo, variable, objeto, etc. que no hemos definido. Para corregirlo simplemente definimos lo que necesitamos usar. El segundo caso es ms comn y se relaciona a un error de escritura, es decir que hemos escrito mal el nombre de lo que queremos utilizar y al no reconocerlo el compilador nos marca este error.
378
www.redusers.com
En nuestro ejemplo, el error est referenciado a un problema de escritura. Simplemente debemos ir al cdigo y escribir WriteLine de la forma correcta. Compilemos y continuamos con el siguiente error Nuevamente nos queda un error. Este error nos dice que no hay un mtodo sobrecargado. Este error suele pasar cuando tenemos una funcin o mtodo y estamos pasando una cantidad errnea de parmetros o los parmetros son de un tipo no correcto. En nuestro programa vemos que el mtodo MuestraValor() necesita de un parmetro, pero en la invocacin no se est pasando ningn valor y esto genera el problema. Para resolverlo simplemente debemos colocar el valor a pasar. Por ejemplo podemos colocar la lnea de la siguiente forma:
// Invocamos la funcion MuestraValor(a);
Ahora podemos compilar nuevamente. La ventana de salida nos indica que se ha compilado exitosamente la aplicacin. Esto significa que ya no tenemos errores de compilacin, pero an es posible tener errores en tiempo de ejecucin.
12. DEPURACIN
Figura 3. En cuanto el programa levanta una excepcin, finaliza su ejecucin de forma inesperada y nos presenta un dilogo con informacin.
Como vemos el programa ha levantado una excepcin. Para poder depurar el programa debemos ejecutarlo en modo de depuracin. Para esto seleccionamos el men de Debug o Depurar y presionamos Start Debugging.
Ya que nos encontramos en el depurador, el lugar donde se gener la excepcin aparece marcado en forma muy clara, y junto a l tendremos un cuadro de dilogo que contiene la informacin correspondiente.
Si observamos el cuadro de dilogo veremos que la excepcin, es decir el error, fue provocado por un intento de dividir entre cero. La divisin entre cero no est definida y por eso es una operacin invlida. Ahora que ya sabemos qu provoca el problema, simplemente podemos corregir el cdigo. Podemos pensar que la correccin es sencilla y simplemente dividir entre la variable que tiene un valor de cero, puede ser algo como lo que se muestra en el siguiente bloque de cdigo, a modo de ejemplo:
www.redusers.com
381
12. DEPURACIN
// Hacemos la division r = b / a;
Si procedemos con la compilacin, no aparece ningn problema, pero veamos qu sucede cuando ejecutemos nuevamente el programa.
El programa nuevamente tiene problemas de ejecucin. Si observamos la informacin que nos provee el depurador inmediatamente nos damos cuenta de que la excepcin ha ocurrido porque no estamos colocando el formato correcto en la cadena. Al ver la lnea de cdigo podemos identificar que efectivamente el formato es incorrecto, la lnea con el formato adecuado debe ser como la siguiente:
// Mostramos el resultado Console.WriteLine(El resultado es {0},r);
Despus de corregir, nuevamente debemos compilar y ejecutar. Todo debe estar bien y el programa puede ejecutarse sin problema. El resultado lo vemos en el ejemplo que se muestra en la siguiente figura:
382 www.redusers.com
Figura 7. El programa por fin se ejecuta y podemos ver en la consola los resultados.
Ya vimos cmo localizar el cdigo que nos genera excepciones. Pero lo mejor sera poder evitarlas o controlarlas de alguna manera.
12. DEPURACIN
using System; using System.Collections.Generic; using System.Text; namespace Cap12_2 { class Program { static void Main(string[] args) { // Variables necesarias int a = 5; int b = 10; int c = 0; int r = 0; // Pedimos el dato al usuario Console.WriteLine(Dame el valor del divisior); a = Convert.ToInt32(Console.ReadLine()); // Hacemos la division r = b / a; // Mostramos el resultado Console.WriteLine(El resultado es {0}, r);
// Mostramos el resultado 5 veces for (int n = 0; n < 5; n++) { Console.WriteLine(El resultado es {0}, r); } // Invocamos la funcion MuestraValor(a); } static void MuestraValor(int n) {
384
www.redusers.com
Veamos cmo este programa puede ejecutarse correctamente a veces y con problemas en otros casos. Si ejecutamos el programa y damos como valor 5, el programa se ejecuta correctamente. Cuando ejecutemos el programa nuevamente, si el valor que damos es cero, entonces la excepcin ocurrir. Esto lo vemos claramente en las dos figuras que se mostrarn a continuacin. Es sencillo saber qu mtodos pueden generar excepciones. Simplemente debemos ir a MSDN y buscar la documentacin del mtodo a utilizar. Dentro de esta documentacin hay una seccin que describe las posibles excepciones que pueden ocurrir. De esta forma hacemos que nuestro programa las evite.
Para llevar a cabo la administracin de excepciones vamos a tener tres bloques de cdigo conocidos como: try, catch y finally.
www.redusers.com 385
12. DEPURACIN
Lo primero que tenemos que hacer es detectar dnde se encuentra el cdigo peligroso, es decir, dnde puede ocurrir la excepcin. En nuestro caso es fcil de identificar ya que sabemos que es la divisin.
Figura 9. Ahora podemos observar cmo la excepcin se ha levantado y el programa finaliza su ejecucin.
El cdigo que tiene el riesgo de levantar la excepcin debe ser colocado en el bloque de try. Por ejemplo, en nuestro caso colocaremos lo siguiente:
// Codigo peligroso, lo colocamos en try para administrar la excepcion
386
www.redusers.com
El cdigo adentro de try tiene dos opciones: levantar o no la excepcin. Si la excepcin se levanta entonces en el bloque de catch podemos colocar el cdigo que se encargue de evitar que el programa termine inesperadamente. Aqu podemos poner cdigo que corrija lo ocurrido. En nuestro caso, no hay mucho que hacer, simplemente podemos enviar un mensaje al usuario y dar un valor adecuado a la variable de resultado.
catch (Exception e) { // Aqui colocamos el codigo que salva la a plicacion Console.WriteLine(No es posible dividir entre cero); r = 0; }
Vemos que este bloque tiene un parmetro llamado e. Adentro de este parmetro podemos encontrar informacin relacionada con la excepcin. Lo que coloquemos en el interior del bloque depende de la lgica de nuestra aplicacin. Si no hubiera excepcin el cdigo adentro del bloque catch no se ejecuta. Tenemos otro bloque llamado finally. Este bloque es opcional. El cdigo que se coloque en el bloque finally se ejecuta siempre sin importar si la excepcin se llev a cabo o no. Siempre se ejecuta una vez que try o catch han finalizado de ejecutarse. Finally puede ser utilizado para limpiar o liberar cualquier recurso que se haya utilizado en try o catch. En nuestro caso puede utilizarse simplemente para darle al usuario el valor del resultado.
finally { // Mostramos el resultado Console.WriteLine(El resultado es {0}, r); }
www.redusers.com
387
12. DEPURACIN
388
www.redusers.com
// Mostramos el resultado 5 veces for (int n = 0; n < 5; n++) { Console.WriteLine(El resultado es {0}, r); } // Invocamos la funcion MuestraValor(a); } static void MuestraValor(int n) { Console.WriteLine(El resultado es {0}, n); } } }
Veamos si esto funciona adecuadamente. Compilemos el programa y al ejecutarlo vamos a dar el valor de cero. El programa ahora no deber generar problemas, pues hemos capturado la excepcin y ejecutado cdigo que evita que el programa finalice de forma no adecuada.
RESUMEN
La depuracin nos permite corregir los problemas que pueda tener nuestro programa. Los errores de compilacin impiden que el programa pueda ser compilado y muchas veces son simples errores de sintaxis. Tenemos una ventana que nos muestra la lista de errores, siempre debemos corregir el primer error de la lista, ya que muchos errores se generan en cascada. La depuracin es un proceso iterativo. Si tenemos cdigo peligroso que puede generar excepciones, es recomendable administrar ese cdigo para evitar que la excepcin termine con nuestro programa, cuando administramos la excepcin, podemos colocar cdigo que salve al programa.
www.redusers.com
389
EJERCICIOS PRCTICOS
1 Usar la depuracin paso a paso para observar cmo cambia el valor de la variable en el programa del factorial. 2 Utilizar el mtodo WriteLine() de la clase Debug para que las funciones nos indiquen cuando entramos y salimos de ellas. 3 Buscar en MSDN cules son las excepciones que pueden ocurrir con los arreglos.
390
www.redusers.com
C#
Servicios al lector
En este ltimo apartado encontraremos un ndice temtico con las palabras ms significativas de esta obra. Una gua que nos servir para encontrar con mayor facilidad el contenido que necesitamos.
SERVICIOS AL LECTOR
NDICE TEMTICO
#
.NET 16 bits 15 16 Catch Char Chars Ciclos Ciclos enlazados 319 319 319 123 219 33 14 363 262 262 218 196 189 188 364 364 16, 17 CIL Clase Clases Clear() CLR CLS Colecciones COM Comentarios Compare() Compilador Concatenar Console Console Application Constructor Contador Contains() ContainsValue() Convert 14 353 34 46 44 359 24 44/350 350 D.O.S. CopyTo() Count Cpp Create CreateNew CultureInfo Current 387 44 261 111 198 16, 17 23 318 236, 245 15 16 218 15 45, 46 263 15 260 27, 35 20 238 123 236, 244, 264 252 57 267 245 21 363 363 274 353
A
Acceso privado Acceso protegido Acceso pblico Acumulador Add() Algoritmo API Append Append() AppendFormat() ArrayList Arreglos de dos dimensiones Arreglos de una dimensin Arreglos ASCII ASCIIEncoding Assembly
B
Basic Begin Bloque de cdigo Bloque de comentarios Bool Buffer Build Byte Bytes
D
25 257 324 25 44 DateTime
C
C++ Cadenas Case 392 14 256 105
www.redusers.com
ndice temtico
Decrementos Depuracin Depurar Dequeue Diagnostics Diagrama de flujo Disyuncin Do while Double
125 373 25 242, 244 389 61 98 134 44, 51 If If anidados If-else Incrementos Indentacin IndexOf() 84 319 353 266 242 309 264 38 38 299 380 21 96 LastIndexOf() Length LIFO Lnea de comandos Long 241 363 369 387 45, 51 350 112 225 257 15 147, 148, 156 Main() Math Matriz MemoryStream Mtodos Mono MSDN Multiplataforma Jagged Java Jitter Insert() Instanciacin Int Hashtable Herencia
H
218, 249 319
I
76 89 84 125 92 224 222, 268 319 43, 44
E
Else Encapsulamiento End EndsWith() Enqueue Enumeraciones Equals() Errores de lgica Errores de sintaxis Estructuras enlazadas Excepciones Explorador de soluciones Expresiones lgicas
J
205 14 17
L
269 262 232 25 45
F
FIFO FileMode FileStream Finally Float Flujos For Foreach Format Framework .NET Funciones
M
23, 28 22 196 351 147 18 57 16
N G
Get GetBytes() 329 364 Namespace Not Now 22 96 257 393
www.redusers.com
SERVICIOS AL LECTOR
O
Open OpenOrCreate Operador Operador de asignacin Operadores Orientado a objetos Override OWL 363 363 49 45 73 34 287, 297 14
272 232 149, 154 350 45, 256 261 265 105 364
P
PadLeft() PadRight() Paso por copia Paso por referencia Passport Peek() Pop Private Proceso Proteccin de datos Proyecto Public Push 270 271 178 178 18 244 233, 235 281 62 329 19 281 233 Tipo Toint32() ToLower() ToSingle() ToString() ToUpper() Trim() TrimEnd() TrimStart() Truncate Try Type Cast
T
43 57 273 58 256 274 275 276 276 363 387 312
U R
ReadLine() Recolector de basura Recursin RemoveAt() Replace() Runtime 56, 172 17 183 223 271 14 Variable Uint Uling UML Ushort Using 45 45 321 45 22
V
42 28 14 18 Vista de clases
S
Sbyte Seek() SeekOrigin Set SetValue() Singleton Solucin 394 44 354 353 329 239 338 20
W
While Write() WriteLine 141 41 35
www.redusers.com
>> Vea informacin ms detallada sobre cada libro de este catlogo. >> Obtenga un captulo gratuito para evaluar la posible compra de un ejemplar. >> Conozca qu opinaron otros lectores. >> Compre los libros sin moverse de su casa y con importantes descuentos. >> Publique su comentario sobre el libro que ley. >> Mantngase informado acerca de las ltimas novedades y los prximos lanzamientos.
usershop.redusers.com
PHP 6
Este libro es un completo curso de programacin en PHP en su versin 6.0. Un lenguaje que se destaca tanto por su versatilidad como por el respaldo de una amplia comunidad de desarrolladores lo cual lo convierte en un punto de partida ideal para quienes comienzan a programar.
> COLECCIN: MANUALES USERS > 368 pginas / ISBN 978-987-663-039-9
Access
Este manual nos introduce de lleno en el mundo de Access para aprender a crear y administrar bases de datos de forma profesional. Todos los secretos de una de las principales aplicaciones de Ofce, explicados de forma didctica y sencilla.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-663-025-2
Redes Cisco
Este libro permitir al lector adquirir todos los conocimientos necesarios para planicar, instalar y administrar redes de computadoras. Todas las tecnologas y servicios Cisco, desarrollados de manera visual y prctica en una obra nica.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-663-024-5
Dreamweaver y Fireworks
Esta obra nos presenta las dos herramientas ms poderosas para la creacin de sitios web profesionales de la actualidad. A travs de procedimientos paso a paso, nos muestra cmo armar un sitio real con Dreamweaver y Fireworks sin necesidad de conocimientos previos.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-663-022-1
Excel revelado
Este manual contiene una seleccin de ms de 150 consultas de usuarios de Excel y todas las respuestas de Claudio Snchez, un reconocido experto en la famosa planilla de clculo. Todos los problemas encuentran su solucin en esta obra imperdible.
> COLECCIN: MANUALES USERS > 336 pginas / ISBN 978-987-663-021-4
Robtica avanzada
Esta obra nos permitir ingresar al fascinante mundo de la robtica. Desde el ensamblaje de las partes hasta su puesta en marcha, todo el proceso est expuesto de forma didctica y sencilla para as crear nuestros propios robots avanzados.
> COLECCIN: MANUALES USERS > 352 pginas / ISBN 978-987-663-020-7
usershop@redusers.com
usershop.redusers.com
Windows 7
En este libro, encontraremos las claves y los secretos destinados a optimizar el uso de nuestra PC tanto en el trabajo como en el hogar. Aprenderemos a llevar adelante una instalacin exitosa y a utilizar todas las nuevas herramientas que incluye esta versin.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-663-015-3
De Windows a Linux
Esta obra nos introduce en el apasionante mundo del software libre a travs de una completa gua de migracin, que parte desde el sistema operativo ms conocido: Windows. Aprenderemos cmo realizar gratuitamente aquellas tareas que antes hacamos con software pago.
> COLECCIN: MANUALES USERS > 336 pginas / ISBN 978-987-663-013-9
Webmaster profesional
Esta obra explica cmo superar los problemas ms frecuentes y complejos que enfrenta todo administrador de sitios web. Ideal para quienes necesiten conocer las tendencias actuales y las tecnologas en desarrollo que son materia obligada para dominar la Web 2.0.
> COLECCIN: MANUALES USERS > 336 pginas / ISBN 978-987-663-011-5
Silverlight
Este manual nos introduce en un nuevo nivel en el desarrollo de aplicaciones interactivas a travs de Silverlight, la opcin multiplataforma de Microsoft. Quien consiga dominarlo crear aplicaciones visualmente impresionantes, acordes a los tiempos de la incipiente Web 3.0.
> COLECCIN: MANUALES USERS > 352 pginas / ISBN 978-987-663-010-8
Flash extremo
Este libro nos permitir aprender a fondo Flash CS4 y ActionScript 3.0 para crear aplicaciones web y de escritorio. Una obra imperdible sobre uno de los recursos ms empleados en la industria multimedia, que nos permitir estar a la vanguardia del desarrollo.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-663-009-2
Hackers al descubierto
Esta obra presenta un panorama de las principales tcnicas y herramientas utilizadas por los hackers, y de los conceptos necesarios para entender su manera de pensar, prevenir sus ataques y estar preparados ante las amenazas ms frecuentes.
> COLECCIN: MANUALES USERS > 352 pginas / ISBN 978-987-663-008-5
Vista avanzado
Este manual es una pieza imprescindible para convertirnos en administradores expertos de este popular sistema operativo. En sus pginas haremos un recorrido por las herramientas fundamentales para tener mximo control sobre todo lo que sucede en nuestra PC.
> COLECCIN: MANUALES USERS > 352 pginas / ISBN 978-987-663-007-8
Seguridad PC
Este libro contiene un material imprescindible para proteger nuestra informacin y privacidad. Aprenderemos cmo reconocer los sntomas de infeccin, las medidas de prevencin por tomar, y nalmente, la manera de solucionar los problemas.
> COLECCIN: MANUALES USERS > 336 pginas / ISBN 978-987-663-004-7
usershop@redusers.com
usershop.redusers.com
Mtodos giles
Este libro presenta una alternativa competitiva a las formas tradicionales de desarrollo y los ltimos avances en cuanto a la produccin de software. Ideal para quienes sientan que las tcnicas actuales les resultan insucientes para alcanzar metas de tiempo y calidad.
> COLECCIN: DESARROLLADORES > 336 pginas / ISBN 978-987-1347-97-1
SuperBlogger
Esta obra es una gua para sumarse a la revolucin de los contenidos digitales. En sus pginas, aprenderemos a crear un blog, y profundizaremos en su diseo, administracin, promocin y en las diversas maneras de obtener dinero gracias a Internet.
> COLECCIN: MANUALES USERS > 352 pginas / ISBN 978-987-1347-96-4
UML
Este libro es la gua adecuada para iniciarse en el mundo del modelado. Conoceremos todos los constructores y elementos necesarios para comprender la construccin de modelos y razonarlos de manera que reejen los comportamientos de los sistemas.
> COLECCIN: DESARROLLADORES > 320 pginas / ISBN 978-987-1347-95-7
Ethical Hacking
Esta obra expone una visin global de las tcnicas que los hackers maliciosos utilizan en la actualidad para conseguir sus objetivos. Es una gua fundamental para obtener sistemas seguros y dominar las herramientas que permiten lograrlo.
> COLECCIN: MANUALES USERS > 320 pginas / ISBN 978-987-1347-93-3
Esta obra nos permitir ingresar al fascinante mundo de la robtica. Desde el ensamblaje de las partes hasta su puesta en marcha, todo el proceso est expuesto de forma didctica y sencilla para as crear nuestros propios robots avanzados.
CONTENIDO
1 | C# Y .NET Programacin para Windows / Comprender .NET / Compilador de C# / El ambiente de desarrollo 2 | LOS ELEMENTOS BSICOS DE UN PROGRAMA Lenguajes / Errores en los programas / Las variables / Comentarios / Precedencia de operadores / Pedido de datos 3 | EL PROGRAMA TOMA DECISIONES La toma de decisiones / Expresiones y operadores relacionales / El uso de if y else / If anidados / Escalera de if-else / Expresiones lgicas / El uso de switch 4 | CREACIN DE CICLOS El ciclo for / El valor de inicio / Lmite de conteo / Control de incremento / El contador y el acumulador / Incrementos y decrementos / El ciclo while y do while 5 | FUNCIONES Y MTODOS Las funciones / Tipos de funciones / Optimizar con funciones / Pasaje de parmetros por copia y paso por referencia 6 | LOS ARREGLOS Declaracin de arreglos / Asignacin y uso de valores / Acceso a arreglos / Arreglos de tipo jagged 7 | LAS COLECCIONES ArrayList / Declaracin / Agregar informacin / El ciclo foreach / Stack / Queue / Hashtable 8 | LAS CADENAS El mtodo ToString() / StringBuilder / Justificacin del texto / Intercambio entre maysculas y minsculas 9 | ESTRUCTURAS Y ENUMERACIONES Definicin / Crear variables del nuevo tipo / Acceso a la estructura / Creacin de un constructor 10 | CMO CREAR NUESTRAS PROPIAS CLASES Programacin orientada a objetos / Clases / Datos / Mtodos / Proteccin de datos / Mtodos pblicos y privados CAPTULO 11: FLUJOS Y ARCHIVOS Los flujos / Streams en memoria / Uso de archivos CAPTULO 12: DEPURACIN Cmo depurar un programa / Errores de compilacin / Errores en tiempo de ejecucin / Manejo de errores / Errores de lgica / Detener la ejecucin
C#
Este libro es un completo curso de programacin en C#, actualizado a la versin 4.0, incluida en Visual Studio 2010. Es ideal tanto para quienes desean migrar a este potente lenguaje, como para quienes quieran aprender a programar, incluso, sin tener conocimientos previos. C# es el lenguaje ms utilizado en la actualidad, por ser poderoso, flexible y robusto. En esta obra cubriremos desde las bases de la programacin estructurada hasta los fundamentos de la orientada a objetos, sin dejar de aprender el manejo de estructuras complejas, como los archivos y las clases. Nicols Cosio aporta su vasta experiencia y la didctica comprobada de sus obras previas, para facilitar al lector la tarea de comprender cmo se logra desarrollar cdigo optimizado destinado a obtener aplicaciones poderosas y eficientes. Una obra imprescindible para fundar bases slidas en el desarrollo y aprender a programar de la mejor manera.
En este sitio encontrar una gran variedad de recursos y software relacionado, que le servirn como complemento al contenido del libro. Adems, tendr la posibilidad de estar en contacto con los editores, y de participar del foro de lectores, en donde podr intercambiar opiniones y experiencias.
Si desea ms informacin sobre el libro puede comunicarse con nuestro Servicio de Atencin al Lector: usershop@redusers.com
C# 2010
This book is a full C# learning course. Aimed for those who want to migrate to this language, as well as for those who want to learn programming, even if they do not have previous knowledge on the subject.
NIVEL DE USUARIO
PRINCIPIANTE INTERMEDIO AVANZADO EXPERTO