Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Introducción a la Unidad de Aprendizaje 0.0 Algoritmia y programación estructurada Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Algoritmia y programación estructurada Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 ¿Qué es una computadora? Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • ¿Qué es información? Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • Una computadora es una máquina capaz de procesar información a gran velocidad. 4 • Los datos ordenados son los que constituyen una entrada (input) a la computadora, la cuál se encarga de procesar mediante una lógica (programa) para producir una nueva información de salida (output). Información de entrada Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • La Información es un conjunto de datos ordenados que representan algo. Información de salida Procesamiento 5 Hardware Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Una computadora esta compuesta por un conjunto de componentes electrónicos, mecánicos e interfaces para interactuar con el exterior (usuarios u otros dispositivos) y por un conjunto de programas que determinan que operaciones llevar a cabo. Computadora Software 6 Entrada Conjunto de programas (software) Salida Una computadora esta formada por un parte física y otra lógica (hardware & software), la primera de estas esta conformada por los elementos físicos que la conforman (dispositivos electrónicos y mecánicos), la parte lógica es aquella que determina que procesos se van a realizar con la información de entrada. Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Computadora (hardware) 7 • La razón de ser de una computadora es poder resolver problemas capaces de ser modelados y representados en datos coherentes y ordenados (información), apoyándose de su gran velocidad y capacidad de seguir una serie de pasos programados con anterioridad y dependientes de la información que se maneja. Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • Para definir el conjunto de programas de una computadora existen personas responsables de indicar a la computadora la lógica de procesamiento. Cada programa es que es definido necesariamente es construido por especialistas (arquitectos de software y programadores). • ¿Qué información es capaz de procesar una computadora? 8 • La información de salida es transformada a un formato entendible por el usuario o dispositivo que la recibirá, lo que significa que no obligatoriamente el procesamiento realizado con la información se realizo como aparentemente se ve a la salida. Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • La información que puede ser procesada por la computadora será toda aquella que se encuentre codificada de manera tal que sea posible manipular por los dispositivos que la conforman, i.e. la información de entrada es digitalizada. 9 Algoritmia Disciplina del conocimiento cuyo objeto de estudio son los algoritmos. • Conceptos a importantes • • • • Algoritmo Paradigma Programa de computadora Programación Programación estructurada Es una forma de escribir programas de computadora (Es un paradigma de programación). Los principios que rigen este paradigma de programación son el uso de únicamente tres estructuras de control: secuencia, selección e iteración. • • • • Algoritmia y programación estructurada 0.0 Algoritmia y programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Algoritmia y programación estructurada Secuencia Selección Iteración Modularidad 10 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad I "Conceptos básicos y herramientas de programación" 1.1 Algoritmo (pseudo–código) Estructuras de datos (Prof. Edgardo A. Franco) 1 • Algoritmia • ¿Qué es un algoritmo? • Métodos algorítmicos • Diagrama de flujo • • • • • Símbolos utilizados en los diagramas de flujo Reglas para la construcción de diagramas de flujo Ejemplo 01 Ejemplo 02 Ejemplo 03 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Pseudocódigo • Convenciones comunes de un pseudocódigo • Ejemplo 04 2 • Área de estudio cuyo objeto de estudio son los algoritmos. • En computación un algoritmo permite modelar la serie de pasos necesarios a realizar para poder resolver una parte o la totalidad de un problema computacional. • Al hablar de un problema computacional se hace referencia a la necesidad de dada cierta información alcanzar un resultado buscado sabiendo que existe una o un conjunto de soluciones capaces de ser encontradas utilizando las capacidades de procesamiento de una computadora. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Algoritmia 3 • Es un conjunto ordenado y finito de operaciones que permite hallar la solución de un problema. • Podemos decir que un algoritmo es una "receta", ya que si se sigue de manera correcta encuentran un resultado en un tiempo acotado. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez ¿Qué es un algoritmo? • P.g. escribe un algoritmo para resolver el problema de llegar de tu casa a ESCOM. 4 Es un conjunto preescrito de instrucciones o reglas bien definidas, ordenadas y finitas que permite realizar una actividad mediante pasos sucesivos que no generen dudas a quien lo ejecute. Dados un estado inicial y una entrada, siguiendo los pasos sucesivos se llega a un estado final y se obtiene una solución. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Definición formal de algoritmo 5 • Un algoritmo es univoco, lo que implica que si se ejecuta varias veces el mismo algoritmo sobre un conjunto de datos de entrada, siempre se obtiene la misma solución a la salida. Además, el resultado debe generarse en un tiempo finito. • Los métodos que utilizan algoritmos se denominan métodos algorítmicos, en oposición a los que implican algún juicio o interpretación, que se denominan heurísticos. Los métodos algorítmicos se pueden implementar fácilmente en computadoras; sin embargo los métodos heurísticos no con facilidad, además de que no aseguran obtener la misma salida siempre ante las mismas entradas. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Métodos algorítmicos 6 • Existen distintas formas gráfica de representar un algoritmo, el diagrama de flujo fue una de las primeras empleadas. • Un diagrama de flujo se utiliza símbolos con significados bien definidos que representan los pasos del algoritmo, y representan el flujo de ejecución mediante flechas que conectan los puntos de inicio y de término. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Diagrama de flujo 7 • Muestra los pasos o procesos a seguir para alcanzar la solución de un problema • Utilizan símbolos (cajas) estándar y tienen los pasos del algoritmo escritos en estas cajas unidas por flechas Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Es la representación gráfica de un algoritmo • La secuencia del algoritmo esta determinado por el flujo de la flechas 8 Inicio y Fin Almacenamiento/ Salida de datos Lectura/Entrada de datos Conector Proceso Flujo del diagrama Decisión Decisión múltiple Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Símbolos utilizados en los diagramas de flujo 9 Sumar Menos Multiplicación División Equivalencia Mayor que Menor que Mayor o igual que Menor o igual que ←o→ Asignación Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez + * / = > < ≥ ≤ <> o != Diferente de «La definición de datos se da por supuesta, principalmente para variables sencillas» 10 1. Todo diagrama de flujo debe tener un inicio y un fin 2. Las líneas utilizadas para indicar la dirección del flujo del diagrama deber ser rectas: verticales u horizontales 3. Todas las líneas utilizadas para indicar la dirección del flujo del diagrama deben estar conectadas mediante algún símbolo 4. El diagrama de flujo debe construirse de arriba hacia abajo y de izquierda a derecha Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Reglas para la construcción de diagramas de flujo 11 La notación utilizada en el diagrama de flujo debe ser independiente del lenguaje de programación 6. Si la construcción del diagrama de flujo requiere más de una hoja se deben utilizar los conectores adecuados Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez 5. 12 • Diseñe un algoritmo para calcular el área de un triangulo. • Se recibe como entrada la base y la altura. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 01 13 • Diseñe un algoritmo para calcular el área de un triangulo. • Se recibe como entrada la base y la altura. Inicio base, altura Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 01 area ← (base * altura) / 2 área Fin 14 • Construir un algoritmo que, al recibir como entrada una clave de un empleado y los seis primeros sueldos del año de este, calcule el ingreso total semestral y el promedio mensual para el empleado, finalmente se imprimirá su clave, el ingreso total y el promedio mensual. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 02 15 • Construir un algoritmo que, al recibir como entrada una clave de un empleado y los seis primeros sueldos del año de este, calcule el ingreso total semestral y el promedio mensual para el empleado, finalmente se imprimirá su clave, el ingreso total y el promedio mensual. Inicio clave, su1, su2, su3, su4, su5, su6 ingreso ← su1 + su2 + su3 + su4 + su5 + su6 promedio ← ingreso / 6 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 02 clave, ingreso, promedio Fin 16 • Calcular la media de una serie de números positivos, suponiendo que los datos se leen uno a uno. • Un valor de cero como entrada indicará que se ha alcanzado el final de la serie de números positivos. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 03 17 numdatos ← 0 suma← 0 1 media ← suma/ (numdatos‐1) media dato Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Inicio Fin numdatos ← numdatos + 1 suma← suma+ dato si dato <>0 no 1 18 • El pseudocódigo es una descripción de alto nivel de un algoritmo que emplea una mezcla de lenguaje natural con algunas convenciones sintácticas propias de lenguajes de programación, a usar (es un supuesto lenguaje) . • Es utilizado para describir algoritmos de manera formal en libros y publicaciones científicas, y como producto intermedio durante el desarrollo de un algoritmo. • El pseudocódigo está pensado para facilitar a las personas el entendimiento de un algoritmo, y por lo tanto puede omitir detalles irrelevantes que son necesarios en una implementación. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Pseudocódigo 19 • Es independiente del lenguaje de programación. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Programadores diferentes suelen utilizar convenciones distintas, que pueden estar basadas en la sintaxis de lenguajes de programación concretos. Sin embargo, el pseudocódigo en general es comprensible sin necesidad de conocer o utilizar un entorno de programación específico, y es a la vez suficientemente estructurado para que su implementación se pueda hacer directamente a partir de él. • La definición de datos se da por supuesta, principalmente para variables sencillas, pero si se emplea variable más complejas, por ejemplo pilas, colas, vectores, etc., se pueden definir en la cabecera del algoritmo. 20 21 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Asignación x←y y→x • Variables declaradas por el desarrollador volumen←∏ r2h resultado←sin(a) Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Convenciones comunes de un pseudocódigo 22 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Secuencia de instrucciones Instrucción1 Instrucción2 Instrucción3 Instrucción4 Instrucciónn Diagrama de flujo Pseudocódigo 23 condición si Instrucciones Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Condicionales no Pseudocódigo 24 condición no si Instrucciones2 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Condicional doble Pseudocódigo Instrucciones1 25 condición1 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Condicional múltiple no si condición2 Instrucciones1 no Pseudocódigo si Instrucciones2 condición3 si no 26 condición si no Pseudocódigo Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Iterativa Instrucciones 27 • Estructuras de control Iterativa condición si Repetir Instrucciones Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Pseudocódigo no Mientras ≈ Repetir 28 • Estructuras de control Iterativa i≤n no i←x si Para Instrucciones i ← i+1 Para → mientras Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Pseudocódigo 29 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Anidamiento 30 • Calcular la media de una serie de números positivos, suponiendo que los datos se leen uno a uno. • Un valor de cero como entrada indicará que se ha alcanzado el final de la serie de números positivos. Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 04 31 Inicio numdatos ← 0 suma← 0 1 media ← suma/ (numdatos‐1) 1) media Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 04 (Algoritmo en diagrama de flujo) dato Fin numdatos ← numdatos + 1 suma← suma+ dato si dato <>0 no 1 32 Procedimiento Media() numdatos<‐0 suma<‐0 repetir dato<‐Entrada() numdatos<‐numdatos+1 suma‐>suma+dato hasta que ¬(dato<>0) media<‐suma/(numdatos‐1) media‐>Salida() fin procedimiento Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 04 (Algoritmo en pseudocódigo) 33 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad I "Conceptos básicos y herramientas de programación" 1.2 La arquitectura de Von Neumann Estructuras de datos (Prof. Edgardo A. Franco) 1 • Arquitectura de una computadora • Elementos básicos de una arquitectura • Aspectos que definen y distinguen arquitectura una • Arquitectura de una computadora según la organización de los elementos • Arquitectura Harvard • Arquitectura Von Neumann • Funcionamiento general de este tipo de arquitectura Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • Computadora: "Máquina capaz de procesar información a muy alta velocidad". • Podemos determinar con esta definición que esta tiene una arquitectura establecida y un modo de funcionamiento, debido al hecho de ser una maquina. • La arquitectura de una computadora es un modelo y una descripción funcional de los requerimientos y las implementaciones de diseño para varias partes de una computadora, con especial interés en la forma en que la unidad central de proceso CPU trabaja internamente y accede a las direcciones de memoria. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Arquitectura de una computadora 3 • Todas las computadoras constan principalmente de tres partes, la CPU que procesa los datos, la memoria que guarda los datos y los dispositivos de entrada y salida que permiten la comunicación con el exterior. Computadora digital Procesador Memoria Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Elementos básicos de una arquitectura Dispositivos de entrada y salida 4 Procesador • Desde el punto de vista funcional, un microprocesador es un circuito integrado que incorpora en su interior una unidad central de proceso (CPU) y todo un conjunto de elementos lógicos que permiten enlazar otros dispositivos como memorias y puertos de entrada y salida (I/O), formando un sistema completo para cumplir con una aplicación específica dentro del mundo real. Para que el sistema pueda realizar su labor debe ejecutar paso a paso un programa que consiste en una secuencia de números binarios o instrucciones, almacenándolas en uno o más elementos de memoria, generalmente externos al mismo Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Procesador Datapath Control 5 • La memoria primaria está directamente conectada a la CPU de la computadora. Debe estar presente para que la CPU funcione correctamente. (Registros del procesador, Memoria cache y memoria principal de acceso aleatorio RAM). • La memoria secundaria requiere que la computadora use sus canales de entrada/salida para acceder a la información y se utiliza para almacenamiento a largo plazo de información persistente. (Discos Duros, Memorias Flash, etc.) Memoria Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Memoria • Se refiere a los componentes de una computadora, dispositivo y medios de almacenamiento que retienen datos informáticos durante algún intervalo de tiempo. Las memorias de computadora proporcionan unas de las principales funciones de la computación moderna, la retención o almacenamiento de información. Es uno de los componentes fundamentales de todas las computadoras modernas. 6 Dispositivos Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Dispositivos de entrada‐salida • E/S o I/O (input/output), es la colección de interfaces que usan las distintas unidades funcionales (subsistemas) de un sistema de procesamiento de información para comunicarse unas con otras. Entrada Salida 7 Computadora Procesador Unidad de Control Memoria Dispositivos Entrada Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez • De acuerdo a lo anterior, una arquitectura de computadora será formada por los siguientes elementos básicos. Datapath (ALU, Registros, …) Salida *Un datapath es una colección de unidades funcionales, por ejemplo ALUs o multiplicadores, o unidades que realizan un proceso u operaciones con los datos. La mayoría de los procesadores consisten en un datapath y una a unidad de control, la unidad de control se dedica a regular la interacción entre el datapath y la memoria. 8 • Toda arquitectura computacional incluye tres aspectos que la definen y distinguen. 1. Conjunto de operaciones 2. Organización de la computadora 3. Hardware de la computadora Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Aspectos que definen y distinguen una arquitectura 1. El conjunto de operaciones: es la interfaz visible entre el hardware y la programación. • Las dos principales aproximaciones al conjunto de instrucciones son: • CISC (Complex Instruction Set Computer) • RISC (Reduced Instruction Set Computer) 9 1. Arquitectura Von Neumann 2. Arquitectura Harvard Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez 2. La organización de la computadora: es la lógica de funcionamiento de la arquitectura, pueden distinguirse dos arquitecturas teóricas básicas. Computadora Procesador Unidad de Control Memoria Dispositivos Entrada Datapath (ALU, Registros, …) Salida 10 • i.e. este aspecto se refiere a las características del hardware (Velocidad, capacidad, …). Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez 3. El Hardware de la computadora: es lo que físicamente lleva a cabo el trabajo de procesamiento. De acuerdo a las capacidades y tipos se organizan de acuerdo a una arquitectura estándar para la construcción de una computadora. 11 • La organización de la computadora: es la lógica de funcionamiento de la arquitectura, pueden distinguirse dos arquitecturas teóricas básicas. 1. Arquitectura Von Neumann 2. Arquitectura Harvard Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Arquitectura de una computadora según la organización de los elementos • Ambos modelos contemplan la existencia de un modulo de procesamiento, una serie de dispositivos de entrada/salida y memoria. 12 • Arquitectura Harvard hace referencia una organización de la computadora que utiliza dispositivos memorias físicamente separadas para las instrucciones y para los datos. • El término proviene de la computadora Harvard Mark I, que almacenaba las instrucciones en cintas perforadas y los datos en interruptores. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Arquitectura Harvard 13 • Cada memoria dispone de su respectivo bus, lo que permite, que la CPU pueda acceder de forma independiente y simultánea a la memoria de datos y a la de instrucciones. • Como los buses son independientes éstos pueden tener distintos contenidos en la misma dirección . • Además de que el ancho de palabra del bus de datos de cada memoria puede ser distinto. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Memoria Usos de esta arquitectura • Esta arquitectura suele utilizarse en Microcontroladores y DSPs (procesadores digitales de señales), usados habitualmente en productos para procesamiento de audio y video así como sistemas electrónicos con cómputo embebido. 14 Procesador Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Organización de la computadora digital según la arquitectura Harvard 15 • El nacimiento u origen de la arquitectura Von Neumann surge a raíz de una colaboración en el proyecto ENIAC del matemático de origen húngaro, John Von Neumann. • Este trabajaba en 1945 en el laboratorio atómico de Los Alamos cuando se encontró con uno de los constructores de la ENIAC. Compañero de Albert Einstein, Goedel y Turing en Princeton, Von Neumann se interesó por el problema de la necesidad de "recablear" la máquina para cada nueva tarea. • En 1949 había encontrado y desarrollado la solución a este problema, consistente en poner la información sobre las operaciones a realizar en la misma memoria utilizada para los datos, escribiéndola de la misma forma, es decir en código binario (Computadora EDVAC). Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Arquitectura Von Neumann 16 Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez • La arquitectura Von Neumann es un modelo de organización en arquitecturas de computadoras que utilizan el mismo dispositivo de almacenamiento tanto para las instrucciones como para los datos (a diferencia de la arquitectura Harvard). 17 v Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez • Los ordenadores con esta arquitectura constan de cinco partes: La unidad aritmético‐lógica o ALU, la unidad de control, la memoria, dispositivos de entrada/salida y el bus de datos que proporciona un medio de transporte de los datos entre las distintas partes. 18 • Se compone de un conjunto de celdas del mismo tamaño (número de bits). • Cada celda está identificada por un número binario único, denominado dirección. • Una vez seleccionada una celda mediante su correspondiente dirección, se pueden hacer dos operaciones: • Lectura: Permite conocer el valor anteriormente. • Escritura: Almacena un nuevo valor. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Memoria almacenado 19 • Con la aparición de los circuitos integrados, y en concreto a partir de los años 70, cuando la tecnología alcanzó el nivel de integración adecuado, se integró en una sola pastilla la CPU. A este circuito integrado se le denomina Microprocesador. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Unidad Central de Proceso (CPU) • Es el conjunto formado por la Unidad de Control, los registros y la Unidad Aritmética Lógica, es decir es el bloque encargado de ejecutar las instrucciones. Una forma de determinar el rendimiento de un computador es por el número de instrucciones que ejecuta por segundo (MIPS). 20 • Realiza las operaciones elementales, tanto aritméticas como lógicas, que implementa el computador: suma, resta, AND, OR, NOT, etc. • Los datos con los que opera se leen de la memoria, y pueden almacenarse temporalmente en los registros que contiene la CPU. Unidad de Control • Ejecuta las instrucciones máquina almacenadas en la memoria. • Captura las instrucciones y las decodifica. • Según el tipo de instrucción, genera las señales de control a todas las unidades internas de la CPU para poder realizar su ejecución. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Unidad Aritmético‐Lógica (ALU) 21 • Realiza la transferencia de información con las unidades externas, denominadas periféricos: unidades de almacenamiento secundario (disco duro, disquete, cinta, etc.), impresoras, terminales, monitores, etc. • La memoria secundaria (MS), se considera como un periférico. La MS es más lenta que la principal, pero tiene una mayor capacidad de almacenamiento. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Unidad de Entrada/Salida 22 • Además de las 4 unidades básicas, en un computador existen conjuntos de señales, que se denominan buses, y cuya función es transferir las instrucciones y los datos entre las distintas unidades. • Estos buses se representan en la figura mediante flechas de trazo continuo. Se suelen distinguir tres tipos de buses: Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Buses • Bus de direcciones • Bus de datos • Bus de control 23 24 Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Funcionamiento general de este tipo de arquitectura 1. Obtiene la siguiente instrucción desde la memoria en la dirección indicada por el contador de programa (PC) y la guarda en el registro de instrucción (IR). 2. Aumenta el contador de programa en la longitud de la instrucción para apuntar a la siguiente instrución. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián • Un ordenador con esta arquitectura realiza o emula los siguientes pasos secuencialmente: 25 4. Se ejecuta la instrucción en este paso puede cambiar el valor del contador del programa, permitiendo así operaciones repetitivas. El contador puede cambiar también cuando se cumpla una cierta condición aritmética, haciendo que el ordenador pueda 'tomar decisiones', que pueden alcanzar cualquier grado de complejidad, mediante la aritmética y lógica anteriores. Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez 3. Decodifica la instrucción mediante la unidad de control. Ésta se encarga de coordinar el resto de componentes del ordenador para realizar una función determinada. 26 5. Vuelve al paso 1 Dispositivos periféricos Unidad de control UC Unidad Aritmética y lógica ALU E E R/W PC AR IR DR AC Algoritmia y programación estructurada 1.2 La arquitectura de Von Neumann Autor: M. en C. Edgardo Adrián Franco Martínez Unidad central de proceso CPU Unidad de E/S Unidad de Memoria Bus de Direcciones Bus de Datos Bus de Control 27 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad I "Conceptos básicos y herramientas de programación" 1.3 Herramientas de programación Estructuras de datos (Prof. Edgardo A. Franco) 1 • Lenguaje de programación • Programa computacional • Clasificaciones de los lenguajes de programación • Clasificación según su nivel de abstracción • Clasificación según su modo de ejecución final • Clasificación según su paradigma de programación Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Lenguaje C • Historia del lenguaje C • Ventajas y desventajas del lenguaje C • El estándar ANSI C 2 • Un lenguaje de programación es un idioma artificial diseñado para expresar computaciones que pueden ser llevadas a cabo por máquinas como las computadoras. • Pueden usarse para crear programas que controlen el comportamiento físico y lógico de una máquina, esto permite expresar algoritmos con precisión e interacción humano‐maquina. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Lenguaje de programación 3 • Sintáctica (reglas que gobiernan la combinatoria de los símbolos y la formación de unidades superiores a estos) • Semántica (aspectos del significado, sentido o interpretación del significado de un determinado elemento, símbolo, palabra, expresión o representación formal) Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Está formado de un conjunto de símbolos y reglas sintácticas y semánticas que definen su estructura y el significado de sus elementos y expresiones. 4 • Un programa computacional es un conjunto de instrucciones que una vez ejecutadas realizarán una o varias tareas en una computadora. • La razón de ser de un programa computacional es permitir resolver problemas con apoyo de equipos computacionales por lo que al crearlos es necesario abstraer los componentes de este y modelarlos en un ambiente computacional. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Programa computacional Abstracción:, acto mental en el que conceptualmente se aísla un objeto o una propiedad de un objeto. 5 • En la actualidad hay muchos tipos de lenguajes de programación, cada uno de ellos con sus propias reglas, terminología, sintaxis y manera de crear un programa computacional. • La clasificación de los lenguajes de programación puede realizarse desde tres aspectos básicos. • Según su nivel de abstracción • Según su modo de ejecución final • Según su paradigma de programación Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Clasificación de los lenguaje de programación 6 Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Clasificación de los lenguaje de programación según su nivel de abstracción 7 • Lenguajes de programación de bajo nivel: Son mucho mas fáciles de utilizar que el lenguaje máquina, pero dependen mucho de la máquina o computadora al igual que el lenguaje máquina. • El lenguaje ensamblador fue el primer lenguaje de programación que trato de sustituir el lenguaje máquina por otro mucho más parecido al de los seres humanos. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Lenguaje Máquina: es el lenguaje de programación que entiende directamente la computadora o máquina. Este lenguaje de programación utiliza el alfabeto binario, es decir, el 0 y el 1. 8 Lenguaje maquina (Instrucciones en binario) Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Lenguaje de bajo nivel (Instrucciones en código maquina) 9 • Son precisos para ciertas aplicaciones como la creación de sistemas operativos, ya que permiten un manejo abstracto (independiente de la máquina, a diferencia del ensamblador), pero sin perder mucho del poder y eficiencia que tienen los lenguajes de bajo nivel. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Lenguaje de medio nivel: Lenguaje de medio nivel es un lenguaje de programación que se encuentran entre los lenguajes de alto nivel y los lenguajes de bajo nivel. Suelen ser clasificados muchas veces de alto nivel, pero permiten ciertos manejos de bajo nivel. 10 11 Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Lenguajes de programación de alto nivel: Este tipo de lenguajes de programación son independientes de la máquina, lo podemos usar en cualquier computador con muy pocas modificaciones o sin ellas, son muy similares al lenguaje humano, pero precisan de un programa interprete o compilador que traduzca este lenguaje de programación de alto nivel a lenguaje de máquina que la computadora pueda entender. 12 • El modo de ejecución final de un lenguaje de programación, se refiere al proceso necesario para poner en ejecución las instrucciones de dicho lenguaje en un equipo de cómputo. Para finalmente proporcionar las entradas que serán tomadas para obtener una salida de todo el conjunto de instrucciones (programa computacional). Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Clasificación de los lenguaje de programación según su modo de ejecución final 13 • Lenguaje de programación que requiere de un proceso de compilación antes de poder ser ejecutado. Código Fuente Entrada Compilador Programa en lenguaje maquina u objeto Programa en lenguaje maquina u objeto Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Lenguaje compilado Salida 14 • Es un lenguaje de programación que está diseñado para ser ejecutado por medio de un intérprete. Código Fuente Entrada Intérprete Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Lenguaje interpretado Salida Compilador 15 • El paradigma de programación es un modelo que rige como construir un programa de computación bajo un lenguaje de programación, por lo que algunos lenguajes han surgido orientándose a ellos. También existen lenguajes de programación capaces de soportar más de un paradigma de programación Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Clasificación de los lenguaje de programación según su paradigma de programación Un paradigma de programación representa un enfoque particular o filosofía para la construcción del software. 16 • También hay situaciones donde un paradigma resulta más apropiado que otro. • En la actualidad el paradigma orientado a objetos es el más utilizado debido a la facilidad para abstraer a su filosofía la mayoría de las soluciones a los problemas actuales, para su implementación y a reemplazado al paradigma de programación estructurada muy empleado en la década de los 80’s y 90’s. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez • Un paradigma de programación no es mejor uno que otro sino que cada uno tiene ventajas y desventajas. 17 • C es un lenguaje de programación creado en 1972 por Dennis MacAlistair Ritchie en los Laboratorios Bell como evolución del anterior lenguaje B, creado por Ken Thompson. • Se trata de un lenguaje fuertemente tipificado de medio nivel pero con muchas características de bajo nivel. • Dispone de las estructuras típicas de los lenguajes de alto nivel pero, a su vez, dispone de construcciones del lenguaje que permiten un control a muy bajo nivel. • Los compiladores suelen ofrecer extensiones al lenguaje que posibilitan mezclar código en ensamblador con código C o acceder directamente a memoria o dispositivos periféricos. Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Lenguaje C 18 • Programación Estructurada • Economía de expresiones • Gran cantidad de operadores y tipos de datos • Codificación en alto y bajo nivel simultáneamente Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Ventajas del Lenguaje C • Reemplaza ventajosamente la programación en ensamblador • Utilización natural de las funciones primitivas del sistema operativo (Unix) 19 • De propósito general • No posee de instrucciones de entrada y salida • No posee de instrucciones de manejo de cadenas de caracteres • La libertad en la escritura en los programas lleva a errores en la programación (semánticos) que, por ser correctos sintácticamente no se detectan a simple vista • La precedencia de operadores convierten las expresiones en pequeños rompecabezas Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Desventajas del Lenguaje C 20 • Un código fuente en C, es un conjunto de líneas que expresan computaciones bajo la sintaxis y semántica del lenguaje C. Un programa escrito en C tiene como características sobresalientes, el ser eficiente y veloz. • Como el lenguaje C es compilado, se requiere del empleo de un compilador apropiado según la plataforma en la que se desea ejecutar el programa. Código Fuente en C Compilador ANSI C (gcc) Programa ejecutable u código objeto Algoritmia y programación estructurada 1.3 Herramientas de programación Autor: M. en C. Edgardo Adrián Franco Martínez Código fuente en C 21 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad I "Conceptos básicos y herramientas de programación" 1.5 Representación de expresiones Estructuras de datos (Prof. Edgardo A. Franco) 1 • Operadores • Precedencia de Operadores • Operadores y expresiones aritméticas • Expresiones condicionales; operadores relacionales y lógicos • Operaciones para el manejo de bits • La librería estándar <math.h> Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Funciones • Constantes • Ejemplo 2 • Son palabras o símbolos que implican una acción sobre ciertas variables. • Pueden operar de manera: • Unaria (con 1 variable) • Binaria (con 2 variables) • Ternaria (con 3 variables) • Existen en C operadores: • • • • • • Aritméticos Relacionales Lógicos De Asignación De Dirección De Bits Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores 3 Operadores Tipo Asociatividad ( ) [ ] ‐> Alta prioridad Izquierda a derecha ! ~ ++ ‐‐ + ‐ * & (tipo) sizeof Unarios Derecha a izquierda * / % + ‐ Aritméticos Izquierda a derecha << >> Corrimiento de bits Izquierda a derecha < <= > >= == != Relacionales Izquierda a derecha &^| Bits Izquierda a derecha && || Lógicos Izquierda a derecha ?: Condicional Derecha a izquierda = += ‐= *= /= %= &= ^= |= <<= >>= Asignación Derecha a izquierda , Evaluación Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Precedencia de Operadores 4 Izquierda a derecha Operador Nombre Descripción * Multiplicación 5*2 → 10 / División 5/2 → 2 % Módulo 5%2 → 1 + Suma 5+2 → 7 ‐ Resta 5‐2 → 3 (tipo de dato) “Cast” forzado (double)5 → 5.0 sizeof(tipo de dato) Tamaño de dato sizeof(int) → 4 Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores y expresiones aritméticas 5 Operador = ++ ‐‐ += ‐= *= /= %= Abreviado a=2; n++; n‐‐; n+=2; n‐=2; n*=2; n/=2; n%=2; No Abreviado a=2; n=n+1; n=n‐1; n=n+2; n=n‐2; n=n*2; n=n/2; n=n%2; Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores y expresiones de asignación 6 • Son expresiones validas aquellas que utilicen de manera adecuada algún tipo de operador, y el resultado de su evaluación dependerá del orden de los operadores en la expresión, su prioridad y asociatividad. Expresión en C a=a+5*b; x*=y+1; x=++n; y=n‐‐*5+n; z=n+1*45+10.4E‐10*6 z=(n+1)*(45+10.4E‐10)*6 x+=x*(10.5E11+x); Significado a=a+(5*b) x=x*(y+1) x=n+1 y n=n+1 y=((n‐1)*5)+n y n=n‐1 z=n+(1*45)+(10.4E‐10*6) z=(n+1)*(45+10.4E‐10)*6 x=x+(x*10.5E11)+x b=z=x=10.5; b=10.5 y z=10.5 y x=10.5 Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Expresiones 7 aritméticas invalidas las Expresión en C Posible significado a dar a=a+5*b=4; a=a+(5*b) y b=4 x*=y+1++; x=x*(y+2) x=++n‐‐; x=n+1 y n=n‐1 y=n‐‐*5++n; y=((n‐1)*6)+n y n=n‐1 z=n+1*45+10.4x10^‐10*6 z=n+(1*45)+(10.4E‐10*6) z=(n+1)*(45+10.4E‐ 10)*6=x ++x=x*(10.5E11+x++); z=(n+1)*(45+10.4E‐10)*6 y x=z x=x+1+x+(x*10.5E11)+x; Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez • Son expresiones siguientes. 8 • Debido a que el lenguaje C es un lenguaje fuertemente tipificado, es necesario estar consientes de las asignaciones que se realizan entre distintos tipos de datos. • Aunque sintácticamente el lenguaje permite realizar asignaciones entre variables de distintos tipos de datos es necesario realizar de manera consciente estas asignaciones y apoyarse de la operación de modelado o cast. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Casting (Moldeado de variables) 9 • b=(int)a; //Antes de realizar la asignación a "b" se moldea a "a" como entero. • b=(unsigned asignación a sin signo. int)k; //Antes de realizar la "b" se moldea a "k" como entero • c=(float)g; "c" //Antes de realizar la asignación a se moldea a "g" como flotante. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez (cast) • c=(char)j; //Antes de realizar la asignación a "c" se moldea a "j" como char. 10 • Si se tienen expresiones entre operadores de relación, se puede decir que dichas expresiones son condicionales, las cuales a su vez pueden estar unidas mediante operadores lógicos para obtener una condición múltiple. • Los operadores de relación tienen la misma precedencia y esta esta por debajo de los operadores aritméticos. • Las expresiones condicionales son evaluadas de izquierda a derecha y si se encuentran operadores lógicos son tratados en ese orden. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Expresiones condicionales; operadores relacionales y lógicos 11 Operador Nombre Descripción == Igual a if (a==‘s’) != Diferente de if (a!=null) > Mayor que if (a>0.5) < Menor que if (a<2l) >= Mayor o igual que if (a>=2f) <= Menor o igual que if (a<=3) Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores Relacionales 12 Operador Nombre Descripción && Y (AND) if ((a>3) && (a<9)) || O (OR) if ((a==2) || (a==3)) ! NEGADO (NOT) if (!(a==3)) es igual a if (a!=3) Importante: Cuando se evaluá una condicional, los valores que se obtienen son: Si es FALSA se obtiene cero. Si es VERDADERA se obtiene algo diferente de cero. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores Lógicos 13 #include<stdio.h> #include<math.h> int main(void) { const float pi=3.1416; float distancia,x1=10,y1=11,x2=20,y2=16; //Cálculo de la distancia entre dos puntos distancia=sqrt(pow((x2-x1),2)+pow((y2-y1),2)); if(distancia>0&&x2-x1<0&&y2-y1<0) printf("\nEl punto P2(%.2f,%.2f) esta debajo de P1(%.2f,%.2f)",x2,y2,x1,y1); if(distancia>0&&x2-x1>0&&y2-y1>0) printf("\nEl punto P2(%.2f,%.2f) esta por encima de P1(%.2f,%.2f)",x2,y2,x1,y1); if(distancia==0) printf("\nEl punto P2 y P1 están en las mismas coordenadas(%.2f,%.2f)",x2,y2); return 0; } Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo de condicionales; operadores relacionales y lógicos 14 • El lenguaje C proporciona seis operadores para manejo de bits; sólo pueden ser aplicados a variable integrales, esto es, char, short, int y long, con o sin signo. • No se debe confundir el operador & con el operador &&, & es el operador Y sobre bits, && es el operador lógico Y. Similarmente los operadores | y ||. • El operador unario ~ sólo requiere un argumento a la derecha del operador. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operaciones para manejo de bits • Los operadores de desplazamiento, >> y <<, mueven todos los bits en una posición hacia la derecha o la izquierda un determinado número de posiciones. • Como los operadores desplazan bits en un sentido, la computadora trae ceros en el otro extremo. Se debe recordar que un desplazamiento no es una rotación: los bits desplazados en un extremo no vuelven al otro. Se pierden y los ceros traídos los reemplazan. 15 Operador Nombre Descripción << Corrimiento a la izquierda b=a>>2; >> Corrimiento a la derecha b=a<<3; & Y (AND) entre bits c=a&128; | O (OR) entre bits c=a|0x0a; ~ Complemento A1 c=~a; ^ O exclusivo (XOR) c=^a; Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores de Bits 16 • El operador AND de bits (&) a menudo es usado para enmascarar álgun conjunto de bits. • El operador OR (|) es empleado para encender bits. • El operador OR exclusivo (^) pone uno en cada posición donde sus operandos tienen bits diferentes. • El operador unario (~) realiza el complemento A1; esto es convierte cada bit 1 en un bit 0 y viceversa. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operaciones del manejo de bits 17 • Una aplicación que tienen los operadores de desplazamiento de bits es para realizar multiplicaciones y divisiones rápidas con enteros. Como se ve en la siguiente tabla, donde un desplazamiento a la izquierda es multiplicar por 2 y uno a la derecha dividir por 2. • Los desplazamientos son mucho más rápidos que la multiplicación actual (*) o la división (/) por dos. Por lo tanto, si se quieren multiplicaciones o divisiones rápidas por 2 se usan desplazamientos. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez • Los operadores << y >> realizan corrimientos a nivel de bits, ya sea a la izquierda o derecha. 18 char x x = 7; x << 1; x << 3; x << 2; x >> 1; x >> 2; Ejecución 00000111 00001110 01110000 11000000 01100000 00011000 Valor de x 7 14 112 192 96 24 Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez • Multiplicaciones y divisiones por 2 al realizar corrimientos (<< y >>). 19 #include<stdio.h> int main(void) { int byte=0xFF; printf("\nEl valor byte&=0x00; printf("\nEl valor byte|=0xFF; printf("\nEl valor byte>>=1; printf("\nEl valor byte<<=2; printf("\nEl valor return 0; } de byte es: %4X H",byte); de byte es: %4X H",byte); Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo: Operaciones del manejo de bits de byte es: %4X H",byte); de byte es: %4X H",byte); de byte es: %4X H",byte); 20 Operador <<= >>= &= |= ^= = Abreviado n<<=2; n>>=2; n&=0x0a; n|=7; n^=0x03; n=0x7f; Nota: 0x7f, 0x0a, 0x03 son un números hexadecimales. No Abreviado n=n<<2; n=n>>2; n=n&0x0a; n=n|7; n=^0x03; n=0x7f; Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Operadores de Asignación para bits 21 • math.h es un archivo de cabecera de la biblioteca estándar del lenguaje de programación C diseñado para operaciones matemáticas básicas. • Muchas de sus funciones incluyen el uso de números en coma flotante. • Una nota importante: si se está programando en C/C++ bajo Linux, y se utiliza uno de los compiladores nativos de este sistema operativo (gcc o g++), es necesario incluir, al compilar, la opción ‐lm, dado que, de lo contrario, el compilador generará un error. Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez La librería estándar <math.h> 22 ceil(x) Redondea al entero más pequeño no menor que x. cos(x)Coseno de x. exp(x) ex. fabs(x)Valor absoluto de x. floor(x)Redondea al entero más grande no mayor que x. log(x)Logaritmo natural de x. log10(x)Logaritmo base 10 de x. pow(x,y) xy. sin(x) Seno de x. sqrt(x) Raíz cuadrada de x. tan(x)Tangente de x. tanh(x)Tangente hiperbólica de x. cosh(x)Coseno hiperbólico de x. sinh(x) Seno hiperbólico de x. fmod(x) Resto del punto flotante de x. *Todas las funciones en las que participan ángulos toman y devuelven radianes. *Todas operan con parámetros de tipo double (también se soportan flotantes) y devuelven resultados de tipo double (pueden guardarse como flotantes). Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez • La biblioteca math.h contiene la definición de muchas funciones matemáticas útiles. El siguiente es un listado breve de algunas funciones. 23 • La biblioteca de matemáticas define varias constantes. Siempre es aconsejable usar estas definiciones. • • • • • • • • • • • • • M_E La base de los logaritmos naturales e. M_LOG2E El logaritmo de e de base 2. M_LOG10E El logaritmo de e de base 10. M_LN2 El logaritmo natural de 2. M_LN10 El logaritmo natural de 10. M_PI pi M_PI_2 pi/2 M_PI_4 pi/4 M_1_PI 1/pi M_2_PI 2/pi M_2_SQRTPI 2/sqrt(pi) M_SQRT2 La raíz cuadrada positiva de 2 M_SQRT1_2 La raíz cuadrada positiva de 1/2 Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Constantes <math.h> 24 #include<stdio.h> #include<math.h> int main(void) { const float pi=3.1416; float distancia,x1=1.5,y1=-10,x2=2.5,y2=20; //Mostrando la diferencia de exactitud entre pi y M_PI printf("\nEl seno de pi es: %f",sin(pi)); printf("\nEl seno de M_PI es: %f",sin(M_PI)); //Cálculo de la distancia entre dos puntos distancia=sqrt(pow((x2-x1),2)+pow((y2-y1),2)); printf("\nLa distancia entre P2(%.2f,%.2f) y P1(%.2f,%.2f) es: %.4f",x2,y2,x1,y1,distancia); return 0; } *Su compilación en Linux sería: gcc programa.c –lm –o programa Algoritmia y programación estructurada 1.5 Representación de expresiones Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo empleando <math.h> 25 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad I "Conceptos básicos y herramientas de programación" 1.6 Flujo de ejecución Estructuras de datos (Prof. Edgardo A. Franco) 1 • Estructuras secuenciales • Estructuras selectivas • • • • • if If else If ‐else if switch‐case operador ? • Estructuras iterativas • while • do‐while • For Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Sentencias de salto • • • • return goto break continue 2 • La secuencia de pasos es la más fácil de las estructuras de control, ya que en lenguaje C basta con escribir los pasos en orden descendente y las instrucciones se ejecutarán de manera secuencial. //01 Declarar tres variables enteras int x, y, z; //02 Igualar las tres variables enteras con VALOR x=y=z=VALOR; //03 Ejecutar la función modulo3D mod3=modulo3D(x,y,z); //04 Mostrar en la salida estandar el rtesultado printf(“\nEl módulo es: %lf”,mod3); //05 Salir del programa return(0); Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras secuenciales 3 • Las estructuras de selección (o bifurcación) se utilizan para elegir entre diversos cursos de acción. • En C hay tres tipos de estructuras de selección: if (selección simple), if…else (selección doble) y switch (selección múltiple) Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras de selección 4 if (expresión) sentencia; Nota: una expresión en C es todo aquello que regresa un valor. Como por ejemplo una condición lógica, operaciones aritméticas, llamadas a funciones, una variable, una constante (numérica, carácter, etc.). if (expresión) { sentencia1; sentencia2; } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if) 5 if (expresión) sentencia; else sentencia; if (expresión) { sentencia1; sentencia2; } else { sentencia1; sentencia2; } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if – else) 6 if (expresión) sentencia; else if (expresión) sentencia; … else sentencia; if (expresión) { sentencia1; sentencia2; } else if { sentencia1; sentencia2; } … else { sentencia1; sentencia2; } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if – else if) 7 switch(expresión) { case 1: sentencias; break; case 2: sentencias; break; : case n: sentencias; break; default: sentencias_default; break; } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (switch‐case) 8 (expresión)? sentencia1 : sentencia2; expresión? sentencia1 : sentencia2; Se ejecuta: sentencia1 si expresión = verdadero sentencia2 si expresión = falso. Es un operador ternario y puede utilizarse para asignar variables: Var = (expresión)? sentencia1:sentencia2; Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (operador ?) 9 if (calificacion>=60) { printf ("Alumno Aprobado"); } else { printf ("Alumno Reprobado"); } if (calificacion>=90) { printf ("Alumno de muy buena calificación"); } else if (calificacion>=70&& calificacion<90) { printf ("Alumno regular"); } else if (calificacion>=60&& calificacion<70) { printf ("Alumno"); } else { printf ("No es alumno"); } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Selección (ejemplos) 10 • Estas estructuras permiten repetir una serie de veces la ejecución de unas líneas de código. • Esta iteración se realiza o bien un número determinado de veces o bien hasta que se cumpla una determinada condición de tipo lógico o aritmético. • En C hay 3 tipos de instrucciones de repetición: while, do…while y for. Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras iterativas 11 • La sentencia while permite repetir un bloque de instrucciones. • La sintaxis del ciclo while es: while(condición) { sentencia o bloque; }; verdadero condición sentencias Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Estructura iterativa (while) falso • Si la condición se cumple se ejecutan las sentencias del bloque y se regresa el flujo de control a evaluar nuevamente la condición. El proceso se repite hasta que la condición sea falsa. • El ciclo puede ejecutarse 0 veces si la condición no se cumple. 12 • El ciclo do‐while es similar al ciclo while excepto que la condición se realiza al final del ciclo, esto fuerza a que se ejecute por lo menos una vez. do{ sentencias; }while(condición); Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Estructura iterativa (do‐while) sentencias condición falso verdadero 13 • La sentencia for permite definir fácilmente ciclos controlados por contador. for(expresion1; expresion2; expresion3) { sentencias; } • Esta es equivalente a la siguiente sentencia while: expresion1; while(expresion2) { sentencias; expresion3; } expresion1 = sentencia de iniciación expresion2 = condición de terminación expresion3 = sentencia de incremento Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Modelado de la iteración (For) expresion1 verdadero condición falso sentencias expresion3 14 • En C hay sentencias para evitar la ejecución estrictamente secuencial del programa. En general (sentencias goto, break y continue) no deben utilizarse para elaborar programas estructurados, aunque pueden ser útiles si se justifica en forma apropiada su aplicación en un código. • return <expresión>; • Se usa para devolver el control del flujo de ejecución desde una función, siendo <expresión> el valor (dato) retornado por ella. Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez Sentencias de salto de C • goto <etiqueta>; …. <etiqueta>: <acciones> • Permite efectuar un salto incondicional hasta otro punto del programa, indicado por una etiqueta. 15 ha iniciado"); 1"); 2"); 3"); 4"); 5"); • break; • Se usa para romper el flujo en un switch‐case o terminar sentencias iterativas (for, while, do‐while). Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez #include<stdio.h> int main(void) { printf("\nEl programa printf("\nInstrucción printf("\nInstrucción goto se_me_antoja; printf("\nInstrucción printf("\nInstrucción se_me_antoja: printf("\nInstrucción } • continue; • Se puede usar en un bloque iterativo (for, while, do‐while) para forzar una nueva iteración del ciclo ignorando las sentencias que están a partir de continue y hasta el fin del ciclo. 16 #include<stdio.h> int main(void) { short i; for(i=0;i<100;i++) { printf("\n%d",i); continue; printf("\nDespues del continue"); } } Algoritmia y programación estructurada 1.6 Flujo de ejecución Autor: M. en C. Edgardo Adrián Franco Martínez #include<stdio.h> int main(void) { short i; for(i=0;i<100;i++) { printf("\n%d",i); break; printf("\nDespues del break"); } } 17 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad II “Modularidad" 2.1 Metodología Divide y vencerás Estructuras de datos (Prof. Edgardo A. Franco) 1 • Divide y vencerás • Ventajas de dividir un problema • Funciones y procedimientos Algoritmia y programación estructurada 2.1 Metodología Divide y vencerás Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • C fue diseñado como lenguaje para soportar el paradigma de programación estructurada, el cual permite entre otras cosas diseñar algoritmos mediante la metodología divide y vencerás, la cual dice: • Para un problema complejo, abstraerlo y dividirlo en pequeños subproblemas. • Cada subproblema dividirlo en otros más pequeños y fáciles de entender. Y continuar así hasta tener dicho problema complejo particionado en pequeños módulos comprensibles y reutilizables para otros problemas. Algoritmia y programación estructurada 2.1 Metodología Divide y vencerás Autor: M. en C. Edgardo Adrián Franco Martínez Divide y vencerás 3 • Abstraer un problema complejo metodología trae muchos beneficios: • • • • • mediante esta Entender mejor un problema complejo. Ir aislando de manera especifica cada subproblema. Escribir algoritmos correctos y más eficientes. Producir programas que son más fáciles de mantener. Escribir programas que son reutilizables. • En la programación estructurada la modularización de una solución es posible al emplear funciones y procedimientos. Algoritmia y programación estructurada 2.1 Metodología Divide y vencerás Autor: M. en C. Edgardo Adrián Franco Martínez Ventajas de dividir un problema 4 • Son elementos que realizan una tarea en particular y retornan un valor a la salida. • Son utilizadas como expresiones primarias y por lo tanto formar parte de expresiones más complejas, es decir, se pueden utilizar para realizar operaciones con el valor que retornan a la salida. Por ejemplo, sumarse, restarse, multiplicarse, dividirse, etc. float valor; valor = 2*pow(x,y)+sqrt(4.23245)+7*sin(2*3.1416); Algoritmia y programación estructurada 2.1 Metodología Divide y vencerás Autor: M. en C. Edgardo Adrián Franco Martínez Funciones 5 • Son elementos que realizan una tarea en particular pero que no retornan un valor a la salida y pueden recibir o no parámetros a la entrada. • Son utilizadas como expresiones instrucción y se invocan cuando se requiere que el programa realice esa tarea en particular. Algoritmia y programación estructurada 2.1 Metodología Divide y vencerás Autor: M. en C. Edgardo Adrián Franco Martínez Procedimientos printf( “Imprimir una cadena de caracteres” ); scanf( “%f”, &x );//Capturar el valor de una variable 6 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad II “Modularidad" 2.2 El concepto de función, procedimiento y modulo Estructuras de datos (Prof. Edgardo A. Franco) 1 • Funciones y procedimientos • Concepto de función en C • Funciones en C • Funciones y procedimientos en C • Estructura de una función en C • Llamada o invocación a una función • Prototipo o declaración de funciones • Definición de funciones Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • Son elementos que realizan una tarea en particular y retornan un valor a la salida. • Son utilizadas como expresiones primarias y por lo tanto formar parte de expresiones más complejas, es decir, se pueden utilizar para realizar operaciones con el valor que retornan a la salida. Por ejemplo, sumarse, restarse, multiplicarse, dividirse, etc. float valor; valor = 2*pow(x,y)+sqrt(4.23245)+7*sin(2*3.1416); Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Funciones 3 • Son elementos que realizan una tarea en particular pero que no retornan un valor a la salida y pueden recibir o no parámetros a la entrada. • Son utilizadas como expresiones instrucción y se invocan cuando se requiere que el programa realice esa tarea en particular. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Procedimientos printf( “Imprimir una cadena de caracteres” ); scanf( “%f”, &x );//Capturar el valor de una variable 4 • Una función es un miniprograma dentro de un programa más general, en otras palabras, una función es un pequeño fragmento de código “funcional” que realiza una tarea especifica. Desarrollar un programa utilizando funciones ayuda a: • Ahorrar espacio eliminando el código repetido. • Hace más fácil la programación. • Proporcionan un medio para dividir un proyecto grande en pequeños módulos más entendibles y manejables. • Permiten construir nuevos sistemas a partir de otros ya desarrollados. • Facilitan la labor de planeación, desarrollo y documentación de los programas. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Concepto de función en C 5 • Un programa en C puede constar de una o varias definiciones de funciones. • Cada una de estas funciones realiza una tarea en particular. • Las funciones en C no se pueden anidar, es decir, no se puede declarar el cuerpo de una función dentro de otra función. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Funciones en C • En C todas las funciones son externas y globales, es decir, pueden ser invocadas desde cualquier parte del programa, incluso dentro de otra función. 6 • Las funciones en C provienen de las llamadas a subrutinas de Fortran, sin embargo, su uso intensivo se introdujo con los procedimientos y funciones de Algol y Pascal. • Las funciones en C se pueden utilizar para modelar los conceptos de la modularidad como: Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Funciones y procedimientos en C • Funciones (Retornando un valor y recibiendo o no parámetros) • Procedimientos (No retornando ningún valor y recibiendo o no parámetros) 7 • La estructura de una función es: tipo_de_retorno nombreFuncion( listaParámetros ) { /**Cuerpo de la función*/ return expresión; } Donde: • tipo_de_retorno: Es el valor devuelto por la función o la palabra reservada void por si la función no retorna ningún valor. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Estructura de una función en C • nombreFuncion: Es el identificador o nombre de la función. • listaParametros: Es la lista de parámetros que la función recibe como entrada, separados por comas. 8 • Expresión: Es el valor que regresa la función. La sentencia return termina inmediatamente la función en la se ejecuta. tipo_de_retorno nombreFuncion( listaParámetros ) { /**Cuerpo de la función*/ return expresión; } Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez • Una llamada a una función produce la ejecución de las expresiones del cuerpo de la función y un retorno a la unidad de programa invocadora después de que la ejecución de la función haya terminando, normalmente cuando se encuentra una sentencia return. 9 Por convención el nombre de una función debe comenzar con una letra en mayúscula o con un guión bajo ( _ ) y puede estar formado de una longitud n se recomienda una longitud no máxima de 32 caracteres alfanuméricos, mayúsculas, minúsculas y guiones bajos, pero sin espacios intermedios. • Tipo de retorno: Una función siempre devuelve un tipo de valor a la salida, este tipo de retorno puede ser uno de los datos simples de C o un apuntador a cualquier tipo de dato, sin embargo, si una función no devuelve un resultado, se utiliza el tipo void, que se considera como un tipo de dato nulo. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez • Nombre o identificador de una función: 10 • Una función puede tener cualquier numero de sentencias return, en el momento que el programa encuentre una de estas sentencias, devolverá el control a la sentencia invocadora. • Sí no se encuentra ninguna sentencia return la ejecución de la función continuará hasta el final de dicha función, es decir, hasta que se encuentre la llave de cerrado “}”, en ese momento se devolverá el control a la sentencia invocadora. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Una función devuelve un único valor, el valor devuelto (expresión) puede ser cualquier tipo de dato conocido en C (simple o estructurado). Sin embargo, también se puede retornar valores múltiples devolviendo un apuntador a una estructura o un arreglo. 11 En C sólo se permite el paso de parámetros por valor y únicamente de los tipos de datos básicos. No obstante, C utiliza el paso de apuntadores para el paso de parámetros por referencia, es decir, se puede pasar apuntadores a tipos de datos simples, estructuras, arreglos e incluso a funciones. (Se retomará con el tema de apuntadores). El paso de parámetros en una función es opcional, pero si se incluyen, deben estar declarados entre los paréntesis de la declaración de la función y separados por comas, es decir, cada parámetro debe tener una declaración independiente. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez • Parámetros de entrada formales: 12 • Las funciones, para poder ser ejecutadas, han de ser llamadas o invocadas. Cualquier instrucción o expresión puede tener una llamada a función que redirigirá el control del programa a la función invocada. • Normalmente la invocación a una función ser realiza desde la función principal main(), sin embargo, también pueden ser invocadas desde otras funciones, incluso desde ellas mismas “recursividad”. • Una función invocada recibe el control del programa, se ejecuta y cuando termina (cuando se alcanza una sentencia return o la llave de cierre de la función) el control del programa retorna a la función principal o a la función llamadora. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Llamada a una función 13 Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Control del flujo del programa 14 • A la declaración de una función se le llama prototipo. Los prototipos de funciones comúnmente van declaradas en la cabecera del código después de la definición de las macros del preporcesador (directivas #include y #define) pero antes del método main() y con terminación en (;). • El prototipo consta de los siguientes elementos: tipo_retorno nombre_funcion(lista_prototipos_parametros); Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Prototipo o declaración de funciones • tipo_de_retorno: Es el valor devuelto por la función o la palabra reservada void por si la función no retorna ningún valor. • nombreFuncion: Es el identificador o nombre de la función. • lista_prototipos_parametros:Es la lista de parámetros que la función recibe como entrada, separados por comas. Colocar el identificador de los parámetros es opcional, sin embargo se recomienda colocarlos para mejor entendimiento de la función 15 • Cuando se realiza una invocación a una función, el compilador ya conoce cuales son el numero y los tipos de dato que la función debe recibir, confirma que los datos enviados a la función coincidan con los que conoce previamente y si no coinciden se generara un error en tiempo de compilación. • El compilador sólo utiliza la información de los tipos de dato que debe recibir una función. Los identificadores de dichos datos son irrelevantes para tal proceso, sin embargo, se recomienda utilizarlos con propósito de hacer más comprensible la utilidad de la función. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez • El prototipo de la función sirve para que el compilador realice la comprobación de tipos de dato de retorno y envío. 16 • La declaración de un prototipo de función es diferente a la definición de dicha función. • La declaración contiene sólo la cabecera de la función, es decir, su prototipo y se listan sus características. • La definición significa colocar el cuerpo de la función, es decir, definir la estructura del código de la función en alguna parte del programa, pero fuera del método principal main(). • La declaración del prototipo de la función sirve para el compilador pueda validar que número y el tipo de datos de entrada de la función coincidan con los que se utilizan en la llamada o invocación a dicha función. Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez Definición de funciones 17 #include <stdio.h> double calcularCuadrado( double ); Declaración del Prototipo de la función sin identificadores en los tipos de dato int main( void ) { double x = 11.5; double resultado; resultado = calcularCuadrado( x ); printf( "El cuadrado de x es: %8.4lf \n", resultado ); return 0; Definición de la función, } en este momento se double calcularCuadrado( double numero ) colocan los { identificadores en los return numero*numero; tipos de dato } Algoritmia y programación estructurada 2.2 El concepto de función, procedimiento y modulo Autor: M. en C. Edgardo Adrián Franco Martínez • Cuando se define el código de la función, es este momento, si es necesario colocar tanto tipo de datos y sus identificadores ya que se le estará indicando al compilador que utilice dichos identificadores como elementos de procesamiento para que la función realice la tarea especificada. 18 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad II “Modularidad" 2.3 El paso de parámetros y valores de retorno Estructuras de datos (Prof. Edgardo A. Franco) 1 • Parámetros de una función • Paso por valor • Paso por referencia • Ámbito de variables • Variables locales • Variables globales Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • C siempre utiliza el paso de parámetros por valor, para pasar la copia del valor de una variable a una función. Sin embargo, C utiliza el paso de apuntadores para el paso de parámetros por referencia. (Se retomará con el tema de apuntadores). Paso de parámetros por valor. El paso por valor o paso por copia, significa que cuando C compila la función y el código que hace la llamada a la función, la función recibe una copia de los valores de los parámetros, es decir, si se modifica el valor de dichos parámetros dentro de la función, dichos cambios sólo serán validos dentro de la función pero no fuera de ella. Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez Parámetros de una función 3 • En la técnica del paso de parámetros por valor, la modificación de la variable (parámetro recibido) dentro de la función receptora no afecta el valor original del parámetro enviado al momento de la invocación a dicha función. #include <stdio.h> double calcularCuadrado( double ); int main( void ) { Parámetro enviado double x = 11.5; double resultado; resultado = calcularCuadrado( x ); printf( "El cuadrado de %d es: %8.4lf \n", x, resultado ); return 0; Parámetro copia del } parámetro enviado double calcularCuadrado( double x ) { int aux = x; Modificación al valor x++; del parámetro copia return aux*aux; } Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez Parámetros de una función – Paso por valor 4 • Existen dos tipos de ámbito en la variables que puede manejar C, estas son las variables locales y globales. • Variables locales son aquellas que son declaradas dentro del ámbito de una función y su uso se restringe dentro de la misma función, se dice entonces que la variable es local a esa función. • Esto implica que todas las variables que se declaren dentro de una función sólo van a poder ser manipuladas dentro de dicha función y no podrán ser referenciadas desde fuera de la función. Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez Ámbito de variables • Cualquier variable que se defina dentro de las llaves del cuerpo de una función el compilador la interpretará como una variable local a esa función. • Si otra función declara otra variable con el mismo identificador entonces dichas variables serán “tocayas” más no iguales. 5 es aquella que se define fuera del cuerpo de cualquier función, normalmente después de la definición de las directivas del preprocesador (#include y #define). • El ámbito de una variable global son todas las funciones que componen el programa. • Cualquier función puede acceder a dichas variables para leer y modificar su valor. Es decir, se puede hacer referencia a su dirección de memoria en cualquier parte del programa. Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez • Variables globales • No puede haber declaración de variables globales con el mismo identificador. • Las variables globales pueden ser inicializadas en el mismo instante que se declaran. • Puede haber variables globales de cualquier tipo de dato que puede manejar C. 6 • La declaración de las variables globales es la misma que la declaración de una variable local, es decir: #include <stdio.h> Constante también tomada Como una variable global #define PI 3.1416 a partir de su declaración <tipo de dato> <identificador>; <tipo de dato> <identificador> = <valor>; int main( void ){ ... } • Si una función declara una variable local con el mismo identificador que una variable global (tocayas), entonces, el compilador le dará mayor prioridad al uso de la variable local que la global. Algoritmia y programación estructurada 2.3 El paso de parámetros y valores de retorno Autor: M. en C. Edgardo Adrián Franco Martínez Ámbito de variables – variables globales 7 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad II “Modularidad" 2.4 Reutilización de código Estructuras de datos (Prof. Edgardo A. Franco) 1 • Reutilización de código • Tipos de reutilización • Copiar y pegar • Reutilizar código en C • Concepto de Librería en Programación • Biblioteca estándar de C • Creación de bibliotecas para C • Generación de código ejecutable • Generando una librería para C Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • La reutilización de código se refiere al comportamiento y a las técnicas que garantizan que una parte o la totalidad de un programa informático existente se puedan emplear en la construcción de otro programa. De esta forma se aprovecha el trabajo anterior, se economiza tiempo, y se reduce la redundancia. Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Reutilización de código 3 • Reutilización oportunistas • Ocurre cuando al iniciar un proyecto, el programador se da cuenta de que hay componentes existentes que se puede reutilizar. • Reutilización planificada Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Tipos de reutilización • Sucede cuando un equipo planea estratégicamente los diseños de componentes que serán reutilizables en futuros proyectos. 4 • La manera más fácil de reutilizar código es copiarlo total o parcialmente desde el programa antiguo al programa en desarrollo. Pero es trabajoso mantener múltiples copias del mismo código, por lo que en general se elimina la redundancia dejando el código reusable en un único lugar, y llamándolo desde los diferentes programas. Este proceso se conoce como abstracción. • La abstracción puede verse claramente en las bibliotecas de software, en las que se agrupan varias operaciones comunes a cierto dominio para facilitar el desarrollo de programas nuevos. Hay bibliotecas para convertir información entre diferentes formatos conocidos, acceder a dispositivos de almacenamiento externos, proporcionar una interfaz con otros programas, manipular información de manera conocida (como números, fechas, o cadenas de texto). Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Copiar y pegar 5 • Para que el código existente se pueda reutilizar, debe definirse alguna forma de comunicación o interfaz. Esto se puede dar por llamadas a una función o procedimiento. • En lenguaje C como sabemos únicamente podemos modelar los procedimientos con funciones que retornan un dato tipo void, estas funciones deberán estar siempre bien diseñadas para poder reutilizarlas en más programas. Si además las agrupamos según su comportamiento puede formarse nuestras propias librerías de funciones útiles para varios desarrollos distintos. Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Reutilizar código en C 6 • Es un conjunto de subprogramas utilizados para desarrollar software. • Las bibliotecas contienen código y datos, que proporcionan servicios a programas independientes, es decir, pasan a formar parte de estos. Esto permite que el código y los datos se compartan y puedan modificarse de forma modular. Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Concepto de Librería en Programación 7 • Ejecutables y bibliotecas hacen referencias (enlaces) entre sí a través de un proceso conocido como enlace, que por lo general es realizado por un software denominado enlazador. Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez • Algunos programas ejecutables pueden ser a la vez programas independientes y bibliotecas, pero la mayoría de estas no son ejecutables. • Las bibliotecas o librerías, pueden ser clasificadas según el tipo de enlace que se realice para ser parte de un programa final en: • Bibliotecas estáticas • Bibliotecas dinámicas 8 • La biblioteca estándar de C es una recopilación de archivos cabecera y bibliotecas con funciones, estandarizadas por un comité de la Organización Internacional para la Estandarización (ISO), que implementan operaciones comunes, tales como las de entrada y salida o el manejo de cadenas. A diferencia de otros lenguajes como COBOL, Fortran, o PL/1, C no incluye palabras clave para estas tareas, por lo que prácticamente todo programa implementado en C se basa en la biblioteca estándar para funcionar Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Biblioteca estándar de C 9 • Es posible generar biblioteca para C generando nuestros propios archivos cabecera y bibliotecas con funciones. Archivos cabecera • Es un archivo, que el compilador incluye al procesar algún código fuente, este contiene, normalmente, una declaración directa funciones, variables, u otros identificadores. Aquellos programadores que desean declarar identificadores estándares en más de un archivo fuente pueden colocar esos identificadores en un único header file, que se incluirá cuando el código que contiene sea requerido por otros archivos. Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Creación de bibliotecas para C 10 Código fuente Compilador Archivos de Cabecera / Cabeceras independientes Código objeto Enlazador Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Bibliotecas con funciones • Son los códigos fuentes que definen las funciones de los archivos de cabecera y son independientes. Estos pueden ser compilados por separados y tenerse como el código fuente original o códigos objetos capaces de ser enlazados por otros códigos fuentes que hagan uso de estas definiciones y programas. Programa ejecutable Biblioteca / Otros códigos objeto 11 • Como se ve en la etapa de compilación de un lenguaje compilado, se obtiene un código objeto, el cuál contiene sólo la traducción del código fuente. Esto no es suficiente para ejecutar realmente el programa. Es necesario incluir los archivos de biblioteca o módulos compilados de manera independiente. Código fuente Compilador Archivos de Cabecera / Cabeceras independientes Código objeto Biblioteca / Otros códigos objeto Enlazador Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Generación de código ejecutable Programa ejecutable 12 • Generar los siguientes archivos, con los contenidos que se muestran y guardarlos con los nombres dados. #include <stdio.h> #include "mi_libreria.h" int main (void) { int n,res; printf("\nIntroduce un número entero") scanf("%d",n); Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez Generando una librería para C res=mi_funcion01(n); printf("\nEl resultado es: %d",res) return 0; } programa.c 13 int mi_funcion01(int numero); mi_libreria.h #include "mi_libreria.h" int mi_funcion01(int numero) { return numero*CONSTANTE; } Algoritmia y programación estructurada 2.4 Reutilización de código Autor: M. en C. Edgardo Adrián Franco Martínez #define CONSTANTE 100 def_mi_libreria.c • Generar el código objeto de la librería gcc def_mi_libreria.c –c • Compilar el programa gcc programa.c def_mi_libreria.o –o programa 14 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad II “Modularidad" 2.5 Bibliotecas estándar de funciones Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Biblioteca estándar de C • Diseño de la biblioteca estándar de C • El estándar ANSI C • Historia de ANSI C • Archivos de cabeceras de la biblioteca ANSI C • Funciones incorporadas del compilador • Biblioteca estándar de POSIX • The C Library Reference Guide Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • El lenguaje de programación C, antes de normalizarse, no disponía de funcionalidades tales como operaciones de entrada/salida (a diferencia de lenguajes tradicionales como Cobol y Fortran). • Con el tiempo, las comunidades de usuarios de C fueron compartiendo ideas, así como las implementaciones de lo que ahora se denomina las bibliotecas estándar de C para proporcionar esas funcionalidades. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • La biblioteca estándar de C (también conocida como libc) es una recopilación de ficheros cabecera y bibliotecas con rutinas, estandarizadas por un comité de la Organización Internacional para la Estandarización (ISO), que implementan operaciones comunes, tales como las de entrada y salida o el manejo de cadenas. A diferencia de otros lenguajes como COBOL, Fortran, o PL/1, C no incluye palabras clave para estas tareas, por lo que prácticamente todo programa implementado en C se basa en la biblioteca estándar para funcionar. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Biblioteca estándar de C 4 • El nombre y las características de cada función, el prototipo, así como la definición de algunos tipos de datos y macros, se encuentran en un fichero denominado archivo de cabecera (con extensión ".h"), pero la implementación real de las funciones están separadas en un archivo de la biblioteca. La denominación y el ámbito de las cabeceras se han convertido en comunes, pero la organización de las bibliotecas sigue siendo diversa, ya que éstas suelen distribuirse con cada compilador. • Dado que los compiladores de C, a menudo, ofrecen funcionalidades adicionales que no están especificados en el ANSI C, la biblioteca de un compilador no siempre es compatible con el estándar ni con las bibliotecas de otros compiladores. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Diseño de la biblioteca estándar de C 5 • La biblioteca estándar de ANSI C consta de 24 archivos cabecera hasta C99 y 29 en C11 que pueden ser incluidos en un proyecto de programación con una simple directiva. Cada cabecera contiene la declaración de una o más funciones, tipos de datos y macros. • En comparación con otros lenguajes de programación (como por ejemplo Java) la biblioteca estándar es muy pequeña, está proporciona un conjunto básico de funciones matemáticas, de tratamiento de cadenas, conversiones de tipo y entrada/salida por consola o por archivos. • Hasta C99, no se incluyen, ni un conjunto de tipos de datos contenedores básicos (listas, pilas, colas, ...), ni herramientas para crear una interfaz gráfica de usuario (GUI), ni operaciones para trabajar en red. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez El estándar ANSI C 6 • Tanto Unix como C fueron creados en los laboratorios Bell de AT&T a finales de la década de los 60 y principios de los 70. • Fue en los 70 cuando el lenguaje de programación C acrecentó su popularidad. Muchas organizaciones y universidades crearon sus propias versiones del lenguaje para sus propios proyectos. A comienzos de los 80 se evidenciaron los problemas de compatibilidad derivados de la existencia de las múltiples implementaciones del lenguaje. • En 1983 el Instituto Nacional Americano de Estándares ANSI, creo un comité para establecer una especificación estándar del lenguaje conocida como ANSI C. Este trabajo culminó con la creación del llamado estándar C89 en 1989. Una parte del estándar resultante fue un conjunto de bibliotecas de software denominado bibliotecas estándar de ANSI C. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Historia de ANSI C 7 • Las cabeceras <iso646.h>, <wchar.h> y <wctype.h> fueron añadidas con Normativa Addendum 1 (abreviado NA1), y fueron ratificadas por el estándar en 1995. • En 1999 se realizó una revisión del estándar que se denominó C99 a la que se añadieron las cabeceras <complex.h>, <fenv.h>, <inttypes.h>, <stdbool.h>, <stdint.h> y <tgmath.h>. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez • Posteriores versiones del C estándar han añadido algunos nuevos ficheros cabecera a la biblioteca. El soporte de estas nuevas extensiones varía según implementaciones. 8 • En marzo de 2000, ANSI adoptó el estándar ISO/IEC 9899:1999. A este estándar se le conoce como C99. http://www.open‐std.org/jtc1/sc22/wg14/www/docs/n1124.pdf • C11 (antes conocido como C1X) es un nombre informal para ISO/IEC 9899:2011,3 el último estándar publicado para C. El borrador final, N1570,4 fue publicado en abril de 2011. El nuevo estándar superó su última revisión el 10 de octubre de 2011 y fue oficialmente ratificado por la ISO y publicado el 8 de diciembre de 2011. http://www.open‐std.org/jtc1/sc22/wg14/www/docs/n1570.pdf Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez • En 1990, el estándar ANSI C (con algunas modificaciones menores) fue adoptado por la International Organization for Standardization bajo la denominación ISO/IEC 9899:1990. 9 Contiene la macro assert (aserción), utilizada para <assert.h> detectar errores lógicos y otros tipos de fallos en la depuración de un programa. Conjunto de funciones para manipular números <complex.h> complejos (nuevo en C99). Contiene funciones para clasificar caracteres según sus tipos o para convertir entre mayúsculas <ctype.h> y minúsculas independientemente del conjunto de caracteres (típicamente ASCII o alguna de sus extensiones). Para analizar los códigos de error devueltos por <errno.h> las funciones de biblioteca. Para controlar entornos en coma flotante (nuevo <fenv.h> en C99). Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Archivos de cabeceras de la biblioteca ANSI C 10 Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Contiene la definición de constantes que especifican ciertas propiedades de la biblioteca de coma flotante, como la diferencia mínima entre dos <float.h> números en coma flotante (_EPSOLON), el número máximo de dígitos de precisión (_DIG), o el rango de valores que se pueden representar (_MIN, _MAX). Para operaciones de conversión con precisión entre <inttypes.h> tipos enteros (nuevo en C99). Para utilizar los conjuntos de caracteres ISO 646 <iso646.h> (nuevo en NA1). Contiene la definición de constantes que especifican ciertas propiedades de los tipos <limits.h> enteros, como rango de valores que se pueden representar (_MIN, _MAX). Para la función setlocale() y las constantes <locale.h> relacionadas. Se utiliza para seleccionar el entorno local apropiado (configuración regional). 11 Contiene las funciones matemáticas comunes. Declara las macros setjmp y longjmp para <setjmp.h> proporcionar saltos de flujo de control de programa no locales. Para controlar algunas situaciones excepcionales <signal.h> como la división por cero. posibilita el acceso a una cantidad variable de <stdarg.h> argumentos pasados a una función. <stdbool.h> Para el tipo booleano (nuevo en C99). <stdint.h> Para definir varios tipos enteros (nuevo en C99). <stddef.h> Para definir varios tipos de macros de utilidad. Proporciona el núcleo de las capacidades de <stdio.h> entrada/salida del lenguaje C (incluye la venerable función printf). Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez <math.h> 12 Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Para realizar ciertas operaciones como conversión de tipos, generación de números pseudo‐ <stdlib.h> aleatorios, gestión de memoria dinámica, control de procesos, funciones de entorno, de señalización (??), de ordenación y búsqueda. <string.h> Para manipulación de cadenas de caracteres. Contiene funcionalidades matemáticas de tipo <tgmath.h> genérico (type‐generic) (nuevo en C99). Para tratamiento y conversión entre formatos de <time.h> fecha y hora. Para manipular flujos de datos anchos y varias clases de cadenas de caracteres anchos (2 o más <wchar.h> bytes por carácter), necesario para soportar caracteres de diferentes idiomas (nuevo en NA1). <wctype.h> Para clasificar caracteres anchos (nuevo en NA1). 13 • Algunos compiladores (por ejemplo GCC1 ) proporcionan versiones incorporadas de muchas de las funciones de la biblioteca estándar de C; es decir, la implementación de las funciones está escrita dentro del fichero objeto compilado, y el programa llama a la versión incorporada en vez de, a la función del fichero objeto compartido en la biblioteca de C. Esto reduce el sobrecoste de una llamada a función, especialmente si las llamadas a función son remplazadas con variantes inline, y permiten otras formas de optimización (como cuando el compilados sabe las características de control de flujo de las variantes incorporadas), pero puede causar confusión al depurar (por ejemplo, las versiones incorporadas no pueden ser remplazadas por las variantes instrumentadas). Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Funciones incorporadas del compilador 14 • POSIX especifica una serie de rutinas que deben estar disponibles más allá de la propia biblioteca estándar de C. • A menudo éstas se implementan conjuntamente con la biblioteca de C estándar, con distintos niveles de proximidad. Por ejemplo, glibc implementa funciones como fork() dentro de libc.so, pero antes NPTL se fusionó con glibc constituyendo una biblioteca con su propia marca de linkado. • A menudo, esta funcionalidad de POSIX se considera una parte de la biblioteca; la propia biblioteca de C puede ser identificada como la biblioteca ANSI C o ISO C. Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez Biblioteca estándar de POSIX 15 http://www.acm.uiuc.edu/webmonkeys/book/c_guide/index.html Algoritmia y programación estructurada 2.5 Bibliotecas estándar de funciones Autor: M. en C. Edgardo Adrián Franco Martínez The C Library Reference Guide 16 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad III “Control de flujo" 3.1 Sentencias de selección Estructuras de datos (Prof. Edgardo A. Franco) 1 • Estructuras de selección • Selección simple • Selección doble • Selección múltiple • Estructuras de selección en C • • • • • if If else If ‐else if switch‐case operador ? Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • Las estructuras de selección (condicionales) se utilizan para elegir entre diversos cursos de acción. Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras de selección 3 si condición Instrucciones Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de selección simple no Pseudocódigo 4 no condición si Instrucciones2 Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de selección doble Pseudocódigo Instrucciones1 5 • Algoritmia y programación estructurada 1.1 Algoritmo (pseudo–código) Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras de selección múltiple no condición1 si condición2 Instrucciones1 no Pseudocódigo si Instrucciones2 condición3 si no 6 • En C hay tres tipos de estructuras de selección: if (selección simple), if…else (selección doble) y switch (selección múltiple) Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras de selección en C 7 if (expresión) sentencia; Nota: una expresión en C es todo aquello que regresa un valor. Como por ejemplo una condición lógica, operaciones aritméticas, llamadas a funciones, una variable, una constante (numérica, carácter, etc.). if (expresión) { sentencia1; sentencia2; } Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if) 8 if (expresión) sentencia; else sentencia; if (expresión) { sentencia1; sentencia2; } else { sentencia1; sentencia2; } Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if – else) 9 if (expresión) sentencia; else if (expresión) sentencia; … else sentencia; if (expresión) { sentencia1; sentencia2; } else if { sentencia1; sentencia2; } … else { sentencia1; sentencia2; } Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (if – else if) 10 switch(expresión) { case 1: sentencias; break; case 2: sentencias; break; : case n: sentencias; break; default: sentencias_default; break; } Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (switch‐case) 11 (expresión)? sentencia1 : sentencia2; expresión? sentencia1 : sentencia2; Se ejecuta: sentencia1 si expresión = verdadero sentencia2 si expresión = falso. Es un operador ternario y puede utilizarse para asignar variables: Var = (expresión)? sentencia1:sentencia2; Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (operador ?) 12 if (calificacion>=60) { printf ("Alumno Aprobado"); } else { printf ("Alumno Reprobado"); } if (calificacion>=90) { printf ("Alumno de muy buena calificación"); } else if (calificacion>=70&& calificacion<90) { printf ("Alumno regular"); } else if (calificacion>=60&& calificacion<70) { printf ("Alumno"); } else { printf ("No es alumno"); } Algoritmia y programación estructurada 3.1 Sentencias de selección Autor: M. en C. Edgardo Adrián Franco Martínez Selección (ejemplos) 13 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad III “Control de flujo" 3.2 Sentencias iterativas Estructuras de datos (Prof. Edgardo A. Franco) 1 • Estructuras iterativas • Iterativa “mientras” • Iterativa “repetir” • Iterativa “para” • Estructuras iterativas en C • Estructura iterativa “while” en C Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Estructura iterativa “do‐while” en C • Estructura iterativa “for” en C 2 • Estas estructuras permiten repetir una serie de veces la ejecución de unas líneas de código. • Esta iteración se realiza o bien un número determinado de veces o bien hasta que se cumpla una determinada condición de tipo lógico o aritmético. • En C hay 3 tipos de instrucciones de repetición: while, do…while y for. Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras iterativas 3 condición si no Pseudocódigo Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez • Estructura de control Iterativa “mientras” Instrucciones 4 Pseudocódigo Repetir Instrucciones condición si Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Iterativa “repetir” no Mientras ≈ Repetir 5 Pseudocódigo i←x i≤n no si Para Instrucciones i ← i+1 Para → mientras Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez • Estructuras de control Iterativa “para” 6 • La sentencia while permite repetir un bloque de instrucciones. • La sintaxis del ciclo while es: while(condición) { sentencia o bloque; }; verdadero condición sentencias Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez Estructura iterativa “while” en C falso • Si la condición se cumple se ejecutan las sentencias del bloque y se regresa el flujo de control a evaluar nuevamente la condición. El proceso se repite hasta que la condición sea falsa. • El ciclo puede ejecutarse 0 veces si la condición no se cumple. 7 • El ciclo do‐while es similar al ciclo while excepto que la condición se realiza al final del ciclo, esto fuerza a que se ejecute por lo menos una vez. do{ sentencias; }while(condición); Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez Estructura iterativa “do‐while” en C sentencias condición falso verdadero 8 • La sentencia for permite definir fácilmente ciclos controlados por contador. for(expresion1; expresion2; expresion3) { sentencias; } • Esta es equivalente a la siguiente sentencia while: expresion1; while(expresion2) { sentencias; expresion3; } expresion1 = sentencia de iniciación expresion2 = condición de terminación expresion3 = sentencia de incremento Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez Estructura iterativa “for” en C expresion1 verdadero condición falso sentencias expresion3 9 Algoritmia y programación estructurada 3.2 Sentencias iterativas Autor: M. en C. Edgardo Adrián Franco Martínez • El encabezado de un bucle for tiene tres partes separadas por ";". En la primera se inicializan las variable de control y sólo se ejecuta una vez, antes de la primera iteración, la segunda es una expresión que indica la condición lógica que debe cumplirse para que la próxima iteración se ejecute; esta condición se evaluá antes de cada iteración y, cuando deja de satisfacerse, el bucle for termina. La tercera parte del encabezado es la actualización de las variables de control y se ejecuta después de cada iteración. 1 . ; 2 7 for(. . . .5 .;. 4. .) { 3 6 sentencias; } n 10 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad III “Control de flujo" 3.3 Teorema de la programación estructurada Estructuras de datos (Prof. Edgardo A. Franco) 1 • ¿Qué es programación? • ¿Qué es el código fuente? • ¿Qué es un programa computacional? • Lenguaje de programación • Primeras programaciones • Paradigma de programación • Programación estructurada • • • • Paradigma de la programación estructurada Teorema de la programación estructurada Lenguajes de programación estructurada La programación estructurada y el lenguaje C • Estructuras secuenciales • Estructuras selectivas • Estructuras iterativas o repetitivas Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • La programación es el proceso de diseñar, codificar, depurar y mantener el código fuente de programas computacionales. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez ¿Qué es programación? 3 • El código fuente de un programa computacional (o software) es un conjunto de líneas de texto que son las instrucciones que debe seguir la computadora, escritas en un lenguaje de programación para ejecutar dicho programa. • Por tanto, en el código fuente de un programa está descrito por completo su funcionamiento. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez ¿Qué es el código fuente? 4 Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • El proceso de escribir código requiere frecuentemente conocimientos en varias áreas distintas, además del dominio del lenguaje a utilizar, algoritmos especializados y lógica formal. 5 Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • El código fuente es escrito en un lenguaje de programación. El propósito de la programación es crear programas que exhiban un comportamiento deseado. 6 • Un programa computacional es un conjunto de instrucciones que una vez ejecutadas realizarán una o varias tareas en una computadora. • Al conjunto general de programas, se le denomina software, que se refiere al equipamiento lógico o soporte lógico de una computadora digital. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez ¿Qué es un programa computacional? 7 • Un lenguaje de programación es un idioma artificial diseñado para expresar computaciones que pueden ser llevadas a cabo por un equipo computacional. • Un lenguaje de programación se usa para crear programas que controlen el comportamiento físico y lógico de una máquina, esto permite crear soluciones a problemas reales e interacciones humano‐maquina. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Lenguaje de programación 8 • Sintáctica (reglas que gobiernan la combinatoria de los símbolos y la formación de unidades superiores a estos) • Semántica (aspectos del significado, sentido o interpretación del significado de un determinado elemento, símbolo, palabra, expresión o representación formal) Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • Un lenguaje de programación está formado de un conjunto de símbolos y reglas sintácticas y semánticas que definen su estructura y el significado de sus elementos y expresiones. 9 • En los inicios de la programación de computadoras (segunda mitad de la década de 1950), el nacimiento de los primeros lenguajes de alto nivel como Fortran y Cobol apoyaban en la codificación de soluciones a problemas computacionales, pero la gran mayoría de las veces el diseño y la implementación de la solución quedaba determinados según criterios personales y de cada programador. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Primeras programaciones 10 • Un paradigma de programación es una propuesta tecnológica que es adoptada por una comunidad de programadores cuyo núcleo central es incuestionable en cuanto a que unívocamente trata de resolver uno o varios problemas claramente delimitados. • Un paradigma de programación representa un enfoque particular o filosofía para la construcción del software. • Es decir un paradigma de programación establece como programar la solución a un problema de cierta manera en un código fuente bajo un lenguaje de programación. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Paradigma de programación 11 • Es una forma de escribir programas de computadora (paradigma de programación). • Los principios que rigen este paradigma de programación son el uso de únicamente tres estructuras de control: secuencia, selección e iteración Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Programación estructurada 12 • El paradigma del la programación estructurada es un resultado en la teoría de lenguajes de programación. • Establece a grandes rasgos que toda función computable puede ser implementada en un lenguaje de programación que combine subrutinas en únicamente tres formas. Esas tres formas (también llamadas estructuras de control) son: 1. Ejecutar una subrutina y luego otra subrutina (secuencia) 2. Ejecutar una de dos subrutinas, dependiendo del valor de una variable booleana (selección) 3. Ejecutar una subrutina mientras una variable booleana sea 'verdadera' (iteración, ciclo o bucle) • Los científicos de la computación usualmente acreditan el teorema a un artículo de 1966 escrito por Corrado Böhm y Giuseppe Jacopini. Sin embargo, David Harel rastreó sus orígenes hasta la descripción de 1946 de la arquitectura de von Neumann y el teorema de la forma normal de Kleene. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Paradigma de la programación estructurada 13 • En 1966 los matemáticos Corrado Böhm y Giuseppe Jacopini demostraron que: "Un programa propio puede ser escrito utilizando solamente 3 tipos de estructuras de control (Secuenciales, selectivas e iterativas)". • A su vez un programa propio: • Posee un solo punto de entrada y uno de salida o fin. • Existen caminos desde la entrada hasta la salida que se pueden seguir y que pasan por todas partes del programa. • Todas las instrucciones son ejecutables (sin código muerto) y no existen lazos o bucles infinitos (sin fin). Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Teorema de la programación estructurada 14 • Un lenguaje de programación estructurada es aquel que establece una sintaxis y semántica propia para expresar computaciones, y se basa en el teorema de la "programación estructurada", ofreciendo instrucciones para expresar las tres estructuras de control del teorema. SECUENCIA Indica que las instrucciones de un programa se ejecutan una después de la otra, en el mismo orden en el cual aparecen en el programa. Se representa gráficamente como una caja después de otra, ambas con una sola entrada y una única salida SELECCIÓN También conocida como la estructura SI‐CIERTO‐FALSO, plantea la selección entre dos alternativas con base en el resultado de la evaluación de una condición o predicado; equivale a la instrucción IF de todos los lenguajes de programación. ITERACIÓN También llamada la estructura HACER‐MIENTRAS‐QUE, corresponde a la ejecución repetida de una instrucción mientras que se cumple una determinada condición. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Lenguajes de programación estructurada 15 • C es un lenguaje de programación que permite programar de manera estructurada ya que establece una sintaxis y semántica propia para expresar computaciones, ofreciendo sentencias de control para describir secuencias, selecciones e iteraciones. SECUENCIA SELECCIÓN if ..else switch ITERACIÓN while do...while for Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez La programación estructurada y el lenguaje C 16 • Son las sentencias (asignaciones e invocaciones a funciones) escritas en el código fuente, cada una de estas será ejecutada de manera secuencial (en orden de aparición) una vez compilado el fuente. #include<stdio.h> int main(void) { int byte=0xFF; printf("\nEl valor de byte es: %4X H",byte); byte&=0x00; printf("\nEl valor de byte es: %4X H",byte); Instrucción1 Instrucción2 Instrucción3 Instrucción4 byte|=0xFF; printf("\nEl valor de byte es: %4X H",byte); byte>>=1; printf("\nEl valor de byte es: %4X H",byte); byte<<=2; printf("\nEl valor de byte es: %4X H",byte); return 0; Instrucciónn Diagrama de flujo Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras secuenciales } Pseudocódigo Código en C 17 • Las estructuras selectivas se utilizan para tomar decisiones con bases en la evaluación de una condición. Selectiva simple si condición if(condición) { Instrucciones; }; no Instrucciones Diagrama de flujo Pseudocódigo Código en C Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras selectivas (if) 18 no condición if(condición) { Instrucciones1; } else { Instrucciones2; }; si Instrucciones2 Instrucciones1 Diagrama de flujo Pseudocódigo Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Selectiva doble Código en C 19 if(condición1) { Instrucciones1; } else if (condición2) { Instrucciones2; } else if (condición3) { Instrucciones3; } … else { Instruccionesn; }; no condición1 si no condición2 si Instrucciones1 In no Instrucciones2 In condición3 si Diagrama de flujo Pseudocódigo Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Selectiva múltiple Código en C 20 if(expresión1) { sentencias1; } else if(expresión2) { sentencias2; } else if(expresión3) { sentencias3; } else { sentencias4; } *Las preposiciones else if (sino si) y else (sino) pueden omitirse. Si la expresión1 se evaluá y si esta es verdadera (diferente de 0) entonces se lleva a cabo el código inmediato entre llaves. Sino si (else if) la expresión2 se evaluá y si esta es verdadera (diferente de 0) entonces se lleva a cabo el código inmediato entre llaves. Sino si (else if) la expresión3 se evaluá y si esta es verdadera (diferente de 0) entonces se lleva a cabo el código inmediato entre llaves. … Sino (else) si ninguna condición ha sido verdadera entonces se lleva a cabo el código inmediato entre llaves. Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • La preposición de control de flujo if se utiliza para expresar decisiones, formalmente la sintaxis es: 21 #include<stdio.h> int main(void) { float a,b; printf("\nIntroduce dos números reales separados por una coma: "); scanf("%f,%f",&a,&b); if(a<0&&b<0) { printf("\nAmbos numeros son negativos"); } else if(a>0&&b>0) { printf("\nLos dos numeros son positivo"); } else if(a>0||b>0) { printf("\nUno de los dos numeros es positivo"); } else if(a==0&&b==0) { printf("\nAmbos numeros son igual a cero"); } else { printf("\n..."); } return 0; } Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo (if‐else) 22 • Una estructura selectiva del lenguaje c, que facilita implementar algunas decisiones múltiples cuando se presentan todas con base en la evaluación de una expresión es switch‐case. switch(expresión) { case exp-constante1: <acción break; case exp-constante2: <acción break; ... case exp-constanteN: <acción break; default: <acción } 1>; 1>; Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Estructura selectiva (switch) N>; M>; *El uso de switch es valido si se utiliza apropiadamente bajo la teoría de la programación estructurada, ya que incluye una sentencia de salto que no debería de ser utilizada indiscriminadamente (break) 23 #include<stdio.h> int main(void) { short opcion; printf("\nOpción 1"); printf("\nOpción 2"); printf("\nOpción 3"); printf("\nOpción 4"); printf("\nOpción 5"); printf("\nSelecciona una opción..."); scanf("%d",&opcion); switch(opcion) { case 1: printf("\nOpción 1 seleccionada"); break; case 2: printf("\nOpción 2 seleccionada"); break; case 3: printf("\nOpción 3 seleccionada"); break; case 4: printf("\nOpción 4 seleccionada"); break; case 5: printf("\nOpción 5 seleccionada"); break; default:printf("\nOpción no valida"); } } Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo (switch) 24 • Las estructuras repetitivas se utilizan para realizar varias veces el mismo conjunto de operaciones con base en una condición. Iterativa "mientras" condición si Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras iterativas o repetitivas while(condición) { Instrucciones; }; no instrucciones 25 Diagrama de flujo Pseudocódigo Código en C Iterativa "repetir" instrucciones do { Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez • Con "repetir" se asegura que las instrucciones de dentro del ciclo se ejecutan al menos una vez. Instrucciones; }while(!(condición)); no condición si Diagrama de flujo Pseudocódigo Código en C 26 • La estructura de control while evaluá la expresión antes de comenzar cada iteración, si esta es verdadera (diferente de 0) se realizan las sentencias de dentro de las llaves. • La estructura de control do‐while se utiliza cuando se quiere asegurar que las sentencias de dentro del ciclo se ejecuta al menos una vez puesto que la evaluación de la expresión lógica se hace al final de este. while(expresión) { Sentencias; }; Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Estructura while & do‐while do { Sentencias; } while(expresión); 27 • La estructura for permite definir un bucle controlado por un contador, denominado variable de control o de inducción. i←x for(i=x;i<=n;i++) { instrucciones; } si i≤n no instrucciones i ← i+1 Diagrama de flujo Pseudocódigo Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Iterativa "para" Código en C 28 #include<stdio.h> int main(void) { int i,n; for(i=0,n=10000;i<n;i++,n=n-i) { printf("\t%3d",i); } return 0; Algoritmia y programación estructurada 3.3 Teorema de la programación estructurada Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo (for) } 29 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad III “Control de flujo" 3.4 La importancia de realizar pruebas Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Pruebas del Software • Relación entre error, defecto y fallo • • • • • Objetivo de la prueba Principios de las pruebas Facilidad de Prueba Características de una Prueba El proceso de Prueba Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Ciclo completo de las Pruebas • Enfoque de Diseño de Casos de Prueba • Pruebas de Caja Blanca • Pruebas de Caja Negra • Pruebas Aleatorias 2 ¿Qué es probar software? Algunas definiciones incorrectas: • Probar es demostrar que no hay errores presentes en un programa. • El propósito de probar es mostrar que el programa realiza correctamente las funciones esperadas. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Introducción La definición Correcta • Probar es el proceso ejecución de un programa con el fin de encontrar errores. 3 Otras Definiciones •Verificar. •Validar. •Pruebas. •Caso de Prueba. •Defecto. •Fallo. •Error. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Pruebas del Software 4 Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Relación entre error, defecto y fallo 5 • La prueba es el proceso de ejecución de un programa con la intención de descubrir un error. • Un buen caso de prueba es aquel que tiene una alta probabilidad de mostrar un error no descubierto hasta entonces. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Objetivos de la Prueba. • Una prueba tiene éxito si descubre un error no detectado hasta entonces. 6 • A todas las pruebas se les debería poder hacer un seguimiento hasta los requisitos del cliente. • Las pruebas deberían planificarse mucho antes de que empiecen. • Las pruebas deberían empezar por “lo pequeño” y progresar hacia “lo grande”. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Principios de las pruebas • No son posibles las pruebas exhaustivas. • Para ser más eficaces (pruebas con la más alta probabilidad de encontrar errores), las pruebas deberían ser realizadas por un equipo independiente. 7 • Cada caso de prueba debe definir el resultado de salida esperado. • Al generar casos de prueba, se deben incluir tanto datos de entrada válidos y esperados como no válidos e inesperados. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez • Se debe inspeccionar a conciencia el resultado de cada prueba para, así, poder descubrir posibles síntomas de defectos. • Las pruebas deben centrarse en dos objetivos (es habitual olvidar el segundo) • Probar si el software no hace lo que debe hacer • Probar si el software hace lo que no debe hacer, es decir si provoca efectos secundarios 8 • Se deben evitar los casos desechables. • La experiencia indica que donde hay un defecto hay otros. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez • No deben hacerse planes de prueba suponiendo que, prácticamente, no hay defectos en los programas, y dedicando pocos recursos a las pruebas. • Las pruebas son una tarea creativa como el desarrollo de software. 9 • Operatividad • Observabilidad • Controlabilidad • Capacidad de descomposición • Simplicidad • Estabilidad • Facilidad de comprensión Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Facilidad de Prueba 10 • Debe tener una alta probabilidad de encontrar un error. • No debe ser redundante. • Debe ser la mejor de todas las posibles. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Características de una Prueba • No debe ser ni demasiado sencilla ni demasiado compleja. 11 1. La depuración (localización y corrección de defectos). Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez El proceso de Prueba 2. El análisis de la estadística de errores. 12 Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Ciclo completo de las Pruebas 13 1. Enfoque estructural o de caja blanca 2. Enfoque funcional o de caja negra 3. Enfoque aleatorio Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Enfoque de Diseño de Casos de Prueba 14 • Se denomina cajas blancas a un tipo de pruebas de software que se realiza sobre las funciones internas de un módulo. Las pruebas de caja blanca están dirigidas a las funciones internas. Entre las técnicas usadas se encuentran: • La cobertura de caminos (pruebas que hagan que se recorran todos los posibles caminos de ejecución). Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Pruebas de Caja Blanca • Pruebas sobre las expresiones lógico‐aritméticas. • Pruebas de camino de datos (definición‐uso de variables). • Comprobación de bucles (se verifican los bucles para 0,1 y n iteraciones, y luego para las iteraciones máximas, máximas menos uno y más uno). 15 • Se centra en las funciones, entradas y salidas. Intenta encontrar errores de las siguientes categorías: • Funciones Incorrecta o ausente. • Errores de Interfaz. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Pruebas de Caja Negra. • Errores en estructuras de datos o acceso a base de datos externas. • Errores de rendimiento. 16 • Errores de inicialización y de terminación. • En las pruebas aleatorias simulamos la entrada habitual del programa creando datos de entrada en la secuencia y con la frecuencia con las que podrían aparecer en la práctica (de manera repetitiva). Para ello habitualmente se utilizan generadores automáticos de casos de prueba. • Consiste en utilizar modelos (en muchas ocasiones estadísticos) que representen las posibles entradas al programa para crear a partir de ellos los casos de prueba • Si el proceso de generación se ha realizado correctamente, se crearán eventualmente todas las posibles entradas del programa en todas las posibles combinaciones y permutaciones. • Baja probabilidad de encontrar errores. Algoritmia y programación estructurada 3.4 La importancia de realizar pruebas Autor: M. en C. Edgardo Adrián Franco Martínez Pruebas Aleatorias 17 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 4.1 Arreglo unidimensional Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Arreglos unidimensionales • Lectura‐escritura de elementos en arreglos unidimensionales • Inicialización de un arreglo • Tamaño de un arreglo Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Función Sizeof • Cadenas en C • Manejo de cadenas en C <string.h> • Prueba y manejo de caracteres en C <ctype.h.h> 2 • Un arreglo estático es una colección finita y constante (que no cambia su tamaño) de elementos del mismo tipo. • Un arreglo también es conocido como vector, matriz o array. • Se pueden crear arreglos de cualquier tipo de dato en C, es decir, tipos de dato simple, estructurado, archivos e incluso de apuntadores. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • Se conocen dos tipos de arreglos: los unidimensionales y los multidimensionales. Y al igual que otra variable primero se debe declarar antes de utilizarse. • Sintaxis para declarar un arreglo unidimensional: <tipo_de_dato> identificador[tam_arreglo]; • Cuando se declara un arreglo unidimensional o multidimensional, se debe indicar el tamaño de dicho arreglo y este permanecerá constante durante el ciclo de vida del programa o de la función, es decir, no podrá cambiar su tamaño de manera dinámica. (Arreglos estáticos) Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Arreglos unidimensionales 4 int arreglo[ 10 ]; • Esta declaración hace que el compilador le indique al sistema operativo que reserve espacio suficiente para almacenar 10 valores enteros. • En estos casos, cuando se declara un arreglo el S.O. le asigna a dicho arreglo una porción consecutiva de memoria que es múltiplo del tamaño del tipo de dato con el que se declaro el arreglo. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Por ejemplo: 5 Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • int arreglo[ 10 ]; 6 • Cada ítem del arreglo se le denomina elemento del arreglo. • Todos los elementos que constituyen un arreglo se numeran consecutivamente comenzando en 0 hasta n‐1 donde: Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Lectura‐escritura de elementos en arreglos unidimensionales • 0: es el primer elemento del arreglo, • n‐1: es el ultimo elemento del arreglo y • n: es el tamaño total del arreglo. 7 • Por ejemplo: int arreglo[30]; int dato; dato = arreglo[10]; arreglo[25] = 2344; Tamaño total del arreglo Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • A los valores de 0 a n‐1 se les denomina índices o subíndices del arreglo, es decir, un índice o subíndice nos ubica en una posición determinada dentro del arreglo y nos permite tener acceso directo al elemento de ese índice, para obtener su valor o para modificarlo, Índice o subíndice del arreglo Se obtiene el valor del elemento (10 + 1) Se modifica el valor del elemento (25 + 1) 8 • Al igual que una variable local, un arreglo puede estar previamente inicializado antes de usarlo, caso contrario el arreglo contendrá datos basura. • Existen diferentes formas de inicializar un arreglo: 1. 2. 3. 4. int numeros[6] = { 10,20,30,40,50,60 }; int numeros[] = { 10,20,30 }; char cad[] = {‘h’,‘o’,‘l’,‘a’,‘\0’}; char s[] = “hola"; Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Inicialización de un arreglo • Cada elemento dentro de las llaves corresponde a un elemento que se almacena en una localidad del arreglo. • Un caso especial es el de las comillas dobles ʺcadenasʺ, este tipo de inicialización aplica solamente para arreglos de caracteres y también significa que se está inicializando dicho arreglo. 9 • Inicializar un arreglo de números aleatorios int i; for( i = 0, i < 6, i++ ) { numeros[i] = rand(); } • Inicializar un arreglo de con el abecedario char i; int h = 0; for( i = ‘a’, i <= ‘z’, i++ ) { letras[h] = i; h++; } Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • Ejemplos 10 • Para obtener saber el tamaño de un arreglo, se puede utilizar la función sizeof(), esta función nos devolverá el numero de bytes reservados para el arreglo completo. • Por ejemplo: int arreglo[ 10 ]; int tamanio; tamanio = sizeof( arreglo ); Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Tamaño en bytes de un arreglo 11 • sizeof() también sirve para darnos el tamaño de un tipo de dato en especifico o el tamaño de un elemento dentro del arreglo. • Por ejemplo: int tamanio; double a = 3.1455; float b = 3.084; char c = ‘e’; tamanio = sizeof( a ); tamanio = sizeof( b ); tamanio = sizeof( c ); tamanio = sizeof( tamanio ); tamanio = sizeof( arreglo[1] ); Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Función Sizeof ( ) 12 • A diferencia de otros lenguajes de programación que emplean un tipo denominado cadena string para manipular un conjunto de símbolos, en C, se debe simular mediante un arreglo de caracteres, en donde la terminación de la cadena se debe indicar con nulo con valor 0. char c [4]; char cad[5]; Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Cadenas en C 13 • Por ejemplo, si se quiere declarar un arreglo cadena que guarde una cadena de diez caracteres, se hará como: char cadena[11]; Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • Un nulo se especifica como '\0'. Por lo anterior, cuando se declare un arreglo de caracteres para ser usado como cadena, se debe considerar un carácter adicional a la cadena más larga que se vaya a guardar. 14 Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • Se pueden hacer también inicializaciones de arreglos de caracteres en donde automáticamente C asigna el carácter nulo al final de la cadena, de la siguiente forma: char nombre_arr[ tam ]="cadena"; • Por ejemplo, el siguiente fragmento inicializa cadena con ``hola'': char cadena[5]="hola"; • El código anterior es equivalente a: char cadena[5]={'h','o','l','a','\0'}; 15 operador & en el scanf paras el argumento, ya que el nombre del arreglo es un apuntador estático al arreglo), de igual forma para mostrarlo en la salida estándar. #include <stdio.h> int main(void) { char nombres[15], apellido[30]; printf("Introduce tu nombre(s): "); scanf("%[^\n]",nombres); //Leer caracteres hasta fin de línea printf("Introduce tu apellido: "); scanf("%s",apellido); printf("Usted es %s %s\n",nombres,apellido); //Leer caracteres hasta el primer espacio return 0; } Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • Para asignar la entrada estándar a una cadena se puede usar la función scanf con la opción %s (cadenas sin espacios) %[^\n] (cadenas con espacios hasta el fin de línea) (observar que no se requiere usar el 16 #include <stdio.h> int main(void) { char a[25]; printf("Ingresa tu nombre: "); scanf("%24s",a); // 24 caracteres a tomar printf("Tu nombre es: %s\n",a); return 0; } Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • El %s puede delimitar los caracteres a considerar como máximos a tomar para almacenar en una cadena. %24s indica que 24 es la máxima cantidad de caracteres que esperemos se ingresen (uno menos que el tamaño del arreglo). Si se intenta ingresar más de 24 sencillamente no los almacenará. Esta es una buena costumbre cada vez que se utiliza scanf() para capturar cadenas. 17 #include <stdio.h> int main(void) { char nombre[40], apellidos[40], completo[80]; nombre="José María"; // Asignaciones ilegales apellidos="Morelos y Pavón"; completo="Gral."+ nombre + apellidos; // Operación Ilegal Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • El lenguaje C no maneja cadenas de caracteres, como se hace con enteros o flotantes, por lo que lo siguiente no es válido: return 0; } 18 • string.h es un archivo de la Biblioteca estándar que contiene la definición de macros, constantes, funciones y tipos de utilidad para trabajar con cadenas de caracteres. • Las funciones declaradas en string.h funcionan en cualquier plataforma que soporte ANSI C. Sin embargo, existen algunos problemas de seguridad con estas funciones, como el desbordamiento de arreglos, que hacen que algunos programadores prefieran opciones más seguras frente a la portabilidad que estas funciones ofrecen. Además, las funciones para cadenas de caracteres sólo trabajan con conjuntos de caracteres ASCII o extensiones ASCII compatibles. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Manejo de cadenas en C <string.h> 19 • Además, es importante preservar el carácter de terminación NULL ‘\0’, ya que con éste es como C define y maneja las longitudes de las cadenas. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • Para poder utilizar las funciones del manejo de cadenas, es necesario incluir la biblioteca: #include <string.h> • Todas las funciones de la biblioteca estándar para el manejo de cadenas de C lo requieren para una operación satisfactoria. 20 • Las funciones de uso más común de dicho archivo de cabecera son: Nombre de la función Descripción strcat() char* strcat (char* destino, const char* fuente) Añade la cadena fuente al final de la destino. Devuelve la cadena destino. strlen() Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Funciones para manipulación de arreglos de caracteres (Manipulación de cadenas) size_t strlen( const char* s ) Devuelve la longitud de la cadena s strncpy() char* strncpy( char* dest, const char* fuente, size_t n) Copia n caracteres de la cadena fuente a la cadena destino strcpy() char* strcpy( char* dest, const char* fuente) Copia la cadena de caracteres de la cadena fuente a la cadena destino 21 Descripción strncat() char* strncat( char* s1, const char* s2, size_t n) Añade los primeros n caracteres de S2 a S1. Devuelve s1 si n>=strlen(s2), entonces strncat tiene el mismo efecto que strcat. strchr() char* strchr( const char* s1, int ch) Devuelve un apuntador a la primera ocurrencia de ch en s1, devuelve NULL si ch no se encuentra en s1. strcmp() int strcmp( const char* s1, const char* s2) Compara alfabeticamente la cadena s1 con s2 y devuelve un dato de: cero si s1 == s2 menor que cero si s1 < s2 mayor que cero si s1 > s2 strcspn() size_t strcspn( const char* s1, const char* s2) Devuelve la longitud de la subcadena más larga de s1 que comienza con el carácter s1[0] y no contiene ninguno de los caracteres de la cadena s2. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Nombre de la función 22 *Consultar las funciones de la librería "string.h" de ANSI C • Una biblioteca relacionada #include <ctype.h> la cual contiene muchas funciones útiles para convertir y probar caracteres individuales. • Las funciones más comunes para revisar caracteres tienen los siguientes prototipos: • • • • • • int isalnum(int c): Verdad si c es alfanumérico. int isalpha(int c): Verdad si c es una letra. int isascii(int c): Verdad si c es ASCII. int iscntrl(int c): Verdad si c es un caracter de control. int isdigit(int c): Verdad si c es un dígito decimal. int isgraph(int c): Verdad si c es un caracter imprimible, exceptuando el espacio en blanco. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez Prueba y manejo de caracteres en C <ctype.h> 23 • Las funciones para conversión de caracteres son: • int toascii(int c): Convierte c a ASCII o un unsigned char de 7 bits, borrando los bits altos. • int tolower(int c): Convierte la letra c a minúsculas, si es posible. • int toupper(int c): Convierte la letra c a mayúsculas, si es posible. Algoritmia y programación estructurada 4.1 Arreglo unidimensional Autor: M. en C. Edgardo Adrián Franco Martínez • int islower(int c): Verdad si c es una letra minúscula. • int isprint(int c): Verdad si c es un caracter imprimible, incluyendo el espacio en blanco. • int ispunct(int c): Verdad si c es un signo de puntuación. • int isspace(int c): Verdad si c es un espacio • int isupper(int c): Verdad si c es una letra mayúscula. • int isxdigit(int c): Verdad si c es un dígito hexadecimal. 24 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 4.2 Arreglos de más dimensiones Estructuras de datos (Prof. Edgardo A. Franco) 1 • Arreglos multidimensionales • Inicialización de arreglos multidimensionales • Lectura‐escritura de elementos de arreglos multidimensionales Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • Los arreglos multidimensionales son los que tienen más de una dimensión, los más usuales son los de dos dimensiones que también son conocidos como tablas o matrices. Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Arreglos multidimensionales 3 Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez • Una arreglo de dos dimensiones tienen 2 índices que nos ayudan a ubicar un elemento dentro del arreglo. 4 <tipo_dato> identificador [tam_filas][tam_columnas]; • Por ejemplo: int datos[3][3]; Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez La sintaxis para la declaración de un arreglo de dos dimensiones seria: • Esta línea de código declara un arreglo en dos dimensiones de 3 X 3 elementos, es decir, este arreglo contendrá en su interior 9 elementos de tipo entero. 5 • Para acceder a alguno de sus elementos se utilizan los dos índices, es decir: 0 datos[0][2] = 12; datos[2][0] = 0; datos[2][2] = 30; Los arreglos van de 0 hasta n‐1, datos es un arreglo de 3 X 3 entonces datos[2][2] hace referencia al ultimo elemento del arreglo 0 1 2 12 1 2 0 30 • Un arreglo en dos dimensiones en realidad es un arreglo de arreglos unidimensionales, es decir, cada elemento del un arreglo no es un valor entero, sino que cada elemento es un arreglo. Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Acceso arreglos multidimensionales 6 int datos[3][3]; Es un arreglo que contiene 3 arreglos de tres elementos cada uno. datos[0] datos[1] datos[2] datos[2][0] Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez • Es decir: datos[2][2] datos[2][1] 7 • Existen varia formas de inicializar un arreglo de dos dimensiones: a) b) c) int datos[3][3] = { 1,2,3,4,5,6,7,8,9}; int datos[3][3] = { {1,2,3},{4,5,6},{7,8,9}}; int datos[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}}; d) o finalmente con un ciclo anidado: for ( i = 0; i < 3; i++){ for( j = 0; j < 3; j++){ datos[i][j] = rand()%30; } } Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Inicialización de arreglos multidimensionales //i manipulara las filas //j las columnas //Se delimita los valores //entre 0 y 30 Todas estas inicializaciones tienen el mismo efecto. 8 • Para escribir o leer un elemento de un arreglo bidimensional siempre se va a requerir utilizar los dos índices con los cuales se declaro el arreglo. • Para escribir en uno de ellos, obteniendo el valor desde consola sería: int datos[3][3]; printf( "Escribe un dato entero: \n" ); scanf( "%d", &datos[1][2] ); printf( El dato capturado fue: %d , &datos[1][2] ); Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Lectura‐escritura de elementos de arreglos multidimensionales 9 • Para mandar por referencia un arreglo a una función se debe entender que el nombre del arreglo, es decir, el identificador que se le coloco al arreglo es un apuntador, por lo tanto para mandar un arreglo a una función se hace de la siguiente forma: int arregloInt[10]; funcion( arregloInt ); . . . int funcion( int *ptr ){ ptr[0] = 123; ptr[1] = 7; } Se manda el nombre arregloInt que es un apuntador que contiene la dirección del primer elemento dentro del arreglo. La referencia del arregloInt se debe recibir con una variable apuntador del mismo tipo que fue declarado el arreglo. Hacen ya referencia directamente a los elementos de arregloInt Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Mandar por referencia a una función un arreglo unidimensional o de dos dimensiones 10 • Para un arreglo de dos dimensiones sucede lo mismo, solo hay que tomar en cuenta que el nombre de arreglo multidimensional es un apuntador a apuntadores, es decir, el apuntador a apuntadores quedara definido dependiendo de la dimensión del arreglo, así para un arreglo de dos dimensiones: int arreglo2D[5][10]; funcion(arreglo2D); . . . Algoritmia y programación estructurada 4.2 Arreglos de más dimensiones Autor: M. en C. Edgardo Adrián Franco Martínez Mandar por referencia a una función un arreglo unidimensional o de dos dimensiones Se recibe con un apuntador a cadena ya que se trata de un arreglo de 2D y su nombre seria un apuntador a una cadena int funcion2( int (*ptr)[10] ){ ptr[5][8] = 1; Hacen ya referencia ptr[9][6] = 7542; directamente a los } elementos de arreglo2D 11 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 4.3 Diferencia entre acceso de memoria dinámica y estática Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Dirección de memoria • Definición de apuntador • Declaración de un apuntador • Inicialización de un apuntador • Indirección de un apuntador • • • • • • Operadores para utilizar apuntadores Apuntadores NULL y void Apuntadores a apuntadores Aritmética de apuntadores Paso por referencia en funciones Memoria dinámica • Asignación dinámica de memoria Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Función malloc() • Uso de malloc() para generar un arreglo bidimensional • Uso de free() para liberar la memoria asignada dinámicamente • Función calloc() • Función realloc() 2 • Los apuntadores o punteros son otros tipos de dato que se utilizan en lenguaje de programación C. • Su utilidad radica en que permiten a un programa ser más potente, dinámico y flexible. • Además, su uso le da al lenguaje C su potencia y la popularidad que ha adquirido, debido a que permiten el acceso a memoria de manera más eficiente, sin embargo, una mala referencia a dicha memoria provocará en el programa una salida inesperada. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • Una variable apuntador o puntero, es una variable que contiene direcciones de otras variables, es decir, almacenan la dirección de memoria donde se encuentran los datos asociados a dichas variables. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Trabajar con apuntadores implica la no manipulación de variables en sí, sino manejar direcciones de memoria en la cuales residen los datos. 4 • Cuando una variable se declara, se le asocian tres atributos fundamentales a dichas variables: su identificador, su tipo de dato y su dirección de memoria. por ejemplo: int n; 0x4fffd34 n 1234 int identificador Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Dirección de memoria dirección de memoria valor de la variable tipo de dato 5 • Cuando se declara una variable en C, el compilador establece un área de memoria para almacenar el contenido de la variable, cuando se hacer referencia a dicha variable, el compilador accede automáticamente a la dirección de memoria donde se almacena el contenido la variable para poder utilizarla. • Cuando se declara una variable de tipo apuntador, el compilador también le asigna una dirección de memoria Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Definición de apuntador 6 int variable = 30; int *ptr = &variable; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Cuando se declara una variable de tipo apuntador, el compilador también le asigna una dirección de memoria, sin embargo, en esa localidad de memoria no se almacena un dato, sino la dirección de una variable del mismo tipo que se declaro el apuntador, es decir: 7 1. Un apuntador es una variable como cualquier otra; 2. Una variable apuntador contiene una dirección que apunta a otra posición de memoria; 3. En esa posición de memoria se almacenan los datos a los que apunta el apuntador; 4. Un apuntador apunta a una variable que se encuentra almacenada en alguna parte de la memoria física. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Los apuntadores en C se rigen por la siguientes reglas básicas: 8 • Al igual que todas la variables, los apuntadores deben de ser declarados antes de ser utilizados, la forma de declarar un apuntador es el siguiente: <tipo_de_dato_apuntado> * <identificador_apuntador> = & <variable_a_apuntar>; donde: • <tipo_de_dato_apuntado>: Es el tipo de dato al cual va a apuntar el apuntador; • *: Es el elemento que dice que la variable va a ser un apuntador; • <identificador_apuntador>: Es el nombre del apuntador; • &: Es el elemento para obtener la dirección de la variable apuntada; • <variable_a_apuntar>: Identificador de la variable a apuntar. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Declaración de un apuntador 9 • Como sucede con las variables locales, C no inicializa un apuntador cuando se declara y es preciso inicializarlo antes de su uso ya que de lo contrario no se estará haciendo referencia a ninguna localidad de memoria, provocando un error en tiempo de compilación. • Para asignar la dirección de memoria a un apuntador se utiliza el operador de referencia de dirección &, por ejemplo: int *ptr = &x; A este tipo de inicialización también se le llama inicialización estática ya que la dirección de memoria es fija y no puede desaparecer, es decir, la memoria para la variable siempre estará reservada hasta que termine el programa. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Inicialización de un apuntador 10 • Para asignar un nuevo valor o recuperar dicho valor que se encuentra almacenado en localidad de memoria a la que apunta el apuntador se utiliza el operador de indirección *. por ejemplo: int variable2; int variable = 30; int *ptr = &variable; *ptr = 45; variable2 = *ptr; Se inicializa el apuntador ptr Se cambia el valor de la localidad de memoria Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Existe un segundo método para inicializar un apuntador y es mediante la asignación dinámica de memoria, para realizar este proceso se utilizan funciones de asignación de memoria como malloc(), calloc(), realloc() y free(). Se retomarán cuando se vea el tema de manejo de memoria dinámica. Se obtiene el valor de la localidad de memoria a la que apunta ptr 11 int n=1234; int * ap = &n; tipo de dato identificador valor de la variable Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Los apuntadores se enlazan a tipos de datos específicos y el compilador también verifica que las variables que se asignan al apuntador son del tipo correcto, ya que de otra forma se estará generando un error en tiempo de ejecución, es decir, C requiere que las variables apuntador direccionen realmente variables del mismo tipo de dato ligado en s declaración. dirección de memoria int n 1234 0x4fffd34 Int * ap 0x4fffd34 0x4fffd38 12 Otro ejemplo: int edad; int *ptr_edad; ptr_edad = &edad; *ptr_edad = 50; printf("%d", edad); printf("%d", *ptr_edad); Ejemplo: Otra forma de inicializar ptr, nótese que en esta línea ya no es necesario utilizar el * ya que si se utiliza sería un error. Se utiliza el * sólo en la declaración del apuntador #include <stdio.h> char c; //variable global int main( void ){ char *ptr_char; ptr_char = &c; //apuntar a la variable global for( c = 'A'; c <= 'Z'; c++ ){ printf( "%c",*ptr_char ); } return 0; } Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Indirección de un apuntador 13 Operador Propósito & Operador de dirección: obtiene la dirección de la variable * Operador de indirección: permite modificar u obtener el contenido del dato que se encuentra en la localidad de memoria que apunta el apuntador. * Nota: En una declaración define la variable como apuntador P.e. int * apuntador; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Operadores para utilizar apuntadores 14 • Cuando se declara un apuntador, el compilador no lo inicializa, es decir, tendrá un valor aleatorio, esto condiciona a que si se le asigna la dirección de una variable, el compilador no sepa a que tipo de dato se quiera apuntar. • Si se requiere, existen dos tipos de apuntadores especiales: los apuntadores void y NULL (nulo). Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Apuntadores NULL y void 15 • Un apuntador nulo no apunta a ninguna localidad de memoria o dato valido, este es muy útil cuando se requiere indicar al programa que valide cuando el apuntador no esta apuntando a nada (dato no valido). Es decir, es muy útil para propósitos de comparación en una estructura condicional o en una iterativa, por ejemplo: if( ptr == NULL ) { . . . } while( ptr != NULL ) { . . . } NULL es una macro de tipo: #define NULL 0 que se encuentra definida en las bibliotecas stdef.h, stdio.h, stdlib.h y string.h Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Apuntador NULL 16 int *ptr = (int *) 0; El casting (int *) no es necesario ya que existe una conversión estándar de 0 a una variable apuntador. • Nunca se utiliza un apuntador para referenciar un valor, solo se utiliza para saber si el apuntador se ha inicializado correctamente o para saber cuando el apuntador a dejado de apuntar a un dato valido, es decir, en un test de comparación. char *ptr; ptr = malloc(121*sozeof(char)); if( ptr == NULL ) printf("Error de asignacion de memoria…"); Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Otra forma de declarar un apuntador nulo es: 17 • Los apuntadores void son apuntadores que apuntan a cualquier tipo de dato, es decir, no se inicializa con un tipo de dato especifico, también son llamados apuntadores genéricos. La forma de declarar un apuntador void es: void *ptr; • Un apuntador void permite a una función especificar un parámetro de entrada para recibir cualquier tipo de apuntador sin que se produzca un error de tipos. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Apuntador void 18 int main( void ) { char *ptr_char; float *pf; int *pd; int variable1 = 10; float variable2 = 343.3543; ptr_char = &c; pd = &variable1; pf = &variable2; funcion( pd ); printf( "\n%d",variable1 ); c = ‘a’; funcion( ptr_char ); printf( "\n%c", c ); funcion( pf ); printf( "\n%f",variable2 ); return 0; } void funcion( void *p ) { int *ptr = p; *ptr+=1; } Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez #include <stdio.h> void funcion( void *p ); char c; //variable global 19 • Un apuntador puede apuntar a otro apuntador, para realizar esta operación se hace preceder a la variable apuntador el numero de asteriscos necesarios para direccionar a los apuntadores, es decir: int valor = 1222; int *ptr_1 = &valor; int **ptr_2 = &ptr_1; int ***ptr_3 = &ptr_2; *ptr_1 = 105; **ptr_2 = 3292; ***ptr_3 = 232; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Apuntadores a apuntadores 20 Actualizan el valor de la variable valor • Un apuntador es una variable que puede modificar el valor al que apunta, es decir, se puede realizar ciertas operaciones aritméticas con ellos. • A un apuntador se le puede sumar o restar un entero n; esto hace que apunte n posiciones hacia adelante o hacia atrás de la dirección actual en la pila de memoria, sin embargo, a un apuntador no se le puede sumar o restar un número de coma flotante, ni multiplicar, ni dividir. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Aritmética de apuntadores 21 ptr = ptr + n; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • A un apuntador se le puede aplicar el operador ++ y ‐‐, esto hace que obtenga la dirección del siguiente o anterior elemento en la memoria de datos, por ejemplo, si se declara un apuntador con un tipo de dato int entonces la siguiente dirección que apunte el apuntador será cuatro localidades después o antes de la referencia actual dependiendo del tipo de operador que se le haya aplicado. 22 Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez #include <stdio.h> int main( void ) { //programa que utiliza un apuntador para modificar el //valor de diferentes variables de tipo entero int a,b,c,d,e,f,g,h,i,j; int n; int *ptr = &a; for( n = 0; n < 10; n++ ) { *ptr = n; ptr‐‐; } printf( "valor de las variables: \n" ); printf( "%d, %d, %d, %d, %d, %d, %d, %d, %d, %d", a, b, c,d, e, f, g, h, i,j); printf( "\n\nvalor de sus direcciones: \n" ); printf( "%d, %d, %d, %d, %d, %d, %d, %d, %d, %d", &a, &b,&c, &d, &e, &f, &g, &h, &i, &j); return 0; } 23 24 Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • El resto de los apuntadores aumentarán y decrementarán la longitud de memoria referente al tipo de dato a los que apuntan. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • En general, cada vez que se incrementa un apuntador, apuntará a la posición de memoria del siguiente elemento de su tipo base. Cada vez que se decrementa apuntará a la posición de memoria del anterior. Cuando se utilizan variables de tipo char, pareciera que la aritmética toma sentido, esto es debido a que un char ocupa un byte de espacio de memoria. 25 • El convenio de paso de parámetros a una función de C sólo es el paso por valor (se pasa la copia del valor de la variable en cuestión), sin embargo, se puede realizar el paso de parámetros a una función por referencia, es decir, pasar la dirección de memoria de una variable a una función para que dicha función pueda trabajar sobre la localidad de memoria que se le asigno a la variable. • En este caso, se dice que se esta pasando un apuntador a la función. • Un apuntador se pasa a una función como cualquier otro argumento, para que esto funcione en la función se debe declarar los parámetros como tipo apuntador. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Paso por referencia en funciones 26 #include <stdio.h> int funcion( int *, int * ); int main( void ){ int x,y; int valorRetorno; x = 20; y = 34; printf( "Valor de x: %d y de y: %d",x,y ); valorRetorno = funcion( &x, &y ); printf( "\nNuevo valor de x: %d y de y: %d",x,y ); printf( "\nEl valor de valorRetorno es: %d", valorRetorno ); return 0; } int funcion( int *x, int *y ){ int variable; *x = *x * 4; *y = *x ‐ *y; variable = *x + *y; return variable; } Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Para pasar una variable por referencia, el operador de dirección & debe de anteceder el identificador de la variable y el parámetro que reciba la dirección de esa variable se deberá declarar como apuntador. 27 • En muchas ocasiones no es posible conocer de antemano la cantidad de variables necesarias para un programa computacional. • Existen aplicaciones que requieren de enormes cantidades de arreglos o datos por momentos breves en el funcionamiento del mismo, por lo que no es viable declarar de antemano a estas como variables, globales o locales de una función. Lo anterior implica emplear funciones de ANSI C que permiten reservar memoria de manera dinámica y ampliarla, reducirla o destruirla en tiempo de ejecución. • El manejo de memoria dinámica es la base del poder del lenguaje C y le da la capacidad de crear programas complejos que emplean grandes cantidades de memoria y los maneja de manera eficiente. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Memoria dinámica 28 • Las variables globales y del programa principal (main) se almacenan en posiciones fijas de la memoria llamada memoria de datos. • Las variables locales se almacenan en el segmento de memoria llamada pila y existen solo cuando se hace una invocación a la función que las declaro. También se pueden declarar variables estáticas locales que también se almacenan en segmentos fijos de memoria o en la memoria de datos , sin embargo, también están disponibles en la función que las declaro. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Todos los programas definen variables que pueden ser definidas como globales y locales. 29 • Sin embargo, no todas las veces es posible conocer el numero de variables con el que va a constar nuestro programa. C ofrece al desarrollador la opción de crear diferentes tipos de variables de forma dinámica, para crear tales variables se utilizan funciones como: malloc(), realloc(), calloc(), y free(). Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Todas estas variables comparten una característica en común, se definen cuando se compila el programa. Esto significa que el compilador reserva espacio en memoria para almacenar los valores para estas variables. • Las regiones de memoria que reservan/liberan estas funciones son almacenadas en el montículo o heap. 30 (Main y código de funciones empleadas) Datos Memoria de proceso activo (Variables globales y declaradas dentro del main) Montículo (Heap) (Variables dinámicas del programa) Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Código Pila Pila (Stack) (Variables y datos de las funciones al estar en ejecución) 31 • Por lo regular cuando se diseña un algoritmo, se debe conocer que elementos de entrada tendrá y cual será la salida, sin embargo, en algunas ocasiones no se sabe de forma exacta el numero de variables que requerirá nuestro algoritmo. • Por ejemplo, suponga que se van a registrar el numero de calificaciones de un conjunto de alumnos, para resolver este problema se podría utilizar una arreglo de calificaciones, sin embargo, si el numero de alumnos crece, nuestro programa ya no seria valido, puesto que no existen los recursos necesarios para almacenar todos los datos validos. Para resolver este problema es necesario recurrir al uso de apuntadores y a la asignación dinámica de memoria. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Asignación dinámica de memoria 32 • Una variable que es generada dinámicamente, se construye (por ejemplo con malloc) y se puede destruir en tiempo de ejecución (uso de free). Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • El espacio de memoria asignado a una variable generada de manera dinámica se crea durante la ejecución del programa (tiempo de ejecución), al contrario de las variables declaradas en código, que el espacio de memoria se les asigna en tiempo de compilación. 33 Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Recordatorio • Las instrucciones de un programa compilado se sitúan en segmentos de memoria denominado segmento de código (memoria de programa). Los datos del programa, tales como variables globales, se almacenan en un área denominado segmento de datos. Las variables locales y el respaldo de los registros de control del programa se sitúan en el segmento llamado pila. Y cuando un programa solicita memoria dinámica para una variable, se le asigna memoria del segmento denominado montículo o heap. 34 • malloc() es la forma más habitual de obtener bloques de memoria dinámica. La función genera o asigna un bloque de memoria que es el numero de bytes pasados como argumento. • malloc() devuelve un apuntador void* al bloque de memoria asignado, por lo tanto, hay que realizar un cast al tipo de apuntador requerido, para hacer buen uso de la memoria o de los datos que se lleguen a almacenar en dicho bloque de memoria. Nota: Todas las funciones de asignación dinámica de memoria se encuentran definidas en la biblioteca stdlib.h Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Función malloc() 35 void* = malloc( size_t bytes); • Donde: • void*: • es el apuntador que almacenará la referencia o apuntara al bloque de memoria generado. bytes: es el tamaño en bytes del bloque de memoria que se va a solicitar. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • El prototipo de la función malloc() sería: 36 //otra forma de generar la memoria //dinámica seria: c = (char *)malloc( sizeof(char) ); entero = (int *)malloc( sizeof(int) ); flotante = (float *)malloc( sizeof(float) ); doble = (double *)malloc( sizeof(double) ); #include <stdio.h> #include <stdlib.h> int main( void ){ char *c; int *entero; float *flotante; double *doble; //Uso de malloc para generar variables sencillas c = (char *)malloc( 1 ); entero = (int *)malloc( 4 ); flotante = (float *)malloc( 4 ); doble = (double *)malloc( 8 ); *c = 'c'; *entero = 2378; *flotante = 128.89172378; *doble = 18947282.48263; printf( "valores: caracter %c, entero %d, flotante %f, doble %lf", *c, *entero, *flotante, *doble ); free( c ); free( entero ); free( flotante ); free( doble ); return 0; } *c = 'a'; *entero = 10; *flotante = 3.89172378; *doble = 1.48263; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Por ejemplo: printf( "valores: caracter %c, entero %d, flotante %f, doble %lf \n\n", *c, *entero, *flotante, *doble ); //Importantísimo liberar la memoria //cuando ya no es requerida free( c ); free( entero ); free( flotante ); free( doble ); 37 int *ptr; ptr = (int *)malloc( 10 * sizeof(int) ); • Al llamar a malloc() puede ser que no haya suficiente memoria disponible, entonces, malloc() devolverá NULL en la operación, por lo tanto, siempre es conveniente preguntar después de la operación si se asigno el bloque de memoria. int *ptr; ptr = (int *)malloc( 10 * sizeof(int) ); if( ptr == NULL){ printf( "No hay memoria disponible…\n" ); //no utilizar ptr return; //fin del programa o realizar la acción conveniente } //utilizar ptr Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • La función sizeof se utiliza con mucha frecuencia para referirnos al tamaño de memoria que se va a generar por las funciones de memoria dinámica. Por ejemplo, si se requiere reservar un bloque de memoria para un arreglo de 10 enteros: 38 int tam; int *ptr; printf( "Ingresa el tamaño del arreglo " ); scanf( "%d", &tam; ); ptr = (int *)malloc( tam * sizeof(int) ); Nota importante: Los apuntadores que se utilizan para hacer referencia al bloque de memoria asignado por malloc() son de tipo dinámico y NO es conveniente que dichos apuntadores apunten a otro lugar antes de liberar el bloque de memoria asignado ya que se estará perdiendo la referencia al bloque de memoria y no abra forma de recuperar la referencia ha esta, por lo tanto, la memoria no será liberada y hasta finalizar el programa. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Si no se conoce el tamaño de memoria que se quiere reservar al momento de diseñar un algoritmo, dicho tamaño se puede solicitar al usuario y generar el bloque de memoria en tiempo de ejecución. Un pequeño ejemplo seria el siguiente: 39 Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Un arreglo bidimensional en realidad es un arreglo cuyos elementos son arreglos. Si el nombre de un apuntador unidimensional es un apuntador sencillo, entonces, el nombre de un arreglo bidimensional será un apuntador a apuntadores sencillos. Para asignar memoria a un arreglo multidimensional, se indica cada dimensión del arreglo al igual que se declara un arreglo unidimensional. 40 • Para generar al arreglo bidimensional utilizando memoria dinámica se hace en dos pasos: 1. Se solicita la memoria para crear un arreglo de apuntadores que van a apuntar a cada fila del arreglo. int **arr2d = (int *)malloc( 10 * sizeof(int *) ); 1. Se solicita memoria para almacenar el numero de elementos que va a formar cada fila o arreglo unidimensional. arr2d[i] = (int*)malloc( elemFilas * sizeof( int ) ); Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Uso de malloc() para generar un arreglo bidimensional 41 arr2d[0] arr2d[1] arr2d[2] arr2d[3] arr2d[4] arr2d[5] arr2d[6] Arreglos unidimensionales de tamaño n arr2d[7] arr2d[8] Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez arr2d Arreglo de apuntadores sencillos arr2d[9] Donde cada arr2d[i] es un apuntador sencillo que apunta a un arreglo unidimensional de tamaño n. 42 int main(){ int **arr2d, **aux; int tamFilas, elemFilas,i,j; int tam; do{ system( "cls" ); printf( "Ingresa el numero de filas: " ); scanf( "%d", &tamFilas ); }while( !(tamFilas > 0) ); arr2d = (int**)malloc( tamFilas * sizeof( int* ) ); aux = arr2d; //para asignar el tamaño de cada una de las filas o arreglos //unidimensionales for( i = 0; i < tamFilas; i++ ){ do{ printf( "Ingresa un valor valido de elementos de una fila: " ); scanf( "%d", &elemFilas ); }while( !(elemFilas > 0) ); //asignar valores a cada arreglo arr2D[i] srand( time(NULL) ); for( j=0; j<elemFilas; j++ ){ arr2d[i][j] = rand()%100; } //imprimir los valores for( j=0; j<elemFilas; j++ ){ printf( "%d ", arr2d[i][j] ); } printf( "\n"); } //liberar la memoria for(i=0; i<tamFilas; i++ ){ free( arr2d[i] ); } free( arr2d ); return 0; //dos formas para generar los arreglos unidimensional //de elementos //1.‐ arr2d[i] = (int*)malloc( elemFilas * sizeof( int ) ); Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez #include <stdio.h> #include <stdlib.h> } //2.‐ /* *aux = (int*)malloc( elemFilas * sizeof( int ) ); aux++;*/ 43 • Cuando se termina de utilizar un bloque de memoria previamente asignado por cualquier función de asignación dinámica de memoria, se debe liberar el espacio de memoria y dejarlo disponible para otros procesos, esto se realiza utilizando la función free(). El prototipo la función free es: void free(void *ptr); • Donde: *ptr es el apuntador que hace referencia al bloque de memoria asignado, si ptr es NULL entonces free no hace nada. • Si embargo, si ptr es un apuntador mal referenciado, el uso de free probablemente destruya el mecanismo de gestión de memoria y provocará un fallo en la aplicación. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Uso de free() para liberar la memoria asignada dinámicamente 44 • calloc() es otra función que permite obtener memoria dinámica. Al igual que malloc() devuelve un apuntador void* que hace referencia al bloque de memoria generado o NULL si no existe memoria suficiente para generar el bloque solicitado, por tal motivo, también es necesario realizar un cast a un apuntador valido para manejar los datos que se van a almacenar en el bloque de memoria asignado. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Función calloc() 45 void* calloc( size_t n, size_t t ); • Donde: • n: es el numero de datos que se van a almacenar en la memoria. • t: es el tamaño de cada elemento, es decir, el tamaño del tipo de dato. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • El prototipo de la función calloc() es: 46 • Forma de uso: Donde: puntero: es un apuntador valido que hace referencia al bloque de memoria generado. tipo *: es el cast al un apuntador valido. numElem: es el numero de elementos que se van a almacenar en el bloque de memoria. tamElem: es el tamaño del tipo de dato que se va a almacenar en la memoria. calloc() una cantidad de memoria igual a numElem * tamElem. Es decir, calloc() asigna memoria suficiente para un arreglo que contiene numElem elementos con un tamaño tamElem cada uno. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez puntero = (tipo*) calloc( numElem, tamElem ); Por ejemplo: int *ptr; ptr = (int *)calloc( 10, sizeof(int) ); 47 //otra forma de generar la memoria //dinamica seria: c = (char *)calloc( 1, sizeof(char) ); entero = (int *)calloc( 1, sizeof(int) ); flotante = (float *)calloc( 1, sizeof(float) ); doble = (double *)calloc( 1, sizeof(double) ); #include <stdio.h> #include <stdlib.h> int main( void ){ char *c; int *entero; float *flotante; double *doble; c = (char *)calloc( 1,1 ); entero = (int *)calloc( 1,4 ); flotante = (float *)calloc( 1,4 ); doble = (double *)calloc( 1,8 ); *c = 'c'; *entero = 2378; *flotante = 128.89172378; *doble = 18947282.48263; printf( "valores: caracter %c, entero %d, flotante %f, doble %lf", *c, *entero, *flotante, *doble ); free( c ); free( entero ); free( flotante ); free( doble ); return 0; } *c = 'a'; *entero = 10; *flotante = 3.89172378; *doble = 1.48263; Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Ejemplo: printf( "valores: caracter %c, entero %d, flotante %f, doble %lf \n\n", *c, *entero, *flotante, *doble ); //Importantisimo liberar la memoria //cuando ya no es requerida free( c ); free( entero ); free( flotante ); free( doble ); 48 • realloc() es la tercera función para obtener memoria dinámica. También devuelve un apuntador void* que hace referencia al bloque de memoria por lo tanto necesario realizar un cast a un apuntador valido. • A diferencia de malloc() y calloc(), realloc() cambia el tamaño de un bloque de memoria asignado dinámicamente, es decir, toma como parámetro de entrada un apuntador *ptr a esa memoria y dependiendo de un segundo parámetro incrementará o reducirá el tamaño de dicho bloque de memoria. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez Función realloc() 49 void* realloc(void* ptr, size_t t); • Donde: • ptr: es el apuntador que hace referencia a un bloque de memoria generado dinámicamente. • t: es el nuevo tamaño en bytes para el bloque de memoria referenciado por ptr. t pude ser mayor o menor que el bloque original. • Se devuelve un apuntador debido a que puede que realloc() tenga que desplazar el bloque original para poder modificar su tamaño. Si este es el caso, se copia la información del bloque original (hasta t bytes) en el nuevo bloque. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • El prototipo de la función es: 50 puntero = (tipo*) realloc( ptr, nuevoTam ); Donde: puntero: es un apuntador valido que hace referencia al bloque de memoria generado. tipo *: es el cast al un apuntador valido. ptr: el apuntador que hace referencia a un bloque de memoria generado dinámicamente. nuevoTam: es el nuevo tamaño para el bloque de memoria referenciado por ptr. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Forma de uso: 51 1. En el C99 se especifico que la memoria referenciada por ptr se libera y se crea un nuevo bloque. 2. El nuevo bloque contiene la misma información que el bloque original (hasta la longitud especificada por nuevoTam). Se regresa un apuntador al nuevo bloque de memoria, sin embargo, el compilador puede generar el nuevo bloque a partir de la misma dirección de inicio del bloque anterior, es decir, el nuevo bloque puede contener la misma dirección de inicio que el bloque anterior. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez • Hay que tener en cuanta varias consideraciones al utilizar la función realloc(): 52 4. Si no hay memoria suficiente para asignar nuevoTam bytes, realloc() devuelve un apuntador NULL y el bloque original permanecerá intacto. Algoritmia y programación estructurada 4.3 Diferencia entre acceso de memoria dinámica y estática Autor: M. en C. Edgardo Adrián Franco Martínez 3. Si ptr es NULL, realloc() simplemente genera el bloque de memoria especificado por nuevoTam. Si nuevoTam es cero, se libera la memoria referenciada por ptr y la función devuelve NULL. 53 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 4.4 Tipos estructurados Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Estructuras • Declaración de una estructura • Definición de variables de una estructura • Inicialización de una estructura • Crear una referencia a una estructura desde el método main • Acceso a una estructura • Estructuras anidadas • Sinónimo de un tipo de dato Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • C proporciona cinco diferentes elementos para creación de tipos de datos propios, es decir, tipos de datos que permiten al programador crear aplicaciones más potentes: • Estructuras: es la agrupación de variables del diferente tipo, bajo un mismo nombre. • Unión: permite que la misma parte de memoria sea definida como dos o más tipos de variables diferentes. • Campo de bits: es un tipo especial de estructura o unión que permite el fácil acceso a bits individuales. • Enumeración: es una lista de constantes enteras con nombre. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • El uso de las estructuras o tipos de datos estructurados, permiten al usuario crear nuevos tipos de datos más versátiles y específicos, para crear aplicaciones más potentes y resolver problemas aun más complejos. E.g., diseñar elementos que contengan registros para una base de datos, creación de datos como: pilas, colas, árboles, etc. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras 4 • Un arreglo es un tipo de dato estructurado, la diferencia entre un arreglo y una estructura radica en que: un arreglo está constituido por un determinado numero de elementos, todos del mismo tipo, sin embargo, como ya se menciono, una estructura es homogénea, es decir, puede estar constituida por diferentes tipos de datos (datos simples, arreglos, estructuras, etc). Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • La potencia de las estructuras radica en que están constituidas por múltiples variables, que pueden ser de diferentes tipos de datos e incluso una estructura puede contener a otras estructuras como tipos de dato. 5 • La declaración de una estructura forma una plantilla que puede utilizarse para crear objetos estructuras, es decir, generar múltiples variables que tengan el cuerpo de la estructura ya definida. • A las variables que componen o se encuentran dentro de una estructura se les llama miembros, elementos o campos de la estructura. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • Definición de estructura: Una estructura es una colección de variables que se referencian bajo un único nombre, proporcionando un medio conveniente de mantener junta información relacionada. 6 • Como ya se menciono, un estructura es un tipo de dato definido por el programador y al igual que las demás variables se debe declarar antes de utilizarla. La firma de una estructura es: struct <identificador de la estructura> { <tipo de dato miembro1> <identificador1> <tipo de dato miembro2> <identificador2> . . . <tipo de dato miembron> <identificadorn> }; El fin de la declaración de la estructura debe terminar con punto y coma (;) Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Declaración de una estructura 7 struct persona { char nombre[20]; char domicilio[100]; int edad; char CURP[18]; long int telefono; . . . }; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • Por ejemplo si quisiéramos declarar una estructura que almacene los datos de una persona, en este caso seria: 8 • Hasta el momento se ha declarado el cuerpo o la plantilla de una estructura, para poder utilizarla se debe definir una variable que haga referencia a los elementos de la estructura. Para declarar una variable de la estructura siguen los mismos pasos que cuando se declaran variables de tipos de datos simples, es decir: Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Definición de variables de una estructura struct <identificador de la estructura> <identificador de la variable de la estructura>; 9 struct persona per1, per2, per3; Donde: per1, per2, per3 son diferentes variables que contienen los mismos elementos definidos en la estructura persona. Otro ejemplo: struct libro { char titulo[200]; char autor[100]; char editorial[100]; char ISBN[100]; int numPaginas; . . . }; struct libro book1, book2, book3; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Para definir una o varias variables de la estructura de tipo persona: 10 Se puede inicializar una estructura de dos formas: 1. Al momento de definir la plantilla de la estructura, se especifican los valores iniciales entre llaves, por ejemplo: struct libro { char titulo[200]; char autor[100]; char editorial[100]; char ISBN[100]; int numPaginas; } book1 = { "Manual de referencia en C", "Herbert Schildt", "Mc Graw Hill", "84‐481‐2895‐8", 709 }; 2. Dentro de la sección donde se va a utilizar la estructura, es decir, por asignación. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Inicialización de una estructura 11 Ejemplo 2: struct info_libro { char titulo[200]; char autor[100]; char editorial[100]; int anio; } book1 = {"Maravilla del saber", "Lucas Garcia", "Mc Graw Hill", 1999}; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Otro ejemplos para inicializar una estructura seria: 12 struct corredor { char nombre[200]; int edad; char sexo; char categoria[100]; char club[100]; float tiempoPromedio; }; struct corredor v1 = { "Salvador Hernandez", 29, 'H', "Senior", "Independiente", 0.0 }; También con terminación punto y coma (;) Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Ejemplo 3: 13 #include <stdio.h> struct persona{ char nombre[30]; int edad; float altura; float peso; }; Se define la variable de la estructura persona dentro de main. Para este caso p1 será una variable local a main Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Crear una referencia a una estructura desde el método main int main( void ){ struct persona p1; printf( "El tamanio de la estructura persona es: %d", sizeof(p1) ); return 0; } 14 • Para tener acceso a los elementos de una estructura, bien para modificar o recuperar su valor se utilizan dos operadores: 1. El operador punto (.) 2. Y el operador flecha (‐>) Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Acceso a una estructura 15 Operador punto ( . ) El operador punto es la forma más sencilla de tener acceso a los elementos de una estructura, para utilizarlo basta con definir una variable al tipo de estructura y utilizar esta variable para referirnos a los miembros de la estructura anteponiendo el operador punto. La sintaxis de acceso es: <identificador_variable_a_la_estructura>.<nombreMiembro> = dato; o Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Acceso a una estructura dato = <identificador_variable_a_la_estructura>.<nombreMiembro>; El operador punto proporciona el camino directo al miembro correspondiente y los datos que se almacenan en cada miembro deben ser del mismo tipo con el que se declaro cada miembro. 16 • Refiriéndonos nuevamente a la estructura persona #include <stdio.h> struct persona{ char nombre[30]; int edad; float altura; float peso; }; int main( void ){ Se está teniendo acceso ó haciendo struct persona p1; referencia a los elementos de la strcpy(p1.nombre,"Jacinto Dominguez"); estructura persona a través del p1.edad = 25; operador punto p1.altura = 1.82; p1.peso = 76.3; printf( "El tamanio de la estructura persona es: %d", sizeof(p1) ); return 0; } Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Operador punto ( . ) 17 • El operador flecha se utiliza cuando se están manejando apuntadores a una estructura. • Hay que recordar que un apuntador puede hacer referencia a cualquier tipo de dato y una estructura no es la excepción. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Operador flecha ( ‐> ) • Para definir un apuntador a una estructura, la sintaxis es la siguiente: 18 struct<identificador_de_la_estructura>*<identificador_del_apuntador>; #include <stdio.h> struct estudiante { char nombre[30]; long int matricula; float promedio; short int numMaterias; }; int main( void ){ struct estudiante e1; struct estudiante *ptr_e = &e1; strcpy(ptr_e‐>nombre,"Julian Arreaga"); ptr_e‐>matricula = 2010568912; ptr_e‐>promedio = 9.06; ptr_e‐>numMaterias = 6; return 0; Se declara el apuntador a la estructura estudiante Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Operador flecha ( ‐> ) Se hace referencia a los elementos de la estructura estudiante a través del apuntador ptr_e con el operador flecha } 19 • El uso más general para utilizar apuntadores a estructuras es cuando se requiere pasar por referencia una estructura a una función o cuando se están trabajando listas, colas o generación de estructuras dinámicas, es decir, uso de memoria dinámica. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Operador flecha ( ‐> ) • El operador flecha sirve para tener acceso a los elementos de una estructura a partir de un apuntador. 20 • Otro aspecto muy importante para pasar por referencia una estructura a una función radica en que si una estructura se pasa por valor (por copia) a una función o el tipo de retorno de dicha función es la misma estructura y si esta estructura consta de muchísimos miembros, entonces, copiar todos estos elementos de ida y de regreso en la llamada a la función degradaría mucho la ejecución del programa e incluso a niveles inaceptables, por lo tanto, es más conveniente pasar la referencia a dicha estructura a través de apuntadores, esto conlleva a que la llamada a la función sea muy rápida. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Operador flecha ( ‐> ) 21 • Cuando se utiliza el operador punto, quiere decir que se están creando variables a estructuras de manera estática, es decir, cuando se declaran dichas variables el compilador les asigna memoria como a cualquier otra variable y esta memoria se mantendrá asignada todo el ciclo de vida de nuestra aplicación. • El operador flecha se utilizará mayormente cuando se estén creando estructuras de manera dinámica o cuando se pase por referencia una estructura a una función. Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • La mayor diferencia de utilizar el operador punto (.) y el operador flecha (‐>) para tener acceso a los miembros de una estructura radica en: 22 • Una estructura puede contener variables a otras estructuras llamadas estructuras anidadas. Usar estructuras anidadas nos permite ahorrar tiempo en la escritura de programas que utilizan estructuras con información similar, por ejemplo: struct empleado { int ID; char nombre[30]; char direccion[30]; char ciudad[30]; long int CP; double salario; }; struct cliente { int ID; char nombre[30]; char direccion[30]; char ciudad[30]; long int CP; double credito; }; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Estructuras anidadas 23 struct info_persona { int ID; char nombre[30]; char direccion[30]; char ciudad[30]; long int CP; }; struct empleado { struct info_persona info_empleado; double salario; }; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • Las dos estructuras anteriores contiene información que es muy similar, para ahorrarnos el código repetido, se podría generar una estructura que contenga los datos similares y anidarla dentro de las dos estructuras más generales, es decir: struct cliente { struct info_persona info_cliente; double credito; }; 24 #include <stdio.h> int main( void ){ struct empleado emp; struct cliente cli; //Para introducir los datos del empleado strcpy(emp.info_empleado.nombre,"Julian Arreaga"); strcpy(emp.info_empleado.direccion,"Bugambilias #48"); strcpy(emp.info_empleado.ciudad,"Tlalpan"); emp.info_empleado.CP = 68643; emp.salario = 20345.123; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • Y para tener acceso a cada uno de los elementos de cada estructura sería de la siguiente manera: //Para introducir los datos del cliente strcpy(cli.info_cliente.nombre,"Hernesto Juarez"); strcpy(cli.info_cliente.direccion,"Matamoros S/N"); strcpy(cli.info_cliente.ciudad,"Tlalpan"); cli.info_cliente.CP = 68643; cli.credito = 10000000.000; return 0; } 25 • Existe en C una palabra reservada que nos permite definir sinónimos de un tipo de dato ya definido, esta palabra reservada es typedef. La firma para utilizar typedef es: typedef <identificador_datoDefinido> <nuevoNombre>; Así por ejemplo si quisiéramos dar un nuevo nombre a los datos dobles sería: Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez Sinónimo de un tipo de dato typedef double dobles; y su uso seria: dobles a = 3.13473; dobles b = 0.47293764; dobles c = 947282.43232; 26 typedef char* String; typedef conts char* string = "Adios a todos…"; String nombre = "Luis Joyanes Aguilar"; typedef también se puede utilizar para definir nuevos nombres a una estructura, por ejemplo: struct complejo { float imaginario; float real; }; typedef struct complejo complex; Algoritmia y programación estructurada 4.4 Tipos estructurados Autor: M. en C. Edgardo Adrián Franco Martínez • Otros ejemplos de typedef: //definición de variables de estructuras complejo, ya no es necesario //colocar la palabra struct ya que va implícita en el nombre complex. complex c1, c2, c3; 27 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 5.1 Entrada/Salida Estructuras de datos (Prof. Edgardo A. Franco) 1 • Entrada y salida estándar • Funciones de <stdio.h> • Captura • Scanf • Salida • Modificadores de formato Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Contenido • Secuencias de escape • Re‐direccionar la entrada y salida estándar 2 • En lenguaje C no existen palabras reservadas para realizar entradas y salidas. Para ello, el programador puede hacer uso de las funciones de entrada y salida estándar proporcionadas por la biblioteca estándar de lenguaje C, como son printf y scanf, entre otras que se encuentran declaradas en la cabecera <stdio.h>. • stdio.h "standard input‐output header" (cabecera estándar E/S), es la biblioteca estándar del lenguaje de programación C, el archivo de cabecera que contiene las definiciones de macros, las constantes, las declaraciones de funciones y la definición de tipos usados por varias operaciones estándar de entrada y salida. Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Entrada y salida estándar 3 fclose fopen freopen fdopen remove tmpfileme rewind auto clearerr feof ferror fflush fgetpos fgetc fputsputcgets ftell fseek fsetpos fread fwrite getc getchar gets printf fprintf sprintf snprintf vprintf perror putc putchar fputchar scanf fscanf sscanf vfscanf vscanf vsscanf setbuf setvbuf tmpnam ungetc puts Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Funciones de <stdio.h> 4 • La función scanf() (scan‐format) incluida en stdio.h, representa a una familia de funciones que analizan una entrada de datos con formato y cargan el resultado en los argumentos que se pasan por referencia a dichas funciones: • scanf() lee los datos de entrada en el stdin (flujo de entrada estándar). Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Captura • fscanf() (file‐scanf) lee en un flujo de entrada dado, por lo general un fichero (file) abierto para lectura. • sscanf() (string‐scanf) obtiene la entrada que se va a analizar de una cadena de caracteres dada (string). 5 • Cada uno cuenta con varios argumentos: por un lado, un formato de la secuencia del control (se describe más abajo), por otro, un sistema de argumentos del indicador que señala dónde la entrada convertida debe ser almacenada. • El resultado es indefinido si hay escasos argumentos para dar formato. Si se agota el formato mientras que sigue habiendo las argumentos, los argumentos sobrantes son evaluados pero no procesados de ninguna otra manera. Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez • Todas las funciones anteriores leen caracteres, los interpretan según un formato, y almacenan los resultados en sus argumentos. 6 #include<stdio.h> int main(void) { int entero1; float real1,real2; scanf("%d",&entero1); scanf("%f %f",&real1,&real2); return 0; } Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez • En el ejemplo siguiente se lee un número entero decimal desde el teclado, que se almacena en la variable entero1, posteriormente se leen dos números reales separados por un espacio o salto de línea y se almacenan en las variables real1 y real2. 7 • El primer parámetro de scanf() es la cadena de formato, que indica como debe interpretar el dato leído. El segundo parámetro corresponde a la variable en memoria donde quedará almacenado ese dato, y su tipo debe de ser consistente con lo que se espera como entrada. scanf(" formato de la entrada ", Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez scanf ); variables donde guardar 8 • Existen funciones dentro de stdio.h (getc , getchar y fgetc), las cuales obtienen el valor de un carácter de la entrada estándar. Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez • La función scanf() es útil para capturar por parte de la entrada estándar cualquier tipo de dato. En muchas ocasiones es necesario recibir caracteres del teclado, ya sea para compararlo con su valor real o su valor ASCII. *Investigación del alumno Codificación ASCII #include<stdio.h> int main(void) { char caracter; caracter=getchar(); printf("El caracter introducido es %c y su valor ASCCI es %d decimal %x hexadecimal",caracter,caracter,caracter); return 0; } •. 9 • La función printf() y las funciones derivadas fprintf(), sprintf() y snprintf(); permiten escribir una cadena de caracteres en salida estandar (stdout), su nombre proviene de "print formatted". • La instrucción printf escribe en pantalla • Mensajes de texto • Valores de variables y expresiones • Una mezcla de ambas cosas printf ( “cadena de formato”, arg1, arg2,... argN ); Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Salida #include<stdio.h> int main(void) { int entero1=10; float real1=0.34; printf("El valor del número entero es: %d y del número real es: %f",entero1,real1); return 0; } . 10 #include<stdio.h> int main(void) { char caracter, caracter2; caracter='A'; caracter2=65; putchar(caracter); putchar(caracter2); return 0; } Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez • La función printf() es útil para enviar a la salida estándar cualquier tipo de dato. En muchas ocasiones es necesario mostrar solo un carácter. • Existen dos funciones dentro de stdio.h (putchar y fputchar), las cuales muestran el carácter a la salida estándar. 11 %c Carácter %d Número entero(int) %D Número entero long(o también %ld) %i Número entero(int) %f Punto flotante(float) %e Notación científica con e minúscula %E Notación científica con E mayúscula %g Utiliza %f o %e según sea más corto %G Utiliza %f o %E según sea más corto %o Número octal sin signo %s Cadena de texto %u Entero sin signo %U Entero sin signo long(o también %lu) %x Hexadecimal sin signo con minúsculas %X Hexadecimal sin signo con mayúsculas %p Puntero, dirección de memoria %n Número de caracteres %o Formato entero octal %O Formato entero octal long(o también %lo) %lf Formato double %LF Formato long double Indican el tipo o trato que se le deberá de dar a la variable a la que se hace referencia. Se utilizan dentro de las funciones de entrada y salida; como printf() y scanft(). Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Modificadores de formato 12 • Son un conjunto de caracteres en los textos que son interpretados con algún fin. Secuencia Descripción \n Nueva línea: Coloca el cursor en el principio de la siguiente línea. \t Tabulador horizontal: Mueve el cursor al siguiente tabulador. \v Tabulador vertical: Mueve el cursor al siguiente tabulador. \r Retorno de carro: Coloca el cursor hacia el principio de la línea actual. \b Retroceso: Backspace o retroceso del cursor. \\ Diagonal invertida: Imprime la diagonal invertida, una sola diagonal sería interpretada como un carácter de escape. \" Comillas: Imprime la doble comilla. Sin la diagonal invertida, se interpretaría como un inicio o un fin de una cadena. \a Alerta: Suena la beep del sistema. Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Secuencias de escape 13 #include<stdio.h> int main(void) { printf("\nHola\tmundo\n¿Como estás? \"Bien\""); printf("\aEsto es una\b \\Alerta\\"); printf("\rNo sobrescribir"); return 0; } Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez El siguiente código muestra el uso de algunas secuencias de escape. 14 • La entrada estándar es el lugar desde donde un comando obtiene la información necesaria de entrada. Habitualmente, por omisión, ésta es el teclado. • La salida estándar es el lugar a donde un comando envía el resultado de su ejecución, por omisión, este lugar es la pantalla). • < Acepta la entrada estándar desde un archivo. Algoritmia y programación estructurada 5.1 Entrada/Salida Autor: M. en C. Edgardo Adrián Franco Martínez Re‐direccionar la entrada y salida estándar • > Envía la salida estándar a un archivo. • >> Añade la salida estándar a un archivo. • | Conecta la salida estándar de un comando con la entrada estándar de otro. 15 Departamento de Ciencias e Ingeniería de la Computación Academia de Ciencias de la Computación Autor: M. en C. Edgardo Adrián Franco Martínez Unidad IV “Arreglos y tipos estructurados” 5.2 Bibliotecas de funciones para acceder archivos Estructuras de datos (Prof. Edgardo A. Franco) 1 • Introducción • Tipos de archivos • Manejo de archivos en C • Modo texto • Modo binario • Manejo del desplazamiento sobre el archivo Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Contenido 2 • Los datos que hemos tratado hasta el momento han residido en la memoria principal. Sin embargo, las grandes cantidades de datos se almacenan normalmente en un dispositivo de memoria secundaria. Estas colecciones de datos se conocen como archivos. • Un archivo es un conjunto de bits almacenado en un dispositivo de memoria secundaria, el cuál puede ser almacenado con un conjunto de propiedades y recuperado de la misma manera por el sistema operativo para que un programa tenga acceso a este. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Introducción 3 • Los archivos digitales se llaman así porque son los equivalentes digitales de los archivos en tarjetas, papel o microfichas del entorno de oficina tradicional. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez • Un archivo es identificado por un nombre y la descripción de la carpeta o directorio que lo contiene. 4 • Hay dos tipos de archivos, archivos de texto y archivos binarios. • Un archivo de texto es una secuencia de caracteres organizadas en líneas terminadas por un carácter de nueva línea. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Tipos de archivos • En estos archivos se pueden almacenar, fuentes de programas, texto plano, base de datos simples, etc. • Los archivos de texto se caracterizan por ser planos, es decir, solo contienen caracteres de texto. 5 • El número de bytes escritos (leídos) será el mismo que los encontrados en el dispositivo externo. • E.g. de estos archivos son Fotografías, imágenes, texto con formatos, archivos ejecutables (aplicaciones), etc. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez • Un archivo binario es una secuencia de bytes que tienen una correspondencia uno a uno con un dispositivo externo. Así que no tendrá lugar ninguna traducción de caracteres. 6 • En C, un archivo es un concepto lógico que puede aplicarse a muchas cosas desde archivos de disco hasta terminales o una impresora. • Para trabajar con un archivo se asocia una estructura especial de tipo FILE con un archivo especifico realizando una operación de apertura. • Una vez que el archivo está abierto, la información puede ser intercambiada entre este y el programa. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Manejo de archivos en C 7 • La tabla siguiente da un breve resumen de las funciones que se pueden utilizar. • Observe que la mayoría de las funciones comienzan con la letra “f” (file), esto es un vestigio del estándar C de Unix. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez • Se puede conseguir la entrada y la salida de datos a un archivo a través del uso de la biblioteca de funciones estándar "stdio.h"; C puro no tiene palabras claves que realicen las operaciones de E/S. 8 Función fopen() Abre un archivo fclose() Cierra un archivo fgets() Lee una cadena de un archivo fputs() Escribe una cadena de un archivo fseek() Busca un byte especifico de un archivo fprintf() Escribe una salida con formato en el archivo fscanf() Lee una entrada con un formato en el archivo feof() Devuelve cierto si se llega al final del archivo ferror() Devuelve cierto si se produce un error rewind() Coloca el cursor de posición en el archivo al principio del mismo remove() Borra un archivo fflush() Vacía un archivo fread() Lee un bloque de una “stream” de datos (binario) fwrite() Escribe un bloque de datos a un archivo como “stream” (binario) Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Nombre 9 • Un puntero a un archivo es un puntero a una información que define varias cosas sobre él, incluyendo el nombre, el estado y la posición actual del archivo. • En esencia identifica un archivo especifico y utiliza la secuencia asociada para dirigir el funcionamiento de las funciones de E/S con buffer. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez El puntero a un archivo. • El puntero a un archivo es un tipo especial que opera como hilo común que unifica el sistema de E/S con buffer. 10 • Un puntero a un archivo es una variable de tipo puntero al tipo FILE que se define en "stdio.h". • Un programa necesita utilizar punteros a archivos para leer o escribir en los mismos. Para obtener una variable de este tipo se utiliza una secuencia como esta: Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez …El puntero a un archivo. FILE *F; 11 FILE * fopen (const char nombre_archivo, const char modo); • Donde nombre_archivo es un puntero a una cadena de caracteres que representan un nombre valido del archivo y puede incluir una especificación del directorio. • La cadena a la que apunta modo determina como se abre el archivo. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Apertura de un archivo • La función fopen() abre una secuencia para que pueda ser utilizada y la asocia a un archivo. Su prototipo es: 12 Modo Significado r Abre un archivo de texto para lectura (read) w Abre un archivo de texto para escritura desde el comienzo (write) a Abre un archivo de texto para escritura al final del archivo (append) rb Abre un archivo binario para lectura (read binary) wb Abre un archivo de binario para escritura desde el comienzo (write binary) ab Abre un archivo binario para escritura al final del archivo (append binary) r+ Abre o crea un archivo de texto para lectura / escritura w+ Crea un archivo de texto para lectura / escritura a+ Añade o crea un archivo de texto para lectura / escritura rb+ Abre o crea un archivo binario para lectura / escritura wb+ Crea un archivo binario para lectura / escritura ab+ Añade o crea un archivo binario para lectura / escritura Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Modos de apertura de un archivo 13 • La función fopen() devuelve un puntero a archivo. Un programa nunca debe alterar el valor de ese puntero. • Si se produce un error cuando se esta intentando abrir un archivo, fopen() devuelve un puntero nulo (NULL). • Se puede abrir un archivo bien en modo texto o binario. En la mayoría de las implementaciones, en modo texto, la secuencias de retorno de carro / salto de línea se convierten a caracteres de salto de línea en lectura. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Abrir un archivo ‐ fopen() 14 • En la escritura, ocurre lo contrario: los caracteres de salto de línea se convierten en salto de línea. Estas conversiones no ocurren en archivos binarios. • La macro NULL está definida en "stdio.h". La función fopen() detecta cualquier error al abrir un archivo: como por ejemplo disco lleno o protegido contra escritura antes de comenzar a escribir en él. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez … Abrir un archivo ‐ fopen() • Si se usa fopen() para abrir un archivo para escritura, entonces cualquier archivo existente con el mismo nombre se borrará y se crea uno nuevo. 15 • Si se quiere añadir al final del archivo entonces debe usar el modo a. Si se usa a y no existe el archivo, se devolverá un error. • La apertura de un archivo para las operaciones de lectura requiere que exista el archivo. Si no existe, fopen() devolverá un error. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez … Abrir un archivo ‐ fopen() • "+" abre un archivo para las operaciones de leer / escribir, el sistema operativo no lo borrará si existe; sin embargo, si no existe, el sistema operativo lo creará. 16 • La función fclose() cierra una secuencia que fue abierta mediante una llamada a fopen(). Escribe toda la información que todavía se encuentre en el buffer en el disco y realiza un cierre formal del archivo a nivel del sistema operativo. • Un error en el cierre de una secuencia puede generar todo tipo de problemas, incluyendo la pérdida de datos, destrucción de archivos y posibles errores intermitentes en el programa. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Cierre de un archivo ‐ fclose() 17 • Donde F es el puntero al archivo devuelto por la llamada a fopen(). Si se devuelve un valor cero significa que la operación de cierre ha tenido éxito. • Generalmente, esta función solo falla cuando un disco se ha retirado antes de tiempo o cuando no queda espacio libre en el mismo. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez …Cierre de un archivo. int fclose(FILE *F); 18 • Para introducir u obtener datos en modo texto de un archivo tenemos las siguientes cuatro funciones: • • • • fprintf() fscanf() fgets() fputs() • Estas funciones se comportan exactamente como prinft() y scanf(), gets() y puts() excepto que operan sobre archivo. Sus prototipos son: int fprintf(FILE *F, const char *cadena_de_control, .....); int fscanf(FILE *F, const char *cadena_de_control, .....); char *fputs(char *str, FILE *F); char *fgets(char *str, int long, FILE *F); Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Manejo de archivos en C (Modo texto) 19 • Desgraciadamente esta es la forma más compleja de almacenar registros e información así como recuperarla por parte de aplicaciones profesionales, por ello no es recomendable trabajar solo con el modo texto. Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez • El operar con los archivos en modo texto facilita la comprensión de los archivos por cualquier usuario que logre abrir el archivo con otra aplicación que permita leer el texto claro. • El modo binario permite un almacenamiento mucho más seguro, fiable y fácil de manejar (si se diseña correctamente la aplicación). 20 • Para introducir u obtener datos en modo binario de un archivo tenemos las siguientes funciones: • fread() • fwrite() • Sus prototipos son: Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Manejo de archivos en C (Modo binario) size_t fread ( void * ptr, size_t size, size_t count, FILE * archivo); size_t fwrite(void *ptr, size_t tamano, size_t count, FILE * archivo); 21 • Esta función lee un bloque de una "stream" de datos. Efectúa la lectura de un arreglo de elementos "count", cada uno de los cuales tiene un tamaño definido por "size". Luego los guarda en el bloque de memoria especificado por "ptr". El indicador de posición de la cadena de caracteres avanza hasta leer la totalidad de bytes. Si esto es exitoso la cantidad de bytes leídos es (size*count). Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez fread() size_t fread ( void * ptr, size_t size, size_t count, FILE * archivo); 22 • ptr: Puntero a un bloque de memoria con un tamaño mínimo de (size*count) bytes. • size: Tamaño en bytes de cada elemento (de los que se van a leer). • count : Número de elementos, los cuales tienen un tamaño "size". Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez size_t fread ( void * ptr, size_t size, size_t count, FILE * archivo); • archivo: Puntero a FILE, que especifica el archivo de entrada. 23 • Esta función está pensada para trabajar con registros de longitud constante y forma pareja con fread. • Es capaz de escribir hacia un fichero uno o varios registros de la misma longitud almacenados a partir de una dirección de memoria determinada. El valor de retorno es el número de registros escritos, no el número de bytes. Los parámetros son: un puntero a la zona de memoria de donde se obtendrán los datos a escribir, el tamaño de cada registro, el número de registros a escribir y un puntero FILE del fichero al que se hará la escritura. size_t fwrite(void *ptr, size_t tamano, size_t count, FILE * archivo); Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez fwrite() 24 (Manejo del desplazamiento sobre el archivo) fseek() • Esta función está sitúa el puntero (cursor) de un archivo en una posición deseada, trabaja para modo binario y texto. int fseek(FILE *archivo, long offset, int origen); • archivo es un puntero a la estructura del archivo • offset es un entero largo que especifica el número de bytes de origen, donde se colocará el cursor. • origen es un número entero que especifica la posición de origen. Puede ser: • SEEK_SET: El origen es el comienzo del archivo • SEEK_CUR: El origen es la posición actual • SEEK_END: El origen es el final del archivo Algoritmia y programación estructurada 5.2 Bibliotecas de funciones para acceder archivos Autor: M. en C. Edgardo Adrián Franco Martínez Manejo de archivos en C 25