Programación en Lenguajes Estructurados

Ciclo de Desarrollo de Aplicaciones Informáticas

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

i

1.- RESOLUCIÓN DE PROBLEMAS CON ORDENADOR..................................................... 1 1.- Introducción. ....................................................................................................................................1 2.- Concepto de algoritmo.....................................................................................................................1 3.- Análisis del problema. .....................................................................................................................2 4.- Diseño del algoritmo. .......................................................................................................................3 4.1.- Escritura inicial del algoritmo. .....................................................................................................4 5.- Herramientas de programación. ....................................................................................................6 5.1.- Diagramas de flujo........................................................................................................................6 5.2.- Pseudocódigo................................................................................................................................7 6.- Los lenguajes de programación. .....................................................................................................7 6.1.- Instrucciones del ordenador..........................................................................................................8 6.2.- Lenguajes máquina. ......................................................................................................................8 6.3.- Lenguajes de bajo nivel. ...............................................................................................................8 6.4.- Lenguajes de alto nivel. ................................................................................................................9 6.5.- Traductores de lenguaje................................................................................................................9 6.5.1.- Compiladores.........................................................................................................................9 6.5.2.- Intérpretes. .............................................................................................................................9 7.- Resolución del problema mediante ordenador. ..........................................................................10 7.1.- Codificación del algoritmo en un programa. ..............................................................................10 7.2.- Ejecución de un programa. .........................................................................................................10 7.3.- Verificación y depuración de un programa. ...............................................................................10 2.- ELEMENTOS GENERALES DE UN PROGRAMA.......................................................... 13 1.- Datos y tipos de datos. ...................................................................................................................13 1.1.- Datos numéricos. ........................................................................................................................13 1.2.- Datos carácter o alfanumérico. ...................................................................................................13 1.3.- Datos lógicos o booleanos. .........................................................................................................13 2.- Identificadores, constantes y variables. .......................................................................................14 2.1.- Identificador................................................................................................................................14 2.2.- Constante. ...................................................................................................................................14 2.3.- Variable.......................................................................................................................................14 3.- Expresiones.....................................................................................................................................15 3.1.- Expresiones aritméticas. .............................................................................................................15 3.2.- Expresiones lógicas (booleanas).................................................................................................16 3.3.- Operaciones alfanuméricas.........................................................................................................17 3.4.- Orden de evaluación de los operadores. .....................................................................................18 3.- INTRODUCCIÓN A LA PROGRAMACIÓN ESTRUCTURADA. ..................................... 21 1.- Concepto de programa. .................................................................................................................21 2.- Tipos de instrucciones. ..................................................................................................................21 2.1.- Instrucciones de declaración.......................................................................................................21 2.2.- Instrucciones primitivas..............................................................................................................22 2.2.1.- Instrucción de asignación. ...................................................................................................22 2.2.2.- Instrucción de lectura de datos. Entrada. .............................................................................23 2.2.3.- Instrucción de salida de datos. .............................................................................................23 2.3.- Instrucciones de control..............................................................................................................24 2.3.1.- Instrucciones alternativas.....................................................................................................24 2.3.1.1.- Alternativa simple.........................................................................................................25
alozanoi@teleline.es Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

ii

2.3.1.2.- Alternativa doble. .........................................................................................................25 2.3.1.3.- Alternativa múltiple. .....................................................................................................25 2.3.2.- Instrucciones repetitivas. Bucles. ........................................................................................26 2.3.2.1.- Estructura MIENTRAS. ...............................................................................................27 2.3.2.2.- Estructura REPETIR.....................................................................................................27 2.3.2.3.- Estructura PARA. .........................................................................................................28 2.3.3.- Instrucciones de ruptura de secuencia. ................................................................................28 3.- Variables auxiliares de un programa...........................................................................................29 3.1.- Contadores. .................................................................................................................................29 3.2.- Acumuladores. ............................................................................................................................29 3.3.- Interruptores................................................................................................................................29 4.- Escritura de programas.................................................................................................................30 4.1.- Cabecera del programa. ..............................................................................................................30 4.2.- Declaración de objetos................................................................................................................30 4.3.- Cuerpo del programa. .................................................................................................................30 4.- SUBPROGRAMAS. ......................................................................................................... 35 1.- Introducción a los subprogramas.................................................................................................35 2.- Funciones. .......................................................................................................................................35 2.1.- Declaración de funciones............................................................................................................36 2.2.- Invocación a las funciones..........................................................................................................36 3.- Procedimientos o subrutinas.........................................................................................................37 4.- Ámbito: variables locales y globales.............................................................................................38 5.- Comunicación con subprogramas: paso de parámetros. ...........................................................39 5.1.- Paso por valor. ............................................................................................................................39 5.2.- Paso por referencia. ....................................................................................................................39 5.- CARACTERÍSTICAS GENERALES DE LOS PROGRAMAS EN LENGUAJE C. .......... 41 1.- Estructura de un programa C. .....................................................................................................41 1.1.- Comentarios................................................................................................................................41 1.2.- Cabecera. ....................................................................................................................................41 1.3.- Entorno. ......................................................................................................................................42 1.4.- Función main()............................................................................................................................42 2.- Elementos del lenguaje C ..............................................................................................................42 2.1.- Léxico de C.................................................................................................................................42 2.2.- Sintaxis de C. ..............................................................................................................................43 3.- Ejemplo de programa en lenguaje C............................................................................................43 6.- TIPOS DE DATOS, OPERADORES Y EXPRESIONES .................................................. 45 1.- Tipos de datos.................................................................................................................................45 2.- Constantes.......................................................................................................................................46 2.1.- Constantes enteras. .....................................................................................................................46 2.2.- Constantes reales. .......................................................................................................................47 2.3.- Constantes de un sólo carácter....................................................................................................47 2.4.- Constantes de cadena..................................................................................................................47 2.5.- Expresiones constantes. ..............................................................................................................47 2.- Variables: declaración...................................................................................................................48 3.- Operadores. ....................................................................................................................................48
alozanoi@teleline.es Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

iii

3.1.- Operadores aritméticos. ..............................................................................................................48 3.2.- Operadores relacionales y lógicos. .............................................................................................48 3.3.- Operadores de incremento y decremento. ..................................................................................49 3.4.- Operadores de asignación y expresiones. ...................................................................................49 3.5.- Operador condicional..................................................................................................................50 4.- Conversión de tipos........................................................................................................................51 5.- Precedencia y orden de evaluación de los operadores................................................................52 7.- ENTRADA Y SALIDA POR PANTALLA ......................................................................... 53 1.- Acceso a la librería estándar.........................................................................................................53 2.- Funciones de entrada y salida estandar.......................................................................................53 2.1.- Salida con formato. Función printf(). .........................................................................................53 2.2.- Entrada con formato. Función scanf(). .......................................................................................55 3.- Función getchar()...........................................................................................................................57 4.- Función putchar(). .........................................................................................................................58 5.- Función gets(). ................................................................................................................................58 6.- Función puts(). ...............................................................................................................................58 7.- Funciónes getch() y getche()..........................................................................................................58 8.- SENTENCIAS DE CONTROL DE PROGRAMA.............................................................. 59 1.- Introducción. ..................................................................................................................................59 2.- Sentencias y bloques. .....................................................................................................................59 3.- Sentencias de selección o condicionales. ......................................................................................59 3.1.- Sentencia if-else..........................................................................................................................59 3.2.- Sentencia switch. ........................................................................................................................60 4.- Sentencias de iteración o bucles....................................................................................................61 4.1.- Sentencia while...........................................................................................................................61 4.2.- Sentencia for. ..............................................................................................................................63 4.3.- Sentencia do-while......................................................................................................................64 9.- TIPOS DE VARIABLES, PUNTEROS Y FUNCIONES .................................................... 67 1.- Tipos de variables. .........................................................................................................................67 1.1.- Variables locales.........................................................................................................................67 1.2.- Variables globales.......................................................................................................................67 1.3.- Variable estáticas. .......................................................................................................................67 1.4.- Variables registro........................................................................................................................67 2.- Teoría básica de punteros. ............................................................................................................68 2.1.- Variables puntero........................................................................................................................68 2.2.- Operadores de punteros. .............................................................................................................68 3.- Funciones. .......................................................................................................................................70 3.1.- Declaración de funciones............................................................................................................70 3.2.- Definición de funciones..............................................................................................................71 3.3.- Llamada a funciones. ..................................................................................................................71 3.4.- La función main(). ......................................................................................................................71 3.5.- Retorno de valores. .....................................................................................................................72 3.6.- Paso de parámetros. ....................................................................................................................72 3.6.1.- Paso de parámetro por valor. ...............................................................................................72 3.6.2.- Paso de parámetros por referencia.......................................................................................72
alozanoi@teleline.es Apuntes de clase

.................. ................................................................................................................................81 4......................................................................Representación de las cadenas.................1..............................................Operaciones sobre matrices............99 4....................................................................................................................... ..........................................................87 5................99 4.................I....... ..... CAMPOS DE BITS Y UNIONES ....Búsqueda lineal en una matriz.............................................................Mezcla de vectores.................... Página: iv 10....Ordenación de tablas.....98 4........................Paso de estructuras a funciones....................................................................................................................... ...........Declaración de estructuras.............................93 2.......Funciones de conversión......................88 6..........................Ejemplos de funciones con cadenas..........Arrays de estructuras....................3..2...........................................................................103 2...........................................113 6......................................................................................................... 93 1.....Funciones de estándar para la manipulación de cadenas............. .........2......................1...........................................................................................................................................CADENAS DE CARACTERES....................................Ordenación por selección directa.....90 11..............76 3............................1..................Ordenación por intercambio directo o método de la burbuja..................Funciones de caracteres..107 7....USO DE PUNTEROS COMO ARRAYS.....Tablas: conceptos...................................................................................... .......................................Tipos de tablas..Uniones... ............© A...Inicialización de arrays de caracteres........................... ............................88 6..................Búsqueda binaria o dicotómica en un vector..........Arrays bidimensionales y punteros....Tablas unidimensionales o vectores.......Búsqueda lineal....................... ........Manipulación de estructuras...................................................... ...................................ESTRUCTURAS DE DATOS ESTÁTICAS...................................................................................Búsqueda lineal en un vector ordenado..............................................................Reserva de memoria..104 5................................................................................................1..............A........................................................................................................................................................................... ........89 6...85 4......................Tipos de datos definidos por el usuario ...103 3............... D.75 3.................................... ...................Ordenación por inserción directa..........................................................................................75 2...........................I................es Apuntes de clase ....104 4......................................ESTRUCTURAS.................................... ..........Arrays unidimensionales.....Búsqueda lineal en un vector no ordenado..................................... .............................................................................................................. 103 1..................................................................................................................... ...116 alozanoi@teleline..............Tablas bidimensionales o matrices..........114 7............................................................................100 12.............Introducción a las estructuras de datos..................... 109 1..................... ......................... ........................... Programación en lenguajes estructurados....2..Introducción ............................................85 4........106 6........... ................................................................Definición de registro o estructura......................................................Arrays unidimensionales y punteros.....................................................................Operaciones sobre vectores.....................3.................... 75 1...............112 5..............109 2.......L. ........................................1..............87 6......................80 3................................................Arrays bidimensionales................1..................................................76 3..................................................................................108 13.................................................................................... definiciones y representación........ ....... ........................................89 7.95 3.....Estructuras y punteros.....109 3............ ..............2................................................................................................................................................Paso de parámetros array a funciones.......................................................86 4.......................115 8...........................111 4........................2..1....................................................77 3...........................

...................................................2.............................................124 6................Organización directa.... ....2..................................... .142 11............................................................................................Posicionamiento en el fichero: e/s de acceso directo..................Detectar fin de fichero..................................................2........................Clasificación según el almacenamiento físico en el soporte.............2..Partición de archivos....2.....................138 7...Cambiar el nombre de un archivo.....................................139 9............... ..................................................................es Apuntes de clase ....133 7........................135 7...Rupturas de control.........Desplazamiento al comienzo del archivo..138 8..Cerrar archivo...................127 6.............................................................2..........Clasificación según su uso.1....................................118 14.................................................1................Reasignación de archivo....... .139 8.........................Búsqueda en archivos desordenados....................................................................................................................Conceptos.............125 6.......................... ............1..........Mezcla de archivos desordenados.......................................Operaciones sobre registros...........................11.......................................................................................122 3........................................................ ............L.....Búsqueda en archivos ordenados........................4.....................Mezcla de archivos ordenados..........139 8............................................................................................................. ............. definiciones.............137 7..............................................................................................122 3.141 10...............................................................................Posición actual de la cabeza de E/S......................123 4..................137 7.1......... .......... ....................................................................................................................9................Enumeraciones.......Archivos en lenguaje C.....................................................2....................................................................142 10................Clasificación por mezcla directa..Clasificación según su método de acceso..............Organización secuencial indexada.................... Página: v 9..............................1................................................................................ESTRUCTURAS DE DATOS EXTERNAS..................Clasificación de los archivos............. reapertura...............................137 7............................143 11............................................8.........................................................2..............Mezcla de archivos.....................142 10...........122 3.......Organización relativa............................................140 9.....................Organización relativa o indirecta............................................145 12.135 7....................... .....................Detección de errores.............................................................................Creación y apertura de un archivo...........................................Introducción.........................................................................................................123 5....124 6........................................................................... ...................................................................................14.........I...............121 2...........................Campos de bits......................................................................................................Lectura y escritura de bloques de información..............13.123 3.......................................... .................................................................© A...............................................Borrar un archivo........126 6.1............................Vaciar el buffer.......................................................140 9.......................... ........ Programación en lenguajes estructurados..........................................Partición por contenido.......... ..............................Clasificación por mezcla equilibrada............. ......7............................................126 6........ .................................................................................................. ..............................................Organización de los archivos..A...................................3.............6.129 7.137 7.........................................................5...........................137 7........................................... 121 1.................. .....................................131 7........................129 7...............12....... ......................................................................145 alozanoi@teleline....... D......................... ........................Operaciones sobre archivos...................136 7..........................Lectura y escritura de cadenas........ ............... .............................I.............................15..............................4................ ..........131 7................121 3..........Búsqueda en archivos......2........117 10..........Partición en secuencias..................................................................132 7.........................................Clasificación desde el punto de vista del usuario....Entrada y salida con formato...1..................................................................................................................................................................Organización secuencial.....................................................................................3.................Clasificación de archivos......3..................................143 11.......Lectura y escritura de caracteres..2..............................................................................................1.........................10.............................................................127 7.... ..........

........................................165 3.......................Añadir nodos a la lista..............Árboles..2....2...............3..........................Colas.............166 3....7........ elementos y representación de los árboles. Detrás del apuntado............189 3..................3...............................................................184 2........................187 2.............161 2..........2...............................3..........159 2...4..............3.............................................................................Inserción en árboles ordenados............................. ......................................................................Recorrido de la lista...............................................169 4...........................184 2................................................184 2.........L..2......................................................159 2..............1........................2..3. Programación en lenguajes estructurados.......1................. .................................... .................................2................................ 178 1............................Buscar en árboles ordenados.............Insertar en la lista....................................................Construcción un árbol binario equilibrado.........Operaciones sobre listas enlazadas circulares.....................Extensión del nombre de los ficheros............................. ........ D...................................................................Operaciones sobre listas doblemente enlazadas ..........................................167 4.......................Declaración simplificada de variables estructura y enum............ 189 1........................1................189 alozanoi@teleline...........171 4......................................Implementación.................................................................163 3...........5...................1........................LENGUAJE C++ COMO UN C MEJORADO.............................................Pilas.....Insertar entre dos nodos............................................ 157 1........................189 2.....1............171 4.......................................................................................................................160 2..............................2.................. ................................3.........169 4........2........................2.................................168 4.......................162 2..............................................I.....................Funciones de inicializar........2.......1.1..Lista vacía........Insertar entre dos nodos............1...............................................173 5...........................................2..................159 2.1....................................2...................................................................1......................................Ver si el árbol está vacío..................2.........Recorrido de un árbol...1....2..............................Inicialización.............................1.......... .......................2..............................Listas doblemente enlazadas.....159 2......................... .....................................174 6............................................................................Inserción en una lista ordenada...1............................1............ ........Insertar al final de la lista...............A...1.....................Insertar en medio o al final de la lista..............Definición de árbol binario y su representación........ESTRUCTURAS DINÁMICAS LINEALES DE DATOS ..168 4..................................................................... . Delante del apuntado...........................1...............................................................187 17.....158 2...............Introducción............2.............2................................4..............2................... ................................1......157 2...........................................Borrar un nodo de la lista..............................................................................2..................................................2..........2......183 2...4.......................................1.......Insertar al principio de la lista........1.................................................... .................. ......................1............Creación de un árbol..................................Listas enlazadas..............Comentarios.Definición.........................................2............................ ...186 2..........................................Operaciones con árboles binarios......................182 2.......160 2..............................1..............165 3..........................................................169 4....................Borrar un nodo de la lista................................. ...........1.......................... ....3...........................Listas enlazadas circulares... crear un nuevo nodo.................184 2............................1.....................................174 16......................................... ......6...1................Operaciones básicas para la manipulación de listas.............170 4.........................2......................2...................................................185 2.Recorrido de una lista....4..........................3.164 3...157 2...................................Recorrido de la lista........ESTRUCTURAS DINÁMICAS NO LINEALES DE DATOS........... ................... ....... ...................I.......167 4.5....... .182 2....................... ................................. vacía............................................................2...............Insertar en lista doble.......Insertar al principio de la lista.........................1...............2......es Apuntes de clase ..............................2..........................................© A.. .....................1... Página: vi 15.................................... ................. ...........Borrado de nodos de la lista.........Recursividad.............1.............................1........................178 2.....3......1.....2..Borrado en árboles ordenados.......................

.............................2............. . ............................................................................................................Vectores de objetos..........................Comportamiento del objeto.............190 8.............................. Programación en lenguajes estructurados......................................................................204 3.......................................................................Sobrecarga de operadores en clases.......................................4...............................................© A...........192 12........Encapsulamiento...........................6........Instanciación de objetos................................................................................................................................1.....5..................Especificador const para punteros......1............................Constructor copia y el operador de asignación.........8..............2.........................195 18....2.................Jerarquía..........................195 15...........................................................................199 2.............PROGRAMACIÓN ORIENTADA A OBJETOS.Conversiones explícitas de tipo........ ..................................................................192 13..............Nueva forma de realizar la entrada y salida................................................. ......................... ....Relación de asociación.................202 3....................................Relación de uso..1................2...................................................Variables de tipo referencia....................Campo de clase .........................................Nivel de acceso....................................215 3.... ....... ..... ..... ..................................189 6..................Control de acceso a miembros......................... .............................................................................................................................................Objetos dinámicos.............................4.......213 3.....................................3.201 2................................................................................Introducción.....................Características de la poo..... .............................................1.8.................................................................... Página: vii 4.....................................215 3..............189 5......................................3............................................................7.................................2............................. ................................................................................................................................................200 2.............211 3...................................................................................I.....7.....................217 4........................................1................................201 3...........................................Clase...................203 3...............1...............................................................................208 3...................................................... ...............194 14...................................Operadores new y delete.....................................................................................................................Abstracción..Estado del objeto.................................................Especificador const para variables............................I....5........ ..................4....Declaración de clases.................. .2.....................Sobrecarga de operadores....................................2.................. ...Destructor..1.......................................5...........Creación e inicialización de objetos..............................Clases y objetos............................Constructor por defecto.........................Constructores generales....................................................................217 4........................................191 11...............Sobrecarga de funciones.................................................Especificador inline para funciones....202 3......... .........................201 3.......................................................................................204 3...........207 3........203 3.......................Objeto................................191 10...............................205 3.......................8.... ................ Gestión dinámica de memoria ..............4........2................215 4...................................................Componentes o miembros de la clase..............Relaciones entre clases........................................211 3..............................Flexibilidad en la declaración de variables...3...........................2.......................206 3................................................... ..........................L................................3................................................Relación de herencia.....................2.....................................................................................212 3............................................209 3..................................................................7...........................................................199 2.........................................213 3.............................. 199 1...............................................7...... moldeo...................................3...............208 3.......................................................Identificador.............Punteros a objetos.................................. ........................217 4...................................1............................................................... .................................7..........218 alozanoi@teleline...200 2.........................1...........204 3...........................................Operador de resolución de visibilidad..Relación de agregación.........210 3.......1............................3...........................Identidad del objeto...A. .. .........................................................................................Valores por defecto de parámetros de una función............190 7............Acceso entre clases amigas................... ...................2.. D...................2...........................es Apuntes de clase .Modularidad.......................190 9....217 4...............

......I.............................230 alozanoi@teleline............ ..............2...........................................227 6....... Página: viii 4........... ....................................1......230 7.........................Clases abstractas.....© A................................................Herencia múltiple y clases virtuales.................4...Herencia de clases........................Lenguaje Smalltalk.........................................4...2........................................................... ................................2...........229 7............................. Programación en lenguajes estructurados.1......Lenguajes de POO.......................................4.......................1.............2..................................................I....................................................... ...........................Polimorfismo...............................Lenguaje C++.......................222 4............................Sobrecarga de métodos y operadores.........................................3..............................................L.........224 5.....................2........Lenguaje Java........... ......A.................................. .........................................es Apuntes de clase ..... D.....225 5.....2.........220 4....................................................................................................................... .............230 7...................225 5.......Enlace dinámico..228 7.... ............Acceso a miembros heredados y tipos de acceso................1..........................................................3....Conversiones entre objetos de clases base y clases derivadas................225 5........................Enlace estático................................................. ................... ..........224 5.............................

adaptar y probar programas para mejorar la explotación del sistema y las aplicaciones. D. OBJETIVOS. hemos optado por el siguiente enunciado para el contenido organizador: Elaborar. Integrar y enlazar módulos de programación. que el aprendizaje se orienta hacia los modos de saber hacer. A este procedimiento general y global está asociado un amplio conjunto de conocimientos de carácter conceptual que constituyen los contenidos soporte de las habilidades y destrezas que los alumnos deben adquirir. el contenido organizador.© A. teniendo en cuenta el perfil profesional del título y considerando las responsabilidades asignadas a la función de administración en el entorno de los sistemas. Analizando las capacidades terminales del módulo. Conocer y usar las utilidades para desarrollo y puesta a punto de programas. rutinas y utilidades.es Apuntes de clase . Teniendo en cuenta las capacidades terminales asociadas al módulo y las características generales del ciclo formativo. se entiende que el proceso educativo ha de organizarse en torno a los procedimientos.L. Entender y manejar las estructuras de datos internas. Por tanto. alozanoi@teleline. Codificar programas en lenguajes de programación de tercera generación. Aplicar las técnicas de programación estructurada empleando la metodología más frecuentemente utilizada para programar.I. Entender y manejar las estructuras de datos externas. Conocer las características generales de los lenguajes de tercera generación. Utilizar el lenguaje de programación C para la codificación de los programas. siguiendo las especificaciones del diseño y el diagrama de estructuras. El contenido organizador debe comprender y aglutinar todas las capacidades que pretendemos que desarrolle el alumno y que vienen expresadas como capacidades terminales del módulo en el Real Decreto que define el título. será de tipo procedimental. incluidas y no incluidas en el entorno de desarrollo integrado. que habitualmente proporcionan los lenguajes de programación. Página: ix INTRODUCCIÓN.I. el eje del proceso de aprendizaje. Conocer los elementos básicos de un programa: datos. Programación en lenguajes estructurados. · · · · · · · · · · · · Adquirir el concepto de programa como método para resolver problemas generales.A. operaciones sobre los datos e instrucciones de control y manipulación. Adquirir el concepto de programación orientada a objetos y ser capaz de codificar programas en lenguaje C++ con las características de la POO. es decir. tanto estáticas como dinámicas. Documentar las instrucciones y las estructuras de datos utilizadas para diseñar los programas y redactar la documentación técnica y la guía de uso de los programas.

que habitualmente proporcionan los lenguajes de programación. C++. Para poder llegar a realizar un programa es necesario el diseño previo de un algoritmo.es Apuntes de clase . El eje central de la metodología gira en torno al concepto de algoritmo. para ejecutarlo. Página: 1 1.I. de la misma forma que una receta de cocina puede ser expresada en cualquier idioma. debemos tener en cuenta que el lenguaje de programación es..L. Pascal. Por ejemplo. El propósito fundamental de éste módulo es la resolución de problemas mediante un ordenador. de forma que sin un algoritmo no puede existir un programa.. PROBLEMA -> DISEÑO DEL ALGORITMO -> PROGRAMA DE ORDENADOR -> EJECUCIÓN Cualquier algoritmo es independiente del lenguaje de programación en el que se expresa el problema y de la máquina que ejecuta el programa. Validación y ejecución del programa por el ordenador: comprobar si el programa resuelve o no el problema planteado y es válido para todo el conjunto de datos posibles.Introducción. Entender y manejar las estructuras de datos: internas (estáticas y dinámicas) y externas. Programar en lenguajes estructurados de tercera generación: Lenguaje C. alozanoi@teleline. incluidas y no incluidas en el entorno de desarrollo integrado. Expresar el algoritmo como un programa en un lenguaje de programación adecuado: C. y un ordenador es sólo un procesador.A. Programación en lenguajes estructurados.Concepto de algoritmo. todo problema puede ser expresado en forma de algoritmo. es decir. D. pero los pasos para la elaboración del plato se realizarán sin importar el cocinero. Los pasos necesarios para resolver un problema son los siguientes: · · · Diseño del algoritmo: describe la secuencia ordenada de pasos que conducen a la solución de un problema dado. Un algoritmo es un método general de resolución de todos los problemas del mismo tipo. Conocer y usar las utilidades para desarrollo y puesta a punto de programas.© A. etc. si queremos calcular el área de un rectángulo... en realidad.I. el algoritmo realizado debe ser el mismo para calcular el área de cualquier rectángulo. Por tanto. un mero medio de expresar un algoritmo. independientemente de que tengan una altura o una base mayor o menor. Documentar los programas. Introducir al alumno en la programación orientada a objetos. 2. una máquina.RESOLUCIÓN DE PROBLEMAS CON ORDENADOR 1. el algoritmo que estamos utilizando para resolver este problema consta un conjunto de pasos que nos han enseñado en clase de matemáticas. siendo éste valido para todos los problemas de iguales características. Los objetivos que se pretender conseguir son los siguientes: · · · · · · Aplicar las técnicas de programación estructurada usando la metodología más frecuentemente utilizada para programar.

L. un algoritmo es cualquier manual de instrucciones que describa paso a paso las acciones que debemos realizar para conseguir una meta final. el conjunto de operaciones realizadas con los datos de entrada para poder ofrecer una solución. En definitiva.es Apuntes de clase .A.I. para calcular la velocidad a la que se desplaza un cuerpo pueden darnos la siguiente descripción: calcular la velocidad a la que corre un atleta los cien metros lisos si tarda en realizarlos diez segundos. manual de uso de una radio. alozanoi@teleline. Esto no implica que el camino (algoritmo) para cumplir el objetivo sea único. Programación en lenguajes estructurados. No debemos encender el ordenador sin haberlo conectado previamente a la red eléctrica o no debemos tirar de la palanca de cambio de marcha del coche sin haber pisado antes el embrague por que los resultados son imprevisibles. Por ejemplo. o sea. puede haber. Debe indicar el orden correcto de la realización de cada paso. D. Es la primera fase de la resolución de un problema con un ordenador. 3) ¿Cual es el método que produce las salidas a partir de las entradas? Habitualmente. pasos para la instalación de un juego en el ordenador. este debe terminar en algún momento.Análisis del problema. 2) ¿Cuales y cuantas son las salidas? Son los resultados (datos) que nos pide el enunciado. Cada uno de estos pasos debe realizarse en el orden en que se indican para poder solucionar el problema. está bien definido. por ejemplo el manual de instalación de un televisor. de hecho hay. distintos caminos para llegar al mismo lugar. En el ejemplo.. el método consiste en la aplicación de la fórmula para calcular la velocidad (v= s/t). Las características fundamentales de un algoritmo son las siguientes: · Un algoritmo debe ser preciso. Por ejemplo. Podemos plantearnos una pregunta: ¿Llegamos o no llegamos a clase? · · 3.© A. Las entradas que nos proporciona el enunciado son cien metros y diez segundos. entonces. manual de reparación de una bicicleta. Un algoritmo debe ser finito. el camino que seguimos todos los días para ir a clase nos conduce al mismo sitio. Si un algoritmo se sigue dos veces se debe obtener el mismo resultado cada vez. Página: 2 Se pueden citar infinidad de ejemplos de algoritmos de la vida cotidiana. En el ejemplo anterior nos indica que debemos calcular la velocidad de desplazamiento. etc. necesitamos de tres requisitos indispensables: 1) ¿Cuales y cuantas son las entradas? Son las premisas (datos) que proporciona el enunciado del problema. en caso de no obtener el mismo resultado quiere decir que no está bien diseñado y.I. El método es. Se requiere una definición clara del problema: contemplar exactamente que debe hacer el programa y cual es el resultado o solución deseada. por tanto. para resolver cualquier problema matemático (y cualquier problema en general) combinamos adecuadamente las premisas proporcionadas por el enunciado para obtener los resultados. unos resultados. Un algoritmo debe estar bien definido. Para poder definir correctamente un problema. debe tener un número finito de pasos. Si un algoritmo se sigue. hay que corregir su diseño.

.Fórmula para calcular la superficie. estos pueden ser divididos en otros más pequeños y fáciles de solucionar.Altura del rectángulo (H). por ello es responsabilidad del programador.es Refinamiento introducir la BASE Apuntes de clase .. a su vez. Normalmente los pasos diseñados en un primer esbozo son incompletos.Circunferencia del circulo. basado en el anterior.. . somos nosotros quienes debemos proporcionar los valores numéricos para esas entradas. . Entradas: . Subproblema introducir la BASE alozanoi@teleline. Programación en lenguajes estructurados.Superficie del circulo. . D. con mayor número de pasos y mucho más específicos. Salidas: Método: Las entradas son la Base y la Altura..I. posteriormente se desarrolla otro.I.© A. El conjunto de estos pasos sucesivos es lo que anteriormente hemos denominado algoritmo. Esta técnica se llama comúnmente "divide y vencerás". más completo.Fórmula para calcular el perímetro. El enunciado no indica cuales son las medidas de los lados del rectángulo. Página: 3 Ejemplos: 1.Leer el radio de un círculo y calcular e imprimir su superficie y circunferencia. Entradas: Salidas: . con muy pocos pasos.A.Área del rectángulo (A).Radio del círculo.Base del rectángulo (B).Calcular el área del rectángulo de base 3 y altura 5. debemos proporcionarle los pasos sucesivos que tiene que realizar para resolver el problema. Es sabido que un ordenador no es capaz de solucionar un problema por sí mismo. desglosamos el problema en otros más pequeños que tengan una solución más fácil.L.Calcular el área del rectángulo de base B y altura H. Cuando un problema es demasiado grande para solucionarlo como un bloque único.Diseño del algoritmo. Método: 4.Fórmula para calcular el área del rectángulo.. A= B x H. Esta técnica de desarrollo de algoritmos con diferentes niveles de complejidad se denomina "refinamiento del algoritmo". . . Ejemplos: 1. debiendo tener una gran habilidad para descomponer un problema en subproblemas. . No existe ninguna norma fija de como realizar estas divisiones. 2.

I.© A. hay que representar el algoritmo con una determinada herramienta de programación como es el diagrama de flujo o el pseudocódigo.I.BASE * ALTURA visualizar ÁREA Obtener raices Sacar resultados Refinamiento introducir A Introducir B Introducir C x1=-b+sqrt(b*b-4*a*c)/(2*a) X2=-b-sqrt(b*b-4*a*c)/(2*a) ¿Errores? Visualizar x1 Visualizar x2 ¿Errores? Tras haber realizado la división del problema en subproblemas. existen unas reglas que tienen las siguientes propiedades: · · Deben estar seguidas de alguna secuencia definida de pasos hasta que se obtenga un resultado diferente. Página: 4 introducir la ALTURA calcular el ÁREA visualizar ÁREA 2. Programación en lenguajes estructurados. Una primera aproximación en forma de algoritmo que soluciona el problema sería: ir al cine comprar la entrada ver la película regresar a casa Como puede observarse. Sólo puede ejecutarse una operación a la vez. un algoritmo consiste en realizar una descripción paso a paso del problema en cuestión.es Apuntes de clase . Como hemos visto anteriormente. 4.. El flujo de control de un algoritmo es usualmente secuencial. en un primer refinamiento. ver la cartelera del cine si no proyectan "Casablanca" entonces decidir otra actividad alozanoi@teleline.Escritura inicial del algoritmo. Subproblema Dar coeficientes introducir la ALTURA ÁREA <-. el algoritmo es muy simple. veamos el algoritmo correspondiente a la siguiente pregunta: ¿Qué hacer para ver la película “Casablanca"?. Para una correcta descripción de un algoritmo simple basado en una serie de cálculos elementales.L. el algoritmo anterior se puede escribir de la siguiente forma: Inicio.Ecucación de segundo grado. D. Así.A. este algoritmo.. de forma que una acción no se realiza hasta que no ha sido realizada la anterior: sin embargo.1. consta de cuatro acciones que se realizan una a continuación de otra y en un orden estricto. se puede descomponer en pasos más simples siguiendo el método de refinamiento sucesivo.

Existen dos aspectos importantes a considerar en el ejemplo: · · Hay palabras reservadas que describen las estructuras de control fundamentales y procesos de toma de decisión. las acciones que van dentro de las estructuras fundamentales se han desplazado a la derecha. todo depende de la imaginación del programador. es posible un refinamiento sucesivo.I.I. Como puede observarse. Página: 5 si proyectan "Casablanca" ir al cine si hay cola entonces ponerse en ella mientras haya personas delante hacer avanzar en la cola si existen asientos disponibles entonces comprar una entrada encontrar el asiento correspondiente mientas proyectan la película hacer ver la película sino protestar abandonar el cine volver a casa fin. es decir. Se ha empleado la identación (sangrado o justificación) para la escritura del algoritmo. así. podemos seguir aplicando el método de refinamiento sucesivo sobre el algoritmo. Como se ha dicho en puntos anteriores. Otro ejemplo de algoritmo es el que responde a "cambiar una rueda de un coche". vamos a aplicar esta técnica a la acción: "encontrar el asiento correspondiente". D.es Apuntes de clase . inicio caminar hasta llegar a la primera fila repetir comparar número fila con número billete si no son iguales entonces pasar a la siguiente fila hasta que se localice la fila correcta mientras número asiento no igual número billete hacer avanzar en fila al siguiente asiento sentarse en el asiento fin. Programación en lenguajes estructurados. repetir_hasta).L. prodría ser el siguiente: inicio si el gato del coche está averiado entonces llamar a la estación de servicio sino poner el gato en su alojamiento repetir aflojar los tornillos de las ruedas hasta que todos los tornillos estén flojos repetir levantar el gato hasta que la rueda pueda girar alozanoi@teleline. Incluyen los conceptos de selección (si_entonces_sino) y los de repetición (mientras_hacer.A.© A.

Entrada / Salida Proceso.L. PROCESO alozanoi@teleline.© A. 5.1. resta. Página: 6 quitar los tornillos quitar la rueda poner rueda de repuesto y tornillos bajar el gato repetir apretar los tornillos hasta que estén apretados todos los tornillos fin 5.I. Utiliza símbolos (cajas) estándar y tiene los pasos del algoritmo escritos en las cajas. Los dos tipos generales de operaciones de proceso son operaciones aritméticas y operaciones de transferencia de datos. D. están unidas por flechas. Representa el INICIO y el FINAL del programa. Una operación de transferencia de datos es el cambio de valores entre elementos de datos.A. Es una técnica muy antigua aunque todavía en uso.. Dentro se sitúa un comentario que indica la operación específica que se ejecuta. multiplicación.. e indican la secuencia en que deben ejecutarse. Los símbolos más utilizados en los diagramas de flujo son: Terminal. Se utiliza siempre que los datos son manipulados o procesados. Programación en lenguajes estructurados. división.Herramientas de programación. Este símbolo se utiliza siempre que entra o sale una información a o desde el ordenador. denominadas líneas de flujo. exponenciación o cualquier combinación de éstas. Introducción y visualización de datos.Diagramas de flujo. Inicio Fin Entrada/Salida. Las dos herramientas más utilizadas para diseñar algoritmos son diagramas de flujo y pseudocódigo. Un diagrama de flujo es una representación gráfica de un algoritmo. Una operación aritmética es una suma.I.es Apuntes de clase .

En su momento veremos todas y cada una de las estructuras usadas en pseudocódigo. Se usan para unir partes lejanas de un diagrama de flujo. dado que ha de traducirse posteriormente a un lenguaje de programación.. 5. visualizar. por ejemplo cuando un algoritmo no cabe en una página y debemos unir acciones de una a otra página. N Ejemplos: 1.Los lenguajes de programación..2.es Apuntes de clase . Conectores. Nació como un lenguaje similar al inglés y era un medio para representar básicamente las estructuras de control de programación estructurada. alozanoi@teleline.I.. leer. Programación en lenguajes estructurados. Se considera un primer borrador. D.I. Su ventaja es que el programador se puede concentrar en la lógica y en las estructuras de control y no preocuparse de las reglas de un lenguaje específico. Ejemplos: 1.Cálculo del área y de la circunferencia de un círculo. el algoritmo se ha de expresar en un formato que se denomina programa. fin.Pseudocódigo. mientras_finmientras. repetir_hasta..© A. Cuando el procesador que debe interpretar un algoritmo es un ordenador.Cálculo del área de un triangulo. El uso del pseudocódigo se ha extendido ampliamente con términos en español como inicio. 2. Un programa se escribe en un lenguaje de programación y las operaciones que conducen a expresar un algoritmo en forma de programa se denomina programación. escribir.Cálculo del área de un triángulo.A. si_entonces_sino. 6.Cálculo del área y de la circunferencia de un círculo.L. Indica operaciones lógicas entre los datos y en función del resultado determina cual de los distintos caminos debe seguir el programa. Página: 7 Decisión. 2. El uso de tal lenguaje hace el paso de codificación final (traducción a un lenguaje de programación) relativamente fácil. El pseudocódigo es un lenguaje de especificación de algoritmos.. Usar esta terminología en español facilita enormemente el aprendizaje y uso diario de la programación. etc..

poca fiabilidad.Instrucciones del ordenador.. Programación en lenguajes estructurados. etc.© A. Página: 8 Los principales tipos de lenguajes de programación utilizados en la actualidad son: · · · Lenguaje máquina Lenguaje de bajo nivel Lenguajes de alto nivel 6. dificultad para verificar el código.Lenguajes máquina. por tanto. diferirán de un ordenador a otro. El código máquina es el código binario.Lenguajes de bajo nivel.. P). La elaboración de un programa requerirá conocer el juego de instrucciones del lenguaje así como la sintaxis y la semántica del propio lenguaje. Estas cadenas binarias se denominan instrucciones de máquina o código máquina. sentencias o proposiciones (el primero se usa para lenguajes de bajo nivel y máquina y el segundo para los lenguajes de alto nivel).1. Un programa escrito en este lenguaje no puede ser ejecutado directamente por el ordenador. Las instrucciones en lenguaje máquina dependen del hardware del ordenador y. Los tipos fundamentales de instrucciones se verán posteriormente. El principal lenguaje de bajo nivel es el ensamblador y sus instrucciones son conocidas como nemotécnicos (ADD M.I.. Las ventajas e inconvenientes son los mismos que los del lenguaje máquina. Por tanto.L. sino que necesita una fase de traducción a lenguaje máquina. aunque más relajados. Los diferentes pasos (acciones) de un algoritmo se expresan en los programas como instrucciones. D. Los lenguajes máquina son aquellos que están escritos en lenguajes directamente inteligibles por el ordenador. 6. 6. sólo son ejecutables en máquinas del mismo tipo que para la que se escribió el programa. ya que sus instrucciones son cadenas binarias (0 y 1) que especifican una operación y las posiciones de memoria implicadas en la operación.3.2. alozanoi@teleline.es Apuntes de clase .A.I. los inconvenientes son muchos: dificultad y lentitud de codificación. un programa consta de una secuencia de instrucciones cada una de las cuales especifica ciertas operaciones que debe ejecutar el ordenador. N. La principal ventaja de programar en este lenguaje es que la velocidad de ejecución es superior a la de cualquier otro lenguaje. Son más fáciles de usar pero siguen dependiendo de una máquina en particular.

Para solucionar este problema.2. · Fácil modificación y puesta a punto.I. 6. A diferencia del anterior. como la máquina no reconoce mas que el lenguaje máquina. se diseña un nuevo conjunto de instrucciones (Lenguaje de alto nivel) más conveniente para las personas que el ya incorporado en la máquina... D.. Debido a que el lenguaje máquina es demasiado elemental. ..5. 6.). los programas escritos en lenguajes de alto nivel deben ser traducidos a lenguaje máquina. Esta conversión puede ser realizada de dos formas diferentes: compilación e interpretación.L. es difícil y tedioso utilizarlo. es necesario convertir los programas escritos en el primero al segundo.Lenguajes de alto nivel.I.es Apuntes de clase . no requiere la alozanoi@teleline. · Reducción del coste de los programas. Esta técnica se denomina traducción y al programa compilador.Intérpretes. El resultado es un nuevo programa escrito en lenguaje máquina inteligible por misma.Traductores de lenguaje. Ventajas: · Formación corta.A. Programación en lenguajes estructurados. · No se aprovechan los recursos internos de la máquina que se explotan mejor en los lenguajes máquina y ensambladores. 6. Los compiladores son programas que toman cada instrucción del lenguaje de alto nivel y la convierten en una secuencia equivalente de instrucciones del lenguaje máquina..1.5.Compiladores. · Transportabilidad.© A. · Aumento de la ocupación de memoria.5. · La escritura de programas se basa en reglas sintácticas similares a los lenguajes humanos (READ. PRINT.. además de ser independientes de la máquina (son portables a otros ordenadores). · El tiempo de ejecución de los programas es mucho mayor. Página: 9 6. Los intérpretes son programas que toman programas escritos en lenguaje de alto nivel como datos de entrada y los lleva a cabo examinando cada instrucción por turno y ejecutando directamente la secuencia equivalente de instrucciones en lenguaje máquina. Al igual que en los lenguajes ensambladores. Son los más utilizados por estar diseñados para que las personas escriban y entiendan los programas de un modo mucho más fácil que los anteriores. Inconvenientes: · Incremento del tiempo de puesta a punto de los programas al necesitarse diferentes traducciones del programa. Una vez diseñado el lenguaje de alto nivel.4.

L.2. al lenguaje de la máquina. siempre que el algoritmo haya sido diseñado correctamente. y las operaciones/instrucciones indicadas en el lenguaje natural expresarlas en el lenguaje de programación correspondiente. que aún no es ejecutable. ya sea diagrama de flujo o pseudocódigo.. Si se producen errores. Si tras la compilación se presentan errores. Esta técnica se denomina interpretación y el programa se llama interprete. es necesario traducirlo en un nuevo programa que el ordenador sea capaz de entender. Dado que el diseño de un algoritmo es independiente del lenguaje de programación utilizado para su implementación. Este proceso se realiza con el compilador y el sistema operativo.A. Este proceso se repite hasta que no se produzcan errores.1. pasamos a la resolución práctica del problema con el ordenador. Una vez que hemos obtenido el programa fuente.I. en otro caso volvemos a corregir sobre el programa fuente y realizamos los pasos anteriores. ya se puede ejecutar con solo teclear su nombre.Codificación del algoritmo en un programa. Una vez que el algoritmo ha sido diseñado y representado mediante una herramienta de programación. Es una fase totalmente mecánica. Programación en lenguajes estructurados.I.es Apuntes de clase .. D. Una vez obtenido el programa ejecutable. es preciso corregirlos y volver a compilar.3.© A. se corrigen y volvemos a realizar la compilación y montaje de programa. Si no existen errores de ejecución se obtendrán los resultados. 7.. obteniendo lo que se denomina programa fuente. que determinarán si el programa tiene errores. La verificación o comprobación de un programa es el proceso de ejecución del programa con una amplia variedad de datos de entrada.. 7. el código puede ser escrito con igual facilidad en un lenguaje o en otro.Verificación y depuración de un programa. 7. La depuración es el proceso de encontrar los errores y corregirlos. Para obtener el programa ejecutable debemos realizar el montaje o enlace (link) del programa objeto con las librerías del programa compilador. Para realizar la conversión del algoritmo en programa se deben sustituir las palabras reservadas en español por sus homónimos en inglés. Esta fase la descomponemos en varias subfases que se describen a continuación. obteniéndose el programa objeto. Codificación es la escritura del algoritmo desarrollado anteriormente en un lenguaje de programación. 7.Ejecución de un programa.Resolución del problema mediante ordenador. Se pueden dar tres tipos de errores: alozanoi@teleline. Página: 10 generación de un nuevo programa.

4. Ejercicios.000 pts. 7. Calcular la media de edad de los alumnos de la clase. Algoritmo para extraer los números de la Primitiva.L. 5.000 pts es un 10%. división por cero o raíz negativa. . 6.I. 2. Suma. alozanoi@teleline.es Apuntes de clase .ó nulo. Son los más frecuentes y los más difíciles de detectar. Decir si un número es +. Si es inferior a 1. es un 5% de descuento. y menor a 100. Calcular el precio final del producto con el 15% de impuestos.A. no hay descuento. D. Leer una calificación numérica entre 0 y 10 y transformarla en una alfabética. 3. Programación en lenguajes estructurados. y si es mayor a 100. Página: 11 · · · Errores de compilación: Se producen por el uso incorrecto de las reglas del lenguaje de programación. 1. Decir cual es el mayor de dos números o si son iguales. Errores de ejecución: producidos por instrucciones que el ordenador puede comprender pero no ejecutar. Ejemplo.000 pts.© A. si está entre 1. resta y producto de dos números.000 pts. Un comercio realiza un descuento dependiendo del precio del producto.I. Errores lógicos: se producen en la lógica del programa y la fuente del error suele ser el algoritmo.

.

Los datos de entrada se transforman. 214. Especiales: . 3.L. .0. 123. etc.2. 1. Los simples son los siguientes: numérico. Ejemplos de datos de tipo alfanumérico son: 'Pepe'.I.. El tipo numérico es el conjunto de los valores numéricos. a. después de las etapas intermedias. "Luís". *.© A.1416. Son aquellos que pueden tomar uno de dos valores posibles: cierto o verdadero (true) o falso (false). Ejemplos de datos numéricos enteros son: 5... Tienen parte decimal (y punto decimal) y también pueden ser positivos y negativos. +.A. -8.ELEMENTOS GENERALES DE UN PROGRAMA.1.. Ejemplos de datos numéricos reales son: -0. es decir.es Apuntes de clase . <. 1.. b.34.I. Son números completos. 1. · Numérico real: es un subconjunto de los números reales. 0.Este tipo de dato se usa para representar las alternativas a determinadas condiciones. en los datos de salida. -45... El rango normal en los ordenadores va de -32768 a 32767..Datos lógicos o booleanos. Programación en lenguajes estructurados. . sin parte fraccionaria y pueden ser positivos y negativos. 1. 2. Numéricos: 0. La acción de las instrucciones ejecutables de los ordenadores se reflejan en los cambios en los valores de las partidas de datos. . Su longitud es el número de caracteres que están encerrados entre las comillas. Por alozanoi@teleline. son los valores con los que opera.Datos y tipos de datos.. Página: 13 2.3.. 1. D.. 87. Una cadena de caracteres es una sucesión de caracteres que se encuentran delimitados por una comilla (apóstrofe) o dobles comillas. . %.234.. . Pueden representarse de dos formas: · Numérico entero: es un subconjunto finito de los números enteros.. B. -67. Los ordenadores suelen reconocer los siguientes tipos de caracteres: · · · Alfabéticos: A. '1 de Enero de 1993'. Los datos compuestos o estructurados son conjuntos de datos simples relacionados entre sí.Datos carácter o alfanumérico. etc. -98 etc.Datos numéricos. Existen dos tipos de datos: Simples y Compuestos. Es el conjunto finito y ordenado de los caracteres del ordenador.. 7. El primer objetivo de todo ordenador es el manejo de la información o de los datos. 23. carácter y lógico. Un dato es la expresión general que describe los objetos con los cuales opera un ordenador.

No hay límites en cuanto a su extensión. Tales valores se llaman constantes. 2.L.1. carácter. Estas básicamente son: · · · · Deben comenzar con una letra (A a Z). mientras una variable entera puede tomar sólo valores enteros. Para nombrarlos... constantes. lo hacemos mediante identificadores. hay diferentes tipos de variables. tipo de dato y valor inicial que toma. etc. No se puede usar como identificador una palabra clave del lenguaje. Los identificadores son los nombres que se designan para dicho propósito.I.'28905 Getafe' (Constante alfanumérica). puede tomar como valor sólo caracteres.A. D..Constante. Página: 14 ejemplo.© A. Una variable carácter.Variable Es un objeto o partida de datos cuyo valor puede cambiar durante el desarrollo del algoritmo o ejecución del programa.Identificador. leerlos. Una variable que es de un cierto tipo puede tomar valores únicamente de ese tipo. Dependiendo del lenguaje. Los nombres de variables elegidos deben ser significativos.Identificadores. Los programas de ordenador contienen ciertos valores que no pueden cambiar durante la ejecución del programa. carácter y cadena. reales. Para que una variable esté bien definida. cuando se pide determinar si un valor entero es par. lógicas y cadena. 2.180 (Constante entera). como pueden ser los casos siguientes: alozanoi@teleline. 2.es Apuntes de clase . procedimientos. Es una partida de datos (objetos) que permanecen sin cambios durante todo el desarrollo del algoritmo o durante toda la ejecución del programa. constantes y variables.3. reales.I..1416 (Constante real). Existen constantes lógicas. Los identificadores se construyen de acuerdo a las reglas de sintaxis del lenguaje específico. hay que especificar: Nombre. 2. ciudad <-. El segundo carácter y posteriores puede ser letra o dígito (también el carácter de subrayado). operar con ellos. etc. pi <-. pero generalmente son enteras. De igual forma. existen otros valores que si pueden cambiar durante la ejecución del programa. Ejemplos de constantes son los siguientes: angulo_llano <-. enteras. Programación en lenguajes estructurados. la respuesta es verdadera o falsa según sea par o impar.3. a estos valores se les llama variables. En los lenguajes de alto nivel se necesitan nombres para identificar los objetos que se deseen manipular: variables. por ejemplo. Estos permiten elegir nombres significativos que sugieran lo que representan.2. En un ordenador los datos necesitan ser manejados mediante herramientas que permitan almacenarlos en memoria.

el de una expresión lógica es de tipo lógico. saludo <-. Ejemplos de variables son las siguientes: contador <-. ↑ div mod alozanoi@teleline. Las mismas ideas son utilizadas en notación matemática tradicional. Carácter: construidas con operadores alfanuméricos.Expresiones.L.1. Según sea el tipo de objetos que manipulan. Las variables y constantes son numéricas (real o entera) y las operaciones son las aritméticas. Una expresión consta de operandos y operadores. Cada expresión toma un valor que se determina tomando los valores de las variables y constantes implicadas y la ejecución de las operaciones indicadas. paréntesis y nombres de funciones especiales. variables. Por ejemplo: a + (b + 3) + c Aquí los paréntesis indican el orden de cálculo y c representa la función raíz cuadrada de 'c'. Página: 15 NOMBRE representa nombres de personas.I.23 (Variable entera).‘x’ (Variable carácter) 3. Las expresiones son combinaciones de constantes. Los operadores aritméticos son los siguientes: + * / **. PRECIOS representa precios de diferentes artículos.es Suma Resta Multiplicación División Potencia División entera Módulo (resto de la división) Apuntes de clase . Programación en lenguajes estructurados. Letra <-. el de una expresión carácter es de tipo carácter.. 3. NOTAS representa las notas de una clase.verdadero (Variable lógica). fin <-.A. area <-. Lógicas: construidas con operadores lógicos y relacionales.© A. se clasifican en: · · · Aritméticas: construidas con los operadores aritméticos. D.45 (Variable real). símbolos de operación. R2D2?' (Variable alfanumérica)..803. El resultado de la expresión aritmética es de tipo numérico.Expresiones aritméticas. Las expresiones aritméticas son análogas a las fórmulas matemáticas.I.'¿Qué tal.

Para realizar comparaciones de datos tipo carácter. Esta ordenación suele ser alfabética. ('A'<'B'<'C'<.<'z'). Página: 16 Ejemplos de operaciones aritméticas son las siguientes: Expresión (3+2)*5 6-2 40 div 6 23 mod 2 Resultado 25 36 6 1 3. unión). negación). pero si se consideran caracteres mixtos.I. AND (y. Ej.Operadores lógicos: los operadores lógicos o booleanos básicos son NOT (no.© A.es Apuntes de clase . Las letras mayúsculas 'A' a 'Z' siguen el orden alfabético.. Sirven para expresar las condiciones en los algoritmos. Por ejemplo si 'A=6' y 'B=5' entonces 'A > B' es verdadero. considerándolas de modo independiente.2. Programación en lenguajes estructurados.<'Z').I.. Esto es '0'<'1'<'2'<. ('a'<'b'<'c'<. similar al orden creciente o decreciente. alozanoi@teleline. .<'9'. intersección) y OR (o.Operadores de relación: los operadores relacionales permiten realizar comparaciones de tipo numérico o carácter.Expresiones lógicas (booleanas). ... Una expresión lógica es aquella que sólo puede tomar dos valores diferentes: verdadero o falso.. denominadas tablas de verdad. tanto mayúsculas como minúsculas. Los operadores relacionales son los siguientes: < > = <= >= <> Menor que Mayor que Igual que Menor o igual que Mayor o igual que Distinto de El formato general para una operación de comparación es: EXPRESION1 OPERADOR RELACIONAL EXPRESION2 y el resultado de la operación será verdadero o falso.A. La definición de los operadores lógicos se resume en las siguientes tablas. se debe recurrir a un código normalizado como es el ASCII. se requiere una secuencia de ordenación de los caracteres. La aplicación de los operadores de relación es evidente. Las letras minúsculas están en el mismo orden alfabético.. · · · Los valores de los caracteres que representan a los dígitos están en su orden natural.L. D. mientras '(A-2) < (B-4)' es falso.. Se forman combinando constantes y variables lógicas y los operadores relacionales.:Si A='PEPE' y B='LUIS' entonces A<B es falso y B<A es verdadero.

Por ejemplo: es de día y hace sol.L. No 5>3.3. Por ejemplo: es de día o es de noche.' + '1416' ----> '3.A. '+'. usado para unir variables o expresiones alfanuméricas. -Tabla de verdad de AND (y): A FALSO FALSO CIERTO CIERTO B FALSO CIERTO FALSO CIERTO AYB FALSO FALSO FALSO CIERTO AND o Y un operador binario. La expresión que forma es cierta cuando al menos uno de sus operandos es cierto. y al revés. Página: 17 -Tabla de verdad de NOT (no): A FALSO CIERTO NO A CIERTO FALSO NOT o NO es un operador unario. '3' + '. -Tabla de verdad de OR (o): A FALSO FALSO CIERTO CIERTO B FALSO CIERTO FALSO CIERTO AOB FALSO CIERTO CIERTO CIERTO OR u O es un operador binario. Programación en lenguajes estructurados.1426'. entonces a+b='Juan Antonio'.I. Se construyen mediante los operadores alfanuméricos. Si a='Juan' y b=' Antonio'.. por ejemplo: (1<5) y (5<10) es verdadera (5>10) o ('A'<'B') es verdadera. Así. esta operación se denominada concatenación. afecta a un operando. Apuntes de clase alozanoi@teleline. Son las que producen resultados de tipo alfanumérico. Ejemplos: 'Saca' + 'puntas' ----> 'Sacapuntas'. 3. Sólo tenemos un operador alfanumérico. Actúa sobre la expresión cambiando su estado lógico: si era verdad lo transforma en falso. D. afecta a dos operandos.I.es . En las expresiones lógicas se pueden mezclar operadores relacionales y operadores lógicos.© A. Por ejemplo: no es de día. La expresión formada es cierta cuando ambos operandos son ciertos al mismo tiempo.Operaciones alfanuméricas. 5>3 y 5>4.

7º Relacionales (<. pvp = 2 c) (a + 7 * c) / (b + 2 .5 17 79 17 -31 2. =. <=. *.Convertir en expresiones aritméticas de algoritmos las siguientes expresiones algebraicas: 5(x + y) x2 + y2 x y(z + w) x+ y w n+ a x= .. 3º Potencias (↑). div. 2º Signo (-). 5º Sumas y restas (+.4. >=. Programación en lenguajes estructurados.Evaluar las siguientes expresiones aritméticas: a) (a + b) / PVP + 2 Valores: a = 6. >.Evaluar las siguientes expresiones: a) 4 * 3 + 5 b) 7 * 10 . o). Página: 18 3.I.5) mod 3) * 4 + 9 d) . PVP = 7 b) iva * iva .Orden de evaluación de los operadores.I.15 mod 3 * 4 + 9 c) (7 * (10 .L.b ± b2 . D.© A. La evaluación de operadores de igual orden se realiza siempre de izquierda a derecha. y). 9º Conjunción (AND. Ejercicios. -). <>).a) + 2 * b alozanoi@teleline. b = 8.4 * 7 + 2 ** 3 / 4 . tasa = 3.A.es 4 25 18. 6º Concatenación (+). Los operadores de una expresión se evalúan en el siguiente orden: 1º Paréntesis (primero los más internos)..4 * tasa * pvp Valores: iva = 7.2 Apuntes de clase . mod).. 1. no).4ac 2a 3.. 4º Productos y divisiones (/. 8º Negación (NOT. 10º Disyunción (OR.

.b Valores: a = 3.Evaluar las siguientes expresiones: Valores: a= 1.es Apuntes de clase . a) a > 3 y b = 4 ó a + b <= c c) a > 3 y (b = 4 ó a + b <= c) d) (1 > 0) y (3 = 3) e) no (z > 14) 66 V F V V si Z<=14 alozanoi@teleline.L.I. b = 6 4.I. c = 4 d) (a + 5) * 3 / 2 * b . b = 6. Programación en lenguajes estructurados.© A. Página: 19 Valores: a = 3.A. D. b = 4. c = 10.

.

© A. Un programa de ordenador es un conjunto de instrucciones y datos lógicamente ordenados que producirán la ejecución de una determinada tarea. Real N. b) Bloque de instrucciones: contiene el conjunto de operaciones que se van a realizar para la obtención de los resultados pedidos por el problema. tipo y otras características corresponden a cada uno de ellos. Su misión es anunciar la utilización de objetos en un programa indicando qué identificador. en acciones de manipulación de los objetos del programa. Real N.INTRODUCCIÓN A LA PROGRAMACIÓN ESTRUCTURADA.A. Un formato usado en pseudocódigo para la declaración de objetos puede ser el siguiente: Entorno: Nombre Lista de objetos Tipo Tipo de los objetos Valor inicial Cuando se declaran en una misma sección variables y constantes. se denominan declaraciones implícitas. tanto las variables como las constantes. Real N.I. 2... estas se situarán delante de la variables.L. es decir. Real Valor inicial 3. Se realizará el tratamiento de los datos de entrada para la obtención de los datos de salida. un programa es un medio para conseguir un fin: información necesaria para solucionar el problema.Concepto de programa.I.Tipos de instrucciones. D. Ejemplos: Entorno: Nombre AREA BASE ALTURA Entorno: Nombre PI AREA_CIRCULO LONG_CIRCUNF Tipo N. Todo programa contiene dos bloques bien diferenciados: a) Bloque de declaraciones: se especifican todos los objetos que intervienen en el programa. desde su estado inicial hasta otro estado final que contendrá los resultados del proceso. Programación en lenguajes estructurados. Las instrucciones consisten. Página: 21 3.. 2. en general.14159 alozanoi@teleline.es Apuntes de clase ..Instrucciones de declaración. Entero Valor inicial Tipo N. Entero N.1. 1. En casi todos los lenguajes hay establecidas declaraciones por defecto.

4 * a * c) ** (1 / 2)) / (2 * a) Valor inicial de 'x': 0 (o cualquier otro) Valor de 'a': 1 Valor de 'b': 2 Valor de 'c': 1 alozanoi@teleline. un valor de un tipo de dato específico.Instrucciones primitivas. La operación de asignación se representa con el símbolo u operador “ “ (flecha con sentido a la izquierda). 2. por tanto. Página: 22 2. Es decir. El formato general de su uso es IDENTIFICADOR EXPRESIÓN donde IDENTIFICADOR es cualquier nombre de objeto válido. previamente declarado.Instrucción de asignación. Esta instrucción es conocida como sentencia de asignación. es decir.1.es Apuntes de clase . La sentencia de asignación es destructiva. debe existir una concordancia de tipo de dato entre el identificador y la expresión.I.A.I.© A. para que una sentencia de asignación sea correcta.. D. no dependen de otra cosa que de su propia aparición en el programa para ser ejecutadas. b) El valor obtenido se almacena en la variable cuyo identificador está a la izquierda del operador de asignación. sustituyendo el valor que tenía anteriormente. Ejemplo: El valor inicial del objeto denominado 'PRECIO' es el siguiente: 1253 PRECIO Si aplicamos la sentencia de asignación PRECIO 8312 obtendremos un nuevo valor en el objeto 'PRECIO': 8312 PRECIO La sentencia de asignación es ejecutada por el ordenador en dos pasos bien definidos: a) Evalúa la expresión situada a la derecha del operador de asignación. pues el valor que tuviera la variable antes de la asignación se pierde y es reemplazado por el valor resultante de evaluar la expresión.b + (b * b . y EXPRESIÓN es cualquier expresión válida (bien construida) cuyo tipo de resultado se corresponda con el tipo de la variable.2. Usada para darle el valor que le corresponda a una variable. Programación en lenguajes estructurados. y obtiene. Ejemplo: x (..2.L. Son aquellas que ejecuta el procesador de modo inmediato.

A. los cálculos realizados por el ordenador requieren de entrada de datos externos para realizar las acciones necesarias para obtener los resultados.Instrucción de salida de datos.2. pueden ser aritméticas. lógicas y de carácter. Ejemplo: Introducir BASE.© A. La sentencia se salida de datos es la forma principal de comunicación del ordenador con las personas.2. La sentencia de entrada de datos suele (debe. Consiste en darle al ordenador un dato (valor) desde el dispositivo estándar de entrada (teclado) y este lo almacenará en memoria principal en el objeto cuyo identificador aparece en la propia instrucción. en la propia instrucción: constantes y/o expresiones..L.es Apuntes de clase . alozanoi@teleline.Instrucción de lectura de datos. b y c) permanecen invariables. 2.3. Si hay más de un elemento. Programación en lenguajes estructurados. la instrucción de entrada es destructiva. Por tanto. D..I.2. Consiste en que el ordenador envía datos (información procesada) al dispositivo estándar de salida (el monitor). según los casos) ir precedida de una sentencia de salida de datos (se verá a continuación) que nos identifique el tipo de entrada que se nos pide por pantalla. Entrada. Ejemplos válidos de sentencias de asignación en pseudocódigo son las siguientes: a 4 b 25 c a*b nombre 'José' + 'Luis’ continuar verdadero fin a > b and continuar 2. se separan por comas. Las sentencias de asignación se clasifican según el tipo de dato de las expresiones. En ocasiones.I. El formato general de su uso es Introducir Objeto/Lista_de_Objetos donde “Introducir” es una palabra reservada que indica el tipo de instrucción a realizar y “Objeto/Lista_de_Objetos” es el conjunto de elementos (objetos) donde se van a depositar en memoria principal los datos leídos. Como la sentencia de asignación. b) Valores definidos. estos datos pueden ser: a) Valores de objetos depositados en memoria principal. de alguna forma. Página: 23 Los objetos que forman parte de la expresión (a. ALTURA Si damos los valores 5 y 6 desde teclado. el objeto “BASE” tomará el valor 5 y el objeto “ALTURA” el valor 6. el valor previo que tuviera el objeto se pierde y es reemplazado por el valor introducido desde el teclado.

Página: 24 El formato general de uso es Visualizar Expresión/Lista_de_Expresiones donde “Visualizar” es una palabra reservada que indica el tipo de instrucción a realizar y “Expresión/Lista_de_Expresiones” es el conjunto de informaciones y datos que queremos mostrar. 5.1. Algoritmo que calcule la hipotenusa de un triángulo rectángulo cuyos catetos se dan por teclado. decenas y centenas.. Son instrucciones que no realizan trabajo efectivo salvo la evaluación de expresiones. AREA Ejercicios : 1. Las estructuras selectivas se utilizan para tomar decisiones lógicas. Programa que calcule y escriba el perímetro y el área de un rectángulo cuya base y altura se leen desde teclado. Los tres tipos de argumentos pueden entrar a formar parte de la instrucción de salida. BASE . irán encerrados entre comillas o apóstrofes. 3. 2. Valores: datos constantes que se visualizarán por pantalla tal como están definidos en la propia instrucción. dobles y múltiples.es Apuntes de clase . En caso de ser de tipo carácter. alozanoi@teleline. Pueden ser de tres tipos: simples. se evalúa una condición o expresión y en función de su resultado se bifurca a un determinado punto del programa. BASE * ALTURA Visualizar 'El área de rectángulo es '. es decir. 2. Expresiones: son todo tipo de expresiones posibles de construir. Programa que calcule y escriba el cuadrado del número 243.3. con el objetivo de controlar la ejecución de otras instrucciones o alterar el orden de ejecución de las instrucciones de un programa.I. Los argumentos de la instrucción son los siguientes: · · · Objetos: su valor -el contenido almacenado para el objeto en memoria. ' es '.3. Una instrucción de selección o decisión es aquella que controla la ejecución de uno o varios bloques de instrucciones. generalmente lógicas. debiendo ir separados por comas.L. Programa que lea un número y escriba su cuadrado. ' y altura '. dependiendo del cumplimiento o no de alguna condición o valor final de alguna expresión. 25 y 100 pesetas..I. ALTURA .Instrucciones alternativas. La expresión es evaluada y únicamente su valor final resultará mostrado por pantalla. 2. Programa que lee una cantidad de dinero y la desglosa en las monedas de 1. Programación en lenguajes estructurados. 7. 4. Programa que lee una cantidad menor de 1000 y la desglosa en unidades. Ejemplos: Visualizar 'El área de rectángulo de base '.© A. Programa que intercambie los valores de dos variables numéricas. D. no se visualizará el identificador del objeto.se visualizará por el monitor.Instrucciones de control. 5.A. 6.

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

25

Simple

Doble

Múltiple

2.3.1.1.- Alternativa simple.

Se evalúa una condición y si esta es verdadera se realiza una acción o un bloque de acciones ; si, por el contrario, es falsa, no se realiza ninguna acción. El formato es el siguiente: si CONDICIÓN Instrucción/es fin si

2.3.1.2.- Alternativa doble.

Esta estructura nos permite elegir entre la realización de dos posibles acciones. Si la condición es verdadera se realiza una o varias acciones y si es falsa se realiza otro grupo de acciones. La alternativa simple es un caso particular de la alternativa doble. El formato de la sentencia alternativa doble es el siguiente: si CONDICIÓN Instrucción/es si CONDICION ES CIERTA si no Instrucción/es si CONDICION ES FALSA fin si

2.3.1.3.- Alternativa múltiple.

La alternativa de decisión múltiple evalúa una expresión que podrá tomar N valores diferentes. Según se elija uno de estos valores en la condición, se realizará una de las N acciones posibles. Las distintas opciones deben ser disjuntas entre sí, es decir, sólo puede cumplirse una de ellas ya que los valores de cada opción no se pueden repetir. El formato es el siguiente: Evaluar Expresión_Evaluar Cuando VALOR_1 Instrucción/es 1 Cuando VALOR_2 Instrucción/es 2 Cualquier otro Instrucción/s N Fin evaluar

Bloque opcional

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

26

Para cada valor de la expresión se pueden ejecutar una o varias acciones. Los valores de la expresión no tienen por qué ser consecutivos pero sí únicos; se pueden considerar rangos de constantes numéricas o de caracteres (según los lenguajes). Ejercicios : 1. Decir si un número es positivo, negativo o nulo. 2. Algoritmo que nos diga si un número N es o no múltiplo de 2. 3. Programa que calcula las raíces de la ecuación de segundo grado. 4. Programa que lee una calificación numérica entera comprendida entre 0 y 10 y la transforma en una calificación alfabética. 5. Programa que toma como entrada el número de un mes y nos indica el número de días que tiene.

2.3.2.- Instrucciones repetitivas. Bucles. Un bucle es un fragmento de algoritmo o programa cuyas instrucciones se repiten un número determinado de veces : mientras se cumple una determinada condición o hasta que la condición se cumpla, dependiendo del tipo de estructura que se use. Una iteración es el hecho de repetir la ejecución de una secuencia de acciones. Un bucle consta de tres partes bien diferenciadas:
·

Decisión: Se sitúa una condición que puede ser verdadera o falsa y se comprueba una vez a cada paso o iteración del bucle, determinando la continuidad o finalización del mismo. La condición determina el número de veces que se deben ejecutar las acciones. Cuerpo del bucle: Fragmento de programa o conjunto de instrucciones que se repiten. Se ejecutan una vez en cada paso o iteración del bucle. Aquí es fundamental que el valor de la condición sea afectado por las instrucciones para asegurar la finalización del bucle en algún momento. Salida del bucle: Finalización del bucle. A continuación están situadas el resto de las instrucciones que componen el programa.

·

·

Mientras

Repetir

En un programa pueden existir varios bucles; estos pueden ser independientes o anidados. Son anidados cuando están dispuestos de tal modo que unos son interiores a otros.

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

27

Independientes

Anidados

Cruzados. No válidos

Disponemos de tres tipos de estructuras repetitivas dependiendo de su configuración.

2.3.2.1.- Estructura MIENTRAS.

Es aquella en la que el cuerpo del bucle se repite mientras se cumple la condición. Su formato es el siguiente : Mientras CONDICION Instrucción/es Fin mientras Los pasos para la ejecución son los relacionados a continuación : a) Evaluar la condición. b) Si es falsa continúa en el paso f). c) si es verdadera continúa en el paso d). d) Instrucciones del cuerpo del bucle. e) Regresa al paso a). f) Instrucciones siguientes al bucle. Al ser la condición de finalización la primera acción que se realiza del bucle, puede darse el caso de que el cuerpo del bucle no se ejecute ninguna vez. En ocasiones esta opción es necesaria. Ejercicio: Visualizar los números menores que N, siendo N un número introducido por teclado.

2.3.2.2.- Estructura REPETIR.

Se ejecuta hasta que se cumpla una condición determinada que se comprueba al final del bucle. El formato es el siguiente : Repetir Instrucción/es Hasta CONDICION Los pasos para su ejecución son los siguientes : a) Comienzo del bucle. b) Ejecución de cuerpo del bucle. c) Evaluar la condición. d) Si es falsa continúa en el paso a). e) Si es verdadera continúa en el paso f). f) Instrucciones siguientes al bucle.
alozanoi@teleline.es Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

28

Como la última acción que se realiza en el bucle es la evaluación de la condición, el cuerpo del bucle se realiza siempre, al menos una vez. Las diferencias principales entre los bucles mientras y repetir son estas: a) El bucle mientras finaliza cuando la evaluación de la condición da como resultado falso y el repetir cuando es verdadero. b) El cuerpo del bucle repetir se realiza una o más veces y el cuerpo del bucle mientras se ejecuta 0 o más veces.

2.3.2.3.- Estructura PARA.

Controla la ejecución del conjunto de instrucciones que configuran su rango, de tal forma que estas se ejecutan un número determinado de veces que queda definido en la cabecera del bucle. En ella se define un identificador de variable que va a actuar como contador asociado y que se denomina variable de control del bucle (Vc), definiéndose al mismo tiempo su valor inicial (Vi), su valor final (Vf) y el incremento (In) que esta variable de control va a adquirir en cada repetición. El formato es el siguiente : Para Vc de Vi a Vf [con Incremento In] hacer Instrucción/es Fin para La variable de control tomará el valor inicial y va incrementándose en In en cada iteración de bucle, de tal forma que el proceso finaliza cuando la variable de control supera el valor final (en caso de incremento negativo se invierten los términos). Los valores Vi, Vf e In pueden estar expresados por un valor constante, una variable o una expresión ; entendemos que si son variables, estas no se modificarán en el cuerpo del bucle. De igual forma, la Vc tampoco debe ser modificada en el cuerpo del bucle. El número de iteraciones que se realizarán en una instrucción para viene dado por la expresión :

 Vf − Vi  Ni = parte entera   +1  In 

2.3.3.- Instrucciones de ruptura de secuencia. El desarrollo lineal de un programa se interrumpe cuando se ejecuta una bifurcación. Las bifurcaciones pueden ser, según el punto del programa a donde se bifurca: hacia adelante o hacia atrás. Estas instrucciones no deben usarse. Instrucción 1 Instrucción 2 Instrucción 3 ... Instrucción 9 ... Salto hacia delante
alozanoi@teleline.es

Instrucción 1 Instrucción 2 Instrucción 3 ... Instrucción 9 ... Salto hacia atrás
Apuntes de clase

Contadores.3. ETC. Ir a <etiqueta> Bifurcación condicional: La bifurcación depende del cumplimiento de una determinada condición. Antes de usarlo. Realiza la misma función que un contador con la diferencia de que el incremento o decremento de cada suma es una variable en lugar de una constante. D. El acumulador o totalizador es una variable cuya misión es almacenar cantidades variables resultantes de sumas sucesivas. debemos darle un valor inicial. puede ser cualquier valor. Los procesos repetitivos necesitan normalmente contar los sucesos o acciones internas de bucle. Un contador es una variable cuyo valor se incrementa o decrementa en una cantidad constante en cada iteración. VARIABLE_ACUM Ejemplo: Cuenta bancaria VARIABLE_ACUM ± VARIABLE_INCREMENTO SALDO SALDO SALDO + IMPOSICIÓN SALDO . y si es falsa no se realiza. Página: 29 Bifurcación incondicional: Se realiza siempre que el flujo del programa pase por la instrucción sin necesidad del cumplimiento de ninguna condición.2. es decir. Antes de usarlo.Interruptores. Son objetos que sólo pueden tomar uno de dos valores posibles CIERTO o FALSO. Si la condición es cierta se realiza la bifurcación. 1).A. el número de iteraciones que realiza el bucle.0 VUELTAS + 1 FALTAN .I. 1 ó -1.1.Acumuladores. El valor de esta constante no tiene por que ser la unidad. FALTA <. Programación en lenguajes estructurados.1 Ejemplo: Carrera de coches VUELTAS VUELTAS FALTAN 3. 3. de tal alozanoi@teleline. pero en todo el programa debe conservar siempre dicho valor.© A.es Apuntes de clase .) Se usan dándoles un valor inicial y en el lugar que corresponda del algoritmo se niega..L. Si CONDICION ir a <etiqueta> 3. VAR_CONTADOR VAR_CONTADOR ± CONSTANTE_INCREMENTO 0..REINTEGRO 3..Variables auxiliares de un programa..I. debemos darle un valor inicial (0.

Cabecera del programa. Página: 30 forma que si después de negarlo examinamos su valor. Se describen todos los objetos usados en el programa. Decidir en instrucciones alternativas cual es la acción a seguir. En esta sección se escriben todas las sentencias que debe realizar el programa.Cuerpo del programa. SW = FALSO SW = NO SW ? NO SI 4. El formato se ha visto anteriormente..Declaración de objetos. escribiendo el identificador del objeto.1. 4.© A.I.. D. El formato general del programa es el siguiente: alozanoi@teleline. La cabecera de programa es omitida habitualmente y en su lugar se escribe un comentario relacionado con el programa..2.A. Debe comenzar por la palabra ‘inicio‘ y acabar con ‘Fin Programa’.Escritura de programas. Programa NOMBRE DEL PROGRAMA o COMENTARIO. entre ellas se escriben las sentencias. será en cada caso contrario al anterior.es Apuntes de clase . 4..L. Un programa consta de tres partes diferentes: · · · Cabecera de programa Declaración de objetos Cuerpo del programa 4. Son usados en casos como los siguientes: · · · Ejecutar alternativamente acciones diferentes dentro de un bucle. Programación en lenguajes estructurados.I. En ella se expresa una palabra reservada que indica el comienza del programa seguida de un identificador que da nombre al mismo. su tipo y su valor inicial (siempre que lo consideremos necesario).3. Recordar en puntos determinados del programa la ocurrencia o no de un suceso anterior.

. Y.5 Y <-.20 Z <-.NX * TRES Visualizar NX Visualizar DOBLE Fin Programa Valor inicial B) V.© A.es Apuntes de clase .X + Y Visualizar X.L.¿Qué resultado se obtiene de los siguientes programas? A) Programa EJEMPLO_1 Entorno: Nombre Tipo X Nº Entero Y Nº Entero Z Nº Entero Inicio X <-. D.Algoritmo que decida cual de tres número es el mayor.I. D = d * c + R ----> R=D-d*c M=N*c+R ----> R=M-N*c c = Cociente entero de (M / N) 3.25 DOBLE <-. Inicial 3 2. X * Y X <-..Algoritmo que nos diga si un número N es o no divisor de otro número M.I. Ejercicios: 1. Página: 31 Programa NOMBRE DEL PROGRAMA // Descripción del programa Entorno: Nombre Tipo Declaración de los objetos Inicio Descripción de las sentencias Fin Programa. Programación en lenguajes estructurados. Z Fin Programa Programa EJEMPLO_2 Entorno: Nombre Tipo TRES Nº Entero NX Nº Entero DOBLE Nº Entero Inicio NX <-. alozanoi@teleline.A..X * X Visualizar X.

A.Suma de los N primeros números pares enteros positivos.Calcular el factorial de N.Suma de los primeros números enteros positivos. 11. ¿Al cabo de cuantos años de duplicará el capital ? I= C×R 100 21..es Apuntes de clase .Tabla de multiplicar de un número N (1. Programación en lenguajes estructurados....Algoritmo que calcula las siguientes características de los alumnos de la clase: a) ¿Cuantos alumnos tienen menos de 18 años? b) ¿Cuantos alumnos tienen 18 años? c) ¿Cuantos alumnos tienen 19 años? d) ¿Cuantos alumnos tienen más de 19 años? 6. 15. 16. 12. 10. El capital se incrementa cada año con los intereses producidos en el mismo.. 8. alozanoi@teleline.I.Producto de dos números por sumas sucesivas.Escribir las tablas de multiplicar de 1 a 10. D.Imprimir y sumar los cuadrados de los números menores que N.Un capital C se coloca a un rédito R. 17..Obtener la raíz cúbica de todos los números leídos por teclado hasta que encontremos el 0..Valor del número e como suma de la serie : e=∑ 1 1 1 1 1 1 = + + + + . 9. 7. 20.10)..Invertir un número N entero positivo. 22.L.. 13..Programa que obtenga e imprima la lista de los intereses producidos y el capital acumulado anualmente por un capital inicial C impuesto un rédito R durante N años a interés compuesto.© A....I.Número de dígitos que tiene un número N entero positivo... 5...Calcula A elevado a B por productos sucesivos (+ y -).+ i ! 0! 1! 2 ! 3! N! 18..Algoritmo que lee dos números enteros positivos distintos y diga si el mayor es múltiplo del menor. 19..Suma del dinero de los alumnos de una clase..División (cociente y resto) de dos números por restas sucesivas.Edad media de los alumnos de una clase. 14.. Página: 32 4..

.. Un número es perfecto si la suma de sus divisores. 36. 26.. 28.. 25...Programa que lee una secuencia de calificaciones numéricas (0.Programa que lee una secuencia de nombres y escribe el número de veces que se repite el primero de ellos..Igual al anterior. alozanoi@teleline.I. 35. 34. Programación en lenguajes estructurados.Programa que lee el nombre y sueldo de cien personas y escribe el nombre y sueldo de la persona que más cobra y de la que menos. 33.Generar la lista de los N primeros números primos. el menor y el número de veces que ha aparecido cada uno de ellos.Indicar si un número N es capicúa. 32.. el número y porcentaje de aprobados y de suspensos. Por definición el 1º es 0 y el 2º es 1..es Apuntes de clase .Determinar si dos números enteros positivos son amigos. 31.Calcular la sucesión de Fibonacci.L. 29. visualizando un mensaje de si ha aparecido o no un número negativo.10) que finaliza con el valor –1 y calcula y escribe la media aritmética..Programa que calcula el mayor número primo menor que N.Decir si un numero N es primo.. Son amigos si la suma de los divisores del primero excepto él mismo es igual al segundo y viceversa. 24. Página: 33 23. es igual a propio número.© A. 30.. terminada con la introducción de un cero. excepto él mismo.Calcular los múltiplos de N inferiores a M que sean capicúas.I. Cada término es igual a la suma de los dos anteriores.Programa que lee una secuencia de números no nulos..Generar la lista de los divisores de un número N. Dar el mayor. 27. y obtiene e imprime el mayor.A.Números perfectos menores que 1000... D.

.

Así. Para alozanoi@teleline.Introducción a los subprogramas. 1. A su vez. El subprograma ejecuta una tarea y cuando la finaliza retorna el control al programa.. de forma que unos no influyen sobre los otros.SUBPROGRAMAS. por ejemplo x f ( x) = 2 1+ x donde f es el nombre de la función y x es el argumento. esta operación se puede realizar tantas veces como sea necesario y desde cualquier punto del programa. salida de datos. procesos. en cuanto a lo que al desarrollo se refiere. denominado parámetro formal. Este método de diseñar la solución de un problema (principal) obteniendo soluciones parciales (subprogramas) se denomina “Diseño descendente” ya que partimos de un problema general a soluciones específicas de problemas puntuales.es Apuntes de clase .I. Existen dos tipos de subprogramas: funciones y procedimientos o subrutinas.© A. Para solucionar un problema complejo debemos dividirlo en subproblemas más simples y sencillos de solucionar.A.1 Subprograma 2 2. un subprograma también puede realizar llamadas a otros subprogramas. Sin embargo. al punto desde donde se realizó la llamada.Funciones. Programa Subprograma 1 Subprograma 1. Programación en lenguajes estructurados. un subprograma lo utiliza el programa para un propósito específico: recibir datos desde el programa y devolverle los resultados. Cada uno de estos subproblemas se desarrolla de forma independiente del resto.I. Página: 35 4. no lleva asociado ningún valor y es utilizado en la definición de la función. estos se pueden dividir también en otros más sencillos aún. D. El argumento ‘x’. comportándose de la misma que lo hace que cuando la llamada proviene del programa principal.L.. a su vez. Matemáticamente una función es una operación que toma uno o más valores llamados argumentos y produce un valor denominado resultado (valor de la función para los argumentos dados). Llamadas Programa Subprograma Retornos Un subprograma puede realizar las mismas acciones que un programa principal: entrada de datos..

. bloque de declaraciones.I. Una función puede ser llamada desde cualquier parte del programa principal o desde otro subprograma de la forma siguiente: IdentificadorDeFuncion (Lista de parámetros actuales) alozanoi@teleline. consta de cabecera. Cada lenguaje de programación implementa sus propias funciones: cos(x).Declaración de funciones.. sin(x). denominado parámetro actual. Existen dos tipos de funciones: las funciones incorporadas en el propio sistema. Una función tiene una constitución similar a la de un programa. La declaración de una función se hace de la siguiente forma: FUNCION IdentificadorDeFuncion([[Parámetro es Tipo].2. encerrados entre paréntesis. es decir debe haber una sentencia como esta: IdentificadorDeFuncion <--. El programa llama a la función con el nombre de esta en una expresión seguida de una lista de argumentos y la función. y con él calcular el resultado. 2. llamadas funciones internas.L.es Apuntes de clase . cuerpo con las sentencias ejecutables y un final. es lo que después conoceremos como variables locales. son identificadores de variables con su tipo de dato correspondiente y que sólo se utilizan dentro del cuerpo de la función. D.en la que se asigne un valor (el de retorno) al nombre de la función. Cada función se invoca utilizando su nombre en una expresión con los argumentos actuales. después de realizar los cálculos.Expresión.© A. los valores reales.A. devuelve un único valor. 2. Página: 36 evaluar la función debe dársele un valor real a ‘x’. Para el ejemplo anterior podemos escribir el siguiente código de función: Función F( X es entero) es real Inicio F x/(1 + Cuadrado(X)) Fin de función Los argumentos de la declaración de la función se denominan parámetros formales.Invocación a las funciones.I..]) Tipo de Retorno Entorno: Declaraciones de objetos Inicio Sentencias ejecutables Fin de función En el cuerpo de la función debe existir una sentencia de asignación -o más de una. Programación en lenguajes estructurados. .. y las definidas por el usuario o funciones externas (usadas cuando las funciones internas no satisfacen las necesidades de los cálculos).1.

L. Ejemplo: Calcular Y= Xn Función Potencia(x es real. no puede formar parte de una expresión. no pueden utilizarse funciones y debemos recurrir a la utilización de procedimientos o subrutinas. pueden ser constantes. etc. Hay una correspondencia uno a uno de izquierda a derecha. El parámetro actual debe ser del mismo tipo que su correspondiente parámetro formal o un tipo de dato compatible. Página: 37 Los parámetros utilizados en la llamada a la función se denominan parámetros actuales. 3. La subrutina se invoca desde cualquier parte del programa con sólo indicar su nombre y los parámetros asociados. que. Cada vez que se llama a una función se establece una correspondencia entre los parámetros actuales y los parámetros formales de la siguiente manera: · · · Debe haber el mismo número de parámetros actuales que de parámetros formales. por tanto. entre estas sentencias debe estar la asignación de un valor al nombre de la función. Una llamada a una función implica que se realicen los siguientes pasos: · · · A cada parámetro formal se le asigna el valor real de su parámetro actual.I. una vez ejecutadas todas las sentencias que la componen se devuelve el control al programa que la llamó. Un subrutina se diferencia de una función en los siguientes puntos: alozanoi@teleline. Se devuelve el valor de la función previamente asignado y se retorna al punto desde el que se realizó la llamada a la función.I. No tiene ningún valor asociado al nombre y. Un procedimiento o subrutina es un subprograma que ejecuta un proceso específico. a su vez. n es entero) es real Entorno: I es entero y es real Inicio: y 1 para i de 1 a absoluto(n) hacer y y*x fin para si n<0 entonces y 1/y fin si Potencia= y Fin de función Ejercicios: ¿Dos números son amigos? ¿Es capicúa un número? Cálculo del factorial. Cuando necesitemos subprogramas que retornen más de un valor al lugar desde donde se invocaron. Se ejecuta el cuerpo de sentencias ejecutables de la función de la forma que lo hace cualquier programa. D. variables.Procedimientos o subrutinas.A.© A..es Apuntes de clase . Programación en lenguajes estructurados. llamadas a otras funciones.

Si un subprograma está definido localmente a otro subprograma -no todos los lenguajes de programación lo permiten-. La declaración de una subrutina se realiza de la siguiente forma: SUBRUTINA IdentificadorDeSubrutina([[Parámetro es Tipo]. 4. tendrá significado sólo dentro del ámbito de ese subprograma.A.es Apuntes de clase .Ámbito: variables locales y globales. . Disponemos de dos tipos de variable dependiendo del lugar en el que se declaren: variables locales y variables globales. en ningún caso cómo lo hace ni cómo está programado. subprograma o programa principal. el ámbito es la parte del programa donde la variable es visible. el control pasa a la siguiente sentencia desde la que se invocó. esta se consigue con la comunicación a través de los parámetros entre el subprograma y el programa principal. alozanoi@teleline. · · Una variable local es aquella que está declarada dentro de un subprograma y es distinta de otras variables con el mismo nombre declaradas en cualquier otro lugar del programa. la función tiene asociado un valor y sólo puede retornar un valor. es decir. Para utilizar un subprograma sólo necesitamos conocer lo que hace. Programación en lenguajes estructurados.L.. Por el contrario.. 1 o más valores en forma de lista de parámetros. A las variables y constantes les sucede lo mismo: sólo pueden utilizarse dentro del subprograma donde fueron definidas. El uso de variables locales hace posible la independencia de los subprogramas. Cuando se realiza una llamada a la subrutina. la función continúa en la misma sentencia. La parte del programa en que está declarada la variable se conoce como ámbito de la variable y es el fragmento de programa donde puede ser utilizada.© A. La subrutina no tiene asociado ningún valor a su nombre y puede devolver 0. los parámetros formales toman el valor o la dirección de su correspondiente parámetro actual. Ejercicio: Lista de números primos. Una variable global es aquella que está declarada para el programa completo.. las variables globales tienen la ventaja de compartir información de diferentes subprogramas sin una correspondiente entrada de lista de parámetros. D. Página: 38 · · Una vez ejecutada la subrutina.]) Entorno: Declaraciones de objetos Inicio Sentencias ejecutables Fin de función La llamada a una subrutina se realiza mediante la sentencia IdentificadorDeSubrutina(Lista de parámetros actuales) Los parámetros formales y los parámetros actuales tienen el mismo significado que en las funciones.I. El ámbito de un identificador es la parte del programa donde se conoce el identificador.I.

El subprograma no se comunica con el exterior salvo que utilicemos una función. Existen dos métodos principales para pasar los parámetros a subprogramas: paso por valor y paso por variable o referencia. Los parámetros formales -locales a la función.Paso por valor. La correspondencia entre los parámetros se establece aparejando los parámetros actuales y formales según su posición en la lista de parámetros. El subprograma se comunica con el exterior a través de los parámetros. ya que sólo importa el valor del argumento.es Apuntes de clase . Cuando un programa llama a una subrutina. variable o dirección. por tanto. P. que se devuelvan resultados al lugar llamante. 5.L.A. alozanoi@teleline.. utilizamos el método de paso por referencia.. P.. cuya dirección se ha pasado. se puede modificar directamente por el subprograma.I. Una referencia al correspondiente parámetro formal se trata como una referencia a la posición de memoria.© A. Programación en lenguajes estructurados. La unidad que llama pasa a la unidad llamada la dirección del parámetro actual.P. la información se comunica a través de los parámetros y se establece una correspondencia automática entre los parámetros formales y los actuales.P <--. los parámetros son sólo de entrada.S.Paso por referencia.2.1.P. D.P.I. En la cabecera del subprograma no ha habido ningún cambio con respecto a las declaraciones anteriores: sólo se declaran los parámetros formales con su correspondiente tipo de dato. P. no el argumento en sí.P ---> S. Página: 39 5.P <---> S. Los parámetros se pueden clasificar como: · · · Entradas: proporcionan valores desde el lugar que llama y son utilizados dentro del subprograma. Cuando requerimos que ciertos parámetros sirvan como parámetros de salida.reciben como valores iniciales los valores de los parámetros actuales y con ellos se ejecutan las acciones descritas en el subprograma. Los actuales son sustituidos o utilizados en lugar de los parámetros formales. Cualquier cambio que se realice en los parámetros formales (variables locales) no se verá reflejado en el programa llamante. Son parámetros unidireccionales utilizados para proporcionar información al subprograma pero en ningún caso se realizará de forma contraria. Entradas/Salidas: los parámetros se utilizan tanto para mandar argumentos a un subprograma como para devolverlos. que tiene asociado un valor.Comunicación con subprogramas: paso de parámetros. En la llamada al subprograma los parámetros actuales son expresiones. Los parámetros se tratan como variables locales y los valores iniciales se proporcionan copiando los valores de los correspondientes argumentos. Entonces una variable pasada como parámetro real es compartida. 5. Salidas: producen los resultados del subprograma.

Los dos métodos se aplican tanto a las funciones como a los procedimientos.es Apuntes de clase . Dividir el divisor por el resto. Calcular el cociente y el resto. obteniendo un producto equivalente. el parámetro actual pasado por referencia tiene que ser una variable.I. Un procedimiento sólo puede devolver valores por medio de los parámetros por referencia. 5. Por ello. salvo si el segundo factor es impar. alozanoi@teleline. Ejercicios: 1..A.División de dos números por restas sucesivas. Programación en lenguajes estructurados.Calcular el máximo común divisor por el “Algoritmo de Euclides”. · · Una función puede devolver los valores al programa principal como valor asociado a la función y a través de argumentos por referencia. 2. en ambas direcciones. El proceso finaliza cuando el segundo factor se hace cero. Dividir el mayor por el menor. en cuyo caso es necesario acumular previamente el primero en donde se va a obtener el resultado.© A.Calcular el producto de dos números por el “Algoritmo ruso del producto”. D. Página: 40 El lugar de la memoria en que se almacena la variable correspondiente al parámetro actual se utiliza para pasar información de entrada y/o salida. Seguir dividiendo el último divisor por el último resto hasta que la división sea exacta....I. El último divisor es el máximo común divisor. no puede ser una expresión.Calcular el coeficiente del binomio m m!  =  n  n! ( m − n )!   4. 3.. con una dirección de memoria. Consiste en duplicar el primer factor y dividir (cociente entero) por dos el segundo. En seudocódigo la forma de indicar que un parámetro va a ser pasado por referencia consiste en anteponerle la palabra “REFERENCIA” o simplemente indicándolo como un comentario.L.Calcular las raíces de la ecuación de segundo grado.

Programación en lenguajes estructurados..Comentarios..h” #include <stdio.A.h> #include “c:\datos\miarch. Contienen declaraciones de funciones.I.I. Las más habituales son las dos siguientes : #define : Usada para la definición de constantes simbólicas. #include <ArchivoCabecera.es Apuntes de clase . dicho archivo se buscará en el directorio por omisión en el que se encuentran los archivos cabecera . 1. alozanoi@teleline. Las directivas son palabras reservadas que comienzan por el carácter ‘#’ y son detectadas por el preprocesador al llamar al compilador. #define IDENTIFICADOR valor #define PI 3.© A.Estructura de un programa C. Pueden ocupar una o más líneas y no se pueden anidar..Cabecera. · 1. el archivo debe encontrarse en el directorio indicado explícitamente o en el directorio actual de trabajo. si va encerrado entre comillas. El preprocesador tiene la función de leer el programa fuente y sustituir las definiciones de las directrices por los valores correspondientes dentro del programa.h> #include “ArchivoCabecera. En ella se sitúan las directivas usadas por el preprocesador de C. Hay dos formas de escribir comentarios en un programa: · Como una tira de caracteres encerrados entre “/*” (comienzo del comentario) y “*/” (fin del comentario). El signo ‘#’ debe ir en la primera columna seguido de la palabra ‘define’ y a continuación el identificador (habitualmente en mayúsculas) seguido de su valor. Como una tira de caracteres precedida por “//”. Página: 41 5..L. 1. Sólo actúa desde donde se encuentra hasta el final de la línea. D.h” Si el nombre del archivo cabecera está encerrado entre los signos de mayor y menor.2.14159 #define ANGULORECTO 90 #include : Incluye archivos externos en el programa fuente actual.CARACTERÍSTICAS GENERALES DE LOS PROGRAMAS EN LENGUAJE C.1. variables y constantes globales.

I. Página: 42 1..) definidos por el programador. D.Léxico de C. while).. constantes.h> main() { printf(“El primer programa en lenguaje C”) .es . En un programa C siempre debe existir esta función. Programación en lenguajes estructurados.3.Elementos del lenguaje C 2.© A. y además única. Se definen las variables globales del programa y los prototipos de las funciones. Un formato muy general de definición de variables. 1. El lenguaje C hace distinción entre las letras mayúsculas y las minúsculas. tabulador. Operadores : usados para formar expresiones de distintos tipos. esta puede recibir parámetros de entrada y retornar un valor de salida. El lenguaje C dispone de diversos elementos básicos necesarios para la construcciones de programas: · · Palabras clave : juego de instrucciones del lenguaje (for. #include <stdio. Identificadores : nombres de objetos (variables.Función main(). Instrucciones } La función ‘main()’ es una función especial ya que es la primera que se llama cuando se ejecuta el programa. La llave que cierra la función indica el final del programa. Apuntes de clase · · alozanoi@teleline..4. tanto globales como locales.L.A. aunque en esta ocasión se realizará desde y hacia el sistema operativo.I. siempre y cuando.. cambio de línea y comentario). Un programa C es una colección de una o más funciones. se consideren necesarias. indica el comienzo del mismo. es el siguiente : TipoDeDato Identificador [= Valor] . Separadores : usados para separar los diferentes elementos que forman el lenguaje (espacio en blanco..Entorno. tanto unas como otras. La forma genérica de definición de una función en C es: TipoDeDato NombreDeLaFuncion (TipoDeDato Argumento..1.) { Definición de objetos locales a la función. } 2. para que el compilador sepa donde empezar la ejecución. etc. Puede encontrase en cualquier lugar del programa aunque generalmente está situada en la zona superior del mismo (por razones de claridad y estructuración). Como toda función.

es Apuntes de clase . D.I. return F . } unsigned Factorial(int Numero) { unsigned F = 1. &Numero) . Numero.2. void main() { int Numero . getche(). F *= Numero--).h> unsigned Factorial(int N) ..© A. El par de llaves ({}) se usa para la construcción de bloque de programa (sentencias compuestas).Ejemplo de programa en lenguaje C. printf("%d! = %u". Las reglas generales para escribir programas en C son las siguientes : · Toda declaración y sentencia simple debe finalizar en un punto y coma . scanf("%d". Página: 43 2. for ( . Programación en lenguajes estructurados.A. Los bloques de programa son grupos de sentencias lógicamente relacionadas entre si.Sintaxis de C. Numero > 0 . printf("Calcular el factorial de: ") . · 3. Factorial(Numero)) . } alozanoi@teleline. este es usado como terminador de la instrucción.. A continuación de la llave de cierre no va punto y coma.L. #include <stdio.h> #include <conio.I.

.

OPERADORES Y EXPRESIONES 1. Tanto long como short. además. Los unsigned son positivos o 0 y los signed son positivos. signed. pueden proporcionar diferentes tamaños a los tipos de datos. float double Un número decimal en punto flotante de doble precisión (64 bits). Página: 45 6. normalmente del tamaño de los enteros de la máquina donde se ejecuta. una serie de cualificadores que se pueden aplicar a los tipos básicos modificando su rango de valores y/o su tamaño: short long Se aplica al tipo de datos int.TIPOS DE DATOS. que serán las constantes del nuevo tipo. se asume que es un tipo de datos int.Tipos de datos. Si se usa sólo. D. [signed|unsigned] char int Un entero (16 bits o 32 bits). Programación en lenguajes estructurados. Si se usa sólo. se asume que es int. Sólo se imprimen los positivos. todos los tipos de datos son con signo.es .L. void Existen. capaz de contener un elemento del juego de caracteres ASCII. unsigned Se aplican a los tipos de datos int. char.I. Los valores del tipo enumerado se representan con identificadores.A. [signed|unsigned] [short|long] int En general: Tamaño(short) <= Tamaño(int) Tamaño(int) <= Tamaño(long) float Un número decimal en punto flotante de precisión normal (32 bits).© A.I. Si se usan sin ningún tipo de dato. [long] double enum Una lista de enteros que pueden ser tomados por una variable de ese tipo. Apuntes de clase alozanoi@teleline.. Hay dos tipos de datos en C: fundamentales y derivados. Por omisión. long y short. se asume que es un tipo de datos int. Se aplican a los tipos de datos enteros y reales de doble precisión. Los tipos de datos fundamentales son los siguientes: char Un octeto (8 bits).. negativos o 0. Usado para la declaración de funciones que no retornan ningún valor o para declarar punteros a un tipo no especificado.

7 x 10-308 3.483.483.147. También se puede especificar el tipo de la constante añadiendo los sufijos L(long).7 x 10-308 3. Se pueden escribir en mayúsculas o minúsculas.768 -32..648 0 -2. U(unsigned int) o UL(unsigned long int).295 2. 2. 0X(hexadecimal).147. Tipo unsigned char char short int unsigned int int unsigned long enum long float double long double near (pointer) far (pointer) Longitud 8 bits 8 bits 16 bits 32 bits 32 bits 32 bits 16 bits 32 bits 32 bits 64 bits 80 bits 32 bits 32 bits 0 -128 -32. D.147.767 4.4 x 10+38 1. Podemos usar el sufijo (tipo) y el prefijo (base) en el mismo número.767 32.7 x 10+308 1.535 32. En caso de ser negativa.483..1. debe especificarse el signo menos. 31(decimal) = 037(octal) = 0x1f(hexadecimal) alozanoi@teleline.L.147.7 x 10+308 1.© A.295 2.967.483.483.1 x 10+4932 no aplicable no aplicable 2.767 65.967.147. El tipo de una constante entera viene determinado por su valor.647 3.294.768 0 -2.483.648 3.I.4 x 10-4932 Rango to to to to to to to to to to to 255 127 32.4 x 10+38 1.768 0 -32.147.647 3.768 0 -2. Programación en lenguajes estructurados.es Apuntes de clase .1 x 10+4932 no aplicable no aplicable Resumen de los tipos de datos de 32 bits.294.Constantes enteras.4 x 10-38 1.295 2.967.4 x 10-38 1.Constantes.647 4.767 4.294.648 -2. Además se puede especificar la base de representación del número con los prefijos 0(octal).A. Tipo unsigned char char enum unsigned int short int int unsigned long long float double long double near (pointer) far (pointer) Longitud 8 bits 8 bits 16 bits 16 bits 16 bits 16 bits 32 bits 32 bits 32 bits 64 bits 80 bits 16 bits 32 bits 0 -128 -32.483.147.4 x 10-4932 Rango to to to to to to to to to to to 255 127 32.I.648 3.483. Página: 46 Resumen de los tipos de datos de 16 bits.647 2.147.

Una tira es un vector cuyos elementos son caracteres.Constantes de cadena.Expresiones constantes.A.I. Tiene siempre el tipo double. Se evalúa en tiempo de compilación.3. Está formada por una parte entera. seguida de un punto decimal. Se pueden usar también las secuencias de escape. Algunos caracteres no imprimibles se representan como constantes mediante secuencias de escape ( \n: nueva linea.4. Es un único carácter escrito entre comilla simples. Es una expresión formada únicamente por constantes. \\: barra invertida. #define FORMFEED '\014' #define BEEP '\x7' 2.. La primera representa el valor numérico del carácter y la segunda es una tira de caracteres finalizada con el carácter nulo. Cualquier carácter de la tabla ASCII se puede representar de la forma ‘\ooo’(octal. a no ser que se usen los sufijos F(float) o L(long double). Página: 47 2.. de 1 a 3 dígitos) o '\xhh'(hexadecimal. 2. Es una tira de cero o más caracteres encerrados entre comillas dobles. Estas constantes participan en las operaciones numéricas como cualquier otro número.L.I.. El compilador sitúa el carácter nulo (\0) al final de la cadena para conocer cual es el final de la misma..5. \0: nulo..© A. \’: comilla simple). aunque sólo es uno.2. dos dígitos). sólo delimitan. #define MINUTOS 60 #define SEGUNDOS 60 .es Apuntes de clase . Programación en lenguajes estructurados. La memoria requerida para almacenar una cadena es su longitud más uno (el carácter nulo).Constantes de un sólo carácter. y una parte fraccionaria. Su valor es el número que ocupa el carácter dentro de la tabla ASCII.. También se puede usar la notación científica. \t: tabulador. "La casa" L a C a s a \0 "A" A \0 'A' 65 Debemos distinguir entre una contante de tipo carácter y una cadena. 2. aparece como dos caracteres. D.Constantes reales. Tiempo = MINUTOS * SEGUNDOS alozanoi@teleline. estas no forman parte de la tira.

const int Dias = 10. El % (el resto de la división entera) sólo puede usarse con operandos enteros. Página: 48 2. Las variables pueden ser inicializadas en su declaración como en el ejemplo anterior. *.I. (const Dias = 10. Cuando en una expresión aparecen los operadores lógicos..I. Los operadores lógicos son: &&(y). Los operadores relacionales son: >. "es par" /* N % 2 = 0 */ alozanoi@teleline.. <. El operador ! convierte un operando distinto de 0 (o valor cierto) en cero y uno con valor 0 (o valor falso) en uno. Todas las variables deben declararse antes de que puedan ser utilizadas. / y %. int inf..2.Variables: declaración. D.1. Si N % 2 visualizar N. -.A.Identificador]. linea[1000]. "es impar" /* N % 2 <> 0 */ si no visualizar N. 3. int sup = MAXIMO. 3..Operadores aritméticos. !=. Las globales las inicializa el compilador a 0 y las locales tendrán un valor indefinido. Los operadores aritméticos binarios son: +. Programación en lenguajes estructurados. ||(o) y !(no). ==. La declaración de un objeto puede ir precedida de la palabra 'const' indicando que este objeto es una contante. su evaluación finaliza tan pronto como se conozca su resultado. Mientras Primo && c > n && Una expresión lógica retorna un valor 0 si su evaluación es falsa y un 1 (o distinto de 0) si esta es verdadera. paso. <=.. char linea[1000].© A.L. El formato general para la definición de objetos en programa C es: Tipo_de_dato Identificador [.. int inf = MINIMO. int paso = 1. char c. sup.Operadores. Una declaración especifica un tipo de dato seguido de una o más variables.Operadores relacionales y lógicos.. char c = '\A'.es Apuntes de clase .) const char nombre[] = "Antonio" 3. >=.

en las expresiones donde la variable receptora del valor también forma parte de la expresión. c <-.I. A . modifica el valor de la variable después de usar su valor.'E' */ Expresión no deseada i <-.Operadores de incremento y decremento.es Apuntes de clase . c <-. modifica el valor de la variable antes de usar su valor y cuando se aplica como sufijo (i--). Página: 49 3. Si “Identificador” es una variable y “Expresión” una expresión válida. ++i) o como sufijos (detrás del operando i--). visualizar ++i visualizar i++ visualizar ++i. Esto significa que en el contexto donde se utilice el valor y no sólo su efecto. char c = 'D'. En ambos caso el efecto producido sobre la variable es el mismo. Hay dos operadores en C para incrementar o decrementar variables (sólo pueden aplicarse a variables.'E' */ i <-. esta se puede simplificar.A.. ++i e i++ son distintos. i = 10.I.Operadores de asignación y expresiones. ++i visualizar ++c visualizar c++ i = c++ i = ++c i = i++ + j /* /* /* /* /* /* /* /* /* 11 */ 10 */ Resultados no deseados 12 10 ( de derecha a izquierda)*/ Resultados no deseados 11 11*/ E */ D */ i <-..1. A++ es equivalente a A Resta uno al operando. En el fragmento de programa siguiente es indiferente usar el operador como prefijo que como sufijo: Mientras i < n ++i Mientras i < n i++ En las siguientes expresiones. La característica fundamental de estos dos operadores es que se pueden usar como prefijos (delante del operando. entonces Identificador op= Expresion es equivalente a alozanoi@teleline. nunca a expresiones): ++ -- Suma uno al operando.4. i++ visualizar i++. Programación en lenguajes estructurados.3. El operador de asignación es el signo = y el formato general de la sentencia de asignación es: Variable = Expresión Además.ASCII('E').© A. A— es equivalente a A A + 1. sin embargo.12 */ 3. depende de que se use como prefijo o sufijo para obtener un resultado u otro: int j = 1. D. existe una diferencia: cuando se aplica como prefijo (++i).ASCII('D').L. incremento o decremento de la misma en una unidad.

-.5. Página: 50 Identificador = (Identificador) op (Expresion) Los paréntesis implican asociación: x *= y + 1 ===> x = x * (y + 1) La mayor parte de los operadores binarios disponen del correspondiente operador op=. i.Operador condicional. D. i++) if (i%5==4 || i==99) printf("%2d\n". for (i = 0. 3. "E1 ? E2 : E3" es equivalente a "si E1 entonces E2 si no E3". /. Si es cierta. Suma += Numero % I ? 0 : I.I. el tipo del resultado se establece por las reglas de conversión. siendo este el valor de la expresión condicional.es Apuntes de clase . *. En otro caso. i < 100. &. Programación en lenguajes estructurados. |.I. Si E2 y E3 son de diferente tipo de dato. Ejemplos: z = (a > b) ? a : b. ^. Si a > b z=a si no z=b Fin si Suma = Numero % I ? Suma : Suma += I. i < 100. <<.. Los operadores de asignación pueden aparecer en expresiones.i).A. si Numero % I = 0 Suma = Suma + I Fin si for (i = 0. se evalúa la expresión e2. y éste será su valor.© A. se evalúa e3. i++) printf("%2d%c". Usar sentencias de asignación de esta forma hace que el compilador genere un código ejecutable mas eficiente y normalmente ayuda a la comprensión de las sentencias. (i%5==4 || i==99)?'\n':' '). En la expresión "e1 ? e2 : e3" primero se evalúa e1. %.L.i). alozanoi@teleline. donde op es: +. aunque debe evitarse en la medida de lo posible. else printf("%2d ". >>.

el otro se convierte. Los caracteres y enteros (char e int) se pueden mezclar libremente en las expresiones aritméticas: todo char de una expresión se convierte a int automáticamente.I. int Minusculas(int c) { if (c >= 'A' && c <= 'Z') Return(c + 'a' . los dos operandos son de tipo int. el valor de la derecha se convierte al tipo de la izquierda. · Si un operando es de tipo unsigned long. alozanoi@teleline. el otro se convierte..Conversión de tipos. en general. Cuando usamos una expresión aritmética. por orden. else Return(c). Si es al contrario. el otro se convierte. zero filled enum int Same value · Si un operando es de tipo long double. · Si un operando es de tipo unsigned. Los enteros de mayor magnitud (long) se convierten al tipo short o a caracteres por eliminación de los bits de orden superior. double se convierte en float por redondeo. sign extended unsigned short unsigned int Same value.L. · Si un operando es de tipo long. · · · De float a int se trunca la parte fraccionaria. tal como a + b. · En cualquier otro caso. el otro se convierte. Sqrt((double)n): convierte n al tipo double pero no modifica su valor. (Nombre_de_tipo) expresión Nombre_de_tipo (expresión) (C) (C++) La expresión se convierte al tipo de dato citado mediante las reglas de conversión anteriores. Página: 51 4. no hay variación en el valor de la variable o expresión asignada. · Si un operando es de tipo double.es Apuntes de clase .© A. Programación en lenguajes estructurados. redondeando o eliminando los bits más significativos. se truncará el valor. son las siguientes: Tipo Dato Conversión A Método char int Zero or sign-extended unsigned char int Zero-filled high byte (always) signed char int Sign-extended (always) short int Same value. el otro se convierte. Sólo se realizan aquellas que tienen sentido.'A'). el operando de tipo de dato inferior es ascendido al tipo de dato superior antes de evaluar la expresión y el resultado es del tipo superior. Otra forma de realizar una conversión del tipo de dato es indicando explícitamente la conversión mediante una construcción denominada cast (casting). el otro se convierte. cuando a y b son de diferente tipo.I.A. D. Las conversiones también tienen lugar en asignaciones. } Las reglas de conversión. que es el tipo del resultado. · Si un operando es de tipo float. Cuando el tipo de dato de la variable que recibe el valor es de un tipo igual o superior.

La siguiente tabla muestra el orden de precedencia y asociatividad de todos los operadores. Programación en lenguajes estructurados. !. >= ==.*.© A.I. Asociatividad De izquierda a derecha De derecha a izquierda De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De izquierda a derecha De derecha a izquierda De izquierda a derecha alozanoi@teleline.A. Página: 52 5. ->* *. . new. delete . != & ^ | && || ?: =. *. *=. Los operadores situados en la misma línea tienen la misma precedencia y las filas están colocadas en orden de precedencia decreciente. D. ++. +=. sizeof. |=. >> <. %=. <<=. % +.. <<. ::. &. /=. +.es Apuntes de clase .Precedencia y orden de evaluación de los operadores. Operadores ().I. >>= . /. -=. ->. >. -.L. <=. --. []. &=. ~. ^=.

.h>" al principio del mismo. Básicamente. D. 2. bajo la supervisión de la cadena de control o formato.]).I.. Indica el número mínimo de caracteres que se deben imprimir.. Si no se especifica. Si es un número entero. Es opcional. Es una cadena de dígitos (la precisión). se justifica a la derecha y se rellena por la izquierda con blancos o ceros.. El formato del comando de control por orden de escritura es el siguiente: % [flags] [ancho] [. Cada comando de control comienza por el símbolo de tanto por ciento (%) y finaliza en un carácter de control.. [ancho] [. 2.h define ciertas macros y variables empleadas por la librería estándar de E/S así como el prototipo de las funciones de E/S.Salida con formato. y los comandos de control de formato o especificadores de conversión. que no implica base octal). int printf("Cadena de control" [. . Justifica el argumento a la izquierda y rellena con blancos por la derecha. Función printf()..precisión] [h|l|L] Carácter_de_control [flags] Caracteres señalizadores.Funciones de entrada y salida estandar. o el número de dígitos que se deben imprimir a la derecha del punto decimal de un valor de tipo real (float o double). Retorna el número de bytes visualizados.en la salida. Estas pertenecen a la librería estándar de E/S. Todo fichero fuente que use funciones de la librería estándar de E/S deberá contener la línea "#include <stdio. . printf() convierte (da formato) y visualiza sus argumentos en la salida estándar. cada uno de los cuales origina una conversión del siguiente argumento de printf().Acceso a la librería estándar.A. int printf(const char *format[. argumentos. + Muestra el signo + o . que se visualizan por pantalla. El fichero stdio. Especificador de precisión..prec] alozanoi@teleline.I. Son opcionales. Es opcional.es Apuntes de clase . que indica el número máximo de caracteres que se imprimirán de la cadena.ENTRADA Y SALIDA POR PANTALLA 1. argument. se rellena con blancos o ceros (si se escribe un 0 delante del ancho.© A.1. lo que realiza esta función es imprimir una cadena de caracteres sobre la pantalla del ordenador (por stdout). Página: 53 7. Especificador del ancho del campo. indica el número mínimo de dígitos a imprimir.L.]). La cadena de control es una constante de tipo cadena que contiene dos tipos de objetos: caracteres ordinarios. Programación en lenguajes estructurados.. Las funciones que proporciona el lenguaje para la entrada y salida estándar no forman parte del propio lenguaje.

Es un real con signo de la forma [-]dddd.dddd.F) Argumento de tipo float o double.C. '\n' Nueva línea.I. Si es pto.d. '\"' Visualiza ".D.A.I. Este modificador afecta a la forma en que la función printf() debe interpretar el tipo de dato del argumento que se escribe a continuación.© A. '\\' Visualiza \.Flotante c s Carácter Cadena % Nada Entero decimal con signo Entero octal con signo Entero decimal sin signo Entero hexadecimal sin signo (a. son los siguientes: d. Es opcional. '\t' Tabulador horizontal. La parte decimal se imprime si es necesario. También se usan constantes de tipo carácter no imprimibles en la cadena de control. 6 por defecto. los resultados son imprevisibles. int main(void) { char Cadena[10] = "La casa". '\b' Backspace (retroceso). Flotante. Estos.e.B. i o u x X f Entero Entero Entero Entero Entero P. se visualiza. Visualiza un carácter simple. Visualiza el carácter %.Flotante e. Redondea dependiendo de la precisión.dddd o e[+/-]ddd.Flotante g. Es un real con signo de la forma [-]d.E. Argumento de tipo float o double.f) Entero hexadecimal sin signo (A.E P. '\xhh' Valor ASCCI hexadecimal. h = short int (dioux) l = Long (dioux) L = long double (efg) l = Double (efg). Estos son: '\a' Beep. Página: 54 [h|l|L] Modificador del tamaño del campo. El número de dígitos decimales viene indicada por la precisión. Si el carácter que va detrás del % no es uno de los anteriores. Carácter de control Carácter de conversión de tipo de dato. El número de dígitos decimales viene indicado por la precisión. Usa el más corto de entre %e y %f.b. '\'' Visualiza '. Visualiza una tira de caracteres hasta que se encuentre con el carácter nulo (\0) o alcanzar el número de caracteres indicados en el especificador de precisión. alozanoi@teleline. Si el número de caracteres de control no se corresponden (en número y tipo) con los argumentos.G P. Programación en lenguajes estructurados.c. 6 por defecto. Es obligatorio. D.L. Indica la forma en que debe realizarse la conversión del argumento para que sea visualizado por pantalla. '\ooo' Valor ASCII octal.es Apuntes de clase .

Real). Resultado erróneo.Entero).111115E+05: : 111112: 2. Es equivalente a printf() pero en la entrada de datos desde el puerto estándar de entrada: el teclado (por stdin). printf(":%15f:\n".Real).]). Justifica a la derecha.Real)..Cadena). printf(":%s:\n". // // // // // // Visualización de los resultados. los interpreta de acuerdo con la cadena de control. printf(":%15o:\n". printf(":%-15X:\n". // Justifica a la derecha. Página: 55 int Entero = 12345. Rellena con ceros.A. .EnteroH). :La casa: : La casa: :La casa : :La c : :12345: : 12345: :000000000012345: :12345 : : ff: :FF : : 377: : 65432: : -104: :111111. printf(":%15x:\n". No tiene efecto. y almacena los resultados en los restantes argumentos.. Rellena a blancos.523438: : 111111. int scanf("Cadena de control" [. int scanf(const char *format[. // Justifica a la izquierda.L. printf(":%15s:\n". Hexadecimal mayúsculas Octal Largo entero // Largo entero.Entero). Los argumentos deben ser punteros (dirección de alozanoi@teleline.Cadena).LargoEnt). printf(":%15ld:\n".EnteroH).Cadena). // Justifica a la izquierda y visualiza los primeros (4). Justifica a la izquierda. printf(":%2d:\n".Entero). dir. printf(":%E:\n". printf(":%-15s:\n".Real).Real). D. argumentos. printf(":%15d:\n".Entrada con formato.es Apuntes de clase . float Real = 111111.I. Hexadecimal minúsculas.Real).523438 : :111111. Rellena a blancos. printf(":%15G:\n". long int LargoEnt = 65432. Rellena a blancos. Función scanf().I. printf(":%-15f:\n".© A.EnteroH).2f:\n".2..LargoEnt).. printf(":%-15d:\n". printf(":%-.Cadena). address. No deja espacios // Justifica a la derecha. printf(":%15d:\n". .523438: :111111. printf(":%-15. visualizado como entero simple.52: :1.4s:\n". printf(":%f:\n".Entero). Programación en lenguajes estructurados. Lee los caracteres desde el teclado.422222.. int EnteroH = 255.]). printf(":%015d:\n". } // // // // // // // // Justifica a la derecha.

L. Especificador del ancho del campo.© A. Si se indica supresión de asignación (*).es Apuntes de clase . Es opcional. la función scanf() pasa los argumentos por referencia. o. Retorna el número de argumento convertidos. Estos. El formato del comando de control por orden de escritura es el siguiente: % [*] [ancho] [h|l|L] Carácter_de_control [*] [ancho] Suspende la asignación de entrada para el siguiente argumento. no por valor como lo hace printf(). Un carácter de control dirige la conversión del próximo campo de la entrada. o. D. La cadena de control es una constante de tipo cadena que contiene los comandos de control de formato o especificadores de conversión. la conversión se realizará a long tipo. u. Carácter d f o i u x s c Si los caracteres de control d. flt. cada uno de los cuales origina una conversión del siguiente argumento de scanf(). no se realiza la asignación.I. siendo necesario indicarselo anteponiendo el carácter & (dirección) a cada argumento. Es opcional. no se toma en cuenta el campo de entrada.A. son los siguientes: Control Argumento Decimal integer Puntero a int (int *arg) Floating point Puntero a float (float *arg) Octal integer Puntero a int (int *arg) (Empieza por 0) D. i. El resultado se almacena normalmente en la variable a la que apunta el correspondiente argumento. Cada comando de control comienza por el símbolo de tanto por ciento (%) y finaliza en un carácter de control. Modificador del tamaño del campo. Es obligatorio. Indica el número máximo de caracteres que se deben leer para el argumento. Es opcional. h integer Puntero a int (int *arg) Unsigned d integer Puntero a unsigned int (unsigned int *arg) Hexadecimal integer Puntero a int (int *arg) Cadena de caracteres Puntero a array de chars (char arg[]) Puntero a char (char *arg). Programación en lenguajes estructurados. excepto a los de tipo cadena. Indica la forma en que debe realizarse la conversión del argumento para que sea almacenado en el argumento correspondiente. Página: 56 memoria del argumento) que indican donde se debe almacenar el resultado. x son escritos en mayúsculas (equivalentes a poner el prefijo l). Se suprime el salto Carácter normal sobre el carácter blanco. h = short int l = long int (si Carácter Control integer) l = double (si Carácter Control pto. Este modificador afecta a la forma en que la función scanf() debe interpretar el tipo de dato del argumento que se escribe a continuación. alozanoi@teleline. usar %1s.I.) L = long double [h|l|L] Carácter de control Carácter de conversión de tipo de dato.

abarca hasta el primer blanco o tantos caracteres como indique el tamaño del campo. &m.32E-1 Pérez Asigna a i el valor 25. fin de línea). La próxima llamada a cualquier rutina de entrada comenzará la exploración en la letra a. El contenido de los corchetes se llama scanset. Scanf("%*[^0-9] %d". por lo que no es necesario inprimirlo. nombre). También envía un eco del carácter pulsado a la pantalla. scanf("%2d %f %*d %2s".es Apuntes de clase .Función getchar(). &i). Entrada: 25 54.I. se eliminan. Cuando encuentra el final del fichero en la entrada de datos o cuando se produce un error devuelve el valor EOF. una lista ([01234]) 0 el signo ^ seguido por un rango o lista para indicar no (negación). Programación en lenguajes estructurados. Al llegar al final del fichero se devuelve EOF. El scanset puede ser un rango de valores ([a-z]). Uso de scanf() con Scanset: Hay que usar corchetes en la cadena de control.0 a x. Entrada: 56789 0123 54a72 Asigna 56 a i. [^a-z] lee chars mientras no sean minúsculas. Ejemplos: int i. estos permiten que scanf() acepte caracteres que reemplacen el grupo de caracteres que haya dentro de los corchetes. 3.. str.I. float x. char nombre[50]. &a) scanf() acaba cuando se agota la tira de control o cuando la entrada no coincide con el carácter de control. int getchar(void). scanf("%d %f %s". &i.h con valor -1. pero como lleva el *.© A. siempre que no haya caracteres almacenados en el buffer esperando para ser leídos) y después devuelve su valor. &x. scanf(“%2d%*c%2d%*c%2d%*c”. EOF es una contante simbólica definida en stdio. [a-z] lee chars mientras sean minúsculas. Espera a que se puse una tecla. alozanoi@teleline. 2 ó 3. &x. de la entrada cada vez que se invoca. Lee caracteres situándolos en str mientras no sean dígitos. Lee caracteres mientras no sean dígitos. tabuladores. &i.L. [123] lee chars mientras sean 1. &i). se salta 0123 y a nombre la tira "54". nombre). Página: 57 Un campo de entrada se define como una cadena de caracteres delimitada por espacio en blanco (blancos. Devuelve como valor el número de elementos de entrada que ha podido reconocer y asignar. a x el valor 54.32E-1 y a nombre el valor Pérez. Esta función devuelve el siguiente carácter leído.A. en forma de entero. Scanf("%[^0-9] %d". &d. D. 789.

alozanoi@teleline. Sólo visualiza caracteres. 6.Funciónes getch() y getche(). Reconoce los códigos de escape (p. no números.Función gets()...e. No se comprueba la entrada de datos. int puts(const char *s). 5. 7. Pide una cadena de caracteres desde el teclado y la devuelve como un array terminada en el carácter nulo en el parámetro de la función. #define LONGITUD 20 char Cadena[LONGITUD + 1].L. pero sólo si es un carácter del código de caracteres. printf("%s". D. Página: 58 4. Programación en lenguajes estructurados. La entrada finaliza con el retorno de carro. Se escribe automáticamente el carácter de nueva línea.Función puts()..Función putchar(). Envía un carácter a la salida estándar. \n)para la visualización.A. gets(Cadena)).I. gets(Cadena). int putchar(int c). puts(Cadena).I. por lo que la longitud de la cadena debe ser lo suficientemente grande como para que quepan todos los caracteres tecleados.. Si se produce algún error retorna EOF. .© A.es Apuntes de clase . por tanto no puede realizar ninguna conversión de formato.. si no hay espacio suficiente se produce un error. Escribe el argumento de tipo cadena en la pantalla. char *gets(char *s)..

se mencionan las demás sentencias que afectan al flujo del programa -break. si no se quiere así. while. si es falsa (igual a cero) no se realiza ninguna acción o. if (n > 0) if (a > b) z = a. En C el punto y coma indica el final de la sentencia.Sentencias de selección o condicionales... permiten la repetición una serie de operaciones. [else <Sentencia/s 2>. no será necesario encerrarla entre llaves. if (n > 0) { if (a > b) z = a. Se evalúa la expresión y si esta es cierta (distinta de cero) se realiza el grupo de <sentencias 1>.Introducción. Puesto que se han diseñado los bucles para tener un punto de entrada y un punto de salida. alozanoi@teleline. Una expresión simple como x = 0 ó i++ se convierte en una sentencias cuando va seguida de un punto y coma. Las sentencias condicionales if y switch permiten alterar el flujo del programa según ciertas condiciones. Cuando en una sentencia múltiple (if.. El formato de la sentencia es el siguiente: if ( <condición> ) <Sentencia/s 1>. Si existe más de una sentencia en cualquiera de los bloques de acciones.pero no se profundiza en su uso por no formar parte de la programación estructurada. deberá encerrarse entre llaves.] Esta sentencia se usa para tomar decisiones. for.SENTENCIAS DE CONTROL DE PROGRAMA 1.L.. en una sentencia compuesta o bloque. else z = b. Dos ejemplos donde necesariamente debemos usar las llaves son: · · Para encerrar el cuerpo de una función. Página: 59 8.© A. se realiza el grupo de <sentencias 2>. ..Sentencia if-else. Si sólo hay que ejecutar una sentencia. 2. D. La cláusula ‘else’ se asocia con el ‘if’ inmediatamente anterior.. 3. for y do-while..A. Se van a estudiar las sentencias que afectan al control de flujo del programa.es Apuntes de clase .I.1. en el caso de que la clausula else esté presente. continue y goto. Las construcciones de bucle. se deben usar las llaves para forzar la asociación deseada. lógicamente relacionadas. } else z = b.) debamos ejecutar varias sentencias lógicamente relacionadas entre sí formando un bloque de acciones.Sentencias y bloques. Las llaves ({}) se usan para agrupar declaraciones y sentencias. siendo sintácticamente equivalentes a una sentencia simple.I. Programación en lenguajes estructurados. 3.

Es una sentencia múltiple que comprueba si una expresión es igual a uno de entre varios valores constantes.. mayúsculas. CuentaMayusculas).*/ #include <stdio. printf("Min: printf("May: printf("Dig: printf("Otr: } %d\n". si alguna es cierta. if (c >= 'a' && c <= 'z') ++CuentaMinusculas.2. El formato de la sentencia es el siguiente: switch ( <Expresión> ) { case <Expresión constante 1> : <Sentencia/s 1> [break. Las expresiones se evalúan en orden. CuentaOtro).L. %d\n". Programación en lenguajes estructurados. se realizará si no se cumple ninguna de las condiciones anteriores. se ejecuta la sentencia o bloque de sentencias encerradas entre llaves asociada con ella. int CuentaMayusculas = 0.es Apuntes de clase . c = getchar(). Esta sentencia también nos permite realizar construcciones de la siguiente forma: if (expresión 1) <Sentencia/s 1> else if (expresión 2) <Sentencia/s 2> else if (expresión 3) <Sentencia/s 3> else <Sentencia/s N> Es la forma normal de escribir una decisión múltiple. 3. else ++CuentaOtro. %d\n".I. Falta el bucle. sólo se usa para dar una mayor legibilidad al programa y así evitar la ambigüedad. El último else.I. else if (c >= 'A' && c <= 'Z') ++CuentaMayusculas. dígitos y otros caracteres. Página: 60 El sangrado de las sentencias no implica asociación de ningún tipo. CuentaDigitos). int CuentaOtro = 0. que es opcional.] alozanoi@teleline. int CuentaMinusculas = 0. int CuentaDigitos = 0. D.h> void main(void) { int c. else if (c >= '0' && c <= '9') ++CuentaDigitos. CuentaMinusculas).A.Sentencia switch. %d\n".© A. bifurcándose de acuerdo con ello. /*Cuenta minúsculas.

no se realiza nada. En las sentencias de iteración que proporciona el lenguaje C. Programación en lenguajes estructurados.I. es fácil que el bucle realice una iteración de más o de menos. que es opcional. El formato del bucle es el siguiente: while ( Condición ) <Sentencia/s> alozanoi@teleline. las sentencias que forman el cuerpo del bucle se ejecutan mientras la condición de finalización o continuidad sea verdadera. Ejemplo switch (Operando) { case MULTIPLY: x *= y. Comprobar que se realizan correctamente la primera y la última iteración. case INCREMENT2: x++.] default : <Sentencia/s N>. /* Continúa en la línea siguiente */ case INCREMENT1: x++. case EXPONENT: case ROOT: case MOD: printf("No se hace nada\n"). } 4. break. Las opciones deben ser todas diferentes.L. a no ser que se use la sentencia ‘break’ que fuerza una salida inmediata del ‘switch’. se ejecuta si no se cumple ninguna de las anteriores. dado que cada ‘case’ se comporta como una etiqueta. se debe modificar el valor de la condición de finalización del bucle dentro del cuerpo del mismo. break. Página: 61 case <Expresión constante 2> : <Sentencia/s 1> [break. constante carácter o expresión constante. Después de la ejecución de un bloque de sentencias.A. se ejecuta el grupo de sentencias asociado a él. Es esencial poner especial cuidado en la construcción de un bucle en los siguientes puntos: · · Asegurarse de que hay condiciones de finalización del bucle para evitar que estos se ejecuten indefinidamente. case ADD: x += y. Se evalúa la expresión entera y compara su valor con todos los casos. case DIVIDE: x /= y. break. D. break.Sentencia while.Sentencias de iteración o bucles.© A. case SUBTRACT: x -= y. la ejecución continúa en el siguiente case. no admite expresiones variables.es Apuntes de clase .I. 4. default: printf("¡Error!\n").1. break. si no existe. break. break. El ‘default’.. En el caso en que un valor sea igual a la expresión.. } Cada opción debe ser etiquetada con un entero. disjuntas.

while ((c = getchar()) != EOF) { if (c >= 'a' && c <= 'z') ++CuentaMinusculas. int Penul. &Penul. else if (c >= 'A' && c <= 'Z') ++CuentaMayusculas. &Ultimo.I.h> #include <ctype. printf("Nuevo número: ").I. Entradas++. Aunque el C y otros lenguajes de programación permiten la construcción de bucles infinitos y finalizarlo por otros medios.h> #include <conio. Numero. si ya se ha escrito un * finaliza. Ultimo. D.h> int main(void) { int Entradas = 3. { Penul = Ultimo. La condición es cualquier expresión lógica válida. Página: 62 La sentencia o grupo de sentencias (entre llaves en este caso) se realizará hasta que la Condición de valor falso. while ((Carácter = getchar()) != '*') putchar(toupper(Caracter)). dígitos y otros caracteres*/ #include <stdio. siempre necesitaremos una condición de finalización o continuidad del bucle. scanf("%d %d %d". por tanto. Ultimo = Numero. int CuentaDigitos = 0. } /*Cuenta minúsculas. Entradas).L. } printf("Introducidos %d".A. int CuentaMinusculas = 0.es Apuntes de clase . int CuentaMayusculas = 0. Programación en lenguajes estructurados. También debe contar el número de entradas.*/ int main(void) { int Caracter. puede que el cuerpo del bucle no se realice ninguna vez. printf("Los tres primeros\n"). no está contemplado en la programación estructurada y. } alozanoi@teleline. int CuentaOtro = 0.h> int main(void) { int c.h> /*Usada por los caracteres y conversiones: int toupper(int ch). Como lo primero que se hace es evaluar la condición. mayúsculas.© A. } Ejercicio: Programa que lee una secuencia de números desde teclado y finaliza cuando se introduce uno mayor que la suma de los dos anteriores. &Numero) while (Numero <= Penul + Ultimo). Ejemplo: lee caracteres de la entrada de datos y después de un Enter visualiza lo escrito en mayúsculas. else if (c >= '0' && c <= '9') ++CuentaDigitos. scanf("%d".h> #include <conio. else ++CuentaOtro. #include <stdio. #include <stdio. &Numero).

Los puntos y coma siempre deben aparecer. Página: 63 printf("Min: printf("May: printf("Dig: printf("Otr: return 0. I=1. I<Numero. es indiferente usar la notación prefija o sufija en los operadores de incremento. I++). %d\n". 4. Si se omiten las tres expresiones.Sentencia for.2. for (I = 1. I < Numero. Suma de los divisores de un número. Visualiza los primeros números. Suma = 0 . CuentaMinusculas). [<Incremento>] ) <Sentencia/s> Funcionamiento: · · · Antes de la primera iteración del bucle. Programación en lenguajes estructurados.A. I++). I++) Suma +=I. así pues. Las variables usadas en la cabecera del for no se deben modificar dentro del cuerpo del bucle. for (I = 1. se inicializa la/s variable/s de control del bucle situada/s en la zona de inicialización. Después de cada iteración se incrementa el contador. for (I = 1. D. ++I) Suma = Numero % I ? Suma : Suma += I. se convierte en un bucle infinito.L. for (Suma=0.I++)). La sentencia o grupo de sentencias se ejecuta hasta que la condición sea falsa. for (I = 1. ) Putchar(tolower(c)). alozanoi@teleline. Suma = Numero % I ? Suma : Suma += I. Suma = 0 . For ( . [<Condición>] . Suma += Numero Lee caracteres.I. I < Numero.es Apuntes de clase . Ejemplos: Suma los primeros números. CuentaOtro). Las expresiones de inicialización y de incremento pueden llevar más de una expresión (habitualmente sentencias de asignación) separadas por comas (se evalúan de izquierda a derecha). Suma +=I. Si se omiten estas dos expresiones. %d\n". CuentaMayusculas). I < Numero. printf("%d\t".© A. I < Numero. ++I). for (I = 1. CuentaDigitos). I < Numero. % I ? 0 : I. igual a while. El formato del bucle es el siguiente: for ( [<Inicialización>] . %d\n"..I. para eso está el while.(c = getchar()) != EOF. el for se comporta como un while. } %d\n".

I<100.I. I++) { scanf("%d". If (Numero<0) Continue.L. else .es Apuntes de clase . s[i] = s[j].. Como lo último que se hace es evaluar la condición. j--) { c = s[i]. } alozanoi@teleline. El formato del bucle es el siguiente: do <Sentencia/s> while (Condición). } Sentencia continue. &Numero). j=strlen(s)-1.. . ).Sentencia do-while.© A. else . I<100. Invierte una cadena. el control pasa a la etapa de incremento y posterior evaluación de la condición.I.. I)..h> //Librería de cadenas. For (I=0. Proporciona una salida forzada e inmediata de un bucle y de la sentencia switch.. i++. el cuerpo del bucle se realiza al menos vez. For(i=0. I++) { scanf("%d". Bucle for infinito: for( . For (I=0. D. If (Numero<0) break. En los bucles while y do-while obliga a evaluar la condición inmediatamente. } 4. i<j. Página: 64 For (I=0 . #include <string. printf("caracteres leídos %d". Programación en lenguajes estructurados. Sentencia Break. La sentencia o grupo de sentencias (entre llaves en este caso) se realizará hasta que la Condición de valor falso. en un for. s[j] = c. &Numero). Obliga a que se ejecute la siguiente iteración del bucle que la contiene.3.A.(c = getchar()) != '*'. I++) Putchar(tolower(c)).

I.L. Produce un salto incondicional a una etiqueta.I. Programación en lenguajes estructurados.© A.es Apuntes de clase . Página: 65 Sentencia goto.A. Goto <Etiqueta> Etiqueta: alozanoi@teleline. D.

.

I. Int suma(int a) { static int Contador = 0. 1.Variables locales. incluidas las funciones. 1. son externas al programa. } La variable Contador se irá incrementando en las sucesivas llamadas a la función y sólo se inicializará en la primera llamada.Variables globales.2. está visible durante toda la ejecución del programa.4. Si se definen dos variables con el mismo identificador. y todas las funciones. en su definición se le antepone la palabra reservada static.. Son variables locales o globales . es decir. use uno de los registros del microprocesador para almacenar la variable. Indica al compilador que cuando sea posible. de forma que el acceso a la misma es más rápido.1. alozanoi@teleline.L.TIPOS DE VARIABLES.A. Una variable global comienza a existir cuando empieza la ejecución del programa y desaparece cuando este finaliza. una global y otra local. Reciben el nombre de variables automáticas y pueden ser definidas como auto (sólo dentro de una función).. Son las variables declaradas dentro de una función y su ámbito se reduce a la misma. Sólo puede ser definida una vez en el programa.es Apuntes de clase .. en ningún otro.Variable estáticas.I. Página: 67 9. entendiendo este como la función main(). Esto hace que en distintas funciones pueda haber definidas variables con el mismo nombre pero todas ellas son diferentes. indica que la variable sólo es accesible en el programa fuente en el que está definida.. PUNTEROS Y FUNCIONES 1. 1. Estas variables. Programación en lenguajes estructurados.© A.. esto es. cuando se llame a la función prevalece la variable local. Comienzan a existir cuando se llama a la función y desaparecen cuando finaliza. Si se define como una variable local indica que su existencia es permanente..Tipos de variables. Contador++ .. si no que en las sucesivas llamadas a la función sigue manteniendo el valor de la llamada anterior. 1.Variables registro. por esta razón no pueden conservar su valor entre dos llamadas sucesivas a la misma función. Son variables definidas externamente a todas las funciones y por tanto tienen ámbito en todo el programa. que no aparecen y desaparecen cada vez que se ejecuta la función.3.. aunque rara vez se usa. D. Si está definida como una variable global.

D. entonces debe declararse como tal. Valor Dirección 1003 1001 1002 123 1003 1004 La posición de memoria 1001 tiene como valor la dirección de memoria 1003. El primero (&) es un operador que devuelve la dirección de memoria de su operando. por lo que es importante declarar bien el puntero. y *. Por ejemplo.1. el operador * y el nombre de la variable. La declaración de un puntero reserva memoria la necesaria para almacenar una dirección de memoria.Operadores de punteros. 2.I. entonces se dice que la primera variable apunta a la segunda. operador de indirección.. ambos unarios: &.2. m = &Cuenta. El tamaño de memoria reservado es de 32 bits el tipo far y 16 ó 32 el near según la máquina. NombreDeVariable es un puntero que apunta a un tipo de dato base definido por TipoDeDato.. que es la que contiene el dato. Una declaración de un puntero consiste en un tipo base .. Sin embargo. Un puntero es una variable que contiene una dirección de memoria. } 2.es Apuntes de clase .L. no el dato al que apunta. El tipo base del puntero define el tipo de variables a las que puede apuntar el puntero. Int suma(register int a) { register int Contador = 0. El formato general de definición de un puntero es TipoDeDato* NombreDeVariable. donde TipoDeDato es el tipo base del puntero y puede ser cualquier tipo válido de C. Programación en lenguajes estructurados. 2...A. Esa dirección es la posición de otro objeto (normalmente otra variable) en memoria. alozanoi@teleline. Página: 68 Sólo pueden definirse de tipo register las variables locales automáticas y los parámetros formales de las funciones.Variables puntero.I. cualquier tipo de puntero puede apuntar a cualquier lugar de la memoria.Teoría básica de punteros. la aritmética de punteros está hecha en relación a su tipo base. Contador++ .© A. Si una variable contiene la dirección de memoria de otra variable. la dirección de memoria 1001 apunta a la 1003. Técnicamente. 123. Hay dos operadores de punteros. operador de dirección. Si una variable va a contener un puntero (la dirección de otra variable).

antes de que tome la dirección de una variable. Un puntero no puede ser usado antes de que se haya inicializado. Declaración: int variable. Programación en lenguajes estructurados. “m” recibe la dirección de “Cuenta”. entonces q = *m. Los dos operadores tienen mayor prioridad que todos los operadores aritméticos excepto los unarios (+ y -).© A. q = *m. lo que implica que el sistema puede funcionar mal. int* puntero.es 10 0xFF00 Variable Apuntes de clase . pone el valor de “Cuenta” en “q”. Cuenta = 123.A. Valor Dirección 1003 1001(m) 123 1002(q) 123 1003(Cuenta) 1004 Esta sentencia significa que “q” recibe el valor almacenado en la dirección “m”. Siguiendo el ejemplo anterior.L. 0xAA00 Puntero Inicialización: variable = 10. m = &Cuenta. si se usa sin inicializar es posible reescribir zonas de memoria no reservadas para almacenar determinados valores. respecto de los cuales tienen igual precedencia. si “m” contiene la dirección de memoria de la variable “Cuenta”. 0xFF00 Variable 0 0xAA00 Puntero alozanoi@teleline.I. Valor Dirección 1003 1001(m) 1002 123 1003(Cuenta) 1004 El segundo operador de punteros (*) es un complemento de & que devuelve el valor de la variable localizada en la dirección que le sigue. D. Página: 69 pone en la variable “m” la dirección de memoria de la variable “Cuenta”. es decir. no el valor de la variable. m = &Cuenta. Cuenta = 123. puntero = 0.I.

1. // numero = 20. *puntero).I.A. El lenguaje C no dispone de subrutinas.Funciones. alozanoi@teleline. // numero = getchar(). Página: 70 Asignación: Puntero = &variable . 3. *puntero = numero. El formato de la declaración de una función es el siguiente: TipoDatoRetorno NombreFunción([TipoParámetro [NombreParámetro]] . numero. // Operación no deseada.© A. *puntero). Se puede eludir la declaración de la función si se realiza la definición delante de cualquier llamada a la misma. Programación en lenguajes estructurados. // *puntero = 30.).es Apuntes de clase . // *puntero = 50.I. int numero = 10.. // puntero = &numero. 10 10 20 10 20 30 20 20 40 40 50 50 Ejercicio: ¿Cuál es el resultado de evaluar dos expresiones siguientes? (*Puntero)++ *Puntero++ 3. Ejemplo: #include <stdio. numero. Si se invoca a la función sin haber sido declarada. printf("%d %d\n". el compilador no puede determinar si la llamada a la función se realiza correctamente. printf("%d %d\n".. *puntero).h> main() { int* puntero. estas se pueden comportar como cualquiera de los dos tipos de subprogramas. de esta forma. numero. La declaración o prototipo de una función consiste en describir la función antes de que sea invocada. 0xFF00 0xAA00 Puntero 10 0xFF00 Variable Después de realizar la asignación anterior disponemos de dos accesos al contenido de la variable. *puntero). *puntero). numero.. printf("%d %d\n". printf("%d %d\n".. // numero = 40. sólo de funciones. } puntero no está inicializado.Declaración de funciones. *puntero). numero.L. D. printf("%d %d\n". el compilador crea los enlaces correspondientes a la función para que esté localizado el lugar de su definición y también conoce los parámetros formales y el tipo de dato de retorno. printf("%d %d\n". uno a través de la propia variable y otro mediante el puntero usando el operador *. numero.

palabra). } El nombre de la función y los tipos de los parámetros formales de la cabecera se deben corresponder con los del prototipo. si finaliza normalmente retorna un 0 y cualquier otro valor implica algún tipo de error. el compilador asume que es un tipo de dato int. Cuando ejecutamos un programa desde el sistema operativo.es . Si no se especifica tipo dato de retorno. 3.2.I.char* argv[]): Recibe argumentos y devuelve un entero al sistema operativo. Para llamar a una función hay que poner el nombre de la función. g = contar_vocales(11.4.L.© A. dentro de una expresión o de una sentencia. En las dos últimas formas existe comunicación desde el sistema operativo hacia el programa.. Sentencias ejecutables. El formato general de la definición de una función es el siguiente: Tipo_Dato_Retorno Nombre_Función(Tipo_Parámetro Nombre_Parámetro . Los argumentos de main() significan lo siguiente: · argc: Número de parámetros que pasa el sistema operativo al programa incluido el nombre del programa. 3. char* argv[]): Recibe argumentos y no devuelve nada. Página: 71 El tipo de dato de retorno de una función puede ser declarado de tipo void. D.) { Declaración de variables locales.. void main(int argc.A. En la definición de la función es donde se escribe el código de la función: las sentencias que forman el cuerpo ejecutable de la función y que describen la acción que realiza.La función main()..3. Programación en lenguajes estructurados. seguida de los parámetros actuales.Definición de funciones..Llamada a funciones. Para poder usar una función hay que invocarla. El compilador se encarga de comprobar si los argumentos coinciden en número y tipo con los del prototipo de la función. indicando que la función no retorna nada. realmente se está haciendo una llamada a la función main(). char palabra[11] = "murciélago".I. Hay varias formas de declarar la función main(): · · · · void main(): No recibe nada ni devuelve nada. 3. int main(int argc.. Apuntes de clase alozanoi@teleline. int main() o main(): Devuelve un entero al sistema operativo.

Paso de parámetros por referencia.© A.: C:\copiar a: b: Los valores de los argumentos son: Argc = 3 Argv[0] = "copiar" Argv[1] = "a:" Argv[2] = "b:" 3. ya que se le pasa una copia. Esto significa que la función no puede modificar el valor de las variables externas a ella. Programación en lenguajes estructurados. La sentencia return no es necesaria cuando la función no retorna ningún valor (tipo void). De esta forma.I. alozanoi@teleline. Expresión es del mismo tipo que el tipo de retorno de la función. se pasa una copia temporal del parámetro.L. lo que recibe el parámetro formal es esa dirección de memoria. aunque puede usarse sin la expresión para finalizar la función (equivalente a break en un bucle).Retorno de valores.. se debe usar el paso de parámetros por referencia. no una copia de su valor.Paso de parámetros. de modo que dentro de la función puede cambiar su valor pero los cambios no tienen efecto fuera de ella. Por omisión.. Los parámetros actuales pueden ser expresiones. no necesariamente variables.6. La forma que tiene C de pasar por referencia consiste en usar los punteros. Página: 72 · argv[]: Se almacenan los argumentos pasados.es Apuntes de clase . no el valor original. Un parámetro por valor se puede entender como una variable local.6. por tanto. Return provoca la salida inmediata de la función y puede haber cualquier número de ellas en el cuerpo de la función. El lenguaje C dispone de una sentencia para devolver el valor de una función. Como en muchas ocasiones queremos que los parámetros pasados a la función cambien de valor o devolver más de un dato. Ejemplo: Llamada desde el S. su formato es: return [<Expresión>]. El paso de parámetros por referencia consiste en pasar la dirección de memoria donde está almacenado el argumento.1. 3. el parámetro actual debe ser una dirección de memoria de una variable y.A. se cambia el contenido de una dirección de memoria.I. 3..O.6. todos los parámetros de una función en C se pasan por valor. La única comunicación hacia el exterior de una función que pasa todos sus parámetros por valor es a través del tipo de dato de retorno de una función usando la sentencia return. 3. Cada vez que se cambia de valor ese parámetro en la función.. D.2. es decir.Paso de parámetro por valor.5.

. salvo los múltiplos de cien a no ser que los sean de cuatrocientos.es Apuntes de clase . se tratan igual que si fueran variables enteras. Se desea escribir la hora correspondiente al siguiente segundo.Función que calcule las raíces de la ecuación de segundo grado: ax2 + bx + c = 0 2. Un año es bisiesto cuando es múltiplo de cuatro. *a y *b. como ya se ha visto.. y).  m   = m! / (n!* (m . El tamaño del mismo se introduce por teclado. Página: 73 void Cambia(int* a. &y).. *b = aux.Combinaciones de m elementos tomados de n en n. } Los parámetros formales se declaran como punteros al tipo de dato base y.Función que visualice un rectángulo de * en pantalla. } void main() { int x = 100. no superior ni inferior a la pantalla. Ejercicios: 1. 7.. Según el ejemplo. Cambia(&x.L.© A. Consiste en sumar el día. 5.Indicar si una fecha es correcta.Calcular el número del tarot de una persona a partir de la fecha de su nacimiento. 6. 3. Programación en lenguajes estructurados. aux = *a. printf("x = %d y = %d". *a = *b. en la llamada se les asigna la dirección de los parámetros actuales. alozanoi@teleline.Función que pase un número en base diez a cualquier otra base. al llamar a la función estamos haciendo a = &x y b = &y y luego modificamos el contenido de los punteros a y b usando para ello el operador de indirección *. x.A.I.n)!)  n 4. int* b) { int aux. mes y año.Se introduce la hora del día en Horas. del resultado obtenido se suman sus dígitos y así sucesivamente hasta reducir a un sólo dígito. D. Minutos y Segundos... y = 200.I..

.

Tablas: conceptos. todos del mismo tipo y referenciados bajo un nombre común. Página: 75 10.A. Las estructuras de datos dinámicas no tienen limitaciones o restricciones en el tamaño de memoria ocupada. son los que hemos trabajado hasta el momento.Introducción a las estructuras de datos. el tamaño de la tabla se da al escribir el programa.que consta de un número fijo.I. finito y ordenado de elementos. es decir. Los tipos de datos más frecuentemente usados son: Simples Primitivos Entero Real Carácter Lógico Subrango Enumerado Tablas o Arrays Registros Ficheros Conjuntos Cadenas o String Listas Listas enlazadas Árboles Grafos Definido por el usuario Estructurados Estáticos Dinámicos Los tipos de datos primitivos son aquellos que no están compuestos por otras estructuras de datos y son los más utilizados en los diferentes lenguajes de programación. Una estructura de datos es una colección de datos que pueden ser caracterizados por su organización y las operaciones que se definen en ella.. Una tabla o array es una estructura de datos interna -se almacena en memoria principal.es Apuntes de clase .L. Programación en lenguajes estructurados. Los tipos de datos estructurados pueden ser organizados en diferentes estructuras de datos: estáticas y dinámicas...© A.I.ESTRUCTURAS DE DATOS ESTÁTICAS. Fijo: Es necesario definir su tamaño en tiempo de compilación. 1. definiciones y representación. D. 2. alozanoi@teleline. Las estructuras de datos estáticas son aquellas en las que el tamaño ocupado en memoria se define antes de que el programa se ejecute y no puede modificarse dicho tamaño durante la ejecución del mismo.

A. 3 Nombre: Componentes: Índices: Dimensión: Longitud: Tipo: alozanoi@teleline. Las tablas unidimensionales o vectores tienen una única dimensión y por tanto constan de un sólo índice. 2 Pos.L. segundo.1. igual que cualquier otro objeto del programa. su tipo. Una. Ordenado: El nombre de una tabla es un identificador común para todos sus elementos. Cada componente del vector se direcciona con el nombre de la tabla seguido del número correspondiente al índice entre corchetes. Apuntes de clase .I.. 3.© A. Tipo: Tipo de las componentes. EDAD[1]. D.I. 1 Pos. es decir. Índice: Es una expresión de tipo numérico entero (constante. EDAD[5]. distinguiéndose cada uno de ellos por una lista de índices que complementan a dicho nombre para referenciarlos. elemento de un array puede ser identificado. variable o expresión) que referencia cada componente en la tabla.Tipos de tablas. Dimensión: Número de índices necesarios para referenciar una componente de la tabla. no es así en las estructuras dinámicas. Longitud: Número de componentes que contiene la tabla. EDAD[0]. 0 Pos. EDAD[2]. Un vector se representa de la siguiente forma: EDAD 20 18 31 20 Elto 4º Elto 1º Elto 2º Elto 3º Pos. 5 EDAD. tercero. 6 Numérico entero.. indica la posición de cada componente. 3. se debe definir en su lugar correspondiente indicando su identificador. su longitud y su número de dimensiones. no pueden realizarse sobre el array en su conjunto... Definiciones: Componente: Denominación de los elementos de la tabla. .Tablas unidimensionales o vectores.es 17 Elto 5º Pos. Programación en lenguajes estructurados. Los límites del array no se comprueban en tiempo de compilación. Valores numéricos de 0 a 5 que direccionan cada componente... Las operaciones que se realicen en el array se harán sobre cada componente individualmente.. Las tablas. por tanto es posible sobrescribir datos fuera de dichos límites. Página: 76 Finito: Al ser una estructura de datos interna. Sus valores varían de 0 a Longitud . su tamaño viene limitado por la capacidad de la memoria principal o por el propio lenguaje. El primero. 4 21 Elto 6º Pos.1..

© A.I. D. Nombre_Tabla[Indice] = Expresión.1. la dirección más baja corresponde al primer elemento (dirección almacenada en el propio nombre del array) y la más alta al último. 2 2 bytes 20 Elto 4º Pos. &Edad[0]). 4 2 bytes 21 Elto 6º Pos. pero se realizarán sobre cada componente individualmente. 3 2 bytes 17 Elto 5º Pos. printf("%d". Asignación: Identificador = Nombre_Tabla[Indice].1. y las operaciones que se pueden realizar son las mismas que la usadas con cualquier otra variable.L..A. Entrada: Introducir Nombre_Tabla[Indice] Scanf("%d". alozanoi@teleline. EDAD[6] es de tipo Numérico entero. Edad[1]). 5 Formato general de definición de una tabla: TipoDeLasComponentes Identificador[LONGITUD_DIMENSIÓN].es Apuntes de clase . 1 2 bytes 31 Elto 3º Pos. 0 2 bytes 18 Elto 2º Pos. Salida: Visualizar Edad[Indice] Printf("%d".I. Identificador[LONGITUD_DIMENSIÓN] es de tipo TipoDeLasComponentes. Programación en lenguajes estructurados. Cada elemento es un dato que está almacenado en una posición dentro del vector. Página: 77 El vector se almacena en la memoria principal como un conjunto de posiciones continuas. Edad[1] = 18. Habitualmente la longitud del array se define en una directiva #define: #define TAMANHO 6 int EDAD[TAMANHO]. &Edad[1]). En el caso anterior. la memoria ocupada por la tabla EDAD es la siguiente: EDAD 2 bytes 20 Elto 1º Pos. Scanf("%d". Ejemplo: int EDAD[6].Operaciones sobre vectores. Edad[0]). Edad[0] = 20. 3.

A. printf("La media es: %f\n". i<MAXIMO.© A.Cargar el array de edades y visualizar el contenido: #include <stdio. #define ALUMNOS 30 Float TotalNotas. scanf("%d". Indice++) TRATAR Tabla[Indice]. Medias. para ello usaremos la estructura de control 'para' (bucle for).Cargar un array con las notas de los alumnos de la clase y posteriormente calcular su media. Ejemplos: 1. Programación en lenguajes estructurados. ..I.h> #define MAXIMO 5 void main() { int i. int Edad[MAXIMO]. i++) printf("Elemento %d:\n". i--) printf("Elemento %d: %d\n". i < MAXIMO. componente a componente. // Carga el vector for (i = 0. Un tratamiento secuencial de una tabla consiste en recorrerla completamente. i+1). Indice--) TRATAR Tabla[Indice]. i>=0. i < ALUMNOS. D.. y realizar las operaciones necesarias con la componente tratada en cada caso. TotalNotas / ALUMNOS). Edad[i]). El tratamiento puede realizarse en sentido creciente o decreciente: Creciente: Para Indice de 0 a TAMANHO TRATAR Tabla[Indice] Fin Para for (Indice = 0.Intercambiar el contenido de dos componentes de una tabla: alozanoi@teleline. &Edad[i]).L. } // Visualiza el contenido en sentido creciente for (i=0..1.I. // Visualiza el contenido en sentido decreciente for (i=MAXIMO . Indice < TAMANHO. debemos realizar un recorrido secuencial del mismo.1. Si queremos conocer o simplemente tratar cada una de las posiciones de un array.es Apuntes de clase . 3. Edad[i]). Indice >= 0.. Notas[ALUMNOS]. Página: 78 Recorrido secuencial de un vector.. } 2. ya que conocemos el número de componentes que contiene el vector. i++) TotalNotas += Notas[i]. // Cargar la tabla y demás definiciones de datos y sentencias for (i = 0. i++) { printf("Elemento %d: ". i. Decreciente: Para Indice de TAMANHO a 0 con incremento -1 TRATAR Tabla[Indice] Fin Para for (Indice = TAMANHO .

D. Insertar un elemento en un vector: Consiste en introducir un elemento en el interior del vector. Si se especifica la longitud.0. Hay dos formas de inicializar un array: 1. busquemos el lugar que le corresponde al nuevo elemento. Indice < MAXIMO. en los corchetes.- Inicializar el array en la propia definición del mismo.L. // Definición e inicialización de un array de longitud 7. separados por comas. debe inicializarse cuando sea necesario y en el lugar del programa oportuno con los valores que deba almacenar. = Tabla[j]. For (Indice = 0.Recorriendo secuencialmente el array y almacenando el valor de inicialización en cada componente: //Inicialización de un vector con el valor 0 Int Vector[MAXIMO]. Es necesario un desplazamiento previo para colocar el elemento nuevo en su posición relativa. Inicialización del vector: Un array. Esta posición debe ser conocida a no ser que el contenido del vector esté ordenado y.A. por tanto. pues el propio compilador cuenta el número de valores que hay entre las llaves.0.es 18 1 19 2 20 3 22 4 5 Apuntes de clase .0. Programación en lenguajes estructurados. son las siguientes: Edad[5] = Edad[4] Edad[4] = Edad[3] Edad[3] = Edad[2] El resultado es el siguiente: EDAD 17 0 alozanoi@teleline.0. Int Vector1[] = {0.0.0}. Ejemplo: Insertar la edad 19 en el array EDAD en la posición 2.0. 2. habrá que poner tantos valores como marque la misma.I. = Aux. igual que cualquier otra variable.0}. Indice++) Vector[Indice] = 0. EDAD 17 18 20 22 0 1 2 3 4 5 Las operaciones que se deben realizar desglosadas por pasos sucesivos.0.0. Página: 79 Aux Tabla[i] Tabla[j] = Tabla[i]. No es necesario indicar el número de elementos.© A.0.I.0. Int Vector2[7] = {0. y dará la longitud del vector.

3.1]. la última componente del mismo se pierde. Vector[Posicion] = Elemento. Algoritmo general de inserción: para Indice de MAXIMO . alozanoi@teleline.A.1] fin para Vector[Posicion] = Elemento for (Indice = MAXIMO .1.. tablas de distancias kilométricas entre ciudades. independientemente del identificador usado para nombrarlos. en este caso. por consiguiente. por separado. Por tanto. etc.© A.I. si no que es mejor representarlos en forma de tabla financiera o matriz: informes de ventas anuales (día/mes). Programación en lenguajes estructurados. Vector[???] = Vacío.1. Indice--) Vector[Indice] = Vector[Indice . todos del mismo tipo. una matriz como un grupo de filas. un conjunto de elementos. cuadros horarios de salidas de trenes.1 a Posición con incremento .Tablas bidimensionales o matrices. Indice >= Posición. entre corchetes. Es. D. Esta referencia a un elemento del array. el nombre de la matriz seguido. Existen grupos de datos que no se pueden representar como una secuencia de datos (vectores).L. se puede considerar como una fila de datos. en el cual el orden de los componentes es significativo y en el que se necesitan dos índices para poder identificar a cada elemento del array.es Apuntes de clase . se realiza de la misma forma que en un vector. de dos índices encerrados.1 Vector[Indice] = Vector[Indice . Indice >= Posición. Una matriz está compuesta de filas y columnas. en el ejemplo anterior el fragmento de programa es: #define MAXIMO 6 Posición = 2.1]. El array bidimensional o matriz se puede considerar como un vector de vectores. Página: 80 Debe observarse que si el vector está lleno en su totalidad.1. Elemento = 19. a no ser que este hecho impida la inserción de la nueva componente. for (Indice = MAXIMO . Indice < MAXIMO . Vector[Posicion] = Elemento.I. Borrar un elemento en un vector: for (Indice = Posición. Indice--) Vector[Indice] = Vector[Indice .2. de forma que el primer índice se corresponde con las filas y el segundo con las columnas. Si se visualiza un vector. Indice++) Vector[Indice] = Vector[Indice + 1].

Los dos índices son expresiones numéricas enteras.A. 3.2. Recorrido secuencial de una matriz. Programación en lenguajes estructurados.L. alozanoi@teleline. Página: 81 En la figura siguiente se representa una matriz. C < COLUMNAS.I. de cuatro filas y seis columnas: MATRIZ Fila 0 Fila 1 Fila 2 Fila 3 Columna 0 Columna 1 Columna 2 Columna 3 Columna 4 Columna 5 M[1][3] Una matriz. F++) For(C = 0.I. es decir. todas las columnas de esa fila. Algoritmo en seudocódigo: Para F de 1 a FILAS Para C de 1 a COLUMNAS Tratar TABLA[F][C] Fin para Fin para Fragmento de programa en C: For(F = 0. Un tratamiento secuencial de una matriz se realiza anidando dos bucles. MATRIZ. La expresión MATRIZ[1][3] accede a la componente situada en la fila 1 y columna 3 (el primer índice indica la fila y el segundo la columna). Identificador[FILAS.Operaciones sobre matrices. F < FILAS. este puede realizarse de dos formas distintas: por filas y por columnas. COLUMNAS] es de tipo TipoDeLasComponentes. D.© A. el externo se posiciona en una fila de la tabla y el interno recorre todas sus componentes.es Apuntes de clase . El número de componentes de una tabla viene dado por la expresión Número_Componentes = Número_Filas * Número_Columnas El formato general para la definición de una matriz es: TipoDeLasComponentes Identificador[LONG_FILA] [LONG_COLUMNA]. Por filas: El bucle más externo recorre las filas y el mas interno todas las componentes de la fila..1. C++) Tratar TABLA[F][C]. por tanto. necesita un valor para cada indice para poder identificar un elemento individual.

El resto de operaciones que pueden realizarse sobre los elementos de una matriz son las mismas que las que pueden realizarse con los vectores._ Inicializar el array en la propia definición del mismo.0}. igual que cualquier otra variable.0.0.es Apuntes de clase .0.0}. las filas corresponden al alumno y las columnas a los módulos.0. alozanoi@teleline. Algoritmo en seudocódigo: Para C de 1 a COLUMNAS Para F de 1 a FILAS Tratar TABLA[F][C] Fin para Fin para Fragmento de programa en C: For(C = 0.L. C < COLUMNAS.I.0.I.0.0.{0.0. For (F = 0. F++) Tratar TABLA[F][C]._ Recorriendo secuencialmente el array y almacenando el valor de inicialización en cada componente: #define FILAS 10 #define COLUMNAS 5 //Inicialización de un vector con el valor 0 Int Matriz[FILAS][COLUMNAS]. F < FILAS.0. // Definición e inicialización de un array Int Matriz1[][4] = {{0.0}}. D. 2.0. Calcular e imprimir la nota media de cada alumno y de cada asignatura.0. Inicialización de matrices Un array. C++) Matriz[F][C] = 0. Int Matriz2[2][7] = {0.0.0. F < FILAS. Ejemplo: a) Cargar una matriz de 30 filas y 3 columnas que contiene la nota de cada alumno por cada módulo del ciclo.0.0}.{0. Es necesario indicar el número de elementos de todas las dimensiones excepto de la primera para permitir que el compilador indexe el array adecuadamente. debe inicializarse cuando sea necesario y en el lugar del programa oportuno con los valores que deba almacenar.0. Página: 82 Por columnas: El bucle más externo recorre las columnas y el mas interno todas las componentes de la misma. Programación en lenguajes estructurados.0. 0. F++) For (C = 0. C < COLUMNAS.A.© A. C++) For(F = 0. Hay dos formas de inicializar un array: 1.0.

Es mágica si la suma individual de cada una de sus filas. teniendo en cuenta que la última componente pasa a ser la primera. Visualizar los resultados. Frecuencia de calificaciones.© A. Contar Random y randomize. Se introduce por teclado una secuencia de calificaciones (1. 11. de cada una de las notas. Programa que genera e imprime una matriz unitaria de orden N. Programa que carga una matriz de 5 filas y 10 columnas con números enteros y almacena los valores máximo y mínimo de cada fila en un array. 6. Programa que lee un vector de N componentes y las rota un lugar a la derecha.. 8.I. Contar los números positivos almacenados en un array. Programación en lenguajes estructurados. Programa que invierte el contenido de un vector.I. Dado un número entero positivo con un máximo de N dígitos. 14. Programa que imprime un cuadrado latino de orden N. Página: 83 b) Suponiendo que las notas son enteras y cuyo valor varía de 1 a 10. La primera fila contiene los N primeros números naturales y la siguientes N . Programa que carga una matriz cuadrada y nos dice si es mágica. columnas. Ejercicios. comprobar es capicúa usando un vector de N componentes. Cargar un vector de N componentes y dividirlo en otros dos de forma que uno contenga las componentes cuyo valor es primo y el otro con las de valor no primo. Se pide obtener e imprimir la lista de frecuencia.A. 4. Bolas de la urna. 15.10) que finaliza cuando se introduce una nota errónea. 12. 3. 13. 5.L. la más y la menos repetida. 2. Es aquella que tiene todas sus componentes a 0 excepto las de la diagonal principal que están a 1. rand y srand. 7.es Apuntes de clase . número de extracciones. 9. programa que suma las componentes de índice par y las de índice impar independientemente. srand((unsigned) time(NULL)) randomize() rand() % Rango random(Rango) 10. número de repeticiones.1 filas contienen la rotación de la fila anterior un lugar a la derecha. 1. calcular el total de alumnos para cada nota y asignatura. Programa que lee 50 número enteros sobre un vector y obtiene e imprime cuales son el mayor y el menor número almacenado y cuantas veces se repiten ambos. D. Con el vector anterior. alozanoi@teleline. Programa que calcula la matriz traspuesta de una matriz de N filas y M columnas. diagonales principal y secundaria son iguales. Cargar un vector de N componentes y obtener otro vector resultado de haber multiplicado el primero por un número dado por teclado.

Se considera que la fila anterior a la primera es la última y la columna posterior a la última es la primera. Si el número sigue a un múltiplo de N.I. Se construye mediante las siguientes reglas: · · · · El número 1 se coloca en la casilla central de la primera fila. estando distribuídos por distritos. 19. no se aplica la regla anterior.© A. En ellas se refleja el total en pesetas de las ventas producidas en el día de su fecha. C) Día y mes que se hizo la mejor caja. 17. Cada número siguiente se coloca en la casilla correspondiente a la fila anterior y columna siguiente. Se pide: A) Número de votos totales. D.es Apuntes de clase . Queremos crear una tabla (NxM) que contenga el número de votos de una serie de candidatos de unas elecciones. 18.I. Programación en lenguajes estructurados.A. Una empresa dispone de las hojas de caja diarias de un año. C) Votos de cada distrito. si no que se coloca en la casilla de la fila posterior e igual columna. Un cuadrado mágico de orden N es una matriz cuadrada que contiene los números naturales de 1 a N elevado a 2 tal que coincide la suma de los números de cualesquiera de sus filas. B) Votos de cada candidatos. Decir si dos vectores son disjuntos. Se pide realizar un programa en el que se introduzcan por teclado cada una de las cantidades y calcule: A) Capital total de ventas producidas en cada mes. D) Candidato y distrito más votados y número de votos obtenidos. columnas o diagonales principales. B) Capital total anual. Genera e imprime un cuadrado mágico de orden N (positivo e impar). Página: 84 16.L. alozanoi@teleline.

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

85

4.- Búsqueda lineal.
La búsqueda lineal en un array consiste en determinar si un valor cualquiera, X, del mismo tipo que los componentes del array, está o no almacenado en dicho array y en que posición se encuentra dentro de este.

4.1.- Búsqueda lineal en un vector no ordenado.
Se realiza un recorrido secuencial del vector, comenzando por la primera componente y finalizando cuando el valor buscado coincida con una de las componentes del array o bien, estemos situados en el final del mismo y no hayamos encontrado dicho valor. En este caso, debemos indicar la no existencia del valor buscado en el array. El algoritmo de búsqueda se puede estudiar de dos formas: A) El resultado es la primera componente que coincida con el valor buscado, aunque existan componentes repetidas. Por tanto el recorrido del vector se realiza desde el principio hasta que se encuentra el valor en el array o, en el caso más desfavorable, hasta el final del array. El algoritmo de búsqueda es el siguiente: Dado un vector, Vector, de N componentes, determinar si existe un valor igual que 'X' en el mismo.
i = 0; While (X != Vector[i] && i < N - 1) i++; if (X == Vector[i]) printf("El valor %d está en la posición %d", X, i); else printf("El valor %d no está en el vector", X);

B) El tratamiento del array es completo, desde la primera componente a la última; el resultado consiste en dar todas las posiciones del array en que se encuentra almacenado el elemento que buscamos. De la misma forma que en el caso anterior, debe determinarse si el valor buscado no se encuentra en el vector. El algoritmo de búsqueda es el siguiente: Dado un vector, Vector, de N componentes, determinar todas las ocurrencias de un valor igual que 'X' en el mismo.
i = 0; Encontrado = 0; While (i < N) { If (X == Vector[i]) { printf("El valor %d está en la posición %d", X, i); Encontrado = 1; } i++; } if (!Encontrado) printf("El valor %d no está en el vector", X);

Aunque el algoritmo se implementa con un bucle while, puede hacerse con un bucle for. Ejercicio: Generar la combinación de la lotería primitiva.

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

86

#include <stdio.h> #include <stdlib.h> #include <conio.h> #define N 8 #define RANGO 49 #define RREIN 9 int Buscar(int, int *); void Visualizar(int *); void Generar(int *); main() { int Tabla[N] = {0, 0, 0, 0, 0, 0, 0, 0}; Generar(Tabla); Visualizar(Tabla); getch(); } void Generar(int *V) { int Numeros = 0, Valor; randomize(); while (Numeros < N - 1) { do { Valor = random(RANGO) + 1; }while(Buscar(Valor, V)); V[Numeros++] = Valor; } V[N - 1] = random(RREIN) + 1; } int Buscar(int Valor, int *V) { int i = 0; while (Valor != V[i] && i < N - 1) i++; return V[i] == Valor ? 1 : 0; } void Visualizar(int *V) { int i; printf("\nCombinación :"); for(i=0; i < N -2; i++) printf(" %d\t", V[i]); printf("\nComplementario: %d", V[N - 2]); printf("\nReintegro : %d", V[N - 1]); }

4.2- Búsqueda lineal en un vector ordenado.
Como se ha visto, en la búsqueda lineal en un vector no ordenado, en el caso más desfavorable, que sería no encontrar el valor buscado en el vector, debemos recorrer todo el vector hasta la última componente para poder determinar que dicho valor no está almacenado en el vector. En el segundo caso, independientemente de que se encuentre o no el valor en el vector, debemos recorrerlo hasta el final. En un vector ordenado, el tiempo de búsqueda se reduce considerablemente, dado que no es necesario recorrer el vector hasta el final si el valor buscado no se encuentra en él. Igual que en el método anterior la búsqueda comienza en el primer elemento y se realiza de izquierda a derecha. El recorrido finaliza cuando el valor ha sido encontrado o cuando se encuentra una componente cuyo valor es mayor o menor que el buscado, según el criterio de ordenación. Los dos métodos a estudiar son los siguientes:

a) El resultado es la primera componente que coincida con el valor buscado. El algoritmo es el siguiente:
Dado un vector ordenado ascendentemente de N componentes, determinar si existe un valor X en el mismo.

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

87

I = 0; while (X > Vector[i] && i < N - 1) //En Pascal daría fuera de rango I++; if (X == Vector[i]) printf("El valor %d está en la posición %d", X, i); else printf("El valor %d no está en el vector", X);

b) Es igual que el anterior pero damos todas la posición que ocupan todas las componentes iguales a X.
i = 0; Encontrado = FALSO; // Esta expresión en otro lenguaje de programación puede dar un error de fuera de rango. While (i < N && X >= Vector[i]) { If (X == Vector[i]) { printf("El valor %d está en la posición %d", X, i); Encontrado = CIERTO; } i++; } if (!Encontrado) printf("El valor %d no está en el vector", X);

4.3.- Búsqueda lineal en una matriz.
Igual que en el recorrido secuencial de una matriz anidábamos dos bucles, en la búsqueda también debemos hacerlo. Las técnicas que debemos aplicar son idénticas a las usadas para los vectores. Dada una matriz de M filas y N columnas y un valor X a buscar:
F = 0; while (X != Matriz[F][C] && F < FILAS - 1) { C = 0; While (X != Matriz[F][C] && C < COLUMNAS - 1) C++; If (X != Matriz[F][C]) F++; } if (X == Matriz[F][C]) printf("El valor %d está en la posición %d, %d", X, F, C); else printf("El valor %d no está en la matriz", X);

5.- Búsqueda binaria o dicotómica en un vector.
Ejercicio: piensa un número y haz un programa para que el ordenador lo adivine en el menor número de intentos posibles. Cada vez que el ordenador te proporcione un valor, debes indicarle si es menor, mayor o igual al que pensaste. Igual que la búsqueda lineal, la búsqueda binaria determina si un valor se encuentra almacenado o no en un array. La búsqueda binaria sólo puede aplicarse a vectores cuyos elementos están ordenados. Si existen valores repetidos en el vector, la componente devuelta es una de ellas aleatoriamente. Los pasos del algoritmo son los siguientes: 1. Comparamos el valor buscado con la componente central del vector. 2. Si no son iguales se reduce el intervalo de búsqueda a la mitad derecha o a la mitad izquierda, dependiendo de donde pueda encontrarse el valor buscado. 3. Se repiten los pasos 1 y 2 hasta que se encuentre el elemento buscado o se anule el ámbito de búsqueda.
alozanoi@teleline.es Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página:

88

int LimiteInferior = 0; int LimiteSuperior = ELTOS - 1; int ComponenteCentral = LimiteSuperior / 2; while (Valor != V[ComponenteCentral] && LimiteInferior < LimiteSuperior) { if (Valor > V[ComponenteCentral]) LimiteInferior = ComponenteCentral + 1; else LimiteSuperior = ComponenteCentral - 1; ComponenteCentral = (LimiteInferior + LimiteSuperior) / 2; } if (Valor == V[ComponenteCentral]) ComponenteCentral; else Indicar que no está;

6.- Ordenación de tablas.
Se puede definir una ordenación como la reagrupación de un conjunto de elementos en una secuencia específica. Los tipos de ordenación son los siguientes: ascendente o creciente y descendente o decreciente.

6.1.- Ordenación por inserción directa.
El método de ordenación por inserción directa o método de la baraja, consiste en repetir el siguiente proceso desde la segunda componente hasta la última: se toma dicha componente y se inserta en el lugar que le corresponda entre las componentes situadas a su izquierda (estas ya estarán ordenadas). Las componentes superiores a la tratada se desplazarán un lugar a la derecha. Ejemplo de evolución de la secuencia: Secuencia inicial: Primer paso: Segundo paso: Tercer paso: Cuarto paso: Algoritmo:
void InsercionDirecta(int *V) { int i, j, Auxiliar; for (i = 1; i < ELTOS; i++) { Auxiliar = V[i]; j = i - 1; while (V[j] > Auxiliar && j > 0) { V[j + 1] = V[j]; j--; } if (V[j] > Auxiliar) { V[j + 1] = V[j]; V[j] = Auxiliar; } else V[j + 1] = Auxiliar; } }

3 2 2 1 1

2 3 3 2 2

4 4 4 3 2

1 1 1 4 3

2 2 2 2 4

alozanoi@teleline.es

Apuntes de clase

alozanoi@teleline. j++) if (V[j] < Auxiliar) { k = j.es Apuntes de clase . Programación en lenguajes estructurados.I.. j < ELTOS. Auxiliar = V[i]. Auxiliar. k. void SeleccionDirecta(int *V) { int i. Auxiliar = V[k]. k. i++) { k = i.2. V[i] = Auxiliar. Auxiliar = V[j]. i < ELTOS .I. j++) if (V[j] < V[k]) k = j.. Auxiliar. } V[k] = V[i].Ordenación por selección directa.L. for (j = i + 1. for (j = i + 1.© A.1. se usa el índice sólo para marcar la posición pero no se almacena su valor en una variable temporal dado que está almacenado en el vector en dicho lugar. El método consiste en repetir el siguiente proceso desde la primera componente hasta la penúltima: se selecciona la componente de menor valor de las situadas a la derecha de la componente tratada y se intercambia con esta. } } 6. Página: 89 6. i < ELTOS . V[i] = Auxiliar. V[k] = V[i]. El método consiste en recorrer sucesivamente el vector comparando los elementos consecutivos e intercambiándolos cuando estén desordenados. i++) { k = i. } } Otro algoritmo. for (i = 0.3. j. semejante al anterior pero realizando el intercambio al finalizar la búsqueda. for (i = 0.1. j < ELTOS. El método de la burbuja tiene dos versiones: Recorrido de izquierda a derecha: consiste en colocar en cada pasada el elemento mayor de los tratados en la última posición quedando colocado y por lo tanto excluido de los elementos a tratar en la siguiente pasada al vector.Ordenación por intercambio directo o método de la burbuja. j. D.A. Ejemplo de evolución de la secuencia: Secuencia inicial: Primer paso: Segundo paso: Tercer paso: Cuarto paso: 3 1 1 1 1 2 2 2 2 2 4 4 4 2 2 1 3 3 3 3 2 2 2 4 4 void SeleccionDirecta(int *V) { int i.

Mezcla de vectores. el tamaño del array resultante es. Página: 90 Ejemplo de evolución de la secuencia: Secuencia inicial: Primer paso: Segundo paso: Tercer paso: Cuarto paso: 3 2 2 1 1 2 3 1 2 2 4 1 2 2 2 1 2 3 3 3 2 4 4 4 4 void BurbujaID(int *V) { int i. i++) for (j = ELTOS . se obtenga un tercer array ordenado. Programación en lenguajes estructurados.1] = V[j].1] > V[j]) { Auxiliar = V[j . j--) if (V[j . TABLA3.. i >= 0.A. El proceso es el siguiente: alozanoi@teleline. Auxiliar. Auxiliar. Suponiendo que el tamaño de los arrays iniciales es LON1 y LON2 respectivamente. La operación de mezcla de dos arrays unidimensionales consiste en que dados dos vectores ordenados. esta forma no usa la ventaja de la ordenación previa de los arrays originales. D. j++) if (V[j] > V[j + 1]) { Auxiliar = V[j]. V[j] = V[j + 1]. TABLA1 y TABLA2. j. que contenga los valores de los dos primeros arrays. } } 7. j >= i. V[j + 1] = Auxiliar. j <= i. Sin embargo. i < ELTOS.I. V[j] = Auxiliar. for (i = ELTOS .© A.1]. j. La forma más sencilla de obtener resultados consiste en copiar TABLA1 y TABLA2 en TABLA3 y ordenar esta por cualquier método de ordenación.1. for (i = 1. } } Recorrido de derecha a izquierda: esta versión es igual que la anterior pero desplazando los elementos menores a la izquierda. LON1 + LON2. V[j . Ejemplo de evolución de la secuencia: Secuencia inicial: Primer paso: Segundo paso: Tercer paso: Cuarto paso: 3 1 1 1 1 2 3 2 2 2 4 2 3 2 2 1 4 2 3 3 2 2 4 4 4 void BurbujaDI(int *V) { int i.2.I.L. i--) for (j = 0. por tanto.es Apuntes de clase .

Indice1 < ELTOS. · · El algoritmo de mezcla es el siguiente: void Mezcla(int *V1. Indice2++) { V3[Indice3] = V2[Indice2]. Indice1++) { V3[Indice3] = V1[Indice1]. } } Usando mejor el lenguaje C: void Mezcla(int *V1. D.es Apuntes de clase . El más pequeño se coloca en la posición dos de TABLA3. } Ejercicios : 1. Indice2 = 0. } for (Indice2. Indice2 < ELTO2. Llegará un momento en que se hayan pasado todos los elementos de un array a TABLA3. while (Indice2 < ELTO2) V3[Indice3++] = V2[Indice2++]. Dichos elementos se pasarán directamente a TABLA3. quedando solamente elementos del otro array. int *V2. int *V2.L. Indice3 = 0. Si no hay números negativos. Indice3++. Programación en lenguajes estructurados. } Indice3++. Programa que lee una secuencia de 50 números cargándolos en un vector y a continuación encuentra la posición que ocupa el primer número negativo en caso de existir. while (Indice1 < ELTOS && Indice2 < ELTO2) { if (V1[Indice1] < V2[Indice2]) V3[Indice3++] = V1[Indice1++]. Indice1++. introducido por teclado. se encuentra o no dentro del vector. y así sucesivamente.I. } while (Indice1 < ELTOS) V3[Indice3++] = V1[Indice1++]. int *V3) { int Indice1 = 0. 2. Indice2++. Programa que carga 100 nombres en un vector y a continuación permite consultas sucesivas para ver si un nombre. escribirá un mensaje indicándolo. int *V3) { int Indice1 = 0. else V3[Indice3++] = V2[Indice2++]. Se compara el elemento situado en la posición dos del array. con el primero del otro array. Indice3 = 0. Indice2 = 0. } for (Indice1. alozanoi@teleline.I. } else { V3[Indice3] = V2[Indice2]. while (Indice1 < ELTOS && Indice2 < ELTO2) { if (V1[Indice1] < V2[Indice2]) { V3[Indice3] = V1[Indice1]. del cual se pasó el elemento a TABLA3.A.© A. Página: 91 · Se comparan los elementos situados en la primera posición de TABLA1 y TABLA2 y el menor se coloca en la primera posición de TABLA3. Indice3++.

usar el método de búsqueda binaria. Programa que clasifica simultáneamente dos vectores numéricos de igual dimensión. Realizar un programa que permita consultas sucesivas de teléfonos para nombres introducidos por teclado. de N componentes cada uno. A continuación permite consultas sucesivas de edades para nombres introducidos por teclado. Suponiendo que el vector de nombres está ordenado ascendentemente. 5. 14. una matriz de 2*N. Programa que realiza una ordenación de un vector imprimiendo todos los estados intermedios del mismo. Igual que el ejercicio anterior. 13. El resultado es otro vector V3 ordenado. Programa que carga dos vectores. 6. imprime la lista ordenada de nombres y teléfonos. los ordena ascendentemente y realiza una mezcla de los dos. Dado un vector numérico de 100 componentes. 11. Programación en lenguajes estructurados. el primero almacena nombres de personas y el segundo sus números de teléfono. Programa que realiza la clasificación completa de una matriz numérica en orden creciente (de izquierda a derecha y de arriba a abajo). 15. el primero en orden creciente y el segundo en orden decreciente. Página: 92 3. En lugar de dos vectores. finalmente. alozanoi@teleline.© A. con primer apellido.A. Programa que carga una matriz alfanumérica de 80*2 conteniendo en cada un nombre de persona y su número de teléfono. V1 y V2. D. 10. 4. 7. 9.I. 12. Programa que clasifica simultáneamente en orden creciente sus componentes pares y en orden decreciente las impares. 8. almacenando en el primero una lista de nombres de personas y en el segundo las edades correspondientes a cada una de ellas. Programa que carga un vector numérico de 100 componentes y obtiene e imprime los 10 valores menores y los 10 mayores. Programa que carga una matriz de 100 filas y 3 columnas. A continuación realiza una clasificación ascendente por orden alfabético de nombres y. realizando una clasificación alfabética completa e imprimiendo la lista de nombres clasificada. Programa que genere la combinación de la lotería primitiva. Permitir consultas sucesivas de los teléfonos correspondientes a nombres introducidos por teclado por el método de búsqueda binaria en la tabla ordenada del ejercicio anterior. Programa que carga dos vectores de 35 componentes cada uno.I.es Apuntes de clase . segundo apellido y nombre de 100 personas. Cargar dos vectores de N componentes cada uno.L.

también se puede realizar mediante punteros.USO DE PUNTEROS COMO ARRAYS. p_array . x = *p_array. Si declaramos un puntero a un entero como int *p_array. entonces podemos asignar la dirección del primer elemento del array a ese puntero p_array = &array[0] o bien. 1. el nombre del array es un puntero a la primera componente del mismo. Programación en lenguajes estructurados.. entonces por definición p_array + 1 apunta al siguiente elemento.A. que la indexación.Arrays unidimensionales y punteros. 1 2 3 4 5 copiarán el contenido de array[0] en la variable x y array[0] tomará el valor de la variable y respectivamente. cualquier operación que se pueda realizar con indexación.1]. dado que el nombre del array es un puntero a la primera componente del mismo. *p_array = y.I.© A. en términos generales. y = 10. siendo este método más rápido. En el lenguaje C existe una estrecha relación entre punteros y arrays. p_array Dirección array ---------> 0 Ahora. D. array[2]. array[LONGITUD . Si el puntero p_array apunta al primer elemento de array. En general. de hecho. .. Por tanto.. array[1]. La declaración #define LONGITUD 20 int array[LONGITUD]. La notación array[i] significa que el elemento del array se encuentra a i posiciones del comienzo del mismo..i apunta a i elementos delante de p_array y p_array + i apunta a i elementos detrás de p_array..I.es Apuntes de clase . podemos hacer la asignación p_array = array que es equivalente a la asignación anterior. asignaciones como int x. alozanoi@teleline. Página: 93 11. La expresión x = *(p_array + 1) . define un array de LONGITUD componentes consecutivas de tipo entero (el compilador reserva la memoria necesaria para poder almacenar todos los datos) denominados array[0].L.

printf("%d\t". array[1] *(array + i).h> #include <conio. y como tal. No necesita paréntesis. este retorna el número de bytes de memoria usados por dicho objeto. p_array[0] *(p_array + 1). Página: 94 da el contenido del segundo elemento de array a x. En definitiva. estamos realizando un salto a la siguiente componente del array. p_array = array. array[i] Contenido de la primera componente Contenido de la segunda componente Contenido de la componente i . también son válidos los acceso al array de la siguiente manera: . // 40 4 Depende de la longitud de los enteros de la máquina Como el compilador convierte toda referencia a un array en un puntero al comienzo del mismo. sizeof(array). i<LONGITUD.© A. sizeof(i)). // // // getch(). p_array[i] &array[i]. Cuando incrementamos en una unidad el puntero al array (p_array + 1).I. sumar o restar enteros a punteros y compara punteros. int *p_array. p_array[1] *(p_array + i). Hay que asignarla de nuevo para comenzar. Cuidado en las funciones y bucles anidados. Es posible restar punteros. Esta operación no puede realizarse sobre una variable de tipo array puesto que este es un puntero constante. D. no estamos accediendo a la siguiente posición de memoria. ahora su valor cambia a FF + 1). incremento o decremento en enteros. del valor del puntero es independiente del tipo de dato de las componentes del array.Trabajando con puntero a entero *p_array. } i++) *(p_array++)).Trabajando con la definición del array *array. Asociatividad de derecha a izquierda Se pierde la dirección. calculado por el tamaño de los datos almacenados en las componentes.L.h> #include <stdlib. NOTA IMPORTANTE: p_array++ modifica el contenido de la variable puntero (si su valor era FF. &p_array[i] Contenido de la primera componente Contenido de la segunda componente Contenido de la componente i alozanoi@teleline. #include <stdio.A. // Toma la dirección de array // Carga el vector con números aleatorios for (i=0. Esta modificación. i<LONGITUD. siempre que modifiquemos un puntero el incremento o decremento se adecua al tamaño en memoria del objeto apuntado. no puede modificarse.I. El tamaño de un objeto se conoce mediante el operador sizeof(). array[0] *(array + 1). for (i=0.es Apuntes de clase . int i. Programación en lenguajes estructurados.h> #define LONGITUD 10 main() { int array[LONGITUD]. printf("\n%d %d". array + i p_array + i. i++) *(p_array + i) = random(1000).

int notas[ELTOS] = {0. la longitud del dato al que apunta cada componente del array de punteros es irrelevante. La declaración de una variable de tipo puntero no lleva implícita la asignación o reserva de memoria por el compilador con lo que no puede usarse mientras no se realice una asignación a una zona de memoria.I. p_array[0] = &dato. array1 = array2.6.7. p_array[1][i]). no pudiendo modificar su valor ( no podemos hacer array++. La definición de un array de punteros es la siguiente: tipo_dato *identificador[LONGITUD].Arrays bidimensionales y punteros. en cada uno de sus elementos podemos almacenar la dirección de otra variable.1. for (i=ELTOS/2. int dato = 20.A. con todo puntero que apunta a un array puede usarse la indexación de elementos y con todo array pueden usarse los punteros para acceder a las componentes.2. tal como la dirección de una variable de tipo int (dato) o la dirección de un vector de enteros (notas). La declaración int **puntero_puntero. } p_array dato ---> 20 ---> 0 Notas 1 2 3 4 5 6 7 8 9 Se puede ver como una posición de un array de punteros referencia a una variable.5. i<ELTOS/2. que apunta a otra var. main() { int *p_array[LONGITUD]. que hay que definir como los demás objetos del programa.4. ptr. D. Esto se denomina doble indirección. i<ELTOS.L. existen diferencias entre el nombre de un array y un puntero a un array: · · Un puntero es una variable. //Crea una var. Página: 95 Como se ve. array1 = &array2. indica que se está declarando una variable puntero que almacena la dirección de otro puntero a un entero. mediante la petición directa de memoria. *p_array[0]). p_array[1] = notas. por lo que se puede modificar su valor con operaciones como p_array++ o --p_array mientras que el nombre de un array es una constante. printf("%d\n".I.© A. i++) printf("%d\t". ptr. *(p_array[1] + i)). En definitiva. Esta asignación de memoria se realiza como se ha visto antes (p_array = array o p_array = &array[0]) o bien.. //Crea un array de punteros La siguiente definición declara un array de LONGITUD punteros a enteros.3. alozanoi@teleline.9}.es Apuntes de clase . i. Los arrays bidimensionales necesitan dos índices para poder referenciar los elementos que contienen por lo que no pueden equivaler a un único puntero si no a un array de punteros. i++) printf("%d\t". Programación en lenguajes estructurados. 2. La cuestión es que pasaría si cada elemento de un array apuntara a la dirección de otro puntero.8. Sin embargo. for (i=0. son sentencias ilegales).

p_array F C A Vectores de enteros F+sizeof C+sizeof ----------> ----------> ----------> F C F+sizeof*2 C+sizeof*2 F+sizeof*3 Esquema de un array de punteros a vectores. Si reserva espacio para el array de vectores. // En Variable se almacena un 9 Desde este punto de vista.I. un array multidimensional se puede expresar como un array de punteros. p= &Variable .© A. El compilador no reserva memoria y por tanto necesita una inicialización explícita para obtenerla. // q toma la dirección de p (que tiene la de Variable) **q= 9 . int *p.A. Página: 96 Puntero dirección -------------------> Indirección simple Variable Valor Puntero dirección -------------------> Indirección múltiple Puntero dirección -------------------> Variable Valor int Variable . **q . Programación en lenguajes estructurados. Por tanto un array bidimensional se puede definir como un array unidimensional de punteros de la forma: tipo_dato *identificador[LONGITUD]. en lugar de la definición convencional: tipo_dato identificador[FILAS][COLUMNAS].I. D. Las filas a las que apunta cada puntero pueden ser de diferentes longitudes.1). Usar un array de punteros para definir un array multidimensional presenta ventajas e inconvenientes frente al uso de la definición convencional: · · · · Utiliza más memoria. NOTA:Los contenidos de las celdas no son reales a excepción de los de p_array que si almacenan una dirección. el resto.L. Cada puntero indica el comienzo de un array con un tamaño (N . alozanoi@teleline. no el dato almacenado. // p toma la dirección de Variable q= &p .es Apuntes de clase . array FF FF + sizeof()*4 FF + sizeof() FF + sizeof()*2 FF + sizeof()*3 Esquema de un array convencional. sólo representan la dirección de memoria que ocupan. El acceso a los elementos es más rápido usando la indirección.

Dirección del elemento [i][j]. for (i=0. i<FILAS.es Apuntes de clase .L. j<COLUMNAS. *(*array + 4) *(*array + 7] *array + 9 array + i array[1][0] array[1][3] &array[2][1] array[i] Valor del elemento [1][0] Valor del elemento [1][3] Direcc. i<FILAS. } También. j<COLUMNAS. para acceder a un elemento del array se puede aplicar la expresión: índice_fila * COLUMNAS + índice_columna Así el elemento [1][3] del array anterior. i++) for (j=0. Dirección de la fila [i]. i++) for (j=0.*(*(p_array + i) + j)). for (j=0. del elemento [2][1]. Página: 97 Expresiones propias de arrays de punteros. Dirección de la fila i En general.© A. D. Valor del elemento [i][j].A. j++) *(p_array[i] + j) = random(100). se puede expresar como 1 * COLUMNAS(4 elementos) + 3 = 7 (Octavo elemento de la tabla) Lo anterior sólo es válido para arrays bidimensionales definidos con sus longitudes dado que todas las componentes se almacenan en posiciones consecutivas de memoria reservadas por el alozanoi@teleline. i++) p_array[i] = (int *) malloc(COLUMNAS * sizeof(int)). j++) *(p_array[i] + j) *= CONSTANTE. i<FILAS.I. j++) printf("%d\t". i<FILAS. } for (i=0. i++) { printf("\n"). } getch(). j. que también pueden usarse con arrays bidimensionales normales. i<FILAS. i++) { printf("\n"). j<COLUMNAS. son las siguientes: p_array[i] + j *(p_array + i) p_array[i] + j *(p_array[i] + j) *(*(p_array + i) + j) main() { int *p_array[FILAS]. j<COLUMNAS. for (i=0.I. j++) printf("%d\t". for (i=0.*(p_array[i] + j)). Programación en lenguajes estructurados. for (j=0. a un array multidimensional definido de forma convencional. for (i=0. se puede acceder a sus elementos mediante punteros sin usar la indexación: int array[3][4]. &array[i][j] Array[i] *(array + i) + j array[i][j] Array[i][j] Dirección del elemento [i][j]. int i. Valor del elemento [i][j].

h> #include <stdlib.h> #define LONGITUD 10 main() { int *p_array. puntero = void (tipo *) malloc(Tamaño_Total_Necesario).A. El tamaño de memoria se calcula con el operador sizeof(nombre_tipo) y si no hay memoria disponible retorna el puntero NULL. *array + i*COLUMNAS+j). Programación en lenguajes estructurados. if (p_array == NULL) { puts("Sin memoria").h> puntero = void (tipo *) calloc(Numero_Elementos. } getch(). i++) printf("%d\t". con la función free() para un uso posterior. for (j=0. array[i][j].es Apuntes de clase . sizeof(int)). // Reserva memoria para LONGITUD elementos de tipo int. no de compilación.L. free(p_array). for (i=0. for (i=0. Página: 98 compilador en tiempo de compilación. main() { int array[FILAS][COLUMNAS].I. #include <stdio. //stdlib. i++) *(p_array + i) = random(1000). i<LONGITUD. Array de dos dimensiones creado dinámicamente.. i++) for (j=0. i<FILAS. En C y otros lenguajes de programación se puede asignar y liberar memoria dinámicamente. i. en lenguaje C las funciones usadas para tal propósito son calloc(). devolvérsela al sistema. La sintaxis de estas funciones es la siguiente: #include <stdlib. malloc() y free(). } Una vez que no se necesita la memoria reservada con las funciones calloc() y/o malloc() hay que liberarla. j<COLUMNAS.© A. no es válido para un array de punteros a vectores puesto que cada vector se almacenará en posiciones de memoria no necesariamente consecutivas asignadas en tiempo de ejecución.Reserva de memoria. for (i=0. exit(0). i<LONGITUD. } 3. p_array = (int *) calloc(LONGITUD. void free(puntero). Tamaño_Elemento). int i. j.h> alozanoi@teleline. D. i++) { puts("\n").I.h } for (i=0. p_array[i]). Es necesario reservar memoria para los punteros antes de hacer uso de ellos. i<FILAS. j<COLUMNAS. j++) *(*array + i*COLUMNAS+j) = i+3. #include <stdio. j++) printf("V:%d\tD:%d\t".

free(p_p_array). q++) } printf("%d". La forma habitual de pasar vectores a funciones es la última. *(*(p_p_array+i)+j)). j. i++) { *(p_p_array + i) = (int *) malloc(COLUMNAS*sizeof(int)). i<ELEMENTOS. for (i=0. i++) free(*(p_p_array + i)). printf("Vector de punteros: &p_p_array[0]= %d\n". for (j=0. for (i=0. i<FILAS. D. } } getch(). q<v+ELEMENTOS. for (j=0. ya que el compilador no comprueba los límites de un array.h> #define FILAS 3 #define COLUMNAS 2 main() { int **p_p_array. i<FILAS. Cuando se pasa un array a una función.j. j<COLUMNAS. j++) { printf("Componente: *(p_p_array +%d)+%d=%d\t".h> #include <conio. se está realizando una transferencia por variable o referencia.Paso de parámetros array a funciones. Página: 99 #include <stdlib. i<ELEMENTOS. facilitar la lectura. *q).es Apuntes de clase . i++) for (i=0. alozanoi@teleline. p_p_array). el parámetro actual es el propio nombre del array.1. *q). En cualquier caso.L. Tipo identificador(tipo *vector)..i. j++) *(*(p_p_array + i) + j) = rand() % 100. 4. i++) { puts("\n"). } 4. i.*q. for (i=0. printf("%d". i++) for (i=0. que es la dirección del mismo. El hecho de especificar la longitud no tiene más interés que el meramente simbólico. j<COLUMNAS. i++. printf("%d". void visualizar(int *v) { int i.*(p_p_array+i)+j). printf("%d".A. int i..Arrays unidimensionales. *(p_p_array + i)). printf("Fila: *(p_p_array + %d)= %d\n". realmente se está indicando al compilador que va a recibir un puntero.© A. p_p_array = (int **) malloc(FILAS*sizeof(int*)). for (i=0.I. &p_p_array[0]). Independientemente del encabezamiento empleado. v[i]). Longitud fija: El encabezamiento de una función con un vector como parámetro formal puede ser de tres formas diferentes: Tipo identificador(tipo vector[LONGITUD]). } printf("Puntero: p_p_array= %d\n". i<ELEMENTOS. i<FILAS. Programación en lenguajes estructurados. q++) for (q=v. en el cuerpo de la función se puede usar el método de indexación o aritmética de punteros para acceder a los elementos del array. printf("Valor: *(*(p_p_array + i) + j)= %d\n". q=v. Tipo identificador(tipo vector[]).I. *(v+i)).

no desde 0. Página: 100 main() { int vector[ELEMENTOS]={1. } void visualizar(int tabla[][COLUMNAS]. var = funcion(matriz).1. int array[FILAS][COLUMNAS].1] = elemento. int posicion) { for (i=longitud . longitud++. for (i=0. Para solventar esta dependencia. 4. visualizar(array.3. int insertar(int *tabla. la segunda dimensión de la misma. int f) { int i. for (i=0. int). i>=posicion . Cuando pasamos una matriz a una función. por lo menos. * longitud: elementos actuales. *(*(tabla + i) + j)). Indicar si el contenido de un vector es capicúa.L. i<f.© A. return longitud. visualizar(vector). int f) { int i.A. i--) tabla[i + 1] = tabla[i]. FILAS).. int longitud. sólo hay que pasar a la función un parámetro más: la longitud del array. } void cargar(int tabla[][COLUMNAS]. i<f. int elemento. puts("\n"). j<COLUMNAS. Longitud fija: Son necesarios dos índices para referenciar un elemento de una matriz. main() { void cargar(int [][COLUMNAS]. Función que inserta un elemento en una posición del array: * posición: contando desde 1.1.5. j<COLUMNAS. Prototipo: Definición: Llamada: tipo funcion(tipo array[][COLUMNAS]). i++) for (j=0. cargar(array.2. i++) for (j=0. tipo matriz[F][C].6}.4. Programación en lenguajes estructurados. j. } Ejercicios: Indicar si dos vectores disjuntos. void visualizar(int [][COLUMNAS]. } alozanoi@teleline.I. tabla[posicion . no puede contentarse con el puntero al comienzo del primer elemento. j++) printf("Valor= %d\n".es Apuntes de clase . las funciones no son independientes. j++) tabla[i][j] = rand() % 100. dependen de la constante simbólica definida anteriormente (excepto las cadenas.I. int). D. } Genéricos: Visto del modo anterior. no totales.Arrays bidimensionales. j. que acaban con el nulo). FILAS). el compilador necesita conocer.2.

i<f. int f. tabla = (int **) malloc(f*sizeof(int*)). int f. FILAS. i. Sólo si definido como **matriz. cargar(&array[0][0]. FILAS. } int **reservar_memoria(int f. for (i=0. } void cargar(int *tabla. i<f. int c) // Si definido **matriz { int **tabla. reservar_memoria(p_array. int). COLUMNAS). FILAS. int. j. FILAS. &array[0]).© A. j++) printf("Valor= %d\n". COLUMNAS). FILAS.I. int). int array[FILAS][COLUMNAS]. int).L. i++) free(*(p_array + i)). i<FILAS. COLUMNAS). for (i=0. i. int. for (i=0.I. c). filas. for (i=0. i++) for (j=0. j++) *(tabla + i * COLUMNAS + j) = rand() % 100. // free(p_array). j<c. Página: 101 Longitud variable con un puntero: Prototipo: Definición: Llamada: tipo funcion(tipo *array. *(tabla + i * c + j)). int filas. } void reservar_memoria(int *tabla[]. //Con error warning. visualizar(&array[0][0]. } alozanoi@teleline. i++) for (j=0. int c)//Si definido *matriz[] { int i. COLUMNAS). var = funcion(matriz.es Apuntes de clase . int *p_array[FILAS]. columnas). i<f. array). COLUMNAS). int c) { int i. D. i++) *(tabla + i) = (int *) malloc(c*sizeof(int)). tipo *matriz[]. printf("Puntero: array= %d\n". void cargar(int **. j. f. int. j<c. void visualizar(int *[]. for (i=0. Programación en lenguajes estructurados. printf("Vector de punteros: &array[0]= %d\n". tipo matriz[F][C]. En el cuerpo de la función sólo podemos usar un índice dadas las características del parámetro formal: puntero a entero. i<f. var = funcion(&matriz[0][0]. } Longitud variable con reserva explícita de memoria: Prototipo: Definición: Llamada: tipo funcion(tipo **array. return tabla. int f. void visualizar(int *. int. cargar(p_array. int. int filas. visualizar(p_array. int c) { int i. i++) *(tabla + i) = (int *) malloc(c*sizeof(int)). tipo **matriz.A. var = funcion(matriz. c). } void visualizar(int *tabla. f. int). int columnas). int). int columnas). main() { void reservar_memoria(int **. main() { void cargar(int *.

int f. int f. int c) { int i.A. } void visualizar(int *tabla[].I.L. i<f. j<c. for (i=0.es Apuntes de clase . j. j++) *(*(tabla + i) + j) = rand() % 100. Programación en lenguajes estructurados. } El primer array es de punteros. Página: 102 void cargar(int **tabla. j<c.© A. *(*(tabla + i) + j)). for (i=0. j. i++) for (j=0. hay que reservar memoria para el tamaño del puntero. j++) printf("%d\t". D. alozanoi@teleline. i++) for (j=0. i<f.I. int c) { int i.

© A. \0 N-1 Además.A.. #include <stdio. Esto significa que una cadena de N caracteres de longitud consta de N-1 caracteres (la cadena propiamente dicha) más el carácter nulo.. cadena = "Cadena constante". cuando escribimos una cadena constante ("El hotel de los líos"). aunque el nombre de un array es un puntero al mismo. Página: 103 12..Representación de las cadenas.I. sin embargo. Programación en lenguajes estructurados.I. porque cadena es un puntero y "Cadena constante" ha sido traducido por el compilador a un puntero a la memoria donde se almacena. El medio para almacenar esta información es un array de caracteres. Existe una convención de representación de las cadenas: · · por parte del compilador. //Se asigna un puntero a char while (*cadena) printf("%c".. este es constante y no se puede modificar.CADENAS DE CARACTERES.. copia. 1.es Apuntes de clase . De hecho. para representar las cadenas constantes (escritas entre comillas). . 8 . en su representación interna. alozanoi@teleline.Introducción En lenguaje C no existe ningún tipo de dato para definir variables de tipo cadena. de esta forma es posible conocer el final del array sin necesidad de conocer su tamaño. . por un cierto número de funciones. D. 2. el compilador traduce esta notación de cadena constante en un puntero (a char) a la zona de memoria correspondiente. la siguiente asignación no es válida porque. } Es posible realizar la asignación anterior cadena = "Cadena constante". Una cadena de caracteres se representa por una serie de bytes correspondientes a cada uno de sus caracteres o código ASCII que finaliza con carácter nulo('\0'). que permiten realizar: · lecturas o escrituras de cadenas. · tratamientos como concatenación. *cadena++).h> main() { char *cadena.L. comparación. cadena E 0 l 1 2 h 3 o 4 t 5 e 6 l 7 . el compilador añade al final el carácter nulo. //Puntero a char cadena = "Cadena constante". #define LONGITUD 10 char cadena[LONGITUD + 1]. char cadena[LONGITUD + 1].

es necesario reservar la memoria suficiente para almacenar los datos. "Sab". ' '. char *cad3[7]={"Lunes". char *cad4[]={"Lunes". ver34(cad3). char cadena[] = " Una cadena. queremos usar una de las funciones de entrada de datos por teclado o copiar el contenido de otra variable. no se reserva memoria. el compilador añade el carácter nulo al final de la cadena. "Mie". En la inicialización convencional hay que añadir el carácter nulo al final: char cadena[10]={'E'. "Miercoles". En cualquiera de las dos inicializaciones anteriores. '\0'} Además de la inicialización anterior. i++) puts(*(cadena + i)). for (i=0. "Jueves". '. "Jueves". printf("\n"). En todos los ejemplos se supone que hay memoria reservada para las cadenas usadas. 'h'. cadena++.". } void ver12(char cadena[][4]) { int i. 'l'.". i<7. "Mar". "Jue". // Contar los caracteres. "Vie". ver12(cad1). También se pueden inicializar arrays con varias cadenas: #include <stdio. "Mie". main() { char cad1[7][4]={"Lun". "Sab". "Miercoles". La inicialización de una cadena es semejante a la inicialización de un array. char *cadena = " Una cadena.. "Dom"}.h> void ver34(char **).Ejemplos de funciones con cadenas. } alozanoi@teleline. cadena). también está permitida la siguiente: char cadena[10] = "Una cadena. scanf("%s". i++) printf("%s\t". D. ver12(cad2). i<7. "Dom"}. 't'. No puede haber más. Programación en lenguajes estructurados.I. } 4. "Dom"}. como todo puntero. } void ver34(char **cadena) { int i. Página: 104 Si. en lugar de asignar una cadena constante al puntero.Calcular la longitud de una cadena: int cadlong(char *cadena) { int i. return i. "Mar". "Sab". *cadena. printf("%s". "Jue".'.© A. char cad2[][4]={"Lun". 'e'.".Inicialización de arrays de caracteres. void ver12(char [][4]). con longitud explícita o sin ella. "Dom"}. cadena[i]). for (i=0. 3. ver34(cad4). cadena).. getch().I. "Viernes". 'l'. . "Martes". cadena=(char*)malloc(LONGITUD). "Viernes".es Apuntes de clase . 'o'. for (i=0. "Sab". "Martes".A. i++). "Vie".L.

char *). i++) { k = i. Juego del ahorcado. } return *cadena1 . char *cadena2) { while (*cadena1 == *cadena2 && *cadena1) { cadena1++. "Lozano". 5). k. } . "Diaz".lista[i]). int). i < Longitud. char *cadena2) { while (*cadena1++ = *cadena2++). *(lista + k)) < 0) k = j. cadena2++. i < Longitud . void ordenar(char **. "Garcia"}. void visualizar(char **. int Longitud) { int i. int).Comparar alfabéticamente dos cadenas: Si cadena1 > cadena2 entonces retorna > 0 Si cadena1 < cadena2 entonces retorna < 0 Si cadena1 = cadena2 entonces retorna = 0 int cadcomp(char *cadena1. *(lista + k) = *(lista + i).1.Ordenar alfabéticamente una lista de apellidos: int cadcomp(char *. for (i=0. j.© A. for (i = 0. main() { char *apellidos[] = {"Sanchez". Auxiliar = *(lista + k). i++) printf("%s\t". for (j = i + 1. } Ejercicios: Comprobar si una frase es o no un Palíndromo. char *cadcar(char *cadena.es Apuntes de clase .Encontrar un carácter en una cadena: devuelve un puntero a la posición ocupada por el carácter en la cadena o NULL si no se encuentra. char *Auxiliar. j++) if (cadcomp(*(lista + j). j < Longitud. int caracter) { while (caracter != *cadena && *cadena) cadena++. } } void visualizar(char **lista. D. visualizar(apellidos. Programación en lenguajes estructurados. return *cadena == caracter ? cadena : NULL.I. 5). alozanoi@teleline. "Perez".Copiar una cadena en otra: void cadcopi(char *cadena1. int Longitud) { int i. } void ordenar(char **lista. *(lista + i) = Auxiliar.*cadena2. ordenar(apellidos.A.I. } . Página: 105 . } .L.

strncat(destino. strcat(destino.I. Programación en lenguajes estructurados. Debe haber espacio suficiente.h>. Es igual que la anterior pero comparando sólo el número de caracteres especificado por maxlon. Es igual que la anterior pero copiando de la segunda cadena sólo el número de caracteres especificado por maxlon. blanco). ** int stricmp(const char *s1. size_t maxlon). const char *s2. Retorna un puntero a la primera cadena o un NULL si no se ha realizado la concatenación. ** char *strcat(char *destino. char *blanco = " ". 4). size_t maxlon). Añade a destino el contenido de fuente. strcat(destino. int main(void) { char destino[30] = "El hotel".es Apuntes de clase . No incluye los caracteres europeos. strcat(destino.© A. D. *segunda = "de los lios". } ** char *strncat(char *destino. Retorna un valor entero definido como: . tal como la 'Ñ'.I. segunda. Compara dos cadenas de las que recibe la dirección. destino).. size_t maxlon). destino). printf("%s\n".A. Estas funciones pertenecen a la librería <string. const char *fuente). const char *fuente. const char *cadena2). Página: 106 5. La primera cadena debe tener suficiente espacio para las dos. alozanoi@teleline. int strnicmp(const char *s1. segunda). const char *s2). const char *s2.L.Cero: cadena1 > cadena2 cadena1 < cadena2 cadena1 = cadena2 ** int strncmp(const char *s1. blanco).Funciones de estándar para la manipulación de cadenas.Negativo: . ** int strcmp(const char *cadena1. ** char *strcpy(char *destino. Son similares a strcmp y strncmp pero sin tener en cuenta la diferencia entre caracteres mayúsculas y minúsculas. printf("%s\n". Copia una cadena en otra. const char *fuente).Positivo: .

Convierte una cadena a un int. char c3[20] = "buenos". 6). Otras funciones no-ANSI: strspn. //"buenosxxxxxxxxxxxxxx". Página: 107 ** char *strncpy(char *destino. c1 = "xxxxxxxxxxxxxxxxxxxx".. ** char *strrchr(const char *s. c1). Retorna un puntero a esa posición o uno NULL. Busca la primera posición que ocupa un carácter en una cadena. Si la longitud de la cadena origen es inferior a la longitud máxima. Busca la última posición que ocupa un carácter en una cadena. Convierte una cadena a un double. ** char *strchr(const char *cadena. Pertenecen a la <stdlib.es .I.Funciones de conversión. en caso contrario no se copiará.© A. strncpy(c1. char c2[20] = "bueno". long atol(const char *s). Convierte una cadena a un long. strcspn. Busca la primera ocurrencia completa de una subcadena en una cadena. Retorna un puntero a esa posición o uno NULL. Retorna un puntero a esa posición o uno NULL.A. //"bueno". const char *subcadena). D.h>.I. Apuntes de clase alozanoi@teleline. const char *fuente. int carácter). Sólo de a-z. 6). Convierte una cadena a minúsculas. ** char *strstr(const char *cadena. Convierte una cadena a mayúsculas.L. Retorna un puntero a esa posición o uno NULL. strtok 6. Programación en lenguajes estructurados. strncpy(c1. printf("%s". ** char *strlwr(char *s). const char *cadena2). Sólo de a-z. c3. el carácter nulo de fin de cadena se copia. Es igual que la anterior pero copiando sólo el número de caracteres especificado por maxlon. c1). size_t maxlon). ** ** ** int atoi(const char *s). c2. ** char *strpbrk(const char *cadena1. char *c1 = "xxxxxxxxxxxxxxxxxxxx". double atof(const char *s). ** char *strupr(char *s). printf("%s". int c). Busca la primera ocurrencia de cualquier carácter de una cadena en otra cadena.

(CIERTO/FALSO) ¿Blanco.(CIERTO/FALSO) Imprimible menos blanco y alfanumécos. 0-9)? (CIERTO/FALSO) ¿Alfabético (a-z)? (CIERTO/FALSO) 0-31 y 0127 (CIERTO/FALSO) ¿Dígito? (CIERTO/FALSO) Carácter imprimible menos es blanco.I.I. Sólo de a-z. long y unsigned long respectivamente. Ignoran los espacios iniciales. tab? (CIERTO/FALSO) ¿Mayúsculas? (CIERTO/FALSO) ¿Dígito hexadecimal? (CIERTO/FALSO) alozanoi@teleline.L. nueva línea. 7. Programación en lenguajes estructurados. D.. ** ** ** double strtod(const char *s. ¿Alfanumérico (a-z.es Apuntes de clase . char *siguiente. El puntero siguiente es la dirección del siguiente carácter a tratar. (CIERTO/FALSO) ¿Minúsculas? (CIERTO/FALSO) Carácter imprimible incluído el blanco. return. Base es la base numérica en la que se trabaja. char *siguiente). long strtol(const char *s.h>. Convierten una cadena a número double. Pertenecen a la librería <ctype. Carácter a mayúsculas o ch. devuelven el valor cero si el primer carácter es erróneo y la exploración finaliza con el primer carácter no válido.A.Funciones de caracteres. Sólo de a-z. unsigned long strtoul(const char *s. int tolower(int ch) int toupper(int ch) int isalnum(int) int isalpha(int) int iscntrl(int) int isdigit(int) int isgraph(int) int islower(int) int isprint(int) int ispunct(int) int isspace(int) int isupper(int) int isxdigit(int) Carácter a minúsculas o ch. int base).© A. int base). char *siguiente. Página: 108 Todas reconocen los caracteres adecuados a su tipo de dato.

. Por lo general. se diferencia de un array lineal por lo siguiente: · · Un registro puede ser un conjunto de datos no homogéneo._ Estudiante 2. por lo que no existe un orden natural de sus elementos._ Segundo apellido 3.I. Los nombres asignados a los elementos reciben el nombre de identificadores. Un registro es un tipo de datos estructurado que está constituido por un conjunto de elementos.es Apuntes de clase . Página: 109 13._ Primer apellido 3.]]. los elementos de un registro pueden ser de diferente tipo de dato..Declaración de estructuras. Los elementos de un registro se referencian a través del nombre de cada atributo o campo._ Calificación 2. Aunque un registro es un conjunto de elementos._ Examen(3) 2._ Día 3._ Fecha nacimiento 3. Cada elemento a su vez puede estar constituido por un conjunto de subelementos._ Nombre 2. es decir. Aquellos elementos que son individuales reciben el nombre de elementos simples._ Final 2.. CAMPOS DE BITS Y UNIONES 1. de igual o diferente tipo de dato.. átomos o escalares. alozanoi@teleline. con alguna relación entre ellos.ESTRUCTURAS. Los registros de los estudiantes de una clase pueden organizarse como: 1. D._ Mes 3..A._ Año 2.I.Definición de registro o estructura. una estructura se declara de la siguiente forma: struct [<tipo_estructura>] { <tipo1> <identificador_campo_1>..L. los elementos de un registro forman una estructura jerárquica que puede describirse a través de números de nivel.. . un archivo es un conjunto de registros similares. cada uno de estos elementos recibe el nombre de campo o atributo del registro. <tipo2> <identificador_campo_2>. <tipoN> <identificador_campo_N>. Programación en lenguajes estructurados._ Nombre 3. }[<variable_estructura>[.© A. Dentro de la relación entre grupo de elementos y subelementos..

"Pérez".]. char apelli[30]. variables estructura de ese tipo. A los campos de una estructura también se les pueden asignar valores iniciales en la declaración.4321}.I. int expediente.L. Formato 3 struct s_persona { char nombre[15].Ape. Página: 110 Los campos de la estructura pueden ser de cualquier tipo de dato permitido en C: arrays. } la_persona.Crea un tipo estructura . Cuadro resumen de la declaración de una estructura en C. char apelli[30]. Estudiante Nombre P. pero uno de los dos. . Para poder usar el nuevo tipo hace falta definir al menos una variable. Estos valores deben aparecer en el orden en que serán asignados a los correspondientes campos de la estructura. los campos que componen la estructura se sitúan en direcciones contiguas y cada uno ocupa lo que le corresponde en función de su tipo. Si en la declaración aparece <tipo_estructura>. o los dos.. ----------------------- struct s_persona per2. S.A. Permite inicializaciones parciales. int expediente. } persona. encerrados entre llaves y separados por comas.Crea un tipo estructura (persona). El formato para crear una variable estructura es el siguiente: struct <tipo_estructura> <identificador_variable>[. tipos simples. La representación en memoria interna es semejante a la del array. struct s_persona v_persona = {"Antonio".© A.. Formato 2 struct { char nombre[15].es Apuntes de clase . int expediente. Formato 1 struct s_persona { char nombre[15].Ape. int notas[3]. .No se pueden definir más (la_persona). .Crea una variable estructura . .. Programación en lenguajes estructurados.. <variable_estructura> y <tipo_estructura> son opcionales. estamos creando un tipo de estructura. Nombre Fecha Nacimiento Día Mes Año Examen Final Calif. debe aparecer en la declaración. .Se pueden definir más variables de tipo s_persona. int notas[3]. (s_persona) (s_persona).Se pueden definir más variables de tipo s_persona. char apelli[30]. salvo en la declaración. struct s_persona per1.. int notas[3].I. }. Calif. punteros.Crea una variable estructura . D. 0 1 2 Final alozanoi@teleline. siendo necesario crear una variable de ese <tipo_estructura> (si está <variable_estructura> no es necesario crearla pues se crea en la propia declaración). otras estructuras.

I.h> #include<stdlib. int Ntas[TN].h> #include <conio. Página: 111 3.es Apuntes de clase .Notas[0] /= 2. Identificado_Campo #include<stdio. D. } De la misma forma que un array (que es un tipo estructurado de datos) puede ser miembro de una estructura. OtraPersona = UnaPersona. <identificador_campo> Para acceder a los campos de la estructura anterior podemos hacerlo asignando valores constantes con el operador de asignación o dando valores introducidos por la entrada estándar (igual que cualquier otra variable).Manipulación de estructuras.Nombre). char Apelli[30]. Para referirse a un campo de la estructura interna debe realizarse con el operador punto. gets(UnaPersona.h> #include <stdlib.h> #define TN 3 struct SPersona { char Nombre[15]. <variable_estructura> . main() { struct SPersona UnaPersona.Apelli). también se puede asignar toda la información contenida en una estructura a otra del mismo tipo en lugar de hacerlo campo a campo.Apelli). int Expediente. así mismo.h> #include<conio. Variable_Externa . precedido por el nombre de la variable estructura y seguido por el campo que queremos referenciar. OtraPersona.h> #include<conio. por tanto. int i.Notas[i]). Cuando esto ocurre.h> #define TN 3 #include<stdio. para accede a ella hay que usar también el operador punto.) o selector de campo directo. Los campos de la estructura se referencian usando el operador punto(. }.Nombre). i++) scanf("%d". getch().L. se debe tener en cuenta que esta es un campo de la estructura externa y. gets(UnaPersona.A.h> #include<stdlib. Ejemplo: #include <stdio. &UnaPersona.I. la declaración de la estructura interna debe aparecer antes que la declaración de la estructura que la contiene. i<TN. Programación en lenguajes estructurados.h> #define TN 3 alozanoi@teleline.. Variable_Interna . for (i=0. otra estructura también puede serlo. OtraPersona. puts(OtraPersona. i++) printf("%d\t". for (i=0.Notas[i]).© A. OtraPersona. i<TN. puts(OtraPersona.

short Calificacion.Se desea escribir un programa para controlar los pasajes de una línea aérea que tiene un vuelo a ocho ciudades distintas. Para ello se necesita almacenar la capacidad de cada vuelo y el número de plazas libres de cada vuelo. Alumno[3]. Otro = Alumno. }.Expediente = 1234.Apellido1). }Fecha_Naci. for (i=0. }. Alumno[3].. Para acceder a un elemento de un array de estructuras.I. char Nombre[10]. Diseña y escribe la estructura de datos necesaria. short Mes. char Nombre[10].Apellido1[2] = 'a'.El_Nombre. todo depende de las necesidades futuras que tengamos (definir o no variables de las estructuras internas).Fecha_Nacimiento= vFecha.es Apuntes de clase . char Apellido2[10]. las componentes de un array podían ser de cualquier tipo de dato de C. D. gets(Alumno. struct Estudiante { int Expediente. struct { char Apellido1[10]. short Anho. short Mes.interna } Se puede usar cualquiera de las dos formas usadas para la declaración de la estructura. struct Nombre El_Nombre. char Apellido2[10].El_Nombre.Notas[i]).El_Nombre.Arrays de estructuras. 4. gets(Alumno.L. }.El_Nombre. short Notas[TN]. struct Estudiante Alumno[NUMERO_ALUMNOS].Nombre).. struct Estudiante Alumno. struct Estudiante { int Expediente.Notas[1] = 6. //Registro completo. struct Fecha { short Dia. short Final. short Anho. E. Si además queremos acceder a un carácter del campo Apellido1 o a una nota: Alumno[3]. Página: 112 struct Nombre { char Apellido1[10]. así como el número de reservas que quedan en lista de espera. Ejercicios/Ejemplos: 1.© A. struct Nombre vNombre.I. short Notas[TN]. struct { short Dia. i++) scanf("%d".A. estas pueden ser el tipo de las componentes de un array.Apellido2). gets(Alumno. se debe aplicar el índice sobre el nombre de la variable estructura seguido del operador punto y el campo de la estructura que queremos referenciar. main() { int i. struct Fecha vFecha. struct Fecha Fecha_Naci. alozanoi@teleline. short Final. }. } sNombre. Alumno. i<TN. Como las estructuras son un tipo de dato admitido por el compilador de C. short Calificacion. Otro. &Alumno. Como ya vimos. Programación en lenguajes estructurados.

} DatosPasaje[8]. El formato de definición del alias es el siguiente: typedef <TipoDeDato> <Identificador>. real Temperatura. 2. Una vez establecido el alias. 4. struct Venta Coches[MARCA][MODELO]. Página: 113 struct Pasajes { char Ciudad[20]. int Reserva_Espera.I._ Programa que carga el nombre y número de teléfono de varias personas y realiza una clasificación ascendente por orden alfabético de nombres y. struct Venta { int Numero. float Temperatura. 5. int Capacidad. struct Agencia { int Codigo_Vendedor.I. Vuelo int Capacidad. imprime la lista ordenada de nombres y teléfonos. } Vuelo[8]. siendo equiparable en todos los aspectos. Programación en lenguajes estructurados. int Plazas_Libres.. Por tanto la siguiente sentencia: typedef float real. long Valor. finalmente. struct { Tiempo int Hora. suponiendo que puede haber varios vuelos a una misma ciudad. significa que se reconoce la palabra real como otro nombre de float.Tipos de datos definidos por el usuario Es posible definir un alias para los tipos de dato de C con la palabra reservada 'typedef'.es Apuntes de clase . int Plazas_Libres. struct { }. struct Tiempo Hora. } Vendedores[NUMERO]. alozanoi@teleline..A. Diseña y escribe la estructura de datos necesaria para ello.. struct Vuelo DatosVuelo[NV]. Minutos. 3. struct Pasajes { char Ciudad[20].Diseña y escribe una estructura de datos para almacenar la información del problema anterior. int Reserva_Espera.L.Se desea escribir un programa para controlar las ventas (en número y pesetas) de una agencia de automóviles que tiene en plantilla 10 vendedores y distribuye 5 marcas de coche cada una con 3 modelos diferentes. }. las nuevas variables pueden ser declaradas en términos de ese nuevo tipo/alias. }.© A. D.

Otro = &Alumno.El_Nombre. Programación en lenguajes estructurados. Otro->Expediente). tVenta Ventas1. Cuando se define un puntero a una estructura.I. gets(Alumno. el puntero trabaja de la misma forma que en los casos de punteros anteriores..Nombre).' para acceder a campos de estructuras incluidas en otras más externas. <tipoN> <identificador_campo_N>. tVenta Ventas1. Ventas2[10].' por que se espera. Página: 114 La característica más útil de typedef es cuando se definen estructuras.Estructuras y punteros.. <tipo2> <identificador_campo_2>. D. Nota: Esta declaración puede combinarse con la anterior. gets(Alumno. *Otro. printf("%d\n". Usar el nuevo operador '->' o selector de campo indirecto que permite acceder a los distintos campos de la estructura a partir de su dirección de comienzo. struct Venta { int Numero.Final). typedef Venta tVenta. printf("%s\n". 6. La declaración de un puntero a una estructura se realiza de la siguiente forma: <tipo_estructura>* <identificador_estructura> Para acceder a los campos de una estructura referenciada por un puntero no se usa el operador '. Otro->El_Nombre.© A. Por tanto. struct Estudiante Alumno.Final).. ya que elimina la necesidad de escribir repetidamente la palabra struct <estructura> en todos los lugares donde se referencia la estructura. Ventas2[10]. long Valor. } tVenta. }<identificador_nuevo_tipo>. gets(Alumno. el identificador de una estructura y no una dirección.Expediente). 2. Ejemplo: typedef struct { int Numero. printf("%d\n". Adoptar la notación (*estructura). typedef struct { <tipo1> <identificador_campo_1>. Es posible definir más de un nuevo tipo.Campo para referenciar un campo de la estructura.I. }. usando y sin usar typedef. como primer operando. (*Otro).A. tenemos dos formas de acceder a un campo de la estructura referida por un puntero: 1. alozanoi@teleline. El operador ' ' puede combinarse con el operador '. long Valor.L. typedef struct <estructura> <alias>.Nombre). .es Apuntes de clase .

scanf("%d".&alumno->expedient). Estructura por valor. Cuando pasamos estructuras a funciones existen dos posibilidades: pasar un campo de la estructura o pasar una estructura completa. } Estructura por referencia.&alumno. return alumno. Pasando un campo: Prototipo: Llamada: <tipo> Ident_Funcion(<tipo_campo> [*]P_formales). &alumno. la declaración de un puntero a una estructura no reserva memoria. Trabajo con estructuras. [<Variable> =] Ident_Funcion([&]V_estructura).'. void alta(s_estudiante *alumno) { scanf("%d".. los cambios si se ven reflejados y los campos se referencian con el operador '>'. los cambios realizados sobre estos en el cuerpo de la función no se ven reflejados en la función llamante y los campos se referencian con el operador '. alta(*(alumnos + i)). [<Variable> =] Ident_Funcion([&]V_estructura. &alumno->expedint). Programación en lenguajes estructurados.I. void alta_alumno(s_estudian *alumno) { scanf("%d". Otro = (struct Estudiante *) malloc(sizeof(struct Estudiante)). Alumnos = alta_alumno(). Página: 115 Como todas las definiciones de punteros.expediente). Retorna una estructura.I. Alta_alumno(&alumnos).A. Si se pasan los parámetros por valor.© A. Otro = &Alumno. como en el ejemplo anterior.L. s_estudiante alta_alumno() { s_estudiante alumno.expedinte). 7. En cualquiera de los dos casos podemos usar las dos formas que tenemos para pasar parámetros: por valor y por referencia. alta(alumnos + i).es Apuntes de clase .Campo). Otro = (tEstudiante *) malloc(sizeof(tEstudiante)). } Pasando componentes de un array.Paso de estructuras a funciones. Pasando la estructura completa: Prototipo: Llamada: <tipo> Ident_Funcion(<tipo_estruct> [*]P_formales). void alta(s_estudiante alumno) { scanf("%d". typedef Estudiante tEstudiante. D. } alozanoi@teleline. } Paso por referencia. siendo necesario reservarla explícitamente con la función 'malloc()' o dándole la dirección de otra variable del mismo tipo. El tipo de dato que retorna una función también puede ser una estructura. todos los campos. si se pasan por referencia.

void visualizar(agenda *persona). persona[k]. agenda las_personas[NPERSONAS].. } void visualizar(agenda *persona) { printf("%s\n".nombre) < 0) //if (strcmp((*(per + j)). int Longitud) { int i. Página: 116 Ejemplo : Creación de una agenda de teléfonos.h> #include <conio. j < Longitud. fflush(stdin). printf("Número de telefono de %s: ".© A. } void ordenar(agenda *persona. main() { int i. i<NPERSONAS. persona->telefono). scanf("%s".Uniones. } agenda. i<NPERSONAS.1. persona->nombre). ordenar(las_personas. D. persona[k] = persona[i]. (per + k)->nombre) < 0) k = j. for (j = i + 1. } void alta(agenda *persona) { printf("Nombre: "). k. Una unión es una estructura en la que sus elementos ocupan la misma posición de memoria. char nombre[30].L.h> #define NPERSONAS 5 typedef struct { int telefono. Programación en lenguajes estructurados. &persona->telefono). i++) { k = i. El tamaño de la memoria es el correspondiene al elemento mayor de la unión y los demás elementos comparten dicha memoria. getch(). void alta(agenda *). for (i = 0.h> #include <string. j++) if (strcmp(persona[j]. i++) alta(las_personas + i). i < Longitud . Auxiliar = persona[k]. printf("%d\n".h> #include <stdlib. j.I. scanf("%d". &persona->nombre). for (i=0.I. NPERSONAS). void ordenar(agenda *persona.A.nombre. fflush(stdin). } } 8. persona->nombre). agenda Auxiliar.es Apuntes de clase . i++) visualizar(las_personas + i).nombre. #include <stdio. int). for (i=0. alozanoi@teleline. persona[i] = Auxiliar.

Programación en lenguajes estructurados. break. El formato general es el siguiente : alozanoi@teleline.I. struct TBbi { int Referencia. <tipo2> <identificador_campo_2>. char Editorial[25]. Podrían simularse registros variables.]].DatosEd..es Apuntes de clase . struct { int Dia. El lenguaje C permite acceder a bits individuales. case Revista: puts("Revista").Campos de bits.Publicacion.Edicion). D. break. Hay que saber que campo es el que está almacenado en cada instante. }.Publicacion. Todas estas tareas pueden ser realizadas usando operadores para el manejo de bits pero un campo de bits realza la estructura del código del programa. int Anho. &Bbi. int Anho...A. donde un campo de bits es un tipo especial de campo que define su longitud en bits. scanf("%d".. Suele usarse para campos de bits o conversión de tipos. } Publicacion.Tipo) { case Libro: puts("Libro"). scanf("%d". char Titulo[30]. } Fecha. Sólo se reserva espacio en memoria para almacenar el mayor campo. Ciertas rutinas de cifrado necesitan acceder a los bits de un byte.© A. } DatosEd. }[<variable_union>[. union { struct { int Edicion.L. de forma que siempre hay espacio para almacenar cualquiera de los campos restantes. &Bbi.Tipo). <tipoN> <identificador_campo_N>. &Bbi. switch (Bbi. Página: 117 union [<tipo_union>] { <tipo1> <identificador_campo_1>. enum Clases Tipo. main() { TBbi Bbi. Revista}.Dia). } } 9. El método usado en C para acceder a los bits es la estructura. int Mes. scanf("%d". Los dispositivos transmiten información codificada en bits. Los campos de bits pueden ser útiles por varias razones : · · · Si el almacenamiento es limitado. char Autor[20]..Fecha. ..I. El tratamiento es igual al de la estructura. enum Clases {Libro.

. // Cambio en la línea listo-para-enviar unsigned Delta_dsr :1 . . es cero.L. Apuntes de clase alozanoi@teleline. // Estado de un adaptador de comunicaciones serie struct TipoEstado { unsigned Delta_cts :1 . // Cambio en datos-listos unsigned Tr_final :1 .© A. Tienen alguna dependencia de la máquina. Ejemplos : // Empleado de una empresa struct Emp { struct Dir Dirección . por omisión. // Señal recibida } .. }[<variable_estructura>[.} [ListaDeVariables]. Una enumeración es un conjunto de constantes enteras con nombre que especifica todos los valores válidos que puede tomar una variable de ese tipo. El formato de definición de enumeraciones es el siguiente: enum [<Etiqueta>] {<IdentificadorDeConstante> [= <Valor>]. unsigned o signed. // Llamada telefónica unsigned Linea :1 . // Datos-listos unsigned ring :1 . No se puede saber de una máquina a otra si los campos de bits se distribuyen de izquierda a derecha o al revés.. deben ser de un tipo integral. <tipoN> <identificador_campo_N> : longitud_N. unsigned baja :1 . · · · <Etiqueta> : Es una etiqueta opcional que da nombre al conjunto.. Página: 118 struct [<tipo_estructura>] { <tipo1> <identificador_campo_1> : longitud_1.. unsigned PoHoras :1 . Las restricciones del empleo de campos de bits son las siguientes : · · · No se puede tomar la dirección de una variable de campos de bits. Longitud indica el número de bits del campo. <Valor> : Debe ser un valor entero. D.es .A. <tipo2> <identificador_campo_2> : longitud_2.]]. El tipo de un campo de bits debe ser int. Son llamadas constantes enumeradas. No se pueden construir arrays de campos de bits. } . unsigned Deducciones :3 . Programación en lenguajes estructurados... depende del compilador. // Listo-para-enviar unsigned dsr :1 . 10. El valor de la primera constante de la lista. <IdentificadorDeConstante> : Es el nombre de una constante a la que opcionalmente se le puede asignar un valor. Si se omite esta inicialización.Enumeraciones. // Cambio en la línea de recepción unsigned cts :1 .I.I. // Detección final unsigned Delta_rec :1 . se asume que toma el valor del la constante anterior más uno. float Paga ...

break. Programación en lenguajes estructurados.es Apuntes de clase . break. } printf(“%s”.Domingo} enum Semana Hoy. D. La sentencia enum Semana {Lunes.© A. main() { Hoy= Lunes.A. estas sólo pueden tomar los valores del tipo semana enumerados. cout << Maniana << '\n'. Hoy<=Domingo. break. Página: 119 · <ListaDeVariables> : Es una lista opcional de variables de este tipo enum.Hoy<=Domingo.I.I.Sábado. no una cadena } alozanoi@teleline.L.Jueves. Hoy es un entero.Hoy++) cout << Hoy << '\n'. Maniana . for(Hoy= Lunes. cout << Hoy << '\n'. Hoy) . Maniana= Hoy + 1.Miércoles. //Es un error.Martes. define una enumeración denominada Semana y declara dos Hoy y Maniana como dos variables de ese tipo. for(Hoy=Lunes. case Miercoles:cout << "Miércoles" << '\n'.Hoy++) switch (Hoy) { case Lunes: cout << "Lunes" << '\n'. case Martes: cout << "Martes" << '\n'.Viernes.

.

Página: 121 14. D. Ahora. Un campo puede estar dividido en subcampos. Tipo de datos estructurado que consta de un conjunto de elementos que pueden ser de igual o distinto tipo. definiciones. Las características principales de los archivos son: · · · · Independencia de la información almacenada respecto al programa.. para subsanar esto problemas. 2. un conjunto de datos estructurados en una colección de entidades elementales o básicas denominadas registros que son de igual tipo y que constan. es decir.L. Estos nos permitirán almacenar grandes cantidades de información de forma permanente para... Gran capacidad de almacenamiento. La información almacenada es permanente. Acceso a un archivo por distintos programas en distintos momentos o simultáneos.© A. Registro. imaginemos una pequeña biblioteca: · · · En la biblioteca hay una serie de cajones o archivadores: archivo o fichero. Un archivo es.es Apuntes de clase . Es la unidad lógica mínima/ básica de acceso a un fichero. Archivo o fichero.I. Cada cajón contiene fichas referentes a un libro. son volátiles. Campo. Colección de información (datos relacionados entre sí) almacenada como una unidad en alguna parte del ordenador. alozanoi@teleline. de diferentes entidades de nivel más bajo denominados campos. como se dijo antes. soportes externos de información (cinta.. recuperarla y tratarla en futuras operaciones de modificación o actualización.A. Cada vez que se ejecuta el programa es necesario introducir los datos por teclado. a su vez. Para realizar una semejanza entre las estructuras de datos que se usarán en este capítulo y la vida real. con toda su información: registro.. los objetos tratados por un programa estaban limitados por la cantidad de memoria principal del ordenador y por que su existencia se limita al tiempo de ejecución del programa. los datos se deben manipular de forma que puedan ser usados por futuros programas utilizando estructuras de datos externas o ficheros.I. Los archivos no se almacenan en memoria principal/central del ordenador.) que son capaces de almacenar la información incluso cuando no se esté ejecutando ningún programa o el ordenador no reciba corriente eléctrica. Programación en lenguajes estructurados. Cada uno de los elementos o informaciones individuales que componen un registro. Este conjunto de datos puede ser usado posteriormente mediante el programa adecuado. dispositivo de almacenamiento externo. .Introducción. por tanto. Cada ficha contiene información puntual de cada publicación: campo.Conceptos. Hasta ahora.ESTRUCTURAS DE DATOS EXTERNAS 1. disco. Están limitados por la capacidad del soporte externo. si no que usan memoria externa.

L. Página: 122 Clave. en bytes. es decir. D. Registro físico. · Históricos.2.Clasificación según su uso. Puede contener uno o más registros lógicos. no puede ser tomado por ningún otro campo clave de otro registro. Programación en lenguajes estructurados. Contienen la información actualizada en un determinado momento. Datos. archivo de transacciones de cuentas bancarias. · alozanoi@teleline. Factor de bloqueo.. mayor o igual al del registro lógico. indican cuando realizar altas. su uso.. · De movimiento. Los datos que almacenan permanecen prácticamente constantes.A. 3. Contienen la información que se utilizará para actualizar los archivos maestros. El valor de este campo es único. 1 Reg.Clasificación desde el punto de vista del usuario.es Apuntes de clase . Número de registros lógicos que contiene cada registro físico. · Maestros. Campo especial de un registro que es capaz de identificarlo de forma unívoca. · Permanentes. el almacenamiento físico en el soporte y según su método de acceso. Su tamaño depende de las características físicas del ordenador y del sistema operativo (buffers).© A. Suelen desaparecer una vez cumplido su cometido. bajas.1. La información que almacenan no varía o varía poco. etc. Temporales. · · · Ejecutables. Código. Se supone que el registro físico tendrá un tamaño. uno completo o más de uno. Contienen información ya actualizada y que se mantienen con fines de consulta o estadísticos. La clasificación de los archivos puede realizarse desde distintos puntos de vista: del usuario. ARCHIVO Reg.I.. 3 Nombre Profesión Dirección Teléfono Ciudad Comunidad REGISTRO CAMPO 3. · Constantes. Bloque o cantidad mínima de información que se transfiere en cada operación de Entrada/Salida sobre un archivo. Por ejemplo. Archivo de artículos.Clasificación de los archivos. Por ejemplo. 3. 2 Reg.I. archivo de nombres de provincias. Un registro lógico puede ocupar menos de un registro físico.

consulta. debemos abrirlo. 4. atendiendo al valor de uno o varios de los campos del registro. Todos los sectores que forman un archivo están contiguos. clasificación. Para poder realizar cualquier operación sobre un fichero es necesario que exista previamente. reorganización. Soluciona el problema de los huecos. Las operaciones que podemos realizar sobre los archivos son: creación.es Apuntes de clase .I. debe cerrarse para limitar el acceso a los datos y evitar la corrupción de los mismos.4. · · · · · alozanoi@teleline. 3. Una vez efectuadas las operaciones sobre el fichero. Apertura. Copiado o duplicado.L. ya sea introduciendo información nueva o bien cambiando o eliminando la ya existente. que haya sido creado grabando sobre el soporte externo la información requerida para su posterior tratamiento.. archivos intermedios de ordenación.A. Por ejemplo.Clasificación según el almacenamiento físico en el soporte. borrado. · Creación. Consiste en reagrupar los registros contenidos en el archivo en un orden ascendente o descendente. D. Esta organización tiene el problema de desaprovechar los huecos que se producen al borrar un registro. Para poder acceder a los datos y así permitir realizar las operaciones necesarias de lectura y escritura de los mismos sobre el fichero. Son archivos auxiliares que se crean temporalmente y sólo existen en tiempo de ejecución del programa. dependiendo del criterio utilizado.I. Organización encadenada..la información almacenada en el fichero.3. Organización indexada. 3. Programación en lenguajes estructurados.. Permite modificar -actualizar.Clasificación según su método de acceso. se consulta. · · · Secuenciales. partición. Página: 123 · De maniobra o trabajo. Secuenciales indexados. Un fichero no debe permanecer abierto más tiempo del necesario para operar sobre él. Se guarda una lista de los sectores que forman el archivo y cuando hace falta. Ordenación o clasificación. Cierre. El directorio tiene un puntero al primer sector y cada sector a su siguiente. fusión.Operaciones sobre archivos. La ventaja es que permite usar cualquier tipo de método de acceso u organización lógica del mismo. Directos.© A. Crea un nuevo fichero con la misma estructura y contenido de un fichero fuente. pero no permite saber la longitud del archivo. Actualización. · · · Organización contigua. actualización.

Consiste en realizar un cambio total o parcial de uno o varios campos de los registros de un fichero. Con esta forma de borrado de registros se pierde toda posibilidad de recuperar la información.I. · · · · · 5. el hueco que hubiera generado. Requiere. · Altas. Consiste en eliminar uno o varios registros del fichero. Al hablar de ficheros se hace necesario conocer dos conceptos fundamentales: alozanoi@teleline. se pierde toda la información y la posibilidad de acceder a los datos previamente almacenados. Esta operación permite obtener de dos o más ficheros con la misma clasificación y estructura interna de sus datos.Operaciones sobre registros. se obtiene un tercer fichero que tiene la misma estructura y contenido la suma de los dos anteriores. Eliminando físicamente el registro del fichero haciendo una compactación del mismo o desplazando todos los registros posteriores una posición y eliminando. Es la operación inversa a la creación de un fichero y en consecuencia una vez efectuada dicha operación. A través de las consultas es posible acceder a los registros del fichero y conocer el contenido de sus campos. igual que la baja. Fusión o mezcla. un proceso previo de lectura para la localización del registro que se pretende modificar y un segundo proceso de escritura para la actualización del registro. Permite obtener varios ficheros de uno inicial en función de alguna de las características internas de sus campos. Borrado.es Apuntes de clase . normalmente ocasionados por la eliminación de registros. impresora u otro periférico. · 6. un nuevo fichero que contenga los registros de todos los anteriores sin alterar la ordenación que éstos tenían establecida. Consiste en que dados dos ficheros de igual estructura. D. · Modificaciones. Esta operación permite acceder a uno o varios registros con la intención de visualizar su contenido por pantalla. Partición. Esta operación sólo se permite para en archivos que existen previamente.Organización de los archivos.. Consultas.I. El borrado de registros se puede realizar de dos formas diferentes: · · · Marcando de alguna manera (flag o bandera) la posición ocupada por dicho registro y permitiendo así su posterior recuperación en el caso de que haya habido algún error.© A. Consulta. Compactación o empaquetamiento. por tanto. que han sido creados.L. Página: 124 · Concatenación.A. Programación en lenguajes estructurados. Bajas. Permite la reorganización de los registros de un fichero eliminando los huecos libres intermedios existentes entre ellos. Consiste en la adición o inserción de uno o varios registros en el fichero.. Esta operación requiere un proceso previo de lectura o consulta para la localización del registro que se pretende eliminar.

La organización secuencial tiene la particularidad de que no puede encontrarse nunca en el estado de Lectura/Escritura. Registro N-1 Registro N EOF Los registros se graban consecutivamente cuando el archivo se crea y se debe acceder consecutivamente cuando se leen dichos registros. Ventajas: · Rapidez en el acceso a un bloque de registros. por tanto.y sólo se puede acceder a los registros de uno en uno a partir del primero. También existe una estrecha dependencia entre el tipo de soporte utilizado y el tipo de acceso.I. En una organización secuencial los registros ocupan siempre posiciones consecutivas de memoria en el soporte externo -en consecuencia no hay huecos entre los registros y. directo y por índice. · No permite borrar registros. directa e indexada. cuando leemos de una organización secuencial no podemos realizar escrituras y cuando escribimos no podemos leer. Los tipos de acceso son secuencial. Archivo Registro 1 Registro 2 .1 registros anteriores. Se define como la forma en la que los datos se estructuran y almacenan internamente en el fichero y más concretamente sobre el soporte de almacenamiento. no se desaprovecha el espacio.Organización secuencial.I. Programación en lenguajes estructurados. debemos servirnos de un fichero secuencial auxiliar de movimientos. Acceso. · 6. sólo marcarlos creando un fichero nuevo. · No deja espacios vacíos intermedios entre registro y registro. Página: 125 · Organización. · No permite la inserción de nuevos registros. Básicamente existen tres tipos de organización: secuencial. es decir... D. Este tipo de organización se soporta sobre todos los tipos de dispositivo de memoria auxiliar existentes. para tratar el registro situado en la posición N del fichero. Esta estructura depende mucho de las características del soporte utilizado. si no que tiene que estar en el estado de lectura o en el estado de escritura. sólo nos permite añadirlos al final del fichero creando un nuevo fichero. Tampoco se pueden realizar actualizaciones directamente sobre el fichero.A.L. Los ficheros organizados secuencialmente contienen un registro particular (el último) que contiene la marca fin de archivo (EOF o FF). Es el procedimiento necesario que debemos seguir para situarnos sobre un registro concreto con la intención de realizar una operación de lectura o escritura sobre el mismo.es Apuntes de clase .© A. es necesario tratar los N . alozanoi@teleline.1.. es decir. Inconvenientes: · Para consultar un registro concreto es necesario consultar todos anteriores.

Existen dos variantes de la organización relativa: directa e indirecta o aleatoria. El algoritmo de transformación de claves debe cumplir tres características principales: · · · Aprovechar al máximo el espacio disponible en el soporte externo.A.I.2. 6. El valor de la clave siempre está en relación con la capacidad máxima del soporte físico.. estableciéndose así una relación directa entre la clave y la dirección que ocupa el registro dentro del fichero. Establecer una correspondencia directa entre dirección lógica (clave) y dirección física (memoria). directo. Esta organización se da en cuando la clave es numérica y además tiene un valor que está dentro del rango de direcciones válidas. Inconvenientes: · Al realizar una lectura secuencial del fichero podemos encontrarnos con huecos vacíos de forma que hay que tratarlos convenientemente y como consecuencia hay una perdida de tiempo en el procesamiento de la información..L. D.Organización directa. La dirección de almacenamiento del registro en el dispositivo se obtiene siempre de la clave del propio registro: · Si la clave no es numérica se aplican algoritmos o fórmulas de transformación para obtener valores enteros positivos que facilitan su posterior manejo y tratamiento.1. El almacenamiento físico de los registros sobre el soporte seleccionado se realiza a través de una clave que indica la posición de almacenamiento del registro dentro del fichero.Organización relativa. Página: 126 6. Son aquellos caracterizados por: · · · Deben almacenarse en un soporte direccionable. · Permite realizar operaciones de entrada y salida simultáneamente. alozanoi@teleline.© A. estableciendo así una relación directa entre dirección lógica y dirección física.I. · Permiten acceder a los datos tanto directamente (por su clave) como secuencialmente. Los algoritmos de transformación de claves reciben el nombre de “Hashing” y hay gran variedad de ellos. · Desaprovechamiento del soporte debido a la gran cantidad de huecos que pueden existir. Ventajas: · Permite un acceso inmediato. · Si la clave es numérica se aplica un algoritmo de transformación para obtener un rango de valores comprendidos dentro del intervalo de valores de las direcciones de memoria disponibles. por lo que nunca podemos almacenar un registro cuya clave esté por encima de los límites máximos del fichero. cada posición se localiza por una dirección absoluta (el programador sólo gestiona direcciones relativas).2. a los datos.es Apuntes de clase . · Son muy rápidos en el tratamiento individual de registros. Producir el menor número de registros que con diferentes claves generan idénticas direcciones de almacenamiento tras aplicar el algoritmo de transformación. Programación en lenguajes estructurados.

· No requiere procesos de ordenación. Un índice para cada posición direccionable. la dirección de la posición y el valor de la clave. Área de índices: es una tabla que contiene los niveles de índice. D.es .A. Inconvenientes. Ventajas: · Permite un acceso inmediato a los registros haciendo sólo referencia a su clave. para las actualizaciones.debe sufrir una transformación de la clave para obtener un valor numérico entero que esté comprendido dentro del rango de direcciones válidas y así establecer la correspondencia directa entre la clave y la dirección de memoria que ocupa el registro en el soporte externo en el que se almacena el fichero. 6.2. si fuese necesario. · Los mismo que la organización directa.3. la existencia de varios índices enlazados se denomina nivel de indexación. Un archivo está organizado de forma secuencial indexada si: · · · El tipo de sus registros contiene un campo clave. Los elementos se encuentran almacenados de forma secuencial pero existe una forma de conocer la posición de un determinado elemento.2.Organización secuencial indexada.I. Un archivo con organización secuencial indexada consta de las siguientes parte: · · · Área de datos o primaria: contiene los registros en forma secuencial y está organizada en secuencia de claves sin dejar huecos intercalados.Organización relativa o indirecta. Este hecho se conoce con el nombre de “sinónimo” o “colisión”.© A. Un archivo secuencial indexado es una mezcla de las dos anteriores. · Son muy rápidos en el tratamiento individual de registros.L. Se debe procurar que estos algoritmos generen el menor número posible de sinónimos y de huecos vacíos. Los registros están situados en un soporte direccionable por el orden de los valores indicados por la clave.. Página: 127 6. Esta organización se da en aquellos casos en que la clave –ya sea de tipo numérico entero o de tipo cadena.I. · Permiten acceder a los datos secuencialmente. Área de desbordamiento: utilizada. Consta de un archivo de índice y un archivo de datos. · Se necesita programar la relación que existe entre la clave y la posición de memoria que ocupa el registro y también hay que programar el tratamiento de sinónimos. Apuntes de clase alozanoi@teleline. En este tipo de organización.. cada dirección puede ser ocupada por más de un registro debido a que el algoritmo de transformación aplicado a claves con valores diferentes ha generado la misma posición de almacenamiento en memoria. Programación en lenguajes estructurados. · Permite realizar operaciones de entrada y salida a la vez.

· Acceso rápido. · El sistema de gestión de archivos se encarga de relacionar la posición de cada registro con su contenido mediante la tabla de índices.es Apuntes de clase .A. Página: 128 Ventajas.I. · Desaprovechamiento del espacio por quedar huecos intermedios cada vez que se actualiza el archivo.© A. · Se necesita espacio adicional para el área de índices. alozanoi@teleline. Programación en lenguajes estructurados.I. Inconvenientes.L. D.

Archivos en lenguaje C. es fopen() y cuya sintaxis es la siguiente: FILE *fopen(const char *Nombre_Fichero. unsigned istemp. Además. Esta información no es necesario conocerla porque las funciones de stdio. si se van a realizar sobre el fichero operaciones de entrada. Página: 129 7. independientemente de su organización y modo de acceso. de salida o ambas simultáneamente.es Apuntes de clase . La sentencia anterior define un flujo (stream) que posteriormente se asociará a un fichero externo. etc.I.L. char fd.Creación y apertura de un archivo. unsigned char *buffer.© A. short token. es decir. sin ninguna estructuración más. La estructura FILE contiene la información relativa al archivo. define el área de buffer para la descripción del fichero y para las transferencias de datos. FILE *alumnos.h se encargan de gestionarla. un fichero no es más que una serie ordenada de bytes.1.. Programación en lenguajes estructurados. La función usada para la creación y/o apertura de un archivo. const char *Modo_Apertura). short bsize. FILE <*Puntero_archivo>.A. posición a la que se está accediendo en ese momento. Un archivo en lenguaje C es una estructura de datos que se declara con la palabra reservada FILE.. En lenguaje C no existe la noción de registro. hay que recordar que la barra invertida de path (\) debe expresarse como dos caracteres (\\) para que no indique sólo el carácter de escape. } FILE. 7. *curp. como la localización. tipo de operación que se está realizando sobre el archivo. unsigned char hold. Opcionalmente puede contener el path con su ruta de acceso. La composición de la estructura y la declaración de un archivo son las siguientes: typedef struct { short level. en este caso. Se accede a ella mediante un puntero y las funciones almacenadas en la librería stdio. Modo_Apertura: Es una cadena que especifica el modo en que se abrirá el archivo. D. Los caracteres que indican dicho modo son los siguientes: alozanoi@teleline. Nombre_Fichero: Cadena de caracteres que especifica el nombre físico –externo.I. unsigned flags.h.del archivo de datos.

I. Existen varios stream predefinidos en C que se abren automáticamente al iniciar el programa. se crea uno nuevo.dat". }//Tratamiento del archivo. Abre el archivo para Lectura/Escritura por el comienzo. Salida estandar. si no se produce un error. Si se producen errores en el instante de abrir un archivo puede ser por alguna de estas situaciones: · · · · Si se supera el número máximo de archivos abiertos a la vez permitido por el sistema. Si no existía se crea uno nuevo. estos son: stdin stdout stderr stdaux stdprn Entrada estandar. Pantalla.dat". D. datos = fopen(archivo. Abre un archivo para escritura. Abre el archivo para escritura desde el final del mismo.(t) o en modo binario (b).es Apuntes de clase . No tener permiso para abrir el archivo.a+ -t b Ejemplos: FILE *datos. Página: 130 -r -w Abre el archivo para lectura. El archivo debe existir previamente.L. devolviendo un puntero a dicho canal. fclose(archivo). Salida estandar de errores. La función fopen() asigna un stream (canal por el que leer y escribir) y un buffer (memoria intermedia temporal) a un archivo. Son dos modificadores que pueden acompañar como sufijo a las seis modalidads anteriores con el fin de especificar si se trabaja en modo texto –dado por omisión. Si no existía se crea uno nuevo. se destruye el contenido del anterior. El nombre externo del archivo de datos es incorrecto.© A. } alozanoi@teleline. Pantalla. Si el archivo no existía. COM2. if (archivo == NULL) { puts("Error al abrir el archivo"). Intentar abrir un archivo que no existe usando los modos r o r+. #include <stdio.I. datos = fopen("c:\\trabajo\\lc\infor. El archivo debe existir previamente o se produce un error. datos = fopen(archivo. "r"). "wb"). y si existe. Periférico auxiliar estandar. Si no existe se crea. "w").dat". Programación en lenguajes estructurados. Impresora estandar.h> main() { FILE *archivo. para añadir.w+ .r+ .A. -a . Teclado. se destruye el contenido del anterior. y si existe. la función fopen() devuelve un puntero a NULL. char *archivo = "c:\\trabajo\\lc\infor. PRN. archivo = fopen("datos. exit(-1). Abre el archivo para Lectura/Escritura por el comienzo. "r"). En el caso de producirse un error. Abre el archivo para Lectura/Escritura por el final.

caracter). Macro.h> main() { FILE *archivo. int getc(FILE *fichero). archivo = fopen(nombre.I. int caracter.Lectura y escritura de caracteres. D. lee un carácter del archivo. // while (caracter !=EOF) // { printf("%c". "rt"). Programación en lenguajes estructurados.2. La función fputc() escribe un carácter en la posición actual de la cabeza de lectura/escritura avanzándola a la siguiente posición (la cabeza de E/S puede considerarse como el puntero). FILE *fichero). exit(1). int putc(int c. El formato general de estas dos funciones es el siguiente: Escritura de caracteres: int fputc(int c. Función Macro Función. char nombre[30].I.h> #include <conio. y avanza al siguiente carácter. gets(nombre). 7.A.© A.Cerrar archivo.L. if (!archivo) { puts("Error de apertura"). La función retorna el carácter escrito o EOF si se ha producido algún error. Ejemplo: programa que visualiza un archivo de texto. // carácter = (int)fgetc(archivo). El lenguaje C dispone de la función fputc() para escribir caracteres en un archivo y de la función fgetc() para leerlos del mismo.. Cuando finaliza el tratamiento del archivo es preciso cerrarlo. caracter).3.h> #include <stdlib. Página: 131 7. } alozanoi@teleline.es Apuntes de clase . Retorna un 0 si el archivo se cierra satisfactoriamente y EOF si se produce algún error. Lectura de caracteres: int fgetc(FILE *fichero). entre otras razones para actualizar su contenido y la tabla de asignación de archivos. // } while ((caracter = fgetc(archivo))!=EOF) printf("%c".. el situado en la posición actual de la cabeza de E/S. La función fgetc() realiza la operación inversa a fputc(). FILE *fichero). puts("Nombre del archivo a visualizar"). fclose(archivo). #include <stdio. } //carácter = (int)fgetc(archivo). La función que realiza esta operación es la siguiente: int fclose(FILE *Puntero_Archivo). Si se produce algún error retorna EOF.

Página: 132 Ejemplo: copiar un archivo de texto en otro carácter a carácter. FILE *p_archivo). if (!archivo) { printf("Error de apertura del archivo %s".4. fclose(salida).I. main(int argc. fclose(salida).h> FILE *abrir_archivo(char *nombre. char *modo) { FILE *archivo. #include <stdio. archivo = fopen(nombre. modo).I. entrada = abrir_archivo(argv[1]. nombre). salida = abrir_archivo(destino. "rt"). D. exit(1). fclose(entrada). int caracter. "wt").h> FILE *abrir_archivo(char *nombre. *salida. while ((caracter = fgetc(entrada)) !=EOF) fputc(caracter. } Ejemplo: igual que el anterior pero pasando los nombres de los ficheros como argumentos desde el S. #include <stdio. } 7.. char *argv[]) { FILE *entrada. Programación en lenguajes estructurados. while ((caracter = fgetc(entrada)) !=EOF) fputc(caracter. gets(destino). que retorna el último carácter escrito en el archivo si no se ha producido ningún error (un número no negativo) o EOF si se ha producido. puts("Nombre del archivo destino").h> #include <conio.es Apuntes de clase . sin escribir este en el archivo. "rt"). entrada = abrir_archivo(origen.L.h> #include <stdlib. FILE *p_archivo). "wt"). fclose(entrada).© A.h> #include <conio.O. main() { FILE *entrada. gets(origen). int longitud. int caracter. salida).h> #include <stdlib. char *modo). alozanoi@teleline. } return archivo. char *modo).Lectura y escritura de cadenas. La escritura de una cadena en un archivo se realiza con la función int fputs(const char *cadena. *salida. si se necesita debemos especificarlo. el carácter de fin de línea tampoco se escribe en el archivo . salida). salida = abrir_archivo(argv[2]. puts("Nombre del archivo origen"). La lectura de una cadena de un archivo se realiza con la función char *fgets(char *cadena. } FILE *abrir_archivo(char *nombre. destino[30].A. Disponemos de dos funciones para realizar las operaciones de entrada/salida de cadenas. char origen[30]. La copia de la cadena se realiza desde el principio de la misma hasta el carácter nulo.

char cadena[256]. Programación en lenguajes estructurados. . "%*s")) != EOF) contador++. Leer un texto por teclado y escribirlo en un fichero de texto. argumentos. char *modo).h> #include <stdlib.I. 7.I. fscanf() retorna el número de argumentos que se han leído o 0 si no se ha leído ninguno. int fscanf(FILE *p_archivo. fclose(entrada).5. 2.A.© A. } Ejercicios: 1. if (argc != 3) { puts("Faltan argumentos"). D. "r"). fscanf() lee del fichero las variables de la lista con el formato especificado. Página: 133 que retorna una cadena de caracteres si la lectura ha sido correcta o NULL si se ha producido algún error. pero estas realizan la entrada/salida por stdin y stdout. const char *formato[.h> #include <conio. Contar el número de veces que aparecen en un archivo de texto cada uno de los caracteres ASCII. alozanoi@teleline. Ejemplo: contar las palabras almacenadas en un archivo de texto. Esta operación se realizará con el formato especificado en los argumentos de las funciones... while ((fgets(cadena. Por su parte. Estas funciones son equivalentes a gets() y puts(). printf("Numero de palabras: %d". Ejemplo : Copiar un fichero de texto. main(int argc.L. const char *formato[. fclose(salida). salida).Entrada y salida con formato. fprintf() escribe la lista de elementos especificada en el formato indicado. exit(1).]).]). #include <stdio. contador).h> FILE *abrir_archivo(char *nombre. entrada)) !=NULL) fputs(cadena. direcciones. "w"). si se ha intentado leer más allá del fin de fichero retorna EOF.es Apuntes de clase .. salida = abrir_archivo(argv[2]. La sintaxis de estas funciones es la siguiente: int fprintf(FILE *p_archivo. . Existen dos funciones semejantes a scanf() y printf() para realizar una entrada/salida en archivos de texto.1 caracteres o hasta que encuentra carácter de fin de línea (leyéndolo y añadiéndolo) y posteriormente añade el carácter nulo a la cadena. Lee LONGITUD .. } entrada = abrir_archivo(argv[1]. *salida. char *argv[]) { FILE *entrada. while ((fscanf(entrada. 256. fprinf() retorna el número de bytes escritos o EOF..

NALUM 10 NOTAS 3 struct char nombre[30]. Programación en lenguajes estructurados.notas[j]). alumno). printf("Nombre: "). "\n"). void escribe_alumno(ALUMNO). escribe_alumno(salida. // fgets(a->Nombre. i++) { leer_alumno(entrada.j++) fscanf(f. } void leer_alumno(FILE *f. int notas[NOTAS]. FILE *abrir_archivo(char *.© A. for (j=0. a.notas[j]). for (i=0.nombre). fprintf(salida. main() { FILE *salida.txt". Página: 134 Ejemplo: leer el nombre y tres notas del alumnos y escribirlos en un archivo. j<NOTAS. for (i=0. ALUMNO a) { int j. char *).es Apuntes de clase . FILE *abrir_archivo(char *. "w"). j<NOTAS. } void leer_alumno(ALUMNO *a) { int j. int i. } fclose(salida).txt". i<NALUM. &a->notas[j]). } fclose(entrada).j++) { printf("Nota %d: ". ALUMNO *a) { int j. char *). &alumno). fflush(stdin).I.nombre). a. a. void leer_alumno(FILE *. void leer_alumno(ALUMNO *). D. i++) { leer_alumno(&alumno). i<NALUM. ALUMNO alumno. 30. void escribe_alumno(FILE *. "%-30s". for (j=0. entrada = abrir_archivo("c:\\trabajo\\alumno. for (j=0. escribe_alumno(alumno). f). &a->notas[j]). } alozanoi@teleline. } #define #define typedef { Ejemplo: Leerlo y visualizarlo. fprintf(salida.j++) fprintf(salida. for (j=0. j<NOTAS. j). "%30s". ALUMNO *). } void escribe_alumno(ALUMNO a) { int j. } } void escribe_alumno(FILE *salida. salida = abrir_archivo("c:\\trabajo\\alumno. a. main() { FILE *entrada. int i. } ALUMNO. printf("\n"). ALUMNO). fscanf(f. j<NOTAS.j++) printf("%d\t". "r"). gets(a->nombre). printf("%-30s".A.L. ALUMNO alumno. "%d\t". fflush(stdin). a->nombre).I. "%d". scanf("%d".

1. tipo de datos definido en stdio. size_t nu_b. para detectar el final del fichero es necesario realizar una lectura del fichero.6. void escribe_alumno(FILE *salida. Tanto en la lectura como en la escritura. FILE *p_arch). Retorna el número de bloques leídos del fichero. salida). ALUMNO *a) { fread(a. Hay dos funciones que tratan bloques de bytes independientemente de la información que contengan. alozanoi@teleline. El tamaño del bloque se calcula.L. El final de un archivo se detecta con la función feof() y cuyo formato es el siguiente: int feof(FILE *p_archivo). Programación en lenguajes estructurados. 1.7. Usar las funciones del ejercicio anterior.. Ejemplo: Crear y listar un archivo con el nombre y las notas de los alumnos. este valor nos permite conocer si se ha producido un error en la lectura.Detectar fin de fichero. El formato de la función de escritura es el siguiente: size_t fwrite(const void *p_bl. con la función sizeof().es Apuntes de clase . *p_bloque: tam_b: num_b: *p_arch: t_size: puntero a la zona de memoria donde se realizará la transferencia de E/S. sizeof(*a). número de bloques que se tranferirán del/al archivo. de los dato almacenados. es decir. el número de bytes transferidos viene dado por “num_b * tam_b” (número de bloques a transferir multiplicado por el tamaño del bloque).I. La memoria donde se almacenarán los datos debe estar reservada. FILE *p_arch). f). puntero a archivo FILE.© A.A.I. ALUMNO a) { fwrite(&a. sizeof(a). Retorna el número de bloques escritos en el archivo. tamaño de cada bloque.Lectura y escritura de bloques de información. Página: 135 7. También pueden detectarse posible errores cometidos en la escritura.h (typedef unsigned size_t). Esta función detecta el final del archivo cuando se realiza una lectura después del último registro o byte. size_t num_b. La función fwrite realiza la acción contraria a fread(). así.. size_t ta_b. size_t tam_b. escribe un numero “num_b” de bloques de tamaño “tam_b” bytes tomados de la posición indicada por el puntero 'p_bloque' en el archivo 'p_arch'. } void leer_alumno(FILE *f. D. } 7. como siempre. El formato de la función de lectura es el siguiente: size_t fread(void *p_bloque. La función fread() lee un número “num_b” de bloques de tamaño “tam_b” bytes del archivo 'p_arch' y lo almacena en la posición indicada por el puntero 'p_bloque'.

salida). f). long desplazamiento. &alumno).© A. sizeof(ALUMNO)*(posicion-1).I. desplaza: Retorna un 0 si el puntero se ha posicionado correctamente en el fichero y otro valor si se ha producido algún error. caracter = getc(entrada). SEEK_CURT 1 : Desplazamiento desde la posición actual. SEEK_END 2 : Desplazamiento desde el final del fichero. &alumno). &p). Es una constante simbólica definida stdio. p)) escribe_alumno(alumno). Retorna 0 si no es el final del fichero o un valor distindo si estamos en el final del mismo. fseek() puede usarse en múltiplos del tamaño de cualquier dato para recorrer el archivo o acceder a un registro concreto. int fseek(FILE *p_archivo. sizeof(tipo_dato) * posicion_relativa_registro scanf("%ld". sizeof(*a). long posicion) { fseek(f. D. } Ejemplo: recorrido secuencial del archivo: leer_alumno(entrada.8. Número de bytes a partir de la posición seleccionada (origen) que queremos que se desplace la cabeza de E/S.h y que tiene tres valores posibles: SEEK_SET 0 : Desplazamiento desde principio del fichero. else puts("No está").L. while (!feof(entrada)) { putc(caracter. } 7. Para realizar estas tres acciones se dispone de la función fseek(). } do { alozanoi@teleline. Básicamente se pueden realizar tres tipos de desplazamiento dentro del fichero: desplazamiento al principio del fichero. SEEK_SET). if (p>0) { if(leer_alumno(entrada. Ejemplo: copiar archivo: caracter = getc(entrada). leer_alumno(entrada. } }while (p>0). while (!feof(entrada)) { escribe_alumno(alumno). La función (MACRO) puede usarse con archivos binarios y archivos de texto.Posicionamiento en el fichero: e/s de acceso directo. 1. Puede ser tanto positivo como negativo. ALUMNO *a. &alumno. Página: 136 no basta con abrirlo. int origen). Programación en lenguajes estructurados..I. al final del fichero y a una posición concreta dentro del fichero. origen: Posición relativa desde donde se desea comenzar el desplazamiento.es Apuntes de clase . return !feof(f).A. fread(a. int leer_alumno(FILE *f.

12. · Cambiar el archivo de nombre externo. este valor puede ser usado posteriormente por la función fseek(). } 7.Reasignación de archivo. reapertura. void clearerr(FILE *p_archivo).9. long numero_registros(FILE *f.es Apuntes de clase ..I.I. 7. Retorna el número de bytes desde el comienzo del archivo.Posición actual de la cabeza de E/S. (-1 error) long int ftell(FILE *p_archivo).. Ejemplo: numero de registros de un fichero. 0. El EOF (error) persite hasta que se ejecuta una de estas funciones: clearerr().Vaciar el buffer.© A. return ftell(f) / sizeof(a). La función freopen() tiene tres formas de uso: · Abrir un archivo en un modo diferente del que se abrió inicialmente. int ferror(FILE *p_archivo). Página: 137 7. 7. Vacía el buffer del archivo correspondiente. Programación en lenguajes estructurados. void rewind(FILE *p_archivo). se dispone de la función (MACRO) ferror().A. alozanoi@teleline. SEEK_END). 7. D. ALUMNO a) { fseek(f.. Puede ser usado para prevenir el intento de posicionamiento más allá del final del fichero.. La función ftell() indica la posición actual de la cabeza de E/S en el archivo.10. Es equivalente a fseek(f. · Redireccionar un fichero estandar a otro externo. Retorna != 0 si hay error. 0.L.11. Retorna 0 o EOF si se detecta algún error. Para detectar si se ha producido algún error en el archivo durante una lectura o escritura. La función rewind() rebobina la cabeza de E/S al comienzo del archivo.. SEEK_SET). rewind() o fclose().13.Detección de errores. int fflush(FILE *p_archivo).Desplazamiento al comienzo del archivo.

nuevo) == 0) printf("Renombrado. void perror(const char *cadena). No existe el fichero o directorio. if (rename(viejo.15. int remove(const char *f_externo).\n").. //Rename: descripción del error 7.es Apuntes de clase . FILE *p_archivo). int rename(const char *actual.© A. const char *nuevo). D. Ya existe o path inválido.I. puede invocarse a la función perror() para que visualice cual es el error cometido. 7. No es el mismo periférico. Borra un archivo cerrado. alozanoi@teleline. Retorno: 0 EACCES ENOENT ENOTSAM Correcto. Cambia el nombre de un archivo o directorio. else perror("Rename").Cambiar el nombre de un archivo.A. Retorna un NULL si se ha producido algún error.L.14. Programación en lenguajes estructurados. const char *modo. Página: 138 FILE *freopen(const char *f_externo.I.. Permiso denegado. Retorna: 0 EACCES ENOENT Correcto Permission denied No such file or directory Cuando las funciones rename() o remove() retornan un error.Borrar un archivo.

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 139

8.- Búsqueda en archivos.
En archivos secuenciales, la lectura de un registro para consulta, modificación o supresión va precedida necesariamente de la búsqueda del mismo. La situación es análoga a la anterior, para los archivo directos y los secuenciales indexados, cuando se desconoce la posición del registro dentro del archivo o cuando se desea acceder a un registro por un campo que no es clave. Se usa un algoritmo de búsqueda cuando se desea obtener el contenido de un registro de un archivo, a partir de uno de sus campos o subcampos, que denominaremos clave de búsqueda. Los algoritmos consisten en un recorrido lineal del archivo, variando la condición de finalización según si el archivo está ordenado o no por la clave de búsqueda. La lógica de búsqueda de los algoritmos es válida para cualquier lenguaje de programación, aunque, según en que instante se detecte el final del archivo, tendremos que variar la condición de terminación del bucle y el lugar en que se realiza la lectura del archivo.

8.1.- Búsqueda en archivos desordenados.
Se recorre el archivo desde el primer registro hasta encontrar aquel cuyo valor de su campo clave coincide con el buscado o se acabe el archivo. Si existen varios registros con el mismo valor clave, se obtendrá el primero de ellos. Sea un archivo F, cuyos registros R contienen un campo C, que es la clave de búsqueda, y un valor X a buscar en C.
void Buscar(FILE *F, CLAVE X) { REGISTRO R; int Hallado = 0; fseek(F,0, SEEK_SET); // o bien abrir el archivo, rewind(F) fread(&R, sizeof(REGISTRO), 1, F); while (!Hallado && !feof(F)) { if (X == R.C) Hallado = 1; else fread(&R, sizeof(REGISTRO), 1, F); } if (hallado) Tratar(R); else Indicar que no se encuentra en el archivo; }

Si se desea realizar el mismo tratamiento para todos los registros que tienen el mismo valor de campo clave sólo hay que suprimir el interruptor 'Hallado' de la condición de terminación del bucle y realizarlo dentro del cuerpo del bucle.

8.2.- Búsqueda en archivos ordenados.
El algoritmo anterior es válido para archivos ordenados; no obstante conviene usar la ordenación para optimizar el tiempo de ejecución, ampliando la condición de terminación de búsqueda al caso de sobrepasar el valor de la clave buscada. Algoritmo que busca el primer registro que cumple la condición. Este algoritmo podría dar algún problema; conviene usar el interruptor.

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 140

void Buscar(FILE *F, CLAVE X) { REGISTRO R; fseek(F,0, SEEK_SET); // o bien abrir el archivo, rewind(F) fread(&R, sizeof(REGISTRO), 1, F); while (!feof(F) && X > R.C) fread(&R, sizeof(REGISTRO), 1, F); if (X == R.C) // Si ff y no encontrado. ¿Valor de R.C.? Tratar(R); else Indicar que no se encuentra en el archivo; }

Algoritmo que busca el todos los registros que cumplen la condición.
void Buscar(FILE *F, CLAVE X) { REGISTRO R; int Hallado = 0; fseek(F,0, SEEK_SET); // o bien abrir el archivo, rewind(F) fread(&R, sizeof(REGISTRO), 1, F); while (!feof(F) && X >= R.C) { if (X == R.C) { Hallado = 1; Tratar(R); } fread(&R, sizeof(REGISTRO), 1, F); } if (!Hallado) Indicar que no se encuentra en el archivo; }

9.- Partición de archivos.
La partición de un archivo consiste en repartir los registros del mismo en dos o más, dependiendo de una determinada condición dada por uno o más campos del registro.

9.1.- Partición por contenido.
Sea el archivo F, que se desea dividir en dos, F1 y F2, copiando en el primero los registros de F que contienen en el campo C el valor X, y en el segundo los demás.
FICHERO F; FICHERO F1; FICHERO F2; REGISTRO R; CLAVE X; F = fopen(F_EXTERNO, "rb"); F1 = fopen(F_EXTERNO1, "wb"); F2 = fopen(F_EXTERNO2, "wb"); fread(&R, sizeof(REGISTRO), 1, F); while (!feof(F)) { if (X == R.C) fwrite(&R, sizeof(REGISTRO), 1, F1); else fwrite(&R, sizeof(REGISTRO), 1, F2); fread(&R, sizeof(REGISTRO), 1, F); } fclose(F); fclose(F1); fclose(F2);

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 141

9.2.- Partición en secuencias.
Los registros se distribuyen en secuencias alternativas, de igual o diferente longitud según los casos. Sea el archivo F, que se desea dividir en dos, F1 y F2, copiando en el primero los registros de F que ocupan posiciones impares, y en el segundo los que ocupan posiciones pares (longitud de secuencia 1).
int SW = -1 ... fread(&R, sizeof(REGISTRO), 1, F); while (!feof(F)) { SW = -SW; if (SW==1) fwrite(&R, sizeof(REGISTRO), 1, F1); else fwrite(&R, sizeof(REGISTRO), 1, F2); fread(&R, sizeof(REGISTRO), 1, F); }

Sea el archivo F, que se desea dividir en dos, F1 y F2, copiando alternativamente en uno y otro secuencias de registros de longitud N.
int SW = 1; int C = 0; ... fread(&R, sizeof(REGISTRO), 1, F); while (!feof(F)) { if (SW) fwrite(&R, sizeof(REGISTRO), 1, F1); else fwrite(&R, sizeof(REGISTRO), 1, F2); fread(&R, sizeof(REGISTRO), 1, F); if(N == ++C) { SW = -SW; C = 0; } }

Función para copiar una secuencia de N registros.
void copiar_secuencia(FILE *temporal, FILE *fichero, int longitud) { REGISTRO R; fread(&R, sizeof(REGISTRO), 1, temporal); while (longitud > 0 && !feof(temporal)) { fwrite(&R, sizeof(REGISTRO), 1, fichero); if(--longitud) fread(&R, sizeof(REGISTRO), 1, temporal); } } main() { ... // Declaraciones int N = 4; ... // Aperturas while (!feof(F)) { copiar_secuencia(F, F1, N); if (!feof(F)) copiar_secuencia(F, F2, N); } }

Ejercicio: Una compañía organiza una encuesta para determinar el éxito de sus productos musicales. La población encuestada se va a dividir en cuatro categorías según sexo y edad (por ejemplo menores o iguales a veinte años y mayores de veinte años). A cada persona se le pide que dé el nombre de cinco éxitos según su orden de preferencia. Los éxitos se identifican por los números de

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 142

1 a N. Los resultados se almacenan en un fichero, donde cada elemento del fichero representa a un encuestado que incluye los datos de su nombre y apellidos, además de los mencionados anteriormente. · Crear el archivo con los datos de las encuestas. · Listar los éxitos en orden de popularidad. Para cada uno se lista el número del éxito y el número de veces que ha sido mencionado. · Obtener cuatro archivos de texto con las listas de los nombres y apellidos de todos los encuestados, según su categoría, que habían mencionado en primer lugar uno de los tres éxitos más populares.

10.- Mezcla de archivos.
Es la operación contraria a la partición. La mezcla de archivos consiste en reunir en un único archivo los registros de dos o más archivos, manteniendo el posible orden que hubiese establecido. Los algoritmos de mezcla sobre archivos ordenados ascendentemente, se realizan por el valor de un campo clave.

10.1.- Mezcla de archivos desordenados.
Una mezcla de archivos desordenados consiste en intercalar secuencias de registros de una determinada longitud alternativamente en el archivo destino. Los algoritmos para hacerlo son los inversos a los de la partición.
void copiar_secuencia(FILE *temporal, FILE *fichero, int longitud) { REGISTRO R; fread(&R, sizeof(REGISTRO), 1, temporal); while (longitud > 0 && !feof(temporal)) { fwrite(&R, sizeof(REGISTRO), 1, fichero); if(--longitud) fread(&R, sizeof(REGISTRO), 1, temporal); } } main() { ... // Declaraciones int N = 4; F = fopen(F_EXTERNO, "w"); F1 = fopen(F_EXTERNO1, "r"); F2 = fopen(F_EXTERNO2, "r"); while (!feof(F1) || !feof(F2)) { if(!feof(F1)) copiar_secuencia(F1, F, N); if(!feof(F2)) copiar_secuencia(F2, F, N); } fclose(F); fclose(F1); fclose(F2); }

10.2.- Mezcla de archivos ordenados.
Sean dos archivos F1 y F2, con registros de igual estructura y ordenados ascendentemente por el campo clave C. Se desea obtener el archivo F ordenado por el mismo campo que contenga los registros de ambos. El algoritmo consiste en el recorrido simultáneo de F1 y F2, copiando el registro menor de ellos en F y avanzando en el archivo correspondiente. Se controla el final de los archivos comprobando el final del fichero. A la salida del bucle de fusión, uno de los dos archivos no habrá sido copiado en su totalidad, por lo que es necesario copiarlo en F.

alozanoi@teleline.es

Apuntes de clase

} void copiar_resto(FILE *temporal. fclose(F2). fclose(F).L.h> #include <stdlib. sizeof(NUME). 93. 13. y la fusión correspondiente produce sobre el archivo inicial secuencias ordenadas de longitud 2. 64.Clasificación por mezcla directa. NUME R2. A cada nueva partición y fusión.txt" typedef struct { int C. sizeof(NUME). 1.1. 1. intersección de los dos anteriores. F = fopen(NO. fread(&R. temporal). F). F2). F. FILE *F1. sizeof(NUME). main() { FILE *F. El proceso finaliza cuando la longitud de la secuencia ordenada excede la longitud del archivo a ordenar. Programa que obtenga el archivo F. F1).h> #define NO "c:\\temporal\\numeros. fichero). } else { fwrite(&R2. D. F2). F). sizeof(R). F1 = fopen(NO1. 1.I. 11.A. R1). sizeof(NUME). } } Ejercicio: Se dispone de dos archivos secuenciales. F: F1: F2: 15. La primera partición se hace en secuencias de longitud 1. 51.es . NUME R) { while (!feof(temporal)) { fwrite(&R. sizeof(NUME). fread(&R1.txt" #define NO1 "c:\\temporal\\numeros1. "r"). se duplica la longitud de las secuencias ordenadas. Página: 143 #include <stdio. 40. sizeof(R). 75. 1. 1. que es único en cada archivo. NUME R). while (!feof(F1) && !feof(F2)) if(R1. ambos con los campos CLAVE alfanumérico RESTO DE CAMPOS Los archivos están ordenados ascendentemente por el campo CLAVE. Programación en lenguajes estructurados. 14. } NUME. sizeof(NUME). conteniendo los registros comunes una sola vez. 27. Se trata de la realización sucesiva de una partición y una mezcla que produce secuencias ordenadas de longitud cada vez mayor. fread(&R1. 18.© A.. } copiar_resto(F1. F. fread(&R2.C) { fwrite(&R1. "r"). void copiar_resto(FILE *desde. copiar_resto(F2. R2). NUME R1. FILE *hasta. 13 15 7 14 43 51 75 64 13 18 75 13 40 93 26 27 Apuntes de clase alozanoi@teleline. 11.. fclose(F1). 1.I. F2 = fopen(NO2. 43.txt" #define NO2 "c:\\temporal\\numeros2. 1. 1. existiendo registros comunes a uno y otro. FILE *fichero. 75. FILE *F2. F1).Clasificación de archivos. fread(&R2. "w").C < R2. 26. 7.

F2). SEEK_END). N1++. F1. Programación en lenguajes estructurados. partir(F. R2.int S) { REGISTRO R1. while(!feof(F1)) { N1 = N2 = 0. 27 64. F2 = fopen(NO2. sizeof(REGISTRO). F1 = fopen(NO1. F = fopen(NO.. while ((!feof(F1) && N1 < S) && (!feof(F2) && N2 < S)) if(R1. FILE *F2. "w"). 7 75. fclose(F1). 1. fread(&R2. F1. S *=2. 1. sizeof(REGISTRO). F2. F). F2 = freopen(NO2. N2. sizeof(REGISTRO). "r".I.A. F1). copiar_secuencia(F. int N1. fread(&R1. } } void partir(FILE *F. .. FILE *F1. Finaliza una de las dos. F2).L. F1. sizeof(REGISTRO). F). "r"). sizeof(REGISTRO). while(!feof(F1) && N1++ < S) { fwrite(&R1.txt" #define NO2 "c:\\temporal\\numeros2. void partir(FILE *F. FILE* F. FILE *F2. #include <stdio. F2.h> #define NO "c:\\temporal\\numeros.C < R2. N2++. 13 15 18 13 14 51 93 27 64 7 75 40 43 26 75 13 7 15 18 75. fclose(F2).© A. FILE *hasta.C) { fwrite(&R1.int S) { while (!feof(F)) { copiar_secuencia(F. 1. FILE *F1. F1).. FILE *F2. F2.txt" #define NO1 "c:\\temporal\\numeros1. fclose(F). mezclar(F. 1. F1.int S). F1 = freopen(NO1. F2. lon = ftell(F) / sizeof(REGISTRO). lon. "w"). sizeof(REGISTRO). 13 14 40 43. F1). F2). void copiar_secuencia(FILE *desde. "r". F).. 1. fread(&R1. F1). fread(&R2. "r").h> #include <stdlib. void mezclar(FILE *F. 1. 1. // Copia una secuencia. 13 14. while(S < lon) { F = fopen(NO. F). 26 75. D. S). 13 27 64 . S). F = freopen(NO. "w". S). 51 93. 40 43. } else { fwrite(&R2. fread(&R1. FILE *F1. 26 51 75 93.es Apuntes de clase . Página: 144 F: F1: F2: F: F1: F2: 15 18. 0. } } void mezclar(FILE *F. S).txt" typedef struct { int C. int S). } REGISTRO.. fclose(F). 1. fseek(F. sizeof(REGISTRO). sizeof(REGISTRO). } alozanoi@teleline. main() { int S = 1. FILE *F1. } // Copia el resto de una secuencia.I. FILE *F2. int).

F2: 7 13 14 15 18 40 43 51 75 75 93 F3: 13 26 27 64 Tercera fusión-partición. 40 51 93.I. while(!feof(F2) && N2++ < S) { fwrite(&R2. en la realización de la fusión-partición. 40. para la realización simultánea de fusión y partición. F). A Mes 1 Vendedor Juan Concha Producto . F2: 15 18. El archivo totalmente ordenado estará en el primero. F: F1: 15.A. junto con el original... El proceso termina cuando. D. fread(&R2. 13 F3: 7 75. sizeof(REGISTRO). porque varía el valor de alguno de los campos.. Es una optimización del anterior. 51.. Utiliza tres archivos auxiliares. . 27. .Clasificación por mezcla equilibrada.I. 26 27 64 F1: 13 14 40 43 51 75 93. dos o más secuencias ascendentes. lo que hace que la siguiente partición quede realizada.. 75. que estén consecutivas. TOTAL . F: 7 15 18 75. sizeof(REGISTRO). 64.L.. 27 Primera fusión-partición. 75. F2).2. Página: 145 // Copia el resto de otra secuencia.Rupturas de control.. pueden constituir una única secuencia para el paso siguiente. 13.. Apuntes de clase alozanoi@teleline.. 13 43. el segundo archivo queda vacío. . 43. 13 Partición inicial. 18. Ventas V. La ruptura de control en la generación de listados consiste en la modificación de la línea de detalle del informe debido a que los datos dejan de estar relacionados entre sí.es . 13 Segunda fusión-partición.. Consiste en realizar la partición tomando las secuencias ordenadas de máxima longitud posible y realizando la fusión de secuencias ordenadas alternativamente sobre dos archivos. Durante el proceso de fusión-partición.. 75. 1. F: 7 13 13 14 15 18 26 27 40 43 51 64 75 75 93 F1: 12. Es necesario que el fichero esté ordenado por el/los campo/s que producen la ruptura de control.© A. 26. 7.. 1. 14. } } } 11. Ejemplo: si se listan las ventas realizadas de unos grandes almacenes: Dpto. 14. T. Programación en lenguajes estructurados. 93. 26 64.

.L. DEP.. ... .. fread(&R. sizeof(R).© A. Página: 146 2 Juan Concha . ..RCN) { TRATAR R fread(&R. dentro de éste por Mes y dentro de éste por Vendedor... F)..es Apuntes de clase . TOT.. ..I.. . . while (! feof(F)) { auxRC_1 = R.. 1. ......I. D..RC1.. F). } // Operaciones tras ruptura de control .. .RC1 &&.. sizeof(R)...... .. .RC1) { auxRC2 = R....&& auxRCN==R. . . 1. Programación en lenguajes estructurados... // Otras inicializaciones . . } // Operaciones tras ruptura de control } // Operaciones tras ruptura de control alozanoi@teleline.... while(!feof(F) && auxRC1==R.A.... ....RC2. . VENTAS TOTALES Se produce una ruptura de control por Departamento. // Otras inicializaciones while(!feof(F) && auxRC1 == R....... B 1 2 Julio Nieves Julio Nieves . .

}ARTICULOS.h> #include <conio. Programación en lenguajes estructurados. fflush(stdin). int i.h> #define NARTICULOS 5 #define EX_ARTICULO "C:\\TRABAJO\\ARTICULO. D. f_articulo). i<NARTICULOS. d) Listar las ventas (en cantidad y pesetas) de los artículos. fflush(stdin). CREACIÓN DEL ARCHIVO ARTICULO // Suponemos un único registro.precio[i]). } // Ventas de artículos. "w"). CREACIÓN DEL ARCHIVO ARTICULO // Suponemos un único registro. gets(s_articulo. // Ventas de artículos. Página: 147 Práctica 1: Las ventas de artículos de una determinada cadena de almacenes se encuentran almacenadas en un fichero. 1. printf("Precio: ").I.FIC" typedef struct { char descripcion[NARTICULOS][30]. &s_articulo.descripcion[i]).precio[i]). 1. fwrite(&s_articulo. De pide: a) Programa que cree el fichero de artículos. fclose(f_articulo).h> #include <stdlib.L.h> #define NARTICULOS 5 #define EX_ARTICULO "C:\\TRABAJO\\ARTICULO.descripcion[i]). scanf("%d".© A. int precio[NARTICULOS]. printf("Precio: "). ARTICULOS s_articulo. que contiene las ventas de un determinado almacén de la cadena. sizeof(s_articulo). sizeof(s_articulo). que contiene uno o más registros. i++) { printf("Descripción del artículo: "). gets(s_articulo. } f_articulo = fopen(EX_ARTICULO. #include <stdio. scanf("%d". b) Programa que cree el fichero de ventas. i<NARTICULOS. fwrite(&s_articulo. main() { FILE *f_articulo. int i. int precio[NARTICULOS]. for (i=0. }ARTICULOS.I.FIC" typedef struct { char descripcion[NARTICULOS][30]. for (i=0. fflush(stdin). fflush(stdin). en otro fichero.A.h> #include <stdlib. ARTICULOS s_articulo. i++) { printf("Descripción del artículo: "). fclose(f_articulo).h> #include <conio. &s_articulo. "w").es Apuntes de clase . se almacena el nombre de cada artículo y su precio. tiene la siguiente estructura: REGISTRO almacen Codigo ES CADENA DE 5 Ventas_articulos ES ARRAY DE 5 ENTEROS FIN_REGISTRO Por otra parte. de tal forma que cada registro. c) Listado del total de ventas de cada almacen (en pesetas). #include <stdio. } f_articulo = fopen(EX_ARTICULO. f_articulo). } alozanoi@teleline. main() { FILE *f_articulo.

fflush(stdin). for (i=0.h> <conio. Programación en lenguajes estructurados. scanf("%d". seguir=getchar(). sizeof(s_almacen). fclose(f_almacen). fflush(stdin).ventas[i]).I. fclose(f_articulo). sizeof(s_articulo). CREACIÓN DEL ARCHIVO ALMACEN #include #include #include #include #define #define #define typedef { <stdio. int ventas[NARTICULOS]. if(toupper(seguir)=='S') { printf("Código de almacen: "). int i.h> <ctype.I. i<NARTICULOS. }while(toupper(seguir)!='S' && toupper(seguir)!='N').h> <stdlib. typedef struct { char descripcion[NARTICULOS][30].© A. f_almacen = fopen(EX_ALMACEN. int precio[NARTICULOS]. 1. do { do { printf("Entrar almacen(s/n)"). } }while(toupper(seguir)=='S').A. &s_almacen. f_almacen).codigo). f_articulo = fopen(EX_ARTICULO.es Apuntes de clase . FILE *f_almacen. gets(s_almacen. 1. ALMACEN s_almacen. s_articulo. }ARTICULOS. "w"). i++) { printf("Ventas %s: ".h> NARTICULOS 5 EX_ALMACEN "C:\\TRABAJO\\ALMACEN. }ALMACEN. "r").descripcion[i]). fflush(stdin).FIC" EX_ARTICULO "C:\\TRABAJO\\ARTICULO. Página: 148 // Ventas de artículos. f_articulo). } fwrite(&s_almacen. seguir. fread(&s_articulo.L. } alozanoi@teleline. main() { FILE *f_articulo. D.FIC" struct char codigo[5]. ARTICULOS s_articulo.

© A. "r").L. void acumula(int *. LISTADOS #include #include #include #include <stdio. void lista_articulos(ARTICULOS articulo. i. lista_articulos(s_articulo. printf("%-10s %d\n". sizeof(s_almacen). for (i=0. acumula(s_almacen. Página: 149 // Ventas de artículos. i++) printf("%-30s%10d%10d%10d\n". int precio[NARTICULOS].A.i<NARTICULOS.ventas. total). for (i=0. f_articulo).ventas[i] * articulo. int ventas[NARTICULOS].total[i]*articulo.precio[i]. articulo. } } fclose(f_almacen). } void acumula(int *venta. if (!feof(f_almacen)) { lista_almacenes(s_almacen. ARTICULOS). fread(&s_articulo. s_articulo). total=0. void lista_almacenes(ALMACEN. Programación en lenguajes estructurados. while (!feof(f_almacen)) { fread(&s_almacen. ARTICULOS s_articulo. ventas_articulos). f_almacen).es Apuntes de clase . ALMACEN s_almacen. int *total) { int i.FIC" #define NARTICULOS #define EX_ALMACEN #define EX_ARTICULO typedef struct { char codigo[5]. int *total) { int i.precio[i]).FIC" "C:\\TRABAJO\\ARTICULO. f_almacen = fopen(EX_ALMACEN. }ALMACEN. sizeof(s_articulo).h> <conio. } void lista_almacenes(ALMACEN almacen. i++) total[i] += venta[i].I. int ventas_articulos[NARTICULOS]. i<NARTICULOS.codigo. i<NARTICULOS. total[i]. almacen.h> <ctype. for(i=0. i++) ventas_articulos[i]=0. "r"). f_articulo = fopen(EX_ARTICULO. ARTICULOS articulo) { int i.h> <stdlib.descripcion[i]. D. fclose(f_articulo). i++) total += almacen. }ARTICULOS.articulo.precio[i]. i<NARTICULOS. int *).h> 5 "C:\\TRABAJO\\ALMACEN. main() { FILE *f_almacen. for(i=0. ventas_articulos). int *). } void lista_articulos(ARTICULOS articulo. FILE *f_articulo. } alozanoi@teleline.I. typedef struct { char descripcion[NARTICULOS][30]. 1. 1.

Programación en lenguajes estructurados.I.FIC" EX_FINAL "C:\\TRABAJO\\FINAL. MOVIMIENTO s_movimiento. ALMACEN mover. f_movimiento = fopen(EX_MOVIMIENTO. int i.s_almacen. sizeof(ALMACEN). EX_ALMACEN). } fclose(f_almacen). 1.codigo. }ALMACEN. main() { FILE *f_movimiento. ALMACEN s_almacen.mover. 1.ventas[i]. 1. 1. "r"). i<NARTICULOS. } while (!feof(f_almacen)) { fwrite(&s_almacen.mover.accion) { case 'M': for (i=0. fread(&s_almacen. sizeof(ALMACEN).codigo)==0) switch (s_movimiento.codigo.mover.FIC" struct char codigo[5]. sizeof(ALMACEN). f_errores. i++) s_movimiento. 1. fclose(f_movimiento). //rename(EX_FINAL. break. D. f_almacen). f_almacen).© A. fclose(f_errores).mover. f_almacen = fopen(EX_ALMACEN. } alozanoi@teleline. f_almacen). f_final = fopen(EX_FINAL.L. fread(&s_almacen. f_final). } else if (s_movimiento.A. f_errores). 1. while (fread(&s_movimiento. // Escribe en errores pero también el registro de almacén break. 1. f_almacen. f_final).FIC" EX_ERROR "C:\\TRABAJO\\ERRORES. 1. } if(strcmp(s_movimiento. 1. int ventas[NARTICULOS]. //remove(EX_ALMACEN).ventas[i]+= s_almacen. f_errores = fopen(EX_ERROR. sizeof(MOVIMIENTO). case 'B': fread(&s_almacen. "w").mover. sizeof(ALMACEN). default: fwrite(&s_movimiento.FIC" EX_MOVIMIENTO "C:\\TRABAJO\\MOVIMIE. fwrite(&s_movimiento. fread(&s_almacen. f_movimiento)) { while(!feof(f_almacen)&& strcmp(s_movimiento. ACTUALIZA EL ARCHIVO ALMACEN CON EL DE MOVIMIENTOS #define #define #define #define #define typedef { NARTICULOS 5 EX_ALMACEN "C:\\TRABAJO\\ALMACEN. f_final. f_final).es Apuntes de clase . Página: 150 // Ventas de artículos. "r"). sizeof(ALMACEN). fclose(f_final). sizeof(ALMACEN). sizeof(MOVIMIENTO).s_almacen. else fwrite(&s_movimiento. typedef struct { char accion. "w"). 1. f_final). sizeof(MOVIMIENTO). f_almacen). f_errores). 1. sizeof(ALMACEN).codigo)>0) { fwrite(&s_almacen.accion=='A') fwrite(&s_movimiento. }MOVIMIENTO.I. sizeof(ALMACEN).

printf("Ciudad :"). "w+"))==NULL) { printf("Error de apertura"). } int confirmar(char *texto) { int car.8). sizeof(ALUMNOS).9).gotoxy(40.gets(n).printf("%s". fflush(stdin).5).printf("Codigo Postal :").8).printf("Calle :").24).9). if (hallado) return (ftell(f)/sizeof(ALUMNOS)) ? 1. gotoxy(20.activo. } ALUMNOS. return (car == 'S').clreol(). gotoxy(25.gotoxy(40. gotoxy(40. gotoxy(40.8). modo))==NULL) if((fichero=fopen(f_externo.nombre.0.printf("Edad :"). 1.clreol().5).9). gotoxy(40. if (fread(&estudiante. gotoxy(20.gotoxy(40.calle). SEEK_SET). gotoxy(1. int registro) { ALUMNOS estudiante.L.delline().printf("%s". int hallado = 0.A.I.nombre).gets(estudiante?>cpostal). f)) hallado = (stricmp(estudiante.7). D.7). exit(1).texto). estudiante. } void leerdatos(ALUMNOS *estudiante) { fflush(stdin).6). } alozanoi@teleline.registro*sizeof(ALUMNOS). void dibujapantalla() { clrscr(). }while (car != 'S' && car != 'N'). char calle[20]. estudiante. } void visualizar(FILE *f.6).6).gotoxy(40. &estudiante?>edad). if ((fichero=fopen(f_externo. char *modo) { FILE *fichero. gotoxy(40. SEEK_SET).printf("%d".5).gotoxy(40.8).printf("%s ".7).cpostal). f) && estudiante.gets(estudiante?>ciudad). do { fflush(stdin). Página: 151 Práctica 2: MANTENIMIENTO DE UN ARCHIVO DIRECTO. while (!hallado && fread(&estudiante. estudiante.I. } } void leerclave(char *n) { reintroducir().5). gotoxy(40.printf("Nombre :"). gotoxy(40. } return (fichero). fflush(stdin). gotoxy(40. fflush(stdin).scanf("%d". estudiante?>activo = 1. estudiante. } void reintroducir() { gotoxy(40.printf("%s".printf("%s". fseek(f.7).clreol(). fflush(stdin).activo) { gotoxy(40. char cpostal[10]. gotoxy(40.24). gotoxy(20. FILE *f) { ALUMNOS estudiante.edad). else return (EOF). } int posicion(char *n. gotoxy(20. n)==0) && estudiante.clreol(). car = toupper(getchar()). } FILE *activar(char *f_externo. char activo. Programación en lenguajes estructurados. char ciudad[25].9).es Apuntes de clase . estudiante. int edad.© A. sizeof(ALUMNOS). 1. typedef struct { char nombre[40].6).clreol(). fseek(f.gets(estudiante?>calle).ciudad). gotoxy(20.

. dibujapantalla().??registro). } break. } break. clave). registro = posicion(clave. do { leerdatos(&estudiante). int registro) { ALUMNOS estudiante. break. }while (strchr("IBMRASF".registro).A.A?nterior. 1. f). } break. correcto = 1. F?in ". } } void cuerpo(FILE *f) { int opcion.I. registro*sizeof(ALUMNOS).nombre. } void borrar(FILE *f. case 'A': visualizar(f.delline(). correcto = 1. correcto = 0. } main() { FILE *archivo= activar("c:\\trabajo\\alumnos. else { menu="M?odificar. visualizar(f. do { leerclave(clave). R?int. fseek(f. }while (!confirmar("Es correcto (S/N)")). default: correcto = 1.es Apuntes de clase . } do { gotoxy(10. if (registro == EOF) menu = "I?nsertar. correcto = 1. break. int registro) { ALUMNOS estudiante.B?orrar. correcto = 1. } void modificar(FILE *f. char *clave) { ALUMNOS estudiante. opcion)==NULL).printf("%s".© A. do { fflush(stdin).24).24). *menu. cuerpo(archivo). S?iguiente. sizeof(ALUMNOS). }while (!confirmar("Es correcto (S/N)")).++registro). case 'B': if (registro != EOF) { borrar(f. registro). } }while(!correcto). //Incompleto case 'S': visualizar(f. switch (opcion) { case 'I': if (registro == EOF) { insertar(f. correcto.clave). if (confirmar("borrar el registro (S/N)")) { estudiante. registro).registro*sizeof(ALUMNOS). strcpy(estudiante. f). }while (opcion != 'F'). f). registro. strcpy(estudiante. "r+"). menu).f). F?in ". Página: 152 void insertar(FILE *f. fwrite(&estudiante.. } alozanoi@teleline. SEEK_END). fseek(f. clave). Programación en lenguajes estructurados. case 'M': if (registro != EOF) { modificar(f. 0.nombre.activo = 0. 1. do { leerdatos(&estudiante). SEEK_SET). fseek(f. char *clave. char clave[40].L. D.clave. break. fwrite(&estudiante. R?int. gotoxy(1. sizeof(ALUMNOS).ver". opcion = toupper(getchar()).//Incompleto case 'R': reintroducir().I. 1. SEEK_SET). sizeof(ALUMNOS). fwrite(&estudiante.

...© A. El fichero CATEGORÍA tiene la siguiente estructura de registro: TIPOCATEGORIA de tipo numérico entero DESCUENTO de tipo numérico entero DESCRIPCIÓN de tipo alfanumérico Hay 10 categorías.. Imprimir el número de personas que cumplen la condición de edad mayor que una determinada introducida por teclado y su sueldo neto sea mayor que una cantidad también introducida por teclado. Programación en lenguajes estructurados. Cada vez que se cambie de categoría o escribamos 55 líneas(registros).. Página: 153 Ejercicio: El fichero PERSONAL tiene la siguiente estructura de registro: NOMBRE de tipo alfanumérico EDAD de tipo numérico entero DIRECCIÓN de tipo alfanumérico SUELDOBRUTO de tipo numérico entero ESTADOCIVIL de tipo numérico entero CATEGORÍA de tipo alfanumérico El número de registros es el que necesite el usuario.. escribir la cabecera del listado e incrementar el número de página. número de empleados y sueldo bruto ordenado por número de empleados......... Teniendo en cuenta que el sueldo neto se calcula mediante la siguiente operación: SUELDONETO=SUEDOBRUTO-DESCUENTO..L....... alozanoi@teleline...... . . La categoría está comprendida entre A y J. ........ y en caso de ser iguales...... D. Listado de cobros de la categoría DESCRIPCIÓN NOMBRE EDAD DIRECCIÓN SUELDO NETO __________________________________________________________________ ........ .. ..1 ó 2.......I.. cuando se cambie de categoría escribir el sueldo neto total para la categoría. El descuento se extrae del fichero CATEGORÍA (el campo CATEGORÍA se corresponde con el campo TIPOCATEGORIA)....... Dados los ficheros anteriores y suponiendo PERSONAL ordenado en orden creciente de categoría y CATEGORÍA desordenado. SUELDO NETO TOTAL . de la A a la J.. dando un listado de la categoría... obtener un listado con el siguiente formato: Página: . .. así mismo. por sueldo bruto.... Los valores posibles del estado civil(EC) son 0....I... ........ Obtener el número de empleados y el sueldo bruto total de cada categoría. .....es Apuntes de clase .A.......

. Página: 154 entorno: PERSONAL es archivo de RPERSONAL RPERSONAL es registro compuesto de NOMBRE es de tipo alfanumérico EDAD es de tipo numérico entero DIRECCION es de tipo alfanumérico SUELDOBRUTO es de tipo numérico entero ESTADOCIVIL es de tipo numérico entero CATEGORIA es de tipo alfanumérico fin registro FCATEGORIA es archivo de RCATEGORIA RCATEGORIA es registro compuesto de TIPOCATEGORIA es de tipo alfanumérico DESCUENTO es de tipo numérico entero DESCRIPCION es de tipo alfanumérico fin registro SUELDONETO. 'y sueldo mayor a '. '.PAGINA son de tipo numérico entero AUXCAT es de tipo alfanumérico algoritmo: escribir 'EDAD MAYOR A :' escribir 'SUELDO MAYOR A :' leer MAYOREDAD. FCATEGORIA escribir 'Los empleados con edad mayor a '.NUMPER SUELDO' alozanoi@teleline.NETOTOAL.EDAD. DESCRIPCION escribir 'NOMBRE EDAD DIRECCION escribir '____________________________________' LINEA=0 mientras no ff(PERSONAL) y AUXCAT=CATEGORIA y LINEAS<=55 hacer LINEA=LINEA+1 SUELDONETO=SUELDOBRUTO-DESCUENTO NETOTOTAL=NETOTOTAL+SUELDONETO escribir NOMBRE.NR son de tipo numérico entero MAYOREDAD.DIRECCION.NETOTOTAL fin mientras cerrar PERSONAL.MAYORNETO.FCATEGORIA para lectura leer PERSONAL. D.RPERSONAL mientras no ff(PERSONAL) hacer NR=0 repetir NR=NR+1 leer FCATEGORIA.© A. MAYORNETO PAGINA=0 abrir PERSONAL..PAGINA escribir 'Listado de .' son '.RPERSONAL fin mientras fin mientras escribir 'NETO TOTAL..I.I.es Apuntes de clase ...RCATEGORIA. Programación en lenguajes estructurados. NETOTOTAL=0 mientras no ff(PERSONAL) y AUXCAT=CATEGORIA hacer PAGINA=PAGINA+1 escribir 'Página : '.SUELDONETO si EDAD>MAYOREDAD y SUELDONETO>MAYORNETO NUMPER=NUMPER+1 fin si leer PERSONAL.'..A.NR hasta TIPOCATEGORIA=CATEGORIA AUXCAT=CATEGORIA.MAYORNETO son de tipo numérico entero LINEA.L.MAYOREDAD.

I..DAT se guardan los datos personales de los clientes de un banco. cuyos formatos son: NCC donde: MOVIMIENTO MOVIMIENTO almacena la cantidad.. cada cliente tendrá de 0 a 5 movimientos. C) Ordenar ascendentemente por número de cuenta corriente el archivo de movimientos.es Apuntes de clase . cuyos campos son: NCC NOMBRE DIRECCIÓN POBLACIÓN PROVINCIA SALDO donde SALDO almacena la cantidad actual del cliente: puede ser un saldo deudor.Cero: imposición . D. También se dispone de otro fichero secuencial con los clientes que han tenido movimiento en sus cuentas corrientes. TIPO puede tomar los valores . cada cliente aparecerá en una hoja (pantalla) distinta con el siguiente formato: TIPO CUENTA CORRIENTE : NCC NOMBRE : DIRECCIÓN : POBLACIÓN : PROVINCIA : MOVIMIENTOS TIPO Tipo Tipo . Página: 155 PRÁCTICA: En el fichero secuencial CLIENTES.Uno: reintegro Hacer un programa para resolver los siguientes puntos: A) Crear el fichero de clientes con un mínimo de 25 registros. B) Crear el fichero de movimientos. D) Obtener un listado ordenado de clientes cuyas cuentas corrientes han tenido movimiento.L.A. Opcionalmente se ordenará también el fichero de clientes. Programación en lenguajes estructurados.I..© A.. SALDO CANTIDAD movimiento movimiento saldo(No modificar fichero) E) Obtener un listado ordenado de clientes con el saldo actual (éste se actualizará en el fichero de clientes) con el siguiente formato: NCC NOMBRE DIRECCIÓN POBLACIÓN PROVINCIA SALDO alozanoi@teleline.

.

I.Listas enlazadas.normalmente registros. Página: 157 15. Una lista enlazada es un conjunto de elementos. Programación en lenguajes estructurados.del siguiente elemento de la lista. Una estructura de datos dinámica es una colección de elementos denominados nodos de la estructura que son enlazados juntos. donde cada uno de ellos contiene la posición -dirección. las estructuras dinámicas se amplían o contraen durante la ejecución del programa basada en los registros de almacenamiento de datos del programa. si no que se basan en una implementación con variables de tipo puntero. y se utiliza para construir elementos de este tipo.es Apuntes de clase . por dos campos: la información propiamente dicha (valor del nodo) y un campo enlace que contiene la posición del siguiente nodo de la lista. que contiene un espacio para almacenar un número fijo de elementos. Una estructura de datos dinámica es una colección de elementos -nodos. Las estructuras dinámicas de datos crecen a medida que se ejecuta el programa. no físicamente. Los elementos de la lista se denominan nodos y deben estar formados.Introducción. En la práctica suelen darse casos en los que una estructura de datos puede crecer y/o disminuir sin conocer previamente la extensión o tamaño de los datos.. El mecanismo principal de esta asignación dinámica de memoria para almacenar ciertos elementos de una estructura es el puntero. si no que sea variable con el tiempo. Las estructuras de datos dinámicas se dividen en dos grupos: Listas enlazadas Pilas Colas Árboles Lineales No lineales Grafos 2. al menos. siendo necesario reservar la memoria suficiente para almacenar los datos.. Al contrario que un array. que es en sí una variable dinámica. Por tanto. Las estructuras estáticas necesitan un espacio de asignación de memoria fijo para almacenar los datos. no existen por sí mismas.I.ESTRUCTURAS DINÁMICAS LINEALES DE DATOS 1. lógicamente almacenados uno a continuación de otro. Información Enlace Representación gráfica de un nodo con dos campos LISTA Representación gráfica de una lista alozanoi@teleline. es lo que se conoce como asignación dinámica de memoria. D.A.L..© A. Por ello es necesario un mecanismo que no realice una asignación fija de memoria.

estructuras en las que uno de sus campos es un puntero (enlace) que referencia a la propia estructura.L. donde se almacena el siguiente nodo.Implementación. Una lista tiene las siguientes características: · · · El campo enlace de cada nodo apunta al siguiente nodo de la lista. //Uno o varios campos de datos. El resto de los nodos es accesible mediante el campo enlace que le precede. Un medio para detectar el último elemento de la lista: puntero nulo (NULL).I. //Declaración del nodo struct Nodo { Tinformacion Dato. .es Apuntes de clase . struct Nodo *Siguiente. El formato general para la declaración de una estructura de este tipo es el siguiente: struct <IdEstructura> { <tipo> <IdCampo>. Página: 158 6 4 3 9 Representación gráfica de los elementos de un array. Un puntero de cabecera que permite acceder al primer nodo de la lista..Uno o varios campos de información (los datos propiamente dichos).//Campo enlace }. Registro compuesto por al menos dos campos: . alozanoi@teleline. Una lista enlazada viene definida por los siguientes elementos: · · · El tipo de sus elementos. struct <IdEstructura> *<IdCampoEnlace>. D.I. es un puntero externo que guarda la dirección de memoria donde comienza la lista (primer nodo de la misma). Tinformacion. El primer nodo es apuntado por un puntero cabecera que indica el inicio de la lista. no apunta a nada. es decir.Uno o varios campos enlace (punteros) dependiendo del tipo de lista. cualquier lugar disponible. El campo enlace del último nodo se representa por la palabra NIL/NULL (nulo). }. typedef . typedef struct <IdEstructura> *<Identificador>. una barra inclinada (/) o el símbolo eléctrico de tierra o masa indicando que es el final de la lista. según el formato anterior. Y la componente de una lista. Para realizar la implementación del tipo lista enlazada es necesario usar estructuras autoreferenciadas o recursivas: el nodo contiene elementos de su misma categoría..© A. 2. o //una variable simple o una estructurada..A. quedaría implementada del siguiente modo: //Declaración del campo de información. Los nodos no se almacenan necesariamente en posiciones contiguas de memoria ya que el campo enlace es un puntero que guarda la dirección de memoria.1. Programación en lenguajes estructurados. es decir.

La inserción de un nodo en la lista consta de tres pasos: · · · Reservar dinámicamente la memoria necesaria para almacenar el nuevo nodo. 2. }. } 2. El orden de las operaciones de encadenamiento del nuevo nodo es el siguiente: alozanoi@teleline. Página: 159 y la lista completa sería un puntero a una estructura de este tipo: // Declaración de un tipo de dato del tipo estructura nodo. } 2.2. Todas las operaciones se basan en la estructura definida anteriormente. Este encadenamiento se realizará de diferentes maneras dependiendo del modo de inserción.I. para describir una lista de números enteros. typedef struct Nodo *TLista.//Variable cabecera de la lista.Operaciones básicas para la manipulación de listas.2.Lista vacía.es Apuntes de clase . un puntero vacío.. D.. se puede escribir lo siguiente: typedef int TInformación.Inicialización.3. Encadenar el nuevo nodo a la lista sin perder los enlaces existentes de los restantes nodos. Programación en lenguajes estructurados. ‘calloc()’ u otras que proporcione el lenguaje. Para hacerlo usamos la función ‘malloc()’.2. Asignar la información (los datos) al/los campo/s de datos de la estructura. main() { TLista LaLista.I.Añadir nodos a la lista.2.A.1.L. La variable cabecera se inicializa con el valor NULL. es decir se va a manipular una lista cuyo campo información es un entero.© A. typedef struct Nodo *Tlista. struct Nodo *Siguiente. bool EstaVacia(TLista Lista) { return Lista == NULL. Esta función indica si la lista contiene elementos o no.. void Inicializa(tlista *Lista) { *Lista= NULL. Por ejemplo. //Redefinición de un entero struct Nodo { TInformacion Dato. Esta crea una lista vacía.2.. } 2. Se pregunta por el puntero cabecera de lista.

1. Nuevo->Dato= Info. Si la lista está vacía. Inserción en una lista ordenada. debemos conocer la posición del nodo tras el que queremos insertar el nuevo alozanoi@teleline.// Nuevo apunta a inicio de la lista *Lista= Nuevo. La siguiente función inserta un nuevo nodo en la lista. Página: 160 a) Se encadena el nuevo nodo a los nodos existentes en la lista para no perder los enlaces ya establecidos. Nuevo->Siguiente= *Lista.. delante del primer nodo. Inserción en medio o al final de la lista.Insertar en medio o al final de la lista. Nuevo= (TLista) malloc(sizeof(Nodo)). Las formas de inserción de un nodo que vamos a ver son las siguientes: · · · Inserción al principio de la lista.A.I. Inserta un nodo detrás del nodo apuntado.L. Dato 1 Lista Lista vacía Nuevo Reserva de memoria Dato 1 Lista Primer elemento encadenado Representación gráfica de la inserción del primer elemento en una lista Dato 1 Dato 2 Dato 2 Dato 1 Lista Nuevo Reserva de memoria Lista Segundo elemento encadenado Representación gráfica de la inserción del segundo elemento en una lista void InsertaAlPrincipio(TLista *Lista. independientemente de que esté o no vacía.es Apuntes de clase .3.2. b) Se encadenan los nodos de la lista al nuevo nodo. la inserción es como la anterior..© A. por ello.2.I. Programación en lenguajes estructurados. Si la lista no está vacía.Insertar al principio de la lista.3. 2. TInformacion Info) { TLista Nuevo. el parámetro 'TLista *Lista' se pasa por puntero o referencia y se corresponde con el comienzo de la lista. // Nuevo pasa a ser cabecera de lista } Como estamos insertando al principio de la lista. 2. D.2. el nodo que se crea se convierte ahora en cabecera de la misma (el puntero cabecera de lista debe apuntar al nuevo nodo).

ésta.3. Dato 2 Dato3 Dato SEGUNDO PASO: Posicion->Enlace= Nuevo Dato 1 Lista Dato 2 Posicion Dato3 Dato Nuevo PRIMER PASO: Nuevo->Enlace= Posicion->Enlace Representación gráfica de la inserción de un nodo entre otros dos void InsertarEnMmedio(TLista *Lista.2. Nuevo->Dato= Info. (*Lista)->Siguiente= Nuevo. encadenar el nodo apuntado al nuevo “nodo(*Lista)->Siguiente= Nuevo”. si la información que queremos insertar el la mayor.I. La información que almacena el nodo devuelto tiene valor inferior o igual a la que queremos insertar. devuelve un puntero a: · · NULL.Inserción en una lista ordenada.. Nuevo->Siguiente= NULL. son: primero encadenar el nuevo nodo con el nodo siguiente al apuntado “Nuevo->Siguiente= (*Lista)->Siguiente” y. Una lista ordenada es aquella cuyos nodos están ordenados ascendente o descendentemente según el valor de uno o varios campos de datos del nodo.© A. por orden. si la lista está vacía o es la menor información almacenada en la lista. Programación en lenguajes estructurados. Situación inicial. //*Lista= Nuevo . Nuevo= (TLista) malloc(sizeof(Nodo)).3. } } 2. Para insertar en una lista ordenada ascendentemente. segundo. Dirección del nodo tras el que queremos insertar. *Lista= Nuevo. Para ello tenemos que implementar un nueva función que realice un recorrido secuencial de la lista para determinar en que lugar de la lista hay que insertar.es Apuntes de clase . } else { Nuevo->Siguiente= (*Lista)->Siguiente. if (Vacia(*Lista)) { //Nuevo->Siguiente= *Lista.L. es necesario conocer la posición (mediante un puntero) del nodo cuya información es inmediatamente inferior que la del nodo que queremos insertar. Página: 161 nodo. Nuevo Reserva de memoria. El paso (1) hay que hacerlo necesariamente en primer lugar para no perder la dirección del siguiente nodo al apuntado. D.I. Dato 1 Lista Posicion Lista encadenada. Los pasos que damos. La acción que debemos realizar es la de insertar al principio de la lista. alozanoi@teleline.A. retorna un puntero al último nodo. TInformacion Info) { TLista Nuevo. La acción que realizamos es la de insertar en medio o al final de la lista.

while(!Vacia(Aux->Siguiente) && Info > Aux->Siguiente->Dato) Aux= Aux->Siguiente. Página: 162 void InsertarOrdenado(TLista *Lista. 2. } } Tiene tres bloques diferenciados: · · · Reserva de memoria y asignación de la información. } else { TLista Aux= *Lista. Lista->Dato). // TRATAR (Lista->Dato) Lista= Lista->Siguiente. } Otra función que inserta un nodo en la lista ordenado en sentido ascendente según el valor de uno de los campos de información del nodo y que no utiliza las funciones de inserción creadas con anterioridad es la siguiente: void InsertaOrdenado(TLista *Lista.A. del nodo anterior Lista= Lista->Siguiente. En otro caso se recorre la lista buscando el nodo que contiene la información inmediatamente inferior a la que queremos insertar e insertamos el nuevo nodo detrás de él. a través de su campo enlace. Info).L. TInformacion Info) { TLista Anterior= NULL. *Lista= Nuevo. D.I. Nuevo->Siguiente= Aux->Siguiente. Info). Nuevo->Dato= Info. if (Posicion) InsertarEnMedio(&Posicion. Visualizar(Lista->Siguiente).. //Se almacena la dir. Si la lista está vacía o la información a añadir es menor que las almacenadas en esta. TInformacion Info) { TLista Posicion= Buscar(*Lista. hasta alcanzar el final de la misma (cuando el campo enlace del último nodo es NULL). if (Vacia(*Lista) || Info <= (*Lista)->Dato) { Nuevo->Siguiente= *Lista.4. comenzando en la cabecera de la lista y continuando por los nodos restantes. Programación en lenguajes estructurados. Info). // Condición como está o poner interruptor while (Lista != NULL && Info > Lista->Dato) { Anterior= Lista. El recorrido de una lista se realiza secuencialmente. Aux->Siguiente= Nuevo. } } El mismo tratamiento recursivo es el siguiente: void Visualizar(TLista Lista) { if (!Vacia(Lista)) { printf("%d\t".© A. //Se toma el siguiente nodo } return Anterior. se añade el nodo al principio de la lista.Recorrido de una lista.es Apuntes de clase . } TLista Buscar(TLista Lista. else InsertarAlPrincipio(Lista. void Visualizar(TLista Lista) { while(!Vacia(Lista)) { printf("%d\t". TInfo Info) { TLista Nuevo= (TLista)malloc(sizeof(Nodo)).2.I. Lista->Dato). } } alozanoi@teleline.

uno recorre la lista buscando la información y el otro guarda la posición anterior.es Apuntes de clase .I.I. requiere que se conozca la posición del nodo que se desea eliminar. La operación de borrado de un nodo de la lista.2.5. D. Primer paso: Anterior->Enlace= Auxiliar->Enlace Dato 1 Lista Dato 2 Auxiliar Dato 3 Segundo paso: free(Auxiliar) Dato 4 Anterior Borrar un nodo intermedio o el último de la lista. TInformacion Info) { while (!Vacia(Lista) && Info > Lista->Dato) Lista= Lista->Siguiente. Programación en lenguajes estructurados. } 2. Primer paso: Lista= Lista->Enlace Dato 1 Lista Dato 2 Dato 3 Dato 4 Segundo paso: free(Auxiliar) Auxiliar Borrar el primer nodo de la lista.A. · Liberar la memoria ocupada por el nodo borrado. int Encontrado= 0. igual que la inserción/creación de una lista ordenada. void Borrar(TLista *Lista.. else return Lista.© A. //Final de lista o no se encuentra la información.Borrado de nodos de la lista. Si el elemento se ha encontrado. Los pasos para eliminar un nodo son los siguientes: · · Buscar el elemento en la lista.L. caben dos posibilidades: · Es el primero de la lista: la nueva lista apunta a la segunda componente. if(Vacia(Lista) || Info != Lista->Dato) return NULL. Auxiliar= *Lista. TInformacion Info) { TLista Anterior.//Información encontrada. Página: 163 La implementación de un recorrido que busca un elemento en una lista ordenada es el siguiente: TLista BuscarOrdenado(TLista Lista. · No es el primero de la lista: el elemento actual (anterior al que queremos borrar) apunta a la siguiente componente del elemento que queremos borrar. Se necesitan dos punteros. alozanoi@teleline.

L. visualizar la lista y escribirla de nuevo en el archivo.. Consisten en que el último elemento (nodo) de la lista. obtener LISTA3 como unión de las dos anteriores. Este tipo de listas son una variante de las anteriores. Queda como ejercicio realizar las mismas operaciones sobre una lista circular con nodo cabecera. 4. Página: 164 while (!Encontrado && !Vacia(Auxiliar)) if (Auxiliar->Dato == Info) Encontrado= 1. Las operaciones de concatenación y división de listas son más sencillas. Dada la lista anterior.© A. D. Lista circular Además de este tipo de lista circular existe otro tipo semejante con la diferencia de que contiene un nodo falso. 2. en lugar de apuntar a NULL.I. 3. else { Anterior= Auxiliar. free(Auxiliar). } } Ejercicios propuestos: 1. que siempre está en la lista (nunca está vacía) para indicar la cabecera de la lista. En una lista enlazada simple sólo pueden recorrerse todos los nodos si estamos en la cabecera de lista.A. Este nodo cabecera contiene información nula o especial para distinguirlo de los nodos que tienen información real. Crear una lista lineal de números enteros. Lista circular con nodo cabecera Las operaciones que vamos a ver se realizarán sobre una lista circular sin nodo cabecera. Las listas circulares presentan las siguientes ventajas con respecto a las listas enlazadas simples: · · Cada nodo es accesible desde cualquier otro nodo de la lista dado que podemos realizar una vuelta completa de la lista sin necesidad de estar en la cabecera de la lista. Programación en lenguajes estructurados. } if (Encontrado) { if (*Lista == Auxiliar) // Principio de lista *Lista= (*Lista)->Siguiente. Dadas las listas LISTA1 y LISTA2. alozanoi@teleline. Auxiliar= Auxiliar->Siguiente. 3. La lista de pares debe quedar ordenada ascendentemente y la lista original continuará teniendo su orden primitivo. al primer nodo.es Apuntes de clase . else Anterior->Siguiente= Auxiliar->Siguiente. realizar una función para crear otra lista que contenga sólo los números pares que hay en la primera lista.Listas enlazadas circulares. apunta al primer elemento de la misma.I. Cargar en una lista el fichero de datos de artículos.

Nuevo= (TLista) malloc(sizeof(Nodo)).1. Nuevo->Dato= Info. es una inserción al principio de la lista salvo por este matiz. D. al nodo que apunta el nodo cabecera Nuevo->Siguiente= (*Lista)->Siguiente. //Nuevo->Siguiente= Nuevo. se hace apuntando el campo enlace de éste al último elemento de la lista. Página: 165 3. *Lista= Nuevo.Operaciones sobre listas enlazadas circulares.© A. el puntero cabecera se mantiene fijo a dicho nodo. 3.I..L. El algoritmo es el siguiente: void Insertar(TLista *Lista. La inserción de un nuevo nodo.Insertar en la lista. } alozanoi@teleline. Nuevo->Siguiente= *Lista. 3. y el primero (nodo cabecera de lista) al nuevo insertado. Paso 3 Paso 2 Paso 1 Dato 4 Dato 3 Dato 2 Dato 1 Lista Inserción de los nodos 2. (*Lista)->Siguiente= Nuevo.1.A. cuando la lista no está vacía.. Nuevo->Siguiente= *Lista.I. if (Vacia(*Lista)) { *Lista= Nuevo.es Apuntes de clase .1. TInformacion Info) { TLista Nuevo. es decir. y 4 en la lista circular. Inserta un nodo detrás del primero insertado. //Lista ha tomado la dirección de nuevo Dato 1 Lista Lista vacía Nuevo Reserva de memoria Dato 1 Lista Primer elemento encadenado Representación gráfica de la inserción del primer elemento en una lista circular La inserción del primer nodo hace que su campo enlace apunte al propio nodo. Programación en lenguajes estructurados.

I.© A. Dato 1 Lista Lista= NULL Free(Auxiliar) Lista. Auxiliar.es .. requiere que se conozca la posición del nodo que se desea eliminar. Página: 166 else { Nuevo->Siguiente= (*Lista)->Siguiente. Anterior · No es el único nodo de la lista: o Es el primero de la lista: La nueva lista apunta a la siguiente componente o a la anterior. // Podemos variar el nodo cabecera para realizar una inserción // al final de la lista.I. } } 3. uno recorre la lista buscando la información y el otro guarda la posición anterior. Se necesitan dos punteros.1. Los pasos para eliminar un nodo son los siguientes: · Buscar el elemento en la lista. D. (1) Anterior->Siguiente= Auxiliar->Siguiente Dato 4 Dato 3 Dato 2 Dato 1 (2) free(Auxiliar) Anterior Auxiliar Lista · Liberar la memoria ocupada por el nodo borrado.2. igual que en operaciones de borrado anteriores. se pueden dar las siguientes posibilidades: · Es el único nodo de la lista: hay que inicializar la lista. Programación en lenguajes estructurados.L. Auxiliar o Sea o no el primero de la lista: el elemento actual (anterior al que queremos borrar) apunta a la siguiente componente del elemento que queremos borrar. La operación de borrado de un nodo de una lista circular. detrás del último insertado en la lista //*Lista= Nuevo. · Si el elemento se ha encontrado. (2) Anterior->Siguiente= Auxiliar->Siguiente Dato 4 Dato 3 Dato 2 Dato 1 (3) free(Auxiliar) (1) Lista= Anterior Anterior Lista. (*Lista)->Siguiente= Nuevo. Apuntes de clase alozanoi@teleline.A.Borrar un nodo de la lista.

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 167

void Borrar(TLista *Lista, TInformacion Info) { TLista Anterior, Auxiliar; int Encontrado= 0; if (!Vacia(*Lista)) { Auxiliar = *Lista; do { Anterior= Auxiliar; Auxiliar= Auxiliar->Siguiente; if (Auxiliar->Dato == Info) Encontrado= 1; }while (!Encontrado && Auxiliar != *Lista); if (Encontrado) { if(*Lista == (*Lista)->Siguiente) Inicializa(Lista); // Si sólo hay un nodo. else { if (*Lista == Auxiliar) //Si es el primero *Lista= Anterior; Anterior->Siguiente= Auxiliar->Siguiente; } free(Auxiliar); } } }

La función se puede complementar retornando el valor de 'Encontrado' para indicar a la función llamante si el borrado ha sido satisfactorio.

3.1.3.- Recorrido de la lista.
El recorrido de la lista es similar al realizado para una lista enlazada simple salvo que para la lista circular se necesita un puntero auxiliar. El recorrido comienza en el siguiente nodo a la cabecera de lista y finaliza cuando el puntero auxiliar (previamente inicializado a la lista) coincide con la cabecera de lista.
void Visualizar(TLista Lista) { TLista Auxiliar= Lista; if (!Vacia(Lista)) do { Auxiliar= Auxiliar->Siguiente; printf("%d\t", Auxiliar->Dato); }while(Auxiliar != Lista); }

4.- Listas doblemente enlazadas.
En las listas anteriores el recorrido sólo puede hacerse en un único sentido: de izquierda a derecha (de principio a fin). Las listas que pueden recorrerse en ambas direcciones se denominan listas doblemente enlazadas. En estas, cada nodo consta del campo información y dos campos de enlace: uno apunta al nodo anterior de la lista y el otro al nodo siguiente; por tanto, ocupa más memoria que una lista enlazada simple para una misma cantidad de información. Para poder realizar recorridos en los dos sentidos, la lista puede llevar asociados dos punteros externos que identifiquen la CABECERA y el FINAL de la lista respectivamente. Puntero Anterior Información Puntero Siguiente

Nodo de lista doble

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 168

Cabecera

Lista Doblemente enlazada

Fin

La variable CABECERA y el puntero SIGUIENTE permiten recorrer la lista en sentido normal y la variable FINAL y el puntero ANTERIOR permiten recorrerla en sentido inverso. Para una lista doble siempre se cumple que: SIGUIENTE(ANTERIOR(NODO)) = NODO La estructura del nodo en lenguaje C es la siguiente:
typedef int TInformacion; struct Nodo { TInformacion Dato; struct Nodo *Anterior; struct Nodo *Siguiente; }; typedef struct Nodo *TLista; void main() { TLista Cabecera, Final; ... }

También puede implementarse una lista doblemente enlazada circular, que consiste en que los enlaces siguiente y anterior del último y primer nodo de la lista respectivamente no apunten a NULL, si no que apunten uno al último nodo y el otro al primer nodo de la lista. En esta lista sólo es necesario un puntero externo para identificar la lista.

Cabecera

Lista doblemente enlazada circular

4.1.- Operaciones sobre listas doblemente enlazadas
4.1.1.- Funciones de inicializar, vacía, crear un nuevo nodo.
void Inicializa(TLista *Cabecera, TLista *Final) { *Cabecera= *Final= NULL; } int Vacia(TLista Cabecera) //Puede pasarse ‘Cabecera’, ‘Final’ o ambos { return Cabecera == NULL; } Tlista NuevoNodo(TInformacion Info) { TLista Nuevo= (TLista) malloc(sizeof(Nodo)); Nuevo->Dato= Info; return Nuevo; }

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 169

4.1.2.- Insertar en lista doble.
Se dispone de varias formas de inserción en una lista doblemente enlazada dependiendo del lugar en el que haya que insertar el nuevo nodo. Las diferentes maneras se ven a continuación.

4.1.2.1.- Insertar al principio de la lista. ·

Si la lista está vacía: insertamos el primer nodo de la lista. CABECERA y FINAL apuntan al nuevo nodo y los enlaces anterior y siguiente a NULL. Dato 1
Cabecera= Nuevo ; Final= Nuevo ; Nuevo->Anterior= NULL ; Nuevo->Siguiente= NULL

Cabecera

Final

Lista vacía ·

Cabecera Final

Si la lista no está vacía: el enlace Nuevo.Anterior apunta a NULL, el Nuevo.Siguiente a la cabecera, el Cabecera.Anterior y Cabecera a Nuevo. Esta última asignación cambia el puntero Cabecera al nuevo nodo, convirtiéndose éste en el primer nodo de la lista.
(1) Dato 2 (4) Nuevo Cabecera Final (2) (3) Dato 1
(1) (2) (3) (4) Nuevo->Anterior= NULL; Nuevo->Siguiente= Cab; Cab->Anterior= Nuevo; Cab= Nuevo;

void InsertarAlPrincipio(TLista *Cabecera, TLista *Fina, TInformacion Info) { TLista Nuevo= NuevoNodo(Info); if (*Cabecera == NULL) { *Cabecera= *Final= Nuevo; Nuevo->Anterior= Nuevo->Siguiente= NULL; } else { Nuevo->Anterior= NULL; Nuevo->Siguiente= *Cabecera; (*Cabecera)->Anterior= Nuevo; *Cabecera= Nuevo; } }

4.1.2.2.- Insertar al final de la lista. ·

Si la lista está vacía: Insertamos el primer nodo de la lista. CABECERA y FINAL apuntan al nuevo nodo y los enlaces a NULL. Es el mismo proceso que la inserción al principio. Si la lista no está vacía: El enlace Nuevo.Siguiente apunta a NULL, el Nuevo.Anterior al Final, el Final.Siguiente y Siguiente a Nuevo.

·

alozanoi@teleline.es

Apuntes de clase

© A.L.I.

D.A.I. Programación en lenguajes estructurados.

Página: 170

(3) Dato 1 (4) Cabecera Final Nuevo (2) Dato 2

(1)

(1) (2) (3) (4)

Nuevo->Siguiente= NULL; Nuevo->Anterior= Fin; Fin->Siguinete= Nuevo; Fin= Nuevo;

void InsertarAlFinal(TLista *Cabecera, TLista *Final, TInformacion Info) { TLista Nuevo= NuevoNodo(Info); if (*Final == NULL) { *Cabecera= *Final= Nuevo; Nuevo->Anterior= Nuevo->Siguiente= NULL; } else { Nuevo->Siguiente= NULL; Nuevo->Anterior= *Final; (*Final)->Siguiente= Nuevo; *Final= Nuevo; } }

4.1.2.3.- Insertar entre dos nodos. Detrás del apuntado. ·

Si la lista está vacía o el lugar donde debemos insertar no viene dado o es el último nodo de la lista insertamos al final de la lista. Si la lista no está vacía: El enlace Nuevo.Anterior apunta a donde apunta Posición; Nuevo.Siguiente a donde apunta Posición.Siguiente; Posición.Siguiente.Anterior y Posición.Siguiente a donde apunta el nuevo nodo.

·

Dato 1

Dato 2

(4) Cabecera Posicion

(3) Final

(1) (2) (3) (4)

Nuevo->Ant= Pos; Nuevo->Sig= Pos->Sig; Pos->Sig->Ant= Nuevo; Pos->Sig= Nuevo;

(1)

Dato 3

(2)

Nuevo

void InsertarMedioDetras(TLista *Cabecera, TLista *Final, TLista Posicion, TInformacion Info) { TLista Nuevo; if (Vacia(*Cabecera) || Posicion == NULL || Posicion->Siguiente == NULL) InsertarAlFinal(Cabecera, Final, Info); else { Nuevo= NuevoNodo(Info); Nuevo->Anterior= Posicion; Nuevo->Siguiente= Posicion->Siguiente; Posicion->Siguiente->Anterior= Nuevo; Posicion->Siguiente= Nuevo; } }

alozanoi@teleline.es

Apuntes de clase

Anterior apunta a la dirección apuntada por Posición. TInformacion Iinfo) { TLista Nuevo. if (Vacia(*Cabecera) || Posicion == NULL || Posicion->Anterior == NULL) InsertarAlPrincipio(Cabecera. TLista Posicion. No son necesarios dos punteros dado que disponemos de los dos enlaces del nodo.Anterior.2.Anterior a donde Nuevo.Borrar un nodo de la lista.es Apuntes de clase . Pos->Ant->Sig= Nuevo. Se necesita un puntero que recorre la lista buscando la información. Pos->Ant= Nuevo. Final. Los pasos para eliminar un nodo son los siguientes: · Buscar el elemento en la lista. else { Nuevo= NuevoNodo(Info). Programación en lenguajes estructurados. Info). Nuevo->Anterior= Posicion->Anterior.. Si la lista no está vacía: El enlace Nuevo. } } 4. Página: 171 4.Siguiente a donde apunta Posicion. TLista *Final.A.L. La operación de borrado de un nodo de una lista doble. · Dato 1 Dato 2 (3) Cabecera (4) Posición. Posicion->Anterior= Nuevo. el enlace Nuevo. Final (1) Dato 3 Nuevo (2) void InsertarMedioDelante(TLista *Cabecera.1. Inicializar la lista.3. (1) (2) (3) (4) Nuevo->Ant= Pos->Ant.Anterior. Delante del apuntado. Posición. Nuevo->Siguiente= Posicion. Posicion->Anterior->Siguiente= Nuevo. Nuevo->Sig= Pos. Si el elemento se ha encontrado.Insertar entre dos nodos.I. igual que en operaciones borrado anteriores.I. requiere que se conozca la dirección que ocupa el nodo que se desea eliminar.1.4. D.. uno al nodo anterior y el otro a su siguiente. · alozanoi@teleline. · Si la lista está vacía o el lugar donde debemos insertar no viene dado o es el último nodo de la lista insertamos al principio de la lista.Siguiente y Posición. se pueden dar las siguientes posibilidades: · Si el único nodo.© A.

Auxiliar. (2) Final= NULL. Cabecera. (3) free(Auxiliar). int Encontrado= 0. void Borrar(TLista *Cabecera. (3) free(Auxiliar) . while (!Encontrado && Auxiliar != NULL) if (Auxiliar->Dato == Info) Encontrado= 1. Borrar el primer nodo de la lista y desplazar la cabecera al segundo. Página: 172 (3) (1) Dato 1 (2) (1) Cabecera= NULL. D. · Liberar la memoria ocupada por el nodo que contiene la información que queremos eliminar. Final · Si es el primero de la lista. Borrar el último nodo y desplazar la cabecera al penúltimo. TLista *Final. (2) Cab->Anterior= NULL.L. (2) Aux->Sig>Ant= Aux->Ant . Enlazar el nodo anterior con siguiente del que hay que borrar.© A. (2) Dato 2 Dato 1 (1) Fin= Fin->Anterior .I. (2) Fin->Siguiente= NULL .A. Cabecera (1) Final Auxiliar · Es un nodo intermedio. Dato 1 Dato 2 Dato 3 Cabecera Auxiliar Final (1) Aux->Ant->Sig= Aux->Sig .es Apuntes de clase .I. TInformacion Info) { TLista Auxiliar= *Cabecera. Programación en lenguajes estructurados. (3) free(Auxiliar). else Auxiliar= Auxiliar->Siguiente. alozanoi@teleline. (3) free(Auxiliar) . (2) Dato 1 Dato 2 (1) Cab= Cab->Siguiente. (1) Auxiliar Cabecera Final · Es el último de la lista.

de principio a fin. } else if(Auxiliar == *Final) // Es el último de la lista { *Final= (*Final)->Anterior. } free(Auxiliar). Usamos el enlace ANTERIOR void VisualizarDI(TLista Lista) { while(Lista != NULL) { printf("%d\t".1.. (*Cabecera)->Anterior= NULL. Página: 173 if (Encontrado) { if (*Cabecera == *Final) // Si sólo hay un nodo Inicializa(Cabecera. (*Final)->Siguiente= NULL.I. D. Final). Lista= Lista->Anterior. lista->dato). Programación en lenguajes estructurados. de final a principio. El recorrido de la lista puede realizarse en los dos sentidos: de izquierda a derecha usando el puntero cabecera y de derecha a izquierda usando el puntero final.es Apuntes de clase . } } alozanoi@teleline.4. } } // Recorrido inverso.Recorrido de la lista.L. else if(auxiliar == *cab) // Es el primero de la lista { *Cabecera= (*Cabecera)->Siguiente.© A.A.I. Lista= Lista->Siguiente. Lista->Dato). } else // Es un nodo intermedio { Auxiliar->Anterior->Siguiente= Auxiliar->Siguiente. // Recorrido normal. Auxiliar->Siguiente->Anterior= Auxiliar->Anterior. Usamos el enlace SIGUIENTE void VisualizarID(TLista Lista) { while(Lista != NULL) { printf("%d\t". } } 4.

de acuerdo con este concepto las pilas son llamadas "último en entrar.es Apuntes de clase . La nueva cima de la pila es el siguiente nodo de la misma. Da la información almacenada en la cima de la pila. eN). N>=0. //Crea una pila vacía. por tanto.. Esta operación se denomina habitualmente como ‘Push’. .L.. int Vacia(TPila Cima) { return Cima == NULL.I. //Declaración de pila. void Crear(TPila *Cima) { *Cima = NULL. IMPLEMENTACIÓN DE UNA PILA DE ENTEROS. este extremo se denomina cima de la pila. Poner una información en la cima de la pila. } alozanoi@teleline.© A. Creación de una pila vacía.A. Programación en lenguajes estructurados. Una pila queda definida con sus atributos y las operaciones que se pueden realizar con los mismos: · · · · · · Información almacenada en los nodos. en la que las operaciones sobre sus elementos sólo se realizan por uno de sus extremos. Esta operación se denomina habitualmente como ‘Top’. Esta característica de que los añadidos y extracciones de elementos de una estructura se realicen sólo por un extremo es lo que determina el que la estructura sea una pila. Last Input. }. este apunta a la cima actual de la pila convirtiéndose así en la nueva cima. Esto quiere decir que el último elemento que se añade es el primero que se elimina. Puntero externo que indica la cima de la pila. Eliminar la información almacenada en la cima de la pila. Pone la cima apuntando a NULL. Una pila es una estructura dinámica lineal de datos en la que los elementos sólo pueden ser accedidos por un extremo. struct Pila *Siguiente. Dato 3 Dato 3 Dato 2 Dato 1 Dato 2 Dato1 Cima Representación interna y gráfica de una pila. struct Pila { TInformacion Dato. Así. puede definirse una pila como una secuencia de elementos (e1. Extrae el nodo situado en la cima de la pila y libera el espacio ocupado por este. Página: 174 5. Esta operación se denomina habitualmente como ‘Pop’.I. typedef struct Pila *TPila. } //Comprueba si la pila está o no vacía. cima de la pila. Inserta un nodo al comienzo de la pila. First Output). e2..Pilas. Tomar la información almacenada en la cima de la pila. typedef int TInformacion. primero en salir" (LIFO. Este tipo de estructura de datos suele usarse cuando se quiere recordar una secuencia de objetos o sucesos en orden inverso al que sucedieron. D..

Apuntes de clase alozanoi@teleline. primero en salir" (FIFO. Nodo->Dato= Info. por tanto.© A. Esta característica de que los añadidos y extracciones de elementos de una estructura se realicen por los extremos opuestos es lo que determina el que la estructura sea una cola. el final de la cola le apunta a él y pasa a ser el final de la cola. por un extremo las extracciones. Una cola es una estructura dinámica lineal de datos en la que los elementos sólo pueden ser introducidos por un extremo. estos son el frente y el Final respectivamente. Se necesitan dos punteros externos: uno al principio de la cola. frente de la cola. D. return Info. if (!Vacia(Cima)) Info= Cima->Dato. denominado frente de la cola. Esto quiere decir que el primer elemento añadido es el primero que se puede extraer y el último tiene que aguardar su turno. este apunta a NULL. free(Auxiliar). Programación en lenguajes estructurados.Colas. y extraídos por el extremo contrario. puede definirse una cola como una secuencia de elementos (e1. *Cima= Nodo. . First Output).I. Dato 1 Dato 2 Dato 3 Dato 3 Dato 2 Dato 1 Frente Final Representación interna y gráfica de una pila. } TInformacion Pop(TPila *Cima) { TInformacion Info= -1.. Nodo->Siguiente= *Cima. Así. en la que las operaciones sobre sus elementos se realizan por los extremos opuestos. if (!Vacia(*Cima)) { Info= (*Cima)->Dato. Una cola queda definida con sus atributos y las operaciones que se pueden realizar con los mismos: · · · · Información almacenada en los nodos. Pone el frente y el final apuntando a NULL. final de la cola. de acuerdo con este concepto las colas son llamadas "primero en entrar. Creación de una cola vacía. Inserta un nodo al final de la cola.. y por el otro las inserciones. Este tipo de estructura de datos suele usarse cuando se quiere recordar una secuencia de objetos o sucesos en el mismo orden al que sucedieron. First Input. para extraer.I. } 6. Página: 175 void Push(TPila *Cima.. } */ TInformacion Top(TPila Cima) { TInformacion Info= -1. denominado final de la cola. TPila Auxiliar= *Cima. Poner una información en el final de la cola. eN).A.L. } return Info.es . para insertar. *Cima= (*Cima)->Siguiente.. TInformacion Info) { TPila Nodo= (TPila) malloc(sizeof(Pila)). N>=0. y otro al final de la misma. e2.

if(!Vacia(Cola)) Info= Cola. }. Programación en lenguajes estructurados.I. } Ejercicios: 1. } void Insertar(tcola *cola. junto con el número de la habitación que ocupa. Nuevo->Siguiente= NULL. free(Auxiliar). struct Nodo *Siguiente. 2. Solucionar el problema del director del hotel usando una única lista enlazada. IMPLEMENTACIÓN DE UNA COLA DE ENTEROS. } TInformacion Extraer(TCola *Cola) { TNodo Auxiliar. Página: 176 · · Tomar la información almacenada en el frente de la cola. Eliminar la información almacenada en el frente de la cola. Info= Cola->Frente->Dato. typedef struct Cola TCola. tinformacion infor) { TNodo Nuevo= (TNodo) malloc(sizeof(Nodo)). }. } return Info. Cola->Frente= Cola->Frente->Siguiente. minúsculas. if (Vacia(*Cola)) Cola->Frente= Nuevo. Extrae el nodo situado en el frente de la cola y libera el espacio ocupado por este. También desea disponer en cualquier momento de un listado de clientes por orden alfabético. etc. typedef struct Nodo *TNodo. void Inicializa(TCola *Cola) { Cola->Frente= Cola->Final= NULL. Da la información almacenada en el frente de la cola. Nuevo->Dato= Info.© A.Frente == NULL. D. else Cola->Final->Siguiente= Nuevo. struct Cola { struct Nodo *Frente.A. } TInformacion Tomar(TCola Cola) { TInformacion Info= -1. La frase puede contener espacios.I. return Info. El director de un hotel desea registrar el nombre de cada cliente en el orden de llegada a su hotel.L.es Apuntes de clase . Usar una pila y una cola. TInformacion Info= -1. Dado un archivo de texto con una frase. struct Nodo { TInformacion Dato. mayúsculas. typedef int TInformacion. comprobar si dicha frase es un palíndromo. if(!Vacia(*Cola)) { Auxiliar= Cola->Frente. alozanoi@teleline. } int Vacia(tcola cola) { return Cola.Frente->Dato. El nuevo frente de la cola es el siguiente nodo de la misma. Cola->Final= Nuevo. struct Nodo *Final.

Salida de cliente. Programación en lenguajes estructurados. 3. Escribir el programa principal con el siguiente menú: 1.I. 2. Listado de clientes por orden de llegada. e) Eliminación de un cliente de la lista.© A. Alta de cliente. Inicializar la lista. b) Inserción de un cliente en la lista enlazada que debe estar actualizada en todo momento orden de entrada y alfabéticamente-. Listado de clientes por orden alfabético. alozanoi@teleline. c) Listado de cliente por orden de llegada. 6.A. D. 5.L. d) Listado de clientes ordenados alfabéticamente.I. Fin de la sesión.es Apuntes de clase . Página: 177 Pérez 10 López 18 Hidalgo 13 Orden de entrada Funciones necesarias : Orden alfabético a) Definición de los tipos de datos. 4.

1.1).ESTRUCTURAS DINÁMICAS NO LINEALES DE DATOS.I.1) ! si n > 0 La función FACTORIAL de N expresada en términos recursivos sería : FACTORIAL = N * FACTORIAL(N . de forma que los valores de las variables que tienen validez son los más recientemente creados. D. Conceptualmente puede resultar más clara la aplicación de una función recursiva que una iterativa pero su seguimiento es bastante más complejo y los resultados no son siempre satisfactorios. else return N * factorial(N .1) long factorial(int). si se invoca a sí misma.I. sin embargo. Se dice que una función es recursiva (un elemento que contiene otro de su misma categoría) si forma parte de sí misma.. incluidos los parámetros formales. Página: 178 16.1)*(n . La función A llama a la función A. contiene una referencia a la función A. main() { int Numero = 3.*3*2*1 si n > 0 En términos generales podemos transformar las expresiones anteriores como n!=1 si n= 0 (0 ! = 1) n ! = n*(n . en términos de velocidad de ejecución y consumo de memoria. para evitar que continúe indefinidamente. La función factorial se define de la siguiente forma : n!=1 si n = 0 (0 ! = 1) n ! = n*(n . Puede ser utilizada en lugar de la repetición o iteración (estructura repetitiva).es Apuntes de clase . Cálculo del factorial de un número. } alozanoi@teleline. es decir. es preciso incluir una condición de terminación (igual que en un bucle)..© A. } long factorial(int N) { if (N == 0) return 1. a su vez. se crea una copia de la variables locales a la función. Ejemplo 1.2)*.Recursividad... Antes de comenzar a estudiar las estructuras dinámicas no lineales de datos es necesario conocer el concepto de recursividad dada la estrecha relación que existe entre ambas. factorial(Numero)). La escritura de una función recursiva es idéntica a la escritura de una no recursiva .A. Recursividad indirecta: si una función A tiene una referencia a una función B que.L. Programación en lenguajes estructurados. El uso de la recursión es idóneo para resolver aquellos problemas que pueden definirse en forma natural en términos recursivos. printf("%d". Cada vez que se activa recursivamente una función. Se dispone de dos tipos de recursividad : · · Recursividad directa: si la función se invoca a sí misma. La recursión es un medio particularmente poderoso en operaciones de cálculo.

N es igual a 0.I. 13. D. 34. 21. } alozanoi@teleline. en una pila . 8. La serie es de la forma siguiente : 1. Return 1 * (Cuarta llamada con N = 0) Empieza llamada 4 : N = 0. estos se irán procesando en sentido contrario a como se realizaron las llamadas (LIFO). Return 1 Fin de llamada 4 : RETORNA 1 Return 1 Fin de llamada 3 : RETORNA 1 Return 1 * 1 Fin de llamada 2 : RETORNA 2 Return 2 * (1) Fin de llamada 1 : RETORNA 6 Return 3 * (2 * 1) Ejemplo 2. se ejecuta el else. Si suponemos que la llamada a la función factorial es factorial(3). 2. N es distinto de 0 . 5. junto con sus argumentos. Return 2 * (Tercera llamada con N = 1) Empieza llamada 3 : N = 1. Programación en lenguajes estructurados. N es distinto de 0 . Fibonacci(Numero)). Numero < 20.A. 1. se ejecuta el else. Numero++) printf("%d\t". Return 3 * (Segunda llamada con N = 2) Empieza llamada 2 : N = 2.I. FIB(2) = 1 FIB(N) = FIB(N . Cálculo de la serie de Fibonacci.. Página: 179 El funcionamiento de una función recursiva se realiza almacenando las llamadas pendientes. main() { int Numero. . el proceso de llamadas hasta obtener el resultado es el siguiente : Empieza llamada 1 : N = 3. se ejecuta el else. 3. for (Numero = 1.L. y se expresa así : FIB(1) = 0.2) para N > 2 Una función recursiva para el cálculo de esta serie es la siguiente : int Fibonacci(int)..© A. N es distinto de 0 .1) + FIB(N .es Apuntes de clase .

if (T > 0) Fibonacci(T-1. getch(). int Producto(int A. 1) 1. Indicar si un número es o no primo. main() { char *cadena= "Esto es una cadena". int D) { if(N%D == 0) return false. #include <stdio. Otra solución recursiva para este ejercicio. ahora imprimiendo la sucesión. } //Llamada: Primo(Numero. lo mejor es optar por la solución iterativa. } Ejemplo 5. Producto de dos números. } void palindromo(char *c. por tanto. //Inversa(++c).I. D+1). n . alozanoi@teleline. strlen(cadena)). U+P). B-1). D. bool Primo(int N.© A. else return A + Producto(A.I. Esta solución repite los cálculos para varios términos de la sucesión. int). } Ejemplo 4. putchar(*c).1) + Fibonacci(N . } } //También: void Inversa(char *c) { if(*c) Inversa(c + 1).2)). Programación en lenguajes estructurados.es Apuntes de clase . palindromo(c. int P. else { putchar(c[n]).h> #include <stdlib. int n) { if (n == 0) putchar(c[0]). palindromo(cadena. P).1).L. Visualizar la inversa de una cadena. else if(D <= N/2) return true && Primo(N. } Ejemplo 3. U. int U) { printf(“%d\n”.h> #include <conio.h> void palindromo(char *. es la siguiente: void Fibonacci(int T. Página: 180 int Fibonacci(int N) { if (N == 0) return else if (N == return else return } 0. int B) { if (A==0 || B==0) return 0.A. //Cada llamada produce dos más (Fibonacci(N .h> #include <string. 2).

Página: 181 Ejemplo 6. 3. Cuenta la leyenda tibetana que a los sacerdotes del templo de Brahma les fue asignada en la creación del mundo la siguiente tarea : Se les dio una plataforma con tres soportes verticales consistentes en tres agujas de diamante. 3).1.es Apuntes de clase ... MoverTorre(n .1. Programación en lenguajes estructurados.. } } void main() { int NumDiscos = 3. Hasta: %d\n".Mover los discos desde la barra inicial hasta la barra final usando la barra auxiliar. Uno.Pasar los n . printf("Desde: %d. MoverTorre(n . 3) #include <stdio. alozanoi@teleline. Uno. 1. MoverTorre(n. 2. sujetos a la condición de que sólo se podía mover un disco cada vez. 1.Insertar al final de una lista. MoverTorre(NumDiscos. Tres...Borrar un elemento de una lista. Tres). 2. Uno. y que no estaba permitido colocar un disco colocar un disco encima de otro más pequeño.h> #include <conio.Pasar los n . Tres). } Ejercicios de recursividad: 1. Dos.. En el momento en que los sacerdotes acabaran de mover los 64 discos significaría que había llegado el fin del mundo. 1.Pasar el disco inferior de la barra 1 a la 3. 3. int Uno. getch(). int Tres) { if (N > 0) { MoverTorre(N . En el primer soporte había 64 discos de oro. Hasta: %d\n". cada uno de los cuales era un poco más pequeño que el de debajo. Las torres de HANOI. D. Tres). printf("Desde: %d. 2) 2.1. 2.h> void MoverTorre(int N.1. 1. 3) 1. La solución se da de la siguiente forma : 1. 3.Buscar en una lista.1 discos superiores de la barra 1 a la 2.A. MoverTorre(N . 4.. Uno. int Dos.L. Dos). 2.I.I.© A.Insertar en una lista ordenada.1 discos de la barra 2 a la 3.. Los sacerdotes debían mover los discos de oro desde el primer soporte al tercero.

F. D.© A. G. Es el elemento derivado del padre. Nivel. M alozanoi@teleline. Es el elemento que no tiene ningún sucesor. Dicho número es igual a número de nivel del último nodo más uno. B tiene por antecesor a A y por sucesores a E y F. 2. Existe un elemento llamado raíz. I. Sucesor. Página: 182 2. Es una secuencia de enlaces entre nodos. B. G. D nivel 2 : E.1. M son nodos del árbol. jerarquizados del modo siguiente : · · Cada uno de sus elementos tiene un solo antecesor y puede tener un sucesor. como el origen de un subárbol. F. Un nodo sucesor tiene el nivel de su antecesor más uno. es el número de nodos de la rama más larga.es Apuntes de clase . Es el número de orden asignado a un nodo. que no tiene ningún antecesor. Hoja o nodo terminal. I.A.Definición. H. es decir.L. J. Es el número de nodos que se encuentran en el camino más largo desde la raíz hasta una hoja. con las raíces situadas en la parte superior del árbol y las ramas descienden hacia las hojas que están situadas en su zona inferior. Esta estructura de datos se denomina árbol porque se representa en forma de árbol invertido.. formada por un conjunto de elementos del mismo tipo..I. Es el elemento del que se derivan otros. una rama viene dada por la secuencia de enlaces que hay entre el nodo raíz y una hoja. Nodo. B. Es el elemento sin antecesor. es decir. desde el raíz a un nodo cualquiera. A es el nodo raíz. M son las hojas del árbol. K. E. se puede considerar. . K nivel 3 : L. Rama. Un árbol es una lista no lineal. En el concepto de árbol entran los siguientes términos: - - Raíz. varios o ninguno. Antecesor.Árboles. elementos y representación de los árboles.. A.. Ejemplo : A B E L M F G C H I D J K A. La profundidad del árbol es 4. H. Es el camino que termina en una hoja. Se determina del modo siguiente: El nodo raíz tiene nivel cero.I. a su vez. J. De él se derivan los demás. Es cada uno de los elementos que componen el árbol. Altura o profundidad. descendiente o hijo.. C. L. es decir. L es una rama. C. Es decir.. Camino. ascendiente o padre. Los niveles son : nivel 0 : A nivel 1 : B. Programación en lenguajes estructurados.

La representación de un árbol binario requiere que cada nodo contenga. Página: 183 El conjunto de nodos dependientes de B.2. 1 ó 2 descendientes o hijos subárboles. Se denomina lleno cuando todos sus nodos tienen dos sucesores o hijos. D. búsqueda. C y D. formada por un conjunto de cero o más elementos del mismo tipo. 2. cuyo origen está en B. que se denominan subárbol (descendiente) izquierdo y subárbol (descendiente) derecho. donde cada nodo puede tener un máximo de dos hijos. Puntero al subárbol izquierdo Puntero al subárbol derecho Información almacenada en el nodo typedef int TInformacion. a excepción de las hojas. etc. Se dice que un árbol binario está equilibrado si las alturas de los dos subárboles de cada nodo son iguales o difieren en una unidad. // Puntero al árbol izquierdo struct Nodo *ADe. organizados de siguiente modo : · · Existe un nodo sin ascendientes.L. C y D respectivamente forman tres subárboles.. Cada nodo puede tener 0. typedef struct Nodo *TArbol. como las más usuales de los árboles.A.I. denominado raíz. dos punteros: uno que enlace con el hijo izquierdo y otro con el hijo derecho. Un árbol binario es una lista no lineal.Definición de árbol binario y su representación. // Puntero al árbol derecho. siendo n un número entero positivo. En particular estudiaremos el árbol binario. Datos Datos Datos Datos Datos Datos Datos Representación gráfica de un árbol binario. struct Nodo *AIz. además de la información.© A.. Igual que en las listas lineales. Existen varios tipos de árboles : se dice que un árbol es n-ario cuando el número máximo de hijos por nodo es n. borrado.es Apuntes de clase . hablamos de operaciones de inserción. Todas son recursivas ya que lo que se tiene a derecha e izquierda alozanoi@teleline. Programación en lenguajes estructurados. }. struct Nodo { TInformacion Dato.I.

es Apuntes de clase .. Arbol->Dato). } } alozanoi@teleline. NDcha= NumeroNodos .2.2. else { NIzda= NumeroNodos / 2.L.Generar el subárbol izquierdo con ni = n / 2 nodos.. Arbol->Dato= Info.Generar el subárbol derecho con nd = n . Info. . 2. Programación en lenguajes estructurados. Este procedimiento va generando un árbol a medida que se va introduciendo la información.I. La forma recursiva es la mejor para expresar esta regla de distribución equitativa de un número N de nodos : 1. El árbol estará equilibrado (el número de nodos en el subárbol izquierdo y el número de nodos en el subárbol derecho difieren como mucho en una unidad) pero no ordenado. Imprimir(Arbol->AIz. D.I.i++) printf("\t").Usar un nodo para raíz.. } } Para visualizar el árbol podemos usar la siguiente función recursiva : void Imprimir(TArbol Arbol. Arbol->ADe= Construir(NDcha). 2. &Info). void Crear(TArbol *Raiz) { *Raiz = NULL.A. 2. printf("%d\n".2.Construcción un árbol binario equilibrado. TArbol Construir(int NumeroNodos) { TArbol Arbol. } 2. if (NumeroNodos == 0) return NULL. if (!Vacio(Arbol)) { Imprimir(Arbol->ADe.2.1.. int NIzda.2. que apunte a NULL. int Nivel= 0) //DRI { int i.NIzda . int Vacio(TArbol Raiz) { return Raiz == NULL.ni . La condición para terminar la profundidad de la recursión es que el nodo sea terminal..1.1 nodos. Esta forma de creación de un árbol no es satisfactoria por que no siempre conocemos el número de nodos con los que se debe crear. return Arbol. Nivel + 1).Creación de un árbol.© A.1. for (i=1. scanf("%d". Arbol->AIz= Construir(NIzda). printf("Valor: ").1.3. i<=Nivel..1. 3.Ver si el árbol está vacío. Página: 184 son árboles binarios.Operaciones con árboles binarios.1. Arbol= (TArbol) malloc(sizeof(Nodo)). } 2. NDcha. Nivel + 1).

. I. D.4.es Apuntes de clase . pero lo que queda de árbol por la izquierda es precisamente un árbol binario. Hay tres órdenes de los elementos que están asociados de forma natural con la estructura de los árboles. nos referimos a si procesamos en primer lugar el nodo central. //TRATAR (Arbol->Dato) Inorden(Arbol->ADe). R. D. 1 2 3 4 6 5 Ejemplo de árbol binario para usar en el recorrido. Como puede observarse.I. 4. Las tres organizaciones son: Preorden: Inorden: Postorden: R.L. 2. Preorden(Arbol->ADe). El código en C para realizar los tres tipos de recorrido descritos sobre un árbol es el siguiente : El resultado de aplicar el recorrido en preorden es el siguiente : 1.A.1. Visitar los nodos de izquierda a derecha. al hablar de estos tres tipos de recorrido. Programación en lenguajes estructurados. R. Por ejemplo. Visitar la raíz antes que los subárboles. printf("%d\t".Recorrido de un árbol. 6. 5. Arbol->Dato). } } El resultado de aplicar el recorrido en inorden es el siguiente: 3. D. Esta tarea se considera como un parámetro de una tarea más general que es la visita de todos los nodos o recorrido del árbol. I.© A. una vez procesado el nodo central en que nos encontramos se debe seguir recorriendo el árbol por la izquierda. 3. en el caso del Recorrido en Preorden. 2. estos pueden expresarse de forma recursiva. Si se considera la tarea como un proceso secuencial. 1. y pueden considerarse como organizados según una estructura lineal.I.5 void Inorden(TArbol Arbol)// IRD { if (!Vacio(Arbol)) { Inorden(Arbol->AIz). Página: 185 2. 6 void Preorden(TArbol Arbol) // RID { if (!Vacio(Arbol)) { printf("%d\t". Una tarea corriente que se realiza con un árbol es ejecutar una determinada operación con cada uno de los elementos del mismo. I. Arbol->Dato). por lo que se vuelve a llamar a la función de recorrido para profundizar por la izquierda y una vez que se acaba de profundizar por esa rama se profundiza por la rama de la derecha. } } alozanoi@teleline. Tal como sucede con la estructura del árbol en sí.2. D. Visitar la raíz después que los subárboles. el de la derecha o el de la izquierda. entonces los nodos individuales se visitan en un orden específico. 4. //TRATAR (Arbol->Dato) Preorden(Arbol->AIz).

. else BuscarOrdenadoRecursivo(Arbol->ADe. alozanoi@teleline.L. // return . } La función recursiva para el mismo propósito es la siguiente : TArbol BuscarOrdenadoRecursivo(TArbol Arbol. para todo nodo ‘A’.es Apuntes de clase . 2. 3. 1 void Postorden(TArbol Arbol) // IDR { if (!Vacio(Arbol)) { Postorden(Arbol->AIz). Postorden(Arbol->ADe).Buscar en árboles ordenados. while (Arbol != NULL && !Encontrado) if (Arbol->Dato == Info) Encontrado= 1..© A. //TRATAR (Arbol->Dato) } } 2. printf("%d\t". // return . Como esta búsqueda sigue un camino único desde la raíz hasta el nodo deseado. Info).. else Arbol= Arbol->ADe. D. todas las claves de subárbol izquierdo son menores que la clave de ‘A’. else if (Arbol->Dato > Info) Arbol= Arbol->AIz. 2. se dice que este árbol es un árbol de búsqueda. son mayores que la clave de ‘A’. TInformacion Info) { if (Arbol == NULL) return NULL.Función que calcule la profundidad de un árbol (número de nodos de la rama más larga). está o no en el árbol. por supuesto.A. y todas aquellas claves del subárbol derecho de ‘A’. 6. Programación en lenguajes estructurados. else if (Arbol->Dato == Info) return Arbol. Si el árbol está organizado de tal manera que. dado como parámetro..Función que decida si un valor. Los árboles binarios se usan frecuentemente para representar conjuntos de datos cuyos elementos se identifican por una clave única.. TInformacion Info) { int Encontrado = 0. puede programarse fácilmente por medio de iteración aunque también..I.2. Arbol->Dato). if (Encontrado) //Sólo hace falta poner RETURN arbol return Arbol. else return NULL. lo hacemos de forma recursiva. 4.. 5..5. y avanzando por un camino de forma que la decisión de continuar por el subárbol izquierdo o derecho se toma en base únicamente al valor de la clave de dicho nodo. El código en C de la función no recursiva es el siguiente : TArbol BuscarOrdenado(TArbol Arbol. } Ejercicios: 1.1. Página: 186 El resultado de aplicar el recorrido en postorden es el siguiente: 3. Info).I. else if (Arbol->Dato > Info) BuscarOrdenadoRecursivo(Arbol->AIz.Función que retorne el número de nodos que tiene un árbol. Puede localizarse una clave arbitraria en un árbol de búsqueda empezando por la raíz.

no son buenas para apreciar las capacidades de asignación dinámica.© A.L. El algoritmo. o bien por el elemento más a la izquierda del subárbol derecho.Inserción en árboles ordenados. por añadir claves al árbol repetidas tratando de la misma forma Info == (*Arbol)->Dato que Info > (*Arbol)->Dato. else if (Info > (*Arbol)->Dato) InsertarBusqueda(&(*Arbol)->ADe.El elemento con clave X tiene dos descendientes.2.. En esta situación. Son más apropiadas aquellas en las que la estructura del árbol varía (crece o disminuye) durante la ejecución del programa. En la función borrar se distinguen tres casos : 1.6. D.No hay ningún elemento con clave igual a X. TInformacion Info) { if (Vacio(*Arbol)) { *Arbol= (TArbol) malloc(sizeof(Nodo)). así los cambios se reflejarán en la función que realizó la llamada. No crea un árbol equilibrado. Las aplicaciones en que se construye un conjunto de datos.I.. Info). 2. a pesar de todo. (*Arbol)->AIz = (*Arbol)->ADe= NULL..Función que retorne el número de hojas de un árbol. sólo se modifica el contenido del resto de campos de la estructura TInformacion.. Página: 187 4..Borrado en árboles ordenados. La tarea consiste en borrar el nodo con clave X de un árbol que tiene las claves ordenadas. (*Arbol)->Dato= Info.1.Función que calcule el número de nodos que hay en un nivel dado.7. } else if (Info < (*Arbol)->Dato) InsertarBusqueda(&(*Arbol)->AIz. alozanoi@teleline. 5.A. else (*Arbol)->Dato= Info. Info).2.I. los dos como máximo con un único descendiente. el elemento a borrar debe ser reemplazado.. //Modifica la información del nodo } En el algoritmo no se tienen en cuenta los valores repetidos de las claves. y después éste no se modifica. Programación en lenguajes estructurados. además de insertar un nuevo nodo en el árbol. Esto es así por que una clave debe identificar plenamente el conjunto de datos asociados a ella.El elemento con clave X tiene un descendiente como máximo. realiza una búsqueda previa de la información para localizar la rama donde debe ser insertada.. 3. 2.1. Aquí optamos por reemplazar con la información almacenada en el nodo situado más a la derecha del subárbol izquierdo. El puntero externo árbol se pasa por referencia para que cuando se presente el caso de inserción se pueda asignar un nuevo valor a la variable que contenía el valor NULL . void InsertarBusqueda(TArbol *Arbol. La dificultad está en el borrado de un elemento que tiene dos descendientes. 2. Podemos optar por añadir un campo contador a la estructura de datos que nos indique el número de apariciones de dicha clave o bien. Es fácil si el elemento a borrar es un nodo terminal o tiene un único descendiente. bien por el elemento más a la derecha del subárbol izquierdo.es Apuntes de clase .

Nodo). } } La función anterior borrar se apoya en la función eliminar. Info).L. if (!Vacio(*Arbol)) // El elemento no está en el árbol if (Info < (*Arbol)->Dato) BorrarOrdenado(&(*Arbol)->AIz.I.I. TArbol *Nodo) { if (!Vacio((*Arbol)->ADe)) Elimina(&(*Arbol)->ADe. if (Vacio(Auxiliar->ADe)) *Arbol= Auxiliar->AIz. que se activa sólo en el tercer caso.A. D. Página: 188 void BorrarOrdenado(TArbol *Arbol.es Apuntes de clase . *Arbol= (*Arbol)->AIz. *Nodo= *Arbol. y reemplaza la información de este por la encontrada en el nodo más a la derecha en ese subárbol izquierdo. free(Auxiliar). TInformacion Info) { TArbol Auxiliar. else { Auxiliar= *Arbol. void Elimina(TArbol *Arbol. else { (*Nodo)->Dato= (*Arbol)->Dato. &Auxiliar). Info). } } alozanoi@teleline.© A. else if (Vacio(Auxiliar->AIz)) *Arbol= Auxiliar->ADe. y cuya misión consiste en descender a lo largo de la rama más a la derecha del subárbol izquierdo del elemento a borrar. Programación en lenguajes estructurados. else if (Info > (*Arbol)->Dato) BorrarOrdenado(&(*Arbol)->ADe. else Elimina(&Auxiliar->AIz.

//Declaración en lenguaje C. alozanoi@teleline. siempre delante de cualquier sentencia ejecutable. Programación en lenguajes estructurados.© A. Página: 189 17.. La declaración de variables en C++ es similar a la de C. int x. 1.. con un ámbito solapado con el de otra variable local de igual nombre. nunca a variables locales. 2. main() { int x= 3.Flexibilidad en la declaración de variables. . desde el punto de definición hasta el final del bloque. // Afecta a la variable global.LENGUAJE C++ COMO UN C MEJORADO. La extensión de los ficheros en lenguaje C++ es ..A. 3. obviamente. afecta a la visibilidad: una variable declarada dentro de un bloque tiene una visibilidad restringida a ese bloque.cpp (de C Plus Plus).Comentarios.. struct TRegistro { int Codigo. Esto. En C++ se admite el mismo tipo de comentario y además también es un comentario todo aquello que esté a continuación de los caracteres “//” hasta el fin de línea. Pueden comprender varias líneas y estar distribuidos de cualquier forma. x= 5.c). } // Afecta a la variable local..Extensión del nombre de los ficheros. }. Es importante utilizarla pues determina que se invoque al compilador de C++ o al compilador de C (en caso de utilizar la extensión .I. // Declaración en lenguaje C++..Declaración simplificada de variables estructura y enum. y en C++ pueden ser declaradas en cualquier lugar de un bloque. Sin embargo.Operador de resolución de visibilidad. 5. En C los comentarios empiezan por los caracteres “/*” y terminan por “*/”. No es necesario anteponer la palabra clave struct o enum para declarar una variable del tipo estructura o enumerada respectivamente definida por el usuario. ::x= 8.es Apuntes de clase . D. El operador de resolución de visibilidad “::” permite acceder a variables globales. 4. en C tienen que ser declaradas al comienzo del bloque.I. Tregistro Registro...L. ésta última oculta a la primera. struct TRegistro Registro.

alozanoi@teleline. No permitido. 2. Nombre[0]= ‘M’. La diferencia con respecto a las constantes simbólicas es que las variables const están sometidas a las mismas reglas de duración y visibilidad que el resto de variables. El puntero cambia de dirección.. es detectado por el compilador. Nombre= “Pedro”. // No Permitido.I. D. 8. 7. En lenguaje C la conversión explícita de tipo se realiza anteponiendo a la expresión el tipo de dato al que la queremos convertir encerrado entre paréntesis. Un puntero a una variable const no puede modificar el valor de esa variable (el compilador lo detecta) pero el puntero no tiene por qué apuntar siempre a esa variable. char Array[TAMANO]. Estas variables no son constantes simbólicas aunque tienen cierta similitud. el array debe tener una longitud conocida en tiempo de compilación a no ser que utilicemos reserva explícita de memoria.Conversiones explícitas de tipo. si una variable se declara como const se tiene la garantía de que su valor no va a cambiar durante la ejecución del programa. El puntero es constante. Un puntero constante apuntando a una variable cualquiera. return int (x)/y. const char *Nombre= “Antonio”. // Permitido.© A. Programación en lenguajes estructurados. Puede cambiar su valor. No puede cambiar su valor..es Apuntes de clase .L. cosa que no está permitida en C con la declaración de una variable: const int TAMANO= 5. De cualquier forma. Página: 190 6.I. Nombre[0]= ‘M’. // No permitido.A. En lenguaje C++ la conversión de tipo es similar a la utilizada en C pero encerrando entre paréntesis el valor que deseamos convertir.Especificador const para punteros.Especificador const para variables. Esta declaración no está permitida en lenguaje C. Hay que distinguir entre dos formas de aplicar el cualificador const a los punteros: 1. En C++ el especificador const se puede utilizar tanto con punteros como con variables. // Error de compilación. Un puntero variable apuntando a una variable constante. Un puntero const apunta siempre a la misma posición de memoria pero el valor de la variable se puede modificar. double x.. // Permitido. moldeo. y. double x. i++. y. char* const Nombre= “Antonio”. Nombre= “Pedro”. const i= 3. return (int) x/y. La constantes declaradas así pueden utilizarse para definir la longitud de vectores en la declaración de éste.

h> int absoluto(int x) { return abs(x). y éste puede desestimarla por diversas razones. 2. con las repeticiones consiguientes. Este segundo procedimiento suele utilizarse por medio de ficheros cabecera (*.L.. Programación en lenguajes estructurados. Como contrapartida. En el momento de la ejecución se llama a una u otra función dependiendo del número y/o tipo de los argumentos actuales de la llamada a la función.I. pues no se pierde tiempo transfiriendo el control y realizando conversiones de parámetros. Dichas funciones se definen de forma diferente. el valor de retorno no influye en la determinación de la función que es llamada. Página: 191 9. que aparecen en pocas líneas de código pero que se ejecutan muchas veces (en un bucle for. *i = *j. int *j) { int temp. sólo influyen el número y tipo de los argumentos. etc. int &b). en tiempo de compilación. la directiva inline es sólo una recomendación al compilador. } En cualquier caso. D.. pero cada una aceptando un tipo de argumento diferente y con un valor de retorno diferente. que se incluyen en todos los ficheros fuente que tienen que tener acceso al código de las funciones inline. Las funciones inline resultan interesantes en el caso de funciones muy breves. Considérese el siguiente ejemplo consistente en una declaración seguida de la definición: void permutar (int *i. *j = temp. 10. De esta manera la ejecución es más rápida.© A. poniéndolo entre llaves { } a continuación de ésta. Una primera forma de utilizar funciones inline es anteponer dicha palabra en la declaración de la función. Existen 2 formas de definirlas: 1.I. pues es posible que el código de una misma función se introduzca muchas veces. } long double absoluto(long double x) { return fabsl(x). Tampoco se admite que la diferencia sea el que en una función un argumento se pasa por valor y en otra función ese argumento se pasa por referencia. } long absoluto(long int x) { return labs(x). } double absoluto(double x) { return fabs(x). la llamada a una función por el código correspondiente en el punto en que se realiza la llamada.A. El lenguaje C++ permite sustituir. todas con el mismo nombre abs(). Otra forma de utilizar funciones inline sin necesidad de utilizar esta palabra es introducir el código de la función en la declaración (convirtiéndose de esta manera en definición). como coste de memoria excesivo. La sobrecarga (overload) de funciones consiste en declarar y definir varias funciones distintas que tienen un mismo nombre.Sobrecarga de funciones.Especificador inline para funciones.es Apuntes de clase . como por ejemplo: inline void permutar(int &a.h). se pueden definir varias funciones para calcular el valor absoluto de una variable.} alozanoi@teleline. De hecho. el programa resultante ocupa más memoria. temp = *i. pero con el mismo número y tipo de argumentos. por ejemplo). La sobrecarga de funciones no admite funciones que difieran sólo en el tipo del valor de retorno. Por ejemplo. #include <math.

Por ejemplo. //Divisor común En C esta función tiene que ser necesariamente llamada con dos argumentos actuales que se corresponden con los dos argumentos formales de la declaración. Las variables referencia se declaran por medio del carácter (&).A. j = 2. supóngase la siguiente declaración de una función para calcular el módulo de un vector x con n elementos: double modulo(double x[]. En C++ se exige que todos los argumentos con valores por defecto estén al final de la lista de argumentos.. En C++ la situación es diferente pues se pueden definir valores por defecto para todos o algunos de los argumentos formales en la declaración de la función (si no hay prototipo se hace en la definición). permutar(i.: void Particion(FILE* f1.Valores por defecto de parámetros de una función. se toma el valor asignado por defecto a ese argumento. // no hace falta utilizar a = b. En el segundo caso se utiliza el valor por defecto n=3 incluido en la declaración. j). int Secuencia= 1). v = modulo(x). int &b) // los argumentos son referencias { int temp. j).. i. j = %d".L. } void permutar(int &a.I. D. 12. n). Por lo demás. Programación en lenguajes estructurados. Página: 192 11. La función modulo() puede ser llamada en C++ de las formas siguientes: v = modulo(x.h> void permutar(int &a.© A. // el operador indirección (*) b = temp. printf("\ni = %d. } alozanoi@teleline. // los argumentos son referencias void main(void) { int i = 1. Después. en la llamada. C++ ofrece una nueva forma de pasar argumentos por referencia a una función.Variables de tipo referencia. En ANSI C se espera encontrar una correspondencia biunívoca entre la lista de argumentos actuales (llamada) y la lista de argumentos formales (declaración y definición) de una función. que no obliga a utilizar –dentro de la función– el operador indirección (*) para acceder al valor de la variable que se quiere modificar. Por ejemplo la función permutar() utilizando variables referencia en lugar de punteros seria como sigue: #include <stdio. Si se omite un argumento deben de omitirse todos aquellos que se encuentren detrás de él. j = %d". en el caso de que algún argumento esté ausente de la lista de argumentos actuales. Esto se hace por medio de un nuevo tipo de dato –que no existe en C– llamado tipo referencia. int n=3).I. temp = a. Ej. j). Por ejemplo. int &b). En la llamada a la función pueden omitirse alguno o algunos de los últimos argumentos de la lista. la función modulo() podía haberse declarado del siguiente modo: double modulo(double x[]. FILE* f2. int n). // los argumentos no llevan (*) ni (&) printf("\ni = %d.es Apuntes de clase . i. son variables normales que contienen un valor numérico o alfanumérico.

alozanoi@teleline. lista= NULL. en el sentido de que ambas variables comparten la misma posición de memoria: si se modifica i se modifica iref. delelte lista. Otros ejemplos son los siguientes: // Insertar en una lista ordenada. por ejemplo. D. else return b. sin anteponerles ningún carácter u operador.es Apuntes de clase . del siguiente modo: maxref(i. j) = 0. Programación en lenguajes estructurados. info). } } El principal uso de las variables referencia es como valor de retorno o argumentos de funciones. else insertaOrden(lista->siguiente. } La función maxref() tiene referencias como valor de retorno y como argumentos. int& jref. se inicializan y se convierten en alias de los argumentos actuales. El que una función tenga como valor de retorno una variable tipo referencia permite utilizarla de una manera un poco singular. int& iref = i. Los arrays no pueden ser declarados como variables referencia. Siempre se referirá a la misma posición de memoria. } // Borrar todos los nodos de una lista void destruyeLista(tLista& lista) { if(!Vacia(lista)) { destruyeLista(lista->siguiente). porque ya tienen una forma propia y natural de ser pasados como argumentos a una función. La diferencia con un puntero que apuntase a la dirección de i está en que. y viceversa. que son variables ordinarias. iref es un alias de i. una vez que una variable referencia ha sido declarada como alias de i no puede ser declarada como alias de otra variable. void insertaOrden(tLista &lista. En este sentido. info).© A. Esto permite utilizarla. La variable iref es una variable referencia que se asocia con i. tanto en el prototipo como en el encabezamiento de la definición. Considérese el siguiente ejemplo: int& maxref(int& a. tInfo info) { if (Vacia(lista) || info < lista->dato) lista= new nodo(lista.I.A. Las variables de tipo referencia se declaran con el operador (&) y deben ser inicializadas a otra variable o a un valor numérico. que son referencias. int& b) { if (a >= b) return a.I. Por ejemplo: int i=2. // declaración de referencia válida // declaración de referencia no válida La variable i es una variable normal tipo int. En la llamada a la función los argumentos se ponen directamente.L. C++ permite pasar argumentos por referencia sin más que anteponer el carácter (&) a los argumentos correspondientes. Página: 193 Este programa tiene la ventaja de que no hay que utilizar el operador indirección dentro de la función permutar(). En la función permutar() los argumentos formales.

. }. También se pueden crear variables de tipos definidos por el usuario. cin >> Nombre. Cuando la llamada a la función se sustituye por su valor de retorno. El resultado de esta llamada también es un poco extraño: el valor de retorno es una referencia. en vez de aparecer a la derecha en una expresión aritmética o de otro tipo. Gestión dinámica de memoria Con los operadores new y delete el programador tiene entera libertad para decidir crear o destruir sus variables cuando las necesite. alozanoi@teleline. Un_Usuario = new usuario. char *CopiaNombre = new char[strlen(Nombre)+1].A. Una variable creada con el operador new dentro de cualquier bloque. sino también por motivos de eficiencia. New devuelve. Este mismo efecto puede conseguirse mediante punteros. cout << "Introduzca su Nombre:". las ventajas de eficiencia son todavía mucho más palpables. Un aspecto diferente con la función malloc() es que ésta devuelve un puntero a void (*void) que es después convertido al tipo de variable que se desea. struct usuario { . Esa conversión se evita con new..h> #include <string.© A. mediante una instrucción del tipo: delete p.L..I..Operadores new y delete. Página: 194 Ésta es una forma un poco extraña de utilizar una función: la llamada está a la izquierda del operador de asignación. usuario* Un_Usuario. En C++ las referencias son muy utilizadas para pasar argumentos a funciones (y como valores de retorno). perdura hasta que es explícitamente borrada con el operador delete..I. pues es mucho más rápido pasar un puntero o un alias de una variable que una copia del valor de esa variable.. 13.es Apuntes de clase .. La sintaxis de los operadores new y delete es la siguiente: new TipoDeDato <(ValorInicial)> new TipoDeDato[Tamaño] delete <Variable> delete [ ] <Variable> Ejemplo que reserva memoria dinámica para un vector de caracteres: #include <iostream.. el resultado de la sentencia anterior es que la variable pasada como argumento que tiene mayor valor se hace igual a cero. no sólo para poderlos modificar dentro de la función. un puntero a la variable creada. Cuando una variable ya no es necesaria se destruye con el operador delete para poder utilizar la memoria que estaba ocupando. esto es un alias del argumento de valor máximo.h> void main() { char Nombre[50]. en todos los casos. Si además la variable es una estructura. D. Se puede utilizar el operador new para crear variables de cualquier tipo.. pero con referencias resulta mucho más sencillo.. Programación en lenguajes estructurados.

Para utilizar estos nuevos operadores es necesario incluir la librería iostream. Programación en lenguajes estructurados.es Apuntes de clase . En C++ además de las funciones printf() y scanf() se pueden utilizar los operadores cin y cout. D. Así. Estos operadores están sobrecargados de tal manera que admiten tanto los tipos predefinidos como aquellos tipos de datos definidos por el usuario. sobrecargando adecuadamente los operadores suma (+) y asignación (=). int num=2. } 14.h con la instrucción #include <iostream.Nueva forma de realizar la entrada y salida. f<F. scanf (" %s".Sobrecarga de operadores Los operadores de C++. for(int f= 0. Así en un programa en C habría que hacer algo de este estilo: char nombre[20]. num). cout << "Introduzca el nombre del fichero " << num << ": ".I. Página: 195 strcpy(CopiaNombre. para definir operaciones matemáticas con elementos tales como vectores y matrices. cin >> nombre. pueden ser sobrecargados (overloaded). Esto puede ser muy útil por ejemplo.© A. f++) m[f]= new int[C]. for(int f= 0. m= new int*[F]. La sobrecarga de operadores quiere decir que se pueden redefinir algunos de los operadores existentes en C++ para que actúen de una determinada manera.A. f++) delete []m[f]. asociándolo con un formato determinado. alozanoi@teleline.. definida por el programador. f<F. al igual que las funciones. delete [] CopiaNombre.L. delete []m[f]. con los objetos de un mismo tipo estructurado (nunca sobre datos simples). 15. const int C= 10.. } Ejemplo que crea una matriz dinámica: main() { const int F= 5. printf ("Introduzca el nombre del fichero %d: ". se puede llegar a sumar dos matrices con una sentencia tan simple como: C = A + B. int num=2.h>. //Copia Nombre en la variable CopiaNombre cout << CopiaNombre. Nombre). int **matriz. Es importante darse cuenta de que ahora ya no hace falta especificar el tipo de dato que va a ser impreso o leído. Es el propio programa el que decide el tipo de dato en tiempo de ejecución.I. nombre) En C++ podría escribirse así: char nombre[20].

Complejo operator + (const Complejo a. } Complejo operator . Temp. Ejemplo: tratamiento de números complejos. const Complejo b) { Complejo Temp. const Complejo b) { Complejo Temp. double Imaginaria). const Complejo b). Temp.Imaginaria. return Temp.Real= a.A.b. Temp. Temp.Imaginaria. double Imaginaria) { Complejo Temp.Real + b. double Imaginaria.I. const Complejo b).Imaginaria= a.Real= a. const Complejo b). } alozanoi@teleline. Complejo Restar(const Complejo a.Imaginaria= a.I.Real.Imaginaria + b. es decir. Complejo Crear(double Real. desde el punto de vista de utilización de los recursos del ordenador. Un operador puede estar sobrecargado o redefinido varias veces. La sobrecarga de operadores puede resultar bastante ineficaz.b.h> struct Complejo { double Real.Real . Página: 196 El objetivo último de la sobrecarga de operadores es simplificar al máximo el código a escribir.b. Temp.Real= Real. la precedencia y la asociatividad. return Temp. Programación en lenguajes estructurados. Es precisamente el tipo de los operandos lo que determina qué operador se utiliza en cada caso.Real. const Complejo b) { Complejo Temp. a cambio de complicar algo la definición. return Temp.Imaginaria= Imaginaria.Imaginaria .Imaginaria . Complejo Sumar(const Complejo a. const Complejo b).es Apuntes de clase . Temp.© A. de tal manera que actúe de un modo distinto dependiendo del tipo de objetos que tenga como operandos.Imaginaria= a. Complejo Crear(double Real. aunque esté permitido por el lenguaje. void Imprimir(const Complejo a). Es necesario que al menos un operando sea un objeto de la clase en la que se ha definido el operador sobrecargado. return Temp. La sobrecarga de operadores tiene dos limitaciones teóricas y una práctica: · · · Se puede modificar la definición de un operador pero no su gramática.b. #include <iostream.Real << "+" << a. Las ventajas de la sobrecarga de operadores terminan cuando se utiliza de modo que añade complejidad o confusión a los programas. } Complejo Sumar(const Complejo a. } Complejo Restar(const Complejo a. Temp. Complejo operator . D.Imaginaria. }.Real.(const Complejo a.Real= a. } void Imprimir(const Complejo a) { cout << a. Por ejemplo.L. Sintaxis: <Estructura> operator <operador>(Parámetros).Real . Temp.Imaginaria << "i" << endl.(const Complejo a. no se deberá nunca utilizar el operador (-) para multiplicar matrices o el (+) para imprimir vectores. el número de operandos sobre los que actúa.

} main() { Complejo a.Real + b. Temp. b).I. return Temp.Imaginaria + b.es Apuntes de clase . D.b. b.Real. c= a + b . Página: 197 Complejo operator + (const Complejo a. Imprimir(c). c. c)).L. } alozanoi@teleline. Imprimir(c). Imprimir(a).I.Real= a.1).Imaginaria. //c= Sumar(a. Programación en lenguajes estructurados.A.Imaginaria= a. const Complejo b) { Complejo Temp.© A. c= Sumar(a. Temp. b= Crear(1. a= c .c. a= Crear(1. Restar(b.2).

.

L. Estos objetos se pueden construir partiendo de otros creados anteriormente. manipulamos. se pueden modificar y extender fácilmente las implementaciones de los componentes sin tener que recodificar los programas desde el inicio. pasamos de la ecuación tradicional en programación estructurada (Wirth. Página: 199 18. Como vivimos en un mundo lleno de objetos que existen por naturaleza. De ahí que se pretenda dar una visión orientada a objetos para la creación de software.PROGRAMACIÓN ORIENTADA A OBJETOS. métodos. el objeto (se estudiará más tarde). 1980) Algoritmos + Estructuras de Datos = Programas a una nueva ecuación en POO Atributos + Métodos = Objetos Objetos + Mensajes = Programas Unos autores (Khoshafian.© A. D. 1. 1990) · En la POO los datos (atributos) y el código que actúa sobre los datos (métodos) se convierten en una única entidad. La POO intenta solucionar los problemas de una forma más natural. 1988) en siete: estructura modular basada en objetos. modularidad y jerarquía. Así. gestión automática de memoria. Programación en lenguajes estructurados. abstracción de datos. habitualmente los clasificamos. Otros (Meyer. Construir componentes de software reutilizables y librerías de módulos de software fácilmente extensibles obteniendo como consecuencia un desarrollo de software más rápido. Los cuatro elementos deben existir para que el modelo sea orientado a objetos. 1990) se centran en tres elementos fundamentales para configurar la OO: tipos abstractos de datos. Los objetos se comunican entre sí por medio de mensajes. Así.. (Khoshafian y Abnouz.I.I. Este conjunto de disciplinas proveen conceptos. 2.Introducción. describimos. combinamos. Puede describirse como un conjunto de disciplinas que desarrollan programas para facilitar la construcción de sistemas complejos a partir de componentes individuales (Khoshafian. herencia.Características de la poo. técnicas y herramientas para: · Representar y modelar el mundo real tan fielmente como sea posible a la perspectiva del usuario. clases... Estas características no son propias de la POO si no que se dan también en otras formas de programación. polimorfismo y herencia múltiple. creamos y destruimos. La POO se fundamenta en las siguientes cuatro propiedades: abstracción.A. herencia e identidad de objetos. de mejor calidad y más fácil de mantener debido a su estructura inherentemente descompuesta. 1990). permitiendo así construcciones complejas por partes.es Apuntes de clase . encapsulamiento. alozanoi@teleline.

88). En esta parte se explicitan y codifican los mecanismos necesarios para responder a la interfaz. Yo.I. Ninguna parte de un sistema complejo debería depender de la implementación. permitiendo que el código sea revisado sin afectar a la integridad del sistema.I. 2. Captura la visión externa del objeto y es conocida por los demás objetos del sistema permitiendo la comunicación entre ellos. LEDs. encapsulación y abstracción son términos complementarios: ésta se centra en el exterior de los objetos y aquella oculta a los demás las variaciones de su implementación. de los detalles internos. todos los chips y circuitos adicionales. Lo que no nos interesa son los mecanismos internos que utiliza para proporcionar unos resultados óptimos: estado de transistores. para evitar la corrupción de los datos de un objeto y protegiéndolos de un uso arbitrario.2. · La encapsulación establece una barrera conceptual que indica si los datos y operaciones del objeto encapsulado son o no accesibles por el resto de objetos del sistema. Es. almacenándola en el interior de una cápsula. me comunico con la calculadora a través del interfaz de comunicación que ofrece al exterior: un display. Para que un TAD funcione bien. el resultado de aplicar la abstracción al objeto.© A. el alozanoi@teleline. Implementación. lo que nos interesa de ella es que se puede encender y apagar. oculto y seguro del resto del sistema.1. ficheros. Programación en lenguajes estructurados. de otra parte de ese mismo sistema. no debemos fijarnos en la implementación concreta de las estructuras de datos desde el punto de vista de la programación (arrays.Encapsulamiento. acumuladores.A. La implementación de la representación interna de la estructura y de los servicios del TAD incorpora el concepto de encapsulación.. por tanto. etc. Es el producto de aplicar el encapsulamiento al objeto. Página: 200 2.. operacionales y de comandos.es Apuntes de clase . mostrar los resultados de dichos cálculos entre otras características de la misma. la implementación de su representación y de los servicios debe estar encapsulada (Liskov. Así.. Se centra en la vista externa de un objeto y sirve para separar su comportamiento de su implementación. Es la propiedad que permite empaquetar las características y comportamiento de un objeto en un envase independiente. Así. listas enlazadas.L.Abstracción. El resto. cada objeto tiene dos partes diferenciadas: · Interfaz de comunicación con el exterior.) si no en las características que tiene en la vida real. Es la propiedad que permite representar las características esenciales de un objeto ignorando determinados aspectos de la realidad para facilitar la realización de la tarea. un conjunto de teclas numéricas. ocultando información. sumadores.. es decir. es decir. es capaz de realizar cálculos aritméticos. se nos permite ocultar una parte del sistema del resto. Por tanto. D. estamos realizando un ocultamiento de la información. Si consideremos una calculadora. como objeto. un interruptor de encendido y apagado. Para definir un objeto y establecer las relaciones de este con otros objetos sólo necesitamos conocer QUE es lo que hace el objeto (que operaciones necesitan realizarse y que información resulta de la aplicación de dichas operaciones) y no COMO lo hace.

Evidentemente la calculadora no es una pieza homogénea. y consiste en ‘divide et impera’ (divide y vencerás)”. si no que sirven para cualquier equipo electrónico que los precise. Es la propiedad que permite subdividir. D. Un ejemplo utilizado habitualmente es el del molde de galletas. ciñen.Clases y objetos. Es la propiedad que permite clasificar u ordenar las abstracciones. Jerarquía de estructura de objetos: se implementa mediante relaciones de agregación/composición que permiten el agrupamiento físico de las estructuras relacionadas lógicamente.4. molde o prototipo que permite crear objetos con la misma estructura. es su implementación interna. de esta forma no sólo sirven para ésta calculadora. un sistema en partes más pequeñas. Se suele aplicar un método de refinamiento progresivo de los módulos. Página: 201 operando.que han sido fabricados cada uno independientemente del otro. descomponer. está encerrado dentro de una caja para que no se pueda manipular.. De ésta manera. las clases “Calculadora”. que se adaptan. 3. denominadas módulos.A. Deben ser cohesivos y débilmente acoplados. Programación en lenguajes estructurados. Está formada por un conjunto de componentes –circuitos electrónicos.L. Las jerarquías más importantes son: Jerarquía de clases: se implementa mediante relaciones de herencia y define una relación entre las clases donde se comparte la estructura o comportamiento definido en la clase. conveniente.I.es Apuntes de clase . plásticos. 2.. toda la implementación.Jerarquía. Hay una relación de composición.© A. Ya Dijkstra en 1979 dice: “la técnica de dirigir ésta complejidad ha sido conocida desde antiguo. Cada uno de los módulos debe ser tan independiente como sea posible del sistema y de las otras partes del mismo. alozanoi@teleline. dar una definición sencilla de los mismos.Modularidad. se reduce la complejidad del sistema. en cierta medida. 2. Si pensamos en una clase superior como “Máquina de Calcular”. En la calculadora todos los componentes están relacionados y perfectamente acoplados entre sí componiendo el objeto calculadora.I. y las galletas que hacemos a partir de ese molde ya son objetos concretos creados a partir de las características definidas en el molde. el acumulador. Antes de comenzar a tratar con rigor estos dos elementos imprescindibles de la POO. a la estructura lógica elegida en el proceso de diseño. dada la estrecha relación existente entre ambos. Se establece una jerarquía de clases.. cada módulo puede dividirse en otros más pequeños a su vez. “Calculadora Científica” y “Calculadora programable” comparten el comportamiento de la clase “Máquina de Calcular”. Por objeto entendemos cualquier cosa del mundo real y por clase un marco. LEDs. botones.3. el molde para hacer galletas sería la clase.

un objeto es una de las siguientes cosas: · · · Algo tangible y/o visible. tiene un comportamiento definido. un comportamiento y una identidad que lo diferencian de los demás objetos. Estas son sus características dinámicas. estos componentes tienen unos valores reales para cada objeto que van variando con la actuación del objeto en el transcurso de su uso (toman diferentes valores: 1. es instanciado y se puede crear y destruir. La calculadora tiene todas esas características: es visible. admite un máximo de dígitos. El hecho de que cada objeto tenga un estado implica que ocupa un espacio. alozanoi@teleline. tiene una implementación interna. Desde la perspectiva de la POO. en una estructura autónoma. sólo pueden almacenar un valor en un instante determinado. 345. Así pues. junto con los valores que pueden asumir cada una de estas propiedades -que son dinámicas. por tanto..A.© A. La calculadora es un objeto.1. Un objeto. un objeto es un elemento autónomo de información que proporciona una serie de servicios sobre la estructura de datos en la que se implementa. dispone de un interfaz. Por tanto una clase podrá tener muchos objetos de su tipo pero un objeto sólo podrá pertenecer a una clase.... existe durante un tiempo. D.el operando y el acumulador. El estado del objeto viene determinado por el conjunto de propiedades que tiene -estas suelen ser estáticas. cambian con el tiempo-. Página: 202 3. .Objeto. 3. La estructura y comportamiento del conjunto de objetos similares se definen en una clase común.I. Programación en lenguajes estructurados. 88). con un comportamiento bien definido en el dominio del problema (Smith.Estado del objeto. Alguna cosa que puede ser comprendida intelectualmente. Es decir. Desde la perspectiva del conocimiento humano. cambia el valor de sus atributos. su interfaz y la implementación de su representación interna y de sus servicios.1.L. pueden configurar la parte estática del objeto: no admiten letras.98). tangible.. estas son sus características y no pueden cambiar. representa un elemento individual e identificable. en el mundo real o en la memoria del ordenador.es Apuntes de clase . identificable. además de otros componentes. Por otra parte. en la calculadora -y pasando del objeto tangible a una supuesta programación de la misma con un lenguaje de programación orientado a objetos. un objeto es una instancia de una clase que incorpora. real o abstracta. no cambian-. una unidad o entidad. Definición: un objeto es una instancia de una clase que incorpora una interfaz de comunicación con el exterior y una implementación interna de sus servicios.1.I. En el contexto de POO un objeto posee un estado. 123. Algo hacia lo que se dirige el pensamiento o la acción.

Utilizando ésta segunda manera. Si se hubiera definido la operación “Mostrar Estado”. Página: 203 3.Comportamiento del objeto. podemos nombrar – acceder.© A. Permite que todas las partes del objeto sean accedidas en un orden bien definido. deben comunicarse y actuar unos sobre otros. La calculadora de la mesa está perfectamente identificada por su marca y número de serie o modelo. hubiera sido una operación de este tipo. También podemos crear el alias “Mi Calculadora” para identificar el objeto y a través de él o del nombre podemos realizar las operaciones pertinentes. Así.. Destructor. y dependiendo del lenguaje de programación. Los mensajes son la forma que tienen de comunicarse distintos objetos entre sí. Libera el estado del objeto y lo destruye (ocasinalmente).1. Si consideramos que “Esta Calculadora” es un objeto de la clase “Calculadora” y “Sumar()” una de las operaciones que es capaz de realizar “Esta Calculadora” -forma parte de la interfaz-.3. Programación en lenguajes estructurados. 3.L. D.I. Altera el estado del objeto. el estado de un objeto. En general. reacciona a un mensaje recibido del sistema y dependiendo de éste cambia de estado. es decir. 91). esto se hace con el nombre (identificador) del objeto y/o con direcciones o referencias al objeto almacenado en la memoria. En éste sentido. pero no lo altera. que visualice secuencialmente la memoria. y en programación orientada a objetos. no por sus propiedades descriptivas. dejando el resultado en “Acumulador” y borrando el “Operando” -en líneas generales-. - Seleccionar. “Esta Calculadora” es el nombre del objeto de la clase “Calculadora” definida anteriormente.Sumar()” sería un mensaje que se manda sobre el objeto “Esta Caculadora” para que calcule la suma de sus atributos “Acumulador” y “Operando” -forman parte de la implementación-. 94): - Modificar. Existen cinco tipos de operaciones que suele realizar un objeto (Booch. - Constructor. la que le distingue de los demás objetos (Khoshafian. Un mensaje es una acción que se manda a un objeto para que realice una operación con un propósito específico.es Apuntes de clase . cambiando con ello el estado del objeto. el acumulador y el operando en la calculadora. - Iterar. Accede al estado del objeto.A.I. A través de su nombre o alias podemos realizar todas las operaciones permitidas con el objeto. se distinguen entre si por su propia existencia (inherente). Los objetos se relacionan entre sí. alozanoi@teleline.2.. El comportamiento de un objeto viene determinado por la forma en que actúa al recibir un mensaje desde otro objeto o desde el entorno.1.Identidad del objeto. no es más que el resultado acumulado de su comportamiento. Es la propiedad que caracteriza a un objeto. Mostrar el contenido del “Acumulador” no cambia el estado del objeto. entonces “Esta Calculadora. Crea el objeto e inicializa su estado.a un mismo objeto con varios aliases.

en programación. Existen dos tipos de componentes en una clase: atributos y métodos.. molde o prototipo que permite crear objetos con una estructura y comportamiento comunes. Khosafian (90) clasifica los métodos en tres tipos. en definitiva.Componentes o miembros de la clase. 94): · · · De acceso. atributos.A..I.L. Una clase es una generalización de un tipo determinado de objeto: marco. D. los métodos definen el comportamiento del objeto. referencias y nombres de objeto genera mucha controversia debido a que no son mecanismos adecuados para identificar unívoca y permanentemente el objeto.I. Así. una clase es un tipo de dato y un objeto es una variable de ese tipo de dato.es . es decir. la representación interna de la clase y mantienen el estado del objeto.Identificador Es el nombre que se da a la clase para poder especificar a cual pertenecen los objetos.2. Recuperan el valor de los atributos del objeto. básicamente las mismas operaciones que pueden realizar los objetos (Booch. una clase contiene una completa y detallada descripción de los datos que contendrá el objetos y de las operaciones que podrá realizar. por tanto. y en su implementación a través de direcciones.. 3. copiar y destruir el objeto.2. y las galletas que hacemos a partir de ese molde ya son objetos concretos creados a partir de las características definidas en el molde. · Un constructor se llama automáticamente en el instante de creación del objeto. Un ejemplo utilizado habitualmente para relacionar y diferenciar un objeto y una clase es el del molde de galletas. propiedades. inicializar. le asigna la memoria necesaria para almacenar el objeto y lo inicializa con los valores por defecto -si es Apuntes de clase alozanoi@teleline. Una clase se caracteriza por un identificador. Especifica una estructura de datos y los métodos operativos que se aplican a cada uno de los objetos. de cualquier tipo de dato (simple o estructurado). Constituyen. Cambian el estado del objeto. unos componentes o miembros y por un nivel de acceso a sus componentes.2.Clase.2.2. el molde para hacer galletas sería la clase. 3. Operaciones que se pueden realizar con los atributos y que son utilizables por todos los objetos pertenecientes a la clase. 3. Datos miembro. Constructores y Destructores. Conforman las estructuras de datos.© A. Página: 204 La identidad de un objeto es una característica fundamental del mismo. Son invocados automáticamente para crear. Métodos o funciones miembro. De actualización. Programación en lenguajes estructurados. que van a utilizar los objetos asignándoles unos valores que permitan diferenciarlos unos de otros.

Apagar() –destructor-. Encender() –constructor-. DarOperando() –de acceso. Memoria y Operando que son privados a la clase y que habitualmente los atributos deben serlo. Su implementación sería la codificación de los métodos declarados. es la visión del diseñador de la clase y comprende la implementación de los métodos. Programación en lenguajes estructurados. aunque no necesariamente. mediante las clases podemos instanciar objetos de un mismo tipo que se distinguen entre sí a través de su estado. entre otros. será necesario que el programador cree su propio destructor..El identificador de la clase es “Calculadora” . siendo por tanto un concepto físico y concreto que tiene una existencia real y determinada. .© A. Apuntes de clase alozanoi@teleline. . un objeto es una particularización o instancia de una clase que incorpora una interfaz y una implementación interna de sus servicios. La representación interna es la implementación de la clase. Según las operaciones realizadas con el objeto. Con esta definición de clase. o con los valores especificados en un constructor general definido por el programador.Sus atributos son Acumulador. Declaraciones visibles únicamente a la propia clase. Declaraciones visibles a la propia clase y a sus subclases. Siguiendo con el ejemplo de la calculadora tenemos que: ..que son públicos. y dependiendo del lenguaje.3. Página: 205 · un constructor por defecto creado por el propio compilador-.es . Privada. Así.. Un destructor también se invoca automáticamente justo antes de que el objeto sea eliminado de la memoria y lo incorpora el lenguaje de manera automática. D. Los componentes de la clase tienen distintos niveles de acceso para proteger la información del exterior de la clase (encapsulación). Declaraciones visibles a todos los usuarios de la clase. proporciona las operaciones que se pueden realizar sobre los objetos de la clase. 3. También se pueden copiar unos objetos en otros.L. Este nos permite diferenciar entre el interior y el exterior de la clase.I.Sus Métodos son.2.Nivel de acceso. Protegida.A. del valor de sus atributos.I. es la visión del usuario –la declaración de los atributos y métodos de la clase-. La externa es el interfaz de una clase. Se puede dividir según su visibilidad en tres partes: Pública.y PonerOperando(Parámetro) –de actualización.Se puede declarar el interfaz de la clase de la siguiente manera: Clase Calculadora Atributos y Métodos privados Acumulador es de tipo real Operando es de tipo real Atributos y Métodos públicos Encender() Apagar() DarOperando() PonerOperando(Parámetro real) Sumar() Restar() .

I. } public: void Construir() { Indice= 1000. es decir son clases cuyas instancias son también clases. Proporcionan la ventaja de que pueden almacenar información común a todas las instancias de la clases mediante “variables de clase”. siendo sólo accesibles desde las funciones de la clase. } void Destruir() { Construir(). sólo pueden acceder a ellos los otros miembros de la clase. es decir.Declaración de clases. class Pila { private: int Datos[1000]. El lenguaje permite instanciar clases desde otras clases. es decir. Es el nivel de acceso por defecto a los componentes de una clase. Implementación de una pila de enteros con un array. se puede acceder a los datos y funciones miembro desde otras partes del programa.© A.3. Los componentes se ocultan para todos los objetos de la clase.I. int Indice. Ejemplo. Programación en lenguajes estructurados.A. pero tienen características especiales relacionadas con la herencia. La sintaxis utilizada en C++ para declarar una clase es la siguiente: class Nombre De Clase { Nivel De Acceso: Componentes: datos y funciones Nivel De Acceso: Componentes: datos y funciones }[Lista de objetos].es Apuntes de clase . Existen tres niveles o especificadores de acceso que pueden estar situados en cualquier lugar dentro de la definición de la clase y aparecer tantas veces como sea necesario. Los “métodos de clase” se pueden utilizar para actualizar o recuperar el contenido de estas. } alozanoi@teleline. su ámbito actúa desde que se pone hasta que aparece otro. Protected. } void Push(int v) { if(!EstaLlena()) Datos[--Indice]= v. Los componentes son accesibles directamente por cualquier objeto perteneciente a la clase. Private. 3. Página: 206 Metaclase. Estos son los siguientes: · · · Public. } void Pop() { if (!EstaVacia()) Indice++.. Los componentes son accesibles a través de los miembros de la clase. D. bool EstaLlena() { return !Indice.L.

© A. es decir. Pila1. Programación en lenguajes estructurados.. else return -1.Instanciación de objetos.4. Los métodos se han definido dentro de la propia declaración de la clase: métodos internos. Donde el operador de campo :: quiere decir que la función pertenece al campo de la clase. El formato para el acceso a los miembros de la clase es el mismo que para las estructuras. Pila1. } La sintaxis para definir las funciones externas es la siguiente : TipoRetorno NombreClase::NombreFuncion(Parámetros) .Push(1) . } bool EstaVacia() { return Indice==1000. Ejemplo: Pila Pila1.Pop() . 3. Página: 207 int Top() { if(!EstaVacia()) return Datos[Indice]. Cima = Pila1. Ejemplo.I. Sólo podemos acceder desde el programa a los miembros definidos como públicos.Construir() . Si suponemos que tenemos muchas funciones y muy grandes.I. En general es el siguiente : Objeto.Miembro .L. La diferencia entre definir métodos internos y externos está en que estos se comportan como funciones normales y aquellos se comportan como funciones inline.es Apuntes de clase . D. } }. las siguientes sentencias darían errores de compilación : alozanoi@teleline. esta forma es impracticable y sería deseable que la declaración de la clase contuviera únicamente los atributos y los prototipos de las funciones: métodos externos.A.Destruir() . else return -1. Esto se consigue extrayendo de la clase el código de las funciones de la siguiente forma : int Pila::Top() { if(!EstaVacia()) return Datos[Indice]. El formato para crear objetos o instancias de esa clase es el siguiente : NombreClase ListaObjetos . } bool Pila::EstaVacia() { return Indice==1000.Top() . Pila1. Pila2 . Pila1.

cuando coinciden los tres identificadores se tomará primero el campo local de la función. de manera que cuando hacemos Pila1. int) .Datos[1]= 2 . Así..A. Programa que calcule la distancia entre dos puntos.5. Pila1. 1) . la función anterior podría haberse escrito como void Push(int v) { if(!(this->EstaLlena())) this->Datos[--this->Indice]= v. 1.I. Pero al introducirlo dentro de una clase eliminamos el primer parámetro. ingresos y reintegros desde un menú. denominado this. el campo/atributo de la clase y la variable local/parámetro formal del método . el global : alozanoi@teleline.© A. Permitir crear la cuenta.Control de acceso a miembros. Programación en lenguajes estructurados. petición de saldos. 2..Indice= 100 .5. Sqrt(sqr(x1-x2)+sqr(y1-y2)) 3. Push(Pila1. } La declaración formal del parámetro this es la siguiente TipoClase *const this .Push(1) . Si observamos como invocamos los métodos y lo comparamos como lo haríamos en programación tradicional. la propia pila. En programación estructurada la definición y la llamada de una de las funciones anteriores es la siguiente : void Push(Pila *.L. Página: 208 Pila1. y como ‘this’ es un puntero constante no se puede modificar. podemos darnos cuenta de que falta un parámetro. por lo que estamos pasando implícitamente el parámetro. 1) . D. Programa que simule una cuenta bancaria.Campo de clase Dentro de una función miembro tenemos un conflicto entre tres campos con igual identificador: la variable global. Programa que permita sumar y restar números complejos.es Apuntes de clase . después el campo de clase y por último. En C++ existe el puntero. 3. 3. Ejercicios.1.I. al propio objeto que llama al método. es como si estuviéramos haciendo Push(Pila1.

Acceso entre clases amigas Cuando se definen miembros como private el acceso a miembros entre clases distintas es imposible. y.Pon(2.5.Distancia(p1.x. 2).2. si declaramos dos puntos. d= p1. y= yy. Clase::a= 2 . dado que es un método que está operando sobre dos puntos deberíamos pasarle como parámetros los dos puntos. 2) + pow(b.x .© A. . //Operador de resolución de visibilidad 3.y. Por ejemplo. Tampoco lo tenemos desde una función normal. public: void Pon(double xx. double d. //Parámetro formal de la función //Campo de la clase //Variable global. ::a= 3 . 1). p2.Distancia(p2). la siguiente clase Punto dispone de una función que calcula la distancia entre dos puntos : class Punto { double x. Desde una clase no se puede acceder a atributos o métodos privados a otra clase. su distancia se hallaría de la siguiente forma: main() { Punto p1. alozanoi@teleline.Pon(1. } El método Distancia() accede tanto a los miembros privados de p1 como a los de p2 porque forma parte de la clase punto y. void f(int a) { a= 1 .A. El problema está en que ahora la función Distancia() no es un método de Punto si no que es una función independiente. Página: 209 int a .L. const Punto &b) . por tanto.. Operador de resolución de visibilidad. y la llamada para calcular la distancia es d= Distancia(p1. La forma de hallar la distancia es poco ortodoxa. } double Distancia(const Punto &b) { return sqrt(pow(b. pero uno de ellos va implícito en la propia llamada. } }. 2)). tiene acceso a todos los miembros de la clase a la que pertenece. el parámetro this. p1. } } . El prototipo lógico sería double Distancia(const Punto &a. p2) .y .es Apuntes de clase . class Clase { int a . D. p2) . a no ser que la llamada sea de la forma d= p1... Programación en lenguajes estructurados.I.I. double yy) { x= xx. p2.

En la sobrecarga de funciones en C++ con estructuras se pasan dos parámetros a la función. 3. b. Imaginaria.Real.L.x. Por contra.Real. const Punto &b) . void Complejo::Crear(double Real. y. class Punto { double x.y .C. const Punto &b) // { return sqrt(pow(b. Temp. } Ahora no se pone el operador de campo :: puesto que Distancia() no es un método de la clase Punto y por tanto tampoco tiene el parámetro this. } Complejo Complejo::operator + (const Complejo &C) { Complejo Temp. } Complejo Complejo::operator .Imaginaria.. Para solucionar el problema debemos definir la función Distancia() como función amiga de la clase punto usando la palabra reservada friend.a.Imaginaria= Imaginaria . }. Página: 210 pero igual que en el primer caso es muy poco elegante e incluso puede dar lugar a confusión.2). y= yy.A.(const Complejo &C). } friend double Distancia(const Punto &a. } alozanoi@teleline. cuando se sobrecargan los métodos de una clase se pasa un único parámetro. esto es así por que existe el parámetro implícito this que se comporta como el primer operando.I. } main() { Complejo a. Temp. a= c .Real= Real . public: void Crear(double Real.x .© A. 2)). entonces declaramos toda la clase como amiga: friend class Clase .I. c= a. }. Complejo::Imaginaria= Imaginaria.es Apuntes de clase . Complejo operator . return Temp.C. Temp.Imaginaria. double yy) { x= xx. D.1). Temp. No se usa. c.6. } void Complejo::Imprimir() { cout << Real << "+" << Imaginaria << "i" << endl. 2) + pow(b. Programación en lenguajes estructurados. Si queremos que todos los métodos de una clase sean amigos de otra. //Llamada normal. public: void Pon(double xx.Crear(1.y. double Imaginaria).Sobrecarga de operadores en clases.Imaginaria= Imaginaria + C. void Imprimir(). double Imaginaria) { Complejo::Real= Real. Como ejemplo creamos una clase que calcula la suma y resta de números complejos : class Complejo { private: double Real. a.(const Complejo &C) { Complejo Temp.b. b.operator+(b). //Llamada extendida. return Temp.Real= Real + C. Complejo operator + (const Complejo &C).a.Crear(1. double Distancia(const Punto &a.

. La clase no puede ser derivada.es Apuntes de clase . Programación en lenguajes estructurados. Página: 211 También podemos declarar el operador + como friend. //No existe this. que ha creado el propio compilador si no ha encontrado un constructor definido explícitamente en la clase. alozanoi@teleline.I. y= yy.. } friend double Distancia(const Punto &a.Imaginaria= C1.1. } Las llamadas pueden ser de la forma siguiente : c= operator+(a. b). que nos deja prácticamente sin posibilidades.7. ni siquiera void.L.Real. const Punto &b) . //Extendida. Para identificarlo se usa el nombre de la clase como nombre del constructor. return Temp. La clase no puede tener constructores.Creación e inicialización de objetos.Imaginaria + C2. double yy) { x= xx. . Temp. D.. teniendo en cuenta que ahora no existe el parámetro this: class Complejo { . estática o dinámicamente (new).I. 3. { } void Pon(double xx.A.Real + C2..© A. //Normal. Cada vez que se define un objeto. El constructor por defecto no tiene argumentos ni tampoco retorna ningún valor.7.Real= C1. const Complejo &C2). Complejo operator + (const Complejo &C1..Imaginaria. const Complejo &C2) { Complejo Temp. }. En el momento de definir (construir) un objeto podemos darle unos valores iniciales usando constructores. 3. y. class Punto { double x.Constructor por defecto. constructor por defecto. friend Complejo operator + (const Complejo& C1.. No podemos inicializar los objetos como lo hacemos con las estructuras a no ser que cumpla las siguientes restricciones : · · · · La clase no puede tener miembros privados. La clase no puede tener funciones virtuales. No se usa. c= a + b . se está realizando una llamada a un método. }. Temp. public: Punto() //Igual que lo crea el compilador.

L. }. Punto p(3.2. cada vez que se define un nuevo objeto (Punto p) de la clase punto.}? Habría que modificar el constructor general de la siguiente forma: Punto(double xx= 0. double).A. public: Punto() { x= y= 0.. La segunda forma no suele usarse. public : Punto() { x= 0.. Ahora. Siguiendo con la clase Punto la definimos de la siguiente forma : class Punto { double x.7. Pero. por ejemplo inicializar x e y a 0. parámetro alozanoi@teleline. el de la clase. Programación en lenguajes estructurados. 2) . double yy= 0){…} Definiciones correctas e incorrectas de objetos son las siguientes : Punto p .Constructores generales.0 . }. Punto p() . 0.. ¿qué sucede si eliminamos el constructor por defecto Punto(){. todos con el mismo nombre.I. Podemos definir todos los constructores que queramos en una clase. 3. y. } friend double Distancia(const Punto &a. y.0). y= yy.0. } . Punto p= Punto(3. D. tomará el valor (0. Llaman al constructor con dos parámetros Punto(double.0 . La segunda no se usa. 0 respectivamente: class Punto { double x.. double yy) { x= xx. Incorrectas. Punto p(3) .es Apuntes de clase . } Punto(double xx. Página: 212 En esta clase el constructor no hace nada pero podemos modificarlo para que si haga algo. const Punto &b).© A. } Punto(double xx) { x= y= xx.0. Llaman al constructor con un Punto(double). Ahora no es necesario el método Pon() puesto que construimos los objetos de otra forma.I.. 2) . Punto p= Punto() . Llaman al constructor por defecto. usando las reglas de la sobrecarga de funciones. Punto p= Punto . y= 0. Punto p= Punto(3) . La segunda no se usa.

una referencia.L.A. }. //cuando se destruye el objeto. Punto(double xx. Tira). No lleva parámetros ni retorna ningún valor y su identificador es el mismo que el de la clase precedido por el signo ~ (Alt+126). Punto s(p) .. } 3.es Apuntes de clase . }. cerrar ficheros. alozanoi@teleline.Constructor copia y el operador de asignación. del mismo tipo de la clase donde definimos el constructor. Programación en lenguajes estructurados. Punto p(2. const Punto &b). class Punto { double x. } Cadena::~Cadena() { delete []LaCadena.. Página: 213 Si eliminamos el constructor por defecto manteniendo los restantes. Su finalidad es copiar los datos de un objeto a otro.7.3) . public: ~Punto() . etc.4.I.I. //Destructor. al igual que el constructor.© A.h> #define NULO '\0' class Cadena { private: char *LaCadena. Su uso es habitual y se hace necesario cuando el objeto reserva memoria explícitamente pero también puede finalizar asuntos pendientes. el compilador crea uno por omisión. } main() { Cadena c("asdasdasdasd").7. //Esta memoria no se libera strcpy(LaCadena. //Primer constructor.h> #include <string.3. Se denomina constructor copia a un constructor que tiene un único parámetro. Cadena::Cadena() { LaCadena= new char(NULO). Si no definimos un constructor copia explícitamente. El destructor es. } Cadena::Cadena(char *Tira) { LaCadena= new char[strlen(Tira)+1]. y. un método especial de la clase. #include <iostream. //Inicializa a NULO. //Crea s y con el constructor copia s=(2. public: Cadena(). la primera definición es incorrecta puesto que al existir constructores generales el compilador no crea el constructor por defecto. void Print(). ~Cadena(). Se invoca automáticamente justo antes de que el objeto que lo contiene sea destruido. Las llamadas al constructor copia son: Punto p . r(2) . } void Cadena::Print() { cout << LaCadena.Print(). Punto() . No hace nada. friend double Distancia(const Punto &a. //Hay que destruirla explícitamente. d. Cadena(char *Tira). 3. 3). No arrays. double yy) .Destructor. D. Punto(double xx) . c.

} void Desplazar(double a. realiza una copia de los atributos del objeto fuente. Por tanto. double yy= 0) . Punto t= r . } alozanoi@teleline. no se copia la cadena propiamente dicha si no sólo su dirección. y. public: ~Punto() .© A.I. un puntero a char (char *). const Punto &b). sin embargo si la estudiamos más a fondo vemos que los efectos no son los deseados. La solución es la que se da a continuación : Cadena Cadena::operator = (const Cadena &c) { if (this != &c) //Sólo si son distintos objetos (c= c). x+= b . double b) { x+= a . En la clase Cadena creada antes. 0) //Llama al constructor copia . Por ejemplo.es Apuntes de clase . c. podemos usar el constructor copia y el operador de asignación para copiar los datos de un objeto en otro como si se tratase de cualquier otra variable. }. y= p. //Borra el espacio actual LaCadena= new char[strlen(c.y . c. //Operador de asignación p= (2. Cadena s(c). en la clase punto podemos añadir el constructor copia y el operador de asignación: class Punto { double x. } Punto operator=(const Punto &p) //Operador de asignación { x= p.LaCadena). el constructor copia por omisión no nos sirve para solucionar este problema. Punto(double xx= 0. strcpy(LaCadena.y . La diferencia entre usar uno u otro está en que el primero crea un nuevo objeto y después copia los datos y el segundo sólo copia los datos. Cadena c("1234567890"). { x= p. es decir. } Con el operador de asignación sucede exactamente lo mismo.I. D. //Copia la cadena } return *this. Compara direcciones //(*this != c) Compara objetos llamando al operador !=. } friend double Distancia(const Punto &a.LaCadena)+1].x . Página: 214 p= r . Como el constructor copia.LaCadena)+1]. { delete []LaCadena. una sentencia como s. Una solución es la siguiente : Cadena::Cadena(const Cadena &c) { LaCadena= new char[strlen(c. Es decir. Punto(const Punto &p) //Constructor copia.Poner(“00000”) hará que cambie el atributo de s y también el de c puesto que ambos tienen la misma dirección de memoria. Programación en lenguajes estructurados.A. //Crea nuevo espacio strcpy(LaCadena.LaCadena). trabaja sobre un objeto ya creado. Que la última sentencia llame al constructor copia es por que este dispone de dos notaciones (Punto p(q) y Punto p= q) mientras que el operador de asignación sólo dispone de una (p= q). también se incorporan automáticamente el constructor copia y el operador de asignación . //Destructor.L. Hay otro método que implementa el compilador por omisión : el operador de asignación. Cuando copiamos o asignamos un objeto Cadena a otro se realiza una copia de sus atributos. No hace nada.x . y= p.

Vectores de objetos. · Visualizar la cadena. alozanoi@teleline. return OAuxiliar. j. Esta definición llama al constructor por defecto y por tanto inicializa las tres componentes a cero. Página: 215 Ejercicio: Crear una clase cadena con los siguientes elementos sin usar las funciones del archivo cabecera string.Tamanho. } 3.Objetos dinámicos. realizar inicializaciones parciales como la siguiente: Punto Triangulo[3]= {Punto(1.j<=OCadena. y podemos. j++) //strcat() Auxiliar[i + j]= OCadena.. Punto(2.i<Tamanho..8. for (i= 0. etc. · Operador de asignación de objetos y de asignación convencional. · Concatenación de cadenas sobrecargando el operador +. Podemos declarar un puntero a un objeto de la siguiente forma: Punto *p.Tamanho. 1).Punteros a objetos. 1).I. Cadena Cadena::operator +(const Cadena &OCadena) { Cadena OAuxiliar.L. int i. Programación en lenguajes estructurados.I. i++) //strcpy() Auxiliar[i]= LaCadena[i].2. Auxiliar= new char[Tamanho + OCadena. Punto(2.Tamanho + 1]. comparación. 3)} .8.. da error. además.1. donde las componentes no inicializadas llaman al constructor por defecto. OAuxiliar.LaCadena= Auxiliar. · Todas aquellas operaciones con cadenas que se quieran : longitud. La declaración de punteros a objetos es semejante a la declaración de punteros a otras variables o tipo de datos. También podemos inicializar el array de la siguiente forma : Punto Triangulo[3]= {Punto(1.A. si el constructor por defecto no está definido.h: · Constructor por defecto.LaCadena[j].Tamanho= Tamanho + OCadena. 2)} . 3. D. generales y copia. Punto(3. Punto Triangulo[3] . 2). OAuxiliar.© A. char *Auxiliar. for (j= 0.8.es Apuntes de clase . Se pueden definir arrays de objetos igual que se definen de cualquier otro tipo de dato: el tipo de dato base de las componentes del array seguido del identificador y entre corchetes su longitud y número de dimensiones. 3.

} TInfo cPila::Top() { if (!Vacia()) return Cima->Dato. 3) .I. Punto *Puntero= new Punto[100] . 3 //Puntero a array de objetos Ejercicio : CREACIÓN DE UNA PILA #include <stdio. por tanto. }. Página: 216 que crea un puntero a un objeto. TInfo Top().A. delete [100]Puntero . } bool cPila::Vacia() { return Cima == NULL.es Apuntes de clase . cNodo *Sig. bool Vacia(). La última sentencia elimina el objeto de la memoria (llama al destructor) pero el puntero sigue apuntando la misma posición de memoria (no se inicializa a NULL). y. class cPila { private: cNodo *Cima. cPila::cPila() { Cima= NULL. // Reserva memoria y llama al constructor // Llama al destructor y libera la memoria //Construye con 2. class cPila. Nodo->Dato= Info. 1) . class cNodo { friend class cPila. sólo los cuatro bytes para el puntero. Programación en lenguajes estructurados. delete Puntero . } alozanoi@teleline.h> typedef int TInfo. tiene consecuencias imprevisibles. Cima= Nodo. Puntero->Punto::~Punto() .I. } cPila::~cPila() { while (!Vacia()) Pop(). Nodo->Sig= Cima. private: TInfo Dato. Punto *Puntero . public: cPila(). En esta declaración no se realiza la llama al constructor puesto que es la declaración de un puntero. D. Puntero->Desplaza(2. que ya no existe. }. Los ejemplos anteriores muestran que el uso de punteros a objetos es el mismo de siempre. cualquier acceso a ese objeto. Punto *Puntero= new Punto(2. Punto *Puntero . void Pop(). Puntero= &P . tampoco se reserva memoria para el objeto. } void cPila::Push(TInfo Info) { cNodo *Nodo= new cNodo. no de un objeto. void Push(TInfo). Punto P . Puntero= new Punto . delete []Puntero . También podemos reservar y destruir memoria dinámicamente usando los operadores new y delete respectivamente. ~cPila().h> #include <stdlib.L.© A.

Relación de agregación. De esta forma. Booch existen tres clases básicas de relaciones: generalización (la conocemos como herencia). D. } } main() { int i. Esto se consigue implementando los atributos de la clase como objetos de otra. para formar la calculadora.. printf("\n"). Una clase se relaciona con otra a través de los mensajes que le envía. 4. Una clase se puede relacionar con otra de varias formas diferentes. pedales sillín. el Rectángulo está utilizando Pantalla para dibujarse.© A. es su unión. P. entre objetos no relacionados.Pop(). etc.L.I. Especifica una conexión semántica.Relaciones entre clases. las flores y las velas son objetos independientes pero representan cosas que pueden adornar una mesa y las teclas y el visor se asocian. Para que ofrezca una mayor funcionalidad y pueda realizar mayor número de tareas y con más complejidad es necesario que haya una relación entre las clases. Pila. entre otros objetos. Las piezas que la forman. 4.Push(i).e. agregación (y/o composición) y asociación. Programación en lenguajes estructurados. alozanoi@teleline.3. cPila Pila. en cuanto a su significado.2. no realizan ninguna tarea importante por sí solas. una clase se compone de atributos que son objetos de otra clase. Una clase por sí sola no ofrece gran funcionalidad. lo que componen la bicicleta. Otros autores añaden además la relación de uso. deberíamos hacer “Pantalla.Vacia()) { printf("%d\t". i++) Pila.1.A.Top()).I. Cima= Cima->Sig. delete Aux. Una clase puede estar compuesta de otras clases.Relación de uso. while (!Pila. es decir. Según G. Página: 217 void cPila::Pop() { if (!Vacia()) { cNodo *Aux= Cima.es Apuntes de clase . Un ejemplo podría ser una bicicleta. cuadro.Relación de asociación.Dibujar(Rectángulo)”. 4. i<3. } getch().. Pila.. for (i=0. entre otros atributos diferentes. Si disponemos de una clase Pantalla con el método Dibujar() y queremos dibujar un objeto de la clase Rectángulo. } 4. la relación que se establece entre ellas.. Esto se consigue pasando un objeto de la clase como uno de los parámetros del método invocado por el mensaje.

la característica más importante de la POO. 4. la clase persona está formada por objetos de la clase alumno y objetos de la clase profesor. alumno y profesor. recodificación y verificación de la parte (de las clases) ya implementada. Es decir. a ésta relación se le denomina composición cuando los objetos de una clase contenidos en otra clase no pueden ser independientes El ejemplo de la bicicleta sirve para este caso. es un mecanismo que sirve para definir una nueva clase a partir de otra. una vez que nuestra calculadora está implementada. de lo más general a lo más particular. pudiendo añadir nuevas características sin tener que modificar toda la clase de nuevo. Dependiendo de cual sea la visibilidad de los componentes declarados en la clase base (públicos.y de un número determinado de objetos Teclas –de la clase Tecla-. privados o protegidos) y según el tipo de acceso – forma de heredar. que sólo serán bases y las que están abajo. generalmente. La relación entre estas clases viene dada como: la clase Calculadora se compone. La clase Calculadora vista con anterioridad puede componerse del objeto Display -de la clase Visor. que sólo serán derivadas. sin duda.© A. Por ejemplo. todas las clases serán base y derivadas excepto las primeras. a su vez. utilizar lo que nos ofrezca –sus atributos y métodos-.I. Ahora. no es necesario implementar todos sus atributos y métodos puesto que un alumno es una persona. Esta. Por ejemplo. y añadirle las nuevas características y comportamiento del alumno –Expediente. en una jerarquía de clases. por tanto. La herencia. tienen autonomía propia.A. Para ello.es Apuntes de clase . Y a la relación se le denomina agregación cuando los objetos de una clase contenidos en otra clase pueden ser independientes. A través de ella se pueden construir nuevas clases partiendo de una jerarquía de clases ya existente (comprobadas y verificadas) evitando con ello el rediseño.I..de la subclase. si disponemos de una clase persona que define las características y comportamiento de los objetos persona y creamos una clase alumno. Cada uno de estos. sólo es necesario heredar de la clase persona. Notas. En general. Faltas-. Es. a unos se tendrá acceso y a otros no. La clase de la que se hereda se denomina clase base o superclase y la que hereda se denomina clase derivada o subclase. es decir. ésta tendrá o no acceso a determinados componentes. sin embargo. Dependiendo del lenguaje de programación utilizado para la implementación. sólo tenemos que declarar una nueva subclase de Calculadora alozanoi@teleline. puede ser heredada por otra clase convirtiéndose en clase base. Página: 218 Algunos autores. Programación en lenguajes estructurados. Utilizaremos indistintamente un término u otro. La herencia es el mecanismo fundamental para implementar la reutilización y extensibilidad del software.Relación de herencia. existe una “herencia o visibilidad selectiva” de los componentes de la clase base en la subclase. consiste en que la subclase hereda todos los atributos y métodos de la clase base sin necesidad de cambiar nada de esta. las subclases pueden acceder o no aquellos atributos y métodos que se indiquen en el interfaz de su clase base. la generalización hace alusión a la relación existente entre las clases. relación de composición. Los términos generalización y herencia se refieren a aspectos de la misma idea y habitualmente se utilizan indistintamente. Aquí usaremos el término herencia. de la clase Visor y de la clase Tecla.4. puede que necesitemos añadirle una nueva funcionalidad y con ello ampliar su comportamiento: cambiar de pesetas a euros y viceversa.L. Simplemente los utiliza. D. y la herencia al mecanismo empleado para compartir atributos y métodos usando la relación de generalización.

B2= b. Página: 219 “EuroCalculadora” y añadirle las nuevas características: un atributo que indica si los cálculos se están realizando en pesetas o en euros. } La clase derivada hereda todos los miembros de la clase base aunque seguimos sin tener acceso a los miembros privados de la clase base dentro o fuera de la clase derivada. Si podemos modificar los miembros privados de la base usando los métodos públicos disponibles para ello.es Apuntes de clase . B2. Ejemplo : #include <iostream. alozanoi@teleline. D. Programación en lenguajes estructurados. ob.I.A. Clase Euro : HEREDA de la Clase Tecla Atributos y métodos públicos Pulsar()(Obligados a implementarlo si era un Método abstracto) Fin de la clase Euro Clase EuroCalculadora : HEREDA de Calculadora Atributos y métodos privados Muestra es de tipo numérico (un valor 0 indica pesetas) Euros es de tipo Clase Euro Atributos y métodos públicos CambiaEurosPesetas() Fin de la clase EuroCalculadora El formato general de declaración de una clase derivada en C++ es el siguiente : class NombreClaseDerivada : Acceso NombreClaseBase { Nivel De Acceso: Componentes: datos y funciones Nivel De Acceso: Componentes: datos y funciones }[Lista de objetos]. 2). una nueva tecla que la declaramos como una nueva subclase de Tecla o de Comando y un método para cambiar entre euros y pesetas. class Derivada : public Base { int D. ob. } void MostrarD() { cout << D << endl. } }.MostrarD(). public: void Poner(int a.h> class Base { int B1. } }.L.© A. } void MostrarB() { cout << B1 << " " << B2 << endl. void main() { Derivada ob(3).MostrarB().I.Poner(1. ob. public: Derivada(int a) { D= a. int b) { B1= a.

void main() { Derivada ob(1.1.. Página: 220 Para construir una clase derivada se pueden definir constructores de la siguiente forma : ConstructorDerivado(Tipos Parámetros) : ConstructorBase(Parámetros) . c) { D= a. Programación en lenguajes estructurados... no pueden ser accedidos desde la clase derivada : class Derivada : public Base { . int b.Acceso a miembros heredados y tipos de acceso. Derivada(int a..//Error. B2= c . los miembros protegidos si son accesibles desde la clase derivada. } . se llama al constructor por defecto de la misma.es Apuntes de clase . Una clase derivada no hereda de la clase base los constructores.. Sin embargo. como los atributos miembros están definidos como privados a la clase base. privado y protegido.... Si no ponemos explícitamente la llamada al constructor de la clase base.. private: están protegidos de todo acceso fuera de la clase en la que están definidos. Es decir. 3). public: son accesibles desde cualquier lugar.A. que debe existir (creado por el compilador o por nosotros). los miembros de una clase pueden tener tres tipos de acceso: público. el destructor y los operadores de asignación por que son los que definen los fundamentos de la clase. Privados de la clase base. primero se llama al constructor de la clase base y después al de la derivada. protected: están protegidos contra todo acceso fuera de la clase donde fueron definidos y de las clases derivadas. primero se llama al destructor de la clase derivada y después al de la clase base.4. }..I. }.. class Derivada : public Base { .I. int c) { D= a . los destructores se llaman en sentido inverso al de derivación. 4. int c):Base(b.© A. } . int b. es decir.. Ejemplo : class Base { . } . B1= b . 2. void PonerD(int a. int b) { B1= a. B2= b. } alozanoi@teleline. D. En el ejemplo anterior. } De esta forma inicializamos miembros de la clase base que hemos heredado. Los constructores se ejecutan en orden de derivación.. Como ya se vio. Base(int a.L.

y los convierte en privados. pueden ser modificados desde cualquier lugar. . Ahora si podemos acceder a dichos atributos desde la clase derivada pero no desde el exterior.a. pasando a ser privados de la clase derivada.x. 2) + pow(y . Punto(double xx= 0.y. class D:privated B . double yy= 0) { x= xx. B2. public: Figura(int N.x).L. #include <iostream. } double operator . // Acceso a los miembros no privados de A // Acceso a los miembros no privados de A //Acc. pero entonces. El cuadro siguiente muestra la visibilidad de los miembros según el tipo de acceso a la clase a la clase base: pública protegida privada Clase BASE Públicos Protegidos Privados Públicos Protegidos Privados Públicos Protegidos Privados Clase DERIVADA Públicos Protegidos sin acceso Protegidos Protegidos sin acceso Privados Privados sin acceso class A . } }.b.y). Página: 221 La solución podría consistir en definir como públicos los miembros B1 y B2. class Figura { protected: int NPuntos. y= yy. 2)).es Apuntes de clase .a. 2)). 2) + pow((a. const Punto &b) { return sqrt(pow((a. class E:public D . ya que se comportan como privados de esta clase. class Base { protected : int B1. class C:protected B . D.A. class B:protected A .(const Punto &a) { return sqrt(pow(x . El problema se soluciona definiéndolos como protegidos.I. variando también el nivel de acceso de los miembros. y. } alozanoi@teleline. public: ~Punto(){}.b. Programación en lenguajes estructurados. Punto *Puntos.© A. Puntos= Ptos.h> #include <math..y .h> class Punto { double x. } friend double Distancia(const Punto &a.I. } . Punto *Ptos) { NPuntos= N.. Al derivar la clase también podemos definir el tipo de acceso a la clase base. rompiendo la encapsulación. // No tiene acceso a los miembros de A.x . a miembros no priv.

1416*Radio. Ptos) { Radio= R. } }. getch(). Programación en lenguajes estructurados..double unInteres=0) { Nombre = new char[strlen(unNombre)+1]. Punto(1. strcpy(Nombre. i++) Peri+= Distancia(Puntos[i].I. Puntos[0]). // Interés aplicado public: C_Cuenta(const char *unNombre.Herencia múltiple y clases virtuales. Una clase puede heredar los atributos y los métodos de una o más clases base. unNombre). // Saldo Actual de la cuenta double Interes. } inline char *GetNombre() { return Nombre.es Apuntes de clase . double Peri= 0. // Nombre de la persona double Saldo.Perimetro().2. for(i= 0. Puntos[i + 1]). 2). cout << r. return Peri. } double Perimetro() { return 2*3. } }. Peri= Distancia(Puntos[NPuntos . En el caso de que herede los componentes de una única clase se habla de herencia simple y en el caso de que herede los componentes de varias clases base se trata de un caso de herencia múltiple. cout << r. Rectangulo r(p).4. 3). Ptos) { } double Area() { return (Puntos[0]-Puntos[1])*(Puntos[1]-Puntos[2]). } ~Cuenta() { delete [] Nombre.1416*Radio*Radio. 3). i<NPuntos-1. Punto *Ptos):Figura(1.h> class C_Cuenta { private: char *Nombre.1]. SetInteres(unInteres). Página: 222 double Perimetro() { int i.© A. } }. } 4.I.L. public: Circulo(int R.double unSaldo=0.A. } double Area() { return 3. Se podría definir la clase C_CuentaEmpresarial como la herencia múltiple de dos clases base: la clase C_Cuenta y nueva clase llamada C_Empresa. class Circulo:public Figura { private: double Radio.Area(). Punto(2. Punto(1 . D. class Rectangulo:public Figura { public: Rectangulo(Punto *Ptos):Figura(4. que se muestra a continuación: #include <iostream. } alozanoi@teleline.2)}. SetSaldo(unSaldo). main() { Punto p[4]= {Punto(2. Como ejemplo se puede presentar el caso de que se tenga una clase para el manejo de los datos de la empresa.

si de la clase Calculadora heredan las clases Calculadora de Euros y Calculadora Científica. } } class C_Empresa { private: char *NomEmpresa.es Apuntes de clase .. Programación en lenguajes estructurados.I. } ~C_Empresa() { delete [] NomEmpresa. Página: 223 inline double GetSaldo() { return Saldo.I. Esto hace que los miembros de una clase de ese tipo se hereden tan sólo una vez. es decir. }. varios componentes con igual nombre (cada lenguaje que lo resuelva.. Para evitar este problema los lenguajes lo hacen de tres formas: No está permitida la herencia múltiple.unSaldo. Para evitar este problema las clases Madre_1 y Madre_2 deben derivar de la clase Abuela declarándola clase base virtual. los miembros de la clase Abuela se encontrarán duplicados en la clase Hija.A. double unSaldo=0.0. double unInteres=0. } // Otros métodos . a su vez. indirectamente. Al utilizar la herencia múltiple puede suceder que. class C_CuentaEmpresarial : public C_Cuenta.. Hay que cualificar las componentes.L. public C_Empresa { public: C_CuentaEmpresarial( const char *unNombre. const char *laEmpresa.. en esta los componentes de la clase Calculadora se encontrarán duplicados. C_Empresa(laEmpresa) // se llama a los constructores de las clases base { // Constructor } // Otros métodos }. Un ejemplo de declaración de una clase base virtual es el que se presenta a continuación: class Madre_1 : virtual public Abuela { .0 ):C_Cuenta(unNombre. en C++ se cualifica: objeto. y de estas hereda la clase Calculadora de Euros Científica. D. public: C_Empresa(const char*laEmpresa) { NomEmpresa = new char[strlen(laEmpresa)+1]. alozanoi@teleline. strcpy(NomEmpresa. laEmpresa).Clase::componente). } También puede darse otro problema: la duplicidad de componentes. los miembros de las clases Madre_1 y Madre_2. Es decir. (clase base virtual en C++) Si la clase Madre_1 y la clase Madre_2 heredan los miembros de la clase Abuela y la clase Hija hereda. Se crea una copia única de la clase base. unInteres).© A. una clase herede varias veces los miembros de otra clase.

porque puede suceder que no se disponga de valores para todas las variables miembro de la clase derivada. Esto quiere decir que se puede hacer referencia a un objeto de la clase derivada con su dirección contenida en un puntero a la clase base. en este caso). aunque en esa operación se pierda información.0.© A.4. Por el contrario las conversiones o asignaciones en el otro sentido.. // . void main() { // Válido C_CuentaEmpresarial *c1 = new C_CuentaEmpresarial("Juan". según el diccionario de la RAE.I. es decir de lo más general a lo más particular. la siguiente asignación sería correcta: Objeto_clase_base = Objeto_clase_derivada // Asignación válida Objeto_clase_derivada = Objeto_clase_base // Asignación incorrecta En el siguiente ejemplo se pueden ver las distintas posibilidades de asignación (más bien de inicialización. Es posible realizar conversiones o asignaciones de un objeto de una clase derivada a un objeto de la clase base.es Apuntes de clase . en el caso de que esa función se encuentre definida tanto en la clase base como en la derivada. que se presentan en la clase C_CuentaEmpresarial. Así. Al igual que sucede con los nombres de los objetos. En definitiva. sin tener que especificar el tipo exacto de los objetos. pues haya variables que no tengan a qué asignarse (el número de variables miembro de una clase derivada es mayor o igual que el de la clase de la que deriva). debido a que también los datos pueden presentar cierto tipo de polimorfismo: un identificador puede hacer referencia a objetos de distintas clases jerárquicamente relacionadas. Así pues. Se utilizan los valores por defecto C_Cuenta *c2 = new C_CuentaEmpresarial("Igor". en principio cuando se hace referencia a un objeto por medio de un puntero. 5. // Válido. // NO VÁLIDO C_CuentaEmpresarial *c3 = new C_Cuenta("Igor". 1. } De forma análoga..0). En el ámbito de la POO es la capacidad de llamar a métodos distintos con el mismo nombre.A. polimorfismo “es la propiedad que tienen algunos cuerpos para cambiar de forma sin variar su naturaleza”.0).I. 10. polimorfismo representa a la capacidad de adoptar formas distintas.. "Patata CORP").. Programación en lenguajes estructurados. un puntero a la clase base puede almacenar la dirección de un objeto perteneciente a una clase derivada. Sin embargo. Página: 224 4.Conversiones entre objetos de clases base y clases derivadas. es decir. Por definición. no los de la clase a la que pertenece el objeto.0. Es decir se puede ir de lo más particular a lo más general. Estos pueden actuar sobre objetos distintos dentro de una jerarquía de clases. no son posibles. el tipo de dicho puntero determina la función miembro que se aplica. "Jugos SA". se aplicarán los métodos de la clase a la que pertenezca el puntero. 100000. alozanoi@teleline. D. se puede guardar la dirección almacenada en un puntero a una clase derivada en un puntero a la clase base.Polimorfismo. 100.L. el polimorfismo adquiere una relevancia especial.3.

Por ejemplo. 2). La diferencia entre éstas está en el número y/o tipo de sus parámetros.I. y no se tienen en cuenta los posibles cambios de referencia. class Derivada : public Base{ int D. 4. el método a aplicar puede determinarse en tiempo de compilación..Sobrecarga de métodos y operadores. Esto se conoce como vinculación o enlace estático. pero sus distintos comportamientos no tienen ninguna relación. el término polimorfismo se reserva para aquellos casos en los que la sobrecarga sobreviene como consecuencia de la herencia de clases. c) { D= a. Aunque la sobrecarga de métodos es una forma de polimorfismo... del mismo modo que un identificador de función puede representar distintas secciones de código. la operación “sumar” se puede aplicar tanto a números enteros como reales. Esto se debe a que el compilador comprueba el tipo del objeto y dependiendo de cual sea llama al método correspondiente. public: { Base(int a.© A.es Apuntes de clase . B2= b. B2. Página: 225 dependiendo del contexto.2. } void Mostrar() { cout << D << endl.Herencia de clases.2. Cuando el polimorfismo sobre una función u operador (no todos los lenguajes OO lo permiten) se presenta en situaciones en las que el nombre de la misma coincide.1. Si todos los objetos son asociados estáticamente a una clase. Programación en lenguajes estructurados. int b. public: Derivada(int a. #include <iostream> using namespace std. La declaración del método debe ser idéntico y cada uno tendrá un comportamiento similar pero no idéntico en diferentes clases de objetos y cada uno seguirá una implementación específica. 5).Mostrar().I. derivada.1. 5.Mostrar(). alozanoi@teleline. } // Llama a Mostrar() de la clase base // Llama a Mostrar() de la clase derivada 5.Enlace estático. Derivada derivada(3. 5.A. } }. int c):Base(b. } void Mostrar() { cout << B1 << " " << B2 << endl. // Mostrar de la clase base } }. pero no hay relación entre ellas. int b) B1= a. utilizamos el término “sobrecarga” de funciones o de operadores. base. sin que el sistema sufra ningún tipo de sobrecarga. D. class Base{ int B1. int main(){ Base base(1.L. Base::Mostrar().

return Peri.Perimetro(). //Invoca a Perimetro() de R Circulo C.1416*Radio. Circulo C. for(i= 0. Punto *Ptos):Figura(1. *FP. } }. De esta manera llamamos al método Perímetro() de Circulo aplicado a C.I.es Apuntes de clase . FP= &C.1416*Radio*Radio. public: Figura() { } Figura(int N. } double Area() const { return 3. public: Circulo(int R. Ptos) { } double Area() const { return (Puntos[0]-Puntos[1])*(Puntos[1]-Puntos[2]). i<NPuntos-1. Punto *Ptos) { NPuntos= N. Página: 226 Rectángulo R. i++) Peri+= Distancia(Puntos[i]. alozanoi@teleline. Programación en lenguajes estructurados. Peri= Distancia(Puntos[NPuntos .Perimetro(). C. double Peri= 0. Puntos[0]). } double Perimetro() { return 2*3. de Figura. class Rectangulo:public Figura { public: Rectangulo(Punto *Ptos):Figura(4. La última línea invoca al método Perímetro() de la clase base.I. } }. Por conversión entre clases un objeto o puntero a un objeto de una clase base acepta objetos o punteros a objetos de sus clases derivadas. Punto *Puntos.1].A. Para solucionar el problema podemos recurrir a moldear (cast) el objeto en cuestión: ((Circulo* )FP)->Perímetro().© A. FP->Perímetro(). Las cosas se nos pueden poner peor si queremos calcular el área del circulo puesto que Figura no dispone de ese método. Puntos[i + 1]). D. Puntos= Ptos. Supongamos el siguiente fragmento de programa: Figura F. R. } virtual double Perimetro() { int i.L. class Circulo:public Figura { private: public: double Radio. class Figura { protected: int NPuntos. } }. //Invoca a Area() de C Lo mismo sucede cuanto trabajamos con punteros o referencias a clases aunque no está exento de problemas. Ptos) { Radio= R. produciéndose un error en los cálculos dado que dicho método no sabe calcular el perímetro de un círculo.

2. si no que dependerá de la clase del objeto a la que pertenece. Puntos= Ptos. si no que debe hacerse en tiempo de ejecución. public: Figura(){} Figura(int N. alozanoi@teleline. se denomina vinculación o enlace dinámico. } virtual double Area() const= 0.1416*Radio.I. return Peri. Ptos){} virtual double Area() const { return (Puntos[0]-Puntos[1])*(Puntos[1]-Puntos[2]).Enlace dinámico. Cuando el método que se debe ejecutar no se puede determinar en tiempo de compilación.2. Puntos[0]).1]. Peri= Distancia(Puntos[NPuntos . Punto *Ptos):Figura(1. Puntos[i + 1]). Para las funciones que vayan a tener un puntero para ligar el objeto con su método se definiran funciones virtuales. class Figura { protected: int NPuntos. Una función virtual el un método especial que se llama a través de un puntero o una referencia a su clase base y se enlaza dinámicamente en tiempo de ejecución. i<NPuntos-1. que se pueda aplicar no sólo a objetos existentes. La implementación del código para que exista vinculación dinámica depende del lenguaje OO. La sintaxis para definir un método virtual es el siguiente: virtual <Tipo de retorno> <Nombre de método>(<Parámetros>). public: Circulo(int R. Para que se de este tipo de vinculación no se puede trabajar con objetos estáticos si no que hay que trabajar con objetos dinámicos: referencias o punteros a ellos. }. Programación en lenguajes estructurados. class Circulo:public Figura { private: double Radio.© A. D. } virtual double Area() const { return 3. Punto *Puntos.L.1416*Radio*Radio. } virtual double Perimetro() { int i.. si no también a objetos que sean añadidos en etapas futuras del desarrollo.es Apuntes de clase . double Peri= 0. class Rectangulo:public Figura { public: Rectangulo(Punto *Ptos):Figura(4. Ptos) { Radio= R. } }. En la vinculación dinámica el método invocado no depende del tipo del objeto usado para referenciarlo. } virtual double Perimetro() { return 2*3. Página: 227 5. Punto *Ptos) { NPuntos= N. haciendo posible implementar software genérico. } }. i++) Peri+= Distancia(Puntos[i]. El polimorfismo facilita la reutilización de software.A.I. for(i= 0.

La sintaxis de declaración de un método virtual es la siguiente: virtual <Tipo de retorno> <Nombre de método>(<Parámetros>)= 0.L. o se redefina también como abstracto. Figura *pf. Programación en lenguajes estructurados. Una clase abstracta es aquella que sólo sirve como clase base para otras clases y no puede ser instanciada (no puede haber objetos de esa clase) aunque si puede haber punteros o referencias a ella. 2). Area2. En el caso de que no se redefina alguno. D. Por ello.I. La clase Figura es una clase abstracta por que no conocemos exactamente cual es el comportamiento del método Area(). 6.. la clase heredada también será abstracta. que además está obligada a implementar para poder instanciar sus objetos. const Figura &f2) { int Area1. cout << MayorArea(r.I. } Ahora podemos trabajar con punteros o referencias a objetos con la seguridad de que llamarán a las funciones correctas. if(Area1 < Area2) return -1. Normalmente se trata de clases que representan conceptos abstractos que no pueden ser instanciados. &p). } main() { Punto p= Punto(2. Area2= f2. Punto *Puntos.A. Sirve como clase base de otras subclases. cada figura calcula el área de una forma diferente.Clases abstractas. Circulo c(2. Página: 228 int MayorArea(const Figura &f1. else if(Area1 > Area2) return 0. se crea para que contenga aquellos atributos y métodos comunes a todas las clases que deriven de ella. // Llama a Perimetro() de Círculo sin hacer el moldeo. Esto es muy útil cuando funciones que tienen como parámetros formales punteros o referencias a una clase base reciben como parámetros actuales punteros o referencias a objetos de clases derivadas. En el ejemplo anterior se ve claro este uso. Las clases derivadas de una clase abstracta deben declarar todos los métodos abstractos heredados. Un método abstracto define el protocolo o interfaz para que una operación polimórfica pueda ser redefinida mediante métodos específicos correspondientes a sus subclases. else return 1. dejamos que sea la subclase que herede de Figura la que implemente su comportamiento concreto.Area().© A.Area(). Una clase abstracta se construye incluyendo un método (método virtual puro) abstracto dentro de su definición o indicando que la clase es abstracta –depende del lenguaje-.es Apuntes de clase . c). Area1= f1. pf= &c. si los hay. public: alozanoi@teleline. pf->Perimetro(). class Figura { protected: int NPuntos.

Programación en lenguajes estructurados. clases abstractas. Por último. la clase de lenguajes realmente orientados a objetos es la más restrictiva. C++ y Java. Java. y el manejo de éstas mediante herencia. Smalltalk.I. Puntos[0]). pero no a Ada. Puntos= Ptos. D. y contiene a los lenguajes que soportan la funcionalidad de los objetos. Peri= Distancia(Puntos[NPuntos . return Peri. · Los lenguajes basados en objetos son aquellos que soportan la funcionalidad de los objetos. 7.es Apuntes de clase . Smalltalk. no pueden ser pasadas como parámetros. es decir. Los lenguajes que además incluyen el concepto de clase de objetos como entidad de primera clase se denominan basados en clases. Eiffel. Punto *Ptos) { NPuntos= N. su manipulación mediante clases. } virtual double Perimetro() { double Peri= 0.y los segundos mezclan la POO con la programación procedimental -C++-. debido a que sus clases de objetos no se identifican con un tipo. aunque está basado en clases. Cobol o Pascal. Esta familia de lenguajes incluye Ada. en fin. vinculación dinámica. éstas no pueden relacionarse mediante un mecanismo como la herencia. . métodos y mensajes) –Smalltalk. Java y excluye a lenguajes como Fortran. que no proporcionan objetos como primitiva del lenguaje (aunque existen variantes de estos lenguajes que si soportan objetos).L.Lenguajes de POO. Estos siguen incluyendo a CLU. C++. Eiffel.1]. for(int i= 0. Simula. clases genéricas. CLU y Smalltalk. } virtual double Area() const = 0.I. respectivamente. aquellos que utilizan objetos. C++ y Java.. i<NPuntos-1. }. Los primeros sólo trabajan con programación orientada a objetos (clases. ni ser componentes de un registro. Y queda excluido CLU que. Se pueden catalogar como lenguajes OO: Simula. Smalltalk. una vez eliminados los anteriores. alozanoi@teleline. objetos. Los lenguajes de POO pueden clasificarse.. todas las características expuestas anteriormente.. Según Wegner los lenguajes de POO se pueden clasificar en tres categorías: los asociados con Ada. //Método virtual puro. Eiffel. · · Las características mencionadas en esta clasificación en relación a la orientación a objetos (clases + herencia) no son suficientes para poder obtener los beneficios reales de la orientación a objetos. Simula.© A. Página: 229 Figura() { } Figura(int N. en términos de reutilización y extensibilidad. Puntos[i + 1]). en dos grandes grupos: lenguajes puros y lenguajes híbridos. Hay otros aspectos que son también trascendentales para poder utilizar un lenguaje orientado a objetos con la expresividad que caracteriza a éstos: polimorfismo. CLU. i++) Peri+= Distancia(Puntos[i].A..

sólo puede obtenerse por los cauces adecuados. Es el lenguaje de POO posiblemente más utilizado en la actualidad. Sólo permite herencia simple. · Es seudocompildor lo que hace más lento que un compilador y más rápido que un intérprete. Las clases también son objetos..3. D.2. tienen unas características muy similares: encapsulación. Página: 230 Ventajas · · · · Puros Más potencia. clases abstractas. Flexibilidad para modificar el lenguaje. Es el lenguaje de POO por antonomasia.A. Es un lenguaje de POO puro.Lenguaje Java. 7. vinculación dinámica. objetos métodos y mensajes. polimorfismo. sólo puede obtenerse por los cauces adecuados.Lenguaje C++. Los objetos ocultan su información (encapsulación) dependiendo de niveles de acceso. Más lento.I. etc. Tiene una jerarquía de clases cambiante. · · · · · · Es interpretado lo que hace que resulte relativamente lento.Lenguaje Smalltalk. objetos métodos y mensajes. Tiene una librería jerárquica de clases bien definida y comienza en la clase Object. · · · · · Es compilado lo que hace que resulte muy rápido. Algunas clases están estandarizadas. Más fácil de aprender y enseñar. Permite herencia simple y múltiple. 7. Modificar el lenguaje es difícil. procedimental a POO es fácil. Es un lenguaje de POO creado por Sun Microsystems en los noventa (1995). Los objetos ocultan su información (encapsulación). herencia clases genéricas. Su versión conocida como Smalltalk-80 apareció en 1983.1. Mezcla la programación en C con clases. Creado por Bjarne Stroustrup en los ochenta. 7.. Creado por Alan Kay en los ochenta. Es un lenguaje de POO híbrido. Trabajan con un único modelo.I.es Apuntes de clase . C++ y Java. Inconvenientes · · · Trabaja con dos modelos a la vez. Los tres lenguajes de POO que vamos a ver. Cada compilador de C++ tiene su propia jerarquía de clases lo que hace muy difícil su aprendizaje. · · Híbridos Más rápido Pasar de prog. Smalltalk. tiene una sintaxis semejante a la de C++ y su importancia se encuentra en la utilización dentro del marco de internet..L.© A. Programación en lenguajes estructurados. alozanoi@teleline. Sólo trabaja con clases.

alozanoi@teleline. Programación en lenguajes estructurados..A. Sin embargo dispone de los tipos de datos simple (int. Página: 231 · · · · · Es un lenguaje de POO puro. Sólo utiliza clases. objetos métodos y mensajes.) aunque también están implementados en clases. sólo puede obtenerse por los cauces adecuados.es Apuntes de clase . D. Dispone de un recolector de basura. Tiene una librería jerárquica de clases bien definida y estándar. char.© A. Los objetos ocultan su información (encapsulación) dependiendo de niveles de acceso.L.. Sólo permite herencia simple.I.I. .

Sign up to vote on this title
UsefulNot useful