TEMA 1: CONCEPTOS BÁSICOS • Introducción: Informática, sistemas de información, abstracción. 1.1. Autómata, programas, máquina (virtual, física, programable), cómputo, computador, hardware, software. Máquina de von Newman. • Algoritmo (definición, ejemplo) • Programación, ingeniería de software. • Introducción al lenguaje C. INTRODUCCIÓN • Informática−Ciencia: Estudia lo referente al procesamiento automático de información. • Informática−Técnica: Teoría, diseño, fabricación y uso de computadores. • Sistemas de Información: DATOS! se le aplica ! PROCESO ! genera!INFORMACIÓN !!! antecedentes acciones como un aumento en los necesarios para la reunión, selección conocimientos derivado tener conocimientos cálculo o escritura del análisis de datos. exacto de algo (cantidades, cualidades o hechos). Al proceso de automatizar la información generada por la aplicación de un proceso a una serie de datos, se le llama Informática. • Abstracción: Proceso mental que consiste en que un determinado proceso u objeto realiza un estudio basado en dos aspectos Complementarios. • destacar detalles relevantes e ignorar los irrelevantes. • Buscar los relevantes e irrelevantes. Para conseguir información no es posible analizarlo todo de golpe. Hay que tener en cuenta que lo más importante, lo esencial para uno no lo es para otro. Este proceso se estructura siempre en nivel jerárquico de forma que para un determinado nivel unas cosas pueden ser relevantes y en otro no. 1 La utilidad básica está en reducir la complejidad de los problemas, de forma que se pueden estudiar y manipular con mayor facilidad. AUTÓMATAS: MÁQUINA: Dispositivo capaz de realizar un trabajo. No tiene porque ser físico (virtuales). El primero en intentar construirla fue Babbage. Se clasifican en: • No Automáticas: necesita un estímulo externo constante para operar (máquina de escribir) • Automática: necesita de un estímulo mínimo externo para realizar un trabajo más o menos complejo. Se clasifican en: • No programables: si siempre realiza la misma operación. • Programable: si es capaz de realizar diferentes operaciones dependiendo de un programa que lo gobierna. Una máquina automática es igual que una autómata. Esta consta de: • Parte fija: Hardware • Parte variable: Software. BASE: Es la estructura de von Newman. Las máquinas autómatas de tipo ordenador se han desarrollado en base a esta estructura con estos elementos. ALGORITMO: Una sucesión finita de instrucciones que describen con precisión como resolver todos los problemas de un mismo tipo. Si un algoritmo es la descripción de los pasos en un computador abstracto, un programa será lo mismo en un computador determinado. PROGRAMACIÓN E INGENIERIA DEL SOFTWARE. Programación: Es la disciplina de la informática, que estudia las técnicas involucradas en el desarrollo del programa. Los programas se dividen en 2 géneros: programación a pequeña escala y a gran escala (IS). FASES de la programación: • Problema. • Elaboración o análisis de requerimiento: proceso que conduce desde el problema a la especificación. • Especificación: Representación del problema que de alguna forma indique el comportamiento deseado del programa. ¿Qué? • Diseño: Proceso que conduce desde la especificación hasta la implementación. ¿Cómo? • Implementación: Descripción de algoritmo, lenguaje genérico que explica como pasar de los datos que tengo al resultado que quiero. • Codificación: Proceso en el cual se obtiene el programa a partir de la implementación. • Análisis: Ver si la solución es la correcta. Tres puntos a tener en cuenta a partir de la creación de un programa. • Corrección del algoritmo: si la implementación corresponde con la especificación, el algoritmo es correcto. 2 • Eficiencia: hay que buscar si mi solución es suficientemente eficiente dentro de las que he encontrado. Debe ser ésta la que elijamos. • Claridad: Se pone al mismo nivel de la eficiencia. El programa debe ser correcto, eficiente y claro. TEMA 2: TIPOS Y EXPRESIONES 2.1 Lexemas. • Tipos de datos. • Constantes y variables. • Tipos escalares. • Tipo real. • Expresiones. • Operadores de evaluación perezosa y sobrecarga de operadores. • Conversores de tipo. • Tipos y expresiones en C. LEXEMA: Alfabeto: Conjunto finito y no vacío de elementos, los cuales son llamados símbolos del alfabeto, y se llamará lexema a la unidad indivisible y mínima con significado en el lenguaje que se construya mediante una sucesión finita de símbolos. Ej: a, a,....a "={0,1,2,3,4,5,6,7,8,9,+,−} Lexemas: combinación de esos elementos que tengan significado. Ej: +3 , +1, −3, 258, 5+3−9 no. Admitiremos que determinados lexemas estén sobrecargados, es decir que sirvan para más de un fin. Lexemas que utilizaremos: • Identificadores: Nombres dados a los elementos del programa. Deben Empezar por una letra y estar formados por letras, dígitos y símbolos de subrayado. Se escriben en minúscula. • Palabras reservadas: Conjunto de identificadores utilizado para uso Exclusivo y privado por el lenguaje y no se puede utilizar para otro fin. Se le asigna un código (negrilla) • Literales: Denotan valores concretos de los elementos computables. • Símbolos de operación: Indican operaciones que son válidas entre elementos de mi programa. Ej 14 +7. ( L+ O + L) • Separadores: Lexemas constituidos por uno o varios símbolos de puntuación. Ej. ., ; espacios blancos y líneas no significan nada. TIPOS DE DATOS 3 Son las distintas clases de valores. Se define como un par (L, O) donde L es un conjunto de lexemas de tipo literal o literales y/o un conjunto de lexemas que llamaremos símbolos de operación. Ej: L: conjunto enteros E:{ +, −, 0......9} Para cada tipo de dato hay que dar la siguiente información: que llamaremos signatura o perfil, dominio−rango y condiciones. La signatura de una operación es una notación que representa el símbolo de la operación y el número de parámetros. • Dominio− Rango: Refleja el significado de la operación, indicando la correspondencia entre el dominio de los argumentos que se operan y el rango que indicaría el resultado que se puede obtener. • Condiciones− definición: Serán predicados o expresiones lógicas que establecen qué condiciones deben cumplir los elementos del dominio para que tengan imagen. Si para todos los valores del dominio tienen imagen diremos que la operación es total y el predicado, entonces, será cierto. Si no, diremos que es parcial y especificaremos cuando no tiene imagen. DECLARACIÓN DE TIPOS DE DATOS: Va a ser un enunciado que establece un vínculo entre un especificador y un tipo. Tipos: A la izda. pondremos el identificador del tipo y a la derecha T1: c1 constructores apropiados. T2: c2 Habitualmente pondremos la T mayúscula para establecer un tipo. ..... Tnota_media: (", 10) Tn: cn CONSTANTES Y VARIABLES Constante: Es un indicador que denota uno y sólo uno de los literales de un tipo. Datos que no se pueden modificar durante la ejecución. Da mayor claridad al código sustituyendo valores por dichas constantes o se puede usar cuando un valor (IVA: 16%) puede variar con el tiempo y basta con variar el nº de IVA en vez de cambiar el algoritmo. Por extensión a los literales de determinados valores. • Declaración de constante: Al establecimiento del vínculo entre el identificador y el literal del tipo correspondiente. Las declararemos en una sección del programa que se llamará CONSTANTE o CONs y escribiremos a la izquierda la c1: I1 donde c1: identificadores, I1 literales. Variables: Va a ser por el contrario, elementos que pueden modificar su valor durante la ejecución, por lo tanto su valor dependerá del estado actual del algoritmo. Se representará con un identificador. Irán tomando valores a lo largo del algoritmo. • Declaración de variable: Se hará estableciendo un vínculo entre un tipo de dato y un identificador. En una sección que se llamará var. (idem cons). Con el separador coma, podemos declarar variables del mismo tipo a la vez. Con el punto y coma, de distinto tipo en la misma línea. 4 ELABORACIÓN LINEAL DE DECLARACIONES: No se puede utilizar en una declaración, ningún elemento que no haya sido previamente declarado. Primero se declararán constantes, tipos y variables, siempre que sea posible. Tipos de valores: − Escalar: Cuando es posible definir un conjunto de literales indicando uno a uno sus elementos. − Enumerado: Además de ser escalar tiene una ordenación estricta u orden total que se puede establecer si existe un valor máximo y un mínimo y dos operaciones (sucesor y predecesor). Condiciones para establecer tipo enumerado: • Todos los literales deben de ser distintos. ei" ej si i" j. • Para todos los ei debe ser menor que ej si i< j. • Sólo pertenecen a Te los ei....en, si 1" i"n Operaciones asociadas a este tipo enumerado L={e1,....en} conjunto de literales Conjunto de operaciones: O:{suc, pred} De manera que las operaciones son: Descripción sucesor Predecesor Perfil Suc (_): Te!Te pred (_): Te!Te Condiciones Def (suc(e))"e " en Def (pred(e))"e " e1 Suc (ei): ei+1 Pred (ei): ei−1 Tdias semana (lunes, martes.....domingo) Tipos clásicos: • Enteros: Suponemos que se puede operar en el intervalo (−", +"), sin tener en cuenta las sobrecargas. Hacemos el conjunto L para los números enteros. L={..., −2, −1, 0,1,2...} En LEA no podemos escribir infinito Operaciones: O={+,−,*, /, ^, %, −} • Lógico: El que nos permite establecer condiciones sobre los estados actuales de un algoritmo. Logico:{falso, cierto) además es un tipo enumerado. Operaciones:{No, Y, O} 5 Descripción Negación Conjunción Disyunción Perfil No: logico!logico _ Y_:logico x logico!logico _ O_:logico x logico!logico Condiciones Def (No a)"cierto Def (a Y b)"cierto Def (a O b)"cierto • Tipo real: Se denota mediante el punto fijo. Distinguiendo un conjunto e y un conjunto d: e.d= 2.54 Pero como entre 2 números reales hay infinitos el 2.54 se refiere al (2.54, 2.55). Si lo queremos poner en forma exponencial: Ej 2.54. 10−10 = 2.54e−10 Operaciones: Idem entero. EXPRESION: Es una composición bien formada de operandos (variables y constantes) y operadores de tipo conocido. Hay que distinguir dos aspectos. − sintáctico: si está correctamente expresado. − semántico: significado de cada operación. SEMÁNTICA DE UNA EXPRESIÓN: El valor de un literal será el propio literal. Si tenemos una constante simbólica el valor se tomará de la definición , el de una variable del contenido actual para el estado del algoritmo y el valor de la operación es el resultado que evaluamos. N*Iva +2 8x16+2= Resultado de las operaciones. El problema surge cuando se mezclan operaciones. Tendremos que seguir unas normas de prioridad. Lo haremos: • Explícitamente: Poniendo entre paréntesis lo que vamos a efectuar primero • Implícitamente: Por el mecanismo de prioridad de operaciones. Si esto no es suficiente, aplicaremos la regla de asociatividad. Tabla de prioridad Operador − (opuesto) ^ *, /, % +, − <, <=, >, >=, < > = Y, O Asociatividad Derecha Derecha Izquierda Izquierda Izquierda Izquierda Izquierda Funciones predeclaradas: Permiten que el código sea más fácil. 6 Operaciones relacionables: Indican cual es el orden de mis valores, si están delante o detrás. Expresiones lógicas: son expresiones que evalúan datos o resultados que nos van a dar como resultado, un resultado lógico. Evaluación perezosa de los operadores: Tenemos l1 y l2, si li es falso: xYy CC CF FC FF Y perezoso C F ¿ ¿ Determinados operadores como Y, O pueden dar fallos al compilar. La evaluación perezosa hace que pierdan sus propiedades. Sobrecarga de operadores: Si se aplica un operador a expresiones de tipos diferentes. Conversión de tipo: Funciones que permiten cambiar tipos. La función se aplica sobre un tipo y devuelve otro. Solamente entre real y entero admitiremos el cambio automáticamente. Cuando esto sucede se llama tipificación débil. Ej 3+5.0 Real (3)+5.0 TEMA 3: NOTACIÓN ALGORÍTMICA 3.1 Especificación de algoritmos 3.1.1 Introducción a la lógica de 1º orden 3.1.2 Especificación pre−post 3.2 Implementación de algoritmos 3.2.1 Instrucciones simples 3.2.2 Instrucciones compuestas • Composición secuencial • Composición selectiva • Composición iterativa • Entrada y Salida • Estructura central en C • Entrada y salida en C • ESPECIFICACIÓN DE ALGORITMOS 7 Descripción del comportamiento deseado del mismo. Requisitos esenciales: • Precisión: Debemos ocuparnos de que no haya ambigüedades en el algoritmo, si las hay nos encontramos con un problema indeterminado. • Claridad: Nuestro algoritmo debe ser entendido sin dificultad. • Hay que sacrificar la claridad en aras de la precisión, el lenguaje que mejor cumple estos requisitos es el matemático. • INTRODUCCIÓN A LA LOGICA DE 1º ORDEN Se basa en la construcción de términos y fórmulas . Admitiremos las operaciones lógicas normales. ! ! Falso Cierto No l L1 x>3 x!equivale a ø x " y. (no x o y) x!y equivale (x!y) "(y!x) X Cierto Cierto Falso Falso Y falso cierto falso cierto øx falso falso cierto cierto øx"y Falso Cierto Cierto Cierto C.CUANTIFICADOR: Abreviatura que indica una composición de operaciones análogas. Va a tener asociada una variable ligada y un dominio D: . Ej : "x: D. (P(x)) X es una variable ligada dentro de un dominio, sobre una fórmula lógica. C.Universal: " i: 1" i " N−1 .(i< N) C.Existencial: (falso): elemento neutro. " x : D . (P(x)) asociado a la disyunción " i: 1 " i " N. (i=N) C.Sumatorio: (0) elemento neutro que devuelve cuando no estamos dentro del dominio. " x: D. (expresión) asociado a la suma. 8 " i: 1 " i " N.(i) C.Producto (1). Devuelve 1 si estamos fuera del rango. x: D. (E(x)) i : 1 " i " N.(i) Contador:N (0) N x: D. (P(x)) ¿Cuántos elementos dentro del dominio cumplen la propiedad? N i : (1 " i " N). (i%2=0) C.Máximo (−") MAX MAX x: D.(E(x)) MAX i: (1 " i " N)(i) ! N C:Mínimo: (+") MIN x: D.(E(x)) MIN i: (1 " i " N)(i) !1 • ESPECIFICACIÓN PRE−POST Un lenguaje de especificación mediante predicados que llamaremos precondiciones y postcondiciones mediante un lenguaje formal de la lógica matemática, que permite describir mediante fórmulas los estados por los que discurre en la ejecución del algoritmo. Llamaremos coordenadas o parámetros de un algoritmo al conjunto de variables que necesitamos para su resolución y distinguiremos 2 tipos: • argumentos o parámetros de entrada • resultados o parámetros de salida. Los denotaremos: ai : Tai (entrada) ri: Tri (salida) Para especificar un algoritmo tendremos que especificar el conjunto de estados iniciales válidos y el subconjunto de estados finales a los que conduce el algoritmo. Si especifico claramente los dos conjuntos, tengo especificado el algoritmo. Precondición: Aserto o predicado sobre los argumentos que describen los estados iniciales válidos. Precondición: Pre:{P(a1,a2.....an ) Pre:{ n"0} 9 Postcondición: Predicado sobre los argumentos y los resultados que indiquen cuales son los estados a los que conduce la ejecución del algoritmo. Poscondición: Pos:{ Q(a1,a2.....an, r1,r2.......rm) Ej: x,y,z: reales. Pre:{x=X " y=Y} Pos:{x=X+Y " z=Y+x} x entrada/salida. y entrada. z salida. • IMPLEMENTACIÓN DE ALGORITMO. Es la descripción de su comportamiento real y este lenguaje, nos permite Detallar las transformaciones de estado necesarias para que desde el estado inicial lleguemos al estado final del algoritmo. Denominaremos instrucciones o sentencias a dichas transformaciones de estado. En cada instrucción describiremos la sintaxis que reflejará el modo en que debemos escribir la instrucción y la semántica que reflejará el cambio de estado que implica ejecutar la instrucción. TRAZA: El conjunto de estados por los que pasa el algoritmo durante la ejecución. ai:Tai ri:Tri Pre: {Predicado ai} Nombre del algoritmo Pos: {Predicado Q sobre (a1,a2.....rm)} Declaración de variables locales Algoritmo S={Conjunto de instrucciones} • INSTRUCCIONES Simples: Suponen una única transformación de estado. I.nula: sintaxis Semántica: No modifica el estado del algoritmo 10 I.asignación: sintaxis: v:= E Donde v: (parte izquierda) debe ser un identificador de variable := separador y E= (parte derecha) una expresión bien construida y del mismo tipo. Semántica: se evalúa la expresión de E respecto al estado actual de las coordenadas produciendo un valor v. Se sustituirá el valor que representa v por el nuevo valor. E!v Es muy importante porque nos permite esta evaluación: V:= v+1 El lenguaje podrá decidir si su sintaxis es correcta o no. Admitimos la conversión de enteros reales en expresiones enteras. Si escribimos: M, n : entero M:= n+3.0 M:= truncar (real(n)+3.0) lo admitimos por defecto en la asignación ASIGNACIÓN MÚLTIPLE Sintaxis: < u1,u2....un>:= < e1, e2.....en> Semántica: En el estado actual de las variables, se evalúan cada una de las expresiones y posteriormente se sustituyen los valores obtenidos en las variables correspondientes. n,m : entero Pre:{ n= N " m= M} Intercambio Pos:{n=M " m=N} Algoritmo < n, m> :=< m, n> 3.2.2.1 COMPOSICIÓN SECUENCIAL Composición de instrucciones: Asociación de un conjunto de instrucciones. Sintaxis: S1 S2 11 Sn Semántica: Se ejecuta una detrás de otra (orden textual) Composición de instrucciones selectiva: Sintaxis: si B1 :S1 B2: S2 Bn: Sn Fsi Semántica: Se evalúan todas las protecciones de la selección, tienen que ser todas correctas, se ejecuta la instrucción asociada a la que resulte cierta que solo será una, porque debe cumplirse que B1 U B2 .........Bn tiene que ser cierto y además Bi " Bj sea falso, a menos que i=j. Esto se llama determinismo o exhaustividad. Exhaustividad : Al evaluar todas las protecciones al menos una debe ser verdadera. Poniendo otras , se garantiza la exhaustividad. Determinismo: Se produce cuando no hay más de dos protecciones abiertas o verdaderas. Si no se cumple el determinismo, el programa acaba porque el algoritmo se bloquea. Ej: Hacer un algoritmo para calcular 2 máximos enteros. Var A,b,r: entero Pre:{cierto} Máximo entre a y b Pos:{(a " b ! r = a) " (a< b !r =b) } x!"ø x " y Implementación Si a " b : r:=a a " b : r:=b fsi. Solución no determinista, no tiene el caso a=b. 12 Si a >b : r:=a a< b : r:=b fsi Solución no exhaustiva Si a>=b : r:=a a< b : r:=b fsi Solución correcta 3.2.2.3 COMPOSICIÓN ITERATIVA O BUCLE Sintaxis: mientras B (expresión lógica) S(instrucciones) Fmientras Mientras que se cumple B, realizar S, hasta que falle B. Se realiza en tres pasos: • Evaluar B • Si B es cierto, ejecutar S. Vuelve a B. • Si B es falso, fin del bucle. Ej: Dado un número n, sumar los n primeros números al cuadrado: n, suma : entero Pre: { n " 0} Suma de los n primeros números al cuadrado Pos: { suma=" k : 1 " k " n . (k2) } Cuando n=0, se devuelve el elemento neutro del sumatorio= 0. Implementación: Var n=4 k: entero algoritmo. 13 k:=1; suma:=0 mientras k" n suma:= suma +k^2 K:=k+1 fmientras k 1 2 3 4 5 suma 0 1 5 14 30 K<=n? Si Si Si Si no!fm Invariantes: Predicado que describe el estado del algoritmo que tiene que cumplirse para dar una vuelta al bucle. I"{ Suma: " i: 0.....k−1 . (i2)} Cota: Función que devuelve un número entero y que dice el número de vueltas que quedan por dar en el bucle. C"{ n−k+1 } Esto asegura que el bucle no va a dar infinito. EN LEA desde variable:= valor inicial hasta valor final S fdesde suma:= 0 desde k:= 1 hasta n suma:= suma +k^2 fdesde En C (desde) for (v=valor inicial; v " valor final; v++) { S; 14 } En C (mientras) while (B) { S; } • ENTRADA Y SALIDA Scanf leer v1, v2...... vn vi variable {entero, real, carácter..} Printf escribir e1, e2.....en ej expresión DOCUMENTACIÓN Comentarios: Frases que sirven para un mejor entendimiento del programa. Estos comentarios no deben repetir lo que dice el algoritmo, la precondición y la poscondición se pueden considerar como comentarios. Se escriben entre /* comentario */. TEMA 4: PROCEDIMIENTO Y FUNCIONES 4.1 Introducción 4.2 Abstracción operacional 4.3 Funciones 4.4 Procedimientos 4.5 Visibilidad 4.6 Diseño mediante refinamiento usando abstracciones. 4.1 INTRODUCCION Abstracción es la representación de un objeto que oculta lo que podría considerarse irrelevante, haciendo de esta manera que el uso del objeto sea más fácil y dando relevancia a los conceptos y no a los detalles. 4.2 ABSTRACCION OPERACIONAL El uso básico es para conseguir modular programas de forma que se puedan construir mediante operaciones que me permitan resolver programas complejos. Aparece cuando un problema necesite repetidamente un algoritmo o cuando en un algoritmo se presentes diferentes problemas. 15 Este procedimiento genera algunas ventajas como: • Resolución de problemas complejos. • Mejorar la lectura y mantenimiento de los códigos • Independizar la especificación y la implementación • Reutilizar los algoritmos • Ampliar repertorios de operaciones • Materialización de la abstracción operacional • Parametrización: Nos permite reunir un conjunto de expresiones e instrucciones en un objeto superior, de forma que tendremos acceso a ellas mediante un nombre simbólico y un conjunto de variables que llamaremos parámetros. • Ocultación: Nos permite precisar el comportamiento del objeto según su especificación de manera que no necesitemos conocer su implementación. Ej: factorial (n)!parámetros que necesita para resolverlo ! nombre de la abstracción F= 1 " i " m. (i) 4.3 FUNCIONES Llamaremos funciones a una abstracción operacional en la que todos sus parámetros son de entrada excepto uno que será de salida. De tal forma que si una función llamada f, mediante la asignación la nombraremos r. r:= f(a1,a2......an) Nota: r tomará el valor que resuelva la función mediante la asignación. F será el nombre simbólico (a1......an) parámetros de entrada. Ai: Tai Ri: Tri ! r evalúa el resultado del tipo Tr. Nosotros escribimos la función de la siguiente manera: Prototipo! func f(a1: Ta1, a2:Ta2, .......an: Tan ) dev (r: Tr) !!! palabra nombre simbólico nombre de parámetro de reservada salida y tipo Precondición! Pre: {P (a1.....an)} Poscondición!Pos: {Q(a1.....an, r)} CABECERA 16 La función y el procedimiento no van a ser más que un algoritmo. Cons" Var " constantes y variables locales, puedo usarlas dentro de la función pero nunca fuera. Principio Sentencias CUERPO Fin Sintaxis: Nombre_función (e1.....en) ei: expresión que debe corresponder en el orden textual con los tipos correspondientes a los parámetros indicados en el prototipo. Semántica: Se evalúan cada una de las expresiones ei y se asignan a cada uno de los parámetros ai. Se ejecuta el conjunto de sentencias entre el principio y el fin del algoritmo y se devuelve el contenido en r cuando finalice le ejecución. 4.4 PROCEDIMIENTOS Son una abstracción operacional que nos va a permitir una amplia variedad de posibilidades. Es un algoritmo diseñado de tal forma que puede ser llamado por otro. Si un algoritmo a, necesita de la acción de otro b, diremos que a llama a b. La llamada de un procedimiento se hará igual que antes con un nombre y un conjunto de expresiones ( e1...en) y un conjunto de variables (v1....vn). Pero no podrá ser asignado a una variable. Nombre_proc (e1.....en, v1.....vn) PARÁMETROS: • Entrada: Podrá ser usado su valor pero no modificado. • Salida: Sus valores no podrán ser usados pero si modificados a la salida del procedimiento. • Entrada/ Salida: Sus valores podrán ser usados durante el procedimiento y a la salida del mismo. Sintaxis: Proc + nombre del procedimiento + un conjunto de variables que van a ser de entrada, salida, entrada/salida. Proc nombre_procedimiento (ent a1: Ta1, a2: Ta2.... an :Tan; sal r1: Tr1... rm: Trm ; ent/sal b1: Tb1.... bk: Tbk) Pre:{ P(a.......an ; b ........bk)} Pos:{Q(a1....an; r1 ........rm; b1 ......bk )} cons" 17 var " principio sentencias fin Semántica: Para llamar a un procedimiento se debe hacer: Nombre_procedimiento (e1.......en, v1........vm , w1........wk) Se evalúan los ei y se hace una asignación múltiple: < a1......an >:=< e1.....en > Los parámetros de entrada/salida se asignan a los otros. < b1.....br >:=< w1........wr > Se ejecutan las sentencias correspondientes. Se toman los valores, se hacen los cálculos y se devuelven: < v1.......vm >:=< r1.......rm > < w1.......wr >:=<b1......br > Ej: Proc intercambiar (ent/sal a, b: entero) Pre:{a=A " b=B} Pos:{a=B " b=A} Principio <a, b >:= < b, a > fin Ej programa: var n, m : entero principio n:=3 m:=5 intercambiar (n, m) 18 fin • VISIBILIDAD • DISEÑO MEDIANTE REFINAMIENTO Divide y vencerás • Identificaremos el problema complejo • Mejor descomposición para nuestro problema • Cualquier problema que no tenga descomposición trivial, lo descompondremos en subproblemas. • La mejor descomposición será aquella que me lleve a problemas triviales o simples en un menor número de niveles. • El programa no tendrá especificación pre/pos porque no tiene parámetros de entrada. Las constantes que se declaran para el programa principal y sus tipos serán heredados por el resto de funciones y procedimientos, podremos usarlas en el resto de los problemas que yo haya descompuesto. Las variables que yo necesite para resolver el problema principal no podrán ser usadas en las funciones y procedimientos por lo tanto no se usarán variables globales sino locales. TEMA 5. ESQUEMAS SECUENCIALES 5.0 Introducción 5.1 Acceso secuencial y directo 5.2 Acceso secuencial 5.3 Leer/ escribir flujos de datos 5.4 Esquema secuencial 5.5 Ejemplos 5.0 Introducción 5.1 Flujo de entrada o salida Es un conjunto de datos, todos del mismo tipo y ordenados según su orden de llegada, a los que se le asociará lo que llamaremos un generador de datos. Generador de datos: Admitimos que se pueden hacer las operaciones: primer elemento, siguiente elemento y último elemento. Flujo de entrada: Se puede hacer las operaciones hay elementos, escribir, conectar escritura y marcar. Secuencia: Un conjunto finito de elementos asociados a un flujo y al que se puede establecer los siguientes parámetros: longitud # , parte izquierda pi, parte derecha pd y elementos distinguidos = primer elemento de la parte derecha. Ej: Secuencia (S) caracteres Hola luis 19 ! elemento distinguido pi! Hola_l pd!uis ed!u #= 9 S=/a/ Pi/ed/pd Multiplicidad de un elemento en una secuencia es el número de apariciones que tiene. Tamaño: #(S)= 6 Declaración de flujos de datos Var: Identificador: flujo de entrada de Te Identificador: flujo de salida de Te!tipo descrito anteriormente OPERACIONES Las especificaciones de estas instrucciones son: Proc leer (sal r: Te; ent/sal fle: Flujo entrada Te) Pre:{Pi(S)= " pd(S)=b} Pos:{ r= a " pi(S)= a " pd(S) = b} Proc escribir (ent r: Te; ent/sal fls: Flujo salida Te) Pre:{ pi(S)= " r=a " r " M "pd(S)=<>} Pos:{pi(S)=a " pd(S)= <>} Siendo <> = secuencia vacía Y en los flujos de salida consideramos la operación: Proc marcar (ent/sal fls: flujo sal : Te) Pre:{ (pi(S) = " pd (S)= < > } 20 Pos:{ pi (S)=M " pd(S)=< >} Para las siguientes operaciones tendremos: Proc conectar_lectura (ent/sal fle: flujo entrada Te) Pre:{ cierto} Pos:{S=a " pi(S)= < > " pd(S)=a } Proc conectar_escritura (ent/sal fls: flujo salida Te) Pre:{cierto} Pos:{S=< >} Func hay_elementos (fle: flujo entrada Te) dev r:logico) Pre:{ S=a } o {cierto} Pos:{ pd(S)=< > ! r=falso " pd(S) " < > ! r=cierto} 5.4 ESQUEMA SECUENCIAL El primero de ellos es el llamado Esquema Básico. Considerando que aparecerá en alguna sección del algoritmo. E: Te y fle: flujo de entrada de Te y fls flujo de salida de Te. ESQUEMA BÁSICO DE RECORRIDO conectar_lectura (fle) inicializar_tratamiento mientras hay_elementos (fle) leer (e, fle) tratar e fmientras finalizar_tratamiento Son estructuras que permiten reducir a módulos sencillos los algoritmos fundamentales que actúan sobre los flujos de datos. Representación reducida de los rangos esenciales de un proceso. PROGRAMACION POR ESQUEMAS: Se llama ~ al sistema de plantear algoritmos generales a partir de esquemas simples. • ESQUEMA FILTRO: conectar_lectura (fle) 21 conectar_escritura(fls) mientras hay_elementos (fle) leer (e, fle) si condición escribir (e, fle) |otras: nula fsi fmientras marcar (fls) • ESQUEMA ACUMULADOR l:= l0 conectar_lectura (fle) mientras hay_elementos (fle) leer (a, fle) l:= l op a fmientras Donde l0 es ele elemento neutro del operador op. • ESQUEMA DE BUSQUEDA condición i=falso conectar_lectura (fle) tratamiento_inicial mientras hay_elementos (fle) y NO condición leer (e, fle) tratar(e) fmientras tratamiento_final 22 TEMA 6: TABLAS Y REGISTROS 6.1 Acceso directo 6.2 Tablas 6.2.1 Declaración, literales y operaciones. 6.2.2 Esquema de recorrido 6.2.3 Esquema de búsqueda 6.2.4 Esquema de ordenación 6.3 Registros 6.3.1 Declaración, literales y operaciones 6.3.2 Tablas de registros 6.1 ACCESO DIRECTO Decimos que una estructura de datos tiene acceso directo, si podemos alcanzar cualquier elemento de la misma sin necesidad de pasar por los elementos anteriores. i 1 2 3 ... 6 9 12 ... Debe de haber un índice o una variable 6.2 Tablas Son estructuras de datos homogéneas con acceso directo lineal y de tamaño finito. El concepto de estructura va a s3er el conjunto de datos. • Homogénea ! Todos los datos son del mismo tipo • Acceso directo ! Se puede disponer de un índice de un conjunto finito y ordenado que permite acceder a cualquiera de sus valores • Lineal ! Está almacenada de forma continua • Finito ! Valor máximo que puede manipular el algoritmo. TIPOS DE TABLAS • Vectores: Son tablas de una dimensión con un único índice, podemos acceder a cualquier casilla. • Tabla de Tabla: Son de dos dimensiones con dos índices. • Tabla de tabla de tabla: Son de 3 dimensiones con 3 índices. 23 6.2.1 DECLARACION DE TABLAS cons N=100 Max: 225 Var Identificador: tabla (constante entera) de tipo de dato T: tabla [20] de entero Tdias: tabla[N] de entero Nombre:tabla [Max] de caracteres • Al utilizarlas debo declararlas primeramente. Para construir una tabla se deben conocer primero los elementos que se van a tratar. En los tipos se pueden declarar tipos de tabla: Ej: Ttabla: tabla [20] de entero Tdias: tabla [N] de entero Se declaran los tipos Var t: Ttabla Tdias: Ttdias • LITERALES DE TIPO TABLA Cons N=100 Tipos Tb: .... Tt: Tabla[N] de Tb Var T:Tt Func bisiesto (anyo : entero) dev (l:logico) Principio 24 Si anyo%400=0 O (anyo%4=0 Y No anyo%100=0)) l:=cierto |otras l:=falso fsi fin Un literal para una tabla lo vamos a considerar como un tipo de elemento. L={ { a1, a 2 , ........an } con ai " Tb " 1 " i " N} OPERACIONES: Realizadas sobre tablas Descripción Perfil condiciones _[ _ ] : Tt x entero!Tb Acceso Modificación def t[ i ]" 1 " i " N _[ _ ! _] : Tt x entero x Tb ! Tt Def t[ i! e ] " 1 " i " N Ejemplo T= {a,a, a .....a, e, a,a.....a} Acceso: Como la operación es de acceso, lo que devuelve es el valor que ocupa (i) en la tabla. : = t[i] ! e Lo vamos a utilizar t[i ! e] " t[i] Modificación: t[ i ] : = e' Esto indica que modifique la tabla y donde esté i, coloca el valor e'. t={ a , a ,.....a , e', a ....} Admitiremos también la operación inicialización, pero sólo una única vez. t:={a ,......a } Las operaciones de tablas de 2 dimensiones: M: tabla [N] de tabla [M] de Tb M: tabla [ N, M] de Tb V:= m[ i, j] acceso 25 M[i, j] := v modifica L:{ {a11,a12... a1m} {a21, a22 , .......a2m}....{an1 ,an2 ......anm}} El tratamiento de tablas es análogo al de secuencia de datos. Fe 1 3 5 7 9 •! hay elementos (fe ) leer (e, f(e)) Guarda el dato 1 en e y luego se pasa al siguiente t[ i ] " 1 " i " N Esquema básico conectar lectura tratamiento inicial mientras (hay_elementos (fe)) leer (e, fe) tratar (e) fmientras tratamiento final Ej : Aplicamos este esquema i:= 1 tratamiento_inicial mientras ( i < > N+1) tratar (t[ i ]) I:= i+1 fmientras tratamiento final Hay otro tipo de esquema más simple, que realizaría la misma función. Uno de ellos sería la estructura desde. ESQUEMA SIMPLE DE RECORRIDO DE TABLAS 26 tratamiento_ inicial desde i:=1 hasta N tratar ( t[i]) fdesde tratamiento final Suponemos que en una tabla tenemos almacenada las ventas de un comercio, y queremos sumarlo todo. Cons Nmeses:12 Tipos Tt: tabla[Nmeses] de entero Var t:Tt Pre:{cierto} Pos:{suma:"k: 1 " k " Nmeses. (t(k))} Var var i:entero i:entero principio principio suma:=0 < i, suma>:=< 1, 0> desde i:=1 hasta Nmeses mientras (i< > Nmeses +1) suma:=suma + t[ i ] suma:=suma + t[ i ] fdesde i:=i+1 fmientras fin fin Cuando tenga una tabla de dos dimensiones: Cons N:... 27 M:... Tipos Tm: tabla[N,M] de Tb Var m:Tm i, j : entero Estructura para el tratamiento de una tabla de 2 dimensiones. Utilizaremos (desde). inicializar_tratamiento (Por columnas) desde i:=1 hasta N (M) tratamiento_inicial_de_fila (_de_columna) desde j:=1 hasta M (N) tratar_elemento (m[i,j]) ( m[j,i]) fdesde ! tratamiento_final_de_fila Solo se puede cambiar m[j,i] fdesde cuando la tabla es cuadrada tratamiento_final BUSQUEDA SECUENCIAL O LINEAL inicializar conectar_lectura enc:falso mientras (hay_elementos (f(e) Y No enc) leer (e, fe) si condicion: enc=cierta | otras :nula fsi fmientras 28 Para tablas inicializar i:=1 enc:=falso mientras (i < > N+1 Y No enc) si condicion: enc:= cierto | otras i:= i+1 fmientras fin Ej. cons N: 20 tipos Tt: tabla[ N] de enteros t: Tt b: logico Pre:{cierto} Pos:{b="k: 1" k"N . (t(k)=0) var i:entero enc:logico inicializar i:=1 enc:=falso mientras (i < > N+1 Y No enc) si (t[ i]=0) : enc:=cierto 29 | otras i:= i+1 fsi fmientras b:=enc fin En las tablas (si están ordenadas) hay un método de búsqueda más eficaz. BUSQUEDA DICOTÓMICA O POR PARTICIÓN cons N... tipos Tt= tabla [N] de Tb T:Tt v: Tb enc:logico Pre:{t=T " " q : 1" q" N . (t(q) " t(q+1)} busqueda_binaria Pos:{enc=" k: 1 " k " N . (t(k)=v)} var m,i,d:entero principio <i,d,enc>:= < 1, N, falso> mientras i<=d Y No enc n:=(i+1)/2 si t[m]= v : enc:=cierto |t[m]< v : i:=m+1 |t[m]> v : d:=m−1 30 fsi fmientras fin *Ver ejemplo de los apuntes La ordenación de tablas es bastante corriente y se puede aplicar a cualquier tipo de datos siempre que haya definido una relación total sobre todos sus elementos. Los tipos de ordenación dependen del tamaño del vector, del tipo de dato y de la cantidad de memoria disponible. Las soluciones más simples necesitan N2 accesos a la tabla y las soluciones más eficientes pueden llegar a tener solamente N*logN accesos. La especificación de la ordenación se puede realizar de esta manera: CASO MAS SIMPLE (Método de ordenación por selección) Suponemos un vector desordenado. Busca el menor y lo coloca en primera posición. 8 5 10 2 7 ................ N Esto lo hará mediante la operación de acceso y modificación t[i]:=t[j] Y así sucesivamente cons N:... tipos Tt: Tabla [N] en Tb t: Tt Pre:{t=T " N > 0} Pos:{t!permutaciones (T) "" k: 1" k"N. (t(k) " t(k+1))} var i,j, pos: entero x:Tb principio i:=1 mientras < > N 31 < pos, j > := < i, i+1> mientras j < > N+1 si t[pos]> t[j] : pos:=j |otras :nula fsi j:j+1 fmientras x:=t[pos] t[pos]:=t[i] t[i]:=x fmientras i:=i+1 fin METODO DE INSERCION Busca en la tabla la posición adecuada e inserta el elemento deseado. (Recorre la tabla de abajo a arriba) 8 8 8 8 2 5 5 5 2 4 10 10 2 4 5 2 2 4 5 6 7 4 6 6 7 4 6 7 7 8 6 7 10 10 10 var i, j,k : entero x: Tb principio i:=N−1 mientras i < > 0 < x, k, j >:= < t[i], i, N> 32 mientras k < > j si t[ k+1] < x : < t[k], k>:= <t[k+1], k+1> | t[k+1]>= x :j=k fsi fmientras t[k]:=x i:=i−1 fmientras fin REGISTRO: Es un conjunto de elementos que pueden ser de distintos tipos pero que están relacionados con una entidad particular. Cada componente de información de dicho elemento se llamará campo. Cada campo tendrá asociado un tipo de dato y un identificador. Declaración: registro identificador_1: tipo 1 (declarado previamente) _2: tipo 2 . . . identificador_n: tipo n fregistro cons N:20 tipos Tnom: Tabla [N] de caracteres Tpersona: registro 33 Nombre: Tnom Apel1:Tnom Apel2: Tnom Edad: entero Dni: entero fregistro • Elementos que podría contener una variable de tipo registro. tipos Tr: registro c1: T1 c2: T2 . . cn: Tn fregistro OPERACIONES EN REGISTROS: • Acceso: ! ci: Tr!Ti /Se aplica entre un registro y me va a devolver un elemento del tipo correspondiente al campo Ti/ • Modificación _.ci ! e : Tr x Ti ! Tr • Tabla de registros: Es un conjunto finito y ordenado de elementos de tipo registros y la declararemos: cons N:20 MAX:100 tipos Tnom: Tabla [N] de carácter Tpersona: registro nombre: Tnom apel1: Tnom 34 apel2: Tnom edad: entero dni: entero fregistro persona: tabla [MAX] de persona var p1: Tpersona tp:Ttpersona Ej: p1.edad:20 Tp[5].edad Tp[20].nombre [1] CADENAS: EL tipo cadena está definido en C: • Cuando se superan los 255 caracteres • Operaciones: < >, <=, >=, <, >, =, asignacion:= cad1:= cad2! strcpy (cad1, cad2) (copia cad2 en cad1) ! strcmp (cad1, cad2) (compara las cadenas) Función : longitud n:= longitud (cad1) leer leer cad1 escribir escribir cad2 EN C #define MAXCAR: 255 typedef char cadena [MAXCAR+1] cadena cad1, cad2; EN LEA cons MAXCAR: 255 35 tipos cadena: tabla[MAXCAR] de carácter var cad1, cad2: cadena. TEMA 7: FICHEROS 7.1 : Introducción 7.2: Definición y operaciones con ficheros 7.3: Esquemas de tratamiento. 7.4: Ficheros en lenguaje C EL dispositivo no se puede usar directamente por lo que hay que utilizar una variable o fichero. Para la utilización de ficheros se crean unas zonas de memoria intermedia. REGISTRO_LOGICO: Es la cantidad de memoria que el programador utiliza para obtener información. Al dispositivo de almacenamiento hay que darle un nombre, que será el nombre del fichero. La parte de la información del fichero que el programador utiliza se llama bloque. SINTAXIS DE FICHEROS: Fichero: Es el constructor que va a permitir declarar estructuras de datos permanentes con acceso secuencial o directo y que se van a especificar como secuencias de datos. Tipo base: Puede ser cualquier tipo predeclarado o definido (carácter, entero, real, cadena o registro) Su definición se realizará en el formato habitual : var f: fichero de Tb tipos Tpersona: registro nombre: cadena dni: entero edad: entero sueldo: real 36 fregistro var fp: fichero de Tpersona fe: fichero de entero fc: fichero de cadena OPERACIONES SOBRE FICHEROS Abrir: (nombre_externo, modo_apertura, variable_fichero) Esta operación hay que realizarla antes del fichero. Nombre_externo: Es una cadena de caracteres que contiene el nombre del fichero. Modo_apertura: ent, sal : soportes secuenciales ent/sal: soporte de acceso directo Cerrar (variable_fichero) Ej: apertura de fichero/cierre Abrir ( Datos, trt, sal/ent, fc) ! Los datos se encuentran en este fichero var fc: fichero cadena cad: cadena cerrar (fc) Leer (variable_elemento, variable_fichero) Leer (variable_elemento, variable_fichero, posición) ·Ej: var var fc: fichero cadena fc: fichero cadena cad: cadena cad: cadena 37 cad1: cadena cad1: cadena leer (cad1, fc) leer (cad1, fc, m) n: 1 " n "#(Sf) ! entero que está comprendido en el do minio escribir: En esta operación abrir debe estar en sal/ para poder escribir datos var fc: fichero cadena cad: cadena cad1: cadena escribir( cad1, fc) escribir (cad1, fc, n) n: 1 " n " #(Sf) fdf (fc) ESQUEMAS DE TRATAMIENTO tipos Tpersona: registro nombre: cadena edad: entero fregistro Tfpersona: fichero de Tpersona var f: Tfpersona nom_fich: cadena principio abrir (nombre_esterno, modo, f) tratamiento_fichero 38 cerrar (f) principio leer nom_fich abrir (nom_fich, modo,f) tratamiento_fichero cerrar (f) Ej: A partir de un flujo de entrada de enteros crear fichero fle: flujo entrada de entero tratamiento_fichero Pre:{fle=} crear_fichero Pos:{f=} var r:entero El modo será de salida. La variable f cambiará a fichero de entero. principio conectar_lectura(fle) mientras( hay_elementos (fle)) leer (r, fle) escribir (r, f) fmientras *(Dentro de tratamiento) Ahora queremos copiar un fichero var f1, f2: fichero de entero 39 nom_fich1: cadena nom_fich2: cadena principio leer nom_fich1 leer nom_fich2 abrir (nom_fich1, ent, f1) abrir (nom_fich2, sal, f2) mientras (no fdf(f1)) fdf hasta que lea el último elemento leer (r, f1) de f1 si (condicion): Si no queremos copiar todo el fichero escribir (r, f2) 1, utilizaremos filtros. |otras nula fsi fmientras cerrar (f1) cerrar (f2) CARGA DE UN FICHERO EN UNA TABLA Pre:{f= " #() " N} Pos:{ t= } cons N:100 var nom_fich: cadena f: fichero de entero t: tabla [N] de entero r: entero 40 i: entero principio leer nom_fich abrir (nom_fich, ent , f) i:=1 mientras ( no fdf(f)) leer (r, f) t[i]=r i:=i+1 fmientras cerrar (f) ESQUEMA DE BÚSQUEDA Pre:{f=} Pos:{enc= " i : 1 " i " #() . P ((i))} Esquema var nom_fich: cadena f:fichero de entero r:entero enc: logico principio leer nom_fich abrir (nom_fich , ent, f) enc:=falso mientras (no fdf (F) Y No enc) leer (r, f) 41 si (r=0): enc:=cierto |otras: nula fsi fmientras cerrar (f) ESQUEMA DE CONCATENACION f1, f2!f Pre:{f1= " f2=} Pos:{f=} var r: Tb principio abrir( nom_fich 1, ent, f1) (nom_fich 2, ent, f2) abrir (nom_fich 3, sal, f) mientras (No fdf (f2)) leer (r, f2) escribir (r,f) fmientras cerrar (f1) (f2) (f) fin ESQUEMA DE PARTICIÓN f1, f2, f: fichero de Tb Pre:{f=} 42 Pos:{f1= " f2= " B" " f" " pertenece ( (i), , , P} Pertenece{(e, , , P)=P(e)! e" B " ø P(e) !e " . var r: Tb principio abrir (nom_fich1, sal, f1) abrir (nom_fich2, sal, f2) abrir (nom_fich, ent, f) mientras (no fdf (f)) leer (r,f) si P(r): escribir (r, f1) |otras: escribir (r, f2) fsi fmientras cerrar (f1) cerrar (f2) cerrar (f) fin ESQUEMA DE FUSIÓN f1, f2, f: fichero de Tb Pre:{f1= " f2= " ordenado (f1) " ordenado f2} Pos:{f= " " " " " ordenado )} var r1,r2: Tb principio 43 abrir (nom_fich 1, ent, f1) abrir (nom_fich 2, ent, f2) abrir (nom_fich, sal, f) leer (r1, f1) leer (r2, f2) mientras (no fdf (f1) Y No fdf (f2)) si r2 <= r2 escribir (r2, f) leer (r2, f2) fsi fmientras si fdf(f1) Y No fdf(f2): tratamiento_final_fusion (r1, r2, f2, f1) |fdf (f2) Y No fdf(f1): (r2, r1, f1, f) |otras : insertar_dos(r1, r2, f) fsi cerrar(f1) (f2) (f) proc trat_final_fusion (ent: r1, re: Tb, ent/sal fe,fs: fichero de Tb) Pre:{r= " re =b " fe= a < B " fs= } Pos:{fs= " < a > " < b > " < c > " " ordenado ()} var insertado:logico principio insertado:=falso mientras No fdf(f(e)) Y No insertado 44 si re<= ri escribir (re, fs) leer (re , fe) |otras escribir (r, fs) escribir (re ,fs) fsi encontrado:= Existe fmientras si No insertado: insertar_dos (re , r, f) |otras mientras No fdf (fe) leer (re , fe) escribir(re , f) fmientras fsi fin ORDENACIÓN DE FICHEROS • Llevar fichero a tabla #(Sf)" MAX • Ordenar tabla • Crear nuevo fichero cons MAX: 1000 t: tabla[Max] de Tb FICHEROS EN C • Streams • Ficheros • Puntero o fichero • Funciones relativas o ficheros 45 • Apertura • Cierre • Entrada / salida STREAMS: Dispositivos lógicos que pueden asociarse indistintamente con teclado, pantalla, discos, disquetes o puertos de comunicación asociándoles una zona intermedia de memoria denominada buffer y un conjunto de operaciones E/S que permiten el tratamiento de los datos almacenados en el dispositivo, de forma que para el programador, todos los dispositivos sean idóneos y solamente estarán delimitados por sus características técnicas, como velocidad o tipo de acceso. En C van a existir dos tipos de stream: • Stream de texto: compuesto por un conjunto de caracteres que terminan en uno o más caracteres que simbolizan fin de linea. • Stream binario: Cuando la información no está delimitada por el fin de línea, está formado por un conjunto de bits sin más. Un fichero en C, se considera como aquella información almacenada en un dispositivo externo y asociado a una variable lógica mediante una operación que vamos a llamar apertura. Existen 3 ficheros en C abiertos automáticamente, que nos permite acceder a ellos. Son las correspondientes a la salida y entrada estándar. • Salida estándar: stdont (pantalla) • Entrada estándar: stdin (teclado) • Salida error: stden (pantalla) Definición de un fichero: FILE"* f; FILE"*fopen (char *nombre fichero, car *modo) T:=fopen (imagen_txt, w); I.T. Informática de Sistemas. Introducción a la programación 1. 43 1 I. T. I. S 46