0 évaluation0% ont trouvé ce document utile (0 vote)
159 vues240 pages
Este documento presenta una introducción a la programación orientada a objetos en C# para un curso universitario. Explica los objetivos de enseñar programación, los temas cubiertos como resolución de problemas, programación orientada a objetos y algoritmos. También incluye definiciones clave como problema, objeto e instancia, y describe estrategias para la resolución de problemas como diagramas UML y árboles de decisión, ilustrando con ejemplos.
Este documento presenta una introducción a la programación orientada a objetos en C# para un curso universitario. Explica los objetivos de enseñar programación, los temas cubiertos como resolución de problemas, programación orientada a objetos y algoritmos. También incluye definiciones clave como problema, objeto e instancia, y describe estrategias para la resolución de problemas como diagramas UML y árboles de decisión, ilustrando con ejemplos.
Este documento presenta una introducción a la programación orientada a objetos en C# para un curso universitario. Explica los objetivos de enseñar programación, los temas cubiertos como resolución de problemas, programación orientada a objetos y algoritmos. También incluye definiciones clave como problema, objeto e instancia, y describe estrategias para la resolución de problemas como diagramas UML y árboles de decisión, ilustrando con ejemplos.
Material preparado por Rodrigo Sandoval U en Marzo 2004
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE
ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN
Introduccin a la Programacin Orientada a Objeto en C#
Introduccin a la Programacin (Orientada a Objetos) Rodrigo Sandoval U. IIC 1102 Pgina: 1 Introduccin La presente documentacin contiene la materia vista en el curso IIC1102, Introduccin a la Programacin, dictado por el Departamento de Ciencia de la Computacin, de la Escuela de Ingeniera de la Pontificia Universidad Catlica de Chile, particularmente en su versin Orientada a Objeto, del ao 2004. Por qu ensear programacin? Dentro de una formacin cientfica-analtica, hay tres objetivos principales que se persiguen con este curso. Primero, desarrollar las habilidades de los alumnos para resolver problemas de complejidad ms avanzada. Es adecuado adquirir la capacidad de analizar un problema, luego descomponerlo en partes, para finalmente describir una solucin con detalle. Esencialmente se fomenta el desarrollo de un pensamiento lgico, que posteriormente resulta en un importante aporte en las habilidades organizacionales. En segundo lugar, dar a los alumnos una nocin del potencial y limitaciones de la tecnologa computacional. Aprender a programar es una de las maneras ms efectivas de lograr un contacto profundo con los computadores que hoy forman parte importante de la sociedad. Esto permite lograr el efecto de entender que no es el computador lo ms importante, sino que la inteligencia que el programador y usuarios eficiente aportan. Finalmente, escribir programas y disear soluciones debe ser entretenido. No debe menospreciarse la sensacin de satisfaccin que se logra al completar un interesante y desafiante proyecto de programacin. Qu incluye este curso? Este curso aborda temas tan extensos como La Resolucin de Problemas, donde se analizan estrategias metodolgicas que permiten analizar un problema y plantear una solucin estructurada, as como detalles sintcticos de la programacin en el lenguaje C#, que forma parte de la plataforma .NET de Microsoft. En el proceso, diversos captulos se enfocan en problemticas puntuales que son cubiertas de una u otra manera por los diferentes lenguajes de programacin, pero que en esta ocasin se revisan en funcin de C#. Destaca tambin un fuerte nfasis en la revisin de algoritmos de resolucin de problemas especficos, como son los captulos de Algoritmos Numricos, Recursividad, Ordenamiento y Bsqueda.
Material preparado por Rodrigo Sandoval U en Marzo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.al Los ejemplos fueron adaptados por MSR Lab del DCC de la Escuela de Ingeniera de la P. Universidad Catlica de Chile
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo I - Resolucin de Problemas
1 CONCEPTOS DE RESOLUCIN DE PROBLEMAS.................................................................................... 1 1.1 EL PROCESO DE RESOLUCIN DE PROBLEMAS.................................................................................................1 1.2 DEFINICIONES.................................................................................................................................................1 1.2.1 Problema................................................................................................................................................ 1 1.2.2 Objeto..................................................................................................................................................... 2 1.2.3 Instancia................................................................................................................................................. 2 1.2.4 Modelo ................................................................................................................................................... 2 1.3 ALGORITMOS..................................................................................................................................................2 1.3.1 Qu es un Algoritmo?........................................................................................................................... 2 1.3.2 Cmo se especifican o describen los algoritmos?................................................................................ 3 1.3.3 Existe un nico algoritmo de solucin? ............................................................................................... 3 1.3.4 Qu es una metodologa?..................................................................................................................... 3 1.3.5 Las soluciones tambin pueden tener problemas ................................................................................... 4 2 ORIENTACIN A OBJETOS ........................................................................................................................... 5 2.1 TERMINOLOGA BSICA DE LA PROGRAMACIN ORIENTADA A OBJ ETO ........................................................6 3 ESTRATEGIAS PARA LA SOLUCIN DE PROBLEMAS.......................................................................... 7 3.1 METODOLOGA DE RESOLUCIN DE PROBLEMAS............................................................................................7 3.2 DESCRIPCIN GRFICA DE SOLUCIONES.........................................................................................................8 3.2.1 Diagrama de Casos de Uso - UML........................................................................................................ 8 3.2.2 Diagrama de Clases UML................................................................................................................... 9 3.2.3 rboles de Decisin ............................................................................................................................. 10 3.2.4 Ejemplo: rbol de Decisin: Qu hago el sbado por la noche?...................................................... 10 3.3 EJ EMPLOS DE APLICACIN DE LA METODOLOGA.........................................................................................11 3.3.1 Simulando la Ejecucin de un Penal.................................................................................................... 11 3.3.2 Simulando la preparacin de un pastel................................................................................................ 14 3.3.3 Cambio de neumtico desinflado ......................................................................................................... 16 3.3.4 Llamada Telefnica.............................................................................................................................. 18
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Conceptos de Resolucin de Problemas Resolver problemas no es trivial, pues es necesario comprender qu se quiere resolver, encontrar las herramientas adecuadas para resolver el problema, y luego implementar la solucin con las herramientas disponibles. 1.1 El proceso de resolucin de problemas
1.2 Definiciones 1.2.1 Problema Un problema es una abstraccin de la realidad para la cual nos interesa conocer una solucin, entendiendo que una solucin altera el estado inicial del problema, llevndolo a un estado deseado. Es decir, una solucin es un procedimiento o mtodo para establecer el mecanismo de transformacin del mundo que nos lleve a satisfacer ciertos requerimientos.
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 2 1.2.2 Objeto El mundo est compuesto de objetos fsicos y simblicos. Los objetos en programacin OO son elementos simblicos que representan objetos fsicos del mundo real. En particular se utiliza el trmino clase para describir un tipo de objeto en particular, que tiene ciertas caractersticas comunes. 1.2.3 Instancia Una instancia es un objeto especfico que se puede relacionar con otras instancias u objetos del mismo tipo o de otro tipo. Especficamente, una instancia es un objeto de una clase especfica. 1.2.4 Modelo Toda estructura que se utiliza para dar razn y abstraer de la realidad a un conjunto de acciones o fenmenos que guardan entre s ciertas relaciones. El ejemplo ms simple de un modelo es una instancia, la que no tiene relacin alguna mas que la de ella misma con su objeto respectivo. Modelos ms complejos son los arreglos, registros, archivos y combinaciones de stos. Los lenguajes de programacin normalmente proveen varias combinaciones (no todas) de modelos ms complejos. Un enfoque ms reciente (aos 90) para la resolucin de problemas, se basa en la utilizacin de Objetos, estableciendo un esquema en que cada elemento del mundo real se representa con mayor precisin y fidelidad, logrando as soluciones modulares (compuestas por partes hasta cierto punto independientes, que potencialmente pueden reutilizarse en otros modelos) y con encapsulacin (que logra ocultar la complejidad de soluciones en ciertos mdulos, evitando que los participantes de la solucin tengan que dominar cada parte de sta). A este esquema se le conoce como Orientacin a Objetos. El diseo e implementacin de un modelo son fundamentales para la solucin de un problema computacional.
1.3 Algoritmos 1.3.1 Qu es un Algoritmo? Un algoritmo es un procedimiento detallado y preciso para resolver un problema en pasos (o etapas), cada uno de los cuales toma un tiempo finito. Los algoritmos se especifican en trminos de un conjunto de operaciones bsicas, en las que se involucran diferentes objetos que forman parte de la solucin. Se manipulan las variables del algoritmo y, en general, cambiar el mundo en que se desarrolla el problema. Algunas de estas operaciones permiten tambin controlar el flujo de ejecucin del algoritmo. Llevando a cabo las operaciones que componen el algoritmo, segn su estructura de control, obtendremos la solucin para el problema en cuestin. El flujo de las operaciones especifica la secuencia en que se llevan a cabo las actividades: Toma de decisiones: La secuencia se decide de acuerdo a ciertas condiciones que dependen de los datos del algoritmo. Iteracin: Permite especificar la repeticin de operaciones, tambin en forma controlada por condiciones que dependen de los datos. Al describir un algoritmo es necesario ser lo ms preciso posible, de modo que sea sencillo implementar el procedimiento especificado. En primer lugar, es necesario definir una serie de operaciones bsicas y objetos con las cuales se har la especificacin. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 3 Luego, a partir de los objetos y operaciones definidas, se procede a enumerar los pasos que componen el algoritmo. En esta etapa se puede emplear los componentes bsicos de control de flujo (decisin e iteracin). La principal destreza que se debe desarrollar para escribir algoritmos consiste en poder abstraer un problema y conceptualizarlo de modo que se pueda expresar su solucin en trminos de las operaciones bsicas entre objetos que se definieron. Para esto nos apoyaremos en la descomposicin en partes y subproblemas ms simples, las cuales tambin requieren de cierto grado de conceptualizacin. An cuando muchos algoritmos resulten simples al final, el proceso para llegar a ellos puede ser muy complicado. Existen varios enfoques que se pueden seguir para elaborar un algoritmo a partir de la definicin del problema: Buscar similitud con otros problemas Utilizar ejemplos conocidos Utilizar algoritmos genricos conocidos Conceptualizar actividades y objetos participantes Descomponer en subproblemas La metodologa presentada en este curso hace uso de los dos ltimos, aunque en algunos casos recurriremos al resto como apoyo. 1.3.2 Cmo se especifican o describen los algoritmos? Para especificar un algoritmo puede utilizar el "lenguaje natural" y tambin el "pseudocdigo" (casi cdigo). El lenguaje natural debe utilizar una cantidad suficiente de palabras en frases cortas, pero con sentido completo como para que el algoritmo especificado quede claro. El pseudocdigo suele ser muy utilizado cuando se est diseando un algoritmo que resuelve algn problema computacional, abstrayendo varios detalles de la sintaxis rgida de algn cdigo o lenguaje de programacin, como es el caso del lenguaje C#. 1.3.3 Existe un nico algoritmo de solucin? Para cualquier problema, pueden existir varios algoritmos de solucin, tantos como personas que quieran resolverlos. No existe un algoritmo "nico" de solucin para un problema dado. Ello de ninguna manera quiere decir que estos algoritmos distintos producen soluciones distintas. Aunque ellos sean distintos, todos ellos pueden ofrecer el mismo resultado de solucin. Inclusive un mismo algoritmo que quiere ser implementado mediante algn cdigo de computadora puede ser implementado de distintas maneras, tantas como personas que lo implementen. 1.3.4 Qu es una metodologa? Aplicacin coherente de un conjunto de operaciones ordenadas con que se pretende obtener un resultado. Se puede decir que una metodologa es como un algoritmo genrico. Se aplicar entonces una metodologa que empezando de un problema, llegue a la especificacin de un algoritmo de solucin. Existen muchas metodologas para encontrar una solucin a un problema. En este curso se adoptar la metodologa descrita ms adelante, para contar con un lenguaje comn que pueda dar lugar a su entendimiento por todos aquellos que lo quieran analizar. Esta estrategia en particular se focaliza en el anlisis del problema para luego describir una solucin donde se identifican los objetos involucrados y Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 4 una secuencia de pasos, o algoritmo, que establece las relaciones entre los objetos, alcanzando el objetivo buscado. Una especificacin de un algoritmo de solucin, puede presentar problemas: que el algoritmo resuelva ms de lo que el problema pide (aunque esto por lo general no es perjudicial) o que el algoritmo no resuelva todo lo que el problema requiere. 1.3.5 Las soluciones tambin pueden tener problemas
Para resolver estos problemas es necesario entonces validar la solucin y/o especificar limitaciones del algoritmo de solucin. A veces esta tarea puede ser compleja, debido que para validar la solucin y conocer sus limitaciones hay que ser exhaustivo con el anlisis o seguimiento de la especificacin del algoritmo, considerando todos los casos posibles. Los casos posibles que generalmente no resuelven todas las partes del problema dado, son los casos extremos, como por ejemplo datos nulos si se trata de nmeros, datos negativos si se trata de operaciones aritmticas con nmeros positivos, o por ejemplo para la receta de cocina que se utilice "huevos" pasados en lugar de frescos, etc. Tanto para el diseo de un algoritmo de solucin a un problema dado, como para su validacin se requiere experiencia. PARA TENER EXPERIENCIA ES NECESARIO TENER PRCTICA EN LA RESOLUCION DE PROBLEMAS. PARA TENER PRCTICA ES NECESARIO RESOLVER MUCHOS PROBLEMAS. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 5 2 Orientacin a Objetos En aos recientes se ha adoptado, ms que una tcnica, un enfoque basado en lo que genricamente se denomina Objeto, a diferencia de esquemas tradicionales, denominados Procedurales, en los cuales la solucin se especifica como una secuencia de pasos y subpasos. En el esquema de Orientacin a Objetos se parte de la premisa El Mundo Real est compuesto de Objetos que interactan, y no es un mundo procedural, en que todo ocurre secuencialmente. La Programacin Orientada a Objetos tiene como punto medular el uso de objetos, que en realidad son estructuras lgicas que representan elementos o entidades del mundo real. Esta representacin se basa en los siguientes aspectos: Se usan nombres que permiten hacer una rpida asociacin con el correspondiente objeto. Por ej: para representar un vehculo, se puede definir un objeto o entidad denominado Auto. Para representar el estado del objeto, se utilizan variables, denominadas atributos o propiedades, que almacenan diferentes valores que pueden ir cambiando en el tiempo. Por ej: el auto puede estar representado por cilindraje, velocidad, etc. Para describir el comportamiento del objeto y cmo ste interacta con otros de su mismo tipo o de otro tipo, se definen mtodos, que corresponden a acciones especficas del objeto, una vez ms, simulando el mundo real. Por ej: avanzar, frenar, abrir la puerta delantera derecha, etc.
El objeto Automvil en el mundo real.
Representacin Lgica del Automvil Clase Automvil. Atributos: - Cilindraje - Cantidad de Puertas - Velocidad a la que se desplaza Mtodos (acciones): - Avanzar - Frenar - Cambiar Velocidad - Abrir Puerta N Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 6 El enfoque OO es una evolucin natural de un concepto establecido en la programacin procedural, que se denomin Tipo de Dato Abstracto, siguiendo una intencin de modularizar y a la vez encapsular la complejidad de implementacin de la lgica de un programa. Ms en detalle, la abstraccin de datos es una metodologa que permite aislar la implementacin de un tipo de datos compuesto a partir de tipos bsicos. La idea es estructurar los programas de modo que trabajen sobre datos abstractos, sin conocer su implementacin. Los programas deben usar los tipos de datos de manera que no se hagan suposiciones sobre los datos que no sean estrictamente necesarias para cumplir con la tarea involucrada. Cul es la ventaja de esto? Si tenemos que saber siempre cmo estn implementados los tipos de datos, nuestros programas dependern de esa implementacin. Esto quiere decir que si se producen cambios en la implementacin del tipo de datos, ser necesario cambiar el programa para que siga funcionando. Para poder hacer uso de estos datos, sin conocer su implementacin, se define una interfaz que especifica cmo se puede interactuar con estos datos u objeto. Adicionalmente, la otra gran ventaja del esquema de orientacin a objetos es la posibilidad de reutilizar partes de una solucin para resolver un segundo problema, donde se comparte parte de la lgica resuelta en el primer problema. Esta es una facultad tremendamente importante en la ingeniera de software actual, donde se busca disminuir el esfuerzo involucrado en la implementacin de soluciones a problemas de cada da mayor complejidad. Consideremos el caso de un auto. Somos capaces de conducir distintos autos, de distintas marcas, modelos y aos, sin tener necesidad de saber cmo funciona cada uno de sus componentes. De hecho, no todos los autos tienen los mismos componentes. Incluso, los componentes que son comunes, a pesar de tener la misma funcionalidad, difieren en marcas, modelos, rendimiento, costo, etc. En resumen, la implementacin es distinta pero tienen la misma funcionalidad. De manera similar, una implementacin particular de un tipo de datos es independiente de los programas que lo usan. Lo nico que es intocable es la interfaz. Volviendo al ejemplo del auto, todas las marcas y modelos poseen algo en comn: Una forma de uso establecida por parmetros de operacin y por la forma de entregar esos parmetros (forma de usar el volante, el acelerador, el freno, etc). Nadie comprara un auto en que el freno se encuentre a la derecha del acelerador, o que el volante funcione girando el auto a la derecha cuando se mueve hacia la izquierda.
2.1 Terminologa Bsica de la Programacin Orientada a Objeto - Objeto: entidad lgica que representa un objeto segn lo conocemos los humanos en el mundo real. - Clase: un tipo de objeto, descripcin lgica que especifica caractersticas comunes a todos los objetos de un tipo comn, por ejemplo Vehculo describe genricamente todos los objetos de ese tipo. - Instancia: un objeto particular de una clase especfica. Tambin se los conoce como objetos propiamente tales. Una instancia tiene su propio nombre y se diferencia de otras instancias de la misma clase, por los valores que puedan tener sus atributos en un instante en particular. - Atributos o Propiedades: son variables de estado, cuyo valor se asocia a una instancia en particular de una clase de objeto.
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 7 3 Estrategias para la Solucin de Problemas Tomando en cuenta el objetivo de aprender a enfrentar problemas de cierto nivel de complejidad, se hace necesario contar con una estrategia de resolucin, que permita, estructuradamente y predeciblemente, enfrentar y entender el problema y plantear una solucin entendible y que claramente se enfoque en resolver el problema planteado. En la literatura existen numerosas estrategias, todas enfocadas con mayor nfasis a cierto tipo de problemas. A continuacin se presenta una metodologa de resolucin de problemas de tipo genrico, que ser el puntal para este curso. 3.1 Metodologa de Resolucin de Problemas El proceso que permite obtener una solucin a un problema puede dividirse en las siguientes etapas: 1. Definicin del problema (planteamiento original) El primer paso: Definicin del Problema, busca definir el contexto en que se establece el problema, indicando el alcance u objetivo que se pretende atacar. Este paso se descompone en tres partes: 1.1. Conceptualizacin. Conceptualizar el mundo o contexto en que ocurre el problema. Cualquier suposicin sobre el dominio del problema debe ser descrita aqu. Adems, debe quedar claro cul es la informacin que se conoce relativa al problema (entradas del algoritmo). 1.2. Objetivo. Determinar el objetivo que se quiere alcanzar, en forma cualitativa (descripcin de lo que se desea) y cuantitativa (forma en que se medir el logro alcanzado). 1.3. Elementos involucrados. Especificar los elementos activos (usuarios) y pasivos (recursos disponibles y/o modificables) que estn involucrados en el problema. 2. Conceptualizacin de la solucin El segundo paso: Conceptualizacin de la solucin, se focaliza en una descripcin de los elementos involucrados en la solucin al problema planteado. Esta seccin se enfoca en un esquema de orientacin a objeto, ya que el ncleo de esta definicin no son las acciones a tomar, propiamente tales, sino que los objetos que estarn involucrados en la solucin. A su vez, esta descripcin de elementos se descompone en tres partes: 2.1. Entidades involucradas. Haciendo un paralelo con el problema en el mundo real que se est representando, se determinan cules son las entidades que participan en la solucin del problema, indicando su funcionalidad bsica. Las entidades que son muy complejas pueden definirse en base a otras ms simples. 2.2. Clases de Objetos. Para cada una de las entidades descritas en el punto anterior debe definirse un tipo de objeto que la implemente, tambin llamado clase. La definicin de cada clase debe incluir nicamente la funcionalidad del tipo (para qu sirve?) y la interfaz (cmo se usa?). La interfaz se define en trminos de un conjunto de mtodos con parmetros claramente establecidos. Tambin deben mencionarse las limitaciones de cada una de las clases. 2.3. Instancias. Deben definirse las instancias de cada clase que se emplearn en la solucin del problema, indicando el uso particular que se dar a cada una. A su vez, debe especificarse aquellos datos simples adicionales que estarn involucrados en la solucin.
3. Especificacin del algoritmo El tercer paso: se especifica una secuencia de pasos principales (no detallados), en que las distintas instancias interactan para producir el objetivo esperado. Se detalla paso por paso el procedimiento principal, donde incluso se especifica algunos valores iniciales de las instancias requeridas. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 8 Especificar la secuencia de actividades que conforman la solucin del problema. Esta especificacin debe ser autocontenida y debe estar dada en trminos de las entidades/objetos definidos en (2). Cada uno de los pasos del algoritmo podr ser una operacin simple o alguna operacin sobre uno de las instancias de los objetos.
4. Validacin de la Solucin El cuarto paso: habiendo definido el problema y descrito una solucin se hace un estudio de los posibles escenarios en que la solucin puede funcionar. Los escenarios se definen en funcin de los rangos de valores que los parmetros de la solucin pueden recibir. 4.1. Dominios. Especificar un conjunto de problemas tipo y sus soluciones, los cuales caracterizan el dominio del problema. Debe haber un problema para cada posible dominio. 4.2. Ejecucin. Ejecutar el algoritmo obtenido en (3) para cada uno de los problemas que representan los distintos dominios, validando que se obtengan las soluciones especificadas, es decir, que se alcancen los objetivos propuestos en cada caso.
5. Limitaciones del algoritmo Identificacin de puntos dbiles y escenarios en los cuales el algoritmo no funciona o tiene deficiencias (condiciones crticas).
3.2 Descripcin Grfica de Soluciones La idea de las representaciones grficas, o diagramas, es apoyar la descripcin que se hace, tanto de las problemas y modelos, como de sus soluciones. En estas descripciones grficas se intenta ilustrar, ya sea con metforas visuales o con grficos descriptivos las diferentes condiciones que se imponen sobre la situacin a odelar y que requiere ser resuelta, as como de los elementos que componen su solucin. Particularmente como apoyo a los procesos de diseo de soluciones Orientadas a Objeto, se ha desarrollado en los ltimos aos un lenguaje de modelamiento, llamado directamente Lenguaje de Modelamiento Unificado (Unified Modeling Language UML), que consisten en la conjuncin de diferentes tcnicas tradicionales, en un enfoque ms actualizado con la tecnologa actual. En este contexto slo se analizarn algunos tipos de diagramas manejados en UML, que permiten tanto describir los requerimientos de las soluciones que debern ser diseadas, as como los elementos que componen y definen el modelo de solucin a un problema dado. 3.2.1 Diagrama de Casos de Uso - UML El primer tipo de diagrama utiliza elementos grficos muy simples para describir las funcionalidades de una solucin requerida, a nivel macro. En estos diagramas se identifican: - Actores: elementos que interactan con la solucin, lo que incluye tanto a usuarios, como a elementos externos al sistema o aplicacin, como son bases de datos externas, archivos, u otros sistemas. - Funcionalidades o Casos de Uso, que describen una operacin o un conjunto de operaciones que se pueden gatillar por parte de un usuario o de otro actor, y que producen un resultado medible. - Cada actor puede activar un caso de uso (es decir, su decisin inicia el funcionamiento descrito por dicho caso de uso), o bien, el actor puede recibir la accin de un caso de uso iniciado por otro lado. Esto se representa por una flecha unidireccional, que indica quin activa a quin. Actor1 Caso de Uso Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 9 Tomemos por ejemplo el caso de un cajero automtico. En este caso, consideraremos que el programa que reside en el cajero es la aplicacin a describir, y que los actores involucrados son: un usuario o cliente que acudir al cajero, y el sistema central que tiene los datos de las cuentas corrientes de los clientes. En este modelo, un cliente efecta dos posibles acciones sobre el cajero: Consulta de Saldo y Retiro de Dinero. El cajero a su vez requiere consultar los datos al sistema central para ambos casos, y en particular en el retiro de dinero, adicionalmente actualiza el saldo del cliente en el mismo sistema central.
3.2.2 Diagrama de Clases UML En aquellas soluciones en las que se definen clases que representan objetos del mundo real, pero estructurados y especificados de una manera precisa en el modelo, se utiliza el diagrama de clases donde no slo se identifican grficamente cada una de las clases (o tipos de objetos) que interactan en la solucin, sino que adems se especifican detalles como los elementos que componen cada una de estas clases y cmo se relacionan entre ellas. Este esquema, totalmente dependiente de la modelacin al estilo Orientacin a Objeto, permite definir en forma visual el diseo de la solucin. Entre las relaciones que este tipo de diagrama permite definir entre clases, resultan relevantes dos: la herencia entre clases, y la composicin de clases dentro de otras. En estos diagramas se reconocen bsicamente los siguientes objetos: - Clases: con sus respectivos elementos componentes. Estas se representan por un rectngulo que interiormente describe los componentes, lo que se ver en detalle ms adelante. - Relacin de Herencia: identificada por una flecha de lnea slida y una punta triangular vaca, que va desde la clase derivada a la clase padre. - Relacin de Composicin: que define que una clase contiene una o ms instancias de otra clase, y se identifica por una lnea slida, que puede terminar en flecha con punta abierta, e incluye un rombo en la mitad, donde se describe la cardinalidad (o cuntas instancias de la clase referenciada estn contenidas en cada instancia de la clase contenedora o compuesta). En el siguiente ejemplo, se representa en forma simple la siguiente situacin. Se tiene una clase Vehculo, que representa genricamente los vehculos de cualquier tipo. De ella se derivan dos clases, el Camin, y la Motocicleta. A su vez existe una 4 clase, que representa un automotora, que en realidad contiene varias instancias de vehculos, ya sean camiones o motocicletas. Por ello, en este diagrama, la clase Vehculo es la central, y de ella se derivan las otras clases.
Clase: Vehculo 0 . . 1 * Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 10 Clase: Camin Clase: Vehculo Clase: Motocicleta Clase: Automotora 0..1 *
3.2.3 rboles de Decisin Los rboles de decisin son una herramienta grfica muy til para representar algoritmos en los que estn involucradas una gran cantidad de decisiones a lo largo de su ejecucin. El objetivo es ilustrar la forma en que el algoritmo va evolucionando conforme se van tomando decisiones, normalmente sobre la base de informacin suministrada por el usuario. Cada punto de decisin se representa con una caja rectangular, en la cual se describe brevemente los aspectos a considerar para tomar dicha decisin. Una vez que se conocen los criterios para tomar la decisin en uno de estos puntos, se seala con flechas las distintas posibilidades hacia donde evolucionara el algoritmo, llevando el desarrollo de la ejecucin hacia otro punto de decisin. Para identificar las posibles opciones, se etiquetan las flechas. Las posibilidades pueden ser mltiples, producindose varias bifurcaciones en cada punto de decisin, o simplemente dos, en cuyo caso se obtendra un rbol binario. Este es el caso del ejemplo que se muestra a continuacin. Al llegar al ltimo nivel, es decir, cuando ya no hay decisiones que tomar, se ha obtenido una solucin y el algoritmo ha concluido. A estos nodos dentro del rbol se les conoce como hojas, o tambin como nodos terminales.
3.2.4 Ejemplo: rbol de Decisin: Qu hago el sbado por la noche? Para ilustrar el uso de los rboles de decisin, se presenta un rbol que gua a un usuario a tomar una decisin sobre qu hacer el sbado por la noche. La profundizacin en el rbol se lleva a cabo de acuerdo a las respuestas que va dando el usuario a las interrogantes que se le plantean. Cuando se llega a un nodo terminal en el rbol (hoja), el usuario recibe una recomendacin sustentada en el desarrollo de la interaccin. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 11
3.3 Ejemplos de Aplicacin de la Metodologa 3.3.1 Simulando la Ejecucin de un Penal Este primer ejemplo ilustra la situacin de ejecucin de un penal de ftbol, reconociendo los elementos involucrados en esta situacin y cmo se relacionan para producir un resultado. 1. Definicin del problema Conceptualizacin: El problema consiste en ejecutar un penal, donde un jugador patea la pelota hacia el arco y el arquero trata de detenerla. Particularmente se pretende determinar si al ejecutar un penal, el gol fue convertido o fue atajado. En este caso, un usuario indicar la direccin en que patea el jugador y la direccin en que se lanza el arquero. Si ambas direcciones coinciden, se considera penal atajado. Si no coinciden, se considera penal convertido. Objetivo: El objetivo es determinar para una combinacin de direcciones en que se patea la pelota y se lanza el arquero, ingresadas por el usuario, si el penal fue convertido o no. Elementos Involucrados: Elementos activos, el usuario que indicar las direcciones respectivas. Elementos pasivos, el jugador y la direccin en que lanzar, y el arquero y la direccin en que se lanzar.
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 0 2. Conceptualizacin de la solucin Entidades Involucradas: Dos objetos esenciales se reconocen en este problema: el jugador y el arquero. Clases de Objetos: En este caso particular, ambas entidades se representan cada una por su respectiva clase. Clase Jugador: Representa a un jugador que lanzar la pelota tratando de convertir el penal. Atributos: El nmero en su camiseta, y la direccin en que lanzar. Mtodos: patear la pelota Clase Arquero: Representa a un jugador que intentar impedir que el gol sea convertido. Atributos: la direccin en que se lanza para atajar. Mtodos: Lanzarse a atajar. Instancias Involucradas: en este caso slo se necesita una instancia de la clase Jugador, que representa a quien ejecutar el penal, y adicionalmente se requiere una nica instancia de la clase Arquero, ya que slo uno de ellos participa en el penal.
3. Especificacin del algoritmo Siguiendo el procedimiento de ejecucin de un penal, se involucra al usuario para hacerle las preguntas del caso. 1. Se instancia el jugador (j1), y se instancia el arquero (a1) 2. Se le pregunta al usuario la direccin en que patear el jugador se asigna a la instancia j1 3. Se le pregunta al usuario la direccin en que se lanzar el arquero se asigna a la instancia a1 4. Se invoca el mtodo Patear del objeto j1 5. Se invoca el mtodo Lanzarse del objeto a1 6. Se comparan ambas direcciones. Atributos: - Nmero - Direccin Mtodos: - Patear Atributos: - Direccin Mtodos: - Lanzarse Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 13 a. Si coinciden, se indica al usuario que el penal fue atajado. b. Si no coinciden, se indica al usuario que el gol fue convertido.
4. Validacin de la Solucin Dominios: Los posibles dominios que existen en el contexto de este problema se constituyen a partir de los valores de direccin que el usuario puede ingresar. Es decir, los escenarios posibles se conforman de las 4 diferentes combinaciones de direcciones para ambos jugadores: der-der; izq-izq; izq-der; der-izq. Validacin: revisando las cuatro posibles combinaciones de valores indicados por el usuario, se llega en todos ellos a un resultado predecible por el algoritmo principal, por lo que se valida su ejecucin.
5. Limitaciones Si los valores ingresados por el usuario no son controlados, entonces se podra asumir que el programa podra tener un comportamiento incoherente.
Posibles soluciones:
Versin de Consola
Versin Windows
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 14 3.3.2 Simulando la preparacin de un pastel En este ejemplo se emplea la metodologa de solucin de problemas para definir e implementar los pasos necesarios para simular la solucin a un problema simple: hornear y servir un pastel de fruta. 1. Definicin del problema Conceptualizacin: El problema consiste en preparar un pastel de alguna fruta especfica, de acuerdo a cierta receta, y servirlo a cierta cantidad de comensales. Se recibir como entrada la receta para hornear, es decir, la cantidad de huevos, harina y mantequilla que se emplear, la fruta con que se cubrir el pastel y la cantidad correspondiente, as como el tiempo que debe permanecer en el horno. Adicionalmente, se recibe el nmero de comensales que disfrutarn del producto final, para poder cortarlo y servirlo. Objetivo: El objetivo es poder seguir la receta proporcionada de modo que podamos obtener como resultado un pie de fruta que podamos repartir a los comensales. Elementos involucrados: El nico elemento activo ser la persona que llevar a cabo el proceso (el cocinero). Los elementos pasivos involucrados son la receta del pastel: sus ingredientes y cantidades (huevos, harina, mantequilla, fruta). En este caso, los comensales podran considerarse como elementos pasivos, pues no participan de la solucin (existen, pero simplemente esperan).
2. Conceptualizacin de la solucin Entidades Involucradas: el objeto principal es la receta del pastel, que ser preparado durante el proceso. La receta se compone de las cantidades respectivas de cada ingrediente, adems del tiempo de horneado, el tipo de fruta, y los trozos en que deber partirse. Clases de Objetos: la nica clase requerida es pastel, la cual se define con ciertas propiedades privadas, y algunos mtodos pblicos. Las propiedades privadas son las cantidades de huevos, harina, mantequilla, y fruta, el tiempo de horneado, el tipo de fruta, y la cantidad de pedazos. Todos ellos son datos numricos a excepcin del tipo de fruta, que es de tipo texto. El proceso de hornear y servir el pastel abarca varias etapas. En primera instancia se debe obtener la receta a emplear. Esto consiste en especificar la cantidad de huevos, mantequilla y harina, as como el tipo y la cantidad de fruta que se utilizar. El segundo paso consiste en preparar la base del pie, mezclando la cantidad especificada de huevos, harina y mantequilla. Luego, la base es horneada durante cierto tiempo (lo cual tambin es parte de la receta). El siguiente paso es preparar la fruta con la que se cubrir la base. Finalmente, se procede a cortarlo y servirlo a todos los comensales. Por esto, los mtodos de esta clase son: MezclarBase(): Se toman las cantidades definidas de huevos, harina y mantequilla y se mezclan para lograr la base. HornearBase(): Segn el tiempo definido, que representa la cantidad de minutos que deber permanecer la base en el horno, este proceso se encarga de hornear la base durante dicho tiempo. PrepararFruta(): Usando el tipo o nombre de la fruta que se emplear para cubrir la base, y la cantidad (en gramos) de dicha fruta que debe emplearse (segn la receta), este proceso prepara la cubierta. CortarServir(): Tomando el tipo de fruta con que se cubri el pastel y la cantidad de invitados establecidos, este proceso se encarga de cortar el pastel en tantos pedazos como comensales haya y lo sirve para que los invitados lo puedan comer. El tipo de fruta es necesario para que al servirlo a los comensales se les pueda indicar qu tipo de pie van a comer. Instancias: En el contexto de nuestro problema, ser necesario representar una variable u objeto de clase Pastel, que representa el pastel a preparar en base a su receta (huevos, harina, mantequilla, fruta), el tiempo que debe permanecer el pie en el horno, y la cantidad de comensales que lo disfrutarn. El nombre de esta instancia: pas.
Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 15
3. Especificacin del algoritmo El algoritmo presentado a continuacin emplea la instancia de la clase definida y llama secuencialmente a los mtodos respectivos para resolver nuestro problema. En este caso no fue necesario emplear operaciones de control de flujo, pues el algoritmo se puede especificar en forma totalmente secuencial. Algoritmo: 1. Crear la receta del Pastel, obteniendo del usuario los ingredientes: huevos, harina, mantequilla, tipo, fruta y tiempo, y la cantidad de pedazos en que se debe cortar. 2. MezclarBase() 3. HornearBase() 4. PrepararFruta() 5. CortarServir()
La implementacin en C# de este algoritmo resulta bastante simple. Basta con implementar e invocar el mtodo para cada una de las tareas involucradas. Esta funcin simular el proceso que debe llevar a cabo la tarea. Las primeras lneas del algoritmo involucran la creacin de la instancia, junto con la entrada de datos por parte del usuario del programa (debe proporcionar los valores apropiados para las propiedades de esta instancia).
4. Validacin de la Solucin Dominios: Los posibles dominios que existen en el contexto de este problema se constituyen a partir de los distintos valores de entrada que pueden recibirse del usuario. Es decir, distintos tipos de fruta, distintas cantidades para cada ingrediente, distintos tiempos en el horno y distintas cantidades de comensales. Validacin: Debe ejecutarse (verbalizarse su ejecucin) el algoritmo para los dominios definidos, es decir, cambiando valores para cada dato de entrada, y verificando que se puede alcanzar el objetivo buscado. A priori, no hay validacin de las cantidades numricas indicadas, por lo que el algoritmo funcionara, an cuando se ingresen valores que no tengan sentido de acuerdo al contexto, como por ejemplo usar cantidades de minutos negativas o cero, o nombres incongruentes de frutas.
5. Limitaciones de la Solucin En principio, no hay limitaciones evidentes en el caso de la solucin planteada en este ejemplo, ya que el programa funcionara incluso con nmeros incoherentes (nmeros negativos, nulos) en los valores indicados por el usuario. Atributos: - Huevos - Harina - Mantequilla - Fruta - Tiempo de horneado - Tipo de fruta - Cantidad pedazos Mtodos: - MezclarBase() - HornearBase() - PrepararFruta() - CortarServir() Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 16 3.3.3 Cambio de neumtico desinflado Un auto queda detenido en la carretera al desinflrsele un neumtico. Para tratar este problema particular se aplicar la metodologa para la solucin de problemas presentada anteriormente. 1. Definicin del problema Conceptualizacin: El problema tiene lugar en una carretera, en donde un auto se ha quedado parado, pues uno de sus 4 neumticos se ha desinflado. El auto cuenta con las herramientas necesarias para que el conductor pueda cambiar el neumtico, as como tambin con un neumtico de repuesto en buenas condiciones. El nico dato de entrada con que se cuenta es la posicin del neumtico desinflado, es decir, en cul de las cuatro ruedas ocurri el percance. Objetivo: Cualitativamente, el objetivo es cambiar el neumtico desinflado por el de repuesto, de modo que el auto pueda andar. Cuantitativamente, el logro del objetivo puede medirse verificando que los 4 neumticos estn inflados. Elementos involucrados: Existe un nico elemento activo que es el conductor del auto. Adems, existen los siguientes elementos pasivos, que formaran parte del equipamiento del auto: Maletero Ruedas, una de las cuales tiene el neumtico desinflado Pernos que sujetan cada rueda Neumtico de repuesto, en buenas condiciones, ubicado en maletero del auto Gata hidrulica en el maletero del auto Llave de cruz en el maletero del auto
2. Conceptualizacin de la solucin Entidades Involucradas: el objeto principal es claramente el auto. Es esta entidad la que contiene todos los elementos relevantes de manejar en esta solucin, como son las ruedas, el maletero, y todos los elementos dentro de l, necesarios para el cambio de rueda. Clases de Objetos: la nica clase requerida en este caso, es Auto, la cual es descrita por medio de ciertos atributos y mtodos. Los atributos se definen directamente en funcin de los elementos pasivos requeridos en la solucin, ms un atributo indicando la rueda que est desinflada: maletero, gata hidrulica; llave de cruz; un perno (su nmero: 1, 2, 3, 4); neumtico desinflado; neumtico de repuesto. El mtodo constructor de esta clase recibir como parmetro el N del neumtico desinflado. Los otros mtodos, se pueden resumir en las siguientes actividades: - Retirar y colocar cosas - Aflojar y apretar pernos - Subir y bajar el auto con la gata De esa manera, se podran definir los siguientes mtodos: - Retirar "algo" de un "lugar" - Colocar "algo" en un "lugar" - Aflojar "un determinado perno" - Apretar "un determinado perno" - Subir auto desde "una determinada posicin" - Bajar auto desde "una determinada posicin" Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 17 Los trminos resaltados en cursiva corresponden a variables de entrada (parmetros) que proporcionan generalidad a las operaciones. Por ejemplo, el primer mtodo puede emplearse para retirar el neumtico de repuesto del maletero, pero tambin para retirar la llave de cruz del maletero y un perno de la rueda. Una definicin ms formal involucra especificar claramente cules son los parmetros con los que trabaja cada operacin. As, la lista definitiva de operaciones ser la siguiente: - Retirar Parmetros: Lo que se desea retirar y el lugar de dnde se retirar - Colocar Parmetros: Lo que se desea colocar y el lugar dnde se colocar - Aflojar perno Parmetros: La posicin de la rueda, el nmero de perno que se desea aflojar. - Apretar perno Parmetros: La posicin de la rueda, el nmero de perno que se desea apretar, y la herramienta que se usar - Subir auto Parmetros: La posicin de la rueda en donde se desea subir el auto y la herramienta (gata) que se usar - Bajar auto Parmetros: Ninguno. Instancias: En el contexto del problema la nica instancia necesaria es una de la clase Auto, que simplemente se llamar auto1, la cual contiene todos los atributos necesarios para representar la situacin.
3. Especificacin del algoritmo El algoritmo presentado a continuacin emplea las operaciones (tareas) definidas anteriormente para resolver el problema de cambiar el neumtico desinflado. Se resalta los argumentos de cada operacin. La nica operacin elemental que se emplea para cambiar el flujo de control de las tareas es la iteracin. Algoritmo: Considere N como la posicin del neumtico desinflado (dato de entrada), referenciado como 1, 2, 3, 4. 1. Declarar instancia de Auto, con N como parmetro. 2. Auto.Retirar( gata hidrulica, del maletero ) 2. Auto.Retirar( llave de cruz, del maletero ) 3. Itere sobre cada perno P = 1,2,3,4 3.1. Auto.Aflojar( perno P, en rueda N) 4. Auto.Subir( posicin N ) 5. Itere sobre cada perno P = 1,2,3,4 5.1. Auto.Retirar( perno P, de rueda N) 6. Auto.Retirar( neumtico D, de rueda N) 7. Auto.Retirar( neumtico R, del maletero ) 8. Auto.Colocar( neumtico R, en rueda N) 9. Auto.Colocar( neumtico D, en maletero ) 10. Itere sobre cada perno P = 1,2,3,4 Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 18 10.1. Auto.Colocar( perno P, en rueda N ) 11. Auto.Bajar() 12. Itere sobre cada perno P = 1,2,3,4 12.1. Auto.Apretar( perno P, en rueda N ) 13. Auto.Colocar( llave de cruz, en maletero ) 14. Auto.Colocar( gata hidrulica, en maletero )
4. Validacin del algoritmo Dominios: Los posibles dominios que existen en el contexto de este problema se constituyen a partir del neumtico que se haya desinflado. Por ejemplo, un posible dominio ser aquel en que el neumtico desinflado es el de la rueda izquierda delantera. Validacin: Ejecutando el algoritmo para cualquiera de los cuatro neumticos del auto puede verificarse que la parametrizacin de las operaciones elementales permite alcanzar el objetivo buscado. Al final de la ejecucin del algoritmo, para cualquier dominio (es decir, considerando cualquiera de los cuatro neumticos), el auto contar con todos sus neumticos inflados y por consiguiente podr andar. 5. Limitaciones del algoritmo El desarrollo del algoritmo se hizo para un auto que tuviera 4 pernos sujetando cada rueda. Sin embargo, puede modificarse para recibir este valor como un dato de entrada. Por simplicidad se dejaron de lado algunas consideraciones, como por ejemplo, abrir y cerrar el maletero, transportar los neumticos y las herramientas, etc. Adems, la solucin presentada se aplica nicamente a autos que cuenten con cuatro neumticos.
3.3.4 Llamada Telefnica Se desea conceptualizar el problema de efectuar una llamada telefnica en un telfono pblico que recibe monedas de $10, $50 y $100. El costo mnimo de la llamada es de $100 por 5 minutos. El proceso se inicia desde que se levanta el auricular y finaliza cuando se cuelga. Se aplicar la metodologa para la solucin de problemas presentada anteriormente.
1. Definicin del problema Conceptualizacin: El problema tiene lugar en cualquier telfono pblico que acepta monedas de $10, $50 y $100, con un costo de llamada mnima de $100 por 5 minutos. Supondremos que el aparato funciona apropiadamente y que el usuario cuenta con suficientes monedas, de cualquier denominacin, para completar su llamada. Los datos de entrada son: 1) el nmero de telfono que se desea marcar, y 2) las monedas que lleva consigo la persona que har la llamada. Objetivo: Cualitativamente, el objetivo es que el usuario pueda completar su llamada. Cuantitativamente, el logro del objetivo puede verificarse si el tiempo de duracin de la llamada del usuario es mayor que cero. Elementos involucrados: Existe un nico elemento activo, que es el usuario que realiza la llamada. Adems, existen los siguientes elementos pasivos: - Un telfono pblico en buen estado, que funciona en la forma que se indic. El telfono tiene los siguientes componentes: Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 19 o Ranura para insertar monedas o Auricular o 10 teclas numricas (una con cada dgito) o Ranura para devolucin de monedas - Un conjunto de monedas que se compone de: o Un subconjunto de monedas de $10, que puede ser vaco o Un subconjunto de monedas de $50, que puede ser vaco o Un subconjunto de monedas de $100, que puede ser vaco
2. Conceptualizacin de la solucin Entidades: Para efectos prcticos y funcionales, el problema global de efectuar la llamada telefnica puede descomponerse en las siguientes tareas actividades: Manipular el auricular (levantarlo y colgarlo); Manipular las monedas (recolectarlas, ponerlas en la ranura, recuperarlas cuando son devueltas); Escuchar en el auricular (por el tono de marcar, de llamada en proceso, de conexin aceptada, o de ocupado); Marcar un nmero en el teclado del telfono; Hablar. El problema se describe en la relacin que un usuario hace entre la manipulacin de un telfono y sus dispositivos, y un conjunto de monedas desde el cual saca la cantidad requerida para realizar las llamadas. Clases: Las nicas dos clases que permiten definir la solucin a este problema son Telefono, y Bolsillo, los cuales en forma explcita verbalizan su representacin de la realidad. Adicionalmente se define un tipo de dato especial, que representa un conjunto particular de monedas. Cada una de las clases formales se compone de atributos y mtodos como se describe a continuacin: Clase Telefono Atributos: - costo de la llamada, en este caso siempre valdr $100, por lo que podra manejarse como una constante. - tiempo: Corresponde al tiempo que el usuario ha hablado con al telfono que marc. Mtodos pblicos o LevantarAuricular(): representa la accin de tomar el auricular, que provoca la activacin del telfono y la peticin de tono. o DepositarMonedas(monedas): deposita el conjunto de monedas indicado en el telfono. o ColgarAuricular(): representa la accin de devolver el auricular a su posicin de cuelgue, desactivando as el telfono. o EscucharAuricular(): representa la accin de detectar el tono que tiene el telfono. Como retorno, devuelve el tono esuchado, identificando uno de los siguientes valores: TONO, CONEXION EXITOSA y OCUPADO, DESCONEXION (este tono se escucha cuando se ha esperado por un tiempo determinado y nadie contesta el telfono marcado). o RecuperarMonedas(): permite recuperar las monedas sobrantes, retornando como resultado el conjunto de estas monedas. o Marcar(numero): Esta operacin marca en el teclado numrico cada uno los dgitos del nmero al que se desea llamar. Variables locales: D: almacena los dgitos del nmero al que se desea hablar. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 20 Algoritmo: 1. Iterar sobre cada una de los dgitos D del nmero que se desea marcar 1.1 Presionar en el teclado numrico el nmero correspondiente al dgito D o Hablar(): Esta operacin permite que el usuario hable con la persona a la que llam. Por cada segundo hablado se incrementa en 1 el tiempo de la llamada. Cuando se han cumplido 5 minutos (300 seg.) se debe introducir $100 para seguir hablando. Variables propias: tiempo: almacena el tiempo que se ha hablado hasta el momento. MB: monedas en el bolsillo seleccionadas. Corresponde a las monedas que el usuario posee. MS: monedas seleccionadas. Corresponde a las monedas que el usuario utilizar para efectuar la llamada. Algoritmo: 1. Al comienzo tiempo es 0 seg. 2. Iterar mientras se desee seguir hablando 2.1 Hablar un segundo. 2.2 Incrementar en 1 la variable tiempo. 2.3 Si tiempo tiene el valor 300 seg. 2.3.1 Recolectar monedas para una llamada de $100 desde conjunto de monedas MB y almacenarlas en el conjunto de monedas MS. 2.3.2 Depositar monedas del conjunto MS en el telfono. 2.3.3 Devolver tiempo a 0 seg.
Clase Bolsillo Mtodos pblicos o RecolectarMonedas(monto): recolecta una combinacin de monedas de $100, $50, y $10, que sumen el monto indicado. Como retorno entrega el conjunto de monedas seleccionadas. Variables locales: - monto recolectado: almacena el valor de las monedas que se han seleccionado hasta el momento. Algoritmo: 1. Al comienzo el monto recolectado es $0. 2. Iterar hasta que el monto recolectado sea el indicado 2.1 Seleccionar del bolsillo del usuario una moneda (una de las de mayor valor que tenga) y pasarla al conjunto de monedas seleccionadas 2.2 Sumar el monto de la nueva moneda con el monto recolectado 3. Devolver el conjunto de monedas seleccionadas.
Instancias: En el contexto del problema que se intenta resolver, se necesitarn las siguientes instancias: - El aparato telefnico que se utilizar para la llamada - El bolsillo que contiene las monedas Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 21 - Adicionalmente ser necesario representar como dato el nmero de telfono que se desea marcar. La variable que lo denotar ser Num. - Por otro lado, es necesario representar las monedas seleccionadas desde el bolsillo. Esto se har con la variable MS. - tono: Corresponde al tono escuchado en el telfono. - intentos: Corresponde al nmero de intentos que ha hecho el usuario.
3. Especificacin del algoritmo El algoritmo presentado a continuacin emplea las clases e instancias definidas anteriormente para resolver el problema de hacer una llamada telefnica. En este caso, para controlar el flujo de las operaciones se emplea iteracin y decisin. Adems, con el objetivo de que el usuario no se quede indefinidamente intentando hacer la llamada, en caso de ocupado o que no contesten, se harn nicamente 3 intentos y si no se logra la llamada se abandonar el proceso y el problema no podr ser resuelto. Algoritmo: Considere Num como el nmero que el usuario desea marcar, T como el telfono donde se har la llamada, y B como el bolsillo que contiene las monedas con que har la llamada. Inicialmente la variable intentos valdr 0. Iterar los siguientes pasos mientras intentos sea menor que 3. 1. MS = B.RecolectarMonedas(100) Se recolectan las monedas para una llamada de $100 desde el conjunto de monedas en el bolsillo B y se almacenan en el conjunto de monedas MS. 2. T.LevantarAuricular(). 3. T.DepositarMonedas(MS). 4. tono = T.EscucharAuricular(), se repite hasta que tono sea TONO. 5. T.Marcar(Num) 6. tono = T.EscucharAuricular(). 7. Mientras tono CONEXION EXITOSA o DESCONEXION. a. tono = T.EscucharAuricular(). 8. Si tono = CONEXION EXITOSA entonces a. T.Hablar(). b. T.ColgarAuricular(). 9. Por el contrario, si tono = DESCONEXION u OCUPADO entonces a. T.ColgarAuricular(). b. MS = T.RecuperarMonedas(). c. Incrementar variable intentos en uno.
4. Validacin del algoritmo Dominios: Los posibles dominios que ser necesario analizar se constituyen a partir de las siguientes caracterizaciones: o Las distintas combinaciones de monedas que pueden formarse para llevar a cabo la llamada. Intro a la Prog. Resolucin de Problemas Rodrigo Sandoval U. IIC 1102 Pgina: 22 o El telfono al que se llama est ocupado. o No contestan en el telfono al que se llama. o Al hacer la llamada se obtiene una respuesta satisfactoria. o Llamadas de menos de 5 minutos y llamadas de ms de 5 minutos. o Distinto nmero de intentos al hacer la llamada (1, 2, 3). Validacin: La validacin debe llevarse a cabo tomando en consideracin los dominios definidos en el punto anterior. Para cada uno de ellos debe probarse que el algoritmo es correcto, es decir, que funciona de acuerdo a las especificaciones originales.
Material preparado por Rodrigo Sandoval U en Marzo-Agosto 2004 Basado en la documentacin del curso IIC1102, ao 2003, de Miguel Nussbaum y Marcos Seplveda et. al.
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo II Introduccin al Lenguaje C#
1 EL LENGUAJE C# Y EL FRAMEWORK DE .NET ...................................................................................... 1 1.1 MICROSOFT .NET FRAMEWORK 1.1...............................................................................................................1 1.1.1 Lenguajes de Programacin .................................................................................................................. 1 1.1.2 Common Language Runtime (CLR) ....................................................................................................... 2 1.1.3 Biblioteca de clases de .Net.................................................................................................................... 2 1.2 ESTRUCTURA DE UN PROGRAMA EN C#...........................................................................................................2 1.2.1 Ejemplo de un programa en C# ............................................................................................................. 2 1.3 IDENTIFICADORES...........................................................................................................................................3 1.3.1 Algunas consideraciones al definir identificadores ............................................................................... 4 1.3.2 Ejemplos de identificadores ................................................................................................................... 4 1.4 DECLARACIN DE CLASES Y SUS ELEMENTOS................................................................................................6 1.4.1 Visibilidad/accesibilidad de una clases y sus miembros ........................................................................ 6 1.4.2 Elementos de una Clase ......................................................................................................................... 7 1.4.3 Campos................................................................................................................................................... 7 1.4.4 Tipos de Datos........................................................................................................................................ 8 1.4.5 Mtodos o Funciones ........................................................................................................................... 11 1.4.6 Sintaxis de la llamada a las Funciones definidas ................................................................................ 12 1.4.7 La funcin principal Main() y los programas en C#............................................................................ 13 1.4.8 Ejemplo en C# de la simulacin de compra de un boleto en el metro. ................................................ 13 1.5 EXPRESIONES................................................................................................................................................15 1.5.1 Expresiones Aritmticas....................................................................................................................... 15 1.5.2 Operadores Compuestos ...................................................................................................................... 17 1.5.3 Expresiones Relacionales, Lgicas o Booleanas ................................................................................. 18 1.5.4 Precedencia de todos los operadores................................................................................................... 19 1.6 INSTRUCCIONES............................................................................................................................................20 1.7 OPERADOR DE ASIGNACIN..........................................................................................................................20 1.8 CONVERSIN DE TIPOS (TYPE CASTING)........................................................................................................22 1.9 ENTRADA Y SALIDA......................................................................................................................................23 1.9.1 Salida con Formato: Console.WriteLine.............................................................................................. 23 1.9.2 Entrada con Formato: Console.ReadLine y Console.Read.................................................................. 26 1.10 COMENTARIOS, INDENTACIN Y OTROS ASPECTOS VISUALES.....................................................................27 1.10.1 Comentarios ......................................................................................................................................... 27 1.10.2 Indentacin (indexacin) y otros aspectos visuales ............................................................................. 27 1.10.3 Algunos consejos.................................................................................................................................. 28
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 El Lenguaje C# y el Framework de .NET C#(pronunciado C Sharp) es el nuevo lenguaje de propsito general orientado a objetos creado por Microsoft para su nueva plataforma .NET. Microsoft.NET es el conjunto de nuevas tecnologas en las que Microsoft ha estado trabajando estos ltimos aos con el objetivo de mejorar tanto su sistema operativo como su arquitectura de desarrollo anterior, para obtener una plataforma con la que sea sencilla la construccin de software. La plataforma .NET ofrece numerosos servicios a las aplicaciones que para ella se escriban, como son un recoleccin de basura, independencia de la plataforma, total integracin entre lenguajes (por ejemplo, es posible escribir una clase en C#que derive de otra escrita en Visual Basic.NET que a su vez derive de otra escrita en Cobol) Como se deduce del prrafo anterior, es posible programar la plataforma .NET en prcticamente cualquier lenguaje, pero Microsoft ha decidido sacar uno nuevo porque ha visto conveniente poder disponer de un lenguaje diseado desde 0 con vistas a ser utilizado en .NET, un lenguaje que no cuente con elementos heredados de versiones anteriores e innecesarios en esta plataforma y que por tanto sea lo ms sencillo posible para programarla aprovechando toda su potencia y versatilidad. C#combina los mejores elementos de mltiples lenguajes de amplia difusin como C++, J ava, Visual Basic o Delphi. De hecho, su creador Anders Heljsberg fue tambin el creador de muchos otros lenguajes y entornos como Turbo Pascal, Delphi o Visual J ++. La idea principal detrs del lenguaje es combinar la potencia de lenguajes como C++con la sencillez de lenguajes como Visual Basic, y que adems la migracin a este lenguaje por los porgramadores de C/C++/J ava sea lo ms inmediata posible. Adems de C#, Microsoft propociona Visual Studio.NET, la nueva versin de su entorno de desarrollo adaptada a la plataforma .NET y que ofrece una interfaz comn para trabajar de manera cmoda y visual con cualquiera de los lenguajes de la plataforma .NET (por defecto, C++, C#, Visual Basic.NET y J Script.NET, aunque pueden aadirse nuevos lenguajes mediante los plugins que proporcionen sus fabricantes). 1.1 Microsoft .NET Framework 1.1 El Framework de .Net es una infraestructura sobre la que se rene todo un conjunto de lenguajes y servicios que simplifican enormemente el desarrollo de aplicaciones. Mediante esta herramienta se ofrece un entorno de ejecucin altamente distribuido, que permite crear aplicaciones robustas y escalables. Los principales componentes de este entorno son: Lenguajes de compilacin Biblioteca de clases de .Net CLR (Common Language Runtime) Actualmente, el Framework de .Net es una plataforma no incluida en los diferentes sistemas operativos distribuidos por Microsoft, por lo que es necesaria su instalacin previa a la ejecucin de programas creados mediante .Net. El Framework se puede descargar gratuitamente desde la web oficial de Microsoft (ver link de descarga en los recursos del final). 1.1.1 Lenguajes de Programacin .Net Framework soporta mltiples lenguajes de programacin y aunque cada lenguaje tiene sus caractersticas propias, es posible desarrollar cualquier tipo de aplicacin con cualquiera de estos lenguajes. Existen ms de 30 lenguajes adaptados a .Net, desde los ms conocidos como C#(C Sharp), Visual Basic o C++hasta otros lenguajes menos conocidos en el mundo microsoft como son Perl o Cobol. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 2 1.1.2 Common Language Runtime (CLR) El CLR es el verdadero ncleo del Framework de .Net, ya que es el entorno de ejecucin en el que se cargan las aplicaciones desarrolladas en los distintos lenguajes, ampliando el conjunto de servicios que ofrece el sistema operativo estndar Win32. La herramienta de desarrollo compila el cdigo fuente de cualquiera de los lenguajes soportados por .Net en un mismo cdigo, denominado cdigo intermedio (MSIL, Microsoft Intermediate Language). Para generar dicho cdigo el compilador se basa en el Common Language Specification (CLS) que determina las reglas necesarias para crear cdigo MSIL compatible con el CLR. 1.1.3 Biblioteca de clases de .Net Cuando se est programando una aplicacin muchas veces se necesitan realizar acciones como manipulacin de archivos, acceso a datos, conocer el estado del sistema, implementar seguridad, etc. El Framework organiza toda la funcionalidad del sistema operativo en un espacio de nombres jerrquico de forma que a la hora de programar resulta bastante sencillo encontrar lo que se necesita. Para ello, el Framework posee un sistema de tipos universal, denominado Common Type System (CTS). Este sistema permite que el programador pueda interactuar los tipos que se incluyen en el propio Framework (biblioteca de clases de .Net) con los creados por l mismo (clases). De esta forma se aprovechan las ventajas propias de la programacin orientada a objetos, como la herencia de clases predefinidas para crear nuevas clases, o el polimorfismo de clases para modificar o ampliar funcionalidades de clases ya existentes. Este resumen fue extrado de: http://www.desarrolloweb.com/articulos/1328.php?manual=48 1.2 Estructura de un programa en C# La declaracin de un programa en C#se centra en la definicin de clases que estarn involucradas en la lgica de la solucin. Este programa puede contener cuantas clases se estime necesarias, y al menos una de ellas debe contener el algoritmo principal o Main(). En pocas palabras, la estructura general y simplificada de un programa en C#es la siguiente: se declaran las libreras cuyas clases se referencian en el programa, luego se declaran las clases requeridas con todos sus detalles, y finalmente, la clase principal (que en muchos casos es la ms simple y de corta declaracin), cuyo principal y a veces nico contenido es el mtodo Main(), tambin conocido como algoritmo principal. Este Main() es obligatorio en todo programa, y ser llamado en forma implcita cuando la ejecucin del programa d inicio. [declaracin de namespaces o libreras de clases (externas) requeridas]
[declaracin clase 1] [declaracin clase 2] ... [declaracin clase N o principal] [algoritmo principal o Main()] En la declaracin de un programa, todos los elementos definidos se etiquetan con nombres propios, que se conocen como identificadores. Estos identificadores son asignados arbitrariamente por el programador, siempre cumpliendo algunas reglas que se describen a continuacin. 1.2.1 Ejemplo de un programa en C# El programa ms simple de todos: Hola Mundo, el cual slo contiene una clase principal. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 3 using System; // Referencia al namespace de clases y mtodos ms usado
// Se declara una clase nica y exclusivamente para alojar el Main(). class MainApp {
// Funcin principal, Main() public static void Main() {
// Escribe el texto a la consola. Console.WriteLine("Hola Mundo, estoy hecho en C#!"); Console.ReadLine(); // Espera un ENTER para cerrar } } Como se ve en el trozo de cdigo anterior, todo en C#pertenece a una clase, y por ende, obliga totalmente a tener un enfoque orientado a estos objetos.
1.3 Identificadores Los identificadores son los nombres con que se identifica a los distintos objetos dentro de un programa, como ser: Clases. Instancias. Namespaces. Funciones o mtodos. Variables, campos o propiedades. Constantes. Estructuras de datos. En C#, los identificadores siguen las reglas para identificadores recomendados en el Anexo 15 del Unicode Standard, es decir, cada identificador puede contener: Letras (las del alfabeto maysculas y minsculas, menos la , y las acentuadas). No es posible emplear acentos o caracteres especiales del alfabeto espaol. Dgitos numricos (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) Smbolo de subrayado ( _ ) Adicionalmente, en casos especiales, se puede utilizar el smbolo @ al comienzo de un identificador, cuando ste es una de las palabras claves. Sin ese smbolo, ningn identificador puede ser igual al conjunto de palabras reservadas del lenguaje C#. Ntese, que a diferencia de otros lenguajes, C#as como sus antecesores (C, J ava, etc.) son sensibles a las maysculas, es decir, se considera var1 y VAR1, e incluso Var1, son identificadores totalmente distintos.
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 4 Las palabras reservadas en C#son las siguientes. abstract event New struct as explicit Null switch base extern object this bool false operator throw break finally out true byte fixed override try case float params typeof catch for private uint char foreach protected ulong checked goto public unchecked class if readonly unsafe const implicit ref ushort continue in return using decimal int sbyte virtual default interface sealed volatile delegate internal short void do is sizeof while double lock stackalloc else long static enum namespace string
1.3.1 Algunas consideraciones al definir identificadores En la prctica, la letra de subrayado ( _ ) se emplea para dar mayor legibilidad a nombres compuestos por varias palabras. Adems, se acostumbra emplear letras minsculas para nombrar a las variables y las maysculas se usan al comienzo de una palabra en funciones declaradas con identificadores compuestos. Se recomienda elegir nombres que sean representativos del elemento (atributo o mtodo) que se defina o del valor que la variable guarde. Por ejemplo, una variable que guardar la edad de un empleado podra llamarse edad_empleado o edad, y no simplemente xyz, aunque ste es un identificador vlido y el programa funcionar correctamente este nombre. 1.3.2 Ejemplos de identificadores Los siguientes son todos identificadores vlidos en C#. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 5 puntero nombre_empleado area TAMANO_STRING EdadEmpleado potencia10 i For iF While Nombre nombre Los siguientes son identificadores invlidos. Entre parntesis se indica por qu. nombre-empleado (no se puede usar el guin, slo el subrayado) telfono (no se pueden usar caracteres especiales del Espaol) while (sta es una palabra reservada del lenguaje C#) Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 6 1.4 Declaracin de Clases y sus Elementos Todos los elementos en cualquier programa en C#pertenecen a una clase. Por ello, lo primero que siempre se debe hacer es declarar cada una de las clases que se requerirn. Eventualmente es factible declarar un programa con una nica clase, que contendr su funcin principal. La sintaxis para la declaracin de una clase tiene la siguiente forma: [modificadores] class <classname> [: nombreclasebase] { [cuerpo de la clase] }[;]
Ejemplo bsico: class persona { private string nombre; private int edad;
public void ImprimirNombre() { Console.WriteLine(Nombre: {0}, nombre); } }
La lnea base de la declaracin de una clase describe el nombre, los modificadores y atributos, y la clase desde la cual se est heredando. Aqu se identifican como opcionales todos aquellos elementos entre corchetes. Los modificadores pueden ser: public, private, o nada. El nombre de la super clase o clase base, es cualquier nombre que se haya asignado a otra clase. 1.4.1 Visibilidad/accesibilidad de una clases y sus miembros Cada clase puede pertenecer a un grupo de clases llamado Namespace. A su vez, cada clase se compone de elementos, como atributos y mtodos, que forman parte del cuerpo de su declaracin y que se revisan en la siguiente seccin. Cada uno de stos, ya sea la clase o bien los atributos o mtodos, pueden ser acotados en su visibilidad o accesibilidad, lo cual limita su uso desde mbitos fuera de la clase o del namespace. Dicho de otra manera, si una clase contiene elementos que son privados, stos son slo visibles para los otros elementos dentro de la misma clase, pero no para otros objetos de otras clases. Por el contrario, si la clase contiene elementos pblicos, stos pueden ser visibles desde instancias de otras clases. Para determinar la visibilidad o accesibilidad que se tendr a un elemento en particular, se antepone el trmino: private o public, para explicitar su condicin. En el caso de las clases, al no explicitar nada, se asume que son public. Por el contrario, en el caso de los elementos de una clase, como atributos o mtodos, al no explicitar nada, se asumen como private. Por lo tanto, en la declaracin del ejemplo bsico de clase anterior, la clase persona, es pblica en su mbito; sus dos atributos, nombre y edad son explcitamente declarados como privados, y finalmente el mtodo ImprimirNombre es implcitamente privado, al no haberse declarado expresamente su accesibilidad. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 7 1.4.2 Elementos de una Clase El cuerpo de la declaracin de la clase se compone de los miembros de sta. Entre los miembros se encuentran campos, propiedades, mtodos, constantes, operadores, entre otros varios elementos. Campos: son aquellos atributos de la clase, definidos por un tipo de dato y un identificador. En el ejemplo bsico anterior, nombre es un campo de tipo string (cadena de texto), que es privado a la clase. Mtodos: secuencias de instrucciones que actan sobre los datos del objeto, o valores de los campos. Propiedades: se les conoce tambin como campos inteligentes, ya que son mtodos que se ven como campos de la clase. Esto permite que al utilizar una instancia de esta clase se logre un mayor nivel de abstraccin, ya que no se requiere saber si se accesa un campo directamente o se est ejecutando un mtodo de acceso. Constantes: tal como lo sugiere su nombre, se trata de campos que no pueden ser modificados durante la ejecucin del programa. El valor de la constante se declara junto con la definicin de la clase, por lo que es un valor que debe ser conocido previamente a la ejecucin del programa. Una alternativa para definir campos de valor fijo es usar el modificador readonly, que permite inicializar el valor de un campo en el constructor de la clase, para luego quedar fijo para cualquier efecto posterior. Estos ltimos dos tipos de elementos se vern en detalle en el captulo IV, Programacin OO con C#. 1.4.3 Campos Para poder resolver un problema empleando un computador es necesario contar con algn mecanismo para almacenar datos en forma temporal. Esto se logra con las variables, las que en el caso de ser parte de una clase, se les conoce como campos o atributos. En C#, las variables reciben nombres que respetan las reglas de los identificadores. Adems, toda variable debe tener un tipo de dato asociado, que define bsicamente la clase de dato que se almacenar en ella y la forma en que deber ser tratado. Como se ver ms adelante, toda variable debe ser declarada previamente a su uso dentro del programa, y esto debe hacerse respetando una sintaxis establecida. En resumen: Una variable es un objeto que almacena un dato, es asociado a un identificador y a un tipo. La forma genrica es la siguiente:
Donde <tipo> puede ser: int, float, char, entre otras posibilidades. [] significa opcional. <valor_inicial> puede corresponder a una constante del tipo entero, real, caracter, arreglo, etc. <modificador> puede ser una de las siguientes posibilidades: public, protected, private, static, const, readonly; que corresponden a descripciones del comportamiento de esta variable en relacin al resto de los elementos del programa. Ejemplos de declaraciones de variables: int numero; char sigla; string nombre;
Ejemplos de declaraciones de variables asociadas a un dato: Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 8 int numero = 10; char sigla = G; string nombre = Juan;
Ejemplos de declaraciones de variables con modificadores: public int numero = 10; // Visible para otros objetos private char sigla = G; // Invisible para otros objetos const string nombre = Juan; // Valor fijo, constante
Los modificadores private, public, protected definen la visibilidad que tendrn otros objetos de tener acceso a dichos campos. Por otro lado, const, readonly, se refieren a la factibilidad de poder modificar el valor del campo una vez inicializado o definido. Finalmente, static define el comportamiento de todas las instancias de la misma clase, y el tratamiento que puedan tener sobre el campo en cuestin. 1.4.4 Tipos de Datos Cada uno de los distintos objetos que son manipulados dentro de un programa tiene asociado un tipo de datos. Desde el punto de vista de almacenamiento o para llevar a cabo operaciones sobre estos objetos, es necesario tratarlos de distinta manera. As, la mayora de los lenguajes de programacin separan aquellos objetos que son caracteres de los que son nmeros enteros y nmeros con decimales. Para la plataforma .NET, los tipos de datos bsicos son los siguientes, varios de los cuales sirven para representar cantidades numricas, y otros para representar texto y otros. Categora Nombre de la Clase Descripcin Tipo de Dato C# Nmero Entero Byte Entero sin signo (de 8 bits). Valores de 0 a 256. byte SByte Entero (de 8 bits). Valores de -127 a 128. sbyte Int16 Entero (de 16 bits). Valores de -32767 a 32768. short Int32 Entero de 32 bits int Int64 Entero de 64 bits long UInt16 Entero sin signo de 16 bits.. ushort UInt32 Entero sin signo de 32 bits. uint UInt64 Entero sin signo de 64 bits. ulong Nmeros reales (con decimales) Single Nmero con decimales de precisin simple (32 bits). float Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 9 Double Nmero con decimales con precisin doble (64 bits) double Lgicos Boolean Un valor booleano, verdadero o falso (true/false) bool Otros Char Un carcter o smbolo Unicote (16 bits) char Decimal Un valor decimal de 96 bits decimal Class objects Object La raz de la jerarqua de objetos. object String Una cadena de caracteres inmutable, de largo fijo. string
En el caso del lenguaje de programacin C#, los tipos de datos ms empleados son: Los tipos enteros: int, short y long para manipular nmeros enteros. Los tipos reales: float y double. El tipo: char (a,z,?,$,@,G,7, etc.; en total los 256 caracteres del cdigo ASCII) para caracteres, letras y smbolos. As como algunos ms complejos como los strings y arreglos. Es importante recordar que todo objeto dentro de un programa tiene un tipo de datos asociado, y es necesario tener esta asociacin en mente a la hora de manipular, almacenar, operar y hasta desplegar en pantalla dicho objeto. 1.4.4.1 Tipos enteros Las variables de tipos de datos enteros pueden almacenar nicamente valores numricos sin decimales. Si se intenta almacenar un valor con decimales en una variable entera, se producir un truncamiento del valor. El tipo entero bsico es int. Existen adems las variantes short que permite almacenar valores ms pequeos (con el consiguiente ahorro de espacio en memoria), y el long, que soporta nmeros ms grandes (pero con mayor gasto de memoria). El valor mximo que se puede almacenar en las variables de cada uno de estos tipos depende de la arquitectura del computador y del compilador que se estn empleando. Constantes de Tipo Entero Para declarar valores constantes de tipo entero, hay que reconocer si se trata de enteros de tipo int, o long. Por ejemplo, la inicializacin de las siguientes dos variables considera un valor escrito como constante entera, diferenciando que para el int, se usa un nmero simple y para el long, se agrega una L al final: int n1 = 10; long n2 = 120390L;
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 10 1.4.4.2 Tipos reales Las variables de tipos de datos reales pueden almacenar valores numricos con decimales. El tipo real bsico es float. Existe tambin la variante double, que permite almacenar valores en doble precisin, ms grandes y con mayor cantidad de decimales. Sin embargo, el uso de este tipo provoca un mayor gasto de memoria que si se empleara el tipo bsico float. La cantidad de decimales, as como el valor mximo que se puede almacenar en variables de estos tipos depende de la arquitectura del computador y del compilador que se estn empleando. Constantes de Tipo Real Al igual que en el caso de los enteros, los valores constantes de tipo real se diferencian en su declaracin al identificarse como float o double, an cuando ambos usan valores decimales en su declaracin. El caso de los floats requiere agregar una F al final, tal como se indica en el siguiente ejemplo: float n1 = 10.0F; double n2 = 120.390; 1.4.4.3 Caracteres: Tipo de datos char Las variables de tipos de datos char, pueden almacenar un caracter del cdigo ASCII extendido (256 caracteres). En realidad, lo que se guarda no es el caracter en s, sino el cdigo correspondiente. Por lo tanto, puede verse al tipo char como un subtipo del tipo int, que puede almacenar enteros entre 0 y 255. De hecho, las expresiones de tipo char pueden manipularse como enteros. Las constantes de tipo char se representan delimitadas por comillas simples. As, para escribir el caracter que representa la letra A mayscula escribimos: 'A' El hecho de que las expresiones de tipo char se consideren como enteros permite llevar a cabo conversin de tipos entre expresiones char y expresiones int. Por ejemplo, es posible llevar a cabo las siguientes asignaciones, las cuales son todas equivalentes y almacenan en la variable correspondiente la letra A mayscula (cdigo ASCII 65). char ch; int i;
ch = 65; i = 'A';
ch = 'A'; i = 65; Adems, puede emplearse el smbolo \ para denotar caracteres mediante su cdigo ASCII. Con esta notacin, el caracter 'A' puede representarse tambin como '\65' Esta notacin es muy til para representar caracteres especiales, que no aparecen en los teclados y no se pueden ver en la pantalla. Este es el caso del caracter nulo (ASCII 0): '\0', el cual se emplear ms adelante para indicar el final de los strings. As, las siguientes son representaciones equivalentes en C para el caracter constante que representa la letra A mayscula: 'A' 65 '\65' Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 11 La preferencia en usar la tercera notacin y no la segunda es por simple claridad, para dejar bien claro que se est manipulando un caracter y no un nmero (aunque para el C es lo mismo). Otros caracteres especiales que se pueden representar mediante esta notacin son: '\n': Caracter de nueva lnea (a veces usado en Console.WriteLine, ms adelante) '\t': Tabulador (tambin til en Console.WriteLine) '\\': Caracter \ (esta es la nica forma de especificarlo) Ms interesante resulta la manera de organizar los caracteres como cadenas de char, de manera que puedan manipularse cadenas de texto (string). Las cadenas de texto se especifican entre comillas dobles: "iic1102 seccin". 1.4.5 Mtodos o Funciones Una funcin, genricamente se describe como un conjunto de instrucciones (posiblemente acompaadas de algunos datos temporales), que llevan a cabo una subtarea dentro de un programa ms complejo. Un mtodo es una funcin que pertenece a una clase en particular. Por ejemplo, dentro de un programa que convierte una lista de temperaturas expresadas en grados Fahrenheit, a grados Celsius, podramos definir una funcin que haga una de las conversiones, y la emplearamos varias veces para lograr completar nuestra tarea. Tenemos entonces que las funciones dentro de un programa cumplen con subtareas, para las cuales es necesario suministrarles algunos datos de entrada, y luego de completadas, recibiremos como resultado algunos datos de salida. Para el caso de una funcin que calcula el rea de un crculo, la entrada que requiere la funcin sera el radio del crculo, y la salida que arrojara luego del cmputo sera el valor para el rea. Este hecho se ilustra en el diagrama que se muestra abajo, en el que podemos ver la tarea de transformacin de datos que cumple una funcin: La alimentamos con una entrada y recibimos una salida en respuesta. Por otra parte, para especificar el proceso de transformacin que debe llevar a cabo la funcin, es necesario emplear las instrucciones del lenguaje de programacin. Es necesario respetar algunas pautas, tanto para la especificacin de los parmetros de entrada, como del valor de retorno, pero la estructura general es la misma. 1.4.5.1 Sintaxis de la definicin de Funciones o Mtodos La sintaxis general de definicin de mtodos es la siguiente: <accesibilidad> <tipo_retorno> <nombre_funcin> ( <lista_parmetros> ) { <declaracin_de_variables_locales> ; <cuerpo_de_la_funcin> ; return (<valor_retorno>) ; } <accesibilidad>se refiere a la visibilidad que tienen otras partes de un programa para ejecutar el mtodo. Las posibilidades son public, private, protected, lo cual define la accesibilidad que se tiene a este mtodo desde otras clases. <tipo_retorno> es el tipo del valor que devolver la funcin. Es posible definir funciones que no devuelven ningn valor (para por ejemplo definir funciones que solo imprimen valores o ciertos mensajes en pantalla, para los que no es necesario que devuelva valor alguno). Para definirlos o declararlos, se utiliza como tipo de retorno la palabra reservada void. A estas funciones se las conoce tambin como procedimientos, porque no devuelven ningn valor. <nombre_funcin> debe ser sustituido por un identificador que corresponde al nombre con que se invocar la funcin posteriormente (o llamada de la funcin). Debe ser un identificador vlido. El valor de retorno de la funcin es asociado al nombre de la funcin. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 12 <lista_parmetros>corresponde con una lista de variables denotadas por identificadores asociados a un tipo, cada uno representa un parmetro de entrada. La lista de parmetros puede ser vaca pero los parntesis deben aparecer. La <declaracin_de_variables_locales> se refiere a variables locales que podrn ser utilizadas nicamente dentro de la funcin. Fuera de ella, no sern reconocidas. El <cuerpo_de_la_funcin>es una lista de instrucciones, separadas por punto y coma. <valor_retorno>, debe ser una expresin (constante, aritmtica, lgica del tipo que se especific como <tipo_retorno>, y establece la expresin que retornar la funcin una vez que haya terminado. 1.4.5.2 Ejemplos: Definicin de Funciones Funcin que convierte temperaturas Funcin que calcula el rea de un crculo
// Funcin que recibe una temperatura expresada en grados Fahrenheit y // retorna su equivalente en grados Celsius. El argumento de entrada es // farenheit de tipo int. El valor de retorno tambin es de tipo int. // La frmula de conversin es C=(F-32)*(5/9). Puede ocurrir truncamiento. int celsius(int fahrenheit) { return((fahrenheit-32.0)*(5.0/9.0)); }
// Funcin que recibe una temperatura expresada en grados Celsius y retorna // su equivalente en grados Faherenheit. El argumento de entrada es celsius // de tipo int. El valor de retorno tambin es de tipo int. // La frmula de conversin es F=32+(C*9/5). Puede ocurrir truncamiento. int fahrenheit(int celsius) { return((celsius*9.0/5.0)+32.0); }
// Funcin que calcula el rea de un crculo dado su radio. Tanto el // argumento de entrada (radio) como el valor de retorno es de tipo // float. La frmula implementada es A=Pi*R*R. float area(float radio) { return(3.14 * radio * radio); } 1.4.6 Sintaxis de la llamada a las Funciones definidas La sintaxis general de las llamadas a las funciones definidas es la siguiente:
<variable> = <nombre_funcin> ( <lista_parmetros> ) ; <variable> corresponde a una variable denotada por un identificador del mismo tipo del valor que devolver la funcin. <nombre_funcin>es el identificador que corresponde al nombre con que se invoca a la funcin. <lista_paramtros>debe corresponder a una lista de variables denotadas por identificadores asociadas a un tipo, o expresiones de un tipo. Ya sean variables o expresiones, stas deben corresponder en cuanto a cantidad, posicin y tipos a las variables que se definieron como parmetros de entrada en la definicin de la funcin. Representan los valores que se entregan como entrada a la funcin. Si en la definicin de la funcin no se us parmetro alguno, entonces en la llamada tampoco debe escribirse ninguna expresin o variable, pero los parntesis deben aparecer. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 13
// Llamada a la Funcin que recibe una temp. expresada en grados Fahrenheit y // retorna su equivalente en grados Celsius. El argumento de entrada es // fahrenheit de tipo int. El valor de retorno tambin es de tipo int. // La frmula de conversion es C=(F-32)*(5/9). Puede ocurrir truncamiento. int grados_celsius ; grados_celsius = celsius(int fahrenheit) ;
// Llamada a la Funcin que recibe una temp. expresada en Celsius y retorna // su equivalente en grados Faherenheit. El argumento de entrada es celsius // de tipo int. El valor de retorno tambin es de tipo int. // La formula de conversin es F=32+(C*9/5). Puede ocurrir truncamiento. int grados_farenheit ; grados_farenheit = fahrenheit(31) ;
// Llamadas a la funcin que calcula el rea de un crculo dado su radio. // Tanto los argumento de entrada (radio) como el valor de retorno son // del tipo float. La frmula implementada es calculo_area = Pi*R*R. float calculo_area ; float radio = 5.56 ;
1.4.7 La funcin principal Main() y los programas en C# Un programa en C#, est formado por una o ms clases, que a su vez cuentan con una o ms funciones compuestas de varias instrucciones. Estas funciones que realizan una tarea en particular con los parmetros de entrada, devuelven valores que corresponden a sus resultados, que a su vez son utilizados en otras funciones o mtodos. El computador debe empezar a ejecutar en algn orden estas instrucciones. En el caso de un programa, se comienza por referenciar los namespaces usados, que van en las primeras lneas con la sintaxis using namespace; Luego se registran todas las clases definidas, con sus atributos y mtodos, y luego se llega a la funcin Main(). Esta funcin consta tambin de declaraciones, instrucciones y llamadas a las definiciones de otras funciones e instanciaciones de clase. El orden de ejecucin de las instrucciones dentro de la funcin Main() es secuencial de arriba a abajo y es as como es posible recin seguir la ejecucin del resto de las funciones. 1.4.8 Ejemplo en C#de la simulacin de compra de un boleto en el metro.
using System;
class Boleteria {
const int precio1 = 190; const int precio2 = 250; const int precio3 = 290;
private int cambio = 0;
public void ComprarBoleto(int valor, int dinero_en_mano) { Console.WriteLine("Alcanzo {0} pesos al vendedor.", dinero_en_mano); cambio = dinero_en_mano - valor; }
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 14 public int PreguntarHorario() { int hora; Console.WriteLine("Que horario es (1 = baja, 2 = media, 3 = alta ) ? "); hora = int.Parse(Console.ReadLine()); return(hora); }
// PrecioBoleto: indica el valor del boleto, segn la hora indicada public int PrecioBoleto(int hora) { int precio = 0; if (hora == 1) precio = 190; if (hora == 2) precio = 250; if (hora == 3) precio = 290; Console.WriteLine("Para la hora baja el precio del boleto es {0} ", precio); return(precio); }
public void TomarCambio() { Console.WriteLine("Recibo cambio de {0} pesos", cambio); }
}
class Bolsillo {
private int en_la_mano = 0;
public void SacarMonedas(int moneda) { Console.WriteLine("Tomo una moneda de {0} de mi bolsillo ", moneda); en_la_mano = en_la_mano + moneda; }
public int EnLaMano() { return (en_la_mano); } }
class MainApp {
static void Main() {
Boleteria boleteria = new Boleteria(); Bolsillo bolsillo = new Bolsillo(); int hora; int valor;
hora = boleteria.PreguntarHorario(); valor = boleteria.PrecioBoleto(hora);
// Se sacan las monedas ($300) del bolsillo bolsillo.SacarMonedas(100); Console.WriteLine("Tengo {0} pesos en la mano ", bolsillo.EnLaMano()); bolsillo.SacarMonedas(100); Console.WriteLine("Tengo {0} pesos en la mano ", bolsillo.EnLaMano()); bolsillo.SacarMonedas(100); Console.WriteLine("Tengo {0} pesos en la mano ", bolsillo.EnLaMano());
Console.WriteLine("Gracias por su compra. Presione Enter para terminar"); Console.ReadLine(); } }
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 15
1.5 Expresiones Se conocen como expresiones los valores que son manipulados dentro de un programa. Estos valores pueden surgir como resultado de efectuar operaciones, como valores de retorno de las funciones, al extraerlos de las variables, o simplemente pueden ser constantes expresadas directamente dentro del cdigo del programa. Las expresiones, al igual que el resto de las entidades dentro de un programa, tienen asociado un tipo de datos. Este tipo indicar la forma en que podremos manipular la expresin, por ejemplo, en cules variables podremos almacenar su valor. Existe un conjunto de operadores para cada tipo de datos, de manera que siempre es posible construir una nueva expresin a partir de una o varias ya existentes. Tenemos, por ejemplo, operadores aritmticos para construir expresiones numricas, y operadores lgicos para construir expresiones booleanas. 1.5.1 Expresiones Aritmticas Las expresiones aritmticas son valores numricos, de tipos enteros o reales. Pueden ser constantes, resultados de operaciones aritmticas como sumas o multiplicaciones, contenido de variables numricas, o combinaciones de las anteriores unidas mediante operadores aritmticos. Operadores binarios: + Suma
- Resta
* Multiplicacin
/ Divisin
% Mdulo (slo sobre tipos de nmeros enteros) Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 16 Operadores unitarios: - Signo negativo
++ Incremento
-- Decremento Precedencia: ++ -- -(unitario)
* / %
+ - Asociatividad: Por la izquierda
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 17 Expresiones Los operandos pueden ser variables o constantes numricas. Sin embargo, los operadores unarios ++y - - fueron pensados para aplicarse a variables y el operador unario - a constantes. operando operador-binario operando
operador-unario operando
Caso particular: ++ -- (notacin pre o postfija)
Ejemplos de expresiones aritmticas: 2 + 3 * 2 * tiene precedencia sobre + (Resultado: 8) (2 + 3) * 2 los parntesis alteran la precedencia (Resultado: 10) -2 / x si x vale cero se producir un error de ejecucin x++ notacin postfija (retorna el valor antes del incremento) ++x notacin prefija (retorna el valor despus del incremento) 2 - 1 + 3 asociatividad por la izquierda: 4 15 % 6 operador mdulo o residuo (Resultado: 3) -x le cambia el signo al contenido de x 3 * 4 % 5 igual precedencia, pero asociativa a izq. (Retorna: 2) 3 * (4 % 5) los parntesis alteran la precedencia (Retorna: 12) 1 + 15 % 6 % tiene precedencia mayor (Retorna: 4)
El resultado de una operacin siempre debe ser almacenado en otra variable, o utilizado en alguna funcin como parmetro. Ej: class MainApp { static void Main() { int a, b, c; c = a + b; // Correcto Console.WriteLine({0}, a + b); // Correcto a + b; // Error } } 1.5.2 Operadores Compuestos Un operador compuesto es una combinacin entre un operador binario, junto con un operador de asignacin (=). La sintaxis general es: x op= y; lo cual es totalmente equivalente a x = x op y; Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 18 Por ejemplo: int a, b; b = 10; a = 3; a += b; Console.WriteLine({0}, a); // Imprime 13 1.5.3 Expresiones Relacionales, Lgicas o Booleanas Este tipo de valores se emplea para dirigir al programa por un determinado flujo de ejecucin dependiendo de la evaluacin a verdadero o falso de una expresin lgica. En C#se conoce el tipo booleano como bool. Operadores binarios: && AND (hace la conjuncin lgica de dos valores bool). || OR (hace la disyuncin lgica de dos valores bool). Operadores unitarios: ! NOT lgico
Operadores relacionales o de comparacin: Este tipo de operadores permite comparar el valor de dos expresiones de cualquier tipo, devolviendo como resultado un valor booleano (entero). == igual
!= distinto
< menor
<= menor o igual
> mayor
>= mayor o igual
Precedencia: La precedencia est establecida por el siguiente orden de evaluacin. La asociatividad se aplica de izquierda a derecha, para operadores con igual precedencia. < <= >= >
== !=
&&
||
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 19 Expresiones Los operandos de las expresiones booleanas son valores booleanos, incluyendo aquellos que resulten de la comparacin mediante los operadores relacionales mencionados anteriormente. Pueden emplearse parntesis para dejar clara la precedencia de evaluacin. operando operador-lgico-binario operando
operador-lgico-unario operando
Ejemplos de expresiones booleanas: x Verdadero cuando el contenido de la variable x es true.
!x Verdadero cuando el contenido de la variable x es false.
true Verdadero siempre.
true || x Verdadero siempre, no importa lo que sea x.
false Falso siempre.
false && x Falso siempre, no importa lo que sea x.
(x > 5) && !y Verdadero cuando el contenido de la variable x es mayor que 5, y el contenido de y es false.
(x==1) Verdadero si el valor de la variable x es 1.
5 == 6 retorna Falso. 4 > = 2 Retorna Verdadero. ((4 % 2 == 0) || (4 % 3 == 0)) && false 1.5.4 Precedencia de todos los operadores Mxima ( ) [ ] - - ! ~ ++ -- * / % + - << < <= >= > == = & | && || = += -= /= Mnima Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 20 1.6 Instrucciones Las instrucciones son las rdenes que reconoce un computador mientras se encuentra ejecutando un programa. De hecho, un programa es una secuencia de instrucciones que al ejecutarse resuelve algn problema para el usuario. Los programas estn escritos en un lenguaje de programacin, el cual define el conjunto de instrucciones vlidas que podemos utilizar al escribirlos. En nuestro caso emplearemos el lenguaje de programacin C#, por lo que ser necesario que estudiemos las instrucciones que componen dicho lenguaje. A lo largo del curso vamos a ir introduciendo estas instrucciones de manera paulatina, hasta llegar a cubrir un subconjunto bastante importante del lenguaje. Las instrucciones disponibles pueden clasificarse dentro de alguna de las siguientes categoras: Secuenciales Ejemplos: declaraciones de variables, asignaciones, llamado a funciones, salida (Console.WriteLine) y entrada (Console.ReadLine) Control de flujo (o decisin) Ejemplos: if, switch Iteracin Ejemplos: for, while, do-while, foreach
Sintaxis La sintaxis de las instrucciones en C#vara bastante dependiendo de cada instruccin. En general, toda instruccin debe ir terminada por un punto y coma, de la siguiente manera: <instruccion>; Existen instrucciones complejas que pueden abarcar varias lneas, y que pueden contener otras instrucciones dentro de ellas en forma subordinada. Adems, las instrucciones se pueden agrupar en bloques, delimitados por corchetes: {}, de la siguiente manera: { <instruccion1> ; <instruccion2> ; ... <instruccionN> ; } 1.7 Operador de Asignacin El operador de asignacin ( =) permite almacenar datos en las variables. Es un operador binario, que requiere que su primer operando (el del lado izquierdo) sea una variable. El segundo operando (el del lado derecho) puede ser otra variable, un valor constante, o una expresin en general. La sintaxis general de este operador es la siguiente: <variable>= <expresion>; En caso de que el valor asignado sea una constante, el resultado de esta operacin es que el valor expresado se almacenar en la variable especificada al lado izquierdo. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 21 Si el valor asignado es otra variable, se har una copia del valor almacenado en la segunda variable y se almacenar en la variable del lado izquierdo. Si se trata de una expresin, sta se evaluar previamente y su resultado se almacenar en la variable indicada. En todo caso, es necesario tener en cuenta algunas consideraciones sobre los tipos de las variables y de los valores que se estn asignando. Ms adelante se tratarn los aspectos relativos a la conversin de tipos. Ejemplos indice = 0; Se almacenar el valor 0 en la variable indice suma = a+b; Se obtendr la suma de las variables a y b, y el resultado se almacenar en la variable suma NuevaX = ViejaX; El valor de la variable ViejaX se copiar a la variable NuevaX j = (i = 9) Asigna el valor de 9 a las variables i y j 1.7.1.1 Ejemplo: Intercambio del contenido de dos variables (vasos) En este ejemplo ilustraremos la problemtica de intercambiar el contenido de dos variables. Al igual que cuando nos enfrentamos al problema de intercambiar el contenido de dos vasos, en este caso ser necesario emplear un tercer elemento de almacenamiento (variable o vaso), para guardar temporalmente durante el intercambio uno de los contenidos. El problema del intercambio del contenido de dos variables puede plantearse de manera similar al problema de intercambiar el contenido de dos vasos llenos. La solucin en ambos casos es simple: Se necesita de un tercer elemento de almacenamiento (vaso o variable) para el almacenamiento temporal del contenido.
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 22
using System;
class MainApp {
static void Main() { int var1, var2; // Variables enteras que sern intercambiadas int aux; // Variable auxiliar necesaria para hacer el intercambio var1 = 10; // Asigna valores a las variables var2 = 30;
// Imprime el valor inicial de las variables, antes del intercambio Console.WriteLine("var1 contiene {0} y var2 contiene {1}", var1, var2);
aux = var1; // Paso 1: El valor inicial de var1 se guarda en aux var1 = var2; // Paso 2: El contenido de var2 se pasa a var1 var2 = aux; // Paso 3: El valor inicial de var1 se pasa a var2
// Imprime el valor final de las variables, luego del intercambio Console.WriteLine("var1 contiene {0} y var2 contiene {1}", var1, var2);
Console.Write("Presione ENTER para terminar."); Console.ReadLine(); } }
1.8 Conversin de Tipos (Type Casting) El lenguaje C#permite cambiar el tipo de datos de las expresiones en el momento de llevar a cabo las asignaciones. Por ejemplo, si se asigna una expresin entera a una variable de tipo real, el valor de la expresin se convertir primero al tipo real antes de llevar a cabo la asignacin. Este resulta ser el caso ms simple de una conversin de tipos, pero existen algunas situaciones en las que se requiere de cierta atencin especial: De un tipo real a uno entero Se trunca el valor a su parte entera. La parte decimal se pierde. Asignaciones entre char e int Puesto que en C#se manejan los caracteres mediante su cdigo ASCII (que es un nmero entero), este tipo de asignaciones funciona en general sin problemas.
La forma de realizar la conversin es requerida en forma explcita por C#. Esto se hace siguiendo la siguiente sintaxis: (<tipo>) <expresion> Ejemplo: int a = 2; float b; b = a; // Error: no se puede convertir implcitamente int en float b = (int) a; //Correcto
Ejemplos parte_entera = 7/4; Como todos los valores involucrados son int, a la variable parte_entera se le asignar el Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 23 resultado de la divisin pero truncado: 1 (int)(7.0/4.0) El resultado de esta expresin tambin es 1 7.0/4.0 El resultado de la divisin ser exacto, con todos los decimales 7.0/4 Se convierte el 4 a 4.0 y la divisin arroja decimales x = 7.0/4.0 El resultado de la divisin tendr decimales, pero si la variable x es de tipo entero al asignar el valor habr truncamiento. (float)1 Convierte 1 a tipo float, resultando en 1.0
1.9 Entrada y Salida La mayor parte de los programas interactan con el usuario durante su ejecucin. De esta forma, el usuario puede suministrar al programa sus datos de entrada, y puede recibir de ste los resultados obtenidos. Para llevar a cabo esta interaccin es necesario contar con instrucciones destinadas para tal efecto. C# incluye un conjunto de instrucciones destinadas a llevar a cabo entrada y salida de datos. Quiz las de mayor uso son las orientadas a la entrada y salida de datos con formato (namespace System). Para llevar a cabo salida con formato contamos con la instruccin Console.WriteLine y Console.Write, las cuales permiten desplegar en la pantalla del computador informacin de variados tipos, permitindonos a la vez especificar la forma en que dichos datos debern aparecer (formato). Ambas instrucciones utilizan una serie de caracteres de conversin para especificar el formato que deber tener la informacin de salida. De este modo ser posible interpretarla correctamente. Para obtener entradas con formato disponemos de la instruccin Console.ReadLine y Console.Read, las cuales permiten capturar desde el teclado del computador informacin de variados tipos. 1.9.1 Salida con Formato: Console.WriteLine La funcin Console.WriteLine, permite desplegar datos en la pantalla, con la posibilidad de especificar el formato con que se desea que aparezcan. Esta instruccin se diferencia de Console.Write, en que la primera incluye un cambio de lnea al final, permitiendo comenzar en una nueva lnea al siguiente llamado a la misma instruccin, mientras que la segunda no hace un cambio de lnea al terminar. Sintaxis General: Console.WriteLine("cadena-de-formato",<lista_de_argumentos>); La cadena de formato debe ir delimitada por comillas dobles, y debe incluir una referencia y eventual especificacin de conversin por cada argumento en la lista de argumentos. El texto que se incluya en la cadena de formato aparecer durante el despliegue, y cada especificacin de conversin ser reemplazada por el correspondiente argumento. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 24 La lista de argumentos consiste de una secuencia de expresiones que se desean desplegar. Las expresiones pueden ser variables, constantes u operaciones que deben resolverse antes del despliegue. Tambin es posible especificar llamados a funciones que devuelvan algn valor. 1.9.1.1 Referencia a la Lista de Argumentos En la cadena de formato, se indican los ndices referenciados a la lista de argumentos, especificando el orden en que se mostrarn estos elementos. El primer elemento de la lista corresponde al ndice 0, el segundo al 1, y as sucesivamente. Si por ejemplo se requiere mostrar tres datos en pantalla, se puede hacer de la siguiente manera: int a = 1, b = 2, c = 3; Console.WriteLine(Los valores son: {0}, {1}, {2}, a, b, c); La salida en pantalla de esto sera: 1, 2, 3 Siempre es posible saltarse la cadena de control, cuando el valor a imprimir es uno solo y no se requiere mayor texto. Para imprimir slo la variable a, se usa: Console.WriteLine(a); 1.9.1.2 Especificaciones de Formato Es posible definir cmo se requiere mostrar el valor de una variable en la lista de argumentos, de modo de controlar la esttica de los resultados en pantalla. Este formato depender del tipo de dato que se quiera mostrar, y del espacio que quiera dedicarse en pantalla, lo que ayuda a tabular y organizar la informacin en pantalla en forma ms precisa. La forma de indicar un especificador de formato es agregando informacin en el par de llaves para la referencia de la lista de argumentos, de la forma: {indice:formato}. indice siempre referencia, desde el 0, al primero, segundo, ... elemento de la lista. Formato puede ser uno de los siguientes: - C o c, para formato monetario (tomado de la configuracin de Windows) - D o d, para nmeros enteros (decimales). - E o e, para nmeros en formato de exponente (ej: 1.234E+005) - F o f, para nmeros reales, con parte decimal - G o g, para formato general. - N o n, similar a F, pero con la separacin de miles. - P o p, porcentaje. - R o r, round-trip o viaje redondo, que se usa en nmeros reales. Garantiza que un valor numrico convertido a string ser re-transformado de vuelta sin perder informacin. - X o x, nmero en formato hexadecimal (ej: 1A24C)
Para especificar una cantidad definida de ceros en la parte decimal, se acompaa el formato con un nmero que representa la cantidad de ceros. Ejemplo: int a = 123456; Console.WriteLine({0:F5}, a); // 123456.00000
Para controlar el espacio en que esta informacin se despliega en pantalla, se puede especificar una cantidad de espacios que el dato utilizar en pantalla, e incluso la alineacin. Esto se especifica de la forma: {indice:espacio} Espacio siempre toma el valor de un nmero entero, positivo o negativo, de acuerdo a las siguientes condiciones: Nmero negativo, indica que el campo debe ajustarse a la izquierda. Nmero positivo, indica que el campo debe ajustarse a la derecha. El nmero indicado en espacio, indica la cantidad de espacios en total que debe ocupar el campo. Ejemplo: int a = 123456; Console.WriteLine({0,-15:F5}, a); // 123456.00000 Console.WriteLine({0,15:F5}, a); // 123456.00000 Console.WriteLine({0,10}, a); // 123456
Dentro de la expresin de conversin pueden especificarse las siguientes secuencias que tienen un significado especial: \n - Para provocar que el cursor cambie de lnea \t - Para producir una tabulacin en el despliegue \ASCII - Despliega el caracter con el cdigo ASCII suministrado
Ejemplos: Console.WriteLine("El valor de la variable x es: {0}", x); Desplegar: El valor de la variable x es: 100 (si x contena un valor igual a 100), y avanzar a la siguiente lnea luego del despliegue Console.WriteLine("El valor de dos + cinco es: {0}", 2+5); Desplegar: El valor de dos + cinco es: 7 y avanzar a la siguiente lnea luego del despliegue
Console.WriteLine("El rea de un circulo con radio {0:F2} es {1:F2}", radio, area); Desplegar: El area de un circulo con radio 1.00 es 3.14 (suponiendo los valores indicados para las variables) y avanzar a la siguiente lnea luego del despliegue Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 26 1.9.2 Entrada con Formato: Console.ReadLine y Console.Read La funcin Console.ReadLine, al igual que Console.Read, permite capturar datos desde el teclado, distinguiendo entre ambas por la necesidad de agregar un ENTER al final del ingreso en el caso de la primera. Sintaxis General: string texto; texto = Console.ReadLine(); Usualmente se requiere transformar esta entrada de datos en algn tipo ms razonable de acuerdo al contexto del ejemplo y para ello se utilizan los mtodos nativos de conversin desde texto de los tipos de dato numricos. En dichos casos, la sintaxis es:
<tipo> numero; numero = <tipo>.Parse(Console.ReadLine()); La primitiva Parse(), recibe un string y lo transforma en un valor acorde con el tipo de dato referenciado.
Ejemplos: int edad; Console.Write(Ingrese su edad: ); edad = int.Parse(Console.ReadLine()); Espera un entero que ser almacenado en la variable edad.
float nota; Console.Write(Ingrese su nota: ); nota = float.Parse(Console.ReadLine()); Espera un nmero real (con decimales) que ser almacenado en la variable nota.
string nombre; Console.Write(Ingrese su Nombre: ); edad = Console.ReadLine(); Espera un texto (string) que ser almacenado en la variable nombre.
Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 27 1.10 Comentarios, Indentacin y Otros Aspectos Visuales 1.10.1 Comentarios Con el objetivo de hacer los programas ms legibles, es importante la incorporacin de comentarios que ayuden a comprender lo que hizo el programador. Es importante documentar dentro del programa cualquier aspecto que no quede claro de la simple lectura del cdigo. Los comentarios son IMPRESCINDIBLES. Con este fin, el lenguaje ofrece la posibilidad de incluir dentro del programa cualquier texto que pretenda comentar el cdigo escrito. Este texto puede abarcar una o varias lneas, y debe incluirse dentro de los delimitadores mostrados a continuacin. Sintaxis General: // Comentario simple siempre se separan por lneas, // debiendo comenzar cada nueva lnea con otro par de //
/* Comentario si se usa el asterisco con slash, se puede seguir en varias lneas sin volver a declarar en cada lnea el smbolo de comentarios ... hasta que se termina con */
Ejemplos: /* Programa para calcular ... Escrito por ...
Este ejemplo se refiere al algoritmo que permite calcular el valor de la frmula con los parmetros ... */
int radio; // Guarda el radio del circulo que se usa como referencia
/* La siguiente funcin calcula el rea de un crculo */ float area(float radio) { ...
1.10.2 Indentacin (indexacin) y otros aspectos visuales A pesar de que el lenguaje de programacin C#ofrece una amplia libertad en cuanto a la forma en que pueden escribirse los programas, es necesario establecer algunas normas que ayuden a hacer los programas ms legibles, y por lo tanto ms fciles de comprender y modificar. Aunque no es posible ofrecer una lista exhaustiva de todas las decisiones de formato que un programador debe enfrentar al escribir sus programas, intentaremos establecer algunas pautas, y el resto lo dejaremos para ser percibido a lo largo del curso al estudiar los ejemplos. Ahora bien, las normas aqu mostradas no son absolutas, y reflejan nicamente las preferencias del autor. Existen muchas otras, quiz hasta mejores. Lo importante aqu es adoptar un estndar y respetarlo al mximo posible. De esta forma escribiremos programas correctos, no slo en cuanto a su funcionalidad, sino tambin en cuanto a su apariencia. Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 28 1.10.3 Algunos consejos Dnde poner los corchetes? funcion (argumentos) { ... }
Cmo indentar el cdigo? Los programas normalmente tienen una estructura jerrquica (por niveles), y es importante destacarla al escribirlos. Esto se logra mediante indentacin, es decir, dejando algunos espacios entre el cdigo que esta en un nivel y el del siguiente nivel. Pero cundo indentar?. Lo ms sencillo es mirar los ejemplos. Una regla sencilla es que cada vez que se abran corchetes se estar creando un nuevo nivel y por lo tanto es necesario indentar. Por ejemplo: static void Main () { ... while (...) { ... for (...) { ... } ... } ... }
Para ponerle nombre a las cosas Trate siempre de que el nombre ayude a comprender la funcin del objeto que est identificando. Por ejemplo, una variable que almacena la edad de un empleado podra llamarse Edad, o mejor an EdadEmpleado, y no simplemente x. Las funciones deben tener nombres activos, como CalculaPension, y no simplemente Pension, o peor an un nombre sin sentido. Cuanto ms significativos sean los nombres, menor ser la cantidad de comentarios que deber incluir. Cundo poner comentarios? Es importante iniciar todo programa con un comentario en el que se explica lo que hace el programa de manera general, cules son sus entradas y cules sus salidas, as como las restricciones que tiene, si es que existen. Toda funcin deber tener un comentario similar. Adems, aquellas variables cuyo nombre no sea lo suficientemente explcito, debern tener un comentario sobre su objetivo en la declaracin. Por ejemplo: /* Programa para ... El programa lee del usuario ... ... y le devuelve como respuesta ... Restricciones: No es posible ... */
int x; /* Almacena el valor para ... */
int EdadEmpleado; /* Obvio: No hace falta comentario */
/* Funcion para .... */ ...
/* Funcion para .... */ Intro. Prog. Orientada a Objeto Sintaxis en C# Rodrigo Sandoval U. IIC 1102 Pgina: 29 ...
/* Funcion principal: Hace lo siguiente ... */ main() {
/* Dentro del codigo tambien puede haber comentarios, para explicar aspectos que pueden ser dificiles de comprender */ }
Material preparado por Rodrigo Sandoval U en Marzo y Agosto 2004
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo III Programacin Orientada a Objetos
1 PROGRAMACIN ORIENTADA A OBJETOS............................................................................................. 1 1.1 CONCEPTOS EN ORIENTACIN A OBJETOS......................................................................................................1 1.1.1 Clase....................................................................................................................................................... 1 1.1.2 Objeto..................................................................................................................................................... 1 1.1.3 Relaciones .............................................................................................................................................. 2 1.1.4 Herencia................................................................................................................................................. 3 1.1.5 Polimorfismo.......................................................................................................................................... 3 1.2 LENGUAJ ES ORIENTADOS A OBJETOS .............................................................................................................4 1.3 EJ EMPLO: VEHCULOS HERENCIA Y POLIMORFISMO....................................................................................5
Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Programacin Orientada a Objetos Un enfoque ms reciente (aos 90) para la resolucin de problemas, se basa en la utilizacin de Objetos, estableciendo un esquema en que cada elemento del mundo real se representa con mayor precisin y fidelidad, logrando as soluciones modulares (compuestas por partes, hasta cierto punto, independientes, que potencialmente pueden reutilizarse en otros modelos) y con encapsulacin (que logra ocultar la complejidad de soluciones en ciertos mdulos, evitando que los participantes de la solucin tengan que dominar cada parte de sta). La interaccin entre los objetos se conceptualiza como el paso de mensajes (llamados a los mtodos), que hacen que estos objetos reaccionen, cambiando su estado y condiciones. Una de las principales razones que avalan la programacin OO, es la mantenibilidad del software desarrollado bajo este esquema. Su necesidad se fue viendo cada vez ms evidente a medida que programas de cientos de lneas de cdigo se ponan en produccin y cualquier modificacin mayor significaba un proceso traumtico de revisin, entendimiento, modificaciones y pruebas. El enfoque OO naci en parte de la idea de resolver esta problemtica, aislando la complejidad en mdulos hasta cierto punto independientes, que son individualmente ms fciles de mantener. 1.1 Conceptos en Orientacin a Objetos En este contexto se definen los objetos como estructuras de software para representar elementos del mundo real, relacionndolos a travs de una descripcin del estado del objeto mediante variables o propiedades, y su comportamiento mediante mtodos o funciones. 1.1.1 Clase Una clase es un Tipo de Objeto, definiendo todas aquellas caractersticas: campos o atributos y mtodos o acciones, comunes a todos los objetos de este tipo. Cada clase, por ende, se define en base a elementos que la componen, que en definitiva establecern la diferencia entre un objeto y otro. Los atributos o campos, son elementos que pueden ir tomando diferentes valores a lo largo de la vida del objeto, an cuando algunos de stos puedan ser definidos como constantes. Los mtodos hacen uso de los atributos de la clase, as como de otros elementos propios, para determinar una secuencia de instrucciones descrita en forma de algoritmo. Adicionalmente, es factible definir la accesibilidad que se tendr desde otros objetos a los elementos de dicha clase. Para ello se establece que stos pueden ser pblicos (visibles) o privados (slo visibles desde los mtodos componentes de la clase). 1.1.2 Objeto En una implementacin OOP (Object Oriented Programming), se llaman Instancias a todas aquellos objetos distintos, de una misma clase, que se usen en un momento determinado. Cada objeto se identifica individualmente por su nombre (nombre de la instancia) y se define un estado representado por los valores de sus atributos en un momento particular del tiempo. Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 2
Diagrama que ilustra un programa compuesto de 4 objetos diferentes, los cuales interactan entre ellos, como lo indican las flechas. 1.1.3 Relaciones La relacin entre los objetos puede ir ms all que un simple esquema de mensajes entre ellos. Existen relaciones ms poderosas, que se define como Tipo de, Es un, Parte de, Tiene un. Por ejemplo, hablando de figuras geomtricas, se puede definir la clase Punto, con coordenadas x,y. Esto, en un pseudo-lenguaje OO se ve de la siguiente manera: Clase Punto { atributos: int x, y
Evolucionando la idea un poco ms all, se pueden definir figuras geomtricas en base a la definicin de punto, como sera el caso de un crculo, que tiene un centro (un punto) y un radio. Clase Circulo { atributos: int x, y, radio
Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 3 En este caso, ambas clases tienen dos atributos comunes: x, y. Ambas ofrecen prcticamente los mismos mtodos, y es la clase Circulo la que define un nuevo elemento y mtodos asociados. Por ello, se puede definir que Circulo es un Tipo de Punto, aun cuando es ms especializado que el Punto en si. Si declaramos una instancia de tipo Circulo, nos encontraremos con que esta instancia tiene los mismos elementos que un Punto, por lo que se asume que Circulo Es un Punto tambin. Declarando una tercera clase: Clase Figura { atributos: Circulo circulo1 Triangulo triangulo1
metodos: set(Punto donde) } Nos encontramos con que en el caso de Circulo y Triangulo (una clase definida equivalentemente a Circulo), ambas son Parte de Figura, y que a su vez, Figura Tiene un Circulo y un Triangulo. 1.1.4 Herencia La herencia nos permite establecer relaciones Es un Tipo de y Es un entre clases. En el ejemplo del punto, la declaracin del Circulo en base a la declaracin previa de Punto se vera:
Clase Circulo heredando de Punto { atributos: int radio
metodos: setRadio(nuevoRadio) getRadio() }
De esta manera, esta relacin de herencia asume que todo lo que sea vlido en Punto, lo ser tambin en Crculo. Por ello, un Circulo tendra como atributos el radio, y tambin, x e y, al igual que los mtodos respectivos. De esa manera, la herencia se define como el mecanismo que permite que una clase A herede propiedades de una clase B. Los objetos de la clase A (llamada Clase Derivada o Subclase) tienen acceso a atributos y mtodos de la clase B (llamada Super Clase), sin necesidad de volver a definirlos. 1.1.5 Polimorfismo La definicin de polimorfismo en este contexto se basa en la posibilidad de utilizaar un mismo nombre para diferentes propsitos, que aunque relacionados, son ligeramente distintos. La idea del polimorfismo es permitir el uso de un nombre en una clase especfica de accin. Dependiendo de qu tipo de datos se est utilizando para trabajar, una instancia especfica del caso general se ejecuta. Hay diversas formas de establecer polimorfismo con los lenguajes orientados a objeto: Reutilizacin de nombres de atributos y mtodos, y la sobrecarga de mtodos. Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 4 1.1.5.1 Reutilizacin de Nombres En el ejemplo anterior del Punto, se podra definir el mtodo Mover(x,y), que mueve el punto a una nueva direccin x,y. Esta misma funcin podra ser implementada en un objeto Triangulo, donde la funcin sera exactamente la misma desplazar la figura a una nueva posicin pero actuara de una manera distinta, ya que el objeto en s es distinto, an cuando el mismo nombre de mtodo (Mover) sea utilizado. De esa manera, si el nombre del mtodo resulta ser lo suficientemente explcito para representar la operacin lgica que ejecuta, este nombre se puede reutilizar en la definicin de otras clases, incluso en casos en que una clase que implementa el mtodo, herede de otra clase que tambin lo implementa, de esa manera aprovechando el nombre, pero estableciendo una nueva versin de su funcionamiento. 1.1.5.2 Sobrecarga de Mtodos Cuando el mismo nombre de un mtodo se utiliza ms de una vez dentro de una misma clase, usualmente se diferencia por los parmetros que recibe. Tal es el caso de la declaracin de constructores de las clases, donde pueden existir diversas versiones de stos, cada uno diferencindose del otro por los parmetros (el tipo de los parmetros, la cantidad, y el orden en que se entregan).
1.2 Lenguajes Orientados a Objetos Segn varios autores, el inters por la OO surgi en el contexto de la crisis del software de los aos 70 (la falta de reusabilidad de software). Al hablar de la OO, se suelen identificar las siguientes ventajas: Desarrollo rpido de sistemas. Mejora en la calidad y legibilidad del cdigo. Facilidad de mantenimiento. Aprovechamiento del poder de los LOOP. Reusabilidad de software y diseos. Produccin de sistemas ms resistentes al cambio. La OOP y los LOOP juegan un papel importante dentro de las tecnologas OO. Segn la literatura, el trmino objeto emergi paralelamente en varios campos de la Informtica a principios de los aos 70, para hacer referencia a nociones superficialmente distintas aunque relacionadas. La identificacin de la importancia de la composicin de sistemas en niveles de abstraccin, la ocultacin de informacin y el desarrollo de mecanismos de tipos de datos abstractos en los aos 70 tuvieron una gran influencia en el desarrollo de la OOP, aunque existe cierta polmica sobre como exactamente estos avances dieron lugar a lo que hoy en da se considera como OOP. El LOOP Simula apareci en 1962 (y ms tarde Simula67 en 1967) y, aunque no fue muy utilizado, ha sido reconocido como el primer LOOP, incorporando los conceptos de clase y objeto. El concepto de OOP propiamente dicho fue presentado por Alan Kay, uno de los inventores de Smalltalk (el primer LOOP popular), algunos aos ms tarde: Todo es un objeto que almacena datos y al que se le puede hacer peticiones. Un programa es un conjunto de objetos que intercambian mensajes. Cada objeto tiene su propia memoria que est compuesta por otros objetos. Cada objeto tiene un tipo de mensajes que puede recibir y procesar. Todos los objetos de un cierto tipo pueden procesar los mismos mensajes. Se trata de una caracterizacin muy general que no se puede aplicar a muchos de los LOOP ms utilizados hoy en da. Smalltalk tena estas caractersticas y fue concebido con el objetivo de ser un LOOP dinmico, que permitiera la adicin de nuevas clases, objetos y comportamiento sobre la marcha. Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 5 En las actas del congreso HOPL II editadas en 1993 por la ACM (Association of Computing Machinery), Kay defini la OOP en trminos de una clula que permite el flujo de informacin en las dos direcciones, pero en la cual lo que est dentro est oculto desde fuera. En 1985 apareci el LOOP Eiffel, diseado para mejorar la productividad y calidad de programas OO, pero no fue muy utilizado. Para que la OOP se estableciera como un paradigma era necesario que los programadores lo adoptaran. Por eso fue muy efectiva la modificacin de un LP ya existente para incorporar los conceptos (y beneficios) de la OOP, sin perder la posibilidad de reutilizar cdigo fuente, como ocurri con C++(que es una extensin de C que incluye los conceptos OO). Otros LP han sido expandidos tambin para incorporar estos conceptos: Modula2 se convirti en Modula3, Ada en Ada95, Lisp en CLOS (Common Lisp Object System) va Flavors, COBOL en Object COBOL, etc. Como ejemplos de LOOP de nueva creacin se pueden destacar Python, J ava y C#. Actualmente se pueden identificar unos 140 LOOP que se usan de alguna forma u otra. Otra manera de ver la OOP es como la evolucin natural de la programacin imperativa, desde la programacin sin estructura, pasando por la programacin procedural y modular. En primer lugar, la programacin sin estructura es la ms sencilla y cada programa consiste en una secuencia de instrucciones que operan sobre datos globales o comunes a todas las partes del programa. Lo que ocurre es que, segn va creciendo el programa, van surgiendo problemas. Por ejemplo, si se necesita la misma secuencia de instrucciones en varias partes del programa, hay que copiarla. Para evitar este problema, se empezaron a extraer estas secuencias, a darles un nombre, y a ofrecer una tcnica para llamarlas y devolver el flujo de control desde ellas al programa principal junto con los resultados. As aparecieron los procedimientos y funciones y la programacin procedural. Con la incorporacin del paso de parmetros y procedimientos dentro de otros, se podan escribir programas con ms estructura y menos probabilidades de errores. As, en vez de ver un programa como una secuencia de instrucciones, se poda contemplar como una secuencia de llamadas a procedimientos. La extensin natural de este tipo de programacin consisti en agrupar en mdulos procedimientos comunes a varios programas, y as surgi la programacin modular. En ella cada mdulo tiene sus propios datos y estado, que se modifican con las llamadas al mdulo. Por ltimo, como se ver a continuacin, la OOP soluciona algunos de los problemas de la programacin modular: puede haber simultneamente mltiples versiones de un mismo objeto y cada una es responsable de su propia creacin y destruccin.
1.3 Ejemplo: Vehculos Herencia y Polimorfismo Se da mucho en casos en que se requiere representar modelos jerrquicos derivados del mundo real, en que los objetos involucrados tienen una relacin de origen entre ellos. Tal es el caso en este ejemplo, donde se definen tres clases, dos de las cuales se podran definir como casos particulares de la clase principal, o ms bien clases derivadas de la superclase. public class Vehiculo { public int ruedas; // Cantidad de ruedas public int puertas; // Cantidad de puertas // Mtodos .... public void Avanzar() { ... } }
Introduccin a la Programacin Orientada a Objetos Rodrigo Sandoval U. IIC 1102 Pgina: 6 public class Camion : Vehiculo { // Herencia explcitamente declarada public int tara; public int carga; // Mtodos .... public void Avanzar() { ... } } public class Moto : Vehiculo { // Herencia explcitamente declarada public int cilindraje; // Mtodos .... public void Avanzar() { ... } }
En el ejemplo anterior se puede ver que se implementa: - Herencia de clases. Al declarar la clase Camion, y tambin la clase Moto, como derivaciones de una misma clase base: Vehiculo. Es importante recordar que esta herencia impone que tanto el Camion como la Moto son Vehiculo. - Polimorfismo. Tanto la clase base, como sus derivadas implementan un mtodo de nombre Avanzar(). Este mtodo en forma lgica tiene posiblemente el mismo significado en los tres casos, sin embargo, al estar definido en tres clases distintas, cada una de ellas puede definir su propia implementacin, haciendo que su funcionamiento detallado difiera en todos los casos. Llama particularmente la atencin que al re-definir el mtodo Avanzar() de la clase base, en las clases derivadas, se reemplaza el funcionamiento de esta clase original. PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo IV Programacin Orientada a Objetos en C#
1 PROGRAMACIN ORIENTADA A OBJETOS EN C#................................................................................. 1 1.1 NAMESPACES..................................................................................................................................................1 1.1.1 Referencia de Namespaces..................................................................................................................... 1 1.1.2 Creacin de Namespaces ....................................................................................................................... 2 1.2 CONSTRUCTORES............................................................................................................................................2 1.2.1 Sintaxis de Definicin de Constructores ................................................................................................ 2 1.2.2 Llamado entre constructores de clases heredadas................................................................................. 3 1.3 ELEMENTOS ESTTICOS..................................................................................................................................4 1.4 PROPIEDADES..................................................................................................................................................5 1.5 CLASES ABSTRACTAS......................................................................................................................................6 1.6 SOBRECARGA DE MTODOS HEREDADOS.........................................................................................................7 1.7 SOBRECARGA DE OPERADORES (+, -, ...)..........................................................................................................8 2 SOLUCIONES ORIENTADAS A OBJETO..................................................................................................... 9 2.1 EJ EMPLO: NMEROS RACIONALES CLASES ABSTRACTAS, HERENCIA, OPERADORES, PROPIEDADES. .........9 2.2 EJ EMPLO: EJ ECUCIN DE UN PENAL HERENCIA, PROPIEDADES, SOBRECARGA MTODOS HEREDADOS.....12 2.2.1 Ejecucin de un penal Versin Consola............................................................................................ 14 2.2.2 Ejecucin de un penal Versin Windows .......................................................................................... 15
Material preparado por Rodrigo Sandoval U en Agosto 2004
Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 1 Programacin Orientada a Objetos en C# Siguiendo la idea de la programacin orientada a objetos, y tomando como base la plataforma .NET y el lenguaje C#, a continuacin se muestran algunas potencias de este lenguaje en implementar objetos con ciertas particularidades adicionales a lo que otros lenguajes ofrecen. 1.1 Namespaces En los programas en diversos lenguajes, particularmente en los que se basan en un esquema orientado a objetos, se preferencia fuertemente la referencia a libreras externas, compuestas de elementos (en este caso de clases), que pueden resolver algunos elementos de tipo general en el programa en desarrollo. 1.1.1 Referencia de Namespaces En C# particularmente, se hace referencia a una serie de colecciones de clases que resuelven funcionalidades requeridas por casi todos los programas. Estas colecciones de clases externas, que pueden haber sido programadas y compiladas en forma individual y ajena al programa que las referencia, se conocen en ingls como Namespaces. Un ejemplo extremadamente omnipresente de namespace es la referencia System, el cual es una coleccin de clases relacionadas con el sistema (computador) de uso bastante frecuente. Entre sus clases ms recurridas en los ejemplos de este curso, se encuentra la clase Console, que hace referencia a los mtodos de escritura y lectura hacia la pantalla y desde el teclado (que componen la console). Para hacer referencia a un namespace, se hace uso de la directiva using (que es un equivalente al #include del lenguaje C). Es decir, un programa que hace acceso a la consola, y que referencia al namespace System, se ve as: using System;
cl ass Mai nPr ogr am{
/ / El mt odo Mai n( ) es el al gor i t mo pr i nci pal . publ i c st at i c voi d Mai n( ) {
/ / Escr i be t ext o en l a consol a. Consol e. Wr i t eLi ne( " Hol a Mundo! " ) ; Consol e. ReadLi ne( ) ; / / Esper a Ent er par a t er mi nar } } Muchos de los namespaces incluidos en el framework de .NET, se referencian con nombres fuertes, es decir, que son nombrados de una forma que indirectamente estructuran una organizacin. Es as, como aparte del recurrido namespace System, existen otros que semnticamente se derivan de l, como es el que provee las clases para el acceso a archivos (con mtodos similares a la clase Console), que se conoce como System.IO. Si bien es un namespace totalmente distinto, su nombre completo, compuesto de dos partes separadas por un punto, da una referencia semntica de su relacin con el namespace System. IIC 1102 Pgina: 1 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 1.1.2 Creacin de Namespaces Por otro lado, cada programador puede crear sus propios namespaces, donde en forma lgica se agrupan clases que se complementan en su funcionalidad. Para ello, la declaracin es de la siguiente forma. namespace MiLibreria { cl ass Cl ase1 { . . . } cl ass Cl ase2 { . . . } } El uso de este namespace en un programa compuesto por otros archivos requiere la compilacin conjunto, o bien la creacin de una librera dinmica (DLL), que se referencia en el segundo archivo, que contiene el programa principal.
1.2 Constructores Los constructores son un tipo particular de mtodos pertenecientes a una clase. El constructor es siempre y nicamente invocado al instanciar una clase y proporcionan la capacidad de especificar las acciones a tomar para inicializar la instancia en particular. El constructor es un concepto establecido en prcticamente todos los lenguajes de programacin OO, incluyendo C#. En pocas palabras, el propsito del constructor es concentrar la lgica de inicializacin de una instancia cuando sta es creada. En muchos casos se define que el constructor recibe ciertos parmetros que condicionan esta inicializacin, y que muchas veces se traducen en valores iniciales para los atributos de la instancia. 1.2.1 Sintaxis de Definicin de Constructores La declaracin de los constructores es la siguiente: public <Nombr eCl ase> (<Li st aPar met r os>) { <i nst r ucci ones> } Por definicin, los constructores son pblicos, ya que son ejecutados al instanciar la clase, sin importar si sus otros elementos son pblicos o privados. Por ello, siempre se indica public. Valor de retorno no se declara. No son void, ni ningn otro tipo de dato, ya que por definicin conceptual del constructor, slo devuelve una instancia creada del objeto o clase que representa. El nombre del constructor es siempre el nombre de la clase respectiva. Puede recibir los parmetros que se estimen convenientes en cada caso. Es incluso factible definir ms de un constructor para una misma clase, cambiando slo los parmetros recibidos. Esto cae en la categora de sobrecarga de mtodos, en este caso sobrecarga de constructores. Como cuerpo del constructor, se puede incluir cualquier tipo de instruccin vlida en cualquier mtodo miembro de la clase. Slo es importante recordar que estas instrucciones, por definicin conceptual, estn destinadas a la inicializacin de los elementos de la clase.
Ejemplo: IIC 1102 Pgina: 2 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. cl ass Per sona { st r i ng nombr e; i nt edad;
publ i c Per sona( st r i ng n, i nt e) { nombr e = n; i f ( e >= 0) edad = e; el se edad = 0; } }
Al instanciar un objeto de esta clase, dado que el nico constructor declarado es el que recibe dos parmetros, obligatoriamente se deben pasar los dos parmetros requeridos. Esto se vera as: cl ass Mai nApp { st at i c voi d Mai n( ) { Per sona p1 = new Persona(Juan, 30); . . . } }
1.2.2 Llamado entre constructores de clases heredadas En el caso de haberse implementado herencia entre clases, el llamado entre constructores an puede ser invocado y controlado. Para efectos prcticos, el uso de la palabra clave base() es sinnimo de llamar la ejecucin del constructor de la clase base. Esto se ve en el siguiente ejemplo, cuyo cdigo completo se encuentra en los ejemplos de este captulo, unas pginas ms adelante. cl ass Raci onal : Numer oCompuest o {
publ i c Raci onal ( i nt n, i nt d) / / Const r uct or de l a cl ase der i vada. : base(n,d) // Se llama al constructor de la clase base. { . . . / / I ni ci al i zaci n par t i cul ar de l a cl ase der i vada } Aqu se ve que la clase Racional hereda de NumeroCompuesto, que a su vez cuenta con su propio constructor. Al declarar el constructor de la clase derivada, que en este caso recibe los mismos dos parmetros de la clase base, se pasan directamente estos dos parmetros a la ejecucin del constructor de la clase base, dejando la lgica de ste intacta. El siguiente ejemplo muestra una herencia de tres niveles y el llamado a los constructores respectivos. Al probar este ejemplo se puede ver en pantalla el orden de ejecucin de los tres constructores respectivos. usi ng Syst em;
cl ass Base { publ i c Base( i nt n) { / / Const r uct or Consol e. Wr i t eLi ne( " Const r uct or Base: {0}" , n) ; } }
IIC 1102 Pgina: 3 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. cl ass Her edada1 : Base { publ i c Her edada1( i nt n) : base( n) { / / Const r uct or Consol e. Wr i t eLi ne( " Const r uct or Her edada1: {0}" , n) ; } }
cl ass Her edada2 : Her edada1 { publ i c Her edada2( ) : base( 1) { / / Const r uct or Consol e. Wr i t eLi ne( " Const r uct or Her edada2" ) ; } }
cl ass Mai nApp { st at i c voi d Mai n( ) { Her edada2 h2 = new Her edada2( ) ; Consol e. ReadLi ne( ) ; } }
1.3 Elementos estticos Una instancia (de objeto) se diferencia de otra por los valores de sus respectivos atributos que puedan tener en un cierto momento. Es decir, cada instancia mantiene una copia de cada uno de los atributos definidos para su clase. Sin embargo, es factible declarar tanto atributos como mtodos que no son instanciados por cada objetivo individualmente, sino que son compartidos por todas las instancias de la clase correspondiente. Para declarar cules de los elementos de una clase (atributos, mtodos), son compartidos conjuntamente por todas las instancias de la clase, se le antepone la palabra clave static en su declaracin. Para ilustrar el concepto, el siguiente ejemplo declara una clase Producto, todas cuyas instancias tendrn diferentes valores para los atributo codigo y precio, sin embargo, el mtodo CalcularValor() se basa en un porcentaje de margen, que es comn para todas las instancias. De esa manera, modificar el valor de este atributo es factible de hacerse en cualquiera de las instancias de la clase, y ese cambio se refleja para todas las instancias. usi ng Syst em;
cl ass Pr oduct o { st r i ng codi go; i nt pr eci o; static float margen;
publ i c Pr oduct o( st r i ng c, i nt p) { codi go = c; pr eci o = p; }
publ i c voi d Cambi ar Mar gen( f l oat m) { mar gen = m; }
publ i c f l oat Cal cul ar Val or ( ) { r et ur n( ( f l oat ) pr eci o*( 1+mar gen) ) ; } }
cl ass Mai nApp { st at i c voi d Mai n( ) { Pr oduct o p1 = new Pr oduct o( " P001" , 30) ; IIC 1102 Pgina: 4 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. Pr oduct o p2 = new Pr oduct o( " P002" , 10) ; Pr oduct o p3 = new Pr oduct o( " P003" , 20) ;
p1. Cambi ar Mar gen( 0. 15F) ; / / Se apl i ca a p1, p2, p3
Consol e. Wr i t eLi ne( " Val or es: {0}; {1}; {2}" , p1. Cal cul ar Val or ( ) , p2. Cal cul ar Val or ( ) , p3. Cal cul ar Val or ( ) ) ;
p1. Cambi ar Mar gen( 0. 10F) ; / / Se apl i ca a p1, p2, p3
Consol e. Wr i t eLi ne( " Val or es: {0}; {1}; {2}" , p1. Cal cul ar Val or ( ) , p2. Cal cul ar Val or ( ) , p3. Cal cul ar Val or ( ) ) ;
Consol e. ReadLi ne( ) ; } }
Como resultado en pantalla se vera: Valores: 34,5; 11,5; 23 Valores: 33; 11; 22
El mismo concepto static es aplicable a los mtodos de las clases, estableciendo aquellos mtodos que seran independientes de la instancia particular. Esto es comnmente usado en la sobrecarga de operadores, por ejemplo, lo cual se ve ms adelante en este captulo. Aqu cabe sealar con claridad que es sta precisamente la razn por la cual el mtodo Main() siempre se declara static.
1.4 Propiedades Tomando en cuenta la caracterstica privada de casi todos los atributos que se definen para una clase las buenas prcticas de programacin fomentan declarar como private todos los atributos de las clases se hace necesario ofrecer cierta visibilidad controlada sobre los valores de estos atributos. Esta visibilidad se describe como la obtencin del valor de cada uno de los atributos, como la eventual facultad de modificar dicho valor. Reiterando, si los atributos son privados, ninguna de stas dos funcionalidades est disponible desde otras clases. Una manera clsica en la programacin orientada a objeto de resolver esta visibilidad, an manteniendo el control sobre lo que se puede ver o modificar de un atributo, se utilizan mtodos que definen una u otra de estas funcionalidades. Tal sera el caso en el siguiente ejemplo. cl ass Per sona { pr i vat e i nt edad; publ i c i nt get Edad( ) { r et ur n( edad) ; } publ i c voi d set Edad( i nt e) { i f ( e>0) edad = e; } } IIC 1102 Pgina: 5 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. En esta clase Persona se distingue el nico atributo privado edad, que evidentemente no es visible fuera de la clase. Por otro lado, dos mtodos ofrecen la visibilidad sobre dicho atributo, denominados getEdad() y setEdad(). El primero de ellos es un ejemplo muy simple de un mtodo que al ser declarado pblico es visible fuera de la clase, y como esencial funcionamiento, retorna el valor del atributo cuando es invocado. A su vez, el segundo de ellos modifica el valor del atributo privado, siempre y cuando el nuevo valor cumpla cierta condicin (en este caso sea nmero mayor que cero). La combinacin de las tres declaraciones permite establecer un atributo privado, pero accesible bajo control por medio de sus mtodos. Esta problemtica fue enfrentada por los diseadores del lenguaje C#, lo que ofrecieron una solucin ms eficiente, siempre manteniendo el objetivo presente: dar visibilidad controlada sobre atributos privados. Esta solucin se basa en la denominadas Propiedades, que si bien no tienen la misma declaracin de un mtodo, semnticamente ofrecen lo mismo que los mtodos: ejecucin de instrucciones relacionadas con los atributos. Su declaracin se basa en tres aspectos: su declaracin (identificador), que no lleva parntesis, su declaracin de funcionalidad de visibilidad (get) y la de modificacin (set). En este caso, el mismo ejemplo anterior quedara. cl ass Per sona { pr i vat e i nt edad; public int Edad { get { return(edad); } set { if(value>0) edad = value; } } } En esta segunda versin del mismo ejemplo, utilizando la sintaxis de propiedades de C#, se identifica la declaracin de dos elementos solamente: el atributo privado, y la propiedad pblica. Esta declaracin tiene las siguientes caractersticas: - El identificador para la propiedad es distinto al del atributo, pero por convencin se utiliza uno muy similar (por ejemplo diferenciando slo por la primera letra mayscula) y no lleva parntesis como los mtodos. - Se puede declarar el bloque get o el set, slo uno de ellos o ambos. Es decir, al declarar una propiedad slo con bloque get, implcitamente se est indicando que la propiedad no acepta modificacin de valor por asignacin. - En el bloque set, la manera de identificar el valor que se quiere asignar al respectivo atributo es por el uso de la palabra clave value, que en este contexto se toma como el valor (sea cual sea su tipo de dato correspondiente) que se asigna a la propiedad y por ende, al atributo.
1.5 Clases abstractas Al usar el modificador abstract al declarar una clase, se indica que sta est pensada exclusivamente para servir como clase base de otras que heredarn su definicin bsica. Por definicin, estas clases abstractas no pueden ser instanciadas (no se pueden declarar instancias de dichas clases, slo heredarlas). An as, una clase abstracta puede contener mtodos abstractos (pensados en ser implementados en versiones definitivas en las clases derivadas), o bien mtodos formalmente implementados, pensados en ser utilizados como tales en las clase derivadas (tpicamente el caso de las propiedades centrales de esta clase base). IIC 1102 Pgina: 6 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. abst r act cl ass Per sona { pr ot ect ed st r i ng nombr e; pr ot ect ed i nt edad;
. . .
public void MostrarDatos() { } }
cl ass Al umno : Per sona { i nt numer o;
public void MostrarDatos() { Consol e. Wr i t eLi ne( {0}, {1}, {2}, nombr e, edad, numer o) ; } }
1.6 Sobrecarga de mtodos heredados Aprovechando uno de los principales conceptos de la programacin orientada a objeto, llamado Polimorfismo, en este caso representado por la sobrecarga de mtodos, mediante la redeclaracin de un mtodo en una clase heredada, se deben considerar ciertos aspectos de diseo, que expliciten esta situacin. Por ejemplo, si se da un ejemplo de herencia como el siguiente, donde una clase base representa a una persona en particular, mientras que la heredada representa un alumno de una universidad, se puede hacer la siguiente definicin del mtodo MostrarDatos(). cl ass Per sona { pr ot ect ed st r i ng nombr e; pr ot ect ed i nt edad;
. . .
/ / En l a cl ase base, el mt odo Most r ar Dat os( ) no t i ene / / cdi go, ya que no i nt er esa i mpl ement ar su l gi ca. / / Si n embar go, se decl ar a vi r t ual , expl i ci t ando que / / l a l gi ca de est e mt odo deber ser i mpl ement ada / / por l as cl ases der i vadas. publ i c vi r t ual voi d Most r ar Dat os( ) { } }
cl ass Al umno : Per sona { . . .
/ / En l a cl ase der i vada, el mt odo Most r ar Dat os( ) debe / / ser expl ci t ament e una sobr ecar ga del mi smo de l a / / cl ase base. Par a el l o, se decl ar a over r i de. publ i c over r i de voi d Most r ar Dat os( ) { Consol e. Wr i t eLi ne( Nombr e: , t hi s. nombr e) ; Consol e. Wr i t eLi ne( Edad: , t hi s. edad) ; } }
IIC 1102 Pgina: 7 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 1.7 Sobrecarga de operadores (+, -, ...) Conociendo la posibilidad de definir mtodos con sobrecarga, existe en C#la particularidad de poder re- definir el funcionamiento de algunos operadores estndar, como son los operadores matemticos (+, -, * , /), sobre objetos de tipo ms complejo que los numricos bsicos. En el siguiente ejemplo se define un nuevo tipo de dato, en la forma de una clase, que representa los nmeros complejos, compuestos por una parte real y otra imaginaria. En este caso se re-define la operacin suma, identificada por el smbolo +. cl ass Compl ej o { pr i vat e i nt r eal , i mag; publ i c Compl ej o( i nt r , i nt i ) { r eal = r ; i mag = i ; }
public static Complejo operator+(Complejo c1, Complejo c2) { Complejo c = new Complejo(c1.real+c2.real, c1.imag+c2.imag); return c; } } Con esta declaracin ya es factible armar una expresin con el operador de suma (+) entre dos instancias de la clase Complejo. Un ejemplo ms completo de este concepto se ve ms adelante, en la implantacin de la clase Racional, como representante de los nmeros racionales. IIC 1102 Pgina: 8 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 2 Soluciones Orientadas a Objeto 2.1 Ejemplo: Nmeros Racionales Clases Abstractas, Herencia, Operadores, Propiedades. Para este ejemplo, se toma como referencia todos aquellos tipos de nmeros que estn compuestos por diferentes partes. Tal es el caso de los nmeros complejos, compuestos de una parte real y otra imaginaria, o de los puntos en el espacio bidimensional, compuestos de dos coordenadas en la forma (x,y), y tambin los nmeros racionales, compuestos por un numerador y un denominador. En este caso, es precisamente el caso de los nmeros racionales el que se quiere revisar. Como propsito final se pretende contar con una implementacin del nmero racional lo suficientemente completa como para trabajar en forma transparente con ellos en un programa principal. Como ejemplo se muestra a continuacin un ejemplo de cmo podra utilizarse esta definicin de Racional, conociendo slo los mtodos y caractersticas pblicas. Conociendo esta interfaz es posible emplear este tipo de objetos para resolver problemas en los que es necesario manipular nmeros racionales. Como puede verse, no es necesario conocer la implementacin, de hecho, hasta el momento no sabemos cmo se representan los datos ni cmo estn escritas las funciones que componen la interfaz. Tipo de Dato (clase) Racional. Cada Racional est compuesto por un numerador y un denominador Declaracin Racional r =new Racional(n1, n2); Mtodos Bsicos Numerador(): entrega el valor entero del numerador del racional Denominador(): entrega el valor entero del denominador del racional Imprimir(): muestra en pantalla el racional en la forma (n/d) Operadores Suma (+), resta (-), multiplicacin (*), divisin (/) Teniendo clara esta informacin, se puede proceder a declarar un algoritmo principal en un programa, utilizando extensivamente los Racionales, sin necesariamente conocer su definicin real ni su composicin. usi ng Syst em;
cl ass Raci onal { . . . . }
cl ass Mai nApp {
st at i c voi d Mai n( ) { Raci onal r 1 = new Raci onal ( 2, 3) ; Raci onal r 2 = new Raci onal ( 4, 5) ;
Consol e. Wr i t e( " r 1 es " ) ; r 1. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ; Consol e. Wr i t e( " r 2 es " ) ; r 2. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ;
Raci onal r 3 = r 1 + r 2; Consol e. Wr i t e( " r 1 + r 2 es " ) ; r 3. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ; r 3 = r 2 - r 1; Consol e. Wr i t e( " r 1 - r 2 es " ) ; r 3. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ; r 3 = r 2 * r 1; Consol e. Wr i t e( " r 1 * r 2 es " ) ; r 3. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ; r 3 = r 2 / r 1; Consol e. Wr i t e( " r 1 / r 2 es " ) ; r 3. I mpr i mi r ( ) ; Consol e. Wr i t eLi ne( ) ;
Consol e. Wr i t e( " Pr esi one ENTER. " ) ; Consol e. ReadLi ne( ) ; } } IIC 1102 Pgina: 9 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. La verdadera implementacin de la clase Racional, evidentemente define una serie de elementos internos, que resuelven la problemtica, pero la idea siempre es no requerir conocerla con detalle, sino que slo saber usarla en un programa como el anterior. Para este ejemplo, la implementacin pasa por la definicin de una clase abstracta base, que precisamente representa todos aquellos tipos de nmeros compuestos de dos partes. La clase NumeroCompuesto define dos partes que lo componen. J unto con ello, se definen propiedades de acceso controlado a estas dos partes y el correspondiente constructor, que las inicializa con dos valores pasados como parmetros. Teniendo esa clase base, se define la clase derivada: Racional, que hace la relacin entre las dos partes de NumeroCompuesto, con el numerador y denominador. Es importante destacar en este ejemplo, que los componentes internos de la clase base, NumeroCompuesto, no son visibles en la clase derivada, aunque si lo son las propiedades que controlan el acceso. Haciendo buen uso de stas, se logra definir la lgica de la implementacin de esta clase derivada. Adicionalmente, la clase Racional re-define los operadores bsicos de nmeros: suma, resta, multiplicacin y divisin, de modo que sea an ms natural utilizar en un programa externo este tipo de dato definido. El siguiente Diagrama de Clases en UML refleja esta relacin entre Racional y NumeroCompuesto.
En este diagrama, los elementos que se enumeran con un smbolo -, son privados, los que tienen + son pblicos, y los que anteponen un # son protegidos. El cdigo completo de estas dos clases se encuentra a continuacin, que es totalmente consecuente con el algoritmo principal anteriormente indicado: usi ng Syst em;
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Numer oCompuest o: un t i po de nmer o genr i co compuest o por dos par t es ( en est e cont ext o) / / En est e caso se t r at a de una cl ase abst r act a: def i ni da excl usi vament e par a ser her edada / / y no par a ser i nst anci ada. / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / abst r act cl ass Numer oCompuest o {
pr i vat e i nt par t e1; / / par t e1 y par t e2 son i nvi si bl es al ext er i or de l a cl ase pr i vat e i nt par t e2; / / i ncl uso en l as cl ases der i vadas que l a her edan.
pr ot ect ed Numer oCompuest o( i nt p1, i nt p2) { / / Const r uct or par t e1 = p1; par t e2 = p2; }
// Definicin de las propiedades de la clase NumeroCompuesto pr ot ect ed i nt Par t e1 { get { r et ur n ( par t e1) ; } set { par t e1 = val ue; } } pr ot ect ed i nt Par t e2 { get { r et ur n ( par t e2) ; } set { par t e2 = val ue; } } }
IIC 1102 Pgina: 10 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Raci onal : her edando l as car act er st i cas de Numer oCompuest o ( dos par t es) / / : en est e caso r el aci onando par t e1- >numer ador . . . par t e2- >denomi nador / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
cl ass Raci onal : NumeroCompuesto {
publ i c Raci onal ( i nt n, i nt // Constructor de la clase: inicializacin d) : base( n, d) // se llama al constructor de la clase base. { }
/ / Mt odos bsi cos: acceso a l as par t es del nmer o Raci onal . / / Est o t ambi n se puede hacer con el f or mat o de Pr opi edades publ i c i nt Numer ador ( ) { r et ur n( t hi s. Par t e1) ; } publ i c i nt Denomi nador ( ) { r et ur n( t hi s. Par t e2) ; }
/ / Mt odo si mpl e: i mpr i me en pant al l a el nmer o con sus par t es. publ i c voi d I mpr i mi r ( ) { Consol e. Wr i t e( " {0}/ {1}" , t hi s. Par t e1, t hi s. Par t e2) ; }
// Sobrecarga de operadores: +, -, *, /
/ / Suma de Raci onal es: l a suma de l as mul t i p. cr uzadas / mul t i pl i caci n denom. publ i c st at i c Raci onal oper at or +( Raci onal r 1, Raci onal r 2) { Raci onal r = new Raci onal ( r 1. Numer ador ( ) *r 2. Denomi nador ( ) + r 1. Denomi nador ( ) *r 2. Numer ador ( ) , r 1. Denomi nador ( ) *r 2. Denomi nador ( ) ) ; r et ur n r ; }
/ / Rest a de Raci onal es: l a r est a de l as mul t i p. cr uzadas / mul t i pl i caci n denom. publ i c st at i c Raci onal oper at or - ( Raci onal r 1, Raci onal r 2) { Raci onal r = new Raci onal ( r 1. Numer ador ( ) *r 2. Denomi nador ( ) - r 1. Denomi nador ( ) *r 2. Numer ador ( ) , r 1. Denomi nador ( ) *r 2. Denomi nador ( ) ) ; r et ur n r ; }
/ / Mul t i pl i caci n de Raci onal es: mul t i pl i caci n numer ador es / mul t i pl i caci n denom. publ i c st at i c Raci onal oper at or *( Raci onal r 1, Raci onal r 2) { Raci onal r = new Raci onal ( r 1. Numer ador ( ) *r 2. Numer ador ( ) , r 1. Denomi nador ( ) *r 2. Denomi nador ( ) ) ; r et ur n r ; }
/ / Di vi si n de Raci onal es: mul t i pl i caci ones cr uzadas. publ i c st at i c Raci onal oper at or / ( Raci onal r 1, Raci onal r 2) { Raci onal r = new Raci onal ( r 1. Numer ador ( ) *r 2. Denomi nador ( ) , r 1. Denomi nador ( ) *r 2. Numer ador ( ) ) ; r et ur n r ; } }
IIC 1102 Pgina: 11 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 2.2 Ejemplo: Ejecucin de un Penal Herencia, Propiedades, Sobrecarga Mtodos Heredados. Profundizando un ejemplo del captulo 1, la ejecucin del lanzamiento penal en ftbol se puede modelar desde un enfoque totalmente orientado a objeto, una vez que se han entendido los elementos involucrados. Simplificando en este caso, se requiere de dos jugadores, los cuales si bien comparten parte de los elementos que los definen, tienen ciertos comportamientos y elementos que los diferencian. De tal manera, se hace una definicin de la clase J ugador genrico, que representa lgicamente a cualquier jugador. J unto a esta definicin, se declara el rbitro. Y como derivado del J ugador genrico aparecen el Pateador y el Arquero. Esta estructura de objetos se refleja en el siguiente Diagrama de Clases en UML. Todas estas clases estn contenidas dentro del Namespace Deportes.Futbol.
El cdigo que representa esta definicin, contenido en el namespace Deportes.Futbol, se encuentra a continuacin. Cabe destacar que ninguna de las clases es abstracta, por lo que cualquiera de ellas podra ser instanciada, y por ende, conformar un equipo completo, o dos para un partido oficial. namespace Depor t es. Fut bol {
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / / cl ase Ar bi t r o / / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - publ i c cl ass Ar bi t r o { publ i c st r i ng Pi t ar ( ) { r et ur n ( " PRI I I P! " ) ; } }
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / / cl ase J ugador : r epr esent a a cual qui er j ugador de l a cancha / / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - publ i c cl ass J ugador { pr i vat e i nt di r ecci on; / / 1: i zqui er da; 2: der echa pr i vat e i nt numer o;
publ i c J ugador ( i nt di r ) { i f ( di r <1 | | di r >2 ) di r = 1; di r ecci on = di r ; numer o = 2; } publ i c J ugador ( i nt di r , i nt num) { i f ( di r <1 | | di r >2 ) di r = 1; di r ecci on = di r ; IIC 1102 Pgina: 12 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. numer o = num; }
publ i c i nt Di r { get { r et ur n( di r ecci on) ; } set { i f ( val ue<1 | | val ue>2 ) di r ecci on = 1; el se di r ecci on = val ue; } } publ i c i nt Numer o { get { r et ur n( numer o) ; } }
publ i c st r i ng Di r ecci on { get { i f ( di r ecci on == 1) r et ur n( " i zqui er da" ) ; i f ( di r ecci on == 2) r et ur n( " der echa" ) ; r et ur n( " - " ) ; } }
publ i c vi r t ual st r i ng J ugada( ) { r et ur n( " " ) ; } }
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / / cl ase Pat eador , der i vada de J ugador : / / Repr esent a a un j ugador que pat ear un t i r o l i br e o penal / / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - publ i c cl ass Pat eador : J ugador {
publ i c Pat eador ( i nt di r ) : base( di r , 9) {}
publ i c st r i ng Pat ear ( ) { r et ur n( " J ugador " + Numer o. ToSt r i ng( ) + " pat ea haci a l a " + Di r ecci on) ; } publ i c over r i de st r i ng J ugada( ) { r et ur n( Pat ear ( ) ) ; } }
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / / cl ase Ar quer o, der i vada de J ugador : / / Repr esent a a un ar quer o que se l anzar par a at aj ar un t i r o / / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - publ i c cl ass Ar quer o : J ugador {
publ i c Ar quer o( i nt di r ) : base( di r , 1) {}
publ i c st r i ng Lanzar se( ) { r et ur n( " Ar quer o se l anza haci a l a " + Di r ecci on) ; }
publ i c over r i de st r i ng J ugada( ) { r et ur n( Lanzar se( ) ) ; } } }
IIC 1102 Pgina: 13 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. Teniendo implementada la lgica de los participantes de esta ejecucin de penales, en este namespace Deportes.Futbol, se puede aprovechar e incluir en cualquier programa que implemente un algoritmo principal, que haga referencia y uso de estas clases. De tal manera, a continuacin se entregan dos posibles implementaciones de la ejecucin del penal, una versin simple de Consola, donde se le preguntan las opciones al usuario, y una segunda donde la lgica de operacin es exactamente la misma, pero se interacta con el usuario por medio de una ventana de Windows. 2.2.1 Ejecucin de un penal Versin Consola El siguiente cdigo corresponde a la clase principal del programa, donde se hace referencia al namespace que define los jugadores que participan. Aqu se reconoce un Main() que tiene el algoritmo principal, interactuando con el usuario por medio de la consola.
usi ng Syst em; usi ng Depor t es. Fut bol ;
cl ass CMai n { publ i c st at i c voi d Mai n( ) { i nt di r 1, di r 2; Consol e. Wr i t eLi ne( " LANZAMI ENTO DE UN PENAL" ) ; Consol e. Wr i t e( " I ndi que di r ecci n en que l anza el j ugador ( 1: i zq; 2: der ) : " ) ; di r 1 = i nt . Par se( Consol e. ReadLi ne( ) ) ; Consol e. Wr i t e( " I ndi que di r ecci n a l a que se l anza el ar quer o ( 1: i zq; 2: der ) : " ) ; di r 2 = i nt . Par se( Consol e. ReadLi ne( ) ) ;
Ar bi t r o b = new Ar bi t r o( ) ; Pat eador p = new Pat eador ( di r 1) ; Ar quer o a = new Ar quer o( di r 2) ;
Consol e. Wr i t eLi ne( b. Pi t ar ( ) ) ; Consol e. Wr i t eLi ne( p. J ugada( ) ) ; Consol e. Wr i t eLi ne( a. J ugada( ) ) ;
i f ( p. Di r ecci on == a. Di r ecci on) Consol e. Wr i t eLi ne( " El penal f ue at aj ado! " ) ; el se Consol e. Wr i t eLi ne( " El gol f ue conver t i do! " ) ;
Consol e. ReadLi ne( ) ; } } Para poder generar un archivo penales.exe que contenga la lgica de ambos archivos separados (el namespace Deportes.Futbol en el archivo futbol.cs y el algoritmo principal en penales.cs), se debe ejecutar una compilacin de dos entradas de la siguiente forma (archivo build.bat). Los tres archivos deben estar en el mismo directorio. @%WI NDI R%\ Mi cr osof t . NET\ Fr amewor k\ v1. 1. 4322\ csc. exe / out : . \ penal es. exe f ut bol . cs penal es. cs @pause Compilando, aparece el archivo penales.exe, y al ejecutarlo se ve la siguiente consola:
IIC 1102 Pgina: 14 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. 2.2.2 Ejecucin de un penal Versin Windows Utilizando como base el mismo namespace Deportes.Futbol, sin hacer ni una sola modificacin, se reaprovecha su lgica en la implementacin de una versin equivalente a la de consola, esta vez logrando que la interaccin con el usuario se realice por medio de controles Windows, es decir, elementos grficos con los que el usuario manifiesta sus preferencias. La ventaja de la arquitectura en base a componentes en la Programacin Orientada a Objeto, es precisamente la capacidad de reutilizacin de elementos (lgica de funcionamiento), ya implementada, en otras soluciones. A continuacin se incluye el cdigo fuente de la clase principal de este programa en versin Windows, la cual mantiene la misma lgica operativa de la versin de consola. Este ejemplo en particular, a diferencia del anterior, presenta muchas ms lneas de cdigo y mtodos adicionales, cuyo propsito es especficamente trabajar con los objetos grficos de la ventana de Windows con la que interacta el usuario, dejando la lgica de decisin sobre el problema de ejecucin del penal, en un mtodo final, invocado al activar el botn del usuario.
usi ng Syst em; usi ng Syst em. Dr awi ng; usi ng Syst em. I O; usi ng Syst em. Wi ndows. For ms; usi ng Syst em. Di agnost i cs;
usi ng Depor t es. Fut bol ;
namespace Depor t es. Fut bol . Penal {
/ / / <summar y> / / / Vent ana de si mul aci n de l a ej ecuci n de un penal , / / / donde se el i ge l a di r ecci n en que l anza el pat eador / / / y l a que se l anza el ar quer o. / / / Segn eso, cal cul a si el penal f ue conver t i do o at aj ado. / / / </ summar y> publ i c cl ass Vent anaPenal es : For m{
Pat eador p; Ar quer o a;
pr i vat e Label l bTi t ul o; pr i vat e Label l bPat eador ; pr i vat e Label l bAr quer o; pr i vat e Label l bResul t ado; pr i vat e ComboBox cbPat eador ; pr i vat e ComboBox cbAr quer o; pr i vat e But t on bt Ej ecut ar ;
publ i c Vent anaPenal es( ) { p = new Pat eador ( 1) ; a = new Ar quer o( 1) ;
cbPat eador = new ComboBox( ) ; cbAr quer o = new ComboBox( ) ; bt Ej ecut ar = new But t on( ) ; l bResul t ado = new Label ( ) ; l bPat eador = new Label ( ) ; l bAr quer o = new Label ( ) ; l bTi t ul o = new Label ( ) ; t hi s. SuspendLayout ( ) ;
l bTi t ul o. Fl at St yl e = Syst em. Wi ndows. For ms. Fl at St yl e. Popup; l bTi t ul o. Font = new Syst em. Dr awi ng. Font ( " Mi cr osof t Sans Ser i f " , 12F, Syst em. Dr awi ng. Font St yl e. Bol d, Syst em. Dr awi ng. Gr aphi csUni t . Poi nt , ( ( Syst em. Byt e) ( 0) ) ) ; l bTi t ul o. Locat i on = new Syst em. Dr awi ng. Poi nt ( 16, 16) ; IIC 1102 Pgina: 15 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. l bTi t ul o. Name = " l bTi t ul o" ; l bTi t ul o. Si ze = new Syst em. Dr awi ng. Si ze( 250, 32) ; l bTi t ul o. TabI ndex = 5;
l bPat eador . Fl at St yl e = Syst em. Wi ndows. For ms. Fl at St yl e. Popup; l bPat eador . Font = new Syst em. Dr awi ng. Font ( " Mi cr osof t Sans Ser i f " , 8F, Syst em. Dr awi ng. Font St yl e. Regul ar , Syst em. Dr awi ng. Gr aphi csUni t . Poi nt , ( ( Syst em. Byt e) ( 0) ) ) ; l bPat eador . Locat i on = new Syst em. Dr awi ng. Poi nt ( 16, 55) ; l bPat eador . Name = " l bPat eador " ; l bPat eador . Si ze = new Syst em. Dr awi ng. Si ze( 120, 20) ; l bPat eador . TabI ndex = 6; l bAr quer o. Fl at St yl e = Syst em. Wi ndows. For ms. Fl at St yl e. Popup; l bAr quer o. Font = new Syst em. Dr awi ng. Font ( " Mi cr osof t Sans Ser i f " , 8F, Syst em. Dr awi ng. Font St yl e. Regul ar , Syst em. Dr awi ng. Gr aphi csUni t . Poi nt , ( ( Syst em. Byt e) ( 0) ) ) ; l bAr quer o. Locat i on = new Syst em. Dr awi ng. Poi nt ( 16, 80) ; l bAr quer o. Name = " l bPat eador " ; l bAr quer o. Si ze = new Syst em. Dr awi ng. Si ze( 120, 20) ; l bAr quer o. TabI ndex = 7;
cbPat eador . Dr opDownWi dt h = 112; cbPat eador . Locat i on = new Syst em. Dr awi ng. Poi nt ( 140, 53) ; cbPat eador . Name = " cbPat eador " ; cbPat eador . Si ze = new Syst em. Dr awi ng. Si ze( 112, 21) ; cbPat eador . TabI ndex = 1; cbPat eador . Sel ect edI ndexChanged += new Syst em. Event Handl er ( t hi s. cbPat eador _Sel ect edI ndexChanged) ;
cbAr quer o. Dr opDownWi dt h = 112; cbAr quer o. Locat i on = new Syst em. Dr awi ng. Poi nt ( 140, 78) ; cbAr quer o. Name = " cbAr quer o" ; cbAr quer o. Si ze = new Syst em. Dr awi ng. Si ze( 112, 21) ; cbAr quer o. TabI ndex = 2; cbAr quer o. Sel ect edI ndexChanged += new Syst em. Event Handl er ( t hi s. cbAr quer o_Sel ect edI ndexChanged) ;
bt Ej ecut ar . Locat i on = new Syst em. Dr awi ng. Poi nt ( 160, 110) ; bt Ej ecut ar . Name = " bt Ej ecut ar " ; bt Ej ecut ar . Si ze = new Syst em. Dr awi ng. Si ze( 90, 24) ; bt Ej ecut ar . TabI ndex = 3; bt Ej ecut ar . Text = " Ej ecut ar " ; bt Ej ecut ar . Cl i ck += new Syst em. Event Handl er ( t hi s. bt Ej ecut ar _Cl i ck) ;
l bResul t ado. Fl at St yl e = Syst em. Wi ndows. For ms. Fl at St yl e. Popup; l bResul t ado. Font = new Syst em. Dr awi ng. Font ( " Mi cr osof t Sans Ser i f " , 12F, Syst em. Dr awi ng. Font St yl e. Regul ar , Syst em. Dr awi ng. Gr aphi csUni t . Poi nt , ( ( Syst em. Byt e) ( 0) ) ) ; l bResul t ado. Locat i on = new Syst em. Dr awi ng. Poi nt ( 8, 140) ; l bResul t ado. Name = " l bResul t ado" ; l bResul t ado. Si ze = new Syst em. Dr awi ng. Si ze( 264, 64) ; l bResul t ado. TabI ndex = 4;
/ / Di mensi onami ent o y est i l o de l a vent ana. t hi s. Aut oScal eBaseSi ze = new Syst em. Dr awi ng. Si ze( 5, 13) ; t hi s. Cl i ent Si ze = new Syst em. Dr awi ng. Si ze( 280, 215) ; t hi s. Cont r ol s. AddRange( new Syst em. Wi ndows. For ms. Cont r ol [ ] { l bTi t ul o, l bPat eador , l bAr quer o, bt Ej ecut ar , cbPat eador , cbAr quer o, l bResul t ado }) ; t hi s. Name = " Vent anaPenal es" ; t hi s. Text = " Ej ecuci n de Penal " ; t hi s. ResumeLayout ( f al se) ;
cbPat eador . I t ems. Add ( " I zqui er da" ) ; cbPat eador . I t ems. Add ( " Der echa" ) ; cbPat eador . Sel ect edI ndex = 0; cbAr quer o. I t ems. Add ( " I zqui er da" ) ; cbAr quer o. I t ems. Add ( " Der echa" ) ; cbAr quer o. Sel ect edI ndex = 0; l bTi t ul o. Text =" Ej ecuci n de Penal " ; l bPat eador . Text =" Pat eador pat ea haci a l a" ; l bAr quer o. Text =" Ar quer o se l anza a l a" ; l bResul t ado. Text =" ( Penal an no ej ecut ado) " ; IIC 1102 Pgina: 16 Intro. Prog. Programacin OO en C# Rodrigo Sandoval U. }
/ / / <summar y> / / / Al gor i t mo pr i nci pal de l a apl i caci n. / / / Se abr e una vent ana par a pedi r l os dat os al usuar i o y ej ecut ar . / / / </ summar y> [ STAThr ead] st at i c voi d Mai n( ) { Appl i cat i on. Run( new Vent anaPenal es( ) ) ; }
pr i vat e voi d bt Ej ecut ar _Cl i ck( obj ect sender , Syst em. Event Ar gs e) { lbResultado.Text = p.Patear() + "\n" + a.Lanzarse(); if(p.Direccion == a.Direccion) lbResultado.Text += "\nEl penal fue atajado "; else lbResultado.Text += "\nEl penal fue convertido!"; }
p voi d cbPat eador _Sel ect edI ndexChanged( o r i vat e bj ect sender , Syst em. Event Ar gs e) { p.Dir = cbPateador.SelectedIndex + 1; } pr i vat e voi d cbAr quer o_Sel ect edI ndexChanged( obj ect sender , Syst em. Event Ar gs e) { a.Dir = cbArquero.SelectedIndex + 1; } } } Para poder crear el ejecutable de este programa, es necesario realizar una compilacin que incluya ambos cdigos fuentes: el namespace Deportes.Futbol (futbol.cs), y el Main() para la ventana Windows (penales.cs). En este caso particular se definin una arquitectura de compilacin diferentes: primero se compila futbol.cs, produciendo como resultado un archivo independiente de tipo .NET Module. Luego se compila el archivo principal, tomando en la compilacin el mdulo compilado anterior, produciendo en la suma el ejecutable final. Esta idea se refleja en el siguiente archivo build.bat, en este caso de tres lneas: una para cada compilacin y un pause final. @%WINDIR%\Microsoft.NET\Framework\v1.1.4322\csc.exe /target:module /debug+/d:TRACE futbol.cs @%WINDIR%\Microsoft.NET\Framework\v1.1.4322\csc.exe /target:winexe /debug+ /d:TRACE /addmodule:futbol.netmodule /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.dll penales.cs @pause Finalmente, al producirse el archivo penales.exe como resultado de esta compilacin en etapas, al ejecutarlo aparece la ventana de interaccin con el usuario que finalmente podra usarse para simular la ejecucin del penal segn las opciones seleccionadas por el usuario.
IIC 1102 Pgina: 17 Material preparado por Rodrigo Sandoval U en Marzo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.al
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo V Control de Flujo
1 CONTROL DE FLUJO....................................................................................................................................... 1 2 DECISIN O SELECCIN............................................................................................................................... 2 2.1 INSTRUCCIN IF ..............................................................................................................................................2 2.1.1 Ejemplo: Qu hago el sbado por la noche? (Implementacin) .......................................................... 3 2.2 INSTRUCCIN SWITCH.....................................................................................................................................6 2.2.1 Ejemplo: Conversin a letras de una cantidad de dos dgitos ............................................................... 7 3 ITERACIN......................................................................................................................................................... 9 3.1 INSTRUCCIN WHILE.......................................................................................................................................9 3.1.1 Ejemplo: Tabla de conversin de temperaturas (Fahrenheit-Celsius) .................................................. 9 3.1.2 Ejemplo: Esperando el Ao Nuevo ...................................................................................................... 10 3.2 INSTRUCCIN DO-WHILE...............................................................................................................................12 3.3 INSTRUCCIN FOR.........................................................................................................................................13 3.3.1 Ejemplo: Clculo de x a la n (uso restringido del for)......................................................................... 15 3.3.2 Ejemplo: Conversin a letras de cantidades numricas (uso general del for)..................................... 16 3.4 INSTRUCCIN FOREACH................................................................................................................................19 3.5 EQUIVALENCIA LGICA ENTRE INSTRUCCIONES DE ITERACIN....................................................................19 3.5.1 Ejemplos: Programa con funciones equivalentes y Ciclos anidados ................................................... 21 3.6 ITERACIONES CON ANIDAMIENTO.................................................................................................................24
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Control de Flujo Los algoritmos normalmente requieren modificar el flujo de ejecucin de las instrucciones que lo componen. Esto se lleva a cabo mediante decisin e iteracin. La decisin permite especificar la ejecucin condicional de ciertas instrucciones. La condicin que se considera para tomar la decisin est basada en el estado actual de la ejecucin, es decir, en las entradas del programa, las instrucciones ejecutadas hasta ahora y, en general, en el contenido de las variables. Los lugares dentro del programa en que se toman las decisiones se conocen como puntos de control de flujo, o simplemente, puntos de decisin. Como referencia puede consultarse la seccin que trata los rboles de decisin y, en particular, el ejemplo Qu hago el sbado por la noche?, donde se ilustra una situacin en la que es necesario tomar decisiones durante la ejecucin de un algoritmo. El lenguaje de programacin C#cuenta con dos instrucciones que permiten especificar decisin dentro de un programa: if-else switch Por otra parte, la iteracin permite controlar mediante expresiones lgicas la repeticin de una o varias instrucciones dentro del programa. Los bloques con las instrucciones que se repiten se conocen como ciclos o loops. La expresin que controla la ejecucin del ciclo se conoce como condicin de control. El lenguaje de programacin C#cuenta con cuatro instrucciones para especificar iteraciones, y aunque stas son lgicamente equivalentes (ver ejemplos ms adelante), sus diferencias radican principalmente en la forma en que se controla la continuacin o terminacin del ciclo (especificacin y verificacin). Las instrucciones son: while do-while for foreach
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 2 2 Decisin o Seleccin 2.1 Instruccin if La instruccin if permite decidir si una porcin de cdigo (una o ms instrucciones) se debe ejecutar, tomando como criterio para la decisin el valor de una expresin lgica. Alternativamente, permite elegir entre dos porciones de cdigo, de acuerdo a la evaluacin de la expresin de control. Sintaxis: if ( expresion-evaluacin ) instruccin ;
if ( expresion-evaluacin ) { ... Bloque de instrucciones ... }
if ( expresion-evaluacin ) instruccin1 ; else instruccin2 ;
if ( expresion-evaluacin ) { ... Bloque de instrucciones 1 ... } else { ... Bloque de instrucciones 2 ... } Los bloques de instrucciones consisten en una secuencia de instrucciones terminadas en punto y coma. Al ejecutarse una instruccin if, se evaluar la expresin de evaluacin o expresin booleana (que resulta en Verdadero o Falso) suministrada en los parntesis, y dependiendo de su valor (verdadero o falso, es decir, true o false), se tomar una de las siguientes acciones: Si la expresin es verdadera, se ejecutar la instruccin o bloque de instrucciones que viene despus de la condicin, pero antes de la seccin else (si es que existe). Una vez hecho esto, se continuar la ejecucin en la siguiente instruccin despus del if. Si la expresin es falsa, y no se incluy la partcula else dentro de la instruccin, el if pasar desapercibido, es decir, no se ejecutar las instrucciones contenidas en l, sino que la ejecucin continuar en la siguiente instruccin despus del if. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 3 Si la expresin es falsa, y existe una partcula else dentro del if, se ejecutar la instruccin o bloque de instrucciones que viene despus del else. Una vez hecho esto, se continuar la ejecucin en la siguiente instruccin despus del if. Es posible escribir if anidados, es decir, incluir otras instrucciones if dentro de las instrucciones a ejecutar al evaluar una primera instruccin if.
Ejemplos: 1. int edad; int viejitos = 0;
if (edad > 80) { // Esto se ejecuta si la variable edad tiene un valor mayor a 80 viejitos++; Console.WriteLine("Ud. no califica para descuento de adolescente); } else { // Esto se ejecuta si la variable edad tiene un valor <= 80 Console.WriteLine("Bienvenido, Ud. cuenta con un descuento de $15); }
2. int salario, credito;
if (salario > 1000000) credito = 5000000; else if (salario > 500000) credito = 2000000; else if (salario > 100000) credito = 1000000; else credito = 0;
2.1.1 Ejemplo: Qu hago el sbado por la noche? (Implementacin) Se presenta una implementacin (empleando la instruccin if) del rbol de decisin para saber qu hacer el sbado por la noche. Para ilustrar el uso de los rboles de decisin, se presenta un rbol que gua a un usuario a tomar una decisin sobre qu hacer el sbado por la noche. La profundizacin en el rbol se lleva a cabo de acuerdo a las respuestas que va dando el usuario a las interrogantes que se le plantean. Cuando se llega a un nodo terminal en el rbol (hoja), el usuario recibe una recomendacin sustentada en el desarrollo de la interaccin. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 4
using System;
class MainApp {
public static void Main() { string respuesta;
Console.WriteLine("Veamos qu hacer el sbado por la noche... ");
Console.Write("Desea quedarse en casa? (s/n): "); respuesta = Console.ReadLine();
if (respuesta=="s") { Console.Write ("Le gusta ver TV? (s/n): "); respuesta = Console.ReadLine();
if (respuesta=="s") { Console.Write("Hay algn programa bueno esta noche? (s/n): "); respuesta = Console.ReadLine(); if (respuesta=="s") Console.WriteLine("Sugerencia: Coma cabritas y vea el programa de hoy"); else Console.WriteLine("Sugerencia: Arriende una pelicula"); } Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 5 else { Console.Write("Le gusta leer? (s/n): "); respuesta = Console.ReadLine();
if (respuesta=="s") Console.WriteLine("Sugerencia: Tmese un vinito y lea un buen libro"); else Console.WriteLine("Sugerencia: Vaya a dormir! ...Buenas noches");
if (respuesta=="s") Console.WriteLine("Sugerencia: Vaya a la discotheque El Merengazo"); else Console.WriteLine("Sugerencia: Vaya a la discotheque Los Tarros"); }
else { Console.Write("Le gusta ir al cine? (s/n): "); respuesta = Console.ReadLine();
if (respuesta=="s") Console.WriteLine("Sugerencia: Vaya a ver una pelcula"); else Console.WriteLine("Sugerencia: Vaya a un pub y tmese un Pisco Sour"); } } Console.Write("Presione ENTER para terminar."); Console.ReadLine(); } }
Ejemplo de ejecucin: Veamos que hacer el sbado por la noche... Desea quedarse en casa? (s/n): s Le gusta ver TV? (s/n): n Le gusta leer? (s/n): s Sugerencia: Tmese un vinito y lea un buen libro
Veamos que hacer el sbado por la noche... Desea quedarse en casa? (s/n): n Le gusta bailar? (s/n): s Le gusta la msica tropical? (s/n): n Sugerencia: Vaya a la discotheque Los Tarros Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 6 2.2 Instruccin switch La instruccin switch permite decidir cul bloque de instrucciones se debe ejecutar, de una serie de bloques disponibles, tomando como criterio para la decisin el valor de una expresin. La expresin suministrada se compara con una serie de valores constantes que etiquetan los bloques de instrucciones, y cuando se logra un valor igual se inicia la ejecucin en ese punto. Sintaxis: switch ( expresin ) { case constante1 : { ... Bloque de instrucciones 1 ... break; } case constante2 : { ... Bloque de instrucciones 2 ... break; } ... case constanteN : { ... Bloque de instrucciones N ... break; } default : { // Opcional ... Bloque de instrucciones N+1 ... } } Los bloques de instrucciones consisten en una secuencia de instrucciones terminadas en punto y coma. Al ejecutarse una instruccin switch, se evaluar la expresin suministrada en los parntesis, y se comparar su valor con cada una de las constantes dadas, empezando por la primera y descendiendo. Dependiendo de estos valores puede ocurrir lo siguiente: Si se encuentra una constante igual al valor de la expresin, la ejecucin continuar en el bloque de instrucciones asociado con la constante, y seguir de ah en adelante hasta terminar el caso particular del switch, el cual debe terminar en instruccin break u otra de salto de flujo (como continue o return). Una vez hecho esto, la ejecucin continuar en la siguiente instruccin despus del switch. Si no se encuentra ninguna constante que sea igual al valor de la expresin, y no se incluy la seccin default, la instruccin pasar inadvertida (no se ejecutar ninguna de las instrucciones contenidas en ella), y la ejecucin continuar en la siguiente instruccin despus del switch. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 7 Si no se encuentra ninguna constante que sea igual al valor de la expresin, pero existe un bloque de instrucciones asociado con la partcula default, la ejecucin continuar en ese bloque. Una vez hecho esto, la ejecucin seguir en la siguiente instruccin despus del switch. Es posible escribir switch anidados, es decir, incluir otras instrucciones switch dentro de las instrucciones a ejecutar al evaluar una primera instruccin switch. Ejemplos: Clsico uso en un men de opciones Console.WriteLine(Con qu desea pagar?); Console.WriteLine(1) Efectivo); Console.WriteLine(2) Cheque); Console.WriteLine(3) Tarjeta Crdito); Console.WriteLine(4) MasterCard);
opcion = int.Parse(Console.ReadLine());
switch( opcion ) { case 1: Console.WriteLine(Slo con billetes nuevos); break; case 2: Console.WriteLine(Adjunte su cdula al cheque); break; case 3: Console.WriteLine(Entrguenos su tarjeta, por favor); break; default: Console.WriteLine(Lo siento, pero no manejamos ese medio); }
2.2.1 Ejemplo: Conversin a letras de una cantidad de dos dgitos Programa que convierte una cantidad de dos dgitos a letras, en la forma en que sera til, por ejemplo, para escribir un cheque. El programa es una versin muy simple que soporta slo cantidades entre 30 y 99 (no se consideran excepciones). El programa pide al usuario que ingrese una cantidad entre 30 y 99, y le devuelve por pantalla el equivalente en letras. No se tratan los nmeros entre 1 y 29 por simplicidad, dado que entre estos valores se presentan mltiples reglas de excepcin. Si no se respeta esta restriccin se obtendrn resultados sin sentido using System;
class MainApp { public static void Main() { int cantidad; // cantidad a convertir int decenas; // numero de decenas en la cantidad a convertir int unidades; // numero de unidades en la cantidad a convertir
Console.Write("Ingrese un numero entero entre 0 y 99: "); cantidad = (int) Console.Read();
if(decenas == 1) { switch(unidades) { case 0: {Console.Write("Diez ); break;} case 1: {Console.Write("Once ); break;} case 2: {Console.Write("Doce ); break;} case 3: {Console.Write("Trece ); break;} Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 8 case 4: {Console.Write("Catorce ); break;} case 5: {Console.Write("Quince ); break;} case 6: {Console.Write("Dieciseis ); break;} case 7: {Console.Write("Diecisiete); break;} case 8: {Console.Write("Dieciocho ); break;} case 9: {Console.Write("Diecinueve); break;} } } else{ switch(decenas) { case 2: { if (unidades == 0) Console.Write("Veinte"); else Console.Write("Veinti"); break; } case 3: { Console.Write("Treinta"); break; } case 4: { Console.Write("Cuarenta"); break; } case 5: { Console.Write("Cincuenta"); break; } case 6: { Console.Write("Sesenta"); break; } case 7: { Console.Write("Setenta"); break; } case 8: { Console.Write("Ochenta"); break; } case 9: { Console.Write("Noventa"); break; } }
if(unidades>0 && decenas>2) Console.Write(" y ");
switch(unidades) { case 0: { Console.Write("); break; } case 1: { Console.Write("uno ); break; } case 2: { Console.Write("dos ); break; } case 3: { Console.Write("tres ); break; } case 4: { Console.Write("cuatro); break; } case 5: { Console.Write("cinco ); break; } case 6: { Console.Write("seis ); break; } case 7: { Console.Write("siete ); break; } case 8: { Console.Write("ocho ); break; } case 9: { Console.Write("nueve ); break; } } } Console.Write("\nPresione ENTER para terminar."); Console.ReadLine(); } }
Ejemplo de ejecucin:
Ingrese un numero entero entre 0 y 99: 32 Treinta y dos
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 9 3 Iteracin 3.1 Instruccin while La instruccin while permite repetir una instruccin o un bloque de instrucciones, tantas veces como sea necesario, mientras una determinada expresin lgica sea verdadera. Si la expresin es falsa inicialmente, la instruccin while no tiene efecto alguno, es decir, no ejecuta ninguna de las instrucciones subordinadas. Ms adelante se presenta una equivalencia lgica de las tres instrucciones para especificar iteracin con que cuenta el lenguaje de programacin C. Sintaxis:
while ( expresin-lgica ) instruccin ;
while ( expresin-lgica ) { ... Bloque de instrucciones ... } Los bloques de instrucciones consisten en una secuencia de instrucciones terminadas en punto y coma. Al ejecutarse la instruccin while, se evaluar la expresin booleana suministrada en los parntesis, y si su valor es verdadero, se ejecutarn la o las instrucciones subordinadas. Una vez hecho esto, la condicin es reevaluada y se procede de la misma manera. Cuando la condicin se vuelve falsa, en la siguiente evaluacin se dar la instruccin while por terminada. Las instrucciones subordinadas al while pueden ser compuestas, es decir, otras instrucciones while, if, etc. Si la condicin nunca se vuelve falsa, la instruccin nunca terminar y, dependiendo de las instrucciones incluidas en el ciclo, se generara un error de ejecucin que detendra el programa, o podra ser que el programa itere indefinidamente hasta ser detenido en forma manual. Ejemplos: 1. num = 0; while (num < 50) { // Esto se ejecuta en cada iteracin, hasta que num = 50 if ( (num % 2) == 0 ) Console.WriteLine("El nmero {0} es par", num); else Console.WriteLine("El nmero {0} es impar", num); num++; }
3.1.1 Ejemplo: Tabla de conversin de temperaturas (Fahrenheit-Celsius) Programa que genera una tabla de equivalencias Celsius-Fahrenheit, desde -15 hasta 50 grados Celsius. Se emplea una funcin de conversin para llevar a cabo los clculos. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 10 using System;
class Temperatura {
// Funcin que recibe una temperatura expresada en grados Celsius y retorna // su equivalente en grados Faherenheit. El argumento de entrada es celsius // de tipo float. El valor de retorno tambin es de tipo float. // La frmula de conversin es F=32+(C*9/5) ***************************************************************************/ public float fahrenheit(float celsius) { return((celsius*9/5)+32); } }
class MainApp {
static void Main () { Temperatura temp = new Temperatura(); float centigrados = (float) -15.0; // Temperatura en grados Celsius, inicialmente -15
// Imprime el encabezado de la tabla con un formato que le da buena apariencia // Refirase a la descripcin de Console.WriteLine para mayor detalle Console.WriteLine("{0,15} {1,15}", "Celsius", "Fahrenheit");
// Ciclo que genera la tabla. La variable centgrados vale inicialmente -15, y // dentro del ciclo se va a ir incrementando en paso de 5 grados, hasta llegar // hasta 50: Ver la condicin de control del while. En cada iteracin del // ciclo se imprime el valor en centgrados y su equivalente fahrenheit. // Observe que la conversin se lleva a cabo directamente al imprimir. while (centigrados <= 50.0) { // Imprime la fila de la tabla: Centgrados - Fahrenheit Console.WriteLine("{0,15:F2} {1,15:F2}", centigrados, temp.fahrenheit(centigrados));
// Incrementa centigrados para la siguiente iteracin centigrados = centigrados + 5; } Console.WriteLine("Presione ENTER para terminar."); Console.ReadLine(); } }
Ejemplo de ejecucin: Celsius Fahrenheit -15.00 5.00 -10.00 14.00 -5.00 23.00 0.00 32.00 5.00 41.00 10.00 50.00 15.00 59.00 20.00 68.00 25.00 77.00 30.00 86.00 35.00 95.00 40.00 104.00 45.00 113.00 50.00 122.00 3.1.2 Ejemplo: Esperando el Ao Nuevo Este programa es una simulacin de un cronmetro para la espera del ao nuevo. El programa pide al usuario la fecha y hora actuales, y cuenta los segundos hasta la llegada del primero de enero del siguiente ao. Los segundos se simulan como iteraciones en un ciclo. Una vez llegada la fecha esperada imprime un mensaje que incluye la cantidad de segundos que esper (es decir, la cantidad de iteraciones Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 11 que complet). En esta simulacin se toman las medidas pertinentes para detectar y tratar en forma especial los aos bisiestos.
Ejemplo de ejecucin:
using System;
class Agno {
private int agno;
// Constructor de la clase. Inicializa el valor del ao public Agno(int a) { agno = a; }
////////////////////////////////////////////////////////////////////////////// // Funcin que recibe como argumento un ao y devuelve un nmero entero que // indica si es bisiesto o no. Si el ao pasado es bisiesto la funcin // retorna true, y en caso contrario false. Para saber si un ao es bisiesto // basta con analizar si es divisible por 4 y no por 100 (empleando mdulo). ////////////////////////////////////////////////////////////////////////////// public bool bisiesto() { if ((agno % 4 == 0) && (agno % 100 != 0)) return(true); else return(false); } }
class MainApp {
static void Main() { int d, m, a, hh, mm, ss; // Hora y fecha actuales long contador = 0; // Contador de segundos
Console.WriteLine("Ingrese la fecha actual."); Console.Write("Ingrese el da: "); d = int.Parse(Console.ReadLine()); Console.Write("Ingrese el mes: "); m = int.Parse(Console.ReadLine()); Console.Write("Ingrese el ao: "); a = int.Parse(Console.ReadLine()); Console.Write("Ingrese la hora: "); hh = int.Parse(Console.ReadLine()); Console.Write("Ingrese minutos: "); mm = int.Parse(Console.ReadLine()); Console.Write("Ingrese segundos: "); ss = int.Parse(Console.ReadLine());
Agno year = new Agno(a); // Se inicializa la instancia de ao
// Este ciclo simula la ocurrencia de un segundo en cada iteracin. La variable // contador (inicialmente en 0) se incrementa en cada vuelta, para lograr tal // efecto. Cada vez que pasa un segundo se verifica si es necesario actualizar // el estado de las variables que mantienen la hora, minutos, da, mes y ao. // La condicin para salir del ciclo es llegar (o estar) al primero de enero.
while (d!=1 || m!=1) { // Da=1 y Mes=1 -> 1 enero! ss++; // Se aumenta el contador de segundos if (ss==60) { ss = 0; mm++; if (mm==60) { mm=0; hh++; Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 12 if (hh==24) { hh = 0; d++;
// Verifica si hay cambio de mes, considerando las excepciones: // Abril, Junio, Septiembre y Noviembre tienen solo 30 das // Febrero tiene 28 das excepto en los aos bisiestos // El resto de los meses tienen 31 das if ( (d==29 && m==2 && !year.bisiesto()) || (d==30 && m==2 && year.bisiesto()) || (d==31 && (m==4 || m==6 || m==9 || m==11)) || (d==32) ) { d=1; m++; if (m==13) { m=1; a++; } } } } } contador++; }
Console.WriteLine("Feliz ao {0,4} !!!", a); Console.WriteLine("Transcurrieron {0} segundos", contador); Console.WriteLine("Presione ENTER para terminar."); Console.ReadLine(); } }
3.2 Instruccin do-while La instruccin do-while permite repetir una instruccin o un bloque de instrucciones, tantas veces como sea necesario, mientras una determinada expresin lgica sea verdadera. A diferencia de la instruccin while, la condicin se verifica una vez ejecutadas las instrucciones subordinadas, por lo que si la expresin es falsa inicialmente, y permanece as, el cuerpo del ciclo se ejecutar una vez (con while no se ejecutara). Sintaxis: do instruccin ; while ( expresin-lgica );
do { ... Bloque de instrucciones ... } while ( expresin-lgica );
Los bloques de instrucciones consisten en una secuencia de instrucciones terminadas en punto y coma. Al ejecutarse la instruccin do-while, se ejecutarn la o las instrucciones subordinadas. Una vez hecho esto, se evala la expresin booleana suministrada en los parntesis, y si su valor es verdadero, se volvern a ejecutar las instrucciones subordinadas y se proceder de la misma manera. Cuando la condicin se vuelve falsa, en la siguiente evaluacin se dar la instruccin do-while por terminada. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 13 Las instrucciones subordinadas al do-while pueden ser compuestas, es decir, otras instrucciones do-while, while, if, etc. Si la condicin nunca se vuelve cero, la instruccin nunca terminar y, dependiendo de las instrucciones incluidas en el ciclo, se generara un error de ejecucin que detendra el programa, o podra ser que el programa itere indefinidamente hasta ser detenido en forma manual. Ejemplos: 1. do { // Esto se ejecuta en cada iteracin del ciclo ... Console.Write ("Desea continuar? (s/n): "); respuesta = Console.ReadLine(); } while (respuesta != n);
Programas de ejemplo: Ver ejemplos en captulo de Algoritmos Numricos
3.3 Instruccin for La instruccin for permite repetir una instruccin o un bloque de instrucciones, tantas veces como sea necesario, mientras una determinada expresin lgica sea verdadera. Permite adems especificar instrucciones de inicializacin (que se ejecutarn una nica vez antes de empezar las iteraciones), as como instrucciones que deben ejecutarse al finalizar cada iteracin, pero antes de empezar la siguiente. Al igual que la instruccin while la condicin se verifica antes de ejecutar las instrucciones subordinadas, por lo que si la expresin es falsa inicialmente, la instruccin no tendr efecto alguno, es decir, no se ejecuta ninguna de las instrucciones subordinadas. Ms adelante se presenta una equivalencia lgica de las tres instrucciones para especificar iteracin con que cuenta el lenguaje de programacin C. Sintaxis: for ( inicializacin ; expresin-booleana ; actualizacin ) instruccin ;
for ( inicializacin ; expresin-booleana ; actualizacin ) { ... Bloque de instrucciones ... } Los bloques de instrucciones consisten en una secuencia de instrucciones terminadas en punto y coma. Tanto el componente de inicializacin como el de actualizacin corresponde a una instruccin, o a varias separadas por comas. Cualquiera de los componenentes en los parntesis se puede omitir, incluso los tres, pero los separadores (punto y coma) deben aparecer siempre. Al ejecutarse la instruccin for, en primera instancia se ejecutar la seccin de inicializacin. Posteriormente se evaluar la condicin y, en caso de ser verdadera (no cero), se ejecutarn la o las instrucciones subordinadas. Una vez cumplido esto, se ejecutar la seccin de actualizacin y se volver a verificar la condicin. Cuando la condicin se vuelve falsa (es decir, cero), en la siguiente evaluacin se dar la instruccin for por terminada. Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 14 Las instrucciones subordinadas al for pueden ser compuestas, es decir, otras instrucciones for, do- while, while, if, etc. Si la condicin nunca se vuelve cero, la instruccin nunca terminar y, dependiendo de las instrucciones incluidas en el ciclo, se generara un error de ejecucin que detendra el programa, o podra ser que el programa itere indefinidamente hasta ser detenido en forma manual. El uso normal que se le da a la instruccin for es para implementar ciclos en los cuales se conoce de antemano, o al menos se puede determinar antes del ciclo, la cantidad de iteraciones que son necesarias. En este caso, se emplea una variable de control (contador de iteraciones) que se inicializa en la seccin de inicializacin y se modifica (por ejemplo, incrementndola) en la seccin de actualizacin. Ejemplos: 1. Se conoce de antemano la cantidad de iteraciones:
for (i = 0 ; i < 100 ; i++) Console.WriteLine("{0}", i);
2. Ciclo infinito:
for (;;) { ... instrucciones ... }
3. Programa de uso del For using System;
class MainApp { static void main() { int rep; for (rep=1;rep<=20;rep=rep+5) // repite de 5 en 5 ascendente Console.WriteLine("rep ascendente: {0}",rep); for (rep=20;rep>=1;rep=rep-5) // repite de 5 en 5 descendente Console.WriteLine("rep descendente: {0},rep); } }
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 15 3.3.1 Ejemplo: Clculo de x a la n (uso restringido del for) Programa que calcula x**n (n-sima potencia de x), empleando un ciclo for. Se implementa una funcin que recibe dos argumentos, la base y el exponente, y devuelve el valor indicado. Para probar la funcin, el programa solicita al usuario los valores de la base y el exponente, lleva a cabo el clculo utilizando la funcin, y finalmente devuelve el resultado por pantalla.
using System;
class Calculo {
////////////////////////////////////////////////////////////////////////// // Funcin que calcula la n-sima potencia de un nmero x, ambos valores // recibidos como argumentos de entrada de tipo float. El valor de retorno // tambin es float. No se controla la validez de los argumentos. // Clculo: x**n = x * x * ... * x (n veces) ////////////////////////////////////////////////////////////////////////// public double potencia(double x, double n) { int i; // Contador del nmero de multiplicaciones realizadas double pot; // Acumulador para el resultado pot = x; // Se inicia la acumulacin del resultado con x (la base)
// Ciclo que lleva a cabo el calculo: i variar de 2 a n for (i=2; i<=n; i++) // Se multiplica el acumulado actual una vez ms por la base (x) pot = pot * x; // Devuelve como valor de retorno el resultado acumulado return(pot); }
}
class MainApp {
////////////////////////////////////////////////////////////////////////// // Pide al usuario una base x y un exponente n, y calcula el valor de x**n // (n-sima potencia de x), devolviendo el resultado por pantalla. ////////////////////////////////////////////////////////////////////////// static void Main() { float xbase; // Base empleada para el clculo, dado por el usuario int exponente; // Exponente empleado para el clculo, dado por el usuario Calculo cal = new Calculo();
// Solicita y lee del usuario los valores de base y exponente Console.Write("Ingrese el valor de x: "); xbase = float.Parse(Console.ReadLine()); Console.Write("Ingrese el valor de n: "); exponente = int.Parse(Console.ReadLine());
// Devuelve el resultado de x**n, llevando a cabo en forma directa el // llamado a la funcin que realiza el clculo en si. Emplea 2 decimales. Console.WriteLine("Resultado de x**n: {0}", cal.potencia(xbase, exponente));
Console.WriteLine("Presione ENTER para terminar"); Console.ReadLine(); } }
Ejemplo de ejecucin:
Ingrese el valor de x: 2 Ingrese el valor de n: 8 Resultado de x**n: 256
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 16 Ingrese el valor de x: 8 Ingrese el valor de n: 15 Resultado de x**n: 4747562057728 3.3.2 Ejemplo: Conversin a letras de cantidades numricas (uso general del for) Programa que convierte una cantidad numrica en su equivalente en letras, en la forma en que sera til, por ejemplo, para escribir un cheque. Es una versin mejorada del ejemplo de uso de switch, presentado anteriormente, pero con menos restricciones y, en general, un mejor funcionamiento. Se permiten cantidades de hasta 9 dgitos, aunque la ampliacin a ms dgitos es bastante simple. El programa solicita al usuario la cantidad en cuestin y le devuelve el equivalente. Existen algunas excepciones que no fueron consideradas para no complicar demasiado el ejemplo. Se permiten cantidades de hasta 9 dgitos, aunque la ampliacin a ms dgitos es bastante simple. El programa solicita al usuario la cantidad en cuestin y le devuelve el equivalente. Existen algunas excepciones que no fueron consideradas para no complicar demasiado el ejemplo. No se mostrar el desarrollo completo de la metodologa estudiada, sino tan solo la descomposicin en funciones del problema general, el algoritmo resultante y el cdigo equivalente en el lenguaje de programacin C#. El problema de la conversin a letras puede simplificarse si se descompone en funcionalidades ms independientes, las cuales se implementarn posteriormente como funciones en C#: Unidades Decenas Centenas Milenios (que agrupa desde los cien mil a los mil) Millones
Finalmente, el mtodo que transforma el nmero a texto, se define como toString2()
///////////////////////////////////////////////////////////////////////// // // Curso: IIC1102 - Introduccin a la Programacin Orientada a Objetos // Profesor: Rodrigo Sandoval U. // // Ejemplo de transformacin de nmeros a texto. // //////////////////////////////////////////////////////////////////////////
using System;
class Numero {
private long num;
public Numero(string numero) { this.num = int.Parse(numero); }
string Unidad(long Unidades) { switch(Unidades) { case 1: { return("uno" ); } case 2: { return("dos" ); } case 3: { return("tres" ); } Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 17 case 4: { return("cuatro" ); } case 5: { return("cinco" ); } case 6: { return("seis" ); } case 7: { return("siete" ); } case 8: { return("ocho" ); } case 9: { return("nueve" ); } } return(""); }
string Decenas(long Diez, long Uni) { switch(Diez) { case 0: { return(""); } case 1: { if(Uni >= 6) { return("dieci"); } else { switch(Uni) { case 0: { return("diez"); } case 1: { return("once"); } case 2: { return("doce"); } case 3: { return("trece"); } case 4: { return("catorce"); } case 5: { return("quince"); } default: return (""); } } } case 2: { if(Uni==0) return("veinte"); else return("veinti"); } case 3: { if(Uni==0) return("treinta"); else return("treinta y "); } case 4: { if(Uni==0) return("cuarenta"); else return("cuarenta y "); } case 5: { if(Uni==0) return("cincuenta");else return("cincuenta y "); } case 6: { if(Uni==0) return("sesenta"); else return("sesenta y "); } case 7: { if(Uni==0) return("setenta"); else return("setenta y "); } case 8: { if(Uni==0) return("ochenta"); else return("ochenta y "); } case 9: { if(Uni==0) return("noventa"); else return("noventa y "); } } return(""); }
string Centenas(long Cien, long Diez, long Uni) { if (Cien==1 && Diez==0 && Uni==0) return("cien"); else { switch(Cien) { case 1: { return ("ciento" ); } case 2: { return ("doscientos" ); } case 3: { return ("trescientos" ); } case 4: { return ("cuatrocientos"); } case 5: { return ("quinientos" ); } case 6: { return ("seiscientos" ); } case 7: { return ("setecientos" ); } case 8: { return ("ochocientos" ); } case 9: { return ("novecientos" ); } } } return(""); }
string Milenios(long CienMil, long DiezMil, long Mil) { string resultado = ""; if(CienMil!=0) resultado = resultado + Centenas (CienMil,DiezMil,Mil);
if(DiezMil!=0) resultado = resultado + " " + Decenas (DiezMil,Mil); Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 18
static void Main() { Console.Write("Ingrese un nmero (hasta 9.999.999): "); Numero num = new Numero(Console.ReadLine());
Console.WriteLine("{0}", num.toString2());
Console.WriteLine("Presione ENTER para terminar ... "); Console.ReadLine(); } }
Ejemplo de ejecucin: Ingrese un Numero: 3686041 tres millones seiscientos ochenta y seis mil cuarenta y uno Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 19 Ingrese un Numero: 2568 dos mil quinientos sesenta y ocho
3.4 Instruccin foreach La instruccin foreach repite un grupo de instrucciones definidas, para cada elemento dentro de un arreglo o dentro de una coleccin de objetos. Esta instruccin se usa para iterar a travs de la coleccin para obtener la informacin requerida, pero no debe ser utilizada para cambiar los contenidos de la coleccin del arreglo, ya que puede producir efectos laterales no deseados. La declaracin tiene la siguiente forma: foreach (tipo identificador in expresin) instrucciones
using System; class MainClass { public static void Main() { int impares = 0, pares = 0; int[] arr = new int [] {0,1,2,5,7,8,11};
foreach (int i in arr) { if (i%2 == 0) pares++; else impares++; }
Console.WriteLine("Hay {0} impares y {1} pares.", impares, pares); } } Ms ejemplos de esta instruccin se ven en una siguiente seccin, dedicada a los Arreglos o Arrays.
3.5 Equivalencia Lgica entre Instrucciones de Iteracin Las tres instrucciones con que cuenta el lenguaje de programacin C para la especificacin de iteracin son lgicamente equivalentes. Esto quiere decir que un ciclo escrito empleando una de las instrucciones puede reescribirse empleando otra sin que hayan cambios en la ejecucin del programa (su semntica). Para ilustrar este hecho, se muestra a continuacin un ciclo escrito con la instruccin for, y la forma en que se reescribira empleando las otras dos instrucciones de iteracin. Los bloques son secuencias de instrucciones. Empleando for: for (bloque1; condicin; bloque2) { bloque3 }
// Instrucciones de bloque1 y bloque2 separadas por coma // Instrucciones de bloque3 separadas por punto y coma Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 20
Empleando while: bloque1 while (condicin) { bloque3 bloque2 }
// Instrucciones de los bloques separadas por punto y coma
Empleando do-while: bloque1 if (condicin) do { bloque3 bloque2 } while (condicin);
// Instrucciones de los bloques separadas por punto y coma // Por qu es necesario el if?
Finalmente, se muestra otro ejemplo de la equivalencia lgica entre las instrucciones de iteracin. A continuacin se presenta un ciclo escrito mediante do-while, y la forma como se reescribira empleando while. Empleando do-while: do { bloque } while (condicin);
// Instrucciones del bloque separadas por punto y coma Empleando while: bloque while (condicin) { bloque }
// Instrucciones del bloque separadas por punto y coma // Por qu se debe repetir el bloque (afuera y adentro)? Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 21 3.5.1 Ejemplos: Programa con funciones equivalentes y Ciclos anidados Ejemplo 1: Equivalencia de Ciclos en Funcin Cuadrado() Este programa muestra la equivalencia lgica entre las funciones cuadrado, cuadrado1 y cuadrado2, para imprimir (dibujar) en pantalla un cuadrado.
using System;
class Cuadrado {
public void cuadrado(int longitud) { int a,b; for (a=1;a<=longitud;a++) { // ciclo externo for (b=1;b<=longitud;b++) // ciclo interno Console.Write("*"); Console.WriteLine(); // salto de lnea } }
public void cuadrado1(int longitud) { int a=1,b;
while (a<=longitud) { // ciclo externo b=1; while (b<=longitud) { // ciclo interno Console.Write ("*"); b++; } Console.WriteLine(); // salto de lnea a++; } }
public void cuadrado2(int longitud) { int a,b; a=1;
if (longitud>=1) { do { // ciclo externo b=1; if (longitud>=1) { do { // ciclo interno Console.Write ("*"); b++; } while (b<=longitud); Console.WriteLine(); // salto de lnea a++; } } while (a<=longitud); } } }
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 22 class MainApp {
static void Main() { Cuadrado cuad = new Cuadrado();
Ejemplo de ejecucin: ***** ***** ***** ***** *****
Ejemplo 2: Equivalencia de Ciclos en Series de Letras Las funciones serie_letras1, hasta serie_letras6 son equivalentes e imprimen una serie de letras using System;
class Letras {
public void serie_letras1(char a, char b, char c, char d) { int letra1,letra2;
for (letra1=a; letra1<=b; letra1++) for (letra2=c; letra2<=d; letra2++) Console.WriteLine("{0} {1} ",(char) letra1,(char) letra2); }
public void serie_letras2(char a,char b, char c, char d) { int letra1,letra2;
for (letra1=a; letra1<=b; letra1++) for (letra2=c; letra2<=d; letra2++) Console.WriteLine("{0} {1} ",(char) letra1,(char) letra2); }
public void serie_letras3(int a,int b, int c, int d) { int letra1,letra2;
for (letra1=a; letra1<=b; letra1++) for (letra2=c; letra2<=d; letra2++) Console.WriteLine("{0} {1} ", (char) letra1, (char) letra2); }
Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 23 public void serie_letras4(int a,int b, int c, int d) { int letra1,letra2;
for (letra1=a; letra1<=b; letra1++) for (letra2=c; letra2<=d; letra2++) Console.WriteLine("{0} {1} ",(char) letra1,(char) letra2); }
public void serie_letras5() { int letra1,letra2;
for (letra1='A'; letra1<='C'; letra1++) for (letra2=68;letra2<=69;letra2++) Console.WriteLine("{0} {1} ",(char) letra1,(char) letra2); }
public void serie_letras6() { int letra1,letra2;
letra1 = 65; // 65 ==> 'A'
while (letra1<='C') { letra2 = 'D'; while (letra2<=69) { Console.WriteLine("{0} {1} ",(char) letra1,(char) letra2); letra2++; } letra1++; } } }
Ejemplo de ejecucin A D A E B D B E C D Intro Prog. Orientada a Objeto Control de Flujo Rodrigo Sandoval U. IIC 1102 Pgina: 24 C E 3.6 Iteraciones con Anidamiento Dentro de las instrucciones que se pueden incluir en un ciclo se encuentran a su vez, otros ciclos, es decir, instrucciones while, do-while, y for. Este tipo de construcciones, en las que se incluye una instruccin de repeticin dentro del cuerpo de otra se conoce como iteracin anidada. En una iteracin anidada, en cada iteracin del ciclo exterior, se completa un grupo de iteraciones del ciclo interior. Considere, por ejemplo, el siguiente fragmento de cdigo:
for (i=1; i<=3; i++) for (j=1; j<=5; j++) Console.WriteLine("{0} {1}, i, j);
El ciclo exterior se ejecutar 3 veces, haciendo variar la variable i por los valores 1,2,3. En cada una de estas iteraciones se ejecutar un ciclo de 5 iteraciones (el for interior), en el que se variar la variable j por los valores 1,2,3,4,5. De esta forma, por cada valor que toma la variable i, la variable j tomar todos sus valores. As, la instruccin Console.WriteLine se ejecutar 15 veces (3x5), y la salida de este programa sera algo como: 1 1 1 2 1 3 1 4 1 5 2 1 2 2 2 3 2 4 2 5 3 1 3 2 3 3 3 4 3 5 Es posible anidar cualquier cantidad de instrucciones de iteracin, prcticamente hasta que la implementacin del compilador lo soporte. Sin embargo, demasiados niveles de anidamiento pueden volver el programa difcil de leer, por lo que se recomienda seguir reglas claras de indentacin, que hagan el cdigo ms legible. Ms adelante en la materia se muestran ejemplos en los que se emplean instrucciones de iteracin anidadas.
Material preparado por Rodrigo Sandoval U en Marzo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.al Los ejemplos fueron preparados por el MSR Lab del Depto de Ciencia de la Computacin, Escuela de Ingeniera
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo VI Algoritmos Numricos
1 ALGORITMOS O MTODOS NUMRICOS................................................................................................. 1 1.1 EJ EMPLO: CLCULO DE E MEDIANTE SERIE INFINITA ......................................................................................1 1.2 EJ EMPLO: CLCULO DE E A LA X, MEDIANTE SERIE, COMPARANDO CON FUNCIN EXP() ................................2 1.3 EJ EMPLO: CLCULO DE A ELEVADO A LA X (A**X), MEDIANTE SERIES, CON LA MXIMA PRECISIN POSIBLE4 1.4 EJ EMPLO: MTODO DE NEWTON PARA ENCONTRAR CEROS DE FUNCIONES ....................................................6 1.4.1 Implementacin...................................................................................................................................... 7
Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Algoritmos o Mtodos Numricos
Los mtodos numricos permiten resolver problemas obteniendo aproximaciones para las soluciones mediante algoritmos iterativos. Estos algoritmos reciben el nombre de algoritmos numricos. Las aproximaciones resultan de mucha utilidad cuando las soluciones analticas o algebraicas resultan muy difciles o hasta imposibles de obtener empleando mtodos tradicionales. Los computadores ayudan en gran manera, al facilitar la programacin de los algoritmos basados en iteracin. En esta seccin se presentan ejemplos de estos mtodos. 1.1 Ejemplo: Clculo de e mediante serie infinita Programa que calcula el valor de la constante e, base de los logaritmos neperianos. Se hace una aproximacin empleando la siguiente serie infinita: e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + ... El clculo se detiene cuando el valor acumulado de e, no se logra diferenciar (por la precisin del computador), del valor calculado en la iteracin anterior. Es decir, cuando el siguiente trmino a sumar es tan pequeo que el computador lo considera como un cero. El factorial, representado por ! en la serie, se implementa en el programa mediante una funcin. Una vez que se calcula la aproximacin, el programa despliega el valor encontrado, as como el nmero de iteraciones que se emplearon para obtenerlo, es decir, la cantidad de trminos de la serie que fue necesario sumar para llegar a la aproximacin.
/*************************************************************************** * Ejemplo: Calculo de la constante e mediante una serie infinita ***************************************************************************/
using System;
/*************************************************************************** * Funcin que calcula el factorial de su argumento. Tanto el argumento de * entrada (x) como el valor de retorno son de tipo double. No se hacen * controles sobre la validez del argumento, cuyo valor debe ser > 0. * Cualquier valor de entrada 0 o negativo arrojara un resultado de 1. * Formula del factorial: x! = 1 * 2 * 3 * ... * (x-1) * x ***************************************************************************/ public class CCalculateE { public double iter;
public CCalculateE() { iter = 1; }
private double mFactorial(double x) { double i; // Factor actual de multiplicacin: 2, 3, ..., x double fact = 1.0; // Acumulador para el resultado, inicialmente 1
// Ciclo en el que se calcula el factorial: i variara de 2 a x for (i=2.0; i<=x; i++) // Se multiplica el acumulado actual por el factor actual (i) fact = fact * i;
// Devuelve como valor de retorno el resultado acumulado return(fact); }
public double mGetE() { Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 2 double e = 1, eanterior;
do{ eanterior = e; e += 1/mFactorial(iter); iter++; }while( e != eanterior);
return e; } } /*************************************************************************** * Programa que calcula el valor de la constante e, base de los logaritmos * neperianos. Se emplea una aproximacin de la siguiente serie infinita: * e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + ... * El clculo se detiene cuando el valor acumulado de e, no se logra * diferenciar (por la precisin del computador), del valor calculado * en la iteracin anterior. ***************************************************************************/ public class CMain { public static void Main() { CCalculateE ce = new CCalculateE();
Console.WriteLine("El valor de E es: {0}",ce.mGetE()); Console.WriteLine("Se emplearon {0} iteraciones.",ce.iter); } }
Ejemplo de ejecucin:
Valor de e: 2.718281828459045534884808148490265011787000000000 Se emplearon 19 iteraciones 1.2 Ejemplo: Clculo de e a la x, mediante serie, comparando con funcin exp() Programa que calcula e**x (e elevado a la x), haciendo una aproximacin mediante una serie infinita. Se siguen sumando trminos mientras la diferencia entre el valor aproximado y el valor devuelto por la funcin exp() de la biblioteca math de C, sea mayor que una precisin dada por el usuario. La serie empleada es: Serie empleada: e**x = 1 + (x**1 / 1!) + (x**2 / 2!) + (x**3 / 3!) + ... El factorial, representado por !, y el operador de potencia, representado por **, se implementan en el programa mediante funciones. Una vez obtenida la aproximacin, el programa despliega el valor calculado, y el nmero de iteraciones que se emplearon para llegar a l, es decir, el nmero de trminos que fue necesario sumar.
/*************************************************************************** * Ejemplo: Calculo de e**x (e elevado a la x), empleando serie infinita * ***************************************************************************/ using System;
public class CEelevadoX { public double iter; public double res; public double exacto; public double precision;
Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 3 // Constructor de la clase CEelevadoX public CEelevadoX(double pres) { precision = pres; iter = 1; res = 1; } // Miembro privado ya que solo se usa dentro de la clase private double mFactorial(double x) { double i; double fact = 1;
for (i=2.0; i<=x; i++) fact = fact * i;
return(fact); }
// Miembro privado ya que solo se usa dentro de la clase private double mPotencia(double x, double n) { double i; double pot;
pot = x;
for (i=2; i<=n; i++) pot = pot * x;
return(pot); }
// Miembro pblico ya que se llama desde afuera de la clase para calcular e**x public double mGetEX(double power) { exacto = Math.Exp(power);
do { res += mPotencia(power,iter)/mFactorial(iter); iter++; } while((exacto - res) >= precision);
return res; } }
public class CMain { public static void Main() { double pres,x;
Console.Write("Ingrese la potencia: "); x = Double.Parse(Console.ReadLine()); Console.Write("Ingrese la precisin: "); pres = Double.Parse(Console.ReadLine());
// Nueva instancia de la clase CEelevadoX CEelevadoX ex = new CEelevadoX(pres); ex.mGetEX(x);
Console.WriteLine("El valor de e^x de System.Math es: {0}",ex.exacto); Console.WriteLine("El valor de e^x con {0} iteraciones y precisin de {1} es: {2}", ex.iter,ex.precision,ex.res); } }
Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 4 Ejemplo de ejecucin:
Ingrese el valor de x: 5 Ingrese la precision para el calculo de e(x): 0.01
Valor exp(x) de <math.h>: 148.413159102576600000000000000000000000000000000000
Calculo de e(x) con precision 1.000000e-002: 148.410210275043060000000000000000000000000000000000 Se emplearon 17 iteraciones
Ingrese el valor de x: 5 Ingrese la precision para el calculo de e(x): 0.000001
Valor exp(x) de <math.h>: 148.413159102576600000000000000000000000000000000000
Calculo de e(x) con precision 1.000000e-006: 148.413158521647740000000000000000000000000000000000 Se emplearon 23 iteraciones
1.3 Ejemplo: Clculo de a elevado a la x (a**x), mediante series, con la mxima precisin posible Programa que calcula a**x (a elevado a la x), haciendo una aproximacin mediante una serie, con la mxima precisin que el lenguaje C puede calcular, esto es, hasta que los resultados alcanzados por la serie converjan en un mismo valor. Se siguen calculando trminos de la serie mientras no exista diferencia entre un valor aproximado y el siguiente valor aproximado. La serie empleada es: a**x = 1+x*logE(a)+((x*logE(a))**2)/2!+((x*logE(a))**3)/3! + ... Elevar un nmero a una potencia, es representado en el texto por ** (lo cual no es una sintaxis vlida en C#). Una vez obtenida la aproximacin, el programa despliega el valor calculado. // Clculo de a elevado a la x (a**x) con la mxima precisin posible en C#. // los valores de a y x deben ser mayores que cero // se sabe que a**x = 1 + x * logE(a) + ((x * logE(a))**2)/2! + ((x * logE(a))**3)/3! + ... // y que logE(x) = 2 [(x-1)/(x+1) + 1/3((x-1)/(x+1))**3 + 1/5((x-1)(x+1))**5 - ... // // Recuerde que: (a**n) = a * (a**(n-1))
using System;
public class CAElevadoX { private double mLogE(double x) { double basem,bas,res,resa,rep;
bas = (x-1.0)/(x+1.0); basem = bas; res = bas; rep = 3.0;
do { resa = res; basem = basem * bas * bas; res = res + (1/rep)*basem; rep += 2.0; } while (res != resa);
return(2*res); }
Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 5 private double mFactorial(int x) { int i; double fact = 1;
for (i=2; i<=x; i++) fact = fact * i;
return fact; }
public double mPower(double a, double x) { double res,resa,bas,basem; int rep; bas = x * mLogE(a); basem = bas; rep = 2; res = bas;
do { resa = res; basem = basem * bas; res += ( basem / mFactorial(rep) ); rep++; } while (res != resa);
return(1+res); } }
public class CMain { public static void Main() { double a,x;
Console.Write("Ingrese la base: "); a = Double.Parse(Console.ReadLine()); Console.Write("Ingrese la Potencia: "); x = Double.Parse(Console.ReadLine());
Introducir valores: 2 3 valores de a: 2.00000 y x: 3.00000 resultado 8.00000
Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 6 1.4 Ejemplo: Mtodo de Newton para encontrar ceros de funciones Existen ecuaciones cuya solucin mediante tcnicas algebraicas tradicionales pueden resultar muy difciles de obtener. Un ejemplo es la ecuacin: ln x + 3x = 10.8074 Como se mencion anteriormente, los mtodos numricos ofrecen una alternativa para resolver este tipo de problemas, permitiendo obtener aproximaciones a las soluciones reales. En esta seccin se presenta un algoritmo que implementa el Mtodo de Newton para encontrar soluciones a ecuaciones del tipo f (x) = 0. La funcin para la cual se quieren encontrar los ceros ser definida mediante una directiva de precompilacin #define parametrizada, con lo cual ilustraremos la potencialidad de este tipo de definiciones. El usuario debe suministrar una aproximacin inicial de la solucin, que llamaremos x1. Entre ms cercana est esta aproximacin inicial de la solucin, ms rpido llegar el programa a un resultado. Nuestro algoritmo es iterativo, y se detiene cuando la diferencia entre dos aproximaciones sucesivas est dentro de una precisin o tolerancia dada por el usuario. Es decir:
La frmula bsica empleada en el mtodo de Newton para generar la siguiente aproximacin para la solucin es:
El algoritmo que aqu se presenta hace tambin una aproximacin numrica para la derivada f ' (x), obteniendo entonces la siguiente ecuacin: Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 7
1.4.1 Implementacin La funcin a la que se quiere encontrar el cero se define en el programa mediante la siguiente definicin: public double f(double x) { return Math.Log(x) + 3*x - 10.8074; } El resto de la implementacin es bastante sencilla, y muy similar a otros ejemplos mostrados anteriormente.
using System;
public class CNewton { public double iter; public double precision;
public CNewton(double pres) { iter = 0; precision = pres; }
public double mGetAnswer(double x1) { double di, xi1,xi;
xi1 = x1;
do{ xi = xi1; di = 0.0001 * xi; xi1 = xi - di * (f(xi) / (f(xi+di)-f(xi))); iter++; } while(Math.Abs(xi1-xi) >= precision);
return xi1; } }
/*************************************************************************** * Programa que calcula x tal que f(x) = 0, empleando el mtodo de Newton. * El proceso contina mientras el valor calculado mantenga una diferencia * con el valor obtenido en la iteracin anterior que sea mayor que una * precisin dada por el usuario. ***************************************************************************/
public class CMain Intro. Prog. Orientada a Objeto Algoritmos Numricos Rodrigo Sandoval U. IIC 1102 Pgina: 8 { public static void Main() { double x,pres;
Console.Write("Ingrese el valor de x: "); x = Double.Parse(Console.ReadLine()); Console.Write("Ingrese la presicion: "); pres = Double.Parse(Console.ReadLine());
Ingrese el valor de X1: 10 Ingrese la precision para el calculo de x: 0.000001
Calculo de x con precision 1.000000e-006:
x = 3.213360870175253400000000000000000000000000000000 f(x) = 0.000000000000000000 Se emplearon 4 iteraciones.
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo VII Arreglos y Enumeraciones en C#
1 ARREGLOS......................................................................................................................................................... 1 1.1 DECLARACIN DE ARREGLOS UNIDIMENSIONALES........................................................................................2 1.2 USO DE ARREGLOS UNIDIMENSIONALES.........................................................................................................3 1.2.1 Funciones ms comunes con arreglos.................................................................................................... 4 1.2.2 Foreach para el manejo de arreglos...................................................................................................... 5 1.2.3 Ejemplos de declaracin y uso de arreglos............................................................................................ 6 1.2.4 Ejemplo: Clculo de mnimo, mximo y promedio de una lista de notas de estudiantes....................... 7 1.2.5 Ejemplo: Programa de simulacin de conjuntos con arreglos .............................................................. 9 2 ARREGLOS MULTIDIMENSIONALES....................................................................................................... 13 2.1 DECLARACIN DE MATRICES........................................................................................................................13 2.2 USO DE MATRICES........................................................................................................................................14 2.2.1 Obteniendo Dimensiones de una Matriz .............................................................................................. 14 2.2.2 Ejemplos de uso de Matrices................................................................................................................ 14 2.2.3 Foreach en matrices............................................................................................................................. 14 2.2.4 Ejemplo: Clculo de las notas finales de un curso (mnimo, mximo, promedio) ............................... 15 2.2.5 Ejemplo: Multiplicacin de Matrices Cuadradas ................................................................................ 18 3 .......................................................................................................................................... 23 ENUMERACIONES
Material preparado por Rodrigo Sandoval U en Marzo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.al
Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 1 Arreglos Los arreglos son estructuras de datos complejas (en el sentido de que no son atmicas) que agrupan datos de un mismo tipo en particular, llamado el tipo base del arreglo. El tipo base de un arreglo puede ser cualquiera de los tipos bsicos de C#, o incluso algunos tipos complejos como las clases. Un arreglo es tambin ejemplo de un modelo. Un arreglo puede considerarse como ejemplo de una variable compuesta capaz de almacenar uno o ms datos al mismo tiempo.
La sintaxis del lenguaje permite referirse a cada uno de los elementos que constituyen el arreglo empleando ndices. Esto es posible pues los elementos del arreglo estn numerados en forma jerrquica y consecutiva, empezando en 0 en cada dimensin. El siguiente grfico ilustra un ejemplo de un arreglo llamado numeros, cuya posicin 0 almacena el valor 10, la posicin 1 el valor de 21, etc. Este arreglo en total almacena n+1 elementos. El valor de n, depende de la memoria que pueda tener el computador y el tipo de elementos que se almacenen en el arreglo.
IIC 1102 Pgina: 1 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Los arreglos, al igual que el resto de las variables se identifican con un nombre. Al emplear ese nombre, se hace referencia a la estructura de datos como un todo, es decir, con todos sus elementos. El lenguaje interpreta dicho nombre como un puntero. Cuando se utiliza el nombre del arreglo en forma indexada, es decir, combinado con ndices, se hace referencia a un elemento particular, del tipo base, dentro de la estructura compleja. Importante: El lenguaje C#no controla la validez de los ndices que se emplean para referenciar un arreglo. Esto quiere decir que es posible cometer errores graves y difciles de detectar en este sentido. Ms adelante se presenta un ejemplo en este sentido. 1.1 Declaracin de Arreglos Unidimensionales Los arreglos, al igual que las dems variables deben declararse antes de poder utilizarlas, y cumplen con las mismas reglas de alcance y vida. Los arreglos de una sola dimensin reciben tambin el nombre de vectores. La sintaxis de la declaracin de un arreglo unidimensional es la siguiente: <tipo-base>[] <identificador>; Observaciones: El <tipo-base> puede ser cualquiera de los tipos bsicos del lenguaje, o incluso algunos complejos como estructuras. El <identificador>es el nombre que distinguir el arreglo. Los corchetes [] son obligatorios y denotan que el identificador descrito, del tipo-base indicado, es un arreglo (lista de elementos del tipo base). En esta declaracin NO se define el tamao que tendr el arreglo (aunque se puede determinar las dimensiones, lo que se ver ms adelante). El tamao del arreglo se determina en una segunda declaracin, que puede ir en la siguiente lnea, como se muestra a continuacin. <identificador> = new <tipo-base> [<NumElementos>] En esta declaracin, se dimensiona el arreglo con una cantidad determinada de elementos, todos correspondientes a tipo-base.
Es posible hacer la declaracin del arreglo y su dimensionamiento en una misma sentencia: <tipo-base>[] <identificador> = new <tipo-base>[<NumElementos>]
Adicionalmente es factible declarar, dimensionar, e inicializar un arreglo con todos sus elementos, en una sola declaracin: <tipo-base>[] <identificador> = {valor1, valor2, ..., valorN}; Esta ltima declaracin implcitamente dimensiona el arreglo para almacenar los N elementos descritos, por lo que no se requiere dimensionarlo aparte. Es decir: Con los valores indicados entre llaves {} se inicializarn los elementos del arreglo. Los valores deben ser del <tipo-base>del arreglo.
IIC 1102 Pgina: 2 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Tambin es factible declarar, dimensionar, e inicializar un arreglo con todos sus elementos, en una sola declaracin, pero slo indicando un subconjunto de los valores que el arreglo puede guardar: <tipo-base>[] <identificador> = new <tipo-base>[N] {valor1, ..., valorM}; ... donde M<N, y N debe ser una expresin constante, como por ejemplo 10. Es factible hacer una declaracin donde M>N, en cuyo caso, el real dimensionamiento del arreglo se regir por M. Algunos ejemplos: // Arreglo para 10 enteros int [] numeros; numeros = new int[10];
// Arreglo para 10 enteros int [] numeros = new int[10];
1.2 Uso de Arreglos Unidimensionales Los elementos de un arreglo son variables del tipo base del vector, por lo que se utilizan de la misma manera en expresiones y dems instrucciones, como la asignacin. Por ejemplo, para asignar un valor a un elemento de un arreglo basta con escribir: <arreglo>[indice] = <expresion>; donde <arreglo> es el nombre de la variable e indice hace referencia a la posicin del elemento al que se le quiere asignar el <expresion>. La referencia de valores en un arreglo, se indexa desde el 0 al N-1. Importante: Puesto que los arreglos son estructuras complejas (es decir, no bsicas), no es posible asignar un arreglo a otro mediante una simple asignacin (=). Para hacer esto es necesario escribir un ciclo y asignar elemento a elemento. Como se mencion anteriormente, el lenguaje C# no controla la validez de los ndices que se emplean para referenciar un arreglo. Esto quiere decir que es posible cometer errores muy difciles de detectar en este sentido. Es necesario prestar especial inters a los valores que toman los ndices para evitar estos problemas. Por ejemplo, la siguiente porcin de cdigo compila sin problemas (es decir, sin errores sintcticos), pero probablemente produzca un error en tiempo de ejecucin al referenciarse posiciones inexistentes del arreglo.
// Las posiciones con ndices del 10 al 19 son invlidas. int[] arreglo = { 1,1,1,1,1,1,1,1,1,1 }; // 10 elementos int i; for (i=0; i<20; i++) arreglo[i] = 0; // Error para i >= 10 IIC 1102 Pgina: 3 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Tambin es comn cometer estos errores olvidando que las posiciones de los arreglos estn numeradas a partir del ndice cero. Es decir, en un arreglo de tamao N las posiciones estn numeradas de 0 a N-1. 1.2.1 Funciones ms comunes con arreglos En C#, los arreglos se representan con un tipo especfico, y por ello cuentan con sus propios atributos y mtodos especficos. Por ejemplo, para obtener el largo (la cantidad de elementos dimensionados) de un arreglo, o para ordenarlo. El Largo de un Arreglo En el caso de los arreglos unidimensionales, el tamao o cantidad de elementos se obtiene con la propiedad Length. int [] numeros = { 1,2,3,4,5,6 } Console.WriteLine(Largo: {0}, numeros.Length);
Ordenamiento de un Arreglo En el caso de los arreglos que sean de uno de los tipos predefinidos (int, float, char, etc.), es factible ordenarlos en forma creciente, aprovechando el mtodo bsico Sort() de la clase Array: int [] numeros = { 4,5,2,3,1,6 } Array.Sort(numeros); // 1,2,3,4,5,6
Revertir el Orden de un Arreglo En el mismo caso en que se pueda ordenar un arreglo, se puede reordenar exactamente al revs de cmo est, aprovechando el mtodo bsico Reverse() de la clase Array: int [] numeros = { 1,2,3,4,5,6 } Array.Reverse(numeros); // 6,5,4,3,2,1
Ejemplo de Manipulacin de Arreglos using System;
class Arreglo { int[] numeros;
public Arreglo(int [] arreglo) { numeros = new int[arreglo.Length]; for (int i=0; i<numeros.Length; i++) numeros[i] = arreglo[i]; }
public void Ordenar() { Array.Sort(numeros); }
public void Reordenar() { Array.Reverse(numeros); }
public void Imprimir() { foreach(int i in numeros) Console.Write("{0} ",i); Console.WriteLine(); } IIC 1102 Pgina: 4 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U.
}
class MainApp {
static void Main() { int[] numeros = { 2,5,6,1,3,4 }; Arreglo a = new Arreglo(numeros);
1.2.2 Foreach para el manejo de arreglos Existe esta sentencia de control de flujo, especialmente diseada para este tipo de estructuras, donde se manejan listas de elementos, todos del mismo tipo. Foreach depende de la definicin previa de un arreglo de elementos del mismo tipo, los cuales puede recorrer individualmente sin conocer el tamao explcitamente (como se requiere en otras instrucciones, por ejemplo en el for). La sintaxis de uso es: foreach ( <tipo> <variable> in <arreglo> ) { <instrucciones> } Donde: <tipo>es el tipo bsico de los elementos contenidos en el arreglo. <arreglo>es el arreglo de elementos a revisar. <variable> es un identificador de una variable local del foreach() que se usar para ver un elemento del arreglo en cada iteracin.
Ejemplo: using System; class MainClass {
public static void Main() { int impares = 0, pares = 0; int[] arr = new int [] {0,1,2,5,7,8,11};
foreach (int i in arr) { if (i%2 == 0) pares++; else impares++; } Console.WriteLine("Hay {0} impares y {1} pares.", impares, pares); IIC 1102 Pgina: 5 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Console.ReadLine(); } } A continuacin se incluyen ejemplos, tanto de declaracin y uso de arreglos, como del uso de foreach. 1.2.3 Ejemplos de declaracin y uso de arreglos En todos los casos, A es el nombre de la variable declarada: 1. Declaracin de un arreglo de 50 enteros: int[] A = new int[50];
2. Declaracin de un arreglo de 100 caracteres: char[] A = new char[100];
3. Declaracin e inicializacin de un arreglo de 10 enteros: int[] A = { 2, 5, 8, 100, 1, 2, 100, 5, 5, 5 }
4. Inicializacin parcial: El resto se inicializa e int[] A = new int[100] { 25, 5, 100, 25, 5 } n cero:
5. Declaracin e inicializacin de un arreglo de 10 caracteres: char[] A = { 'a', 'z', 'E', 'e', 65, '\65', '@', 'U', '*', '\n' }
6. Asignando un va A[5] = 200; lor a la sexta posicin de un arreglo de enteros:
7. Imprimiend int i; o un arreglo de 100 enteros mediante un ciclo for: for (i=0; i<100; i++) Console.Write("{0} ", A[i]);
8. Imprimiendo un arreglo de 100 enteros mediante un ciclo foreach:
Console.Write("{0} ", i); foreach (int i in A)
9. Leyendo del usuario el contenido de un arreglo de 20 enteros, mediante un ciclo for: int i; for (i=0; i<20; i++) A[i] = int.Parse(Console.ReadLine());
10. Una funcin que recibe un arreglo de enteros como argumento y calcula el promedio: int promedio(int[] A) { int prom = 0; foreach( int i in A ) prom = prom + i; return(prom/A.Length); }
11. Llamando una funcin que recibe un arreglo de enteros como parmetro: int prom; int[] A; ... prom = promedio(A); IIC 1102 Pgina: 6 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 1.2.4 Ejemplo: Clculo de mnimo, mximo y promedio de una lista de notas de estudiantes Se desea calcular el promedio, mnimo y mximo de una lista de notas correspondientes a un curso. Se recibir el nmero de alumnos y la nota correspondiente a c/u, y se entregan los resultados en la pantalla. 1. Definicin del problema 1.1 Conceptualizacin: El problema consiste en calcular el promedio, mnimo y mximo de una lista de notas de un curso. Cada alumno tiene una nota en el curso. Se supone que el usuario conoce a priori la cantidad de alumnos del curso y que entregar los datos en forma correcta. 1.2 Objetivo: El objetivo es obtener el promedio, el mximo, y el mnimo de las notas del curso. 1.3 Elementos involucrados: Los nicos elementos involucrados son las notas, la cantidad de alumnos, el promedio, el mnimo y el mximo. Como elemento activo, el usuario que conoce las notas en detalle. 2. Conceptualizacin de la solucin 2.1 Entidades: El Curso es la nica entidad relevante, la cual se conceptualiza como la agrupacin de notas correspondientes a los alumnos. 2.2 Clases: La clase Curso, ser la representacin de las notas de un curso cuyo promedio se quiere calcular. Esta clase se compone de los siguientes: Atributos de la Clase Curso notas: un arreglo que almacenar todas las notas (en forma de nmero real, con decimales) promedio (PROM): el valor resultante del promedio de notas del curso minimo (MIN): el valor de la mnima de todas las notas del curso maximo (MAX): el valor de la mnima de todas las notas del curso Mtodos de la Clase Curso Curso: (constructor) obtiene los valores de todas las notas ingresadas por el usuario. El algoritmo de este mtodo es: 1. Obtener la cantidad de alumnos: N 2. Iterar para cada uno de los N alumnos 2.1 Obtener la nota del alumno Calcular: recorre la lista de notas, calculando el mnimo, el mximo y el promedio de estos valores. El algoritmo de este mtodo es: 0. Se declara una variable local: SUMA 1. Inicialmente la suma de notas, SUMA, es 0, el mximo, MAX, es 1, y el mnimo, MIN, es 7 2. Iterar para cada para cada uno de los N alumnos 2.1 Agregar a SUMA la nota del alumno 2.2 Si la nota del alumno es mayor que MAX 2.2.1 MAX es ahora la nota del alumno 2.3 Si la nota del alumno es menor que MIN 2.3.1 MIN es ahora la nota del alumno 3. El promedio, PROM es SUMA dividido por N Mostrar: muestra en pantalla los valores de promedio, mnimo y mximo IIC 1102 Pgina: 7 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U.
2. 3 Instancias: La nica instancia requerida es notas1, de la clase Curso.
3. Especificacin del Algoritmo Algoritmo: 1. Declarar instancia de curso 2. Obtener las notas para el curso 3. Calcular el promedio, mnimo y mximo 4. Mostrar los resultados 4. Validacin Es importante analizar casos extremos en los que el usuario pueda ingresar valores poco usuales. Por ejemplo, si la cantidad de alumnos es cero o si es muy grande. Esto es particularmente importante para validar el programa en C#. Por lo tanto, deben definirse dominios de validacin que representan estas situaciones. Adems, deben considerarse dominios que incluyan distintos valores para las notas. Por ejemplo, varias notas distintas y repetidas, todas las notas iguales, etc. Tambin debe definirse un dominio en el que el nmero de estudiantes es uno, pues podra presentar algn problema. 5. Limitaciones Las limitaciones de este algoritmo se presentan principalmente en su implementacin en el lenguaje de programacin C#. Dado que se va a utilizar un arreglo para almacenar las distintas notas, el mximo nmero de notas que podrn ingresarse estar limitado por la dimensin mxima factible de almacenar en un arreglo, aunque dado el caso de C#y el contexto, se asumo que la cantidad de notas difcilmente ser tan grande. Por otra parte, no se planean controles de validez sobre los nmeros que ingresa el usuario, de modo que se supone que se ingresarn valores correctos, en el rango de 1 a 7. De no ser as, el comportamiento del programa no est definido (es decir, puede pasar cualquier cosa). Tambin se supone que el nmero de alumnos es mayor que cero, o el comportamiento del programa no est definido. Por ejemplo, si se ingresa como nmero de alumnos un cero, esto producir una divisin por cero al calcular el promedio.
//////////////////////////////////////////////////////////////// // Programa que lee del usuario una lista de notas correspondientes a los // alumnos de un curso, y calcula el promedio, mnimo y mximo. Se ilustra // el uso de arreglos para el almacenamiento de la informacin de entrada. // Este programa podra reescribirse sin el uso de arreglos: Como? //////////////////////////////////////////////////////////////// using System;
class Curso {
const float MAX_NOTA = 7.0F; // Las expresiones tipo float requieren una F al final const float MIN_NOTA = 1.0F;
public Curso() { int n; Console.Write("Ingrese el nmero de alumnos en la seccin: "); n = int.Parse(Console.ReadLine());
IIC 1102 Pgina: 8 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. notas = new float[n];
for(int i=1; i<=n; i++) { Console.Write("Ingrese la nota {0}: ", i); notas[i-1] = float.Parse(Console.ReadLine()); } }
public void Calcular() { float suma = 0;
minimo = MAX_NOTA; maximo = MIN_NOTA;
foreach( float nota in notas ) { if (minimo>nota) minimo = nota; if (maximo<nota) maximo = nota; suma += nota; } promedio = suma / notas.Length; }
public void Mostrar() { Console.WriteLine("Promedio de las {0} notas = {1}", notas.Length, promedio); Console.WriteLine("Mnimo de las {0} notas = {1}", notas.Length, minimo); Console.WriteLine("Mximo de las {0} notas = {1}", notas.Length, maximo); } }
class MainApp {
static void Main() { Curso c = new Curso(); c.Calcular(); c.Mostrar(); Console.ReadLine(); } }
Ejemplo de ejecucin: Ingrese el nmero de alumnos en la seccin: 5 Ingrese la nota 1: 5,6 Ingrese la nota 2: 5,8 Ingrese la nota 3: 6,2 Ingrese la nota 4: 4,6 Ingrese la nota 5: 5,1 Promedio de las 5 notas = 5,46 Mnimo de las 5 notas = 4,6 Mximo de las 5 notas = 6,2
1.2.5 Ejemplo: Programa de simulacin de conjuntos con arreglos //////////////////////////////////////////////////////////////// // Programa de simulacin de operaciones sobre conjuntos de // elementos del tipo entero, se pueden considerar todos los // nmeros enteros positivos y negativos, excepto el 0 ////////////////////////////////////////////////////////////////
using System;
class Conjunto { IIC 1102 Pgina: 9 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. const int MAX_NUMS = 20;
int[] numeros;
// Constructor. // Se considera que toda posicin del arreglo que tiene un // 0, no es un elemento del conjunto entonces un arreglo de // n posiciones con valores 0, es un conjunto vaco public Conjunto () { numeros = new int[MAX_NUMS]; Limpiar(); }
public int Elemento(int n) { return(numeros[n-1]); }
public void Limpiar() { for (int i=0; i<MAX_NUMS; i++) numeros[i] = 0; }
public void Cargar() { int i = 0;
Console.WriteLine("CARGA DE DATOS (0 para terminar)"); do { Console.WriteLine("Ingrese el elemento {0} del conjunto ",i+1); Agregar(int.Parse(Console.ReadLine())); i++; } while(numeros[i-1]!=0 && i < numeros.Length); }
// Se requiere la cantidad de elementos que son !=0 public int Largo() { int largo = 0;
foreach (int n in numeros) { if(n==0) break; largo++; } return(largo); }
// Verifica si el elemento a est en el conjunto public bool Esta(int a) { foreach(int n in numeros) if(n == a) return (true);
return (false); }
// Agrega el elemento si hay espacio y slo si no est public void Agregar(int a) { int posicion; posicion = Largo(); if(!Esta(a) && posicion<numeros.Length) numeros[posicion] = a; }
// Imprime en pantalla en formato ( ... ) public void Imprimir() { Console.Write("{0} elementos: ( ", Largo()); foreach(int n in numeros) if(n!=0) Console.Write("{0} ",n); else break; Console.WriteLine(")"); }
// Unin de conjuntos // Se usan dos instancias de la clase como parmetros de este mtodo // Este mtodo es de nivel superior a cada instancia, por lo que se // declara "static" -> comn para todas las instancias de la clase Conjunto public static Conjunto Union(Conjunto c1, Conjunto c2) { Conjunto c = new Conjunto(); IIC 1102 Pgina: 10 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U.
// Primero se copian todos los elementos del conjunto 1 for(int i=0; i<c1.Largo(); i++) c.Agregar(c1.Elemento(i+1));
// Segundo, se copian los del segundo conjunto que an no estn for(int i=0; i<c2.Largo(); i++) if (!c.Esta(c2.Elemento(i+1))) c.Agregar(c2.Elemento(i+1));
return(c); // Se retorna el conjunto resultante }
// Interseccin de Conjuntos public static Conjunto Interseccion(Conjunto c1, Conjunto c2) { Conjunto c = new Conjunto();
// Se copian todos los elementos del conjunto 1 que estn en c2 for(int i=0; i<c1.Largo(); i++) if (c2.Esta(c1.Elemento(i+1))) c.Agregar(c1.Elemento(i+1));
return(c); // Se retorna el conjunto resultante } }
class MainApp {
static void Main() { Conjunto c1 = new Conjunto(); Conjunto c2 = new Conjunto(); Conjunto c3 = new Conjunto(); Conjunto c4 = new Conjunto();
// Se le agregan elementos al primer conjunto y se muestra c1.Agregar(2); c1.Agregar(3); c1.Agregar(4); c1.Imprimir();
Console.WriteLine("5 es elemento del conjunto 0? --> {0}", c1.Esta(5)); Console.WriteLine("Se ingresa 5 al conjunto c1"); c1.Agregar(5); Console.WriteLine("5 es elemento del conjunto 0? --> {0}", c1.Esta(5)); c1.Imprimir(); Console.WriteLine("---------------------------");
Console.WriteLine("Ingrese elementos del conjunto 2"); c2.Cargar(); Console.WriteLine("---------------------------");
Console.WriteLine("Ingrese elementos del conjunto 3"); c3.Cargar(); Console.WriteLine("---------------------------");
IIC 1102 Pgina: 11 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Ejemplo de ejecucin: 3 elementos: ( 2 3 4 ) 5 es elemento del conjunto 0? --> False Se ingresa 5 al conjunto c1 5 es elemento del conjunto 0? --> True 4 elementos: ( 2 3 4 5 ) --------------------------- Ingrese elementos del conjunto 2 CARGA DE DATOS (0 para terminar) Ingrese el elemento 1 del conjunto 1 Ingrese el elemento 2 del conjunto 2 Ingrese el elemento 3 del conjunto 3 Ingrese el elemento 4 del conjunto 4 Ingrese el elemento 5 del conjunto 0 --------------------------- Ingrese elementos del conjunto 3 CARGA DE DATOS (0 para terminar) Ingrese el elemento 1 del conjunto 2 Ingrese el elemento 2 del conjunto 4 Ingrese el elemento 3 del conjunto 6 Ingrese el elemento 4 del conjunto 8 Ingrese el elemento 5 del conjunto 0 --------------------------- Conjunto 2: 4 elementos: ( 1 2 3 4 ) Conjunto 3: 4 elementos: ( 2 4 6 8 ) Conjunto2 U Conjunto3 6 elementos: ( 1 2 3 4 6 8 ) Conjunto2 Intersec. Conjunto3 2 elementos: ( 2 4 )
IIC 1102 Pgina: 12 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 2 Arreglos Multidimensionales Los arreglos que se estudiaron anteriormente son estructuras de datos vectoriales de una sola dimensin. En C#tambin es posible manejar arreglos de ms de una dimensin. Particularmente en este lenguaje, existen dos maneras de declarar arreglos multidimensionales, por un lado aquellos en que todas las dimensiones son fijas, tambin conocidos como matrices, y en segundo lugar, los que tienen filas (o columnas) de largo distinto. En forma rigurosa, estos ltimos arreglos no son ms que arreglos en los que cada elemento es a la vez otro arreglo, que puede ser de diferente dimensin que su vecino. Los arreglos de dos dimensiones reciben el nombre de matrices. Gran parte del desarrollo de esta seccin se limita a las matrices, es decir, a arreglos de dos dimensiones, de filas del mismo tamao. Sin embargo, tanto la sintaxis para la declaracin como la forma de utilizar estos arreglos puede generalizarse sin problema a dimensiones mayores (3D, 4D, etc). Para referirse a cada uno de los elementos que constituyen el arreglo es necesario emplear una serie de ndices. En el caso de las matrices, dos. Esto es posible pues los elementos de la matriz, al igual que en el caso de los vectores unidimensionales, estn numerados en forma jerrquica consecutiva, empezando en 0,0. Cada par de ndices referencia tanto una fila, como una columna de la matriz, identificando de manera nica cada elemento de la estructura. 2.1 Declaracin de Matrices Como se mencion anteriormente, las matrices no son ms que arreglos en los que cada elemento es a su vez otro arreglo. La sintaxis de la declaracin de una matriz es la siguiente: <tipo-base>[,] <identificador>; Observaciones: El <tipo-base> puede ser cualquiera de los tipos bsicos del lenguaje, o incluso algunos complejos como estructuras. Cada elemento de la matriz ser del tipo definido aqu. El <identificador> es el nombre que distinguir la matriz. Los corchetes [] son obligatorios. El separador de dimensiones es la coma ,. El dimensionamiento de estas matrices se puede hacer en una declaracin separada, de la siguiente manera: <identificador> = <tipo-base>[NumElem1, NumElem2]; El trmino <NumElem1> determina el tamao de la primera dimensin de la matriz, es decir, la cantidad de filas que tendr. Los elementos de la segunda dimensin (columnas) estn numerados en forma consecutiva, empezando en 0. El trmino <NumElem2> determina el tamao de la segunda dimensin de la matriz, es decir, la cantidad de elementos del tipo base que contendr. Dichos elementos estarn numerados en forma consecutiva, empezando en 0. Al igual que en el caso de arreglos unidimensionales, es posible declarar una matriz y al mismo tiempo inicializar sus elementos con valores del tipo base. La sintaxis para hacer esto es la siguiente: <tipo-base>[M,N] identif = { { valor1-1, valor1-2, ..., valor1-N }, { valor2-1, valor2-2, ..., valor2-N }, ..., { valorM-1, valorM-2, ..., valorM-N } }; Con los valores indicados entre llaves {} se inicializarn los MxN elementos de la matriz. Los valores deben ser del <tipo-base> de la matriz. IIC 1102 Pgina: 13 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 2.2 Uso de Matrices Los elementos de una matriz se pueden entender como un casillero o una celda, determinada por fila y columna. Para asignar un valor a un elemento de una matriz basta con escribir: matriz[indice1,indice2] = valor; en donde matriz es el nombre de la variable y las expresiones indice1 e indice2 hacen referencia a la posicin del elemento al que se le quiere asignar el valor. El nombre de una matriz tambin puede emplearse sin ndice, bajo ciertas circunstancias, por ejemplo, para pasar la matriz completa como argumento a una funcin. 2.2.1 Obteniendo Dimensiones de una Matriz Al igual que en las matrices unidimensionales, el largo de la fila o columna de una matriz se puede obtener, en este caso con el mtodo GetLength(dimension), donde dimension se refiere a filas, columnas, etc. En el caso de una matriz bidimensional, el largo de las filas se ve con GetLength(0), y de las columnas, con GetLength(1). 2.2.2 Ejemplos de uso de Matrices En todos los casos, matriz es el nombre de la variable declarada: 1. Declaracin de una matriz de 50 filas de 20 enteros: int[,] matriz = new int[50,20];
2. Declaracin e inicializacin de una matriz: int[,] matriz = { { 2, 5, 8 }, { 9, 1, 2 } }; // 2 filas, 3 col.
3. Asignando un valor a la primera posicin de la segunda fila de una matriz de enteros: matriz[1,0] = 50;
4. Imprimiendo una matriz de 100x50 enteros mediante un ciclo for: int i, j; for (i=0; i<100; i++) { for (j=0; j<50; j++) Console.Write("{0} ", matriz[i,j]); Console.WriteLine(); }
5. Imprimiendo una matriz de NxN enteros mediante un ciclo for: int i, j; for (i=0; i<matriz.GetLength(0); i++) { for (j=0; j< matriz.GetLength(1); j++) Console.Write("{0} ", matriz[i,j]); Console.WriteLine(); } 2.2.3 Foreach en matrices En forma similar al caso de los arreglos unidimensionales, es posible utilizar foreach() para recorrer los elementos de las celdas de una matriz. Sin embargo, foreach() hace un recorrido exhaustivo sin explicitar cuando se cambia de fila o de columna. Es decir, en este caso sirve para recorrer todo el contenido de una matriz, sin tener conocimiento explcito de las respectivas posiciones de las celdas. IIC 1102 Pgina: 14 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 2.2.4 Ejemplo: Clculo de las notas finales de un curso (mnimo, mximo, promedio) Se desea calcular las notas finales de los alumnos de un curso, as como tambin el promedio, mnimo y mximo de stas. Se recibir el nmero de alumnos y las notas parciales de cada uno de stos. Las notas parciales corresponden a la I1, I2, T1, T2 y Exmen. La nota final se calcula empleando la frmula: NF =0.7*NP +0.3*Ex en donde NP es la nota de presentacin calculada como: NP =(I1+I2+T1+T2)/4
1. Definicin del problema Conceptualizacin: El problema consiste en calcular la nota final obtenida por cada uno de los alumnos de un curso, y el promedio, mnimo y mximo de estas notas finales. El clculo de la nota final es una funcin de las notas parciales que obtuvo durante el semestre. Se supone que cada alumno tiene todas y cada una de las notas parciales definidas, que el usuario conoce a priori la cantidad de alumnos del curso y que entregar los datos en forma correcta. Objetivo: El objetivo es obtener la nota final de cada alumno, junto con el promedio, el mximo, y el mnimo de stas. Elementos involucrados: Los elementos involucrados son la cantidad de alumnos, las notas parciales y la nota final de cada alumno, y por ltimo el promedio, el mnimo y el mximo de las notas finales. 2. Conceptualizacin de la solucin 2.1 Entidades: El Curso es la nica entidad relevante, la cual se conceptualiza como la agrupacin de notas correspondientes a los alumnos. 2.2 Clases: La clase Curso, ser la representacin de las notas de un curso cuyo promedio se quiere calcular. Esta clase se compone de los siguientes: Atributos de la Clase Curso notas: una matriz que almacenar todas las notas parciales (en forma de nmero real, con decimales). promedio (PROM): el valor resultante del promedio de notas del curso minimo (MIN): el valor de la mnima de todas las notas del curso maximo (MAX): el valor de la mnima de todas las notas del curso Mtodos de la Clase Curso Curso: (constructor) obtiene los valores de todas las notas parciales ingresadas por el usuario. El algoritmo de este mtodo es: 1. Obtener la cantidad de alumnos: N 2. Iterar para cada uno de los N alumnos 2.1 Iterar para cada nota parcial del alumno 2.1.1 Obtener la nota parcial del alumno 2.2 Calcular la Nota P del Alumno 2.3 Calcular la Nota Final del Alumno y agregarlo a la matriz Calcular: recorre la lista de notas, calculando el mnimo, el mximo y el promedio de estos valores. El algoritmo de este mtodo es: IIC 1102 Pgina: 15 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 0. Se declara una variable local: SUMA 1. Inicialmente la suma de notas, SUMA, es 0, el mximo, MAX, es 1, y el mnimo, MIN, es 7 2. Iterar para cada para cada uno de los N alumnos 2.1 Agregar a SUMA la nota FINAL del alumno 2.2 Si la nota FINAL del alumno es mayor que MAX 2.2.1 MAX es ahora la nota FINAL del alumno 2.3 Si la nota FINAL del alumno es menor que MIN 2.3.1 MIN es ahora la nota FINAL del alumno 3. El promedio, PROM es SUMA dividido por N Mostrar: muestra en pantalla las notas finales y los valores de promedio, mnimo y mximo
2. 3 Instancias: La nica instancia requerida es notas1, de la clase Curso.
3. Especificacin del Algoritmo Algoritmo: 1. Declarar instancia de curso 2. Obtener las notas para el curso 3. Calcular el promedio, mnimo y mximo 4. Mostrar los resultados
Cdigo de la Solucin //////////////////////////////////////////////////////////////// // Programa que lee del usuario una lista de notas parciales correspondientes a los alumnos // de un curso, y calcula la nota final de cada alumno, y el promedio, mnimo y mximo. // Se ilustra el uso de arreglos 2D (matrices) para el almacenamiento de la info. de entrada. ////////////////////////////////////////////////////////////////using System;
class Curso { const float MAX_NOTA = 7.0F; // Las expresiones tipo float requieren una F al final const float MIN_NOTA = 1.0F;
public Curso() { int n; float notap; Console.Write("Ingrese el nmero de alumnos en la seccin: "); n = int.Parse(Console.ReadLine()); notas = new float[n,6]; // 6 notas (5 parciales y 1 final) de n alumnos
for(int i=1; i<=n; i++) { Console.WriteLine("Alumno N {0}", i); for(int j=1; j<=5; j++) { // Slo se asignan 5 notas parciales Console.Write("Ingrese la nota {0}: ", j); notas[i-1,j-1] = float.Parse(Console.ReadLine()); } // Nota P, con las primeras 4 notas notap = (notas[i-1,0]+notas[i-1,1]+notas[i-1,2]+notas[i-1,3]) / 4.0F; // Nota final: 0.7*NotaP + 0.3*Examen (la 5a) IIC 1102 Pgina: 16 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. notas[i-1,5] = 0.7F*notap + 0.3F*notas[i-1,4]; } }
public void Mostrar() { Console.WriteLine("Notas Finales:"); for(int i=0; i<notas.GetLength(0); i++) Console.Write("{0:F1} ",notas[i,5]); Console.WriteLine("Promedio de las {0} notas = {1}", notas.GetLength(0), promedio);
Console.WriteLine("Mnimo de las {0} notas = {1}", notas.GetLength(0), minimo);
Console.WriteLine("Mximo de las {0} notas = {1}", notas.GetLength(0), maximo); } }
class MainApp {
static void Main() { Curso c = new Curso(); c.Calcular(); c.Mostrar(); Console.ReadLine(); } }
Ejemplo de ejecucin:
Ingrese el nmero de alumnos en la seccin: 3 Alumno N 1 Ingrese la nota 1: 4,3 Ingrese la nota 2: 4,4 Ingrese la nota 3: 4,5 Ingrese la nota 4: 5,2 Ingrese la nota 5: 5,6 Alumno N 2 Ingrese la nota 1: 5,4 Ingrese la nota 2: 6,2 Ingrese la nota 3: 5,8 Ingrese la nota 4: 5,5 Ingrese la nota 5: 5,7 Alumno N 3 Ingrese la nota 1: 3,4 Ingrese la nota 2: 6,2 Ingrese la nota 3: 5,6 Ingrese la nota 4: 4,5 Ingrese la nota 5: 6,0 Notas Finales: 4,9 5,7 5,2 Promedio de las 3 notas = 5,288333 Mnimo de las 3 notas = 4,9 Mximo de las 3 notas = 5,7175 IIC 1102 Pgina: 17 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 2.2 ces Cuadradas Se desea realizar la multiplicacin AxB de dos matrices cuadradas A y B, utilizando el algoritmo que se uiente forma: .5 Ejemplo: Multiplicacin de Matri presenta en el siguiente diagrama. Dadas dos matrices A, de dimensin MxP, y B, de dimensin PxN, la matriz multiplicacin C, de dimensin MxN, se calcula de la sig
IIC 1102 Pgina: 18 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 1. Definicin del problema Conceptualizacin: El problema consiste en calcular la multiplicacin de 2 matrices cuadrada igual dimensin. El usuario debe entregar la dimensin y los valores de cada uno de los elem las matrices a multiplicar (nmeros enteros). Objetivo: El objetivo es obtener una matriz resultante de multiplicar las dos matrices entregadas. Elementos involucrados: Los elementos involucrados son la dimensin de las matrice matrices a multiplicar y la matriz con el resultado. 2. Conceptualizacin de la solucin Entidades: la nica entidad relevante es Matriz, que representa precisamente una matriz de NxN Clases: para representar esta nica entidad, la clase Matriz ser la encargada de expone informacin y funcionalidad para distinguir una matriz de otra, as como los mtodos para opera ellas, en particular el mtodo de multiplicacin entre matrices. Atributos: la estructura para manejar los datos de la matriz: datos. Mtodos: - Matriz(n): Constructor. Inicializa la dimensin de la matriz (n). - Cargar():se le preguntan los datos al usuario Obtener la dimensin de la matriz Inicializacin de la estructura datos. Obtener los valores de los elementos de las matrices 1. Iterar la fila i de la matriz por todos sus posibles valores 1.1. Iterar la columna j de la matriz por todos sus posibles valores 1.1.1. Obtener el elemento ( i , j ) de la matriz - Multiplicar(Matriz A, Matriz B): se calcula la multiplicacin de dos matrices A y B 1. Iterar sobre cada fila i de la matriz resultado C 1.1. Iterar sobre cada columna j de la fila i 1.1.1. Obtener el valor del elemento C ( i , j ) del resultado 1.1.1.1. Inicialmente C ( i , j ) es 0 (acumulador) 1.1.1.2. Iterar k desde 1 hasta la dimensin de las matrices Agregar a C ( i , j ) el valor A ( i , k ) * B ( k , j ) - Mostrar(): muestra la matriz en pantalla Instancias: A: Primera de las matrices a multiplicar B: Segunda de las matrices a multiplicar C: Matriz resultado (AxB) s de entos de s, las r la r con 3. Especificacin del Algoritmo Declarar instancia Matriz A y B Cargar A y Cargar B Declarar instancia Matriz C C = A x B Mostrar C en pantalla IIC 1102 Pgina: 19 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 4. V es extremas para la dimensin de las matrices, tal o para comprometer la implementacin en C#(segn la defi Por elem las cas ra presentar problemas.
5. Limitaciones No se incluy uario como elementos de las matrices e es correctos. De no ser as, el comportamiento del program n pasar cualquier cosa). Tambin se supone que la dimensin d mportamiento del programa no est definido.
Cdigo de a ///////////////////////////////////////////////////////////////////////// alidacin cion En primera instancia se debe considerar las situa es el caso en que se defina como cero com nicin de la matriz). otra parte, otros dominios deben incluir distintos valores para la dimensin de las matrices y para los entos dentro de las matrices. Algunos casos interesante de estudiar son aquellos en que alguna de matrices (o ambas) son cero (todos sus elementos) o uno (la diagonal). Tambin debe estudiarse el o en que la dimensin de las matrices es uno, lo cual es correcto pero pod en controles de validez de los nmeros que ingresa el us , d modo que se supone que se ingresarn valor a o est definido (es decir, puede e las matrices es mayor que cero, o el co l Solucin // Programa que hace la multiplicacin AxB de dos matrices cuadradas A y B. // El programa pide al usuario que ingrese la dimensin de las matrices, es // decir, la longitud de los lados, as como los valores para las entradas de // ambas at m rices (A y B), calcula la multiplicacin empleando un ciclo for // con a da ni miento de tres niveles, y finalmente despliega el resultado de // la multiplicacin A*B, el cual se almaceno en una tercera matriz: C. /////////////////////////////////////////////////////////////////////////
using System;
class Matriz { int[,] datos;
public Matriz(int n) { datos = new int[n,n]; // Se crea la matriz del tamao indicado }
l pub ic void Cargar() { int i,j; Console.WriteLine("\nIngrese los Valores para la matriz:"); for (i=0; i<datos.GetLength(0); i++) { Console.WriteLine("Fila :", i); {0} 1); j++) { for (j=0; j<datos.GetLength( Console.Write("\tCelda {0}: ", j); datos[i,j] = int.Parse(Console.ReadLine()); } } }
int Tamano() { return(datos.GetLength(0)); }
car(Matriz A, Matriz B) { public static Matriz Multipli A.Tamano()); Matriz m = new Matriz(
ciclo con anidamiento de 3 nivel realiza la multiplicacin // El siguiente for (int i=0; i<m.Tamano(); i++) { for (int j=0; j<m.Tamano(); j++) { m.datos[i,j] = 0; for (int k=0; k<m.Tamano(); k++) m.datos[i,j] += (A.datos[i,k] * B.datos[k,j]); } } return(m); } IIC 1102 Pgina: 20 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U.
// Mostrar(): muestra en pantalla (consola) la matriz. public void Mostrar() {
Console.WriteLine("\n"); // Se imprime por filas completas hacia el lado for (int i=0; i<datos.GetLength(0); i++) { Console.Write("| "); // Se imprime un separador for (int j=0; j<datos.GetLength(1); j++) Console.Write("{0} ",datos[i,j]); Console.WriteLine("|"); // Se imprime un separador } // Al final de recorrer la fila, se cambia de lnea Console.WriteLine(); } }
class MainApp { static void Main() { int N; // Dimension real de las matrices, dada por el usuario Console.WriteLine("Multiplicacin de A(NxN) X B(NxN)"); Console.Write("Ingrese el valor de N (de 1 a 10): "); N = int.Parse(Console.ReadLine());
Matriz A = new Matriz(N); // Se declaran e inicializan las dos matrices A y B Matriz B = new Matriz(N); A.Cargar(); B.Cargar();
Matriz C = Matriz.Multiplicar(A,B); C.Mostrar();
Console.Write("Presione ENTER para terminar..."); Console.ReadLine(); } }
Ejemplo de ejecucin: Multiplicacin de A(NxN) X B(NxN) Ingrese el valor de N (de 1 a 10): 3
Ingrese los Valores para la matriz: Fila 0: Celda 0: 1 a Celd 1: 2 Celda 2: 3 Fila 1: Celda 0: 4 Celda 1: 5 Celda 2: 6 F : ila 2 Celda 0: 7 Celda 1: 8 Celda 2: 9
Ingrese los Valores para la matriz: Fila 0: Celda 0: 9 Celda 1: 8 Celda 2: 7 Fila 1: Celda 0: 6 Celda 1: 5 Celda 2: 4 IIC 1102 Pgina: 21 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. Fila 2: Celda 0: 3 Celda 1: 2 Celda 2: 1
| 30 24 18 | | 84 69 54 | | 138 114 90 |
IIC 1102 Pgina: 22 Intro. Prog. Orientada a Objeto Arreglos y Enumeraciones Rodrigo Sandoval U. 3 Enumeraciones simplificada de arreglos, que se declaran con datos incluidos. Estos se utilizan encialmente para listar opciones fijas para un programa. Por definicin, todos los elementos de las raciones son de tipo entero. En otras palabras, al declarar una enumeracin, se est definiendo un conjunto de valores aceptados, dndole nombres ms entendibles, y como consecuencia, el compilador dar aviso cuando se intente usar un valor no definido. La sintaxis para la declaracin de una enumeracin es la siguiente: enum <identificador> { <nombre1> = <valorEntero1>, <nombre2> = <valorEntero2>, ... <nombreN> = <valorEnteroN> }
Por ejemplo, una til enumeracin se puede definir al utilizar una clase con un atributo que slo puede tomar los valores Femenino o Masculino. Ejemplo: public enum Sexo { Existe una versin es enume Femenino = 1, Masculino = 2 }
class Persona { string nombre; int edad; Sexo sexo;
Public void Mostrar() { Console.WriteLine(Nombre: {0}, nombre); Console.WriteLine(Edad: {0}, edad); if ( sexo == Sexo.Masculino ) Console.WriteLine(Sexo: Masculino); else Console.WriteLine(Sexo: Femenino); } }
Entre los beneficios de utilizar enumeraciones se cuentan: - Se hace ms fcil de mantener el cdigo, al permitir asegurar que las variables slo reciben valores dentro de un rango definido, sin posibilidad de valores invlidos. - Las enumeraciones hacen al cdigo ms legible y entendible, permitiendo referenciar valores enteros con nombres ms descriptivos, en lugar de nmeros oscuros y mgicos. IIC 1102 Pgina: 23 Material preparado por Rodrigo Sandoval U en Abril 2004
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo VIII Strings en C#
1 CADENAS DE TEXTO..............................................................................................................................................1 1.1 LA CLASE SYSTEM.STRING....................................................................................................................................1 1.1.1 Declaracin de un string...............................................................................................................................1 1.1.2 Operadores bsicos sobre un string..............................................................................................................1 1.1.3 Revisando los caracteres individuales de un string ......................................................................................2 1.1.4 Mtodos de la clase String ............................................................................................................................2 1.1.5 Ejemplo: Validacin de formato de un e-mail ..............................................................................................3 1.1.6 Ejemplo: Manejo de un Diccionario, incluyendo la bsqueda de palabras..................................................4 1.1.7 Ejemplo: Bsqueda y Reemplazo de Texto....................................................................................................7 1.2 TRANSFORMACIN DE OTROS TIPOS A STRING ......................................................................................................9 1.2.1 Transformacin con Formato .......................................................................................................................9
Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Cadenas de Texto Los strings esencialmente son cadenas de texto, compuestas por uno o ms caracteres. Si bien no se incluyen dentro de los tipos bsicos de C#, como son el int, el double, el char, efectivamente se reconoci su enorme importancia al haberse incluido una clase String y su alias string en la base del lenguaje C#. Internamente, un string, al ser una lista de caracteres, se puede equiparar con un arreglo de char, sin embargo, dada su propia necesidad funcional, se han agregado diversos atributos y mtodos a la clase String, para simplificar y potenciar su utilizacin, hasta cierto punto ocultando su real implementacin de arreglo interna. 1.1 La clase System.String La clase System.String, o simplemente String (cuando se incluy using System; en la primera lnea del programa) es una clase especialmente diseada para almacenar cadenas de texto, en forma de una secuencia de caracteres. Dada su importancia, una palabra reservada de C#corresponde a un alias para esta clase, al igual que en el caso de in (Int), y otros. Esta palabra clave es simplemente string. 1.1.1 Declaracin de un string string <identificador>;
string <identificador> = valor inicial;
Algunos ejemplos: string nombre; nombre = Juan Prez;
string nombre = Juan Prez; 1.1.2 Operadores bsicos sobre un string Adicionalmente, algunos de los operadores ms recurridos dentro de las expresiones del lenguaje C# tambin son vlidos para trabajar con strings, tal es el caso de la asignacin (=), la igualdad (==), y la suma (+). Ejemplos: string nombre; nombre = Juan;
nombre = nombre + Prez;
Console.WriteLine(nombre);
if( nombre == Juan Prez) Console.WriteLine(Es igual);
Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 2 1.1.3 Revisando los caracteres individuales de un string Considerando que los strings siguen siendo arreglos, es an factible utilizar la misma sintaxis para revisar los caracteres (elementos) segn su indexacin. Esto se hace mediante la declaracin: <identificador>[indice] Ejemplo: string nombre; nombre = Juan;
1.1.4 Mtodos de la clase String Siendo String una clase derivada de Array, los mismos atributos y mtodos de sta (descritos en el captulo anterior), son totalmente vlidos. Tal es el caso de Length (atributo), por ejemplo. Especficamente, los mtodos principales de la clase String son los siguientes: EndsWith Determina si el final de la instancia de String coincide con un substring dado. Equals Determina si dos strings dados tienen el mismo valor. Format Formatea un string conteniendo varios valores y especificadores acerca de cmo cada valor debe ser formateado. IndexOf Ubica la primera ocurrencia de un substring dado, en el string. IndexOfAny Ubica la primera ocurrencia de cualquier carcter de un substring dado, en el string. Insert Inserta un substring en una posicin especfico dentro del string. LastIndexOf Igual que IndexOf, pero comenzando desde el final del string. LastIndexOfAny Igual que IndexOfAny, pero comenzando desde el final del string. Replace Reemplaza todos los caracter4es de un substring indicado, por otro tambin indicado. Split Identifica los substrings en la instancia y los ordena por separado en un arreglo de strings. StartsWith Como EndsWith, pero revisando el comienzo del string. Substring Entrega un substring de la instancia, comenzando en un ndice dado. ToLower Convierte el string as minsculas. ToUpper Convierte el string a maysculas. Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 3 Trim Elimina todos los espacios al comienzo y al final del string. TrimEnd Elimina todos los espacios al final del string. TrimStart Elimina todos los espacios al comienzo del string. 1.1.5 Ejemplo: Validacin de formato de un e-mail ///////////////////////////////////////////////////////////////////////////////// // Validacin de direcciones e-mail. Las reglas de validacin son: // - Que todos los caracteres sean vlidos. // Slo letras, dgitos y los smbolos: _ - @ y el punto // - Que tengan un nico smbolo @, ni ms ni menos // - Que tengan al menos un punto a la derecha del @, pero pueden ser ms de uno // - Que el lado izquierdo sea ms largo que 0. // - Por ende, el largo mnimo de un e-mail es 6: x@x.xx // // En este ejemplo se ilustra el uso de los siguientes mtodos de la clase String: // IndexOf(), LastIndexOf(), Substring(), ToLower(), Trim() /////////////////////////////////////////////////////////////////////////////////
using System;
class Email {
public static bool Validar(string email) { // string que contiene caracteres vlidos dentro de un e-mail string caracteresvalidos = "abcdefghijklmnopqrstuvwxyz1234567890_-.@";
if(email.Length<6) return (false);
// Se valida sobre e-mail en minsculas y sin espacios antes y despus email = email.ToLower().Trim();
// Verifica todos los caracteres for (int i=0; i<email.Length; i++) // Es un caracter no-vlido? if( caracteresvalidos.IndexOf(email[i]) < 0 ) return(false);
// Cantidad de @ if( email.IndexOf('@') < 0 ) return (false); // No haba @ if( email.IndexOf('@') != email.LastIndexOf('@') ) return (false); // Hay ms de 1 @
// Cantidad de . a la derecha de @. // Se busca un . slo en el substring a la derecha del @ if( email.Substring(email.IndexOf('@'), email.Length-email.IndexOf('@')-1).IndexOf('.') < 0) return(false);
// Que el @ no sea el primer smbolo if( email.IndexOf('@') == 0 ) return (false);
return (true); } }
Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 4 class MainApp { static void Main() { string email;
do { Console.Write("Ingrese su e-mail: "); email = Console.ReadLine(); } while( !Email.Validar(email) );
Console.Write("Gracias. Presione ENTER para terminar ..."); Console.ReadLine(); } }
1.1.6 Ejemplo: Manejo de un Diccionario, incluyendo la bsqueda de palabras
///////////////////////////////////////////////////////////////////////////////// // Ejemplo de manejo de un diccionario de palabras // =============================================== // Este ejemplo declara una clase Diccionario que maneja una lista de palabras // (en este caso, nombres de animales). Luego, permitindole al usuario ingresar // nombres o subpalabras a buscar, se filtran y se revisan las palabras del // diccionario que comienzan con la palabra indicada, o terminan, o la contienen. // // En este ejemplo se ilustra el uso de los siguientes mtodos de la clase String: // IndexOf(), StartsWith(), EndsWith(), Trim(), ToUpper(), /////////////////////////////////////////////////////////////////////////////////
// BuscarInicio(palabra): Busca la palabra dada en todos los strings del diccionario // viendo en cules de ellos se encuentra al comienzo // Retorna: un arreglo de strings con las palabras del diccionario que coincidieron public string[] BuscarInicio(string palabra) { string[] resultado; int cantidad = 0; int[] posiciones = new int[diccionario.Length]; // Registrar posiciones que empiezan con el string indicado (palabra) for(int i=0; i<diccionario.Length; i++) if( diccionario[i].StartsWith(palabra) ) { posiciones[cantidad] = i; cantidad++; }
// Se copian los strings correspondientes resultado = new string[cantidad]; for(int i=0; i<cantidad; i++) resultado[i] = diccionario[posiciones[i]];
return(resultado); }
// BuscarFinal(palabra): Busca la palabra dada en todos los strings del diccionario // viendo en cules de ellos se encuentra al final // Retorna: un arreglo de strings con las palabras del diccionario que coincidieron public string[] BuscarFinal(string palabra) { string[] resultado; int cantidad = 0; int[] posiciones = new int[diccionario.Length]; // Registrar posiciones que terminan con el string indicado (palabra) for(int i=0; i<diccionario.Length; i++) if( diccionario[i].EndsWith(palabra) ) { posiciones[cantidad] = i; cantidad++; }
// Se copian los strings correspondientes resultado = new string[cantidad]; for(int i=0; i<cantidad; i++) resultado[i] = diccionario[posiciones[i]];
return(resultado); }
// BuscarInicio(palabra): Busca la palabra dada en todos los strings del diccionario // viendo en cules de ellos se encuentra en cualquier parte // Retorna: un arreglo de strings con las palabras del diccionario que coincidieron public string[] Buscar(string palabra) { string[] resultado; int cantidad = 0; int[] posiciones = new int[diccionario.Length]; // Registrar las posiciones que contienen el string indicado (palabra) for(int i=0; i<diccionario.Length; i++) if( diccionario[i].IndexOf(palabra)>=0 ) { posiciones[cantidad] = i; cantidad++; }
// Se copian los strings correspondientes resultado = new string[cantidad]; for(int i=0; i<cantidad; i++) Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 6 resultado[i] = diccionario[posiciones[i]];
return(resultado); } }
class MainApp { static void Main() { Diccionario d = new Diccionario(); string palabra; string[] resultado;
Console.Write("Indique la palabra a buscar: "); palabra = Console.ReadLine(); // El string ingresado por el usuario debe ser filtrado: // Primero, eliminar todos los espacios blancos, al comienzo y al final palabra = palabra.Trim(); Console.WriteLine("Buscando: \"{0}\"", palabra); // Segundo, la palabra debe venir en maysculas palabra = palabra.ToUpper(); Console.WriteLine("Buscando: \"{0}\"", palabra);
// Primero, los strings que comienzan con la palabra Console.WriteLine("Los sig. strings comienzan con \"{0}\":",palabra); resultado = d.BuscarInicio(palabra); foreach(string s in resultado) Console.WriteLine(s);
// Segundo, los strings que terminan con la palabra Console.WriteLine("Los sig. strings terminan con \"{0}\":",palabra); resultado = d.BuscarFinal(palabra); foreach(string s in resultado) Console.WriteLine(s);
// Tercero, los strings que contienen la palabra Console.WriteLine("Los siguientes strings contienen \"{0}\":",palabra); resultado = d.Buscar(palabra); foreach(string s in resultado) Console.WriteLine(s);
Console.ReadLine(); } }
Ejemplos de Ejecucin Indique la palabra a buscar: oso Buscando: "oso" Buscando: "OSO" Los siguientes strings comienzan con "OSO": OSO OSO HORMIGUERO Los siguientes strings terminan con "OSO": OSO PEREZOSO Los siguientes strings contienen "OSO": OSO OSO HORMIGUERO PEREZOSO Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 7
Indique la palabra a buscar: mo Buscando: "mo" Buscando: "MO" Los siguientes strings comienzan con "MO": MONO MORSA Los siguientes strings terminan con "MO": HIPOPOTAMO Los siguientes strings contienen "MO": CORMORAN HIPOPOTAMO MONO MORSA SALTAMONTES
1.1.7 Ejemplo: Bsqueda y Reemplazo de Texto
///////////////////////////////////////////////////////////////////////////////// // Implementacin de Find-Replace de los Editores de Texto // ======================================================= // Entre las funcionalidades que ofrecen los editores de texto hoy en da se encuentra // la bsqueda y reemplazo de una palabra por otra, todas las veces que sta aparezca // en el texto. // El siguiente programa implementa la bsqueda y reemplazo utilizando las funciones // y conceptos de string, con las siguientes condiciones: // * El contenido del texto se almacena en la clase Texto // * Se incluye el mtodo BuscarReemplazar(str1,str2) // donde el primer parmetro (str1) es el string a buscar y el segundo (str2) // es el string por el cual reemplazar el string encontrado. // * En la bsqueda se consideran idnticas las maysculas de las minsculas, es decir, // "CASA" es totalmente equivalente a "Casa". // * La bsqueda no considera palabras acotadas, es decir, al buscar "el", // se considera que se encontr en "el", "ellos", "aquel". // * Al encontrar la palabra buscada, se reemplaza el texto de ella por el texto indicado. // Si el texto encontrado es parte de otra palabra, slo se reemplaza la porcin corresp. // al texto encontrado. Es decir, si se busca "casa" y se reemplaza por "hogar", // entonces la frase // "El casamiento fue en la tarde", quedar como "El hogarmiento fue en la tarde". // * Se considera ajustar el texto restante: si la palabra buscada tiene distinto // largo que su reemplazo. // // En este ejemplo se ilustra el uso de los siguientes mtodos de la clase String: // IndexOf(), Substring(), ToLower(), Insert(), Remove() /////////////////////////////////////////////////////////////////////////////////
using System;
class Reemplazo { public string texto = "En la casa del explorador, se encuentra todo tipo de cosas, " + "incluyendo fotografas de recuerdo. " + "Estos objetos son parte de la historia de este explorador, " + "a travs de los aos y kilmetros que ha recorrido";
public void BuscarReemplazar(string str1, string str2) { int posicion = 0; // Se comienza desde el primer caracter (-1+1 = 0) int indice = 0; string copiatexto;
Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 8 do { // Se busca la sig. posicin en que str1 est en el texto indice = texto.Substring(posicion,texto.Length-posicion).IndexOf(str1);
// Si la posicin es vlida, se procesa el reemplazo if ( indice >= 0 ) { // Se eliminan los caracteres del str1 // de la posicin encontrada (pero en la original) texto = texto.Remove(posicion+indice,str1.Length); // Se inserta el nuevo string (str2) en la misma posicin texto = texto.Insert(posicion+indice,str2); posicion += indice; } } while(indice>=0); }
public void BuscarReemplazarDirecto(string str1, string str2) { str1 = str1.ToLower(); // El texto a buscar tambin se deja en minsculas.
texto = texto.Replace(str1,str2); }
}
class MainApp { static void Main() { Reemplazo r = new Reemplazo(); string str1; string str2;
Console.WriteLine("** Bsqueda-Reemplazo de texto **"); Console.WriteLine("\nTexto: \"{0}\"\n", r.texto); Console.Write("Texto a buscar: "); str1 = Console.ReadLine().Trim(); Console.Write("Texto de reemplazo: "); str2 = Console.ReadLine().Trim();
// Se efecta el reemplazo y se muestra el resultado r.BuscarReemplazar(str1,str2); Console.WriteLine("\nTexto modificado: \"{0}\"\n", r.texto);
Console.ReadLine(); } }
Ejemplos de Ejecucin ** Bsqueda-Reemplazo de texto **
Texto: "En la casa del explorador, se encuentra todo tipo de cosas, incluyendo fotografas de recuerdo. Estos objetos son parte de la historia de este explorador, a travs de los aos y kilmetros que ha recorrido"
Texto a buscar: la Texto de reemplazo: lo
Texto modificado: "En lo casa del explorador, se encuentra todo tipo de cosas, incluyendo fotografas de recuerdo. Estos objetos son parte de lo historia de este explorador, a travs de los aos y kilmetros que ha recorrido"
Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 9 1.2 Transformacin de otros Tipos a String Es comn requerir que datos, que se almacenan en otro tipo de dato de origen, como podra ser un int, char, float, double, quieran ser transformados a string. Las clases en C#, proveen naturalmente el mtodo ToString(), que efectivamente transforma el dato correspondiente a un string, incluyendo funcionalidad de formato. Ejemplo: // Transformacin bsica int numero = 10; string num = El nmero es + numero.ToString();
1.2.1 Transformacin con Formato Al igual que al imprimir texto en pantalla (por medio de Console.Write() y WriteLine()), es posible transformar tipos bsicos a strings, con un formato numrico predefinido. Para ello, el mtodo ToString() en los tipos numricos bsicos (int, float, double, etc.), permite agregar como parmetro la cadena que indica el formato. El parmetro es de la forma: {formato} Formato puede ser uno de los siguientes: C o c, para formato monetario (tomado de la configuracin de Windows) D o d, para nmeros enteros (decimales). E o e, para nmeros en formato de exponente (ej: 1.234E+005) F o f, para nmeros reales, con parte decimal G o g, para formato general. N o n, similar a F, pero con la separacin de miles. P o p, porcentaje. R o r, round-trip o viaje redondo, que se usa en nmeros reales. Garantiza que un valor numrico convertido a string ser re-transformado de vuelta sin perder informacin. X o x, nmero en formato hexadecimal (ej: 1A24C)
Ejemplo: //////////////////////////////////////////////////////////////////////////////// // Transformacin de tipos bsicos a strings con formato. Uso de ToString() /////////////////////////////////////////////////////////////////////////////////
using System;
class ValoresNumericos {
static void Main() { int[] valores = new int[4];
Console.WriteLine("Proceso de cantidades monetarias");
for(int i=0; i<valores.Length; i++) { Intro. Prog. Orientada a Objeto Strings en C# Rodrigo Sandoval U. IIC 1102 Pgina: 10 Console.Write("Ingrese el monto {0}: ",i+1); valores[i] = int.Parse(Console.ReadLine()); }
// Ntese que el formato moneda viene de la configuracin de Windows Console.WriteLine("Los montos son: "); foreach(int n in valores) Console.Write("{0}, ", n.ToString("C")); // C: currency (moneda)
int contador=0; foreach(int n in valores) // Cuenta montos sobre $100 if(n>100) contador++;
Console.WriteLine("De ellos, el {0} es mayor que {1:C}", ((float)contador/ valores.Length).ToString("P"),100);
Console.Write("Presione ENTER para terminar ..."); Console.ReadLine(); } }
Ejemplos de Ejecucin Proceso de cantidades monetarias Ingrese el monto 1: 150 Ingrese el monto 2: 1200 Ingrese el monto 3: 23 Ingrese el monto 4: 33 Los montos son: $ 150, $ 1.200, $ 23, $ 33, De ellos, el 50,00 % es mayor que $ 100 Presione ENTER para terminar ...
Material preparado por Rodrigo Sandoval U en Mayo 2004
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo IX Archivos en C# y Bases de Datos
1 LECTURA Y ESCRITURA DE ARCHIVOS DE TEXTO.....................................................................................1 1.1 STREAMS ...............................................................................................................................................................1 1.1.1 Lectura de Archivos ......................................................................................................................................1 1.2 USING SYSTEM.IO.................................................................................................................................................2 1.3 CONTROL DE ERRORES ..........................................................................................................................................2 1.4 LECTURA: STREAMREADER...................................................................................................................................2 1.4.1 Constructores de StreamReader....................................................................................................................2 1.4.2 Lectura con StreamReader............................................................................................................................3 1.4.3 Ejemplo: Lectura de un Archivo de Texto, mostrando contenido en pantalla ..............................................3 1.4.4 Ejemplo: Procesamiento de Operaciones Matemticas en Archivo .............................................................4 1.5 ESCRITURA: STREAMWRITER................................................................................................................................6 1.5.1 Constructores de StreamWriter.....................................................................................................................6 1.5.2 Escritura con StreamWriter ..........................................................................................................................6 1.5.3 Ejemplo: Lectura y Escritura de un Archivo.................................................................................................7 2 BASES DE DATOS...................................................................................................................................................10 2.1 CONCEPTOS BSICOS DE BASES DE DATOS .........................................................................................................10 2.1.1 Base de Datos..............................................................................................................................................10 2.1.2 Sistema de Administracin de Base de Datos .............................................................................................10 2.1.3 Elementos relacionados a una Base de Datos.............................................................................................10 2.1.4 EJEMPLO.....................................................................................................................................................0 2.2 MODELOS DE BASES DE DATOS...........................................................................................................................12 2.2.1 Esquema de Archivos ..................................................................................................................................12 2.2.2 Modelo Jerrquico......................................................................................................................................12 2.2.3 Modelo Relacional ......................................................................................................................................13 2.2.4 Modelo Distribuido .....................................................................................................................................15 2.2.5 Modelo de BD Orientado a Objeto .............................................................................................................15 2.2.6 BD Multidimensional ..................................................................................................................................15 2.3 PROGRAMACIN DE BASES DE DATOS CON C#....................................................................................................16 2.3.1 Ejemplo: Programa de Registro de Alumnos..............................................................................................16
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Lectura y Escritura de Archivos de Texto En todos los programas, la manera de almacenar y recuperar informacin que perdure en el tiempo se basa en el uso de memoria secundaria, compuesta esencialmente por discos (diskettes, discos duros, CD, DVD, etc.) y ocasionalmente cintas. En cualquiera de estos medios, la unidad de almacenamiento de informacin se denomina archivo. Al igual que prcticamente todos los lenguajes de programacin, C#ofrece el acceso a leer y escribir archivos en disco, por medio de estructuras especialmente definidas. En el caso de este lenguaje Orientado a Objeto, las estructuras consisten en clases de caractersticas y mtodos particulares, que resuelven la problemtica general de acceso a los archivos, permitiendo desarrollar programas que los utilicen como fuente de informacin y medio de almacenamiento de informacin de largo plazo. 1.1 Streams Un stream es como se denomina a un objeto utilizado para transferir datos. Estos datos pueden ser transferidos en dos posibles direcciones: - Si los datos son transferidos desde una fuente externa al programa, entonces se habla de leer desde el stream. - Si los datos son transferidos desde el programa a alguna fuente externa, entonces se habla de escribir al stream. Frecuentemente, la fuente externa ser un archivo, pero eso no necesariamente es el caso, por lo que el concepto es utilizado ampliamente con fuentes de informacin externas de diversos tipos. Algunas otras posibilidades fuera de los archivos incluyen: - Leer o escribir datos a una red utilizando algn protocolo de red, donde la intencin es que estos datos sean recibidos o enviados por otro computador. - Lectura o escritura a un rea de memoria. - La Consola - La Impresora - Otros ... Algunas clases que C#provee para resolver este acceso a fuentes diversas incluyen las clases de tipo Reader y Writer. 1.1.1 Lectura de Archivos Las clases ms relacionadas con la escritura y lectura de archivos (File Input/Output o File I/O) son: - FileStream, cuyo propsito es lectura y escritura de datos binarios (no de texto legible), a cualquier archivo de tipo binario, aunque se puede utilizar para acceder a cualquier tipo de archivo, inclusive los de texto. - StreamReader y StreamWriter, las cuales estn diseadas para lectura y escritura de archivos de texto. Estas clases se asumen como de un nivel ms alto que FileStream.
Una observacin acerca de la declaracin de nombres/rutas de archivos en C#. Usualmente, la ruta de un archivo contiene el carcter \, que en C#se utiliza como caracter de control para smbolos especiales (como el cambio de lnea: \n). Sin embargo, entendiendo que no es el mismo sentido el que se le quiere dar en la interpretacin de rutas de archivos (por ej: C:\Mis documentos\Programas\ejemplo.cs), se utiliza una sintaxis particular, anteponiendo el smbolo @ antes del string con la ruta del archivo. Es decir: string rutaarchivo = @C:\Temp\archivo.txt; intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 2 Esta declaracin evita la interpretacin de los dos caracteres \ como smbolos especiales y el string queda correctamente inicializado. 1.2 Using System.IO Para el uso de estas clases, es necesario referenciar el uso del namespace System.IO, ya que System no contiene los elementos para el manejo de archivos. Por ello, los programas con acceso a archivos deben incluir la lnea: using System.IO; 1.3 Control de Errores Si bien en una serie de instrucciones de ejecucin en lenguaje C#se pueden producir errores importantes, particularmente cuando hay input del usuario que debera tener cierta forma o valores, o en clculos matemticos (especficamente evitando divisiones por cero), es factible en C#tener cierto control sobre el comportamiento del programa ante dichas situaciones. Esencialmente, el bloque try-catch persigue precisamente tener cierto control sobre lo que el programa har en caso de producirse un error. public int division(int n1, int n2) { int resultado = 0; try { resultado = n1/n2; } catch(Exception e) { Console.WriteLine("Error en la divisin de {0}/{1}\n\n{2}",n1, n2, e.ToString()); } }
1.4 Lectura: StreamReader La ventaja de esta clase es que hace una operacin sobre archivos que resulta muy natural al momento de utilizarla. 1.4.1 Constructores de StreamReader El ms simple de los constructores toma slo el nombre/ruta del archivo a abrir para lectura: StreamReader sr = new StreamReader(@C:\Temp\archivo.txt); Sin embargo, reconociendo que hoy existen diferentes formatos (codificaciones) de archivos de texto y no solamente el tradicional formato ASCII, es factible establecer cul es la codificacin especial que este archivo de texto plano puede tener. Los formatos posibles son: ASCII, Unicode, UTF7, UTF8, BigEndianUnicode. El constructor ad-hoc es: StreamReader sr = new StreamReader(@C:\Temp\file.txt, Encoding.UTF8Encoding); En trminos prcticos, nos ser necesario recurrir a este tipo de codificaciones, ya que usualmente se trabajar con codificacin ASCII. El constructor deja abierto el stream para poder recuperar la informacin del archivo desde la instancia de StreamReader declarada. Para cerrar un stream o archivo, se invoca el mtodo Close(): sr.Close();
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 3 1.4.2 Lectura con StreamReader Son bsicamente tres los mtodos propios de StreamReader que permiten efectuar lectura desde el stream (archivo) declarado. 1.4.2.1 ReadLine() Al igual que el conocido Console.ReadLine(), este mtodo lee una lnea completa de un archivo de texto hasta el cambio de lnea ms prximo. Al igual que su equivalente de consola, StreamReader.ReadLine() no incluye en el string el carcter de cambio de lnea. string linea = sr.ReadLine() 1.4.2.2 ReadToEnd() Este mtodo, por su parte, se encarga de acumular la informacin que hay desde la lectura anterior (que pudo haberse hecho con ReadLine(), por ejemplo) hasta el final del archivo, todo en el mismo string. string linea = sr.ReadToEnd() 1.4.2.3 Read () Finalmente, el mtodo simple Read() se encarga de leer un caracter a la vez, lo que permite procesar smbolo por smbolo el contenido del archivo. Convenientemente, este mtodo reconoce el cambio de lnea y se lo salta como si no existiese. Cuando se encuentra con el fin de archivo, retorna un valor 1, considerando que su retorno es siempre un int (y no un char). int SigCaracter = sr.Read(); Este mismo mtodo ofrece una declaracin alternativa (sobrecarga), donde es posible leer una cantidad especfica de caracteres y almacenarlos en un arreglo de enteros. char[] CharArray = new char[100]; int[] nChars = sr.Read(CharArray, 0, 100); nChars es un arreglo con los enteros retornados por el mtodo, y ser menor si es que la cantidad de caracteres que quedan en el archivo es menor de 100. 1.4.3 Ejemplo: Lectura de un Archivo de Texto, mostrando contenido en pantalla ///////////////////////////////////////////////////////////////////////////////// // Ejemplo de Lectura de Archivos /////////////////////////////////////////////////////////////////////////////////
using System; using System.IO;
class Archivo { StreamReader sr; bool abierto = false;
// Constructor: Recibe el nombre del archivo y lo abre (con control errores) public Archivo(string filename) { try { sr = new StreamReader(filename); abierto = true; } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", filename, e.ToString()); } intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 4 }
public void Mostrar() { string linea;
if(!abierto) return; // Si no se pudo abrir, no hay nada que leer
linea = sr.ReadLine(); while(linea != null) { // Lee lneas mientras haya (mientras sean !=null) Console.WriteLine(linea); linea = sr.ReadLine(); } sr.Close(); abierto = false; }
}
class MainApp {
static void Main() { string nombre;
Console.Write("Nombre del archivo: "); nombre = Console.ReadLine();
Archivo archivo = new Archivo(nombre); archivo.Mostrar();
Console.ReadLine(); } } 1.4.4 Ejemplo: Procesamiento de Operaciones Matemticas en Archivo ///////////////////////////////////////////////////////////////////////////////// // Ejemplo de Lectura de Archivos: Calculadora de Archivo // ====================================================== // Este ejemplo muestra cmo se procesa el contenido de un archivo, que indica // operaciones matemticas bsicas: * / + - /////////////////////////////////////////////////////////////////////////////////
using System; using System.IO;
class Calculadora { StreamReader sr; bool abierto = false;
// Constructor: Recibe el nombre del archivo y lo intenta abrir. // Si no puede abrirse para lectura, "abierto" queda como false public Calculadora(string filename) { try { sr = new StreamReader(filename); abierto = true; } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", filename,e.ToString()); } }
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 5 // Operacion: Recibe la operacin y dos nmeros en forma de string. // Retorna el resultado (int) de la operacin entre ambos nmeros. int Operacion(string op, string n1, string n2) { switch(op) { case "+": return( int.Parse(n1) + int.Parse(n2)); case "-": return( int.Parse(n1) - int.Parse(n2)); case "*": return( int.Parse(n1) * int.Parse(n2)); case "/": return( int.Parse(n1) / int.Parse(n2)); } return(0); }
// Procesar: lee lneas del archivo abierto, procesando el contenido en forma de operaciones. // Observaciones: al finalizar se cierra el stream. No se valida el formato de c/lnea. public void Procesar() { string linea; string[] elementos;
if(!abierto) return; // Si no se pudo abrir, no hay nada que leer
linea = sr.ReadLine(); while(linea != null) { // Para poder usar Split(), las operaciones y los operandos deben // venir separados por espacios. elementos = linea.Split(); Console.WriteLine("{0} = {1}", linea, Operacion(elementos[1], elementos[0], elementos[2])); linea = sr.ReadLine(); } sr.Close(); abierto = false; } }
class MainApp {
static void Main() { string nombre;
Console.Write("Nombre del archivo: "); nombre = Console.ReadLine(); Calculadora c = new Calculadora(nombre); c.Procesar(); Console.ReadLine(); } } Ejemplo de Ejecucin: Tomando el siguiente archivo de operaciones calculos.txt: 4 + 4 5 * 6 8 - 2 6 / 3 Resulta el siguiente output: Nombre del archivo: calculos.txt 4 + 4 = 8 5 * 6 = 30 8 - 2 = 6 6 / 3 = 2
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 6 1.5 Escritura: StreamWriter Esta clase funciona prcticamente de la misma manera que StreamReader, excepto que su propsito es nicamente para escribir dentro de un archivo (u otro stream). Es relevante distinguir que en este caso, el proceso de apertura para escritura considera que: - Si el archivo no existe lo crea vaco para comenzar a escribir. - Si el archivo ya existe, lo deja vaco para comenzar a escribir. - Si el archivo ya existe, es posible abrirlo en forma Append (agregar) para escribir al final. 1.5.1 Constructores de StreamWriter El ms simple de los constructores toma slo el nombre/ruta del archivo a abrir para escritura. StreamWriter sw = new StreamWriter (@C:\Temp\archivo.txt); Este constructor asume por defecto el formato UTF8 de archivos planos, ya que es el manejado por .NET. Sin embargo, existe el constructor equivalente que permite abrir un archivo especificando otra codificacin de archivo plano, por ejemplo ASCII. StreamWriter sw = new StreamWriter (@C:\doc\file.txt, Encoding.ASCII); Un tercer constructor utiliza como segundo parmetro un boolean que indica si el archivo debe ser abierto para Agregar, es decir, en un modo Append. StreamWriter sw = new StreamWriter (@C:\Temp\archivo.txt, true); De la misma manera que en el caso de la lectura, para cerrar un stream o archivo, se invoca el mtodo Close: sw.Close();
1.5.2 Escritura con StreamWriter Son bsicamente dos los mtodos propios de StreamWriter que permiten escribir hacia el stream (archivo) declarado y son los mismos que se usan para escribir en la consola: Write() y WriteLine(). 1.5.2.1 WriteLine() Totalmente equivalente a Console.WriteLine(), se utiliza la misma idea, y el mismo formato, sabiendo que se estar escribiendo el texto no a la consola, sino que al stream abierto con el constructor. string linea = Texto de prueba; sw.WriteLine(linea); sw.WriteLine(Los valores posibles son: {0} y {1}, 3, 5);
1.5.2.2 Write () Tambin presente, el mtodo simple Write(), permite escribir texto en el stream, de la misma forma que su equivalente mtodo de la clase Console. En este caso se reconocen las siguientes alternativas de uso: Imprimir un string string linea = Texto de prueba; sw.Write(linea);
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 7 Imprimir un caracter char caracter = T; sw.Write(caracter); Imprimir un arreglo de caracteres char[] caracteres = new char[100]; for(int i=0; i<100; i++) caracteres[i] = +; sw.Write(caracteres); Imprimir una porcin de un arreglo de caracteres char[] caracteres = new char[100]; for(int i=0; i<100; i++) caracteres[i] = +; sw.Write(caracteres, 25, 50); // Desde posicin 25 se escriben 50 caracteres
1.5.3 Ejemplo: Lectura y Escritura de un Archivo ///////////////////////////////////////////////////////////////////////////////// // Ejemplo de Lectura de Archivos: Calculadora de Archivo // ====================================================== // Este ejemplo muestra cmo se procesa el contenido de un archivo, que indica // operaciones matemticas bsicas: * / + - // Este ejemplo en particular, escribe el resultado en un archivo destino /////////////////////////////////////////////////////////////////////////////////
// Constructor: Recibe el nombre del archivo y lo intenta abrir. // Si no puede abrirse para lectura, "abierto" queda como false // Si lo puede abrir, crea un segundo archivo con un nombre similar. public Calculadora(string filename) { try { sr = new StreamReader(filename); abierto1 = true; } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", filename,e.ToString()); }
if(abierto1) { string nombrearchivo2; // Transforma "nombre.txt" en "nombre.out.txt" nombrearchivo2 = filename.Insert(filename.IndexOf('.'),".out"); try { sw = new StreamWriter(nombrearchivo2); abierto2 = true; } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 8 nombrearchivo2,e.ToString()); } }
}
// Operacion: Recibe la operacin y dos nmeros en forma de string. // Retorna el resultado (int) de la operacin entre ambos nmeros. int Operacion(string op, string n1, string n2) { switch(op) { case "+": return( int.Parse(n1) + int.Parse(n2)); case "-": return( int.Parse(n1) - int.Parse(n2)); case "*": return( int.Parse(n1) * int.Parse(n2)); case "/": return( int.Parse(n1) / int.Parse(n2)); } return(0); }
// Procesar: lee el archivo abierto, lnea por lnea, // procesando el contenido en forma de operaciones y escribiendo // el resultado en un segundo archivo. // Observaciones: Al finalizar se cierran los dos streams. // No se valida el formato de c/lnea. public void Procesar() { string linea, linea2; string[] elementos;
// Si no se pudo abrir, no se podr leer ni escribir if(!abierto1 || !abierto2) return;
Console.WriteLine("Procesando ..."); linea = sr.ReadLine(); while(linea != null) { elementos = linea.Split(); // ahora graba los resultados en el segundo archivo linea2 = linea + " = " + Operacion(elementos[1], elementos[0], elementos[2]).ToString(); sw.WriteLine(linea2); linea = sr.ReadLine(); } sr.Close(); abierto1 = false; sw.Close(); abierto2 = false; Console.WriteLine("Listo"); } }
class MainApp {
static void Main() { string nombre;
Console.Write("Nombre del archivo: "); nombre = Console.ReadLine();
Calculadora c = new Calculadora(nombre); c.Procesar();
Console.ReadLine(); } } Al abrir el archivo calculos.txt, se crea el archivo calculos.out.txt con el siguiente contenido: intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 9 4 + 4 = 8 5 * 6 = 30 8 - 2 = 6 6 / 3 = 2
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 10 2 Bases de Datos Uno de los grandes objetivos de la computacin es la capacidad de procesar datos: muchos datos, en forma rpida, eficiente, y segura (confiable). Esto no era posible con mtodos manuales tradicionales. Hoy en da existen muchas aplicaciones computacionales, pero para este contexto se vuelven muy importantes aquellas que trabajan directamente con la administracin de datos. 2.1 Conceptos Bsicos de Bases de Datos Para la realidad computacional de nuestros das, es necesario definir dos elementos puntuales que existen en todo gran o pequeo sistema que maneje cantidades de datos: la Base de Datos (BD) y el Sistema Administrador de Base de Datos (DBMS). 2.1.1 Base de Datos Se puede definir como Una coleccin estructurada y organizada de datos y de otros objetos que permiten trabajar con esos datos. Si se habla de bolsn de datos, no se incluye un concepto de orden o estructuracin. Una base de datos tiene una estructura claramente definida, sin importar el nivel de complejidad de esta estructura. Tradicionalmente, los datos se manejan en estructuras uniformes, que se pueden comparar con planillas de datos. Es decir, una base de datos contiene varias planillas de datos diversos, que pueden a su vez estar relacionados o no. 2.1.2 Sistema de Administracin de Base de Datos Se puede definir como Un elemento capaz de manejar los datos contenidos en una Base de Datos a travs de operaciones claramente establecidas. Si la Base de Datos contiene los objetos que corresponden a los datos y otras estructuras adicionales, el DBMS (Data Base Manager System) se encarga de accesar esos datos, utilizando operaciones bsicas como: agregar, eliminar, modificar, buscar. Un DBMS es un grupo de programas que se encargan de administrar estas operaciones y todos los elementos que facilitan su ejecucin. 2.1.3 Elementos relacionados a una Base de Datos Al trabajar con los datos de una BD, se deben mantener elementos que apoyan el acceso adecuado a las estructuras de datos. Se distinguen: Planillas de datos: tablas que contienen filas, cada una representa un objeto de un tipo comn para las filas de la tabla, que a su vez se compone de varios atributos o propiedades que se ordenan en las columnas de la planilla. Registro: una fila de una tabla. Representa un objeto de un tipo definido y se compone de atributos. Campos: son precisamente la definicin de estos atributos de la tabla o planilla. Llave Primaria: es una parte de los campos de un registro que permite distinguirlo en forma nica del resto de registros adicionales. Indices: al igual que el ndice de un libro, un ndice de una BD, que se asocia a una sola tabla, referencia la posicin de un registro dentro de una tabla, de acuerdo a un orden predefinido. Vistas: son ngulos de la BD. Al igual que una persona puede ver un auto desde el exterior, lo cual constituye la vista externa del vehculo, existe otra vista interior, y por su parte el objeto vehculo posee muchas propiedades o atributos que no son visibles en algunas vistas.
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 0 2.1.4 EJ EMPLO En una Compra-Venta de autos usados se manejan los datos de los vehculos existentes en el momento. Para poder utilizar informacin adecuada, se entiende que un auto es un objeto de tipo vehculo, y como tal posee ciertas caractersticas determinables: Marca y Modelo, Patente, Nmero de Puertas, Cilindraje, Color. Aplicando los conceptos mencionados de Bases de Datos:
Planilla de Datos o Tabla Marca y Modelo Patente N Puertas Cilindraje Color Suzuki Samurai HK-2367 3 1200 Azul Subaru Impreza J G-2304 4 1800 Blanco Chevrolet Cavalier LM-3948 4 1600 Rojo Toyota Corolla TF-3404 4 1800 Gris Toyota Corolla HK-2376 4 1600 Verde Chevrolet Cavalier BC-2340 4 1600 Rojo
Llave Primaria La llave primaria se obtiene al seleccionar una combinacin de campos cuyos valores combinados no se repitan para ms de un registro. En este caso, podemos ver que el N de puertas es repetido, al igual que el color y el cilindraje. La marca y el modelo tambin se repiten, pero claramente ningn auto posee la misma patente de otro. Entonces la Patente es la candidata ideal para ser una llave Primaria.
Indice Puede ser relevante ordenar la lista de autos por orden alfabtico de la Marca+Modelo. Es decir, el ndice sera el que se ve a continuacin: Chevrolet Cavalier BC-2340 Chevrolet Cavalier LM-3948 Subaru Impreza J G-2304 Suzuki Samurai HK-2367 Toyota Corolla HK-2376 Toyota Corolla TF-3404
Campos Registro intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 12 Vista Como visin parcial de los datos se puede definir verbalmente algo como Todos aquellos autos, identificados por modelo, patente, y cilindraje, cuyo cilindraje sea mayor o igual a 1.700. Marca y Modelo Patente Cilindraje Subaru Impreza J G-2304 1800 Toyota Corolla TF-3404 1600
2.2 Modelos de Bases de Datos Dados los conceptos bsicos de una BD, a travs del tiempo, ya para diversas necesidades se han diseado algunos esquemas o modelos que difieren en su estructura, lo cual muchas veces trae ventajas y desventajas. Muchos de los modelos diseados han quedado obsoletos frente a otros que cumplen de mejor manera con las exigencias funcionales. Algunas de las caractersticas que deben tener: Consistencia en los datos (todos los datos dicen lo mismo, no hay contradicciones) Orden (permite saber qu existe y qu no existe, y dnde) Rapidez en la bsqueda (necesidad de la realidad informtica de hoy) Integridad de los datos (que su solidez se garantice evitando perder datos valiosos con operaciones indirectas). Acceso compartido a los datos (de modo que distintas entidades (usuarios, aplicaciones, etc.) puedan acceder simultneamente a los datos. 2.2.1 Esquema de Archivos Originalmente, los datos eran almacenados en archivos planos, que no contenan ms que una nica estructura bsica de tabla, donde cada registro ocupa un largo fijo de bytes y sus campos son estticos. Se habla de Archivos Secuenciales, ya que los registros son almacenados en orden de llegada y se mantienen en ese orden (muy rgido). Para apoyar las exigencias a este esquema, se utilizan archivos adicionales para manejar los ndices (utilizando el trmino archivos indexados), aunque las operaciones bsicas de insercin y eliminacin funcionan bastante bien. La indexacin (aplicacin de ndices) se realizaba de diversas maneras: ndices absolutos, relativos. Esquemas posteriores permitieron cambiar el esquema secuencial a un de tipo rbol, donde la manera de guardar los datos obedece a un esquema estructurado y jerrquico, de acuerdo a un orden preestablecido. Tradicionalmente se utilizaron productos comerciales, tanto lenguajes de programacin, como DBMS (por as nombrarlos) que manejan este esquema: lenguaje COBOL, archivos DBF (dBase, Clipper). En este captulo es un esquema de este tipo el que se aprovecha al manejar archivos con C#, en un ejemplo ms adelante. 2.2.2 Modelo J errquico Este modelo ms complejo, a travs de la identificacin de relaciones entre los tipos de objetos que se quieren almacenar, es capaz de construir una especia de red o ms bien, rbol de datos, donde existen precedencias en cuanto a la estructura de orden. Esto se puede ver en el siguiente ejemplo.
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 13 N Curso Ttulo Descripcin CURSO REQUISITO N Curso Ttulo DICTAR Da Hora Sala Nombre N Profesor PROFESOR ALUMNO N Alumno Nombre Nota
Este modelo muestra una realidad de una universidad, donde se dictan cursos de distinto tipo que tienen prerrequisitos, profesor (o profesores) que dicta(n) el curso, y alumnos que lo toman. Se distinguen algunos elementos como N Alumno como identificador de alumno. Un ejemplo puntual de este modelo podra darse con los siguientes datos:
El primer sistema que existi con esta esquema fue el IMS (Information Managment System) desarrollado en 1960. Este fue el precursor que fue aprovechado en la NASA en la dcada de los 60, en particular en el proyecto Apollo. Luego apareci System 2000 desarrollado por Intel. Una de las grandes ventajas de este sistema fue la posibilidad de estructurar datos en una forma ms completa que el esquema de archivos simples. An as, se vi en aprietos al momento de representar situaciones donde la naturaleza de los datos implicaba una doble jerarqua, o al momento de consultar sobre datos particulares. 2.2.3 Modelo Relacional Fruto del trabajo de E.F. Codd, y sus publicaciones de la dcada de los 70, naci el System R que implementaba un modelo bautizado como Relacional. La gran caracterstica de este modelo es que las tablas que manejaba representaban entidades, que en la realidad tenan ciertos vnculos entre ellas. Estos vnculos son conocidos como relaciones. 2.2.3.1 Tipos de Relaciones Al identificar dos o ms entidades que estn vinculadas, se distingue una relacin. Esta puede tener distinta cardinalidad, lo que se refiere a las repeticiones que se encuentran del vnculo. Supongamos las entidades del ejemplo de cursos en una universidad: curso, profesor, alumno. Cada curso puede ser dictado por uno o ms profesores, asisten varios alumnos a ese curso, los cules, a su vez asisten a otros cursos. intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 14 2.2.3.2 Relacin 1 a 1 Cuando dos entidades se relacionan en forma nica. Por ejemplo, si se diera como restriccin que cada curso es dictado por un solo profesor, entonces Profesor es 1 a 1 a Curso. 2.2.3.3 Relacin 1 a N Cuando dos entidades se relacionan de modo que una se relaciona varias veces con la otra. Por ejemplo, cada curso debe dictarse en una nica sala (1), pero en una sala se dictan varios cursos (a distintas horas obviamente), entonces Curso es 1 a N a Sala. 2.2.3.4 Relacin N a N Cuando dos entidades se relacionan en forma abierta, es decir muchos de un tipo se relacionan con muchos del otro. Por ejemplo, los alumnos toman varios cursos y a su vez cada curso integra a varios alumnos, entonces Alumno es N a N a Curso. Este modelo de BD se desarroll fuertemente en los 80 y sigue siendo hasta hoy muy utilizado en forma comercial y universal. Otro de los grandes aportes desde el punto de vista de la ciencia que se hizo con este modelo es el lgebra relacional, donde en una manera formal se pueden establecer las relaciones entre las distintas entidades y cules son las caractersticas de estas relaciones. 2.2.3.5 Formas Normales Para asegurar consistencia de los datos, integridad, y evitar redundancia y otras anomalas que algunos esquemas de datos proveen, en el modelo relacional es posible disear un esquema de tablas y relaciones que para un caso puntual pueda asegurar de mejor manera esa integridad y consistencia.
Esta definicin se hace a travs de Formas Normales, las cules definen ciertas reglas que deben cumplir los registros de cada tabla para asegurar estas caractersticas. Existen las formas Normales: 1NF, 2NF, 3NF y BCNF. Cada una de estas establece ciertas caractersticas que permiten mejorar la consistencia de datos, y la integridad. Por ejemplo, en el ejemplo de los Cursos de la Universidad, es posible definir un esquema de datos que maneje todos los datos de una manera muy rudimentaria. De esa manera se tendra una tabla como la siguiente:
N Curso Ttulo Descripcin Nombre Prof. Sala Da Hora Alumno Nota AN-21 C. II Compu.... Prez N7 Mie 19:00 Alvarez 5,6 AN-21 C. II Compu.... Prez N7 Mie 19:00 Barrios 5,8 AN-21 C. II Compu.... Prez N7 Mie 19:00 Cabrera 6,2
Despus de aplicar ciertas reglas los datos podran guardarse en varias tablas. En el esquema rudimentario recin mostrado, se pueden producir los siguientes problemas: - Redundancia: el curso, su profesor y la sala se repiten para cada alumno del curso. intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 15 - Inconsistencia: es posible que en el primer registro diga AN-21 con Prez como profesor, pero en el 2. Registro puede decir AN-21, con Snchez como profesor. No hay cmo saber cul es el correcto. - Problemas de insercin. Si agrego un nuevo alumno debo repetir todos los datos. - Problemas de eliminacin. Si elimino todos los registros de los alumnos (es decir, este curso no tuvo alumnos), entonces se pierde la informacin del profesor que haba sido designado.
En el esquema relacional adecuado, aplicando algn nivel de formas normales se pueden evitar todos estos problemas definiendo tablas separadas, usualmente distinguiendo entidades distintas, y relaciones ms complejas (N a N). 2.2.4 Modelo Distribuido A veces aplicable a varias de las estructuras existentes, la idea del modelo distribuido es repartir los datos en distintas tablas que estn ubicadas en distintas posiciones en una red de computadores. Este esquema se hace necesario cuando la administracin compartida y global de la informacin consume demasiados recursos: canal de comunicacin de red, espacio en discos de los computadores, etc. Lo que se busca con este esquema es repartir los datos de manera que el trfico de datos por la red se vea disminuido, a la vez que se permite que cada unidad que solicita datos a esta BD distribuida, pueda obtenerlos adecuadamente. 2.2.5 Modelo de BD Orientado a Objeto Buscando mejorar el rendimiento de un DBMS ante eventuales bsquedas complejas de informacin de la BD, se diseo la BD OO (Orientada a Objetos). En ella, cada entidad se distingue como un obejto que tiene Propiedades, Atributos (Campos) y Operaciones definidas que accesan esta informacin. 2.2.6 BD Multidimensional Con el creciente desarrollo de las aplicaciones computacionales orientadas a dar informacin de alto nivel, es decir, informacin que ha pasado por varias etapas de proceso desde el detalle de los datos, se han desarrollados esquemas que son capaces de contestar complejas preguntas que requieren de valores a un alto nivel de agregacin de los datos originales. Cuando se habla de la gestin de una empresa, hoy en da se habla de obtener informacin desde los datos originales que permitan tomar decisiones de acuerdo al comportamiento del negocio reflejado por los datos analizados en diversas dimensiones.
En palabras ms simples, cuando se requieren analizar los datos de ventas de productos de una fbrica, tanto por lnea de producto, o distribucin geogrfica, o travs del tiempo, es necesario tener parte de los datos ya digeridos. Si se intenta hacer sumas de detalles de facturas emitidas para obtener la informacin, segn un esquema relacional, la respuesta demorar largo tiempo en llegar, dependiendo de la cantidad de datos existentes. Una BD multidimensional utiliza un esquema en que los datos han sido procesados (sumados, recalculados totales, etc.) hasta cierto nivel y se organizan de acuerdo a las dimensiones relevantes del negocio. Esto permite contestare con buena eficiencia complejas preguntas, como tendencias, etc., pero imposibilita poder analizar una factura en particular (datos a gran nivel de detalle).
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 16 2.3 Programacin de Bases de Datos con C# Si bien hoy existen numerosas tecnolgicas maduramente desarrolladas para administrar datos en Bases de Datos, incluyendo lenguajes de manejo especializados, como es el SQL, es factible hacer programas que incluyan el manejo simple de informacin en archivos de datos de formato definido y acotado. En la gran mayora de estos programas, se define lo que se conoce como una capa lgica, que se conforma de clases que representan los datos almacenados en las diferentes tablas (o archivos), de modo que el resto del programa slo conoce la forma lgica de estas clases, y desconoce el formato de las tablas o archivos. 2.3.1 Ejemplo: Programa de Registro de Alumnos
Definicin del Problema En este ejemplo, se considera un almacenamiento de datos en archivos para poder hacer el registro de alumnos en cursos para semestres especficos. Pensando en un modelo estilo Relacional, se determinan las siguientes entidades de informacin relevantes: - El alumno, detallado con nombre, apellido, N alumno (nico), fecha nacimiento (forma ddmmaaaa), y edad. - El curso dictado, identificado por su sigla (nica), su descripcin, y la cantidad de crditos. - La inscripcin, que relaciona un alumno (identificado por su N) con un curso (identificado por su sigla), asociado a un semestre en particular (de la forma aaaan, donde aaaa es el ao y n el semestre). En este caso particular, se requiere permitir las siguientes operaciones: - Ingresar un nuevo alumno - Ingresar un nuevo curso - Inscribir un alumno en un curso, en un semestre particular - Mostrar todos los cursos - Mostrar todos los alumnos - Mostrar todas las inscripciones realizadas - Leer los datos de los archivos correspondientes - Guardar los datos de los archivos correspondientes. Elementos Involucrados: la lista de alumnos, la lista de cursos, y la lista de inscripciones.
Conceptualizacin de la Solucin Para este programa se requiere implementar las entidades: Lista de Alumnos, Lista de Cursos, Inscripciones. Las clases necesarias para implementar estas entidades son las siguientes: - Alumno y ListaAlumnos - Curso y ListaCursos - Inscripcin y ListaInscripciones Clase Alumno: contiene los datos bsicos de cada alumno y propiedades que permiten acceder a ellos Clase ListaAlumnos: maneja un conjunto de alumnos, permitiendo cargar y guardar datos de y hacia un archivo de texto con un formato especfico y adecuado. Adicionalmente permite operaciones como: Agregar Alumnos, Mostrar los Alumnos registrados, Buscar un Alumno en particular. intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 17 Las clases Curso, ListaCurso, Inscripcion, y ListaInscripciones ofrecen elementos equivalentes, cada una en su propio contexto de informacin a manejar. Adicionalmente, en la clase principal ofrece mtodos para la manipulacin general de los datos, como son: - Men de opciones - Creacin de un nuevo Alumno, preguntando sus datos - Creacin de un nuevo Curso, preguntando sus datos - Registro de una nueva inscripcin, preguntando y validando el curso y el alumno correspondiente.
Algoritmo Principal 1. Crear las instancias de las listas de datos Leer los archivos con datos 2. Repetir mientras la opcin seleccionada no sea Salir a. Mostrar Men de Opciones b. Preguntar opcin c. Si la opcin no es Salir i. Ejecutar Opcin 3. Grabar datos en archivos desde las listas
Limitaciones El programa no hace todas las validaciones de datos ingresados por el usuario, pero particularmente requiere lo siguiente: - Las descripciones de cursos deben ser un nico string sin espacios entre medio. - Los nombres y apellidos no pueden ser compuestos (o al menos, no separados por espacios) - Slo se maneja un nmero limitado de alumnos, un nmero limitado de cursos, y un nmero limitado de inscripciones - Si bien se valida la existencia de los archivos antes de leerlos, se muestra un mensaje en pantalla derivado del registro de error de la plataforma .NET.
Cdigo Fuente de la Solucin ///////////////////////////////////////////////////////////////////////////////// // Ejemplo de Manejo de Datos en Archivos - Inscripcin de Alumnos en Cursos // ========================================================================= /////////////////////////////////////////////////////////////////////////////////
using System; using System.IO; // Namespace de clases StreamReader y StreamWriter, para archivos
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase Curso: representa un curso con sus atributos bsicos //------------------------------------------------------------------------ class Curso { string sigla, descripcion; int creditos;
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 18 public Curso(string s, string d, int c) { sigla = s.ToUpper(); descripcion = d.ToUpper(); creditos = c; }
public string Sigla { get { return(sigla); } } public string Descripcion { get { return(descripcion); } } public int Creditos { get { return(creditos); } } }
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase ListaCursos: representa un conjunto de cursos //------------------------------------------------------------------------ class ListaCursos { Curso[] cursos; // Almacena la lista de cursos int cantidad = 0; const int MAX = 20; // Limitacin: 20 cursos mx string archivo = "cursos.dat";
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de alumnos en MAX public ListaCursos() { cursos = new Curso[MAX]; } // Limitacin: 20 cursos mx
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de cursos en MAX // y carga los datos de archivo identificado por su nombre public ListaCursos(string filename) { StreamReader fr; cursos = new Curso[MAX]; archivo = filename; try { fr = new StreamReader(archivo); } catch(Exception e) { //OJO: esta lnea indicar warning: no se usa e // No se pudo abrir: se crea StreamWriter sw = new StreamWriter(archivo); sw.Close(); return; } string linea; linea = fr.ReadLine(); while(linea != null) { string[] datos = linea.Split(); // Formato del archivo tiene: creditos sigla descripcin Agregar(datos[1].ToUpper(), datos[2].ToUpper(), int.Parse(datos[0])); linea = fr.ReadLine(); } fr.Close(); }
// ---------------------------------------------------------------------------- // Guardar(): guarda datos en estructura al archivo identificado por su nombre public bool Guardar() { StreamWriter fw; try { fw = new StreamWriter(archivo); } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", archivo,e.ToString()); return (false); } for(int i=0; i<cantidad; i++) fw.WriteLine("{0} {1} {2}", intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 19 cursos[i].Creditos, cursos[i].Sigla, cursos[i].Descripcion);
fw.Close(); return (true); }
// ------------------------------------------------------------------ // Agregar(): agrega un curso dado a la lista // Parmetros: Curso c, el curso a agregar public void Agregar(Curso c) { if(cantidad<MAX) cursos[cantidad++] = c; }
// ------------------------------------------------------------------ // Agregar(): agrega un curso dados sus datos, a la lista // Parmetros: la sigla, la descripcin, y los crditos public void Agregar(string s, string d, int c) { if(cantidad<MAX) { cursos[cantidad++] = new Curso(s,d,c); } }
// ------------------------------------------------------------------- // Atributo Cantidad - slo lectura, no se puede modificar "por fuera" public int Cantidad { get { return(cantidad); } }
// ------------------------------------------------------------------------------- // Mostrar(): muestra los datos registrados al momento public void Mostrar() { Console.WriteLine("\nCURSOS:"); for(int i=0; i<cantidad; i++) Console.WriteLine("{0} {1} {2}", cursos[i].Creditos, cursos[i].Sigla, cursos[i].Descripcion); Console.WriteLine("----------------------------------------------------\n"); }
// ------------------------------------------------------------------------------- // Buscar(): Busca curso definido por sigla. Retorna la posicin, -1 si no est. public int Buscar(string sigla) { for(int i=0; i<cantidad; i++) if( cursos[i].Sigla == sigla.ToUpper() ) return(i); return(-1); // Si lleg aqu: no lo encontr }
// ------------------------------------------------------------------------------ // GetCurso(): Entrega curso ubicado en la posicin n del arreglo, con n de 0..N-1 public Curso GetCurso(int n) { return(cursos[n]); } }
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase Alumno: representa un alumno con sus atributos bsicos //------------------------------------------------------------------------ class Alumno { string nombre, apellido; string fechanac; int numero;
public Alumno(int num, string n, string a, string f) { numero = num; nombre = n.ToUpper(); apellido = a.ToUpper(); fechanac = f; } public string Nombre { get { return(nombre); } } public string Apellido { get { return(apellido); } } intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 20 public string FechaNac { get { return(fechanac); } } public int Numero { get { return(numero); } } }
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase ListaAlumnos: representa un conjunto de alumnos //------------------------------------------------------------------------ class ListaAlumnos { Alumno[] alumnos; // Almacena la lista de alumnos int cantidad = 0; const int MAX = 20; // Limitacin: 20 alumnos mx string archivo = "alumnos.dat";
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de alumnos en MAX public ListaAlumnos(){ alumnos = new Alumno[MAX]; } // Limitacin: 20 alumnos mx
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de alumnos en MAX // y carga los datos de archivo identificado por su nombre public ListaAlumnos(string filename) { StreamReader fr; alumnos = new Alumno[MAX]; archivo = filename; try { fr = new StreamReader(archivo); } catch(Exception e) { //OJO: esta lnea indicar warning: no se usa e // No se pudo abrir: se crea StreamWriter sw = new StreamWriter(archivo); sw.Close(); return; } string linea; linea = fr.ReadLine(); while(linea != null) { string[] datos = linea.Split(); // Formato del archivo tiene: num fecha nombre apellido Agregar(int.Parse(datos[0]), datos[2], datos[3], datos[1]); linea = fr.ReadLine(); } fr.Close(); }
// -------------------------------------------------------------------------------- // Guardar(): guarda datos en la estructura al archivo identificado por su nombre public bool Guardar() { StreamWriter fw; try { fw = new StreamWriter(archivo); } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", archivo,e.ToString()); return (false); } for(int i=0; i<cantidad; i++) fw.WriteLine("{0} {1} {2} {3}", alumnos[i].Numero, alumnos[i].FechaNac, alumnos[i].Nombre, alumnos[i].Apellido);
fw.Close(); return (true); intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 21 }
// ------------------------------------------------------------------ // Agregar(): agrega un alumno dado a la lista // Parmetros: Alumno a, el alumno a agregar public void Agregar(Alumno a) { if(cantidad<MAX) alumnos[cantidad++] = a; }
// ------------------------------------------------------------------ // Agregar(): agrega un alumno dados sus datos, a la lista // Parmetros: el nmero, nombre, apellido, y fecha nacimiento public void Agregar(int num, string n, string a, string f) { if(cantidad<MAX) { alumnos[cantidad++] = new Alumno(num,n,a,f); } }
// ------------------------------------------------------------------- // Atributo Cantidad - slo lectura, no se puede modificar "por fuera" public int Cantidad { get { return(cantidad); } }
// ------------------------------------------------------------------------------- // Mostrar(): muestra los datos registrados al momento public void Mostrar() { Console.WriteLine("\nALUMNOS:"); for(int i=0; i<cantidad; i++) Console.WriteLine("{0} {1} {2} {3}", alumnos[i].Numero, alumnos[i].FechaNac, alumnos[i].Nombre, alumnos[i].Apellido); Console.WriteLine("-----------------------------------------------------"); }
// ------------------------------------------------------------------------ // Buscar(): Busca alumno definido por su numero. Retorna posicin, -1 si no est. public int Buscar(int numero) { for(int i=0; i<cantidad; i++) if( alumnos[i].Numero == numero ) return(i); return(-1); // Si lleg aqu: no lo encontr }
// ------------------------------------------------------------------------------- // GetAlumno(): Entrega alumno ubicado en posicin n del arreglo, con n de 0..N-1 public Alumno GetAlumno(int n) { return(alumnos[n]); } }
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase Inscripcion: representa la relacin entre un alumno y un curso //------------------------------------------------------------------------ class Inscripcion { string sigla; int numero, semestre;
public Inscripcion(string s, int n, int m) { sigla = s.ToUpper(); numero = n; semestre = m; } public string Sigla { get { return(sigla); } } public int Numero { get { return(numero); } } public int Semestre { get { return(semestre); } } }
intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 22 //------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase ListaInscripciones: representa un conjunto de inscripciones //------------------------------------------------------------------------ class ListaInscripciones { Inscripcion[] inscripciones; // Almacena la lista de inscripciones int cantidad = 0; const int MAX = 60; // Limitacin: 60 inscripciones mx string archivo = "inscripciones.dat";
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de inscripciones en MAX public ListaInscripciones() { inscripciones = new Inscripcion[MAX]; }
// ------------------------------------------------------------------ // Constructor: dimensiona la lista de inscripciones en MAX // y carga los datos de archivo identificado por su nombre public ListaInscripciones(string filename) { StreamReader fr; inscripciones = new Inscripcion[MAX]; archivo = filename; try { fr = new StreamReader(archivo); } catch(Exception e) { //OJO: esta lnea indicar warning: no se usa e // No se pudo abrir: se crea StreamWriter sw = new StreamWriter(archivo); sw.Close(); return; } string linea; linea = fr.ReadLine(); while(linea != null) { string[] datos = linea.Split(); // Formato del archivo tiene: sigla numero semestre Agregar(datos[0].ToUpper(), int.Parse(datos[1]), int.Parse(datos[2])); linea = fr.ReadLine(); } fr.Close(); }
// ------------------------------------------------------------------------------- // Guardar(): guarda datos en la estructura al archivo identificado por su nombre public bool Guardar() { StreamWriter fw; try { fw = new StreamWriter(archivo); } catch(Exception e) { Console.WriteLine("Error en la apertura de \"{0}\": {1}", archivo,e.ToString()); return (false); } for(int i=0; i<cantidad; i++) fw.WriteLine("{0} {1} {2}", inscripciones[i].Sigla, inscripciones[i].Numero, inscripciones[i].Semestre);
fw.Close(); return (true); }
// ------------------------------------------------------------------ // Agregar(): agrega una inscripcin dada a la lista // Parmetros: Inscripcion i, el curso a agregar intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 23 public void Agregar(Inscripcion i) { if(cantidad<MAX) inscripciones[cantidad++] = i; }
// ------------------------------------------------------------------ // Agregar(): agrega un curso dados sus datos, a la lista // Parmetros: la sigla, la descripcin, y los crditos public void Agregar(string s, int n, int m) { if(cantidad<MAX) { inscripciones[cantidad++] = new Inscripcion(s,n,m); } }
// ------------------------------------------------------------------- // Atributo Cantidad - slo lectura, no se puede modificar "por fuera" public int Cantidad { get { return(cantidad); } }
// ------------------------------------------------------------------------------ // Mostrar(): muestra los datos registrados al momento public void Mostrar(ListaAlumnos la, ListaCursos lc) { Console.WriteLine("\nINSCRIPCIONES:"); for(int i=0; i<cantidad; i++) { Alumno a; Curso c; a = la.GetAlumno(la.Buscar(inscripciones[i].Numero)); c = lc.GetCurso(lc.Buscar(inscripciones[i].Sigla));
//------------------------------------------------------------------------ //------------------------------------------------------------------------ // Clase MainApp: Bloque del Algoritmo Principal y mtodos auxiliares //------------------------------------------------------------------------ class MainApp {
static Alumno NuevoAlumno() { string nombre, apellido, fechanac; int numero;
Console.WriteLine("Datos del nuevo alumno"); Console.Write("Nombre: "); nombre = Console.ReadLine(); Console.Write("Apellido: "); apellido = Console.ReadLine(); intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 24 do { Console.Write("Fecha Nac (ddmmaaaa): "); fechanac = Console.ReadLine(); } while (!ValidarFecha(fechanac)); Console.Write("Numero: "); numero = int.Parse(Console.ReadLine());
// -------------------------------------------------------------------------- // NuevaInscripcion(): Crea una nueva inscripcin relacionando un alumno existente // con un curso que tambin debe ser existente. // Observaciones: Se le pide al usuario slo el N del alumno y la sigla del curso, // validando que ambos existan. static Inscripcion NuevaInscripcion(ListaAlumnos la, ListaCursos lc) { string sigla; int numero, semestre; Alumno a; Curso c;
// Muestra listas en pantalla para ayudar al usuario a indicar datos. la.Mostrar(); lc.Mostrar(); Console.WriteLine("Inscripcin de Curso:"); do { Console.Write("N Alumno: "); numero = int.Parse(Console.ReadLine()); } while( la.Buscar(numero)<0 ); do { Console.Write("Sigla Curso: "); sigla = Console.ReadLine(); } while( lc.Buscar(sigla)<0 ); Console.Write("Semestre: "); semestre = int.Parse(Console.ReadLine());
a = la.GetAlumno(la.Buscar(numero)); c = lc.GetCurso(lc.Buscar(sigla)); Console.WriteLine("El alumno {0} {1} se inscribi en el curso {2} ({3})", a.Nombre, a.Apellido, c.Sigla, c.Descripcion);
static int Menu(string[] opciones) { int contador = 1, op = 0; foreach(string opcion in opciones) Console.WriteLine("{0}) {1}",contador++,opcion); Console.Write("Ingrese su opcin: "); do op = int.Parse(Console.ReadLine()); while (op<=0 && op>=contador); return(op); }
static void Main() { string[] opciones = { "Agregar Alumno", "Agregar Curso", intro. Prog. Orientada a Objeto Archivos y B. de Datos Rodrigo Sandoval U. IIC 1102 Pgina: 25 "Inscribir en Curso", "Mostrar Alumnos", "Mostrar Cursos", "Mostrar Inscripciones", "Salir" }; int opcion = 0;
ListaCursos lc = new ListaCursos(archivocursos); ListaAlumnos la = new ListaAlumnos(archivoalumnos); ListaInscripciones li = new ListaInscripciones(archivoinscripciones);
do { opcion = Menu(opciones); switch(opcion) { case 1: la.Agregar(NuevoAlumno()); break; case 2: lc.Agregar(NuevoCurso()); break; case 3: li.Agregar(NuevaInscripcion(la,lc));break; case 4: la.Mostrar(); break; case 5: lc.Mostrar(); break; case 6: li.Mostrar(la,lc); break; } } while(opcion!=7);
lc.Guardar(); la.Guardar(); li.Guardar(); } } Instrucciones de compilacin. Para compilar este ejemplo, se debe copiar el cdigo en un archivo .cs y compilarlo individualmente. En este proceso aparecern 3 warnings relacionados los bloques try-catch de los constructores de las listas definidas, en especfico, indicando que la variable e no es utilizada. Se puede modificar ese bloque para utilizarla como parte de un mensaje adecuado, pero no es necesario en estricto rigor. Instrucciones de ejecucin. Para ejecutar correctamente este ejemplo, los archivos alumnos.dat, cursos.dat, e inscripciones.dat deeben estar ubicados en la misma carpeta del ejecutable, o bien no existir, y sern creados en dicha ubicacin. PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN Curso: IIC 1102 INTRODUCCIN A LA PROG. ORIENTADA A OBJETO Profesor: Rodrigo Sandoval U.
Simulacin Computacional con C#
1 INTRODUCCIN ............................................................................................................................................... 1 2 MODELO DE SIMULACIN............................................................................................................................ 2 2.1 PARMETROS DE LA SIMULACIN ..................................................................................................................2 2.2 DATOS O INPUT DE LA SIMULACIN................................................................................................................2 2.2.1 Generacin de Nmeros Aleatorios ....................................................................................................... 2 2.2.2 Carga de Datos Reales desde Archivos.................................................................................................. 4 2.3 EJ ECUCIN DE LA SIMULACIN.......................................................................................................................5 2.3.1 El Manejo del Tiempo ............................................................................................................................ 5 2.3.2 Colas en C#............................................................................................................................................ 7 3 EJEMPLOS.......................................................................................................................................................... 9 3.1 SIMULACIN DE CADENA DE CORREO............................................................................................................9 3.2 LLEGADA DE CLIENTES A CAJ A EN EL BANCO..............................................................................................10 3.2.1 Solucin 1.0.......................................................................................................................................... 11 3.2.2 Solucin 2.0.......................................................................................................................................... 13 3.2.3 Solucin 3.0.......................................................................................................................................... 15 3.3 SIMULACIN DE LAS COLAS EN UN SUPERMERCADO....................................................................................17 3.3.1 Definicin del Problema ...................................................................................................................... 17 3.3.2 Caractersticas del Modelo.................................................................................................................. 17 3.3.3 Mediciones Requeridas ........................................................................................................................ 17 3.3.4 Solucin................................................................................................................................................ 18 3.4 SIMULACIN DE UNA PLAZA DE PEAJ E..........................................................................................................24 3.4.1 Definicin del Problema ...................................................................................................................... 24 3.4.2 Solucin................................................................................................................................................ 26
Material preparado por Rodrigo Sandoval U en Agosto 2005, (rsandova@ing.puc.cl) basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.al.
Simulacin Computacional con C# Rodrigo Sandoval U. 1 Introduccin La simulacin mediante programas de computador permite el estudio detallado de sistemas complejos, sobre los que resulta costoso, difcil o peligroso llevar a cabo estudios reales. La simulacin se basa en analizar el comportamiento de un modelo derivado de una situacin real, de la forma ms equivalente posible, para obtener resultados de la medicin del comportamiento de este modelo y as sacar conclusiones. En otras palabras, un modelo de simulacin intenta recrear de la mejor manera posible las caractersticas del sistema representado y se comporta de manera similar a como lo hara en la realidad. La idea es que la ejecucin de la simulacin produzca resultados en la forma de valores estadsticos, o simplemente permita monitorear el desempeo del sistema durante su funcionamiento.
Modelo de Simulacin Los modelos de simulacin distinguen en general cuatro elementos esenciales: A. Parmetros de Funcionamiento. Estos datos, muchas veces valores numricos fijos para una simulacin, determinan ciertas condiciones de la ejecucin, que tambin se define como el escenario a analizar. Siempre ser posible cambiar los valores de estos parmetros y como consecuencia, observar el comportamiento del modelo con esas nuevas condiciones y eventualmente sacar conclusiones al comparar los resultados de un escenario con los de otro. B. Datos o Input de la Simulacin. Para representar situaciones del modelo real, se cuenta con datos de diverso tipo que alimentarn la simulacin completando el escenario a implementar con este modelo. Estos datos generalmente son de tres tipos: datos fijos, conceptualizados como promedios constantes; datos aleatorios que le dan un factor de variabilidad y ofrecen un escenario con elementos impredecibles al modelo; y datos reales, que fueron medidos en una situacin equivalente en la vida real, y que le aportarn el factor realista directo al modelo. C. Ejecucin de la Simulacin. Consiste en realizar la simulacin propiamente tal, por medio de la ejecucin iterativa de pasos que emulan el comportamiento de la situacin modelada. Entre los elementos que se consideran en esta ejecucin, posiblemente el ms importante es el manejo del tiempo, en el cual el modelo es capaz de identificar los eventos que ocurren en un instante relevante de tiempo, y ejecutarlos como parte de la simulacin. D. Resultados de la Simulacin. Datos medidos durante la ejecucin que permiten obtener una visin del desempeo del modelo y por ende, sacar conclusiones de la situacin simulada. Tomando un ejemplo clsico, la simulacin de autos en una interseccin de calles, un parmetro de entrada sera la duracin de la luz roja y de la verde; datos o input sera la llegada de vehculos en momentos de la simulacin; la ejecucin considerara el tiempo que toma que los autos se vayan acumulando en roja y luego salgan en verde; y resultados posibles se consideran el tiempo de espera, o la probabilidad de que un auto no alcance a cruzar en verde. IIC 1102 Pgina: 1 Simulacin Computacional con C# Rodrigo Sandoval U. 2 Modelo de Simulacin 2.1 Parmetros de la Simulacin En estos modelos es de mucha utilidad el uso de parmetros, que permitan de manera simple cambiar las caractersticas del ambiente o del sistema mismo, de modo que sea posible observar los cambios que se producen en su operacin. Definen un escenario especfico en el cual se realizar la simulacin. Normalmente son valores numricos, que se mantienen constantes durante la simulacin completa. El hecho de mantener estos valores paramtricos, permite a quien analiza la simulacin variarlos y poder probar distintos escenarios de simulacin. Por ejemplo, parmetros de una simulacin podran ser la duracin de un semforo en una interseccin, la capacidad de carga de un camin o de otro medio de transporte, la capacidad de atencin de una caja de banco o de tienda, valores monetarios o tarifas. 2.2 Datos o Input de la Simulacin Los datos que alimentan el modelo de simulacin pueden ser fijos que usualmente son ms bien considerados como parmetros de la simulacin o bien generarse en forma aleatoria de acuerdo a ciertas condiciones de distribucin de estos valores casi siempre numricos, y finalmente es posible contar con mediciones reales tomadas en terreno, las cuales al quedar almacenadas en archivos, por ejemplo, permiten su recuperacin durante el proceso de la simulacin, para constituir una fuente realista de la situacin modelada. 2.2.1 Generacin de Nmeros Aleatorios La generacin de valores aleatorios le da un grado de incerteza al comportamiento del modelo. Si bien es posible determinar que ciertos valores que alimentan el modelo se comportan de acuerdo a diferentes tipos de distribuciones estadsticas, en el gran porcentaje de los casos, el uso de la distribucin uniforme en la cual todos los nmeros de un rango tienen la misma posibilidad de salir es suficiente para soportar diferentes modelos. Para producir estos datos es necesario contar con herramientas que generen nmeros aleatorios en ciertos intervalos y con cierta distribucin especificada en el modelo. En C#la generacin de nmeros aleatorios est resuelta por una clase llamada Random, cuyo principal propsito es generar nmeros aleatorios dentro de un rango especificado. Un programa que utilice Random para la generacin de nmeros, depende de dos principales declaraciones: el constructor y el mtodo Next(). 2.2.1.1 Constructor de Random Existen diferentes versiones del constructor, las cuales por sobrecarga reciben distintos parmetros. El constructor simple no recibe parmetros: Random num = new Random(); El constructor con semilla permite su inicializacin estableciendo una semilla de aleatoriedad, de manera que no se repitan las secuencias de nmeros entregados. Para darle un grado de variabilidad a esta generacin de nmeros, se recomienda el uso de una semilla que en cada llamado al programa tenga un valor diferente. El usar un nmero fijo o constante, es equivalente funcionalmente al constructor sin parmetros: la secuencia de nmeros aleatorios ser idntica en cada ejecucin desde cero del programa. Para la semilla, hay dos alternativas: utilizar un nmero entregado por el usuario, que se espere vaya variando en cada ejecucin, o utilizar un valor del reloj del computador, el cual se obtiene del uso de DateTime.Now objeto que se detalla ms adelante en este documento. Este objeto tiene un campo llamado Millisecond, el cual indica la parte de milisegundos (de 0 a 999) de la hora actual. Random num = new Random(DateTime.Now.Millisecond);
IIC 1102 Pgina: 2 Simulacin Computacional con C# Rodrigo Sandoval U. 2.2.1.2 Generacin de nmeros con Next El mtodo Next() tiene varias versiones, las cuales por sobrecarga de mtodos ofrecen comportamientos levemente diferentes y tiles en situaciones distintas. Las dos versiones principales son las siguientes, y ambas incluyen un valor que representa el lmite superior no incluido del rango de valores posibles: int numero1 = num.Next(11); // numero1 tendr un valor entre 0 y 10 int numero2 = num.Next(5,11); // numero2 tendr un valor entre 5 y 10 2.2.1.3 Ejemplo Bsico de Random A continuacin, un ejemplo de un programa que genera 10 nmeros aleatorios entre 1 y 10. using System;
class MainApp { static void Main() { Random rn = new Random(DateTime.Now.Millisecond); for(int n=0; n<10 ; n++) Console.WriteLine(Nmero: {0}, rn.Next(1,11)); // Nmeros entre 1 y 10 Console.ReadLine(); } } En el ejemplo anterior resulta relevante analizar las siguientes lneas: - La instanciacin de un nuevo generador de nmeros aleatorios: Random rn = new Random(...) - Le generacin de un nuevo nmero: rn.Next(1,11); La primera lnea se refiere a la creacin de un nuevo generador de nmeros aleatorios, instanciado como rn. Como argumento al constructor, se entrega la semilla de generacin, que en este caso es un nmero de 0 a 999 (correspondiente a los milisegundos de la hora actual). Este nmero, que segn el instante en que se ejecute la lnea, tendr uno de 1.000 valores posibles, inicializar el punto de partida de la serie de generacin de nmeros aleatorios, asegurando que la posibilidad de que se repita una secuencia de nmeros generados, sea una en mil. La segunda lnea relevante de conocer es la que entrega un nuevo nmero: rn.Next(1,11), indicando que los valores posibles van entre el 1 y el 10 (11-1). 2.2.1.4 Generacin de Valores Aleatorios en Otras Escalas En muchos casos, el uso de valores enteros directamente no es parte del contexto del problema modelado. Por tal razn, existen estrategias de aprovechamiento del comportamiento de Random descrito anteriormente, que permiten generar estos nmeros en otras escalas. Generacin de Verdadero o Falso Aleatoriamente. La conversin es simple, si se toma la generacin de nmeros enteros aleatorios entre 0 y 1 se puede tener una conversin en que 0 corresponde a False (o false en C#) y 1 corresponde a Verdadero (true en C#). using System;
class MainApp { static void Main() { Random rn = new Random(DateTime.Now.Millisecond); for(int n=0; n<10 ; n++) if( rn.Next(2) == 1 ) // Valores entre 0 y 1 Console.WriteLine(VERDADERO); else Console.WriteLine(FALSO); Console.ReadLine(); } } IIC 1102 Pgina: 3 Simulacin Computacional con C# Rodrigo Sandoval U. Generacin de Valores Reales Aleatoriamente. La primera decisin que hay que tomar es cuntos decimales son relevantes para el modelo representado. Si la cantidad de decimales relevantes son 2, entonces, se generan nmeros enteros que se dividen por 100 (10 elevado a 2). using System;
class MainApp { static void Main() { Random rn = new Random(DateTime.Now.Millisecond); for(int n=0; n<10 ; n++) // 10 nmeros reales aleatorios entre 0.00 y 99.99 Console.WriteLine(Nmero: {0}, rn.Next(1,10001)/100); Console.ReadLine(); } }
Generacin con Diferente Probabilidad Un modelo particular puede plantear algo como la cantidad de personas que entran en cada instante de tiempo es de 1 con 20% de probabilidad, 2 con 30% y 3 con 50%. Esta situacin una vez ms puede modelarse con la generacin de nmeros enteros aleatorios, con la adaptacin en funcin de los porcentajes de probabilidades. Es decir, si un caso tiene 20% de probabilidades de salir, implica que de 10 nmeros (1 al 10) la probabilidad de que salga un 1 un 2 es exactamente de 10%+10% =20%. As, el siguiente 30% se da cuando salen el 3, 4 5, y el 50% restante con cualquier nmero entre 6 y 10. En ese caso, el ejemplo podra plantearse en C#. using System;
class MainApp { static void Main() { Random rn = new Random(DateTime.Now.Millisecond); int numero = rn.Next(1,11); if(numero <= 2) Console.WriteLine(20%); if(numero>2 && numero<=5) Console.WriteLine(30%); if(numero>5) Console.WriteLine(50%); Console.ReadLine(); } }
2.2.2 Carga de Datos Reales desde Archivos En muchos casos, ms que asumir comportamientos de acuerdo a una distribucin estadstica, es factible contar con datos reales, en muchos casos medidos en su generacin real. Por ejemplo, la cantidad de autos llegados a una interseccin por unidad de tiempo, la cantidad de clientes que llegan a la caja en un banco, etc. En estos casos, conociendo el comportamiento de cierto parmetro en forma real, estos datos alimentan el sistema de simulacin, el cual procesa la informacin entrante segn la lgica. La informacin se almacena en archivos de datos, cuyo caso ms comn es simplemente el formato de texto plano, cada lnea del archivo representando un dato puntual. El archivo es ledo antes de comenzar la simulacin y sus datos son almacenados en una representacin de cola, o alguna estructura que emule la misma generacin de los datos, secuencialmente en el tiempo.
IIC 1102 Pgina: 4 Simulacin Computacional con C# Rodrigo Sandoval U. 2.3 Ejecucin de la Simulacin Uno de los aspectos ms importantes en una simulacin es el manejo del tiempo, pues los sistemas normalmente se desenvuelven de acuerdo a una componente temporal. En este punto, la alternativa ms simple es emplear una componente de tiempo discreto. Segn este enfoque, el funcionamiento del sistema se puede predecir dentro de unidades discretas de tiempo (por ejemplo, segundos o minutos, e incluso das). La eleccin de esta unidad resulta fundamental, pues introducir cierto margen de error en la simulacin. Otro aspecto fundamental es la alimentacin de la simulacin con datos de entrada reales. Las simulaciones usualmente llevan consigo una gran cantidad de trabajo de campo recogiendo valores de entrada. Por ejemplo, para simular los tacos que se forman en una interseccin ser necesario tomar datos sobre la afluencia de vehculos por cada calle que concurre a la interseccin. Existen bases tericas que pueden aplicarse a distintos modelos de simulacin, tal es el caso de la Teora de Colas para la simulacin de filas en las que usuarios esperan ser atendidos, o Dinmica para la simulacin de cuerpos en movimiento. En general, una simulacin requerir de algn sustento terico que guiar el funcionamiento del sistema, y por consiguiente depender de cada caso en particular. En esta seccin se presenta un modelo de simulacin, junto con su implementacin, que pretende ilustrar esta importante aplicacin de los computadores. El modelo planteado no hace uso de resultados tericos importantes, con el objetivo de hacerlo ms fcil de entender. Sin embargo, presenta conceptos de mucha importancia, como el manejo del tiempo discreto, la representacin de las entidades que forman el modelo como estructuras de datos del lenguaje de programacin empleado, y el manejo de algunos parmetros de configuracin. 2.3.1 El Manejo del Tiempo Tal como se indic, uno de los elementos relevantes de controlar es el tiempo. Ya sea que el contexto de la simulacin requiere una unidad discreta basada en segundos, minutos, horas, das, semanas, o incluso meses, siempre es necesario ir registrando el paso del tiempo con un contador. Este registro puede ser tan simple como utilizar un contador entero que se incrementa de uno en uno, hasta determinar el fin de la simulacin. En este caso, se usa por convencin el concepto de Tics, refirindose a que cada Tic es un incremento en el contador de tiempo. Para esto, dos objetos existentes en el framework de .NET resuelven el manejo del tiempo y lapsos. 2.3.1.1 DateTime En algunos casos, se requiere un registro del tiempo ms preciso que un simple contador, por lo que se usa una estructura que almacena los datos referentes al tiempo. En C#se cuenta con tal tipo de estructura, en la forma de una clase de nombre DateTime. En particular, existe una propiedad de DateTime, que ofrece todos los datos de la hora actual (al momento de ser consultada), incluyendo hasta los milisegundos: ao-mes-da-hora-min-seg-miliseg. Esta es DateTime.Now y se usa como referencia temporal para inicializaciones, o incluso, comparaciones referenciales. La instanciacin de un objeto de tipo DateTime aprovecha las facultades del Constructor. Por ejemplo: using System; // Nueva instancia DateTime con el 28 del 7 de 1979 a las 10:35:05 PM. DateTime dateTime = new DateTime(1979, // Ao 07, // Mes 28, // Da 22, // Hora 35, // Minutos 5, // Segundos 15); // Milisegundo Console.WriteLine("{0:F}", dateTime); // Escribe la fecha IIC 1102 Pgina: 5 Simulacin Computacional con C# Rodrigo Sandoval U. 2.3.1.2 Propiedades, Mtodos y Operadores principales de DateTime Propiedades Date Obtiene el componente correspondiente a la fecha de esta instancia. Day Obtiene el da del mes representado por esta instancia. DayOfWeek Obtiene el da de la semana representado por esta instancia. DayOfYear Obtiene el da del ao representado por esta instancia. Hour Obtiene el componente correspondiente a la hora de la fecha representada por esta instancia. Millisecond Obtiene el componente correspondiente a los milisegundos de la fecha representada por esta instancia. Minute Obtiene el componente correspondiente a los minutos de la fecha representada por esta instancia. Month Obtiene el componente correspondiente al mes de la fecha representada por esta instancia. Now Obtiene un DateTime que constituye la fecha y hora locales actuales de este equipo. Second Obtiene el componente correspondiente a los segundos de la fecha representada por esta instancia. Ticks Obtiene el nmero de pasos que representan la fecha y hora de esta instancia. TimeOfDay Obtiene la hora del da para esta instancia. Today Obtiene la fecha actual. UtcNow Obtiene un DateTime que representa la fecha y hora locales actuales de este equipo y que se expresa en forma de hora universal coordinada (UTC). Year Obtiene el componente correspondiente al ao de la fecha representada por esta instancia. Mtodos AddDays Agrega el nmero de das especificado al valor de esta instancia. AddHours Agrega el nmero de horas especificado al valor de esta instancia. AddMilliseconds Agrega el nmero de milisegundos especificado al valor de esta instancia. AddMinutes Agrega el nmero de minutos especificado al valor de esta instancia. AddMonths Agrega el nmero de meses especificado al valor de esta instancia. AddSeconds Agrega el nmero de segundos especificado al valor de esta instancia. AddTicks Agrega el nmero de pasos especificado al valor de esta instancia. AddYears Agrega el nmero de aos especificado al valor de esta instancia. Compare Compara dos instancias de DateTime y devuelve una indicacin de sus valores relativos. CompareTo Compara esta instancia con un objeto especificado y devuelve una indicacin de los valores relativos. Operadores Suma (+) Agrega un intervalo de tiempo especificado a una fecha y hora especificadas, generando una fecha y hora nuevas. Igualdad (==) Determina si dos instancias especificadas de DateTime son iguales. Mayor que (>y >=) Determina si un DateTime especificado es mayor que otro DateTime especificado. Desigualdad (!=) Determina si dos instancias especificadas de DateTime no son iguales. Menor que (<y <=) Determina si un DateTime especificado es menor que otro DateTime especificado. Resta (-) Sobrecargado. Resta un DateTime especificado de un DateTime especificado. IIC 1102 Pgina: 6 Simulacin Computacional con C# Rodrigo Sandoval U. Ejemplos prcticos del uso de DateTime como parte de los datos de una clase utilizada en una simulacin se ven en la siguiente seccin de ejemplos. 2.3.1.3 TimeSpan Por su parte, el manejo de lapsos o intervalos de tiempo se resuelve con TimeSpan. Esencialmente ste representa el objeto resultante de la diferencia entre dos objetos de tipo DateTime, y es el que se usa para representar los Tics o unidades de tiempo relevante. Existen varias versiones del constructor de TimeSpan, las que varan principalmente en la cantidad de enteros que reciben como parmetro, lo cual determina la cantidad de tiempo que incluye el intervalo de tiempo. Algunas de estas diferentes versiones se demuestran en los siguientes ejemplos. using System;
TimeSpan t1 = new TimeSpan(0, 1, 0); // 0 horas, 1 minuto, 0 segundos TimeSpan t2 = new TimeSpan(1, 0, 0, 0); // 1 da, 0 horas, 0 min, 0 seg TimeSpan t3 = new TimeSpan(0, 0, 0, 0, 1); // 1 dd, 0 hh, 0 mm, 0 s, 1 mseg.
A continuacin se muestra un ejemplo prctico del uso de TimeSpan y DateTIme juntos en una simulacin. En este caso, el reloj de control de la simulacin deber comenzar a las 13:30. Como referencia de fecha, se utiliza la fecha actual por medio de DateTime.Now que corresponde a un objeto de tipo DateTime asignado a la fecha del computador en el momento en que se invoca. using System;
. . .
// Declaracin del reloj que llevar la cuenta de tiempo de simulacin DateTime reloj = DateTime.Now; // Reloj puesto a la fecha y hora actual // Se ajusta el reloj a la hora de inicio de la simulacin reloj.Hour = 13; reloj.Minute = 30; reloj.Second = 0; reloj.Millisecond = 0;
// Declaracin de la hora de fin -> 30 minutos despus del inicio. DateTime fin = reloj + new TimeSpan(0,30,0);
// Declaracin de la unidad significativa de tiempo -> 1 minuto TimeSpan tick = new TimeSpan(0, 1, 0); // 0 horas, 1 minuto, 0 segundos
. . . while(reloj <= fin) { // Mientras el reloj no sea igual a la hora de fin . . . Reloj += tick; // Se incrementa el contador de tiempo en un tick } . . . 2.3.2 Colas en C# El uso de colas en simulacin permite representar la llegada de objetos (personas, autos, rdenes de compra, etc.) en el tiempo y que sern atendidos como parte del proceso de simulacin. El uso de colas es un concepto tradicionalmente referido en simulacin computacional. En el caso del lenguaje C#y del framework de .NET, reconociendo las colas como una estructura frecuentemente requerida, se ha incluido su definicin completa en un objeto denominado Queue, que ofrece el comportamiento tradicional de una cola, en la cual los elementos nuevos ingresan slo al final y se sacan elementos slo por adelante. Esta clase est disponible dentro del Namespace System.Collections. IIC 1102 Pgina: 7 Simulacin Computacional con C# Rodrigo Sandoval U. Esta clase Queue puede almacenar objetos de cualquier tipo, ya que su elemento base es Object, que es el objeto base del cual derivan absolutamente todos los objetos definidos por los desarrolladores. De esa manera, se pueden crear fcilmente colas para almacenar elementos bsicos como nmeros (int, double, etc.) o cualquier otro elemento definido en una clase del programa. Las operaciones estndar de una cola son: Agregar un Elemento (que lo ubica al final de la cola de elementos ya agregados); Sacar el Primero (slo se sacan elementos por el inicio de la cola); Ver el Primero (slo se puede ver el elemento que est en primer lugar sin sacarlo de la cola); y ver el Largo de la lista (para determinar la cantidad de elementos que estn en la cola). Formalmente, los elementos de la clase Queue son los siguientes: Mtodos void Enqueue(Object) Este mtodo encola un elemento derivado de la clase Object. Object Dequeue() Saca el primer elemento de la cola, retornndolo para ser utilizado. Este mtodo no verifica si la cola cuenta con elementos, por lo que es conveniente agregar una clusula condicional verificando que existan elementos antes de retirar el primero, o bien aprovechar un bloque de control de excepciones try-catch. Object Peek() Funciona equivalentemente a Dequeue(), con la diferencia de que el objeto en primer lugar de la cola no es retirado, sino que permanece. Propiedades int Count Propiedad que retorna un nmero mayor o igual a cero, indicando la cantidad de elementos de la cola. Count Enqueue() Dequeue() Peek()
La siguiente seccin incluye diferentes ejemplos que hacen uso exhaustivo de la definicin de Queue, de modo de ilustrar el comportamiento de cada uno de estos mtodos y propiedad, as como dar una nocin de la manera de utilizar esta clase para apoyar el proceso de simulacin. IIC 1102 Pgina: 8 Simulacin Computacional con C# Rodrigo Sandoval U. 3 Ejemplos Entre los ejemplos que ilustran la simulacin conceptual, se distinguen diversos tipos de complejidad. A medida que los ejemplos van involucrando ms elementos de simulacin y de resultados, se van programando y utilizando objetos ms complejos. 3.1 Simulacin de Cadena de Correo Las cadenas enviadas por correo (originalmente en cartas de papel, hoy por e-mail), son seguidas por muchos y odiadas por otros tantos. En este ejemplo se pretende ver el comportamiento de una nueva cadena por correo, la cual cuenta con ciertas caractersticas que definen su funcionamiento. Esta cadena en particular indica que para ser continuada, cada receptor deber re-enviar a 4 nuevas personas. Para efectos del ejemplo se han tomado ciertas simplificaciones a un caso realista, de modo de concentrar el modelamiento en los conceptos vistos en este documento. La forma de funcionamiento es la siguiente: De las 4 personas a quienes se reenva, existe un 66% de probabilidad de que la persona receptora no lo tome en cuenta y corte su parte de la cadena. El periodo que se toma en leer y reenviar es de 24 horas. Este programa de simulacin analiza el comportamiento de una cadena, en la medida en que se van agregando nuevas personas, por un periodo de 30 das. Al final de la simulacin, se indicarn en pantalla cuntas personas en total recibieron la cadena y cuntas efectivamente la reenviaron. Solucin Esta solucin se implementa en forma directa, sin mayores estructuras especiales. En particular, el manejo del tiempo, al no requerirse en fechas absolutas, se maneja en forma relativa con un simple contador de tipo entero, avanzando por un loop o ciclo de 30 iteraciones (representando los 30 das de simulacin). Cdigo Fuente Solucin using System;
class MainApp { static void Main() { Random rn = new Random(DateTime.Now.Millisecond); int enviaron = 1, recibieron = 0, recibieronant = 1; // Se parte con 1 sola persona
for(int i=0; i<30 ; i++) { // loop para 30 das int rec = 0, env = 0; Console.Write("Da {0}: ", i+1); for(int j=0; j<recibieronant; j++) { // p/todos los receptores da anterior for(int k=0; k<4; k++) { // c/u de los anteriores, envi a 4 rec++; if( rn.Next(0,3) > 1 ) // Posibilidad de que lo reenve env++; } } Console.WriteLine(" de:{0} rec:{1} y env:{2}", recibieronant, rec, env); recibieronant = env; recibieron += rec; enviaron += env; }
Console.WriteLine("En un periodo de simulacin de 30 das:"); Console.WriteLine("Recibieron: {0} personas", recibieron); Console.WriteLine("Enviaron: {0} personas", enviaron); Console.ReadLine(); } } IIC 1102 Pgina: 9 Simulacin Computacional con C# Rodrigo Sandoval U. Ejemplo de ejecucin y resultados: Da 1: de:1 rec:4 y env:3 Da 2: de:3 rec:12 y env:3 Da 3: de:3 rec:12 y env:9 Da 4: de:9 rec:36 y env:14 Da 5: de:14 rec:56 y env:22 Da 6: de:22 rec:88 y env:28 Da 7: de:28 rec:112 y env:32 Da 8: de:32 rec:128 y env:41 Da 9: de:41 rec:164 y env:56 Da 10: de:56 rec:224 y env:70 Da 11: de:70 rec:280 y env:85 Da 12: de:85 rec:340 y env:100 Da 13: de:100 rec:400 y env:140 Da 14: de:140 rec:560 y env:192 Da 15: de:192 rec:768 y env:251 Da 16: de:251 rec:1004 y env:332 Da 17: de:332 rec:1328 y env:450 Da 18: de:450 rec:1800 y env:596 Da 19: de:596 rec:2384 y env:805 Da 20: de:805 rec:3220 y env:1027 Da 21: de:1027 rec:4108 y env:1389 Da 22: de:1389 rec:5556 y env:1803 Da 23: de:1803 rec:7212 y env:2430 Da 24: de:2430 rec:9720 y env:3337 Da 25: de:3337 rec:13348 y env:4488 Da 26: de:4488 rec:17952 y env:5960 Da 27: de:5960 rec:23840 y env:7777 Da 28: de:7777 rec:31108 y env:10201 Da 29: de:10201 rec:40804 y env:13572 Da 30: de:13572 rec:54288 y env:18036 En un periodo de simulacin de 30 das: Recibieron: 220856 personas Enviaron: 73250 personas
3.2 Llegada de Clientes a Caja en el Banco Este ejemplo muestra el simple proceso de la llegada de clientes a una caja de banco y cmo son atendidos. En particular se busca mostrar distintas versiones de un mismo ejemplo, agregando ciertos elementos o simplificando algunas condiciones para ilustrar el uso de los diferentes elementos que tanto la teora, como la librera de clases del Microsoft .NET framework ofrecen para facilitar estas implementaciones. Se toman las siguientes condiciones: El periodo de simulacin es de 30 minutos. Se conoce el momento de llegada de los clientes a la cola, datos que vienen almacenados en un archivo de datos. Puede llegar ms de un cliente por minuto. En un archivo de entrada, clientes.dat, vendr como nico dato por cada lnea, el instante en que lleg el cliente N (con N: lnea del archivo). Es posible que ms de una lnea contenga el mismo nmero, representando que ms de un cliente lleg en el mismo instante de tiempo. Se asume que todos los clientes tienen en promedio la misma cantidad de trmites que realizar, por lo que se demorarn lo mismo. IIC 1102 Pgina: 10 Simulacin Computacional con C# Rodrigo Sandoval U. Se sabe que el nico cajero atendiendo, procesa 1 cliente por minuto. Por esta razn se utilizar 1 minuto como unidad de tiempo significativa. Instante 1 Instante 2 Instante 3 Instante 4 Orden de Llegada Atiende 1 cliente por minuto 1 4
Al finalizar la simulacin interesa conocer: El total de clientes atendidos por el cajero. La espera mxima en la cola en minutos.
3.2.1 Solucin 1.0 Esta primera versin del ejemplo se modela y soluciona de la forma ms simple, tomando algunas suposiciones de la operacin real y utilizando los elementos bsicos del lenguaje C#. Solucin Se implementar una cola de clientes, registrando el instante de llegada de cada uno de ellos, de modo de procesar los momentos de llegada en sincronizacin con el manejo del tiempo de la simulacin, mientras que se utilizan los instantes de llegada para medir el tiempo de espera de cada cliente, al compararlo con el momento en que son atendidos. El proceso general tomar un reloj de tipo nmero entero, funcionando como contador (cronmetro de minutos), que ir aumentando en 1, cuando haya clientes en cola, o se adelantar hasta el instante en que llega el siguiente cliente. Es decir, no es necesario una contabilizacin exhaustiva de cada unidad de tiempo de simulacin, sino que se puede simplificar el proceso computacional involucrado al procesar slo los instantes en que ocurren eventos relevantes dentro del proceso, como es la atencin de clientes, mientras que se saltan los instantes en que no hay clientes en la cola. Cdigo Fuente Solucin using System; using System.IO;
// ---------------------------------------------------------------- // Clase Cliente // Representa un cliente, con su instante de llegada // ---------------------------------------------------------------- class Cliente { int llegada;
public Cliente(int l) { llegada = l; } public int Llegada { get { return(llegada); } } }
IIC 1102 Pgina: 11 Simulacin Computacional con C# Rodrigo Sandoval U. // ---------------------------------------------------------------- // Clase Cola // Representa la cola que se forma frente a la caja. Almacena todos // los clientes ingresados con su respectivo instante de llegada // ---------------------------------------------------------------- class Cola { const int MAX = 30; Cliente[] clientes; int cantidad = 0; string archivo = "clientes.dat";
public Cola() { clientes = new Cliente[MAX]; // Dimensionamiento
StreamReader sr; try { sr = new StreamReader(archivo); } catch (Exception e) { Console.WriteLine("Error al abrir \"{0}\"\n{1}", archivo, e.ToString()); return; }
string linea = sr.ReadLine(); while(linea != null) { Agregar(int.Parse(linea)); linea = sr.ReadLine(); } sr.Close(); }
// Agregar(): dado un instante de llegada 'l', lo agrega a la cola public void Agregar(int l) { if(cantidad<MAX) clientes[cantidad++] = new Cliente(l); }
// Primero(): devuelve el primer cliente en la cola public Cliente Primero() { if(cantidad>0) return(clientes[0]); else { Cliente vacio = new Cliente(0); return(vacio); } }
// Atender(): atiende al primer cliente de la cola, sacndolo de ella public void Atender() { if(cantidad>0) { for(int i=1; i<cantidad ; i++) clientes[i-1] = clientes[i]; cantidad--; } }
public int Cantidad { get { return(cantidad); } } }
// ---------------------------------------------------------------- // Clase Principal // ---------------------------------------------------------------- class Principal { static void Main() { int reloj = 0; // reloj contador de minutos Cola cola = new Cola(); // Instancia la cola de clientes int esperamax = 0; int cantclientes = cola.Cantidad; // Se registra la cantidad total de clientes
Console.WriteLine("Procesando...");
// Proceso simulacin involucra 30 min o hasta que se acaben los clientes while(reloj<=30 && cola.Cantidad>0) { Cliente c = cola.Primero();
if(reloj<c.Llegada) reloj = c.Llegada; // Se avanza reloj al primero IIC 1102 Pgina: 12 Simulacin Computacional con C# Rodrigo Sandoval U. else reloj++; Console.Write(" {0}", reloj);
3.2.2 Solucin 2.0 Evolucionando un poco el ejemplo anterior, esta segunda versin profundiza un poco en el uso de la clase Queue como apoyo al modelamiento de la cola de clientes que llegan al banco, de manera que la implementacin de la cola de clientes se muestra ms simple en cdigo. Particularmente, el enfoque de esta solucin, implementa la clase Cola, heredando de Queue, complementando algunos mtodos especiales para el contexto de este problema, en particular el constructor. IIC 1102 Pgina: 13 Simulacin Computacional con C# Rodrigo Sandoval U. Cdigo Fuente using System; using System.IO; using System.Collections;
// ---------------------------------------------------------------- // Clase Cliente // Representa un cliente, con su instante de llegada // ---------------------------------------------------------------- class Cliente { int llegada;
public Cliente(int l) { llegada = l; } public int Llegada { get { return(llegada); } } }
// ---------------------------------------------------------------- // Clase Cola (Hereda de Queue) // Representa la cola que se forma frente a la caja. Almacena todos // los clientes ingresados con su respectivo instante de llegada // ---------------------------------------------------------------- class Cola : Queue { string archivo = "clientes.dat";
public Cola() { StreamReader sr; try { sr = new StreamReader(archivo); } catch (Exception e) { Console.WriteLine("Error al abrir \"{0}\"\n{1}", archivo, e.ToString()); return; }
string linea = sr.ReadLine(); while(linea != null) { Enqueue(new Cliente(int.Parse(linea))); linea = sr.ReadLine(); } sr.Close(); }
// Primero(): devuelve el primer cliente en la cola public Cliente Primero() { if(Count>0) return( (Cliente) Peek() ); else return(new Cliente(0)); }
// Atender(): atiende al primer cliente de la cola, sacndolo de ella public void Atender() { if(Count>0) Dequeue(); }
public int Cantidad { get { return(Count); } } }
// ---------------------------------------------------------------- // Clase Simulacion // ---------------------------------------------------------------- class Simulacion { int atendidos = 0; int esperamax = 0; int encola = 0;
public void Simular(int tiempo) { int reloj = 1; // reloj contador de minutos Cola cola = new Cola(); // Instancia la cola de clientes
IIC 1102 Pgina: 14 Simulacin Computacional con C# Rodrigo Sandoval U. // Proceso dura 30 minutos o hasta que se acaben los clientes while(reloj<=tiempo && cola.Cantidad>0) { Cliente c = cola.Primero();
if(reloj<c.Llegada) reloj = c.Llegada; // Se avanza reloj al primero else reloj++; Console.Write(" {0}", reloj);
public int Atendidos { get { return(atendidos); } } public int EsperaMax { get { return(esperamax); } } public int EnCola { get { return(encola); } } }
// ---------------------------------------------------------------- // Clase Principal // ---------------------------------------------------------------- class Principal { static void Main() { Simulacion s = new Simulacion(); s.Simular(30); // Efecta el proceso completo de simulacin
// Al final, indica los valores registrados Console.WriteLine("\nPersonas atendidas: {0}", s.Atendidos); Console.WriteLine("Espera mxima: {0}", s.EsperaMax); Console.WriteLine("Personas en Cola: {0}", s.EnCola);
Console.Write("Presione ENTER..."); Console.ReadLine(); } } 3.2.3 Solucin 3.0 En esta tercera versin del mismo caso de simulacin ofrece algunas diferencias al problema original. En primer lugar, la llegada de los clientes se mide en horas absolutas (hh:mm) y no en una referencia relativa de minutos. Por otro lado, la llegada de los clientes no se conoce y se determina en forma aleatoria. En cada instante de simulacin podrn llegar entre 0 y 2 clientes. La tercera diferencia, relacionada con la implementacin, es que se simplifica la definicin de la cola de clientes (utilizando directamente la clase Queue). Dado el uso de minutos en la forma hh:mm, se aprovechar la clase DateTime, identificando para cada cliente el instante de llegada. A la vez, el control de la evolucin del tiempo de la simulacin, tambin tomar el mismo tipo de objeto para ir contabilizando los minutos en la forma hh:mm. Para representar la unidad relevante de tiempo se utilizar un objeto de tipo TimeSpan, como un tick. Cdigo Fuente using System; using System.IO; using System.Collections;
// ---------------------------------------------------------------- // Clase Cliente // Representa un cliente, con su instante de llegada // ---------------------------------------------------------------- class Cliente { DateTime horallegada;
public Cliente(DateTime hl) { horallegada = hl; }
public DateTime HoraLlegada { get { return(horallegada); } } }
IIC 1102 Pgina: 15 Simulacin Computacional con C# Rodrigo Sandoval U. // ---------------------------------------------------------------- // Clase Simulacion // ---------------------------------------------------------------- class Simulacion { int atendidos = 0; int maxespera = 0;
public void Procesar() { DateTime reloj = new DateTime(2000,1,1,13,30,0,0); DateTime horafin = new DateTime(2000,1,1,14,00,0,0); TimeSpan tick = new TimeSpan(0,1,0); Random rn = new Random(DateTime.Now.Millisecond); Queue cola = new Queue();
while( reloj <= horafin ) { int clientes = rn.Next(0,3); for(int i=0; i<clientes; i++) cola.Enqueue(new Cliente(reloj)); Console.WriteLine("{0}:{1}, llegaron {2} clientes a una cola con {3}", reloj.Hour, reloj.Minute, clientes, cola.Count);
if(cola.Count>0) { // Siempre verificar largo de la cola antes de procesar. Cliente sale = (Cliente) cola.Dequeue(); atendidos++; if(maxespera < (reloj.Minute - sale.HoraLlegada.Minute)) maxespera = (reloj.Minute - sale.HoraLlegada.Minute); }
reloj += tick; } }
public int Atendidos { get { return(atendidos); } } public int MaxEspera { get { return(maxespera); } } }
// ---------------------------------------------------------------- // Clase Principal // ---------------------------------------------------------------- class Principal { static void Main() { Simulacion sim = new Simulacion();
IIC 1102 Pgina: 16 Simulacin Computacional con C# Rodrigo Sandoval U. 3.3 Simulacin de las Colas en un Supermercado En este ejemplo se muestra una simulacin que modela las colas que se forman en las cajas de un supermercado. El desarrollo de este ejemplo es informal, en el sentido de que no se basa en formalismos tericos para desarrollar el modelo. 3.3.1 Definicin del Problema Un supermercado recibe una cantidad regular de clientes diariamente, los cuales traen consigo una lista de los productos que van a comprar. Los clientes buscan sus productos en los estantes y pasan de inmediato a la caja que ms les convenga (en la que deban esperar menos en la fila). Una vez que han pagado se retiran del local. Para determinar cul es la caja ms conveniente, los clientes miran las compras que llevan los clientes en la cola, y eligen aquella caja con menos productos delante de ellos (como es natural). 3.3.2 Caractersticas del Modelo El modelo de simulacin que se emplear hace ciertas suposiciones sobre el comportamiento del sistema: Los clientes llegan al supermercado segn una tasa regular todos los das, y siguiendo un comportamiento de compras tambin regular. Un cliente se demora un tiempo constante en ubicar cada uno de los productos que comprar. Las cajeras pasan por el lector de barras los productos a un ritmo constante, es decir, una determinada cantidad de productos por minuto. Una vez que un cliente elige una caja en la que har fila, no se mover a otra. Se considera despreciable el tiempo que le toma al cliente pagar por sus compras y recibir su vuelto. La unidad de tiempo discreto que se emplear en la simulacin es equivalente a un minuto, descartando las tareas que puedan llevarse a cabo en fracciones restantes. Por ejemplo, si a un cajero le toma 10 segundos pasar los artculos de un cliente, el resto de ese minuto lo desperdiciar y no lo emplear atendiendo a otro cliente. El modelo se centrar en la simulacin del tiempo, ejecutando en cada unidad discreta de tiempo las actividades propias del supermercado y los clientes: Se verificar cules clientes han terminado de buscar sus productos y se les colocar en la fila de la caja. Cada cajera atender al primer cliente en la fila, y le pasar tantos productos como pueda en una unidad de tiempo. 3.3.3 Mediciones Requeridas Con fines estadsticos, es necesario guardar la visin que tuvo cada cliente al llegar a la caja, es decir, cuntos productos tienen los clientes que estn delante de l, y cuntos son estos clientes. Esto se llevar a cabo en forma acumulativa con ayuda de la clase, de manera que sea posible obtener promedios al final de la simulacin. Adems, resulta valioso almacenar los valores mximos, tanto para el tiempo de espera como para el largo de cola en cada caja. IIC 1102 Pgina: 17 Simulacin Computacional con C# Rodrigo Sandoval U. 3.3.4 Solucin Los clientes del supermercado se representarn mediante una clase Cola, en donde cada elemento corresponder con un cliente. Para cada cliente se almacenar: o Hora de llegada al supermercado. o Cantidad de productos que pretende comprar (generado aleatoriamente). hh:mm 1 compras1 Orden de Llegada 1 4 hh:mm 2 compras2 hh:mm 3 compras3 hh:mm 4 compras4
Las cajas se representarn tambin como una clase, el cual ofrece en su interfaz funciones de mucha utilidad, como determinar la caja con menos productos para que un cliente se pueda ubicar en ella. El nico dato que es necesario almacenar es la cantidad de productos que lleva cada uno de los clientes que hacen fila en las cajas. compras1 compras2 comprasN . . . Caja1 Caja2 compras1 compras2 comprasN . . . CajaN compras1 compras2 comprasN . . .
IIC 1102 Pgina: 18 Simulacin Computacional con C# Rodrigo Sandoval U. Por otra parte, ser necesario llevar constancia del tiempo actual (hora), para saber en qu momento los clientes pasarn a las cajas y cmo irn evolucionando las colas al cumplirse cada unidad de tiempo. De los resultados arrojados por estas estadsticas dependern los posibles cambios de configuracin que deban llevar a cabo los administradores del negocio. Por ejemplo, el aumento o disminucin de cajas disponibles, la reubicacin de los productos para que los clientes pasen menos tiempo ubicndolos, la capacitacin de las cajeras para que pasen ms productos por minuto por el lector de barras, etc. Entradas del Programa Los datos de los clientes se leen desde un archivo de entrada, llamado clientes.txt. El archivo tiene un formato riguroso. En la primera lnea se indica el nmero de clientes que concurrir al supermercado en el da, seguido de una lnea por cada uno de estos clientes. Cada una de las lneas de clientes est compuesta por dos enteros que indican la hora de llegada al supermercado (hora y minutos). A modo de ejemplo se incluye aqu un archivo de entrada, que considera 25 clientes. 25 10 01 10 05 10 05 10 05 10 05 10 05 10 05 10 07 10 08 10 08 10 10 10 12 10 15 10 20 10 22 10 22 10 22 10 22 10 22 10 22 10 35 10 45 10 50 10 50 10 55 El nmero de cajas que se desea emplear se pregunta como primer paso dentro del programa. Desarrollo de la solucin Para esta solucin, los objetos relevantes son: - Cliente. Representado por una clase cuyos atributos son: la hora de llegada (de tipo DateTime) y la cantidad de compras (int). Estos valores son pasados como parmetros al constructor y adicionalmente se definen las propiedades que dan acceso a los dos atributos privados del objeto Cliente. - Cajas. Un objeto ms complejo, que maneja un arreglo de colas de caja y ofrece una serie de mtodos que resuelven las preguntas ms requeridas, como cul es la caja con la cola ms corta? cuntos productos hay en la caja N? adems de procesar cada cola en una unidad de tiempo de simulacin. IIC 1102 Pgina: 19 Simulacin Computacional con C# Rodrigo Sandoval U. - Estadstica. Un objeto que guarda los valores numricos que se van obteniendo por el proceso de atencin de las cajas y que finalmente sirve para mostrar en pantalla los resultados estadsticos medidos durante la simulacin. - La cola de llegada de los clientes al supermercado se maneja como un objeto de tipo Queue y se incluye la lgica de inicializacin de esta cola al leer los datos que vienen en el archivo de llegadas. El procesamiento de este archivo va creando objetos de tipo cliente, tomando la hora y minutos que indica la lnea respectiva del archivo y tambin generando un nmero aleatorio de productos a comprar, por medio de la clase Random.
Cdigo Fuente Solucin using System; using System.IO; using System.Collections;
class Cliente { private DateTime dt; private int compras;
public Cliente(int hora, int minuto) { dt = new DateTime(DateTime.Now.Year,DateTime.Now.Month,DateTime.Now.Day, hora,minuto,0,0); compras = 0; }
public void Imprimir() { Console.WriteLine("Hora: {0} - compras: {1}",dt,compras); }
public DateTime HoraRegistro { get { return dt; } }
if(Clientes.Count == 0) break; cli = (CRegistro)Clientes.Dequeue(); Cajas.Insertar(cli.registro_compra); } Cajas.Atender(); IIC 1102 Pgina: 22 Simulacin Computacional con C# Rodrigo Sandoval U. DateTime d = dt.AddMinutes(1); dt = d; }
Console.WriteLine("\n\n\t\t-=Estadistica=-\n\n"); int valor = (EsperaTotal / 3) / NumClientes; int min = valor; int seg = ((valor-min)*60); Console.WriteLine("\tTiempo de espera Promedio (mm:ss) -> {0}:{1}",min,seg);
valor = (EsperaMax / 3); min = (int)valor; seg = (int) ((valor-min)*60); Console.WriteLine("\tTiempo de Espera Maximo (mm:ss) -> {0}:{1}",min,seg);
Console.WriteLine("\tLargo de la Cola en las Cajas (Promedio/Maximo):"); for(int i=0 ; i<cajas ; i++) Console.WriteLine("\t\tCaja n{0}: {1} / {2}",i, Estadistica[i].LargoT,Estadistica[i].LargoM);
Console.Write("Presione ENTER ..."); Console.ReadLine(); } }
Ejemplos de ejecucin (varias configuraciones) Con 1 caja: -=Estadistica=-
Tiempo de espera Promedio (mm:ss) -> 29:0 Tiempo de Espera Maximo (mm:ss) -> 52:0 Largo de la Cola en las Cajas (Promedio/Maximo): Caja n0: 44 / 2 Con 2 cajas: -=Estadistica=-
Tiempo de espera Promedio (mm:ss) -> 29:0 Tiempo de Espera Maximo (mm:ss) -> 57:0 Largo de la Cola en las Cajas (Promedio/Maximo): Caja n0: 6 / 2
Caja n1: 50 / 3 Con 4 cajas: -=Estadistica=-
Tiempo de espera Promedio (mm:ss) -> 26:0 Tiempo de Espera Maximo (mm:ss) -> 46:0 Largo de la Cola en las Cajas (Promedio/Maximo): Caja n0: 12 / 4 Caja n1: 12 / 3 Caja n2: 12 / 4 Caja n3: 15 / 4
Modificaciones propuestas IIC 1102 Pgina: 23 Simulacin Computacional con C# Rodrigo Sandoval U. Como se puede ver en los ejemplos de ejecucin, la simulacin arroja algunos valores estadsticos que pueden ser de utilidad para el administrador del supermercado: tiempos de espera de los clientes y largos de cola en las cajas. Sin embargo, la experimentacin es an algo engorrosa, pues cada vez que se quieren ver los resultados para una determinada configuracin, es necesario ejecutar de nuevo el programa y registrar los resultados. Una posible modificacin al programa planteado es hacer que por s mismo busque la mejor configuracin, de acuerdo a parmetros dados por el usuario. Por ejemplo, Cuntas cajas son necesarias para que los clientes no deban esperar ms de 1 minuto?. Para lograr esto, el cuerpo de la simulacin se debe convertir en un mtodo o funcin que reciba como argumento el nmero de cajas y retorne el tiempo de espera promedio (actualmente se enva por la consola). El algoritmo principal (Main) har llamados sucesivos a esta nueva funcin (mediante un ciclo), pasndole como argumento distintos valores para el nmero de cajas en forma incremental (primero 2, luego 3, etc.), hasta que se llegue al tiempo de espera propuesto por el usuario (1 minuto). Otra caracterstica que podra resultar muy til es permitir la simulacin por perodos distintos al da completo. Por ejemplo, es bien sabido que las horas de mayor saturacin en el supermercado se dan al final de la tarde. Sera til que el administrador del supermercado pudiera determinar cuntas cajas requiere para cada perodo del da en forma independiente. Actualmente los datos de las horas de muy alta y muy baja afluencia estn alterando los promedios arrojados. Para lograr esto el programa debera pedir un rango de horas y ejecutar la simulacin nicamente con los datos de entrada que correspondan con el rango especificado. Adems, dependiendo de la hora del da el nmero de productos que llevan los clientes podra variar. Para lograr esto bastara con cambiar la generacin aleatoria de la cantidad de productos para que dependiera de la hora en la que se est comprando. Finalmente, podra ser interesante lograr que la hora de llegada de los clientes se genere en forma aleatoria, de modo que podamos suprimir el archivo de entrada y lo nico que deba dar el usuario es el nmero de clientes y la cantidad de cajas que debern emplearse para la simulacin. La planificacin y la implementacin de estas modificaciones se dejan como ejercicio al estudiante.
3.4 Simulacin de una Plaza de Peaje Este ejemplo en particular se present como trabajo personal dentro de un curso. Cada alumno, contando slo con ejemplos como los anteriores y la explicacin que se indica a continuacin. Este ejemplo se centra en implementar una plaza de peaje de la carretera, donde se tienen distintas casetas abiertas para atencin y en el tiempo van llegando autos a ser atendidos. Una plaza de peaje est compuesta de distintas casetas que atienden a los autos que llegan por cada lado de la carretera. Los autos deben pagar una tarifa que depende de la hora, y segn esa tarifa, la tasa de atencin de la caseta puede aumentar o disminuir. El propsito del programa es determinar la cantidad ptima de casetas abiertas y atendiendo para dar un servicio adecuado a los vehculos al menor costo. Esta particularidad le impone un factor especial al ejemplo, ya que ms que slo ejecutar una simulacin del funcionamiento de la plaza de peaje, se toman los datos obtenidos de una simulacin completa y se usan para cambiar los parmetros que determinan el escenario de la siguiente simulacin (en particular la cantidad de casetas abiertas). De tal manera, se evalan diferentes escenarios y se determina cul de ellos ofrece la mejor relacin costo/ingreso. Este proceso informal de optimizacin se refleja en el algoritmo principal (Main). 3.4.1 Definicin del Problema En detalle el funcionamiento de la simulacin considera lo siguiente: IIC 1102 Pgina: 24 Simulacin Computacional con C# Rodrigo Sandoval U. 3.4.1.1 El Tiempo de Simulacin El periodo a simular consta de dos horas, desde las 17:00 a las 19:00 de un da viernes. Cada unidad de tiempo de simulacin es de 1 minuto. A las 18:00 - la mitad del tiempo de simulacin - se cambia la tarifa de peaje, con lo cual tambin cambia la tasa de atencin. Estos dos valores se explican ms adelante. 3.4.1.2 Las Casetas Hay un total de 20 casetas construidas, de las cuales en una simulacin dada, el total de ellas o slo una parte estarn atendiendo (al menos dos casetas siempre, una para cada direccin). De las abiertas, la mitad est atendiendo a los autos que llegan por el sur y las otras a los que llegan por el norte. La cantidad de casetas que atienden a cada lado tambin es fijo para cada simulacin, pero es el parmetro a ir ajustando para determinar la cantidad ptima. El costo fijo de atencin por caseta es de $50.000 por cada periodo de simulacin, lo que permite calcular los costos. En cada caseta siempre habr una cola que tiene 0 ms autos. Cada auto que llegue a la plaza de peaje, por cualquier direccin, seleccionar la caseta cuya cola sea la ms corta, o bien la primera si todas son iguales. Tarifa de peaje: en la primera hora la tarifa es de $1.200 por vehculo, y en la segunda hora es de $2.000. La tasa de atencin en la caseta es de: o 2 autos por minuto cuando la tarifa es baja (ya que se cuenta el tiempo para dar vuelto en monedas). o 4 autos por minuto cuando la tarifa es alta (ya que no se requiere dar vuelto en monedas). o En cualquiera de los dos casos se atender a la cantidad de autos correspondiente a la tasa del horario actual, y si quedan menos autos, slo se atender a los que haya. 3.4.1.3 Los Vehculos Existe un registro de los autos que llegan por el sur y por el norte respectivamente, identificando la hora (en hh y mm) y la cantidad de autos que llegan en ese minuto. Los del norte vienen en el archivo norte.txt y los del sur en sur.txt. Estos archivos asumen conocidos y para este ejemplo se pueden inventar datos. En cada archivo se registra una lnea por minuto de datos, la cual tiene en orden: hh mm cantidadautos. Si en un minuto dado no se registraron autos (cantidadautos=0), esa lnea no viene en el archivo. En la correccin de la tarea se pueden utilizar otros archivos, por lo que no asuma que esos sern siempre los archivos. 3.4.1.4 El Proceso de Optimizacin El proceso de optimizacin no se enfoca en las tcnicas formales de optimizacin matemtica, ya que ese enfoque no forma parte de este documento. Sin embargo, se busca lograr un punto denominad ptimo por medio de la evaluacin de los resultados tomando distintos escenarios de simulacin. Al comparar progresivamente los escenarios en torno a los costos e ingresos, se puede llegar a una combinacin ideal de casetas abiertas que logren un nivel aceptable de tasa de atencin por vehculo. Para ello, el procedimiento (algoritmo) es el siguiente: Se comienza con el mnimo: 1 caseta abierta para los vehculos del norte y 1 para los del sur. Se efecta la simulacin completa y se miden los siguientes datos que deben mostrarse en pantalla. IIC 1102 Pgina: 25 Simulacin Computacional con C# Rodrigo Sandoval U. o Cantidad de cajas abiertas por cada lado. o Cantidad de autos atendidos por cada lado. o $ ingreso (cobro de peaje). o $ costos (casetas x costo fijo). o Mxima espera en minutos. Se aumenta en uno la cantidad de casetas abiertas por cada lado y se vuelve a simular. Las condiciones de trmino del proceso de optimizacin (que a su vez ejecuta varias simulaciones) son: o El Tiempo Mximo de espera por atencin debe ser menor que un valor en minutos dado por el usuario al comienzo de todo el proceso. o Se analiza si la utilidad (ingresos-costos) disminuye o aumenta. Dentro de la restriccin de Tiempo de Espera Mxima, se busca el menor costo posible (el mnimo de casetas abiertas). o El mximo de casetas es el de la cantidad construida: 20 en total (10 para cada lado). 3.4.2 Solucin Cdigo Fuente using System; using System.IO; using System.Collections;
//------------------------------------------------------------------------------------ // Clase: Auto // Representa un auto cuyos datos relevantes son nicamente los de la hora de llegada //------------------------------------------------------------------------------------ class Auto { DateTime horallegada; // Atributo relevante: la hora de llegada.
public Auto(int hh, int mm) { // Transforma la hora y minutos de llegada en un tipo DateTime horallegada = new DateTime(DateTime.Now.Year, DateTime.Now.Month,
DateTime.Now.Day, hh, mm, 0, 0); }
public DateTime HoraLlegada { get { return(horallegada); } } public int Hora { get { return(horallegada.Hour); } } public int Minutos { get { return(horallegada.Minute); } }
// Al imprimir una instancia de Auto, se imprime la hora de llegada public override string ToString() { return(horallegada.ToString()); } }
//------------------------------------------------------------------------------------ // Clase: Caseta // Hereda de Queue, por lo cual la misma caseta representa una cola de vehculos que // se atienden en dicha caseta. Adems, registra el tiempo mximo de espera durante // toda la operacin de la caseta, contabiliza los autos atendidos, y va sumando // el cobro de peajes segn tarifa por auto atendido. //------------------------------------------------------------------------------------ class Caseta : Queue { int maxespera = 0; int procesados = 0; int ingresos = 0;
// AtenderPrimero(): toma al primero de la cola, y si est en la hora adecuada // lo atiende, registrando su tiempo de espera y contabilizndolo public int AtenderPrimero(DateTime lahora, int valorpeaje) { if(Count<=0) return(-1); // Si no hay autos en cola, no se atiende a nadie. Auto a = (Auto) Peek(); // Se mira el primero de la cola IIC 1102 Pgina: 26 Simulacin Computacional con C# Rodrigo Sandoval U. if( a.HoraLlegada<=lahora ) {// Si lleg antes de la hora actual TimeSpan ts = lahora - a.HoraLlegada; // Tiempo de espera Dequeue(); // Se saca de la cola procesados++; // Se contabiliza ingresos += valorpeaje; // Suma el pago por el peaje al total acum. return(ts.Hours*60 + ts.Minutes); // Retorna el valor total de minutos } return(-1); // Si no se atendi ninguno, retorna <0 para no contabilizar. }
// Dos versiones para Agregar Auto a la cola (Queue) de la caseta. public void AgregarAuto(int hh, int mm) { Enqueue((Object) new Auto(hh,mm)); } public void AgregarAuto(Auto a) { Enqueue((Object) a); }
// Propiedades de Caseta public int CantidadAutos { get { return(Count); } } public int AutosProcesados { get { return(procesados); } } public int Ingresos { get { return(ingresos); } } public int MaxEspera { get { return(maxespera); } set { if(value>maxespera) maxespera = value; } } // PrimerAuto: revisa el primer auto sin sacarlo de la cola public Auto PrimerAuto { get { return( (Auto) Peek()); } } }
//------------------------------------------------------------------------------------ // Clase: Plaza // Representa una coleccin de casetas o plaza de peaje, atendiendo DIR colas de // autos que llegan. Si bien el ejemplo habla de dos extremos por los que llegan // autos, se maneja un tributo DIR que representa la cantidad de extremos en forma // genrica, permitiendo al ejemplo el potencial de ser extendido. // El valor de casetasenuso se maneja referenciando una nica direccin. Si se abren // dos casetas por cada direccin, entonces ese valor es 2, totalizando 4 casetas abiertas. //------------------------------------------------------------------------------------ class Plaza { const int DIR = 2; // Dos direcciones: Norte y Sur Caseta[,] casetas; // Matriz de casetas. N casetas por M direcciones (2 dir: N y S). int casetasenuso;
// Constructor, prepara la plaza indicando cuntas casetas se utilizarn. // No requiere validar un mximo de casetas en uso, ya que es indiferente a este nivel public Plaza(int enuso) { casetas = new Caseta[enuso,DIR]; // Dimensiona la matriz de casetas
for(int dir=0; dir<DIR; dir++) for(int i=0; i<casetas.GetLength(0); i++) casetas[i,dir] = new Caseta(); // Instancia c/celda de la matriz. casetasenuso = enuso; }
// MejorCaseta(): segn la direccin dada (0: norte; 1: sur) // : indica cul es la caseta con la fila ms corta public Caseta MejorCaseta(int direccion) { int mincola = casetas[0,direccion].CantidadAutos; int mincaseta = 0; for(int i=0; i<casetasenuso; i++) if( mincola > casetas[i,direccion].CantidadAutos ) { mincola = casetas[i,direccion].CantidadAutos; mincaseta = i; } return( casetas[mincaseta,direccion] ); // Retorna la caseta elegida. }
public int CasetasEnuso { get { return(casetasenuso); } set { if( value >= 1 ) casetasenuso = value; } // Mnimo de 1 caseta }
// ProcesarMinuto(): atiende autos en las casetas que alcanzan en el minuto actual, IIC 1102 Pgina: 27 Simulacin Computacional con C# Rodrigo Sandoval U. // : de acuerdo a tasa dada, tomando valor del peaje en ese minuto. public void ProcesarMinuto(DateTime lahora, int tasa, int valorpeaje) { for(int dir=0; dir<DIR; dir++) // Para ambas direcciones (norte y sur). for(int i=0; i<casetasenuso; i++) // Para todas las casetas abiertas. for(int j=0; j<tasa; j++) // Los autos que alcanzan en un min. if(casetas[i,dir].CantidadAutos>0) { // Calcula espera del atendido. Si no hay nadie en la cola // no se atiende a nadie, la espera es -1, // que no es asignada a MaxEspera. // Validaciones estn en AtenderPrimero() y de MaxEspera. int espera = casetas[i,dir].AtenderPrimero(lahora, valorpeaje); casetas[i,dir].MaxEspera = espera; } }
// EsperaMax: Calcula la Mxima espera registrada en las cajas. public int EsperaMax { get { int max=0; for(int dir=0; dir<DIR; dir++) for(int i=0; i<casetasenuso; i++) if(max<casetas[i,dir].MaxEspera) max = casetas[i,dir].MaxEspera; return(max); } }
public int TotalIngresos { get { int total = 0; for(int dir=0; dir<DIR; dir++) for(int i=0; i<casetasenuso; i++) total += casetas[i,dir].Ingresos; return(total); } }
public int TotalAutos { get { int total = 0; for(int dir=0; dir<DIR; dir++) for(int i=0; i<casetasenuso; i++) total += casetas[i,dir].AutosProcesados; return(total); } }
public int AutosEnCola { get { int total = 0; for(int dir=0; dir<DIR; dir++) for(int i=0; i<casetasenuso; i++) total += casetas[i,dir].CantidadAutos; return(total); } }
IIC 1102 Pgina: 28 Simulacin Computacional con C# Rodrigo Sandoval U.
//------------------------------------------------------------------------------------ // Clase: ColaLlegada // Representa la cola de autos de llegada por una direccin especfica. //------------------------------------------------------------------------------------ class ColaLlegada : Queue { StreamReader sr;
// Constructor: Abre archivo. Lee todos registrndolos en una cola de autos de llegada public ColaLlegada(string filename) { try { sr = new StreamReader(filename); } catch(Exception e) { Console.WriteLine("Error al abrir {0}\n{1}", filename, e.ToString()); return; }
string linea = sr.ReadLine(); int contador = 0; while(linea!=null) { // Procesa el archivo completo contador++; string[] datos = linea.Split(); if(datos.Length != 3) { // Si no vienen 3 datos, avisa y termina el proceso Console.WriteLine("Error en formato del archivo de entrada: + lnea N {0} no tiene 3 datos", contador); sr.Close(); return; } int cant = int.Parse(datos[2]); // Lee cantidad de autos en min. en proceso for(int i=0; i<cant; i++) // Registra 1 elem. x c/auto en el min. en proc. Enqueue( (Object) new Auto(int.Parse(datos[0]), int.Parse(datos[1]))); linea = sr.ReadLine(); } sr.Close(); // Se cierra el archivo con datos. }
// Propiedades bsicas de la Cola de Llegada --> Se basan en los mtodos de Queue public Auto PrimerAuto { get { return( (Auto) Peek()); } } public int CantidadAutos { get { return(Count); } }
// Mtodos pblicos de la Cola de Llegada public void SacarPrimerAuto() { if(Count>0) Dequeue(); } }
//------------------------------------------------------------------------------------ // Clase: SimuladorPlaza // Se encarga de hacer una simulacin completa en un escenario dado por // las colas de los autos en llegada y de una cantidad determinada de casetas abiertas //------------------------------------------------------------------------------------ class SimuladorPlaza { Plaza p; ColaLlegada c1; ColaLlegada c2; const int TARIFA1 = 1200; const int TARIFA2 = 2000; const int TASA1 = 2; const int TASA2 = 4; const int COSTO = 50000;
public SimuladorPlaza(string file1, string file2, int casetas) { p = new Plaza(casetas); c1 = new ColaLlegada(file1); c2 = new ColaLlegada(file2); }
// Procesar(): Mtodo principal de la clase, que realiza (ejecuta) la simulacin public void Procesar() { // Se procesa el loop de simulacin principal DateTime HoraActual = new DateTime(DateTime.Now.Year, DateTime.Now.Month, IIC 1102 Pgina: 29 Simulacin Computacional con C# Rodrigo Sandoval U. DateTime.Now.Day, 17, 0, 0, 0); DateTime HoraCambio = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 18, 0, 0, 0); DateTime HoraFinal = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 19, 0, 0, 0); TimeSpan UnTick = new TimeSpan(0,1,0);
// Para ver en pantalla avance del proceso: Console.Write("Llegan "); p.Encabezado();
while( HoraActual<=HoraFinal ) { // Console.WriteLine(HoraActual); // Procesa los autos de la hora de llegada actual -> Norte int llegaron1 = 0; int llegaron2 = 0; while( (c1.CantidadAutos>0) && (c1.PrimerAuto.HoraLlegada<=HoraActual) ) { Caseta cas = p.MejorCaseta(0); cas.AgregarAuto(c1.PrimerAuto); c1.SacarPrimerAuto(); llegaron1++; } // Procesa los autos de la hora de llegada actual -> Sur while( (c2.CantidadAutos>0) && (c2.PrimerAuto.HoraLlegada<=HoraActual) ) { Caseta cas = p.MejorCaseta(1); cas.AgregarAuto(c2.PrimerAuto); c2.SacarPrimerAuto(); llegaron2++; } // Ahora procesa las colas int tasa = TASA2; int tarifa = TARIFA2; if( HoraActual < HoraCambio ) { tasa = TASA1; tarifa = TARIFA1; } // Console.Write("{0,2} {1,2} ", llegaron1, llegaron2); // p.MostrarResumen(); // OJO: En simulacin larga esto muestra demasiada info p.ProcesarMinuto(HoraActual, tasa, tarifa);
// Console.Write(" ", llegaron1, llegaron2); // p.MostrarResumen(); // OJO: En simulacin larga esto muestra demasiada info
HoraActual += UnTick; // Aumenta en un instante de simulacin } }
public int Costos { get { return(COSTO*p.CasetasEnuso*2); } } public int Ingresos { get { return(p.TotalIngresos); } } public int Resultado { get { return(Ingresos - Costos); } }
public int MaxEspera { get { return(p.EsperaMax); } } public int AutosAtendidos { get { return(p.TotalAutos); } } }
class CMain { public static void Main() { int casetasenuso = 0; int resultado = 0;
Console.Write("Ingrese tiempo de espera mximo razonable en minutos: "); int esperamax = int.Parse(Console.ReadLine()); int espera = 0; int minespera = 100; int optimocasetas = 2; int maxresultado = 0;
// Loop principal: realiza simulaciones y tiene la lgica de optimizacin. // En cada iteracin aumenta la cantidad de casetas en uso. // Ojo que se maneja un nmero de casetas por lado. // Los datos resultantes de cada simulacin de los pregunta al SimuladorPlaza. do { casetasenuso++; // Cantidad de casetas abiertas por lado SimuladorPlaza sp = new SimuladorPlaza("norte.txt","sur.txt", casetasenuso);
Console.WriteLine("\n==============================); IIC 1102 Pgina: 30 Simulacin Computacional con C# Rodrigo Sandoval U. Console.WriteLine("Nueva Simulacin\n=============================="); sp.Procesar(); resultado = sp.Resultado; espera = sp.MaxEspera; // Se imprimen en pantalla los datos pedidos: Console.WriteLine("\nResultados de la Simulacin); Console.WriteLine("=============================="); Console.WriteLine("Casetas : {0}\nAutos Atendidos: {1}\nMx. Espera: {2}", casetasenuso*2, sp.AutosAtendidos, espera); Console.WriteLine("Ingresos: {0:C}\nCostos: -{1:C}\nResultado: {2:C}", sp.Ingresos, sp.Costos, resultado);
// Registra el punto con espera menor que el mnimo dado. // Dado que siempre ser el de menor cantidad de casetas abiertas // este punto tambin es el de mayores ingresos. if( espera<=esperamax ) { minespera = espera; optimocasetas = casetasenuso; maxresultado = resultado; break; } } while(casetasenuso<10);
Console.Write("Presione ENTER ..."); Console.ReadLine(); } }
IIC 1102 Pgina: 31 Material preparado por Rodrigo Sandoval U en Mayo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.a Los ejemplos fueron adaptados y preparados por el MSR Lab, del DCC de la Escuela de Ingeniera de la PUC
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo XI Recursividad
1 RECURSIVIDAD................................................................................................................................................. 1 1.1 EJ EMPLO: NMEROS DE FIBONACCI................................................................................................................2 1.2 EJ EMPLO: OBTENCIN DEL MXIMO EN UN VECTOR DE ENTEROS...................................................................4 1.3 EJ EMPLO: FUNCIN PARA CALCULAR MDULO...............................................................................................5 1.4 EJ EMPLO: SOLUCIN DE UN LABERINTO.........................................................................................................7 1.4.1 Descripcin ............................................................................................................................................ 7 1.4.2 Diseo .................................................................................................................................................... 7
Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Recursividad Existen muchas funciones matemticas cuyos argumentos son nmeros naturales, que pueden definirse de manera recursiva. Esto quiere decir que el valor de la funcin para el argumento n puede definirse en trminos del argumento n-1 (o alguno anterior). En este tipo de definiciones siempre existir un caso base a partir del cual parte la definicin, el cual normalmente es el valor de la funcin en cero o en uno, aunque no necesariamente debe ser as. Por ejemplo, el factorial puede definirse de manera recursiva de la siguiente manera:
Para definir una funcin en forma recursiva es necesario especificar: Caso(s) base: Donde la recursividad se detiene. Paso de recursin: Cmo se define un elemento distinto del caso base, en trminos de elementos anteriores. Usualmente los lenguajes de programacin permiten definir funciones de manera recursiva. La definicin recursiva para el factorial sera: int factorial(int n) { if ((n == 0) || (n == 1)) return(1); else return(n*factorial(n-1)); } Normalmente las definiciones recursivas pueden expresarse en forma no recursiva. Sin embargo, dependiendo del caso, el resultado puede ser ms confuso. Por ejemplo, un mtodo que calcula el factorial en forma iterativa sera: int factorial(int n) { int i, fact = 1;
for (i=2; i<=n; i++) fact = fact * i; return(fact); } Sin embargo, los algoritmos iterativos tienen una ventaja en cuanto al uso de memoria, si se comparan con los recursivos. La recursividad requiere que se guarde el estado de la ejecucin antes de cada llamado recursivo, implicando un gasto considerable de memoria. Es probable que, por esta razn, las versiones recursivas tengan mayores limitaciones al ejecutarse en un computador. La aplicacin de las definiciones recursivas puede ampliarse a una amplia gama de problemas, en los que la solucin ms natural puede ser la que se expresa de esta forma. Por ejemplo, para buscar un nmero en un vector (arreglo unidimensional de enteros) podemos tener una funcin que reciba como argumento el vector, el rango de bsqueda y el nmero buscado. El prototipo de esta funcin sera como: int busqueda(int[] vec, int inicio, int fin, int num) La funcin que quiere hacer la bsqueda hara el llamado indicando los rangos apropiados para el vector: Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 2 resultado = busqueda(vector, 0, N, x); La funcin busqueda() puede hacer su trabajo partiendo el vector en dos partes y llamndose a s misma en forma recursiva, de la siguiente manera:
El caso base sera cuando el vector que recibe la funcin busqueda() contiene un nico elemento. En este caso simplemente compara el elemento con el nmero buscado y retorna el valor apropiado. Ms adelante, en el captulo sobre Ordenamiento y Bsqueda, se tratar en detalle este algoritmo que recibe el nombre de Bsqueda Binaria. 1.1 Ejemplo: Nmeros de Fibonacci La Sucesin de Fibonacci es una secuencia de nmeros naturales, que empieza con 0 y 1, y cuyos siguientes trminos estn definidos como la suma de los dos anteriores:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
Algoritmo Recursivo Es bastante sencillo y natural definir la Sucesin de Fibonacci en forma recursiva:
Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 3 A partir de esta definicin, se puede escribir un mtodo que genere el trmino n-simo de la sucesin. En el siguiente ejemplo se presenta esta funcin, junto con un programa de prueba que pide un nmero entero al usuario y determina el correspondiente trmino de la sucesin. /*************************************************************************** * Programa que calcula, de forma recursiva, el trmino n-simo de la * sucesin de fibonacci, para un valor n dado por el usuario. ***************************************************************************/ using System;
public class Ccopy { /*************************************************************************** * Ejemplo: Clculo recursivo del n-esimo termino de fibonacci * Por definicin: * Fibonacci(0) = 0 * Fibonacci(1) = 1 * Fibonacci(n) = Fibonacci(n - 1) + Fibonacci(n - 2) ***************************************************************************/ public static double Fibonacci(int n) { switch (n) { case 0 : { return 0; } case 1 : { return 1; } default: { return Fibonacci(n - 1) + Fibonacci(n - 2); } } }
public static void Main() { Console.Write("Ingrese el numero a calcular: "); int a = int.Parse(Console.ReadLine()); Console.WriteLine("El nmero fibonacci solicitado es: {0}", Fibonacci(a)); } }
Ejemplo de Ejecucin Ingrese el valor de n: 10 El termino 10 de Fibonacci es: 55
Ingrese el valor de n: 20 El termino 20 de Fibonacci es: 6765
Algoritmo Iterativo En contraposicin a la implementacin recursiva que se present anteriormente, se ofrece aqu una versin iterativa de la funcin para calcular el n-simo trmino de la Sucesin de Fibonacci. Para implementar el algoritmo en forma iterativa, es necesario guardar en variables los valores para los dos trminos anteriores de la sucesin, para poder llevar a cabo el clculo del siguiente. Una vez hecho esto se actualizan los valores anteriores para preparar el siguiente clculo (siguiente iteracin). Compare ambas funciones. Aparentemente la versin recursiva es ms limpia y clara (fcil de entender) que su contraparte iterativa. Cul es su opinin?. Se mantiene el mismo programa de prueba empleado anteriormente. using System;
public class Ccopy { public static double Fibonacci(int n) { int i; double Fibi = 0, Fibn1, Fibn2; switch(n) { case 0 : { return 0; } case 1 : { return 1; } default : { Fibn2 = 0; /* Fibonacci(n - 2) */ Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 4 Fibn1 = 1; /* Fibonacci(n - 1) */ for (i = 2; i <= n; i++) { Fibi = Fibn1 + Fibn2; Fibn2 = Fibn1; Fibn1 = Fibi; } break; } } return Fibi; }
static void Main() { Console.Write("Ingrese el numero a calcular: "); int a = int.Parse(Console.ReadLine()); Console.WriteLine("El numero fibonacci solicitado es: {0}", Fibonacci(a)); } }
Experimento Sugerido Como se mencion al introducir la recursividad, la implementacin recursiva de un algoritmo normalmente consume ms memoria que su contraparte iterativa. Esto se debe a que es necesario guardar el estado actual de la ejecucin antes de cada llamado recursivo. Esto puede provocar limitaciones importantes en los programas que emplean funciones recursivas. Se sugiere probar los dos programas ofrecidos en esta seccin para valores altos (a partir de 20) y comparar los resultados obtenidos. Variantes Propuestas A manera de ejercicio pueden escribirse variantes de este programa, que empleen la funcin Fibonacci, ya sea iterativa o recursiva: Programa que lee un nmero y dice si pertenece a la Sucesin de Fibonacci. Programa lee un nmero entero n y despliega en pantalla los primeros n trminos de la Sucesin de Fibonacci. En este caso, existe alguna ventaja en usar una versin sobre la otra?, por qu?.
1.2 Ejemplo: Obtencin del mximo en un vector de enteros En este ejemplo mostraremos una funcin recursiva para encontrar el valor mximo en un vector de nmeros enteros. Se incluye un programa de prueba que recibe los valores del vector del usuario y despliega el valor mximo calculado mediante la funcin mencionada. Algoritmo La definicin recursiva de la funcin para obtener el mximo puede hacerse como: Si el vector tiene un nico elemento, ese elemento es el mximo (caso base). Si el valor en la posicin inicial del vector es mayor que el mximo del resto del vector, entonces el valor de la primera posicin es el mximo global. Si el valor en la posicin inicial del vector es menor que el mximo del resto del vector, entonces el mximo global ser el mximo en el resto del vector. Escrito en palabras simples: Para encontrar el mximo en un vector, basta comparar el primer elemento con el mximo del resto del vector. Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 5 /*************************************************************************** * Funcin recursiva que obtiene el mximo en un vector de nmeros enteros. * Retorna el valor del mximo elemento dentro del vector. ***************************************************************************/ using System;
class CMax { public static int Maximo(int [] vector, int n) { int max, maxResto; if (n == 1) max = vector[0]; /* Caso base */ else { int [] vec = new int[vector.Length-1]; for(int i = 0; i < vec.Length; i++) vec[i] = vector[i+1];
maxResto = Maximo(vec, n-1); /* Maximo del resto del vector */ if (vector[0] > maxResto) max = vector[0]; else max = maxResto; } return(max); }
public static void Main() { Console.Write("Ingrese el numero de elementos: "); int [] vec = new int[Int32.Parse(Console.ReadLine())];
for(int i = 0; i < vec.Length; i++) { Console.Write("Ingrese el elemento n {0}: ",i); vec[i] = int.Parse(Console.ReadLine()); }
Ejemplo de ejecucin: Ingrese el nmero de elementos: 5 Elemento[0]: 6 Elemento[1]: 10 Elemento[2]: 8 Elemento[3]: 15 Elemento[4]: 12
Mximo: 15
1.3 Ejemplo: Funcin para calcular mdulo El operador binario mdulo obtiene el resto o residuo de la divisin de dos nmeros enteros. Es bastante sencillo definir en forma recursiva la operacin m md n. La idea es ir restando el divisor del dividendo y calculando de nuevo el mdulo, pues el resultado es el mismo. La recursividad se detiene cuando el divisor es mayor que el dividendo. En ese caso el resultado es el dividendo. La definicin sera: Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 6
A partir de esta definicin, se puede escribir una funcin en C que calcule m md n, con m y n como los parmetros de la funcin. En el siguiente ejemplo se presenta esta funcin, junto con un programa de prueba que pide dos nmeros enteros al usuario, calcula la operacin y muestra en pantalla el resultado.
using System;
public class CModulo { public static int modulo(int m, int n) { if (m < n) return(m); else return( modulo( (m-n) , n) ); }
public static void Main() { Console.Write("Ingrese el valor de m: "); int m = int.Parse(Console.ReadLine()); Console.Write("Ingrese el valor de n: "); int n = int.Parse(Console.ReadLine()); Console.WriteLine("{0} mod {1} es: {2}", m, n, modulo(m,n)); } }
Ejemplo de ejecucin: Ingrese el valor de m: 10 Ingrese el valor de n: 3 10 mod 3 es: 1
Ingrese el valor de m: 3 Ingrese el valor de n: 5 3 mod 5 es: 3
Ingrese el valor de m: 3 Ingrese el valor de n: 3 3 mod 3 es: 0
Ejercicio Propuesto De manera similar a como se defini recursivamente el operador mdulo es posible definir el operador para divisin entera, es decir, divisin sobre operandos enteros y cuyo resultado es entero (se ignoran los decimales). Se deja como ejercicio la definicin recursiva de este operador y la implementacin del mtodo correspondiente. Como programa de prueba puede emplearse el mismo que se emple para el mdulo con unos pocos cambios.
Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 7 1.4 Ejemplo: Solucin de un laberinto Se presenta un programa que resuelve laberintos en forma recursiva. El laberinto a resolver se representa mediante una matriz de caracteres. 1.4.1 Descripcin Se presenta un programa que resuelve laberintos en forma recursiva. El laberinto a resolver se representa mediante una matriz de caracteres, y su configuracin est dada por la inicializacin que se haga a dicha matriz. Por esto, para cambiar el laberinto ser necesario cambiar el cdigo del programa. Una vez que se haya introducido el concepto de archivo ser posible ampliar este programa para que sea ms til, almacenando distintas configuraciones de laberinto en distintos archivos. 1.4.2 Diseo 1. Definicin del problema Conceptualizacin: El problema se ubica en un contexto en el que se debe buscar una solucin a un laberinto con una entrada y una salida, y con movimientos vlidos en cuatro direcciones (no diagonales). En el caso de este ejemplo, el contexto est limitado a una aplicacin de computador, en la que el laberinto est representado mediante una matriz de nmeros enteros. Objetivo: Partiendo de la entrada del laberinto, sealar una ruta que nos gue hasta la salida. Por ejemplo, dado el siguiente laberinto (figura de la izquierda). Una solucin que permitira alcanzar el objetivo sera la ruta mostrada con asteriscos en la figura de la derecha.
Descripcin general de la solucin: El problema se resolver haciendo uso de la recursividad. La solucin se basa en una tarea o funcin que se llamar recursivamente para intentar solucionar el laberinto a partir de una posicin particular. Desde cualquier lugar dentro del laberinto se intentar resolverlo primero intentando hacia izquierda, luego a la derecha, luego arriba y finalmente abajo. Para hacer estos intentos se emplear la funcin recursiva. El procedimiento parte de la posicin de entrada. Se utilizarn marcas que sern dejadas en el camino para no intentar por caminos por los que ya se pas y, en particular, no volver atrs salvo si se determina que no hay solucin por el camino que se sigue hasta ahora. Elementos involucrados: No existen elementos externos involucrados en la bsqueda de la solucin. El nico elemento activo es el computador en s llevando a cabo su trabajo. En el problema participan tambin los siguientes elementos pasivos: la matriz que representa el laberinto la ubicacin de la entrada Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 8 la ubicacin de la salida
2. Conceptualizacin de la solucin Clases: Como se mencion, el laberinto estar representado mediante una clase que contiene una matriz de nmeros enteros: Lab. Adems, la posicin de la entrada en el laberinto estar dada por las coordenadas dentro de la matriz, representadas por las variables x0, y0, para la fila y la columna, respectivamente. De manera similar, la posicin de la salida del laberinto se guardar en xf, yf las cuales sern atributos de la clase. Cada posicin de la matriz puede estar en uno de tres estados: parte del muro (ladrillo) camino libre no visitado camino libre visitado La inicializacin de la matriz que se requiere, se establece con una configuracin de caracteres en cdigo ASCII, y corresponde al laberinto presentado en la figura del inicio. Los caminos estn formados de espacios libres (E's). Observe el contorno del laberinto, formado por L's, y los puntos de entrada y salida.
Mtodos de la Clase Lab Validate(f,c) Parmetros: fila y columna de la posicin. Valor de retorno: valor booleano que indica si la posicin es vlida. Descripcin: Esta funcin analiza una posicin dentro del laberinto, especificada por la fila y columna recibidas como parmetro, y deduce si es una posicin vlida para recorrer. Bsicamente debe verificar que no est fuera de los lmites del laberinto, que no se trate de una posicin en la que hay pared, y que no se trate de una posicin previamente visitada. Algoritmo:
1. Si la posicin dada est fuera del laberinto o si es pared o ya fue visitada 1.1. retornar FALSO 2. En caso contrario 2.1. retornar VERDADERO
Recorrer(f,c) Parmetros: fila y columna (fil y col) desde donde se empieza el recorrido. Valor de retorno: TRUE o FALSE que indica si se logr resolver el laberinto o no. Descripcin: Mtodo recursivo que recorre el laberinto a partir de una posicin dada por la fila y columna pasadas como parmetro y devuelve un valor bool que indica si se logr llegar a la salida. El caso base de la recursividad (condicin de trmino) es que las coordenadas correspondan con la salida del laberinto. En caso contrario, se procede a marcar la casilla y a intentar en las distintas direcciones (izquierda, derecha, arriba y abajo), asegurndose primero que en esa direccin haya una casilla valida (no ladrillo, no fuera del laberinto y no visitada). En caso en que ninguna direccin nos lleva a la salida, se desmarca la casilla actual (pues se va a retroceder) y se devuelve falso como valor de retorno. Las marcas sirven tambin para sealar la ruta que conforma la solucin, una vez alcanzada. Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 9 Algoritmo:
1. Inicialmente l i st o vale FALSO. 2. Se marca la casilla. 3. Si la posicin es el fin del laberinto. 3.1. Retornar VERDADERO. 4. Si no se ha solucionado (l i st o vale FALSO) y la posicin de la izquierda es vlida. 4.1. Llamar a r ecor r er recursivamente con la casilla de la izquierda como parmetro y guardar valor de retorno en l i st o, para ver si se resolvi el laberinto a partir de ah. 5. Si no se ha solucionado (l i st o vale FALSO) y la posicin de la derecha es vlida. 5.1. Llamar a r ecor r er recursivamente con la casilla de la derecha como parmetro y guardar valor de retorno en l i st o, para ver si se resolvi el laberinto a partir de ah. 6. Si no se ha solucionado (l i st o vale FALSO) y la posicin de arriba es vlida. 6.1. Llamar a r ecor r er recursivamente con la casilla de arriba como parmetro y guardar valor de retorno en l i st o, para ver si se resolvi el laberinto a partir de ah. 7. Si no se ha solucionado (l i st o vale FALSO) y la posicin de abajo es vlida. 7.1. Llamar a r ecor r er recursivamente con la casilla de abajo como parmetro y guardar valor de retorno en l i st o, para ver si se resolvi el laberinto a partir de ah. 8. Si no se logr resolver el laberinto en ninguna direccin (l i st o todava vale FALSO). 8.1. Quitar marca de la casilla (pues no formar parte del camino). 9. Retornar l i st o indicando si se pudo resolver o no el laberinto.
Display() Parmetros: no tiene Valor de retorno: no tiene Descripcin: Despliega en la pantalla el laberinto Algoritmo:
1. Iterar i por todas las filas 1.1. Iterar j por todas las columnas 1.1.1. Desplegar posicin i,j 1.2. Cambiar de lnea pues termin una fila
Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 10 3. Especificacin del Algoritmo Principal El algoritmo principal debe llamar a la tarea que recorre el laberinto, especificando como posicin la entrada: ( x0 , y0 ). Antes y despus de la resolucin se despliega el laberinto. La segunda vez incluir el camino que forma la solucin (las posiciones que fueron marcadas y no desmarcadas posteriormente). Algoritmo: 1. Desplegar el laberinto sin resolver 2. Recorrer desde la entrada del laberinto: ( x0 , y0 ) 3. Si se pudo resolver 3.1. Desplegar el laberinto una vez resuelto (con el camino) 4. Si no, desplegar un mensaje indicando que no hay solucin
4. Validacin del algoritmo La validacin de un algoritmo recursivo requiere verificar que la condicin de trmino se cumplir en algn momento. En caso contrario, el algoritmo se llamar a s mismo recursivamente hasta que el stack se agote y el programa colapse (error de ejecucin). En este caso, la condicin de trmino se alcanza cuando se logra llegar a la salida del laberinto o cuando se han probado todas las posibles direcciones (izquierda, derecha, arriba y abajo) y an as no se ha encontrado solucin. En este caso, el algoritmo recursivo se ha planteado de una forma bastante segura. El procedimiento siempre termina, ya sea positiva o negativamente, encontrando la solucin o desistiendo de encontrarla, respectivamente. Por otra parte, es necesario definir dominios que caractericen situaciones distintas bajo las cuales se puede ejecutar el algoritmo. Dominios: Deben definirse dominios en los que, tanto la entrada como la salida del laberinto, se encuentren en distintas posiciones, incluso del mismo lado o hasta contiguas. Validacin: Ejecutando en algoritmo para los dominios definidos debe verificarse que la solucin cumple con la especificacin planteada y por lo tanto alcanza el objetivo propuesto.
5. Limitaciones del algoritmo A simple vista el algoritmo no tiene limitaciones importantes. Sin embargo, no existe una prueba formal de esto, por lo que se deja como ejercicio analizar la solucin propuesta a fin de determinar potenciales limitaciones.
Posibles modificaciones (Ejercicios) Existen diversas variantes de este programa que pueden implementarse como ejercicio. Algunas requieren leves modificaciones, principalmente en la funcin recursiva, pero otras involucran mayores cambios. Ser posible eliminar los pasos innecesarios que puede provocar la funcin recursiva suministrada?. Si es as, modifique la funcin para que no haga esos pasos. El problema puede replantearse, indicando que el laberinto tiene una entrada y el objetivo es buscar algn tesoro que se encuentra en el interior, tomarlo y regresar a la entrada. Implemente la solucin de este nuevo problema. La solucin presentada no toma en cuenta la direccin en la que se viene buscando la solucin. Puede implementarse una solucin en la cual se mantenga la direccin actual, y la bsqueda se Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 11 haga haciendo giros a partir de esa direccin. Tendra esto alguna ventaja?. Trate de implementar la solucin. Ser posible implementar una funcin recursiva que disee el laberinto?. Si lo logra concebir, implemntela. Esto sustituira la tediosa inicializacin de la matriz y le dara mayor flexibilidad al programa. Ahora el programa plantea laberintos y luego los resuelve. Cuando se hayan estudiado bibliotecas para manejo de grficos, ser posible implementar una versin animada de la solucin del laberinto, en la que se vayan mostrando los distintos caminos que va probando el algoritmo.
/********************************************************************** * Ejemplo: Solucin de un laberinto en forma recursiva. * Para mejor comprensin ver la descripcin adjunta. **********************************************************************/
using System;
class Clab { private char [,] lab; public int xf = 11, yf = 20;
public void mDisplay() { Console.Write("\n\t"); for(int i = 0; i < 13; i++) { for(int j = 0; j < 21; j++) Console.Write("{0}",lab[i,j]); Console.Write("\n\t"); } }
private bool mValidate(int f, int c) { // Controla si la posicin esta fuera del laberinto if (((f<0) || (f>=13) || (c<0) || (c>=21)) || (lab[f,c] == '*' || lab[f,c] == '\x4F')) return false; else return true; Intro. Prog Orientada a Objeto - Recursividad Rodrigo Sandoval U. IIC 1102 Pgina: 12 }
public bool mRecorrer(int fil, int col) { bool listo = false; // Indica si se ha encontrado la salida
// Se marca la casilla como visitada lab[fil,col] = '*';
// Se controla la condicin de termino de recursividad: // " Llegamos a la salida? " if (fil == xf && col == yf) return(true);
if (!listo && mValidate(fil,col-1)) // Intento a la izquierda listo = mRecorrer(fil,col-1); if (!listo && mValidate(fil,col+1)) // Intento a la derecha listo = mRecorrer(fil,col+1); if (!listo && mValidate(fil-1,col)) // Intento hacia arriba listo = mRecorrer(fil-1,col); if (!listo && mValidate(fil+1,col)) // Intento hacia abajo listo = mRecorrer(fil+1,col);
// Si no se logr resolver el laberinto desde esta posicin, se // desmarca la casilla pues no ser parte de la solucin. En este // caso se retornara falso lo que provocara que se retroceda. if (!listo) lab[fil,col] = ' '; // Se retorna TRUE/FALSE dependiendo de si se encontr solucin return(listo); } }
class Cmain { public static void Main() { CLab l = new CLab(); l.mDisplay(); if(l.mRecorrer(1,0)) l.mDisplay(); else Console.WriteLine("Laberinto no tiene solucin!"); } }
Obsrvense los pasos innecesarios que se dan (por qu ocurre?)
Material preparado por Rodrigo Sandoval U en Mayo 2004, basado en los apuntes de clase del curso IIC1102, ao 2003, de M. Nussbaum, Marcos Seplveda, et.a Los ejemplos fueron adaptados y preparados por el MSR Lab, del DCC de la Escuela de Ingeniera de la PUC
PONTIFICIA UNIVERSIDAD CATLICA DE CHILE ESCUELA DE INGENIERA DEPARTAMENTO DE CIENCIA DE LA COMPUTACIN IIC 1102 INTRODUCCIN A LA PROGRAMACIN Profesor: Rodrigo Sandoval U.
Captulo XII Bsqueda y Ordenamiento
1 INTRODUCCIN ............................................................................................................................................... 1 2 ALGORITMOS DE BSQUEDA SIMPLE...................................................................................................... 2 2.1 BSQUEDA LINEAL .........................................................................................................................................2 2.1.1 Ejemplo: Bsqueda lineal en vector de enteros ..................................................................................... 2 3 ALGORITMOS DE ORDENAMIENTO .......................................................................................................... 5 3.1 ORDENAMIENTO POR SELECCIN....................................................................................................................5 3.2 ORDENAMIENTO POR SELECCIN (VERSIN ITERATIVA).................................................................................7 4 COMPLEJIDAD DE ALGORITMOS............................................................................................................... 9 4.1 ORDENAMIENTO Y BSQUEDA EFICIENTES.....................................................................................................9 4.2 COMPARACIN DE ALGUNAS FUNCIONES DE TIEMPO......................................................................................9 5 ALGORITMOS EFICIENTES DE BSQUEDA........................................................................................... 11 5.1 BSQUEDA BINARIA .....................................................................................................................................11 5.1.1 Algoritmo ............................................................................................................................................. 11 5.1.2 Ejemplo: Bsqueda Binaria ................................................................................................................. 11 5.1.3 Versin Iterativa................................................................................................................................... 13 5.2 ALGORITMO DE ORDENAMIENTO: QUICKSORT.............................................................................................14 5.2.1 Ejemplo: Ordenamiento con Quicksort de forma recursiva................................................................. 15 5.2.2 Ejemplo: Ordenando las lneas de un archivo..................................................................................... 17
Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 1 1 Introduccin Los computadores se emplean frecuentemente para almacenar y recuperar grandes volmenes de datos. Con su velocidad y facilidad de acceso, los computadores aventajan a otros medios de almacenamiento como el papel y las microfichas. Es importante estudiar la forma en que los computadores pueden almacenar los datos, de modo que su recuperacin (bsqueda) sea rpida. Para lograr esto, y puesto que usualmente los usuarios requieren que los datos recuperados cuenten con algn orden particular, tambin es importante estudiar algoritmos para ordenar los datos almacenados. En todos los ejemplos se supondr que existe un vector que contiene N datos. Para el caso de la bsqueda, el problema consiste en averiguar si un determinado dato est o no en el vector, y si es as, queremos saber su posicin. Para el caso del ordenamiento, el problema consiste en ordenar el vector en forma ascendente (de menor a mayor). Si se quisiera trabajar con ordenamiento descendente los cambios seran mnimos. En este captulo se presentan varios algoritmos de bsqueda y ordenamiento que difieren entre s en cuanto a su complejidad y eficiencia.
Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 2 2 Algoritmos de Bsqueda Simple 2.1 Bsqueda Lineal Algoritmo: Recorrer el vector de inicio a fin, comparando el dato buscado con cada elemento del arreglo. Implementacin: Mediante una funcin que implemente el algoritmo descrito. La funcin retornar la posicin en que se encontr el dato, o bien la cantidad de elementos en el vector en el caso en que no se encuentre (esto sera un subndice invlido). /************************************************************************* * Funcion que realiza una busqueda lineal de un valor entero en un vector * de enteros. La funcion recibe como parametros el vector, la cantidad de * elementos que hay en el vector (N) y el valor entero que se busca. * Si se encuentra el valor entonces se devuelve la posicion de este, sino * se devuelve la cantidad de elementos del vector. *************************************************************************/ int BuscarLinealmente(int Numeros[], int N, int NumeroBuscado) { /* Inicializar el indice para recorrer el vector de numeros */ int i = 0;
/* Recorrer el vector mientras no se llegue a su fin y no se encuentre el numero buscado */ while ((i < N) && (NumeroBuscado != Numeros[i])) i++;
/* Retornar la posicion del numero o la cantidad de elementos */ return(i); }
2.1.1 Ejemplo: Bsqueda lineal en vector de enteros /************************************************************************* * Ejemplo: Busqueda lineal en un vector de enteros. *************************************************************************/ using System; using System.IO;
public class CSort { public int[] mLeerVector(string archivo) { StreamReader sr; int [] numeros;
Console.WriteLine("Leyendo datos de entrada");
// Abrir el archivo try { sr = new StreamReader(archivo); numeros = new int[Int32.Parse(sr.ReadLine())];
Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 3 return(numeros); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); }
return null; }
public void mMostrarVector(int[] vector) { Console.WriteLine("Los contenidos del vector son..."); foreach(int i in vector) Console.WriteLine("{0}",i); }
public int mBusquedaLineal(int[] Numeros, int NumeroBuscado) { for(int i = 0; i < Numeros.Length; i++) if(Numeros[i] == NumeroBuscado) return i;
return -1; } }
public class CMain { public static void Main(string [] args) { CSort cs = new CSort();
Console.Write("Ingrese Nombre archivo: "); string archivo = Console.ReadLine();
int[] vector = cs.mLeerVector(archivo); cs.mMostrarVector(vector); Console.Write("Ingrese el nmero que desea buscar: "); int search = Int32.Parse(Console.ReadLine()); int pos = cs.mBusquedaLineal(vector,search); if(pos == -1) Console.WriteLine("No se encontr el nmero {0}",search); else Console.WriteLine("El numero {0} se encuentra en la posicin {1}", search,pos); } }
Archivo de entrada 10 3 -5 20 0 11 4 2 9 -1 90
Ejemplo de ejecucin Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 4 El vector de 10 enteros es: 3 -5 20 0 11 4 2 9 -1 90 Ingrese un nmero entero: 5 El 5 no esta en el vector.
Leyendo datos de entrada El vector de 10 enteros es: 3 -5 20 0 11 4 2 9 -1 90 Ingrese un nmero entero: 11 El 11 esta en la posicin 4. Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 5 3 Algoritmos de Ordenamiento 3.1 Ordenamiento por Seleccin Algoritmo recursivo escogiendo el mayor: Si el vector tiene un nico elemento no se hace nada. En caso contrario, se elige el mayor de los elementos y se intercambia por el ltimo (posicin N-1). De esta forma, el ltimo elemento estar en su posicin correcta. Luego se ordena el subvector que tiene N-1 datos.
/************************************************************************* * Programa con funcin recursiva que ordena vector de enteros por seleccin. * Si el vector tiene un solo elemento no se hace nada. De lo contrario, * se elige el mayor de los elementos y se intercambia por el ultimo del * vector (posicion N - 1). Luego se ordena el vector con N - 1 datos. *************************************************************************/ using System; using System.IO;
public class CSelSort { public int [] mLeerVector(string archivo) { StreamReader sr; int [] numeros;
Console.WriteLine("Leyendo datos de entrada");
try { sr = new StreamReader(archivo); numeros = new int[Int32.Parse(sr.ReadLine())];
return(numeros); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); }
return null; }
public void mMostrarVector(int [] vector) { Console.WriteLine("Los contenidos del vector son..."); foreach(int i in vector) Console.WriteLine("{0}",i); }
public void mOrdenarPorSeleccionRecursivo(int [] Numeros, int N) { int i, PosMayor, aux;
if (N > 1) { /* Busca el mayor elemento */ PosMayor = 0; /* Supone que el mayor es el primero */ for (i=1; i<N; i++) if (Numeros[i] > Numeros[PosMayor]) Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 6 PosMayor = i;
/* Se lleva a cabo el intercambio */ aux = Numeros[N - 1]; Numeros[N - 1] = Numeros[PosMayor]; Numeros[PosMayor] = aux;
/* Llamado recursivo con el subvector de N-1 elementos */ mOrdenarPorSeleccionRecursivo(Numeros, N - 1); } } }
public class CMain { public static void Main(string [] args) { CSelSort ss = new CSelSort();
Console.Write("Ingrese Nombre archivo: "); string archivo = Console.ReadLine();
int [] vector = ss.mLeerVector(archivo); Console.WriteLine("Antes de ordenar..."); ss.mMostrarVector(vector); ss.mOrdenarPorSeleccionRecursivo(vector,vector.Length-1); Console.WriteLine("Despues de ordenar..."); ss.mMostrarVector(vector); } }
Archivo de entrada 10 3 -5 20 0 11 4 2 9 -1 90
Ejemplo de ejecucin
C:\>ordsel entrada.txt Leyendo datos de entrada
Antes de Ordenar El vector de 10 enteros es: 3 -5 20 0 11 4 2 9 -1 90
Despues de Ordenar El vector de 10 enteros es: -5 -1 0 2 3 4 9 11 20 90 Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 7 3.2 Ordenamiento por Seleccin (versin iterativa) Algoritmo iterativo escogiendo el mayor: Se itera tantas veces como elementos hay en el vector. En cada iteracin se elige el mayor de los elementos y se intercambia por el ltimo. Se decrementa N para que en la siguiente iteracin se trate el siguiente. El orden en que se van ubicando los elementos es el mismo que en el caso recursivo.
using System; using System.IO;
public class CSelSort { public int [] mLeerVector(string archivo) { StreamReader sr; int [] numeros;
Console.WriteLine("Leyendo datos de entrada");
try { sr = new StreamReader(archivo); numeros = new int[Int32.Parse(sr.ReadLine())];
return(numeros); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); }
return null; }
public void mMostrarVector(int [] vector) { Console.WriteLine("Los contenidos del vector son..."); foreach(int i in vector) Console.WriteLine("{0}",i); }
public void mOrdenarPorSeleccionIterativo(int [] Numeros, int N) { int i, PosMayor, aux; /* Itera tantas veces como elementos hay en el vector. */ /* En cada iteracion ubica el elemento en la posicion N */ while (N > 1) { /* Busca el mayor */ PosMayor = 0; /* Supone que el mayor es el primero */ for (i = 1; i < N; i++) if (Numeros[i] > Numeros[PosMayor]) PosMayor = i;
/* Lleva a cabo el intercambio */ aux = Numeros[N - 1]; Numeros[N - 1] = Numeros[PosMayor]; Numeros[PosMayor] = aux; N--; /* Decrementar cantidad de elementos a ordenar */ } } Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 8 }
public class CMain { public static void Main(string [] args) { CSelSort ss = new CSelSort();
Console.Write("Ingrese Nombre archivo: "); string archivo = Console.ReadLine();
int [] vector = ss.mLeerVector(archivo); Console.WriteLine("Antes de ordenar..."); ss.mMostrarVector(vector); ss.mOrdenarPorSeleccionIterativo(vector,vector.Length-1); Console.WriteLine("Despues de ordenar..."); ss.mMostrarVector(vector); } } Archivo de entrada 10 3 -5 20 0 11 4 2 9 -1 90
Ejemplo de ejecucin
Leyendo datos de entrada Antes de Ordenar El vector de 10 enteros es: 3 -5 20 0 11 4 2 9 -1 90 Despus de Ordenar El vector de 10 enteros es: -5 -1 0 2 3 4 9 11 20 90
Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 9 4 Complejidad de Algoritmos El estudio de la complejidad de los algoritmos intenta obtener medidas que indiquen cmo ser el comportamiento de los algoritmos ante variaciones en las caractersticas de los datos de entrada (por ejemplo, la cantidad de datos). El orden de ejecucin de un algoritmo, denotado por O(expresin) indica cmo ser el comportamiento del tiempo de ejecucin del algoritmo ante variaciones en los parmetros de la expresin. Por ejemplo, cuando se dice que un algoritmo tiene orden lineal respecto al nmero de elementos de entrada, n, y denotado por O(n), se quiere expresar que el tiempo de ejecucin del algoritmo se incrementar linealmente conforme se incremente el nmero de elementos de entrada. Puede deducirse entonces que los algoritmos ms deseables son aquellos que cuenten con rdenes de ejecucin logartmicos, y los menos deseables son aquellos con rdenes de ejecucin exponenciales. 4.1 Ordenamiento y Bsqueda Eficientes Cuando la cantidad de datos que se estn manipulando es extremadamente grande, incluso un computador puede tener problemas para llevar a cabo bsquedas u ordenamientos en un tiempo razonable. El algoritmo de bsqueda lineal, como es de esperar, es de orden O(n), donde n es el nmero de elementos. El algoritmo de ordenamiento por seleccin es de orden O(n 2 ), donde n es el nmero de elementos. A continuacin se estudiarn algoritmos que tienen complejidad O(log n). 4.2 Comparacin de algunas funciones de tiempo n log n n log n n2 n2 log n 1 0,00 0,0 1 0,0 2 0,69 1,4 4 2,8 5 1,61 8,0 25 40,2 10 2,30 23,0 100 230,3 20 3,00 59,9 400 1198,3 50 3,91 195,6 2500 9780,1 100 4,61 460,5 10000 46051,7 200 5,30 1059,7 40000 211932,7 500 6,21 3107,3 250000 1553652,0 1000 6,91 6907,8 1000000 6907755,3 2000 7,60 15201,8 4000000 30403609,8 5000 8,52 42586,0 25000000 212929829,8 Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 10 10000 9,21 92103,4 100000000 921034037,2 20000 9,90 198069,8 400000000 3961395021,0 50000 10,82 540988,9 2500000000 27049445711,0 100000 11,51 1151292,5 10000000000 115129254649,7 200000 12,21 2441214,5 40000000000 488242905821,2 500000 13,12 6561181,7 250000000000 3280590844351,1 1000000 13,82 13815510,6 1000000000000 13815510557964,3 2000000 14,51 29017315,5 4000000000000 58034630954096,9 5000000 15,42 77124742,4 25000000000000 385623711759959,0
Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 11 5 Algoritmos Eficientes de Bsqueda 5.1 Bsqueda Binaria La bsqueda binaria puede aplicarse nicamente a un conjunto ordenado de datos. Por esto, supondremos que el vector que contiene los datos se encuentra ordenado ascendentemente (es decir, de menor a mayor). 5.1.1 Algoritmo Se analiza la posicin del medio. Si ah se encuentra el dato buscado, terminamos. Si el dato buscado es menor, se busca en el subvector menor, y si es mayor, se busca en el subvector mayor (aprovechando el hecho de que el vector est ordenado). Cada vez que se hace uno de estos anlisis, se divide el vector en dos (de ah su nombre, bsqueda binaria), y se descarta una de las mitades. Intuitivamente puede verse que la cantidad de trabajo necesaria para encontrar un elemento (o saber que no est), es mucho menor que para el caso de la bsqueda lineal.
/*********************************************************************** * Mtodo que realiza una bsqueda binaria de un elemento en un vector * de enteros. La funcin recibe como parmetros el vector, el ndice de * inicio y de fin del vector, y el valor entero que se desea buscar. * Si el ndice de inicio es mayor que el de fin se retorna que no se * encontr. En otro caso se divide el vector a la mitad, si el numero * buscado es menor que el que esta en la mitad se busca entonces en la * mitad inferior, si el numero buscado es mayor que el que esta en la * mitad se busca entonces en la mitad superior y en otro caso, el numero * en la mitad es el numero buscado. ***********************************************************************/ public int BusquedaBinaria(int[] Numeros, int Inicio, int Fin, int NumeroBuscado) { if (Inicio > Fin) return(-1); // -1 representa: NO ENCONTRADO else { int pos = (Inicio + Fin) / 2; if (NumeroBuscado < Numeros[pos]) return(BusquedaBinaria(Numeros, Inicio, pos-1, NumeroBuscado)); else if (NumeroBuscado > Numeros[pos]) return(BusquedaBinaria(Numeros, pos + 1, Fin, NumeroBuscado)); else return(pos); } }
5.1.2 Ejemplo: Bsqueda Binaria
using System; using System.IO;
public class CSort { Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 12 public void mOrdenarPorSeleccionRecursivo(int [] Numeros, int N) { int i, PosMayor, aux;
if (N > 1) { // Busca el mayor elemento PosMayor = 0; // Supone que el mayor es el primero for (i=1; i<N; i++) if (Numeros[i] > Numeros[PosMayor]) PosMayor = i; // Se lleva a cabo el intercambio aux = Numeros[N - 1]; Numeros[N - 1] = Numeros[PosMayor]; Numeros[PosMayor] = aux;
// Llamado recursivo al mtodo con el subvector de N-1 elementos mOrdenarPorSeleccionRecursivo(Numeros, N - 1); } }
public int [] mLeerVector(string archivo) { StreamReader sr; int [] numeros;
Console.WriteLine("Leyendo datos de entrada");
// Abrir el archivo indicado try { sr = new StreamReader(archivo); numeros = new int[Int32.Parse(sr.ReadLine())];
return(numeros); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); }
return null; }
public void mMostrarVector(int [] vector) { Console.WriteLine("Los contenidos del vector son..."); foreach(int i in vector) Console.WriteLine("{0}",i); }
public int mBusquedaBinaria(int[] Numeros, int Inicio, int Fin, int NumeroBuscado) { if (Inicio > Fin) return(-1); else { Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 13 int pos = (Inicio + Fin) / 2; if (NumeroBuscado < Numeros[pos]) return(mBusquedaBinaria(Numeros, Inicio, pos-1, NumeroBuscado)); else if (NumeroBuscado > Numeros[pos]) return(mBusquedaBinaria(Numeros, pos+1, Fin, NumeroBuscado)); else return(pos); } } }
public class CMain { public static void Main(){ CSort cs = new CSort();
Console.Write(Ingrese nombre archivo: ); string archivo = Console.ReadLine();
int [] vector = cs.mLeerVector(archivo); cs.mOrdenarPorSeleccionRecursivo(vector,vector.Length); cs.mMostrarVector(vector); Console.Write("Ingrese el numero que desea buscar: "); int search = Int32.Parse(Console.ReadLine()); int pos = cs.mBusquedaBinaria(vector,0,vector.Length-1,search); if(pos==-1) Console.WriteLine("No se encontr el No {0}",search); else Console.WriteLine("El No {0} se encuentra en la pos. {1}", search, pos); } } }
5.1.3 Versin Iterativa Tambin es posible implementar el algoritmo de bsqueda binaria iterativamente, reemplazando la recursividad por un ciclo: /************************************************************************ * Mtodo que realiza una bsqueda binaria de un valor entero en vector * de enteros. Se reciben como parmetros el vector, el ndice de * inicio y de fin del vector, y el valor entero que se desea buscar. * Mientras el ndice de inicio sea menor o igual que el de fin se divide * vector a la mitad, si el numero buscado es menor que el que esta en la * mitad se cambia el ndice de fin para la posicin anterior a la mitad y * se vuelve a iterar, si el numero buscado es mayor que el que esta en la * mitad se cambia ndice de inicio para la posicin posterior a la mitad * y se vuelve a iterar, y sino, el numero en la mitad es el buscado. * Si el ndice de inicio se hace mayor que el de fin entonces se retorna * como No Encontrado. *************************************************************************/ int BusquedaBinariaIterativa(int[] Numeros, int Inicio, int Fin, int NumeroBuscado) { while (Inicio <= Fin) { int pos = (Inicio + Fin) / 2; if (NumeroBuscado < Numeros[pos]) Fin = pos - 1; Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 14 else if (NumeroBuscado > Numeros[pos]) Inicio = pos + 1; else return pos; } return -1; // -1 indica no encontrado }
5.2 Algoritmo de Ordenamiento: Quicksort El algoritmo Quicksort fue desarrollado en 1962 por C.A.R. Hoare, antes de que se implementaran los primeros lenguajes con capacidad para ejecutar funciones recursivas. El algoritmo, aplicado a un subvector vec[a ... b] es: 1. Elegir un elemento x cualquiera del vector, entre a y b. El elemento x se llama pivote. Usualmente se elige el elemento que est en el medio. 2. Particionar el vector en dos subvectores: vec[a ... p] y vec[p+1 ... b], intercambiando elementos de modo que todos los elementos que son menores que x estn a la izquierda y todos los mayores que x estn a la derecha. 3. Aplicar Quicksort al subvector vec[a ... p] 4. Aplicar Quicksort al subvector vec[p+1 ... b]
La funcin que implementa el algoritmo Quicksort podra implementarse de la siguiente manera: /************************************************************************* * Mtodo recursivo que ordena un vector de enteros mediante Quicksort. * Si el vector no tiene ms de dos elementos no se hace nada. De lo * contrario, se particiona el vector y se aplica el mtodo a los dos * subvectores que resultan de la particin. * Se reciben como parmetros el vector y el ndice inicial y final. *************************************************************************/ void QuickSort(int[] Numeros, int Inicio, int Fin) { int p;
if (Inicio < Fin) { p = ParticionarVector(Numeros, Inicio, Fin); QuickSort(Numeros, Inicio, p); QuickSort(Numeros, p + 1, Fin); } }
La funcin que lleva a cabo la seleccin del pivote y el particionamiento del vector sera: /************************************************************************* * Funcin para particionar un vector en dos subvectores, intercambiando * elementos de modo que todos los menores que el pivote estn a la * izquierda y los mayores a la derecha. * Se reciben como parmetros el vector y el ndice inicial y final. * Se retorna el ndice para particionar el vector (posicin del pivote). *************************************************************************/ Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 15 int ParticionarVector(int[] Numeros, int Inicio, int Fin) { int pivote = Numeros[(Inicio + Fin) / 2]; int izq = Inicio - 1; int der = Fin + 1; int aux;
while (izq < der) { // Busca el 1er. elemento de la derecha que haya que intercambiar do { izq++; } while (Numeros[izq] < pivote);
// Busca el 1er. elemento de la izq. que haya que intercambiar do { der--; } while (Numeros[der] > pivote);
if (izq < der) { // Lleva a cabo el intercambio aux = Numeros[izq]; Numeros[izq] = Numeros[der]; Numeros[der] = aux; } } return(der); }
5.2.1 Ejemplo: Ordenamiento con Quicksort de forma recursiva
using System; using System.IO;
public class CQSort { public int [] mLeerVector(string archivo) { StreamReader sr; int [] numeros;
Console.WriteLine("Leyendo datos de entrada");
// Abrir el archivo try { sr = new StreamReader(archivo); numeros = new int[Int32.Parse(sr.ReadLine())];
return(numeros); } Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 16 catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); } return null; }
public void mMostrarVector(int [] vector) { Console.WriteLine("Los contenidos del vector son..."); foreach(int i in vector) Console.WriteLine("{0}",i); }
private int mParticionarVector(int[] Numeros, int Inicio, int Fin) { int pivote = Numeros[(Inicio + Fin) / 2]; int izq = Inicio - 1; int der = Fin + 1; int aux;
while (izq < der) { // Busca el 1er elemento de la der. que haya que intercambiar do { izq++; } while (Numeros[izq] < pivote);
// Busca el 1er elemento de la izq. que haya que intercambiar do { der--; } while (Numeros[der] > pivote);
if (izq < der) { // Lleva a cabo el intercambio: swap aux = Numeros[izq]; Numeros[izq] = Numeros[der]; Numeros[der] = aux; } } return(der); }
public void mQuickSort(int [] Numeros, int Inicio, int Fin) { int p;
if (Inicio < Fin) { p = mParticionarVector(Numeros, Inicio, Fin); mQuickSort(Numeros, Inicio, p); mQuickSort(Numeros, p + 1, Fin); } } }
public class CMain { public static void Main() { CQSort qs = new CQSort();
Console.Write(Ingrese nombre archivo: ); Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 17 string rchivo = Console.ReadLine();
int [] vector = qs.mLeerVector(archivo); Console.WriteLine("Antes de ordenar..."); qs.mMostrarVector(vector); qs.mQuickSort(vector,0,vector.Length-1); Console.WriteLine("Despus de ordenar..."); qs.mMostrarVector(vector); } }
5.2.2 Ejemplo: Ordenando las lneas de un archivo Programa que ordena las lneas de un archivo y las guarda en otro. Ilustra el uso de operaciones sobre archivos, y aplica uno de los algoritmos de ordenamiento estudiados. Las lneas del archivo origen se leen una a una mediante fgets, y se almacenan en un vector de strings (o matriz de chars). Una vez ah, se aplica un algoritmo de ordenamiento por seleccin y se procede a escribirlas al archivo de salida mediante fputs. Los nombres de los archivos, se pasan como argumentos a travs de la lnea de comandos.
using System; using System.IO;
public class CLineSort { public string [] mReadFile(string fileName) { StreamReader sr; string [] lines;
Console.WriteLine("Leyendo datos de entrada");
// Abrir el archivo try { sr = new StreamReader(fileName);
lines = new string[Int32.Parse(sr.ReadLine())]; for(int i = 0; i < lines.Length; i++) lines[i] = sr.ReadLine();
sr.Close();
return(lines); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); }
return null; }
public void mWriteFile(string fileName, string [] vector) { StreamWriter sw;
try { sw = new StreamWriter(fileName); foreach(string str in vector) Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 18 sw.WriteLine(str);
sw.Close(); } catch (Exception e) { Console.WriteLine("Problema con apertura de I/O: "); Console.WriteLine(e.Message); Environment.Exit(1); } }
public void mOrdenar(string [] VecString, int N) { int i, PosMayor; string StrAux;
if (N > 1) { // Busca el mayor elemento PosMayor = 0; // Al inicio se supone que el mayor es el primero for (i=1; i<N; i++) if (String.Compare(VecString[i], VecString[PosMayor])>0) PosMayor = i;
/* Se lleva a cabo el intercambio */ StrAux = VecString[N-1]; VecString[N-1] = VecString[PosMayor]; VecString[PosMayor] = StrAux;
// Llamado recursivo a la funcin con el subvector de N-1 elementos mOrdenar(VecString, N - 1); } } }
public class CMain { public static void Main(string [] args) { Console.Write(Ingrese nombre archivo: ); string archivo = Console.ReadLine();
CLineSort ls = new CLineSort(); string [] vector = ls.mReadFile(archivo); ls.mOrdenar(vector, vector.Length); ls.mWriteFile(args[1],vector); } }
Archivo de prueba original Volvo Renault Honda Daihatsu Chrysler Opel Alfa-Romeo Mitsubishi Suzuki Rover BMW Jaguar Ford Intro. Prog. Orientada a Objeto Bsqueda y Ord. Rodrigo Sandoval U. IIC 1102 Pgina: 19 Fiat Mercedes-Benz Volkswagen Dodge Nissan Chevrolet Kia Daewoo Toyota Audi Seat Subaru Citroen Porsche Peugeot Hyundai Mazda
Archivo de salida (resultado) Alfa-Romeo Audi BMW Chevrolet Chrysler Citroen Daewoo Daihatsu Dodge Fiat Ford Honda Hyundai Jaguar Kia Mazda Mercedes-Benz Mitsubishi Nissan Opel Peugeot Porsche Renault Rover Seat Subaru Suzuki Toyota Volkswagen Volvo