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

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

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

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

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

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

Página: ix INTRODUCCIÓN. 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. Teniendo en cuenta las capacidades terminales asociadas al módulo y las características generales del ciclo formativo.L. el eje del proceso de aprendizaje.I. Por tanto. Conocer y usar las utilidades para desarrollo y puesta a punto de programas. hemos optado por el siguiente enunciado para el contenido organizador: Elaborar. será de tipo procedimental. se entiende que el proceso educativo ha de organizarse en torno a los procedimientos. Aplicar las técnicas de programación estructurada empleando la metodología más frecuentemente utilizada para programar. · · · · · · · · · · · · Adquirir el concepto de programa como método para resolver problemas generales. rutinas y utilidades. 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. alozanoi@teleline. D. tanto estáticas como dinámicas.A. 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. Utilizar el lenguaje de programación C para la codificación de los programas. operaciones sobre los datos e instrucciones de control y manipulación.I. Analizando las capacidades terminales del módulo. el contenido organizador. OBJETIVOS. siguiendo las especificaciones del diseño y el diagrama de estructuras. incluidas y no incluidas en el entorno de desarrollo integrado. Conocer los elementos básicos de un programa: datos. que habitualmente proporcionan los lenguajes de programación. Entender y manejar las estructuras de datos externas. 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. Integrar y enlazar módulos de programación. Programación en lenguajes estructurados. que el aprendizaje se orienta hacia los modos de saber hacer. Conocer las características generales de los lenguajes de tercera generación.es Apuntes de clase . Entender y manejar las estructuras de datos internas. 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. Codificar programas en lenguajes de programación de tercera generación.© A. adaptar y probar programas para mejorar la explotación del sistema y las aplicaciones.

pero los pasos para la elaboración del plato se realizarán sin importar el cocinero. para ejecutarlo. Documentar los programas. debemos tener en cuenta que el lenguaje de programación es. y un ordenador es sólo un procesador.L. 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. 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. Programar en lenguajes estructurados de tercera generación: Lenguaje C. D... Para poder llegar a realizar un programa es necesario el diseño previo de un algoritmo.es Apuntes de clase .I. Expresar el algoritmo como un programa en un lenguaje de programación adecuado: C. incluidas y no incluidas en el entorno de desarrollo integrado. el algoritmo realizado debe ser el mismo para calcular el área de cualquier rectángulo. en realidad. que habitualmente proporcionan los lenguajes de programación. el algoritmo que estamos utilizando para resolver este problema consta un conjunto de pasos que nos han enseñado en clase de matemáticas. de la misma forma que una receta de cocina puede ser expresada en cualquier idioma. 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. una máquina. Por ejemplo. alozanoi@teleline.I.© A. Página: 1 1. Un algoritmo es un método general de resolución de todos los problemas del mismo tipo. El propósito fundamental de éste módulo es la resolución de problemas mediante un ordenador. El eje central de la metodología gira en torno al concepto de algoritmo. 2. siendo éste valido para todos los problemas de iguales características.RESOLUCIÓN DE PROBLEMAS CON ORDENADOR 1. C++. 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. Pascal.Concepto de algoritmo.. todo problema puede ser expresado en forma de algoritmo. Conocer y usar las utilidades para desarrollo y puesta a punto de programas. es decir. Introducir al alumno en la programación orientada a objetos. Programación en lenguajes estructurados. Por tanto. de forma que sin un algoritmo no puede existir un programa. independientemente de que tengan una altura o una base mayor o menor.Introducción. un mero medio de expresar un algoritmo. etc.A.. Entender y manejar las estructuras de datos: internas (estáticas y dinámicas) y externas. si queremos calcular el área de un rectángulo.

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

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

El flujo de control de un algoritmo es usualmente secuencial.A.. Como hemos visto anteriormente. hay que representar el algoritmo con una determinada herramienta de programación como es el diagrama de flujo o el pseudocódigo. este algoritmo. se puede descomponer en pasos más simples siguiendo el método de refinamiento sucesivo.Escritura inicial del algoritmo. Subproblema Dar coeficientes introducir la ALTURA ÁREA <-.I. un algoritmo consiste en realizar una descripción paso a paso del problema en cuestión.es Apuntes de clase .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. de forma que una acción no se realiza hasta que no ha sido realizada la anterior: sin embargo. Programación en lenguajes estructurados.© A. 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. 4. el algoritmo anterior se puede escribir de la siguiente forma: Inicio. Página: 4 introducir la ALTURA calcular el ÁREA visualizar ÁREA 2. Así. en un primer refinamiento. existen unas reglas que tienen las siguientes propiedades: · · Deben estar seguidas de alguna secuencia definida de pasos hasta que se obtenga un resultado diferente.L.Ecucación de segundo grado.I. consta de cuatro acciones que se realizan una a continuación de otra y en un orden estricto. el algoritmo es muy simple. veamos el algoritmo correspondiente a la siguiente pregunta: ¿Qué hacer para ver la película “Casablanca"?. D. ver la cartelera del cine si no proyectan "Casablanca" entonces decidir otra actividad alozanoi@teleline.1. Para una correcta descripción de un algoritmo simple basado en una serie de cálculos elementales. Sólo puede ejecutarse una operación a la vez..

vamos a aplicar esta técnica a la acción: "encontrar el asiento correspondiente". 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.I. todo depende de la imaginación del programador. las acciones que van dentro de las estructuras fundamentales se han desplazado a la derecha. Como se ha dicho en puntos anteriores.A. D. repetir_hasta). 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. 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.© A. podemos seguir aplicando el método de refinamiento sucesivo sobre el algoritmo. Incluyen los conceptos de selección (si_entonces_sino) y los de repetición (mientras_hacer. Otro ejemplo de algoritmo es el que responde a "cambiar una rueda de un coche". es posible un refinamiento sucesivo.I. Como puede observarse.L. 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.es Apuntes de clase . Se ha empleado la identación (sangrado o justificación) para la escritura del algoritmo. así. es decir. Programación en lenguajes estructurados.

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

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

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

.Compiladores. 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. Programación en lenguajes estructurados.I.I. Para solucionar este problema. 6.5.. los programas escritos en lenguajes de alto nivel deben ser traducidos a lenguaje máquina. Inconvenientes: · Incremento del tiempo de puesta a punto de los programas al necesitarse diferentes traducciones del programa.). Esta conversión puede ser realizada de dos formas diferentes: compilación e interpretación.4. PRINT. Al igual que en los lenguajes ensambladores. además de ser independientes de la máquina (son portables a otros ordenadores).1.es Apuntes de clase . A diferencia del anterior. . · Transportabilidad. es necesario convertir los programas escritos en el primero al segundo. D. 6. · Fácil modificación y puesta a punto.A.. es difícil y tedioso utilizarlo. Página: 9 6.Traductores de lenguaje.2. · Aumento de la ocupación de memoria. · El tiempo de ejecución de los programas es mucho mayor. Una vez diseñado el lenguaje de alto nivel. El resultado es un nuevo programa escrito en lenguaje máquina inteligible por misma. Esta técnica se denomina traducción y al programa compilador.© A.5.Intérpretes.L. como la máquina no reconoce mas que el lenguaje máquina. · No se aprovechan los recursos internos de la máquina que se explotan mejor en los lenguajes máquina y ensambladores. 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. · La escritura de programas se basa en reglas sintácticas similares a los lenguajes humanos (READ. Debido a que el lenguaje máquina es demasiado elemental. no requiere la alozanoi@teleline.5. · Reducción del coste de los programas. 6... Ventajas: · Formación corta. 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. 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..Lenguajes de alto nivel.

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

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

.

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

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

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

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

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

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

I.Evaluar las siguientes expresiones: Valores: a= 1.L. b = 6.A. Programación en lenguajes estructurados.. b = 6 4.I.es Apuntes de clase . c = 4 d) (a + 5) * 3 / 2 * b .© A. b = 4. D. Página: 19 Valores: a = 3. 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. c = 10.b Valores: a = 3.

.

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

un valor de un tipo de dato específico. Programación en lenguajes estructurados. b) El valor obtenido se almacena en la variable cuyo identificador está a la izquierda del operador de asignación. Es decir. es decir. 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.es Apuntes de clase .2. 2.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. por tanto.Instrucción de asignación. Usada para darle el valor que le corresponda a una variable. La sentencia de asignación es destructiva.I.A.I. y obtiene. Página: 22 2. y EXPRESIÓN es cualquier expresión válida (bien construida) cuyo tipo de resultado se corresponda con el tipo de la variable. no dependen de otra cosa que de su propia aparición en el programa para ser ejecutadas. D. sustituyendo el valor que tenía anteriormente.© A. Ejemplo: x (.. Esta instrucción es conocida como sentencia de asignación. debe existir una concordancia de tipo de dato entre el identificador y la expresión.Instrucciones primitivas.. 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.L.2. previamente declarado. Son aquellas que ejecuta el procesador de modo inmediato.1. para que una sentencia de asignación sea correcta. El formato general de su uso es IDENTIFICADOR EXPRESIÓN donde IDENTIFICADOR es cualquier nombre de objeto válido.b + (b * b . La operación de asignación se representa con el símbolo u operador “ “ (flecha con sentido a la izquierda).

2. Página: 23 Los objetos que forman parte de la expresión (a. ALTURA Si damos los valores 5 y 6 desde teclado. se separan por comas. Consiste en que el ordenador envía datos (información procesada) al dispositivo estándar de salida (el monitor).I. Las sentencias de asignación se clasifican según el tipo de dato de las expresiones. La sentencia de entrada de datos suele (debe. 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. D..2.© A. Entrada.Instrucción de lectura de datos. Por tanto. de alguna forma. Ejemplo: Introducir BASE.es Apuntes de clase .3. b) Valores definidos.Instrucción de salida de datos. 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. La sentencia se salida de datos es la forma principal de comunicación del ordenador con las personas. la instrucción de entrada es destructiva. Programación en lenguajes estructurados. pueden ser aritméticas. Si hay más de un elemento. Como la sentencia de asignación.L. En ocasiones. alozanoi@teleline.. en la propia instrucción: constantes y/o expresiones. lógicas y de carácter. b y c) permanecen invariables.A. estos datos pueden ser: a) Valores de objetos depositados en memoria principal. 2. el objeto “BASE” tomará el valor 5 y el objeto “ALTURA” el valor 6.2.I. 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. 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. el valor previo que tuviera el objeto se pierde y es reemplazado por el valor introducido desde el teclado. los cálculos realizados por el ordenador requieren de entrada de datos externos para realizar las acciones necesarias para obtener los resultados.

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

© 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

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

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

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.25 DOBLE <-.. alozanoi@teleline.© A.es Apuntes de clase ..L.NX * TRES Visualizar NX Visualizar DOBLE Fin Programa Valor inicial B) V.¿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 <-. Ejercicios: 1. X * Y X <-. Z Fin Programa Programa EJEMPLO_2 Entorno: Nombre Tipo TRES Nº Entero NX Nº Entero DOBLE Nº Entero Inicio NX <-. Programación en lenguajes estructurados.20 Z <-. D = d * c + R ----> R=D-d*c M=N*c+R ----> R=M-N*c c = Cociente entero de (M / N) 3. D.X + Y Visualizar X.X * X Visualizar X..I.A.Algoritmo que decida cual de tres número es el mayor.5 Y <-. Inicial 3 2.Algoritmo que nos diga si un número N es o no divisor de otro número M.I. Y.

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

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

.

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

bloque de declaraciones. 2.. 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.1.Invocación a las funciones. son identificadores de variables con su tipo de dato correspondiente y que sólo se utilizan dentro del cuerpo de la función. devuelve un único valor. Existen dos tipos de funciones: las funciones incorporadas en el propio sistema.I.2.Declaración de funciones. denominado parámetro actual..A. los valores reales. encerrados entre paréntesis. D. llamadas funciones internas. Programación en lenguajes estructurados. consta de cabecera. 2. Una función tiene una constitución similar a la de un programa.Expresión.. y las definidas por el usuario o funciones externas (usadas cuando las funciones internas no satisfacen las necesidades de los cálculos). La declaración de una función se hace de la siguiente forma: FUNCION IdentificadorDeFuncion([[Parámetro es Tipo]. 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. y con él calcular el resultado.en la que se asigne un valor (el de retorno) al nombre de la función.. después de realizar los cálculos.I. es lo que después conoceremos como variables locales. sin(x).L. Página: 36 evaluar la función debe dársele un valor real a ‘x’.es Apuntes de clase .© A. es decir debe haber una sentencia como esta: IdentificadorDeFuncion <--. cuerpo con las sentencias ejecutables y un final. . Cada función se invoca utilizando su nombre en una expresión con los argumentos actuales. Cada lenguaje de programación implementa sus propias funciones: cos(x). 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.]) 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.

pueden ser constantes.I. Programación en lenguajes estructurados. a su vez. que.I. Un procedimiento o subrutina es un subprograma que ejecuta un proceso específico. Cuando necesitemos subprogramas que retornen más de un valor al lugar desde donde se invocaron. variables. llamadas a otras funciones. 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. Un subrutina se diferencia de una función en los siguientes puntos: alozanoi@teleline.es Apuntes de clase . 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. Hay una correspondencia uno a uno de izquierda a derecha. 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. Página: 37 Los parámetros utilizados en la llamada a la función se denominan parámetros actuales. una vez ejecutadas todas las sentencias que la componen se devuelve el control al programa que la llamó. entre estas sentencias debe estar la asignación de un valor al nombre de la función.© A. No tiene ningún valor asociado al nombre y. no puede formar parte de una expresión. D. no pueden utilizarse funciones y debemos recurrir a la utilización de procedimientos o subrutinas.Procedimientos o subrutinas. etc. Se ejecuta el cuerpo de sentencias ejecutables de la función de la forma que lo hace cualquier programa. 3.L. Ejemplo: Calcular Y= Xn Función Potencia(x es real. La subrutina se invoca desde cualquier parte del programa con sólo indicar su nombre y los parámetros asociados. 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. por tanto. El parámetro actual debe ser del mismo tipo que su correspondiente parámetro formal o un tipo de dato compatible.A..

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

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

Dividir el mayor por el menor. Consiste en duplicar el primer factor y dividir (cociente entero) por dos el segundo. Calcular el cociente y el resto. 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..Calcular el máximo común divisor por el “Algoritmo de Euclides”..División de dos números por restas sucesivas.I. 2.Calcular el producto de dos números por el “Algoritmo ruso del producto”. Los dos métodos se aplican tanto a las funciones como a los procedimientos. Dividir el divisor por el resto. el parámetro actual pasado por referencia tiene que ser una variable. Ejercicios: 1.. 5. Seguir dividiendo el último divisor por el último resto hasta que la división sea exacta. salvo si el segundo factor es impar. El último divisor es el máximo común divisor. en ambas direcciones. obteniendo un producto equivalente.Calcular las raíces de la ecuación de segundo grado.A. no puede ser una expresión. con una dirección de memoria.. en cuyo caso es necesario acumular previamente el primero en donde se va a obtener el resultado.Calcular el coeficiente del binomio m m!  =  n  n! ( m − n )!   4. 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. · · 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. Programación en lenguajes estructurados. D.I. Un procedimiento sólo puede devolver valores por medio de los parámetros por referencia.© A.es Apuntes de clase . El proceso finaliza cuando el segundo factor se hace cero.L. Por ello.. 3. alozanoi@teleline.

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

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

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

.

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

147.767 4.. En caso de ser negativa.967.4 x 10-38 1.648 -2.483. D.147.768 0 -2.768 0 -32.483.7 x 10-308 3.4 x 10+38 1.147.967.1.295 2.A.648 3.647 3.647 4. También se puede especificar el tipo de la constante añadiendo los sufijos L(long).483.483. Además se puede especificar la base de representación del número con los prefijos 0(octal).648 0 -2.I. 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.4 x 10-4932 Rango to to to to to to to to to to to 255 127 32. Página: 46 Resumen de los tipos de datos de 16 bits.L.768 0 -2.© A.1 x 10+4932 no aplicable no aplicable 2.147.647 3.483.483.147.483.7 x 10-308 3.I.7 x 10+308 1.483.767 65.294.648 3.767 4.967.767 32. El tipo de una constante entera viene determinado por su valor. U(unsigned int) o UL(unsigned long int). 2. 31(decimal) = 037(octal) = 0x1f(hexadecimal) alozanoi@teleline.4 x 10+38 1.294.294. Programación en lenguajes estructurados. Podemos usar el sufijo (tipo) y el prefijo (base) en el mismo número.es Apuntes de clase .295 2.7 x 10+308 1.147.Constantes.535 32.Constantes enteras.147.1 x 10+4932 no aplicable no aplicable Resumen de los tipos de datos de 32 bits.647 2.295 2. 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. debe especificarse el signo menos.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 -32.147. 0X(hexadecimal). Se pueden escribir en mayúsculas o minúsculas..

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

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

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

donde op es: +. y éste será su valor. si Numero % I = 0 Suma = Suma + I Fin si for (i = 0. Suma += Numero % I ? 0 : I. Si es cierta. alozanoi@teleline. else printf("%2d ". i++) if (i%5==4 || i==99) printf("%2d\n". D. /.A. i < 100.i). >>. aunque debe evitarse en la medida de lo posible. "E1 ? E2 : E3" es equivalente a "si E1 entonces E2 si no E3". (i%5==4 || i==99)?'\n':' '). Programación en lenguajes estructurados. el tipo del resultado se establece por las reglas de conversión..I.Operador condicional. ^. i. Los operadores de asignación pueden aparecer en expresiones. %. &. *. se evalúa e3. 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++) printf("%2d%c".I. En la expresión "e1 ? e2 : e3" primero se evalúa e1.es Apuntes de clase .i). i < 100. |.© A.L. Si a > b z=a si no z=b Fin si Suma = Numero % I ? Suma : Suma += I. <<. se evalúa la expresión e2. siendo este el valor de la expresión condicional. -. 3.5. for (i = 0. 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=. Si E2 y E3 son de diferente tipo de dato. Ejemplos: z = (a > b) ? a : b. En otro caso.

} Las reglas de conversión. Cuando usamos una expresión aritmética. · Si un operando es de tipo double.. sign extended unsigned short unsigned int Same value. el otro se convierte. · En cualquier otro caso.I. (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.es Apuntes de clase . el otro se convierte. Sólo se realizan aquellas que tienen sentido.A. 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. tal como a + b. Cuando el tipo de dato de la variable que recibe el valor es de un tipo igual o superior. el otro se convierte. que es el tipo del resultado.© A. el otro se convierte. el valor de la derecha se convierte al tipo de la izquierda. Los enteros de mayor magnitud (long) se convierten al tipo short o a caracteres por eliminación de los bits de orden superior. el otro se convierte. zero filled enum int Same value · Si un operando es de tipo long double. los dos operandos son de tipo int. else Return(c). D. 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. double se convierte en float por redondeo. Sqrt((double)n): convierte n al tipo double pero no modifica su valor. alozanoi@teleline. no hay variación en el valor de la variable o expresión asignada. · Si un operando es de tipo unsigned. · Si un operando es de tipo long. Las conversiones también tienen lugar en asignaciones. redondeando o eliminando los bits más significativos. Programación en lenguajes estructurados.I. 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. · Si un operando es de tipo unsigned long. · · · De float a int se trunca la parte fraccionaria. el otro se convierte.L. cuando a y b son de diferente tipo. 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).'A'). en general. Página: 51 4. · Si un operando es de tipo float. Si es al contrario.Conversión de tipos. por orden. se truncará el valor. int Minusculas(int c) { if (c >= 'A' && c <= 'Z') Return(c + 'a' .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

.

© A.Tablas: conceptos. Fijo: Es necesario definir su tamaño en tiempo de compilación. es decir. Página: 75 10.. definiciones y representación. Los tipos de datos estructurados pueden ser organizados en diferentes estructuras de datos: estáticas y dinámicas.Introducción a las estructuras de datos. 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. 2. 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. finito y ordenado de elementos. 1. Una tabla o array es una estructura de datos interna -se almacena en memoria principal. Las estructuras de datos dinámicas no tienen limitaciones o restricciones en el tamaño de memoria ocupada.ESTRUCTURAS DE DATOS ESTÁTICAS. D.L. 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.I.es Apuntes de clase . son los que hemos trabajado hasta el momento.I. Programación en lenguajes estructurados.. alozanoi@teleline.A. todos del mismo tipo y referenciados bajo un nombre común.. el tamaño de la tabla se da al escribir el programa.que consta de un número fijo.

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

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

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

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

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

C < COLUMNAS. necesita un valor para cada indice para poder identificar un elemento individual. Recorrido secuencial de una matriz.2. es decir.A.I. MATRIZ. F < FILAS.L. 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. por tanto..1. alozanoi@teleline. Programación en lenguajes estructurados. Identificador[FILAS. 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]. Página: 81 En la figura siguiente se representa una matriz. C++) Tratar TABLA[F][C]. Por filas: El bucle más externo recorre las filas y el mas interno todas las componentes de la fila. D.es Apuntes de clase . 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). 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.Operaciones sobre matrices.© A. este puede realizarse de dos formas distintas: por filas y por columnas.I. Los dos índices son expresiones numéricas enteras. 3. COLUMNAS] es de tipo TipoDeLasComponentes. todas las columnas de esa fila. el externo se posiciona en una fila de la tabla y el interno recorre todas sus componentes.

Programación en lenguajes estructurados.0. F++) Tratar TABLA[F][C].0.I. El resto de operaciones que pueden realizarse sobre los elementos de una matriz son las mismas que las que pueden realizarse con los vectores. Hay dos formas de inicializar un array: 1.{0. C++) For(F = 0. igual que cualquier otra variable.0. Int Matriz2[2][7] = {0. 0.0. C < COLUMNAS.{0.0}.I. // Definición e inicialización de un array Int Matriz1[][4] = {{0. F++) For (C = 0. Ejemplo: a) Cargar una matriz de 30 filas y 3 columnas que contiene la nota de cada alumno por cada módulo del ciclo. D. 2.0.0.© A.0}.0.0. C++) Matriz[F][C] = 0.0. C < COLUMNAS. F < FILAS. alozanoi@teleline._ Inicializar el array en la propia definición del mismo. 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.es Apuntes de clase . 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.0.0}}. Inicialización de matrices Un array.0. las filas corresponden al alumno y las columnas a los módulos.0.0}.L. Calcular e imprimir la nota media de cada alumno y de cada asignatura.0.A. F < FILAS. Página: 82 Por columnas: El bucle más externo recorre las columnas y el mas interno todas las componentes de la misma.0. For (F = 0.0.0.0. debe inicializarse cuando sea necesario y en el lugar del programa oportuno con los valores que deba almacenar._ 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].

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

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

© 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

I. for (i = 0. D. j. i++) { k = i. 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. Auxiliar = V[k].I. Programación en lenguajes estructurados. Auxiliar. } V[k] = V[i]. j < ELTOS. V[k] = V[i]. k. i < ELTOS . 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. Auxiliar. for (i = 0. for (j = i + 1.Ordenación por selección directa. V[i] = Auxiliar. i++) { k = i. void SeleccionDirecta(int *V) { int i. i < ELTOS ..1. V[i] = Auxiliar. j++) if (V[j] < Auxiliar) { k = j. 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. 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. j. Auxiliar = V[i].3.es Apuntes de clase . for (j = i + 1. k. j < ELTOS.A.Ordenación por intercambio directo o método de la burbuja.2.1.L. } } Otro algoritmo. semejante al anterior pero realizando el intercambio al finalizar la búsqueda. alozanoi@teleline. Página: 89 6. El método consiste en recorrer sucesivamente el vector comparando los elementos consecutivos e intercambiándolos cuando estén desordenados. j++) if (V[j] < V[k]) k = j. Auxiliar = V[j].© A. } } 6..

V[j] = V[j + 1]. i++) for (j = ELTOS . el tamaño del array resultante es. j >= i. V[j .I. La operación de mezcla de dos arrays unidimensionales consiste en que dados dos vectores ordenados. j--) if (V[j . TABLA1 y TABLA2. Auxiliar. se obtenga un tercer array ordenado. V[j] = Auxiliar. V[j + 1] = Auxiliar. 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. 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. por tanto.A. 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 < ELTOS. Programación en lenguajes estructurados. LON1 + LON2.I.1. esta forma no usa la ventaja de la ordenación previa de los arrays originales. j++) if (V[j] > V[j + 1]) { Auxiliar = V[j]. que contenga los valores de los dos primeros arrays. for (i = 1. } } 7.L.2. j. TABLA3. for (i = ELTOS . i--) for (j = 0.1]. Suponiendo que el tamaño de los arrays iniciales es LON1 y LON2 respectivamente. Auxiliar. Sin embargo.1] = V[j]. i >= 0.Mezcla de vectores. j <= i. j.1] > V[j]) { Auxiliar = V[j ..es Apuntes de clase . El proceso es el siguiente: alozanoi@teleline.© A. D. } } Recorrido de derecha a izquierda: esta versión es igual que la anterior pero desplazando los elementos menores a la izquierda.

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

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

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

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

en cada uno de sus elementos podemos almacenar la dirección de otra variable. 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. indica que se está declarando una variable puntero que almacena la dirección de otro puntero a un entero. for (i=ELTOS/2. i<ELTOS/2. En definitiva. 2. 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". La cuestión es que pasaría si cada elemento de un array apuntara a la dirección de otro puntero. existen diferencias entre el nombre de un array y un puntero a un array: · · Un puntero es una variable. main() { int *p_array[LONGITUD]. Esto se denomina doble indirección.7. } 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. 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. Página: 95 Como se ve. array1 = array2. 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. p_array[1] = notas. i.8.Arrays bidimensionales y punteros. alozanoi@teleline.I.3.1.. Esta asignación de memoria se realiza como se ha visto antes (p_array = array o p_array = &array[0]) o bien. no pudiendo modificar su valor ( no podemos hacer array++.L. int dato = 20. que apunta a otra var.I. *(p_array[1] + i)). tal como la dirección de una variable de tipo int (dato) o la dirección de un vector de enteros (notas). mediante la petición directa de memoria.5. Programación en lenguajes estructurados. Sin embargo. i<ELTOS.4. ptr. que hay que definir como los demás objetos del programa. for (i=0. *p_array[0]).A.2.9}. la longitud del dato al que apunta cada componente del array de punteros es irrelevante. ptr. p_array[1][i]). La definición de un array de punteros es la siguiente: tipo_dato *identificador[LONGITUD]. array1 = &array2. p_array[0] = &dato. i++) printf("%d\t". //Crea una var. son sentencias ilegales).© A.es Apuntes de clase . i++) printf("%d\t".6. int notas[ELTOS] = {0. D. La declaración int **puntero_puntero. //Crea un array de punteros La siguiente definición declara un array de LONGITUD punteros a enteros.

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

for (i=0. 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<FILAS. for (j=0. i++) { printf("\n"). int i. i++) { printf("\n"). Valor del elemento [i][j].A. j++) *(p_array[i] + j) = random(100).© A. i<FILAS. } getch(). Programación en lenguajes estructurados. del elemento [2][1]. i++) for (j=0. Dirección del elemento [i][j].*(*(p_array + i) + j)). j<COLUMNAS. &array[i][j] Array[i] *(array + i) + j array[i][j] Array[i][j] Dirección del elemento [i][j]. Dirección de la fila [i]. Valor del elemento [i][j]. j<COLUMNAS. for (i=0. j++) printf("%d\t". i<FILAS. i<FILAS. a un array multidimensional definido de forma convencional. j++) printf("%d\t". *(*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. for (i=0. i++) for (j=0.L. i<FILAS. 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]. for (j=0. Dirección de la fila i En general. i++) p_array[i] = (int *) malloc(COLUMNAS * sizeof(int)). D. j<COLUMNAS.I. j. } for (i=0. se puede acceder a sus elementos mediante punteros sin usar la indexación: int array[3][4]. for (i=0. 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. j<COLUMNAS.I. Página: 97 Expresiones propias de arrays de punteros.es Apuntes de clase . } También. j++) *(p_array[i] + j) *= CONSTANTE. que también pueden usarse con arrays bidimensionales normales.*(p_array[i] + j)).

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

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

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

int. j++) printf("Valor= %d\n". FILAS. f. j<c. int. tipo matriz[F][C]. COLUMNAS). i. int c) { int i. for (i=0. i++) for (j=0. j<c. for (i=0. int f. COLUMNAS). int).L. int columnas). &array[0]). //Con error warning. i<FILAS. cargar(p_array. *(tabla + i * c + j)). int c)//Si definido *matriz[] { int i. FILAS. int *p_array[FILAS]. int). c). } int **reservar_memoria(int f. Sólo si definido como **matriz. int c) // Si definido **matriz { int **tabla. columnas). main() { void reservar_memoria(int **. int). filas. Programación en lenguajes estructurados. for (i=0. j. FILAS. i<f. for (i=0. } void cargar(int *tabla. int f. i++) *(tabla + i) = (int *) malloc(c*sizeof(int)). COLUMNAS). FILAS. i++) for (j=0. visualizar(&array[0][0].I. reservar_memoria(p_array. i++) *(tabla + i) = (int *) malloc(c*sizeof(int)). j. return tabla. var = funcion(&matriz[0][0]. c). Página: 101 Longitud variable con un puntero: Prototipo: Definición: Llamada: tipo funcion(tipo *array. FILAS. j++) *(tabla + i * COLUMNAS + j) = rand() % 100. var = funcion(matriz. i<f. int array[FILAS][COLUMNAS]. cargar(&array[0][0]. int). int c) { int i. } void visualizar(int *tabla. } Longitud variable con reserva explícita de memoria: Prototipo: Definición: Llamada: tipo funcion(tipo **array. int.© A. D. int filas. f. i<f. } void reservar_memoria(int *tabla[]. tabla = (int **) malloc(f*sizeof(int*)). printf("Puntero: array= %d\n". 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. i<f. } alozanoi@teleline. tipo *matriz[]. array). main() { void cargar(int *. COLUMNAS). tipo **matriz. int. int f. void visualizar(int *[]. for (i=0. void cargar(int **. COLUMNAS).A. printf("Vector de punteros: &array[0]= %d\n". int). int filas.es Apuntes de clase . void visualizar(int *. visualizar(p_array. int columnas). int. i++) free(*(p_array + i)). i. // free(p_array). var = funcion(matriz.

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

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

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

*(lista + k) = *(lista + i). k. } Ejercicios: Comprobar si una frase es o no un Palíndromo. "Perez". alozanoi@teleline.I. } } void visualizar(char **lista. int Longitud) { int i. Página: 105 . "Lozano".A. 5). i++) { k = i.I. visualizar(apellidos. i < Longitud . char *cadcar(char *cadena. *(lista + k)) < 0) k = j. } . ordenar(apellidos. for (j = i + 1. i++) printf("%s\t". i < Longitud. char *). for (i = 0. Programación en lenguajes estructurados. Juego del ahorcado. char *cadena2) { while (*cadena1++ = *cadena2++). "Garcia"}. j < Longitud. void visualizar(char **. char *Auxiliar. "Diaz".Ordenar alfabéticamente una lista de apellidos: int cadcomp(char *. return *cadena == caracter ? cadena : NULL. j. } return *cadena1 .lista[i]).L. D. *(lista + i) = Auxiliar. char *cadena2) { while (*cadena1 == *cadena2 && *cadena1) { cadena1++. } . void ordenar(char **. Auxiliar = *(lista + k). 5). } . int caracter) { while (caracter != *cadena && *cadena) cadena++.© A. cadena2++.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. int Longitud) { int i. int).*cadena2. main() { char *apellidos[] = {"Sanchez". } void ordenar(char **lista.es Apuntes de clase .Copiar una cadena en otra: void cadcopi(char *cadena1. for (i=0.1. j++) if (cadcomp(*(lista + j).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. int).

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

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

Carácter a mayúsculas o ch. (CIERTO/FALSO) ¿Blanco. 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.es Apuntes de clase . D. return. int base).I. Pertenecen a la librería <ctype. unsigned long strtoul(const char *s.© A. Programación en lenguajes estructurados.I. El puntero siguiente es la dirección del siguiente carácter a tratar. char *siguiente. int base). long y unsigned long respectivamente. tab? (CIERTO/FALSO) ¿Mayúsculas? (CIERTO/FALSO) ¿Dígito hexadecimal? (CIERTO/FALSO) alozanoi@teleline. char *siguiente. Sólo de a-z. Ignoran los espacios iniciales. 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.. 7.h>. 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. ** ** ** double strtod(const char *s. Sólo de a-z. Base es la base numérica en la que se trabaja.A.(CIERTO/FALSO) Imprimible menos blanco y alfanumécos. Página: 108 Todas reconocen los caracteres adecuados a su tipo de dato.L. Convierten una cadena a número double. nueva línea. long strtol(const char *s. char *siguiente).Funciones de caracteres. ¿Alfanumérico (a-z. (CIERTO/FALSO) ¿Minúsculas? (CIERTO/FALSO) Carácter imprimible incluído el blanco.

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

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

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

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

struct { }. 3.Diseña y escribe una estructura de datos para almacenar la información del problema anterior. real Temperatura. struct Venta Coches[MARCA][MODELO]. struct { Tiempo int Hora. El formato de definición del alias es el siguiente: typedef <TipoDeDato> <Identificador>. Por tanto la siguiente sentencia: typedef float real.© A.. imprime la lista ordenada de nombres y teléfonos. } DatosPasaje[8]. int Plazas_Libres.Tipos de datos definidos por el usuario Es posible definir un alias para los tipos de dato de C con la palabra reservada 'typedef'. } Vendedores[NUMERO]. Minutos. int Capacidad. float Temperatura. int Reserva_Espera. las nuevas variables pueden ser declaradas en términos de ese nuevo tipo/alias. struct Venta { int Numero. struct Tiempo Hora. D. 5. Vuelo int Capacidad. 4. suponiendo que puede haber varios vuelos a una misma ciudad.. Página: 113 struct Pasajes { char Ciudad[20]. }. Una vez establecido el alias. siendo equiparable en todos los aspectos. struct Vuelo DatosVuelo[NV]. significa que se reconoce la palabra real como otro nombre de float. Programación en lenguajes estructurados.I.A.L.es Apuntes de clase . alozanoi@teleline.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._ 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. long Valor. Diseña y escribe la estructura de datos necesaria para ello. int Reserva_Espera. 2.I. int Plazas_Libres.. struct Pasajes { char Ciudad[20]. }. struct Agencia { int Codigo_Vendedor. finalmente. } Vuelo[8].

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

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

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

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

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

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

.

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

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

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

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

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

· Permite realizar operaciones de entrada y salida simultáneamente.Organización directa.I. · Permiten acceder a los datos tanto directamente (por su clave) como secuencialmente. estableciendo así una relación directa entre dirección lógica y dirección física. Programación en lenguajes estructurados. por lo que nunca podemos almacenar un registro cuya clave esté por encima de los límites máximos del fichero.© A.I. estableciéndose así una relación directa entre la clave y la dirección que ocupa el registro dentro del fichero. 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. · Son muy rápidos en el tratamiento individual de registros. Los algoritmos de transformación de claves reciben el nombre de “Hashing” y hay gran variedad de ellos. a los datos. cada posición se localiza por una dirección absoluta (el programador sólo gestiona direcciones relativas).. Página: 126 6. Producir el menor número de registros que con diferentes claves generan idénticas direcciones de almacenamiento tras aplicar el algoritmo de transformación. Existen dos variantes de la organización relativa: directa e indirecta o aleatoria.2. · Desaprovechamiento del soporte debido a la gran cantidad de huecos que pueden existir. 6.A. D. alozanoi@teleline.es Apuntes de clase .2. 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. 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. directo.. Establecer una correspondencia directa entre dirección lógica (clave) y dirección física (memoria). El algoritmo de transformación de claves debe cumplir tres características principales: · · · Aprovechar al máximo el espacio disponible en el soporte externo. El valor de la clave siempre está en relación con la capacidad máxima del soporte físico. · 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.L. Ventajas: · Permite un acceso inmediato. 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. Son aquellos caracterizados por: · · · Deben almacenarse en un soporte direccionable.1.

En este tipo de organización. Este hecho se conoce con el nombre de “sinónimo” o “colisión”. Un archivo está organizado de forma secuencial indexada si: · · · El tipo de sus registros contiene un campo clave. D. · 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. · Permite realizar operaciones de entrada y salida a la vez.2.Organización secuencial indexada. Un índice para cada posición direccionable. Se debe procurar que estos algoritmos generen el menor número posible de sinónimos y de huecos vacíos.I. Área de índices: es una tabla que contiene los niveles de índice. 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.. Los registros están situados en un soporte direccionable por el orden de los valores indicados por la clave. si fuese necesario. Apuntes de clase alozanoi@teleline. Los elementos se encuentran almacenados de forma secuencial pero existe una forma de conocer la posición de un determinado elemento.es .3.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. Página: 127 6. · No requiere procesos de ordenación.L. 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. Un archivo secuencial indexado es una mezcla de las dos anteriores. la dirección de la posición y el valor de la clave. · Los mismo que la organización directa. Área de desbordamiento: utilizada. para las actualizaciones.I.A. Inconvenientes. Esta organización se da en aquellos casos en que la clave –ya sea de tipo numérico entero o de tipo cadena. · Son muy rápidos en el tratamiento individual de registros. la existencia de varios índices enlazados se denomina nivel de indexación.Organización relativa o indirecta.2. Programación en lenguajes estructurados.© A. · Permiten acceder a los datos secuencialmente. 6. Ventajas: · Permite un acceso inmediato a los registros haciendo sólo referencia a su clave.. Consta de un archivo de índice y un archivo de datos.

· Se necesita espacio adicional para el área de índices.L.© A.A. D.I.es Apuntes de clase . Inconvenientes. Página: 128 Ventajas. · Acceso rápido. alozanoi@teleline. · 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. · Desaprovechamiento del espacio por quedar huecos intermedios cada vez que se actualiza el archivo.I. Programación en lenguajes estructurados.

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

if (archivo == NULL) { puts("Error al abrir el archivo"). Si no existía se crea uno nuevo. COM2. archivo = fopen("datos. estos son: stdin stdout stderr stdaux stdprn Entrada estandar. Abre el archivo para escritura desde el final del mismo. Abre el archivo para Lectura/Escritura por el final.a+ -t b Ejemplos: FILE *datos. El nombre externo del archivo de datos es incorrecto. "r").dat". El archivo debe existir previamente o se produce un error. datos = fopen("c:\\trabajo\\lc\infor. } alozanoi@teleline. Si el archivo no existía. Abre el archivo para Lectura/Escritura por el comienzo. devolviendo un puntero a dicho canal. Salida estandar de errores. Si no existe se crea. para añadir. Teclado. -a . Existen varios stream predefinidos en C que se abren automáticamente al iniciar el programa. PRN. "wb"). exit(-1).w+ .h> main() { FILE *archivo. se crea uno nuevo. En el caso de producirse un error. se destruye el contenido del anterior. 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. datos = fopen(archivo.r+ . El archivo debe existir previamente.(t) o en modo binario (b). Programación en lenguajes estructurados. Pantalla. char *archivo = "c:\\trabajo\\lc\infor.L. y si existe. No tener permiso para abrir el archivo. #include <stdio. fclose(archivo). "r"). Impresora estandar. Intentar abrir un archivo que no existe usando los modos r o r+. se destruye el contenido del anterior.es Apuntes de clase . datos = fopen(archivo. Abre el archivo para Lectura/Escritura por el comienzo. y si existe. Periférico auxiliar estandar.© A. Si no existía se crea uno nuevo. Salida estandar. "w").I. D. 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. }//Tratamiento del archivo. Pantalla. Página: 130 -r -w Abre el archivo para lectura.A. si no se produce un error. la función fopen() devuelve un puntero a NULL.dat".dat". Abre un archivo para escritura.I. La función fopen() asigna un stream (canal por el que leer y escribir) y un buffer (memoria intermedia temporal) a un archivo.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

dando un listado de la categoría.L. Programación en lenguajes estructurados.... La categoría está comprendida entre A y J....... Listado de cobros de la categoría DESCRIPCIÓN NOMBRE EDAD DIRECCIÓN SUELDO NETO __________________________________________________________________ ......... ... alozanoi@teleline. .1 ó 2.. número de empleados y sueldo bruto ordenado por número de empleados. por sueldo bruto............. obtener un listado con el siguiente formato: Página: ........ Obtener el número de empleados y el sueldo bruto total de cada categoría....... escribir la cabecera del listado e incrementar el número de página. de la A a la J.. Dados los ficheros anteriores y suponiendo PERSONAL ordenado en orden creciente de categoría y CATEGORÍA desordenado. Los valores posibles del estado civil(EC) son 0....es Apuntes de clase ...I..© A........ 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. 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.... 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....A.. .. Teniendo en cuenta que el sueldo neto se calcula mediante la siguiente operación: SUELDONETO=SUEDOBRUTO-DESCUENTO. ... .... así mismo. D.. El descuento se extrae del fichero CATEGORÍA (el campo CATEGORÍA se corresponde con el campo TIPOCATEGORIA).... cuando se cambie de categoría escribir el sueldo neto total para la categoría. y en caso de ser iguales......I. SUELDO NETO TOTAL .... . . .. Cada vez que se cambie de categoría o escribamos 55 líneas(registros).....

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

D) Obtener un listado ordenado de clientes cuyas cuentas corrientes han tenido movimiento. D.Cero: imposición . Página: 155 PRÁCTICA: En el fichero secuencial CLIENTES... B) Crear el fichero 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. 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 . C) Ordenar ascendentemente por número de cuenta corriente el archivo de movimientos. También se dispone de otro fichero secuencial con los clientes que han tenido movimiento en sus cuentas corrientes.. cada cliente tendrá de 0 a 5 movimientos. TIPO puede tomar los valores . Programación en lenguajes estructurados.L. cuyos formatos son: NCC donde: MOVIMIENTO MOVIMIENTO almacena la cantidad.Uno: reintegro Hacer un programa para resolver los siguientes puntos: A) Crear el fichero de clientes con un mínimo de 25 registros.DAT se guardan los datos personales de los clientes de un banco.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.A.I.. Opcionalmente se ordenará también el fichero de clientes.

.

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

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

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

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

si la información que queremos insertar el la mayor. } } 2.. *Lista= Nuevo. La información que almacena el nodo devuelto tiene valor inferior o igual a la que queremos insertar.es Apuntes de clase . (*Lista)->Siguiente= Nuevo. Dato 1 Lista Posicion Lista encadenada. por orden. El paso (1) hay que hacerlo necesariamente en primer lugar para no perder la dirección del siguiente nodo al apuntado. encadenar el nodo apuntado al nuevo “nodo(*Lista)->Siguiente= Nuevo”.I.I. Programación en lenguajes estructurados. Nuevo= (TLista) malloc(sizeof(Nodo)). si la lista está vacía o es la menor información almacenada en la lista. 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.2. alozanoi@teleline. Para insertar en una lista ordenada ascendentemente. if (Vacia(*Lista)) { //Nuevo->Siguiente= *Lista. 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. La acción que debemos realizar es la de insertar al principio de la lista. Situación inicial. Dirección del nodo tras el que queremos insertar. Página: 161 nodo. 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.A. Nuevo->Siguiente= NULL.Inserción en una lista ordenada. devuelve un puntero a: · · NULL. } else { Nuevo->Siguiente= (*Lista)->Siguiente.© A. TInformacion Info) { TLista Nuevo. es necesario conocer la posición (mediante un puntero) del nodo cuya información es inmediatamente inferior que la del nodo que queremos insertar. Nuevo Reserva de memoria.3.3. Los pasos que damos. D. Nuevo->Dato= Info.L. segundo. ésta. //*Lista= Nuevo . son: primero encadenar el nuevo nodo con el nodo siguiente al apuntado “Nuevo->Siguiente= (*Lista)->Siguiente” y. retorna un puntero al último nodo. La acción que realizamos es la de insertar en medio o al final de la lista.

© A.I. Info). Nuevo->Siguiente= Aux->Siguiente. } else { TLista Aux= *Lista. Lista->Dato). } } El mismo tratamiento recursivo es el siguiente: void Visualizar(TLista Lista) { if (!Vacia(Lista)) { printf("%d\t". D. hasta alcanzar el final de la misma (cuando el campo enlace del último nodo es NULL).L. } TLista Buscar(TLista Lista. //Se almacena la dir. a través de su campo enlace. comenzando en la cabecera de la lista y continuando por los nodos restantes. } } Tiene tres bloques diferenciados: · · · Reserva de memoria y asignación de la información. //Se toma el siguiente nodo } return Anterior.2. Visualizar(Lista->Siguiente). se añade el nodo al principio de la lista. del nodo anterior Lista= Lista->Siguiente. // TRATAR (Lista->Dato) Lista= Lista->Siguiente.es Apuntes de clase .Recorrido de una lista. 2.I. Programación en lenguajes estructurados. // Condición como está o poner interruptor while (Lista != NULL && Info > Lista->Dato) { Anterior= Lista. Info). TInformacion Info) { TLista Posicion= Buscar(*Lista. if (Posicion) InsertarEnMedio(&Posicion. } 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. else InsertarAlPrincipio(Lista. while(!Vacia(Aux->Siguiente) && Info > Aux->Siguiente->Dato) Aux= Aux->Siguiente. } } alozanoi@teleline. TInfo Info) { TLista Nuevo= (TLista)malloc(sizeof(Nodo)). Lista->Dato). Aux->Siguiente= Nuevo.. TInformacion Info) { TLista Anterior= NULL. void Visualizar(TLista Lista) { while(!Vacia(Lista)) { printf("%d\t". Página: 162 void InsertarOrdenado(TLista *Lista. if (Vacia(*Lista) || Info <= (*Lista)->Dato) { Nuevo->Siguiente= *Lista. Info). *Lista= Nuevo. Si la lista está vacía o la información a añadir es menor que las almacenadas en esta. 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.4. Nuevo->Dato= Info. El recorrido de una lista se realiza secuencialmente.

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

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

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

// Podemos variar el nodo cabecera para realizar una inserción // al final de la lista. · Si el elemento se ha encontrado. } } 3.2. D. Se necesitan dos punteros. (*Lista)->Siguiente= Nuevo.L.I. 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. detrás del último insertado en la lista //*Lista= Nuevo. (2) Anterior->Siguiente= Auxiliar->Siguiente Dato 4 Dato 3 Dato 2 Dato 1 (3) free(Auxiliar) (1) Lista= Anterior Anterior Lista. requiere que se conozca la posición del nodo que se desea eliminar. La operación de borrado de un nodo de una lista circular.es . se pueden dar las siguientes posibilidades: · Es el único nodo de la lista: hay que inicializar la lista. Dato 1 Lista Lista= NULL Free(Auxiliar) Lista. Los pasos para eliminar un nodo son los siguientes: · Buscar el elemento en la lista.A.I.Borrar un nodo de la lista. 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.© A. uno recorre la lista buscando la información y el otro guarda la posición anterior. Apuntes de clase alozanoi@teleline. igual que en operaciones de borrado anteriores. Auxiliar. (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. Programación en lenguajes estructurados.1..

© 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

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

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

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

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

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

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

c) Listado de cliente por orden de llegada. Alta de cliente.es Apuntes de clase . Programación en lenguajes estructurados. alozanoi@teleline.L.A.© A. b) Inserción de un cliente en la lista enlazada que debe estar actualizada en todo momento orden de entrada y alfabéticamente-.I. 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. Salida de cliente. Listado de clientes por orden de llegada. 6. d) Listado de clientes ordenados alfabéticamente. e) Eliminación de un cliente de la lista. Fin de la sesión. Inicializar la lista.I. 5. Escribir el programa principal con el siguiente menú: 1. Listado de clientes por orden alfabético. 2. 3. 4. D.

La función A llama a la función A. La escritura de una función recursiva es idéntica a la escritura de una no recursiva . sin embargo.I. incluidos los parámetros formales. factorial(Numero)). es preciso incluir una condición de terminación (igual que en un bucle). Ejemplo 1. se crea una copia de la variables locales a la función.1) long factorial(int). main() { int Numero = 3. contiene una referencia a la función A. Puede ser utilizada en lugar de la repetición o iteración (estructura repetitiva).es Apuntes de clase . 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. } alozanoi@teleline. printf("%d". Cada vez que se activa recursivamente una función.A.*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. si se invoca a sí misma.ESTRUCTURAS DINÁMICAS NO LINEALES DE DATOS. es decir. de forma que los valores de las variables que tienen validez son los más recientemente creados. Programación en lenguajes estructurados.I.1) ! si n > 0 La función FACTORIAL de N expresada en términos recursivos sería : FACTORIAL = N * FACTORIAL(N . Se dice que una función es recursiva (un elemento que contiene otro de su misma categoría) si forma parte de sí misma. 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 .© A. a su vez.1). 1. El uso de la recursión es idóneo para resolver aquellos problemas que pueden definirse en forma natural en términos recursivos. Se dispone de dos tipos de recursividad : · · Recursividad directa: si la función se invoca a sí misma.. La función factorial se define de la siguiente forma : n!=1 si n = 0 (0 ! = 1) n ! = n*(n .2)*. La recursión es un medio particularmente poderoso en operaciones de cálculo. Página: 178 16.. D.1)*(n .Recursividad. Recursividad indirecta: si una función A tiene una referencia a una función B que.L. Cálculo del factorial de un número. } long factorial(int N) { if (N == 0) return 1... para evitar que continúe indefinidamente.

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

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

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

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

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

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

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

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

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

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

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

El puntero es constante. Nombre= “Pedro”.I. // No permitido. Un puntero variable apuntando a una variable constante. // No Permitido. // Error de compilación.es Apuntes de clase . Estas variables no son constantes simbólicas aunque tienen cierta similitud. char Array[TAMANO]. const char *Nombre= “Antonio”. Nombre= “Pedro”. Programación en lenguajes estructurados. 8. moldeo. return int (x)/y. Nombre[0]= ‘M’.. y. return (int) x/y. Nombre[0]= ‘M’.© A. 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. 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. No puede cambiar su valor. el array debe tener una longitud conocida en tiempo de compilación a no ser que utilicemos reserva explícita de memoria.Especificador const para variables.I. cosa que no está permitida en C con la declaración de una variable: const int TAMANO= 5. Esta declaración no está permitida en lenguaje C. Página: 190 6. De cualquier forma. es detectado por el compilador. 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. El puntero cambia de dirección. // Permitido. No permitido. double x.L. double x. i++. 7. 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. char* const Nombre= “Antonio”.A. Puede cambiar su valor. La constantes declaradas así pueden utilizarse para definir la longitud de vectores en la declaración de éste.Conversiones explícitas de tipo.. const i= 3. D. alozanoi@teleline. 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. Un puntero const apunta siempre a la misma posición de memoria pero el valor de la variable se puede modificar. // Permitido. 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. Un puntero constante apuntando a una variable cualquiera.Especificador const para punteros.. 2. y.

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

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

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

Si además la variable es una estructura. 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. 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. 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.. 13..I.. pero con referencias resulta mucho más sencillo. cout << "Introduzca su Nombre:". esto es un alias del argumento de valor máximo. Una variable creada con el operador new dentro de cualquier bloque. 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.. Se puede utilizar el operador new para crear variables de cualquier tipo.. perdura hasta que es explícitamente borrada con el operador delete. También se pueden crear variables de tipos definidos por el usuario.. Cuando la llamada a la función se sustituye por su valor de retorno. Este mismo efecto puede conseguirse mediante punteros. sino también por motivos de eficiencia.es Apuntes de clase .L. alozanoi@teleline. Esa conversión se evita con new. Cuando una variable ya no es necesaria se destruye con el operador delete para poder utilizar la memoria que estaba ocupando..Operadores new y delete. un puntero a la variable creada. D. pues es mucho más rápido pasar un puntero o un alias de una variable que una copia del valor de esa variable. en todos los casos. no sólo para poderlos modificar dentro de la función. El resultado de esta llamada también es un poco extraño: el valor de retorno es una referencia.I.. New devuelve. Programación en lenguajes estructurados.h> void main() { char Nombre[50]. usuario* Un_Usuario. las ventajas de eficiencia son todavía mucho más palpables. en vez de aparecer a la derecha en una expresión aritmética o de otro tipo. el resultado de la sentencia anterior es que la variable pasada como argumento que tiene mayor valor se hace igual a cero. En C++ las referencias son muy utilizadas para pasar argumentos a funciones (y como valores de retorno).. cin >> Nombre.© A. mediante una instrucción del tipo: delete p.h> #include <string.. char *CopiaNombre = new char[strlen(Nombre)+1]. struct usuario { . Un_Usuario = new usuario.A. }.

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

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

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

.

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

Es. ocultando información. es capaz de realizar cálculos aritméticos. Implementación. se nos permite ocultar una parte del sistema del resto.. es decir. operacionales y de comandos. oculto y seguro del resto del sistema. un interruptor de encendido y apagado. lo que nos interesa de ella es que se puede encender y apagar. Por tanto. La implementación de la representación interna de la estructura y de los servicios del TAD incorpora el concepto de encapsulación. un conjunto de teclas numéricas. ficheros. todos los chips y circuitos adicionales. Si consideremos una calculadora. 2. permitiendo que el código sea revisado sin afectar a la integridad del sistema. cada objeto tiene dos partes diferenciadas: · Interfaz de comunicación con el exterior. estamos realizando un ocultamiento de la información. el alozanoi@teleline. para evitar la corrupción de los datos de un objeto y protegiéndolos de un uso arbitrario. almacenándola en el interior de una cápsula.es Apuntes de clase . Yo. el resultado de aplicar la abstracción al objeto. 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.Encapsulamiento. Ninguna parte de un sistema complejo debería depender de la implementación. El resto. no debemos fijarnos en la implementación concreta de las estructuras de datos desde el punto de vista de la programación (arrays.© A. Así.1. listas enlazadas. Es el producto de aplicar el encapsulamiento al objeto.A. Captura la visión externa del objeto y es conocida por los demás objetos del sistema permitiendo la comunicación entre ellos. 88). de otra parte de ese mismo sistema. 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.L. Programación en lenguajes estructurados. Así. por tanto. es decir. como objeto. En esta parte se explicitan y codifican los mecanismos necesarios para responder a la interfaz. de los detalles internos. acumuladores.. 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. me comunico con la calculadora a través del interfaz de comunicación que ofrece al exterior: un display.I.) si no en las características que tiene en la vida real. D.. 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.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. LEDs. Página: 200 2. mostrar los resultados de dichos cálculos entre otras características de la misma.Abstracción.. Para que un TAD funcione bien. Lo que no nos interesa son los mecanismos internos que utiliza para proporcionar unos resultados óptimos: estado de transistores.I. etc. sumadores. la implementación de su representación y de los servicios debe estar encapsulada (Liskov.

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

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

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

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

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

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

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

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

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

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

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

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

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

es Apuntes de clase . Es decir. también se incorporan automáticamente el constructor copia y el operador de asignación . 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). } void Desplazar(double a. no se copia la cadena propiamente dicha si no sólo su dirección. 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).LaCadena). Cadena s(c). En la clase Cadena creada antes. Por tanto. public: ~Punto() . x+= b .I. { x= p. es decir.I. y. Por ejemplo. Programación en lenguajes estructurados. //Borra el espacio actual LaCadena= new char[strlen(c. un puntero a char (char *). } Punto operator=(const Punto &p) //Operador de asignación { x= p.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. const Punto &b). Página: 214 p= r . realiza una copia de los atributos del objeto fuente. double yy= 0) .© A. //Operador de asignación p= (2. //Crea nuevo espacio strcpy(LaCadena. } Con el operador de asignación sucede exactamente lo mismo. sin embargo si la estudiamos más a fondo vemos que los efectos no son los deseados. } friend double Distancia(const Punto &a. una sentencia como s.LaCadena)+1]. }. Punto t= r .y . D. //Destructor. 0) //Llama al constructor copia . trabaja sobre un objeto ya creado. c. Hay otro método que implementa el compilador por omisión : el operador de asignación. } alozanoi@teleline.x .L.x . Punto(const Punto &p) //Constructor copia. Cuando copiamos o asignamos un objeto Cadena a otro se realiza una copia de sus atributos. strcpy(LaCadena. Como el constructor copia. y= p. Compara direcciones //(*this != c) Compara objetos llamando al operador !=. 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. No hace nada. Una solución es la siguiente : Cadena::Cadena(const Cadena &c) { LaCadena= new char[strlen(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. el constructor copia por omisión no nos sirve para solucionar este problema. { delete []LaCadena.A. Punto(double xx= 0.LaCadena)+1].LaCadena). //Copia la cadena } return *this. double b) { x+= a . y= p.y . en la clase punto podemos añadir el constructor copia y el operador de asignación: class Punto { double x. Cadena c("1234567890"). c.

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

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

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

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

void main() { Derivada ob(3).h> class Base { int B1. public: Derivada(int a) { D= a. ob.Poner(1.I. D. B2= b. } 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.MostrarD(). public: void Poner(int a. } }. Ejemplo : #include <iostream. B2. } }. ob. 2). class Derivada : public Base { int D. 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. 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.es Apuntes de clase . } void MostrarB() { cout << B1 << " " << B2 << endl. Si podemos modificar los miembros privados de la base usando los métodos públicos disponibles para ello.A. int b) { B1= a. } void MostrarD() { cout << D << endl.I. Programación en lenguajes estructurados. alozanoi@teleline. 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].© A.MostrarB(). ob.L.

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful