principios de programacion en c libroc

269
FACULTAD DE INGENIERÍA. DIVISIÓN DE INGENIERÍA ELÉCTRICA. DEPARTAMENTO DE INGENIERÍA EN COMPUTACIÓN, UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO Ingeniería y Ciencias de la Computación Vol I Introducción novel a los fundamentos del software: un enfoque algorítmico Programación Estructurada con el lenguaje de programación C

Upload: fernando-bruno

Post on 02-Aug-2015

69 views

Category:

Documents


6 download

DESCRIPTION

Manual de programacion en c con orientacion a arreglos, archivos, apuntadores, y objetos.

TRANSCRIPT

Page 1: Principios de Programacion en C LibroC

FACULTAD DE INGENIERÍA. DIVISIÓN DE INGENIERÍA ELÉCTRICA. DEPARTAMENTO DE INGENIERÍA EN COMPUTACIÓN,

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO

Ingeniería y Ciencias de la Computación Vol I

Introducción novel a los fundamentos del software: un enfoque algorítmicoProgramación Estructurada con el lenguaje de programación C

Hugo Rangel

INICIATIVA ACADÉMICA DEL LABORATORIO DE INGENIERÍA TELEMÁTICA

Page 2: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 2 de 207

Page 3: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Universidad Nacional Autonoma de MéxicoFacultad de Ingeniería

Ingeniería y Ciencias de la Computación Vol I

Introducción novel a los fundamentos del software: un enfoque algorítmicoProgramación Estructurada con el lenguaje de programación C

Hugo Rangel

División de Ingeniería EléctricaDepartamento de Ingeniería en Computación

INICIATIVA ACADÉMICA DEL LABORATORIO DE INGENIERÍA TELEMÁTICA

Página 3 de 207

Page 4: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Ingeniería y Ciencias de la Computación Vol IIntroducción Novel a los fundamentos del software: Un enfoque algorítmico.Programación Estructurada con el lenguaje de programación C

Prohibida la reproducción y trasmisión total o parcial de esta obra de texto por cualquier medio o sistema electrónico o mecánico (incluyendo el fotocopiado, la grabación o cualquier sistema de recuperación y almacenamiento de información), sin consentimiento por escrito del editor.

Derechos reservados© 2010, Facultad de Ingeniería, Universidad Nacional Autónoma de MéxicoCiudad Universitaria, 04510, México, D. F.ISBN XXXXXXXXX

Primera edición, diciembre 2010Impreso y hecho en México, D. F.

Dedicatoria

Página 4 de 207

RANGEL GUTIÉRREZ, Raymundo Hugo, autorIngenieros y Ciencias de la Computación Vol. IIntroducción novel a los fundamentos del software: Un enfoque algoritmico.México, Universidad Nacional Autónoma de MéxicoFacultad de Ingeniería2010, XXX pgs.

Page 5: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

A Dios misericordioso, quien siempre me a abierto todas las puertas, y a mis siempre bien amados padres Mercedes y José, quienes dieron a sus hijos una buena educación.

Portada

Por ser la más fotogénica de la familia, Pimienta tuvo el privilegio de aparecer en la portada del texto.

Agradecimientos

A la Universidad Nacional Autónoma de MéxicoA la Facultad de Ingeniería

Gracias cumplidas al Dr. Francisco Javier Ugalde, al Ingeniero Rolando Guervassi q.p.d. por el apoyo recibido.

Gracias también a la Mtra. María Cuairán Ruidíaz, Jefa de la Unidad de Apoyo Editorial de la Facultad de Ingeniería de la UNAM, por su apoyo para la revisión y registro de la presente obra de texto.

Agradezco a Angelina Torres Rojas de la Unidad de Apoyo Editorial de la Facultad de Ingeniería, por su valiosa y dedicada revisión del estilo y observaciones del presente texto.

Gracias cumplidas también a la Mtra. Lucila Patricia Mendoza Arellano y a la Mtra. Luciralia Hernández Hernández, colegiadas del Laboratorio de Telemática, por la minuciosa revisión técnica y juiciosa revisión pedagógica de la misma.

A la Mtra Laura Sandoval Montaño por su gran interés en revisar técnica y pedagógicamente la obra y porque se publique.

Al PAPIME (proyecto PAPIME #PE100806) por su apoyo para que esta obra fuese una realidad.

Raymundo Hugo Rangel GutiérrezBuzón e: [email protected]

[email protected] de Ingeniería, UNAM

Agosto del 2012

Página 5 de 207

Page 6: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 6 de 207

Page 7: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Prologo

El desarrollo de un libro de texto es una labor larga y pesada, es, sin embargo, también una actividad muy gratificante. Al modelar el contenido de una asignatura, así como el contenido del texto correspondiente, para un lenguaje de programación especifico, deben tenerse en cuenta los siguientes tres aspectos esenciales:

1. El paradigma, es decir, el modelo de programación que se adopta para el curso, en nuestro caso se trata de la Programación Estructurada (PE).

2. El lenguaje de elección que intenta capturar en su sintaxis al paradigma, en otras palabras, el lenguaje de elección es afín al paradigma. En nuestro caso se trata del lenguaje de programación C. y

3. La didáctica asociada tanto al paradigma como a el lenguaje de elección. Hoy día se reconoce poco la necesidad de una didáctica especifica en la enseñanza de los lenguajes de programación.

Es de importancia capital tomar en cuenta estos tres aspectos en la modelación del contenido de una asignatura – en la que los alumnos de una carrera como la de Ingeniero en Computación se inician en la programación – y de la obra de texto correspondiente que le da soporte a la misma.

Los motivos

La presente obra de texto, para la asignatura de Computación para Ingenieros, tiene su origen en las experiencias del autor en el aula, pero totalmente compatibles con los requerimientos de la asignatura mencionada. No es un texto más en la enseñanza del lenguaje de programación C. Mi larga experiencia en la enseñanza de los lenguajes de programación se refleja a lo largo y ancho del contenido del texto, en particular en los tópicos de árboles sistémicos (árboles s por brevedad) y de la notación Méx, aportaciones propias que se originan en el contexto de una metodología de enseñanza aprendizaje denominada programática educacional o didáctica de los sistemas de software. Este proceso metodológico concibe al docente como un diseñador de entornos de enseñanza que facilita el aprendizaje de uno o más tópicos.

Las metas

Se ha escrito esta obra con las siguientes metas en mente:

Elevar el nivel del juego (lenguaje C)

Página 7 de 207

Page 8: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El diseño de programas es una disciplina que exige la aplicación, con rigor, de un conjunto de reglas que gobiernan la secuencia de un comportamiento determinado en los programadores.Un juego impone ciertas condiciones a los jugadores, y representa una prueba de las habilidades intelectuales (y/o físicas como en el fútbol soccer) individuales o de conjunto de estos al resolver un problema y alcanzar con ello un objetivo determinado. Si el jugador viola una de las reglas comete una “falta” y es sancionado. Considérese el fútbol soccer, los jugadores del equipo A ponen en juego todas sus habilidades físicas e intelectuales, individuales y de conjunto, para colocar un gol en la portería del equipo B y al mismo tiempo evitar que este les coloque uno en su portería. En un juego del ajedrez ambos oponentes también ponen en juego todas sus habilidades intelectuales para darle jaque mate al rey de su oponente. En ambos juegos el objetivo de los jugadores es demostrar habilidades superiores.

Desde hace muchos años, en los cursos de programación, no tiene sentido enseñar solo la sintaxis del lenguaje de programación de elección. Hoy día los compiladores contienen una vastedad de recursos para ayudarle al aprendiente a resolver los problemas de sintaxis. Por lo que la perspectiva actual en la enseñanza de un lenguaje de programación es el diseño de programas (sistemas de software). El nivel del juego se ha incrementado.

Jugar (programar) con agilidad y menos erroresConforme se juega con mayor agilidad – incremento del nivel de aprendizaje - mayor es el dominio que se tiene de la complejidad del juego. En un juego de video el objetivo es dominar, con maestría, todos los niveles del mismo, desde el primer nivel de principiante hasta el más avanzado. Las expectativas de cualquier juego siempre deben ser altas, en concecuencia se espera que el desempeño de los jugadores sea alto también. Un juego es una abstracción mental que vive su propia realidad cuando se bien. Los jugadores, y aun los espectadores, se “apropian” del mismo y lo utilizan como un medio para expresarse a si mismos con un gran sentido de realización. Si, por el contrario, el juego – el desempeño de los jugadores - es mediocre, lo vivido de su propia realidad sufre un gran menoscabo y el sentido de realización se pierde irremediablemente.

Facilitar el dominio de los niveles superiores del juego (programación orientada a objetos (POO) con el lenguaje C++)Las dos primeras ,metas ayudan a preparar el terreno para facilitar el dominio (aprendizaje) del juego de sus niveles superiores (programación orientada a objetos con el lenguaje C++). Un buen dominio de todos los niveles de un juego es la fuente de una gran satisfacción así como de un gran sentido de realización. Estos son parte de una necesidad - muy humana – de expresarse a si mismo y de trascender en la vida. Metas adicionales

Página 8 de 207

Page 9: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Un texto que refleje los requerimientos esenciales para un primer curso de programación con el lenguaje C. Específicamente que sea el libro de texto de las materias de la asignatura de “Computación para Ingenieros” de la carrera de Ingeniería en Computación de la Facultad de Ingeniería, UNAM, (proyecto PAPIME #PE100806 del Laboratorio de Ingeniería Telemática, departamento de Ingeniería en Computación).

Enfocar el texto en una introducción novel a la ingeniería y ciencias en computaciónEl eje temático es el diseño e implementación (desarrollo) de algoritmos para la solución de problemas. Enfatizando la estrategia de divide y vencerás. Estrategia de uso muy común en todo diseño e implantación de un algoritmo.

Que el texto pueda usarse como un manual de referenciade prácticas de ingeniería de sistemas de software de uso cotidiano tanto para estudiantes como profesionistas activos en el campo.

Que el texto refleje mi experiencia de años en la enseñanza de la programación.Espero que esa experiencia de años sea de gran utilidad a los estudiantes de las carreras de Ingeniero en Computación y otras afines. También espero contribuya a actualizar y completar la formación de profesionistas en activo en el campo de la ingeniería de la computación o de la informática u otras afines. La elaboración de un libro de texto debe estar al menos basado en la experie3ncia del autor en el aula.

El lenguaje de programación C

El lenguaje C es el lenguaje que principalmente se elige para el desarrollo de software eficiente y transportable, por lo que es el lenguaje de más uso y más recomendado en los planes de estudio de las universidades y de otras instituciones de nivel superior. C pertenece a la categoría de lenguajes estructurados, es decir, un lenguaje con el que se puede hacer programación estructurada, un paradigma ya consolidado. Este paradigma enfatiza confiabilidad, estructura, modificabilidad, simplicidad y facilidad de uso. La intención con el paradigma es desarrollar programas que se codifiquen con mayor agilidad, libres de errores (en su mayor parte al menos) y lo que es más importante que sean legibles (facilidad de lectura). El desarrollo de sistemas de software demanda del programador un excelente juicio de discernimiento, así como la de prestar gran atención a los detalles y de mucha autodisciplina.

El lenguaje C se desarrolló en los Laboratorios Bell de la At&T alrededor de

Página 9 de 207

Page 10: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

1972 por Dennis Ritchie. Los lenguajes ideados por una sola persona a menudo reflejan el campo de interés del autor, en este caso software de sistemas, es decir, lenguajes de programación, sistemas operativos, generadores de programas, software de aplicaciones y otros. Aunque C puede ser usado para cualquier aplicación como cualquier otro lenguaje, en realidad no es un lenguaje de elección para toda aplicación.

El lenguaje C utilizado en esta obra es compatible con la versión estándar del American National Standards Institute (ANSI). Los programas en lenguaje C ANSI, que usan funciones de biblioteca, se pueden compilar y correr sin cambios en MS-DOS, UNIX, Windows, OS/2, Linux y en muchos otros entornos. A lo largo de la obra el alumno usará C ANSI y esperamos adquiera la disciplina necesaria y suficiente para obtener una experiencia extensa y profunda al codificar y ejecutar programas con el lenguaje C. Por lo que es mi más ferviente deseo de que el texto que tienes ahora en tus manos tenga como característica principal el de comunicar e instruir..

El autor espera detectar cualquier deficiencia de la obra con la ayuda de los profesores y alumnos que lo utilicen como texto en los diversos ambientes de clase. Por lo que daré la bienvenida a cualquier sugerencia de profesores y alumnos y otros lectores de la obra que contribuyan a mejorarla.

Organización del libro

El texto esta organizado en tres partes; la parte A, la parte B y la parte C. La parte A cubre solución de problemas, algoritmos, el lenguaje C y programación estructurada.

El capítulo 1 introduce a la nociones de solución de problemas y de algorítmica.

El capítulo 2 trata con funciones de entrada y salida de datos de tipo carácter, cadenas, enteros y reales en el lenguaje C. Estos programas solo incluyen a la categoría de figuras de secuencia. Se ilustra ampliamente con programas completos simples

El capítulo 3 cubre la categoría de figuras de iteración, se incluyen ejemplos simples completos en el lenguaje C, para ilustrar la naturaleza cíclica de cada una de ellas y sus variantes correspondientes. Previo a las figuras iterativas se introduce el concepto de arreglo, operadores y expresiones de relación, operadores de pre y post autoincremento, los operadores de pre y post autodecremento y la notación corta para ciertas expresiones aritméticas de uso común. Se ilustran vectores y matrices de los enunciados modelara, codificara y correrá programas que incluyen algoritmos que utilizan

Página 10 de 207

Page 11: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El capítulo 4 cubre la estrategia de divide y vencerás (D&V) y su instrumento esencial: el árbol S(istémico) así como su mapeo en la categoría de figuras de decisión. La estrategia de D&V habilita al alumno con una mayor capacidad de abstracción en la solución de problemas que incluyan decisiones. Las competencias – habilidades - que el alumno adquirirá son las de modelar, codificar y correr programas que incluyan algoritmos que utilizan la categoría de figuras de decisión, de acuerdo a los requerimientos establecidos – resultados - en cada caso por el docente.

El capítulo 5 cubre la programación modular, es decir una programación basada en funciones. Esta programación consiste en diseñar e implementar un programa en una función (modulo) principal y una o más funciones de apoyo o soporte. Esta es también una estrategia de D&V La capacidad de abstracción del alumno - en la solución de problemas – se potencia. Las competencias – habilidades - que el alumno adquirirá son las de modelar, codificar y correr programas que incluyan algoritmos modularizados (con funciones), de acuerdo a los requerimientos establecidos – resultados - en cada caso por el docente.

El capítulo 6 cubre el paradigma de la programación estructurada y sus conceptos asociados: seudocódigo (Lenguaje de Diseño de Programas - LDP), las categorías de las figuras de control, el proceso de refinamiento a pasos (una estrategia de D&V), niveles de abstracción, módulos e interfaces. Las competencias – habilidades - que el alumno adquirirá son las de modelar (usando el proceso de refinamiento a pasos), codificar y correr programas de acuerdo a los requerimientos establecidos – resultados - en cada caso por el docente.

El capítulo 7 cubre los tipos de variables predefinidos: La estructura y la unión. El alumno modelara, codificara y correrá programas que incluyen los tipos de variables predefinidos: La enumeración, la unidad y la estructura

El capítulo 8 cubre el tipo de variable predefinido: La enumeración.. El alumno modelara, codificara y correrá programas que incluya el tipo de variable predefinido: La enumeración.

El capítulo 9 cubre las tres organizaciones básicas de archivos; secuencial, directa e indexada. El alumno explicara los conceptos asociados con la solución de problemas y la algorítmica.

La parte B cubre una serie de tópicos que tradicionalmente se han considerado de gran dificultad en su aprendizaje o avanzados. Los capítulos del 12 al 17 están en el primer caso; la combinación de apuntadores con otras estructuras de datos en el lenguaje C. La notación Méx resuelve esta problemática (dominio de problema), un MODOS específicamente diseñado para este fin. El contenido del capítulo 18 tradicionalmente se han considerado de “bajo nivel”, debido a que sus funciones son iguales a las de

Página 11 de 207

Page 12: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

algunas instrucciones del lenguaje ensamblador, por lo que rara vez se incluyen en un primer curso de lenguaje C. El contenido del capitulo 19 es también un tópico que rara vez se incluye en un primer curso de lenguaje C, sin embargo, se incluye porque sirve como un antecedente introductorio a la asignatura de verificación y validación del software, del módulo de ingeniería del software de la carrera de Ingeniero en Computación. La verificación y validación del software, es un tópico que, en sinergia con la lógica computacional, crecen aceleradamente en la actualidad.

Capítulo 10 Trata los conceptos de identificadores estáticos y dinámicos, señalamiento directo e indirecto. El concepto de apuntador a variables simples: enteros, flotantes, caracteres y otros.

Capitulo 11 Cubre la relación conceptual entre un apuntador constante y el nombre de los arreglos, apuntadores que señalan a un arreglo, arreglos de apuntadores e identificadores en los que intervienen apuntadores, arreglos y variables simples.

Capitulo 12 Cubre la relación conceptual entre un apuntador constante y el nombre de las funciones, apuntadores a funciones, funciones que devuelven apuntadores e identificadores en los que intervienen apuntadores, arreglos, funciones y variables simples.

Capítulo 13 Cubre la diferencia conceptual entre la notación de flecha y la notación de punto, apuntadores a estructuras e identificadores en los que intervienen apuntadores, arreglos, funciones y variables simples.

Capítulo 14 Cubre el concepto de referencia en el lenguaje C, la diferencia entre un apuntador y una referencia.

Agradecimientos

Esta obra de texto no habría sido escrita sin el apoyo de tantas personas a quienes deseo expresar mi más profunda gratitud. A las maestras Lucila Patricia Arrellano Mendoza y a Luciralia Hernández Hernández, colegiadas del Laboratorio de Telemática, por la minuciosa revisión técnica y observaciones. A María Cuairán, jefa de la Unidad de Apoyo Editorial de la Facultad de Ingeniería, por proporcionar el soporte necesario, a Angelina Torres Rojas, también de la Unidad de Apoyo Editorial, por su colaboración en la adecuación pedagógica y su dedicada revisión de estilo. Al Ing. Rolando Gervassi (finado) y al Dr. Francisco Javier García Ugalde, Jefe de la División de Ingeniería Eléctrica, por el apoyo que brindaron ante el PAPIME. Agradezco también al PAPIME su apoyo para la realización de esta obra de texto (proyecto PAPIME #PE100806 del Laboratorio de Ingeniería Telemática, departamento de Ingeniería en Computación).

Página 12 de 207

Page 13: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

A l(a)os profesor(a)es que imparten la asignatura de “Computación para Ingenieros” y adopten esta obra de texto, como el texto principal del curso.

Hugo Rangel, agosto del 2012Cd. Universitaria, México, D. F.

Página 13 de 207

Page 14: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Contenido

Parte A Solución de Problemas, Algoritmos y Programación Estructurada

El alumno explicara los conceptos asociados con la solución de problemas, la algorítmica, .el lenguaje de elección y los paradigmas

1.- Solución de Problemas, Algoritmos, el Lenguaje de Elección y los Paradigmas de Software

1.1- Introducción1.2- Solución de Problemas

1.2.1- Problemas de Análisis1.2.2- Problemas de Síntesis1.2.3-Identificación del dominio del problema

1.3- Algoritmos1.3.1- La estrategia de divide y vencerás en el diseño de algoritmos1.3.2- El principio de separación de niveles de interés

1.4- El Lenguaje de elección 1.4.1- Los conceptos de modelos y sistemas1.4.2- El lenguaje de programación de elección1.4.3- La practica de la programación

1.5- Los paradigmas de software1.5.1- La programación Estructurada (PE)1.5.2- La Programación Orientada a Objetos

1.4- Resumen1.5- Conceptos clave1.6- Ejercicios

El alumno modelara, codificara y correrá programas que incluyen funciones de entrada y salida de datos de tipo carácter, cadenas, enteros, reales en el lenguaje C. Estos programas solo incluyen a la categoría de figuras de secuencia.

2- Elementos del Lenguaje de Programación C2.1- Introducción2.2- La estructura de un programa en lenguaje C

2.1.1- Exhibición de una cadena de caracteres2.1.2- Cadenas muy largas2.1.3- Uso de varias salidas con la función puts()

2.2- Identificadores variables y constantes

Página 14 de 207

Page 15: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

2.2.1- El identificador variable de tipo carácter (char)2.2.2- Diferencias entre el carácter A y la cadena con el carácter A2.2.3- Lectura de una cadena de caracteres con la función gets()2.2.4- Las funciones de lectura para un carácter2.2.5- Exhibición de una cadena con la función printf()2.2.6- Cambio de línea con la función printf()2.2.7- El formato s (string) para cadenas

2.3- Exhibición de datos con la función printf()2.4- Lectura de datos con la función scanf()

El alumno modelara, codificara y correrá programas que incluyen algoritmos que utilizan la categoría de figuras de iteración.

3.- Arreglos y la Categoría de Figuras de Iteración3.1- Introducción3.2- Arreglos

3.2.1- Arreglos unidimensionales3.2.2- Arreglos multidimensionales3.2.3- Operadores de relación3.2.4- Los operadores de pre y post autoincremento3.2.5- Los operadores de pre y post autodecremento3.2.6- Notación corta

3.3.- Ciclos3.3.1- La instrucción for y sus variantes3.3.2- La instrucción while y sus variantes3.3.3- La instrucción while-do y sus variantes

3.4- Diseño de programas con ciclos3.5- Resumen3.6- Conceptos clave3.7- Ejercicios

El alumno modelara, codificara y correrá diversos programas que incluyen algoritmos que utilizan la categoría de figuras de decisión.

4.- Operadores de relación, lógicos y la Categoría de Figuras de Decisión4.1- Introducción4.2- Los operadores lógicos básicos

4.2.1- Introducción4.2.2- La tabla de verdad para el operador lógico OR4.2.3- La tabla de verdad para el operador lógico AND4.2.4- La tabla de verdad para el operador lógico NOT

4.3- Diagramas de flujo y el enunciado if-else4.3.1- Introducción4.3.2- Diagramas de flujo4.3.3- El enunciado if-else

4.4-- Diseño de decisiones con árboles sistémicos, parte I

Página 15 de 207

Page 16: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.4.1- Introducción4.4.2- El árbol básico4.4.3- Ejemplos

4.5- Diseño de decisiones con árboles sistémicos, parte II4.5.1- Introducción4.5.2- Ejemplos

4.6- Diseño de decisiones con árboles sistémicos, parte III4.6.1- Introducción4.6.2- Reglas 1 y 24.6.3- El proceso cosecuencial

4.7- Diseño de decisiones con árboles sistémicos, parte IV4.7.1- Introducción4.7.2- Los enunciados switch y break4.7.3- El enunciado continue

4.8- Resumen4.9- Conceptos clave4.10- Ejercicios

El alumno modelara, codificara y correrá programas modulares basados en las funciones del lenguaje C.

5.- Funciones5.1.- Introducción5.2.- Estructura de una función

5.2.1.- El alcance de una función5.2.2.- Identificadores locales y globales

5.3.- Funciones con tipo5.3.1.- Funciones de tipo entero con o sin argumentos5.3.2.- Funciones de otros tipos5.3.3.- Funciones en expresiones

5.4.- Funciones sin tipo (void)5.4.1.- Funciones con o sin argumentos

5.5.- Argumentos por valor y por dirección5.6.- Funciones en línea

5.6.1.- Argumentos por omisión5.6.2.- Argumentos por omisión múltiple

5.7.- Argumentos de main()5.8.- Diseño de programas con módulos (programación modular)5.9.- Resumen5.10- Conceptos clave5.11.- Ejercicios

El alumno explicara los conceptos de refinamiento a pasos, niveles de abstracción, módulos, interfaces y seudocódigo.

6.- La Programación Estructurada y el Lenguaje de Programación C6.1.- Introducción

Página 16 de 207

Page 17: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

6.2.- La programación estructurada6.2.1.- El paradigma de la programación estructurada6.2.2.- Falacias de la programación estructurada

6.3.- El proceso de refinamiento a pasos8.3.1- Abstracción y Español estructurado o seudocódigo6.3.2- Un ejemplo de formulación de un problema (saber reconocer el dominio inquisitivo o del problema).

6.4.- Resumen6.5.- Conceptos clave6.6.- Ejercicios

El alumno modelara, codificara y correrá programas que incluyen los tipos de variables predefinidos: La unión y la estructura.

7.- Los tipos de variables predefinidas: La unión y la estructura7.1.- Introducción7.2.- La unión

7.2.1.- Representación física (memoria) y lógica (visual) de la unión7.2.2.- La declaración de variables de tipo unión

7.3.- La estructura7.3.1.- Representación física (memoria) y lógica (visual) de una estructura7.3.2.- La estructura como un tipo de variable y la declaración de variables de tipo estructura7.3.3.- Estructuras anidadas7.3.4.- Arreglos de estructuras y estructuras con arreglos7.3.5.- Estructuras como argumentos en funciones

7.4.- Resumen7.5.- Conceptos clave7.6.- Ejercicios

El alumno modelara, codificara y correrá programas que incluyen los tipos de variables predefinidos: La enumeración

8.- El tipo de variable predefinido: La enumeración8.1.- Introducción8.2.- Las enumeraciones8.3.- Resumen8.4.- Conceptos clave8.5.- Ejercicios

El alumno modelara, codificara y correrá programas que incluyan las tres organizaciones básicas de archivos; secuencial, directa e indexada

9.- Archivos9.1.- Introducción9.2.- Representación física (disco) y lógica (visual) del archivo secuencial

Página 17 de 207

Page 18: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

9.3.- Representación física (disco) y lógica (visual) del archivo directo9.4.- Representación física (disco y memoria) y lógica del archivo indexadosecuencial9.5.- Instrucciones para abrir y cerrar archivos: fopen() y fclose()9.6.- Instrucciones para leer de y escribir a disco caracteres: getc() y putc()9.7.- Instrucciones para leer de y escribir a disco cadenas: fgets() y fputs()9.8.- Instrucciones para leer de y escribir a disco: fprintf() y fscanf()9.9.- Instrucciones para leer de y escribir a disco palabras: getw() y putw()9.10.- Instrucciones para fin de y error en un archivo: feof() y ferror()9.11.- Instrucción para búsqueda directa: fseek()9.12.- Instrucciones para leer de y escribir a disco: fread() y fwrite()9.13.- Resumen9.14.- Conceptos clave9.14.- Ejercicios

Parte B Programación Avanzada con C

El alumno explicara los conceptos de identificadores estáticos, dinámicos, señalamiento directo, indirecto. El concepto de apuntador a variables simples. Usara estos conceptos en sus programas.

10.- El Apuntador a Variables Simples10.1.- Introducción10.2.- Representación física (memoria) y lógica (visual) de una referencia

12.2.1.- La referencia y su diferenciación con un apuntador12.2.2.- El propósito de las referencias en el lenguaje C12.2.3.- Referencias de un carácter, un entero, un flotante y de un apuntador

10.3.- Representación física (memoria) y lógica (visual) del apuntador12.3.1.- El concepto de una variable estática y de una dinámica12.3.2.- El apuntador a un carácter12.3.3.- El apuntador a un entero12.3.4.- El apuntador a un flotante12.3.5.- El apuntador a otro apuntador

10.4.- Resumen10.5.- Conceptos clave10.6.- Ejercicios

El alumno explicara la relación entre un apuntador constante y el nombre de los arreglos. Usara apuntadores a arreglos, arreglos de apuntadores y usara identificadores en los que intervienen apuntadores, arreglos y otros en sus programas.

11.- Arreglos y apuntadores11.1- Introducción11.2.- Representación física (memoria) y lógica (visual) del arreglo

Página 18 de 207

Page 19: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

11.2.1.- El nombre de un arreglo como un apuntador constante11.2.2.- El identificador apuntador a un arreglo11.2.3.- Identificadores en los que intervienen apuntadores y arreglos

11.3.- Resumen11.4.- Conceptos clave11.5.- Ejercicios

El alumno explicara la relación entre un apuntador constante y el nombre de las funciones. Usara apuntadores a funciones, funciones que devuelven apuntadores y usara identificadores en los que intervienen apuntadores, arreglos, funciones y otros en sus programas.

12.- Funciones y apuntadores12.1- Introducción12.2.- Representación física (memoria) y lógica (visual) de la función

12.2.1.- El nombre de una función como un apuntador constante12.2.2.- El identificador apuntador a una función12.2.3.- Identificadores en los que intervienen apuntadores, arreglos y funciones

12.3.- Resumen12.4.- Conceptos clave12.5.- Ejercicios

El alumno explicara la diferencia entre la notación de flecha y la notación de punto. Usara apuntadores a estructuras e identificadores en los que intervienen apuntadores, arreglos, funciones y estructuras en sus programas.

13.- Estructuras y apuntadores13.1.- Introducción13.2.- Representación física (memoria) y lógica (visual) de la estructura

13.2.1.- Apuntadores y estructuras13.2.2.- Identificadores en los que intervienen apuntadores y estructuras13.2.3.- Identificadores en los que intervienen apuntadores, estructuras, arreglos y funciones

13.3.- Resumen13.4.- Conceptos clave13.5.- Ejercicios

El alumno explicara el concepto de referencia en el lenguaje C. Explicara también la diferencia entre un apuntador y una referencia. Usara estos conceptos en sus programas.

14.- Referencias y apuntadores14.1.- Introducción14.2.- El propósito de las referencias en el lenguaje C14.3.- Referencias

Página 19 de 207

Page 20: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

14.4.- Excepciones en el uso de referencias14.5.- Resumen14.6.- Ejercicios

Página 20 de 207

Page 21: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 21 de 207

Page 22: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 1

Solución de Problemas y Algoritmos

Página 22 de 207

Page 23: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 23 de 207

Page 24: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Introducción

Las computadoras, dispositivos electrónicos programables universalmente, nacen como una necesidad para resolver problemas que son difíciles de tratar manualmente, es decir, que procesan grandes volúmenes de datos a gran velocidad. En algunos casos tenemos como entrada y salida grandes volúmenes de datos con poco proceso, o a la inversa, poco volumen de entrada y salida de datos y un tiempo considerable de proceso, o bien, una combinación de ambos casos. Son ejemplos de dispositivos de entrada de datos, el teclado, el ratón, el scanner y son ejemplos de dispositivos de salida el monitor de pantalla y la impresora.A fin de hacer uso de una computadora primero es necesario describir lo que se quiere mediante un enunciado (mínimo de detalles), luego se procede a obtener un alto grado de detalles mediante una serie de abstracciones. El resultado es un programa. El cual se codifica empleando la sintaxis del lenguaje de programación de elección. Existen diversos lenguajes de programación con un propósito bien definido de aplicación. La elección del lenguaje de programación es critico ya que esto permite una codificación más limpia y fácil si es el adecuado, es decir, si fue desarrollado para la categoría de problemas a resolver que tenemos a la mano.

Un programa – un procedimiento o conjunto de procedimientos - es un modelo que plantea la solución de un problema, cuando este corre en una computadora A, tenemos un sistema A que resuelve el problema en cuestión, cuando corre en una computadora B, una computadora con otras características, se dice que tenemos un sistema B que resuelve el problema, en general, no necesariamente obtenemos los mismos resultados con el sistema A y el sistema B, aunque estos deben estar muy próximos uno del otro.

Solución de Problemas

La obtención de la solución de un problema consiste en un proceso de desarrollo – de un procedimiento o un conjunto de procedimientos - seguido de uno de aplicación. En el primer proceso se desarrolla un programa que plantea la solución del problema, en el segundo se aplica el programa sobre un conjunto de datos. Este conjunto puede ser suministrado por el programador, quien desarrolla el programa, o bien es generado por el procedimiento mismo. Por ejemplo, el enunciado

Página 24 de 207

Page 25: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Desarrolle un procedimiento que exhiba los primeros 500 números impares, comenzando con 1.

Si utilizamos la expresión algebraica 2*n + 1 y sustituimos en la n el conjunto de valores 0, 1, 2, ..., 499, uno a uno, obtenemos el resultado deseado. Sin embargo, realizar esto a mano es impractico, por lo que recurrimos a un compilador instalado en una computadora.Supongamos que el compilador dispone de las siguientes dos enunciados:Primer enunciado

Desde <primer expresión aritmética> hasta <segunda expresión aritmética>

Enunciado(s)

Segundo enunciado

Exhibe(una leyenda o un valor)

Donde la primera instrucción es un enunciado que expresa, de acuerdo a la primera y la segunda expresión aritmética, el número de veces que se realiza(n) la(s) instrucción(es) con diferentes valores, en nuestro caso 0, 1, ..., 499.La segunda instrucción es un enunciado que expresa la exhibición, en la pantalla del monitor, de una leyenda o un valor.

Con estas dos instrucciones podemos construir un procedimiento computacional bien definido que toma un valor o un conjunto de valores (en nuestro caso dos: 0 y 499) y produce uno o un conjunto de valores como salida, en nuestro caso la secuencia de valores {1, 3, 5, ... , 499} lo que resuelve el problema en cuestión como sigue:

Desde n = 0, hasta 499Exhibe (2*n + 1)

Esto funciona como sigue:

desde n = 0 tenemos 2*0 + 1 = 1 n = 1 tenemos 2*1 + 1 = 3 n = 2 tenemos 2*2 + 1 = 5

* * * * *hasta n = 499 tenemos 2*499 + 1 = 999

Podemos distinguir dos categorías básicas de problemas: de síntesis y de análisis.

+++++++++++++++++++++ Categorías en la solución de problemas ++++++++++

Página 25 de 207

Page 26: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El de síntesis consiste de un enunciado de un estado inicial y una meta deseada en la que el principal esfuerzo es la selección de un proceso de solución a la meta explicita deseada, pero para al que el proceso como un todo (es decir, el patrón completo de la solución) es nuevo para nosotros, aunque los pasos individuales no lo son. En tal caso, verificamos la aceptabilidad de la solución al tratar con diversos procesos para una solución y eleminemos progresivamente (reduciendo a cero) el ajuste entre la meta deseada y los resultados obtenidos del proceso de ensayo. Este clase de problemas podemos considerarla como un problema de diseño o de síntesis en el que un proceso de solución completo se sintetiza a partir de pasos más pequeños.

En el de análisis se enfoca más en la aplicación de procesos de transformación conocidos para llegar a una meta. La meta puede que no sea reconocida como la meta correcta de inmediato, pero puede verificarse por el proceso de tal manera que no exista un ajuste entre las condiciones del problema (estado inicial) y la solución. Esta clase de problemas puede ser considerada como un problema de análisis en el que la solución de una transformación o cambio en la representación de la información dada para hacer transparente lo oscuro o lo oculto.

Algoritmos y la estratega de divide y vencerás

Podemos decir de manera informal, que un procedimiento computacional bien definido, que sigue un número finito de pasos bien definidos, que toma uno o más valores, como entrada, y produce uno o más valores como salida, también se le conoce como un algoritmo.

Una estrategia siempre presente en la solución de problemas y el diseño de algoritmos es la de divide y vencerás. Uno puede visualizarla como una estructura de árbol. Podemos imaginar en la raíz del árbol el enunciado o planteamiento del problema original y en las subsecuentes ramas problemas más pequeños derivados al dividir el problema original. Cada uno de estos últimos a su vez se dividen en problemas más pequeños. Este proceso continua tanto como sea posible. Si los subproblemas involucrados son procesos a ser ejecutados en paralelo, entonces el problema se resuelve de abajo hacia arriba combinando los resultados obtenidos hasta llegar a la raíz. Si este no es el caso, es decir, entonces los nodos contienen expresiones lógicas basadas en comparaciones que utilizan los operadores de relación y/o lógicos, en consecuencia es la estructura en árbol misma la solución al problema, ya que esta estructura puede mapearse directamente a condicionales anidados de acuerdo a la sintaxis del lenguaje de elección.En términos generales una estructura de árbol es una herramienta con la propiedad intrínsica de divide y vencerás, sin embargo, no todos los árboles pertenecen a una misma categoría, en otras palabras, existen diversas categorías de árboles que resuelven diferentes categorías de dominios de problemas y por consiguiente se manipulan con reglas propias cada una de esta categorías.

Página 26 de 207

Page 27: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Para comprender mejor esto veamos el siguiente ejemplo:

El Arreglo X se divide en dos arreglos, A y B. Nótese la estructura en árbol donde en cada nodo, al mismo nivel, se realiza un proceso de ordenamiento en paralelo. El propósito de esta estrategia es la de ganar velocidad de proceso. El paso siguiente consiste en intercalar los dos arreglos resultantes, A y B, en uno.

El árbol (líneas punteadas) que aparece inscrito en el rectángulo de esquinas redondeadas ya no es un árbol para procesos en paralelo, sino un algoritmo que intercala el o los valores que proceden de los arreglos A y B en el arreglo de abajo. La línea gruesa es el ciclo que repite una y otra vez la estructura de árbol (algoritmo) bajo su alcance hasta agotar los arreglos.

Una herramienta que hace uso intrínsicamente de esta estrategia es el árbolsistémico, sus diferentes niveles se corresponden con los subproblemas de un problema mayor, es decir, es una herramienta que nos permite dividir un problema complejo en otros de menor complejidad. El problema se plantea como un árbol básico, uno que solo involucra a los operadores de relación <, = y >. El árbol puede comprimirse verticalmente (mediante el operador lógico AND) y horizontalmente (mediante el operador OR). En un árbol sistémico nunca aparecen negaciones (el operador lógico NOR), esto es una gran ventaja, ya que

Página 27 de 207

726 18 4 12 23 10 15 11

726 18 4

1872 4 6

12 23 10 15 11

10 11 12 15 23

Arreglo A Arreglo B

Arreglo X

1872 4 6 10 11 12 15 23

1072 4 6 11 12 15 18 23

Ai < Bj

Xk = Ai

Ai = Bj

Xk = AiXk =Bj

Ai > Bj

Xk = Bj

Page 28: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

las negaciones en las expresiones lógicas de los árboles se pueden leer y comprender con mayor facilidad (menor complejidad). Un árbol sistémico puede utilizarse también como una herramienta para auditar código en el que aparece enunciados condicionales.

Un árbol sistémico conduce a código (enunciados condicionales) que puede ser verificado automáticamente

Un modelo es una abstracción de una porción de interés de la realidad que intenta capturar sus funciones (elementos) principales y la interrelación entre esta(o)s.La practica de la programación

Desafortunadamente, en la actualidad, todavía mucho del enfoque en la programación es empírica y ad hoc. Cada problema se aborda sin relación alguna con aquellos ya tratados dentro de la misma categoría. La experiencia se asimila como una cúmulo de unidades de conocimiento sin conexión alguna. Afortunadamente la programación ha progresando y convertido en una teoría conocida como la programación estructurada. La cual tiene como fundamento la lógica computacional.

El propósito de una teoría es la de categorizar los dominios de problema que enfrenta y de explicar la practica existente con lo que se habilita para que se mejore mediante el desarrollo de nuevas técnicas y de una mayor acuidad. Las experiencias se retroalimentan a la teoría para que el proceso de enriquecimiento continúe. Esta sinergia dialéctica entre teoría y practica es esencial para la emergencia de una ingeniería de la programación robusta y saludable.

Aunque la teoría de la programación estructurada ha avanzado mucho, las experiencias en la enseñanza de los lenguajes de programación en el aula muestran que esto no es suficiente. Es necesaria la practica continua para lograr un mejor aprendizaje, por lo que es imprescindible concurrir a laboratorios equipados con el hardware y el software necesarios y suficientes para el logro de un aprendizaje de mayor calidad.Por otra parte los principios de la buena programación no deben presentarse en el aula como abstracciones conceptuales aisladas, sino en sinergia en el contexto de programas completos que funcionan. Por ejemplo, en el texto no hay capítulos sobre eficiencia, ni de diseño de arriba abajo, ni sobre pruebas y depuración. Sino que, a lo largo del libro, hay observaciones sobre estos tópicos conforme se relacionan con un programa en particular que se desarrolla. Sin embargo si incluimos un capítulo sobre la programación estructurada con la idea de explicar aquí ampliamente dos conceptos que están ganando terreno hoy día, la de interprete y la de representación.

En la portada del libro “Software tools in Pascal”, de Kernighan y Plauger se lee:

Página 28 de 207

Page 29: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

“La buena programación no se aprende de generalidades, sino del examen de cómo los programas significantes pueden hacerse con limpieza, fáciles de leer, fáciles de mantener y modificar, diseñados para las personas, eficientes y confiables mediante la aplicación del sentido común y de las buenas practicas de la programación. El estudio cuidadoso y la imitación de los buenos programas conduce a una codificación mejor.”

El lenguaje de programación C

Un lenguaje de programación como C, puede visualizarse como una colección de lenguajes integrados en un ambiente común de desarrollo. Cada sublenguaje proporciona una perspectiva diferente. Podemos distinguir los siguientes “sublenguajes” en C: Los enunciados de entrada y salida de datos, las funciones que facilitan el manejo de los programas al subdividirlos en pequeños módulos jerárquicos, el manejo de cadenas de caracteres que se manipulan preferentemente mediante la biblioteca de cabecera “string.h”, los enunciados de las figuras de control de flujo, las estructuras de datos con sus diferentes variantes y combinaciones, etc. Todos ellos son potenciales dominios de problema que deben de tratarse de manera individual.Esta visión de concebir a un lenguaje de programación como una colección de lenguajes es de suma importancia, ya que esta constituye un primer nivel de abstracción en la identificación de dominios de problema potenciales. En un segundo nivel de abstracción podemos identificar potenciales subdominios de problema. Esta visión pone en perspectiva una solución para el analfabetismo programático. Solución que ya esta en progreso en un proyecto del Laboratorio de Telemática; Diseño de Entornos para la Enseñanza Aprendizaje, DEEA por sus siglas, en el cual se concibe al docente como un diseñador de entornos de enseñanza que facilitan el aprendizaje de un tópico o tema de difícil asimilación por parte de los alumnos. Esta investigación ha conducido a la creación de los Modelos Didácticos Ontológicos (MoDOs) que se avocan a la solución de un dominio de problema específico. En el texto se incluyen varios de estos, solo por mencionar dos de ellos: Árboles sistémicos y la notación Méx. Estos MoDOs ya sido probados ampliamente en el aula durante varios semestres con bastante aceptación y éxito. Los MoDOs forman parte de una didáctica del diseño de los sistemas de software, o por brevedad: Programática Educativa. Los MoDOs no solo son útiles a nivel pedagógico sino también igualmente a nivel profesional.

La actividad de la programación es una actividad complicada, debido a que demanda diversas habildades del programador. Por otra parte, inevitablemente se hace mucho más compleja, sin embargo, esto no significa que no podamos tratar esa complejidad con claridad y gran capacidad de discernimiento. A mayor complejidad son necesarias más y mejores herramientas para tratarla. Un buen ejemplo de ello, es el dominio

Página 29 de 207

Page 30: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

de problema ya largamente identificado de la pésima comprensión del uso de apuntadores, en el lenguaje C, particularmente cuando estos aparecen combinados con otras estructuras de datos, la complejidad es tal que algunos buenos programadores profesionales han renunciado a aprender C. La respuesta para dominar esta complejidad es la notación Mex, un MoDO, que además nos permite elevar nuestro nivel de C, usar esta complejidad a nuestro favor, pues podemos diseñar programas con mayor agilidad y comprender con mayor facilidad la programación orientada a objetos, según informan los propios alumnos, a quienes se les a impartido este y otros MoDOs.

Página 30 de 207

Page 31: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Brevario

Un estilo simple de solucion de problemas

Tomado de [Segré, 1982].

Bethe expreso, como sigue, la impresión que le causo Fermi:

Lo que más me impresionó del método de Fermi en física teórica fue su simplicidad. Era capaz de reducir a lo esencial cualquier problema sin importar que tan complicado pareciera. Lo desnudaba de complicaciones matemáticas y formalismos innecesarios. De esta forma podía resolver el problema físico esencial implicado, a menudo en media hora o incluso menos. Por supuesto que lo que se obtenía de esta forma no era todavía la solución matemática completa; pero al dejar a Fermi después de una de estas discusiones, quedaba claro como debería elaborarse la solución matemática.Este método me pareció particularmente impresionante porque yo venía de la escuela de Sommerfeld, en Munich, y el desarrollaba todo su trabajo mediante soluciones matemáticas completas. Como madure en la escuela de Sommerfeld, tenía la idea de que el método a seguir consistía en establecer las ecuaciones diferenciales pertinentes para el problema (generalmente la ecuación de Schrödinger), utilizar la destreza matemática de que se dispusiera para encontrar una solución tan exacta y elegante como fuera posible y, posteriormente, discutir dicha solución. Finalmente a través de la discusión se encontrarían las características cualitativas de la solución con la cual se entendería la física del problema. La forma de proceder de Sommerfeld era buena para muchos de problemas en los cuales la esencia de los mismos ya se comprendía, pero resultaba extremadamente laboriosa. Por lo común transcurrían meses antes de que se pudiera conocer la respuesta,

Era tremendamente impresionante comprobar que Fermi no necesitaba hacer todo este trabajo. La naturaleza física del problema se aclaraba inmediatamente el análisis de sus componentes esenciales y unas cuantas ordenes de magnitud. Su modo de proceder era pragmático (practico, es decir, de sentido común, aunque se dice que el menos común de los sentidos es el sentido común, Observación del autor). Fermi era un buen matemático. Era capaz de hacer matemáticas de sitio nivel cada vez que se necesitaba, sin embargo, primero se aseguraba que valía la pena hacerlas. Era un maestro en el arte de alcanzar resultados importantes con un mínimo de esfuerzos y de aparato matemático.Trabajar de esta manera la permitía establecer en gran medida los problemas, especialmente para beneficio de la gente joven que no poseía sus grandes conocimientos. Por ejemplo, su formulación de la electrodinámica cuántica es más simple que la versión original de Heisenberg y Pauli, y se puede entender con suma facilidad. Me intimidaban mucho los artículos de Pauli y Heisenberg y no podía ver el bosque por causa de los árboles; El planteamiento de Fermi me mostró el bosque. Lo mismo puedo decir respecto al artículo que escribimos juntos, acerca de las diversas formulaciones de la teoría relativista de las colisiones. La manera en que Fermi formuló la

Página 31 de 207

Page 32: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

difusión de neutrones, la teoría de la edad, ha sido muy útil para hacer cálculo rápido de difusión de neutrones aún en casos complicados. Podría multiplicar esta lista fácilmente, recurriendo solo a mi experiencia personal con Fermi y su trabajo.

Página 32 de 207

Page 33: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 2

Elementos del Lenguaje de Programación C

Página 33 de 207

Page 34: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 34 de 207

Page 35: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno modelara, codificara y correra programas que incluyen funciones de entrada y salida de datos de tipo carácter, cadenas, enteros, reales en el lenguaje C. Estos programas solo incluyen a la categoría de figuras de secuencia.

Contenido

2- Elementos del Lenguaje de Programación C2.0- Introducción2.1- La estructura de un programa en lenguaje C

2.1.1- Exhibición de una cadena de caracteres2.1.2- Cadenas muy largas2.1.3- Uso de varias salidas con la función puts()

2.2.- Identificadores variables y constantes2.2.1- El identificador variable de tipo carácter (char)2.2.2- Diferencias entre el carácter A y la cadena con el carácter

A2.2.3- Lectura de una cadena de caracteres con la función

gets()2.2.4- Las funciones de lectura para un carácter2.2.5- Exhibición de una cadena con la función printf()2.2.6- Cambio de línea con la función printf()2.2.7- El formato s (string) para cadenas

2.3- Exhibición de datos con la función printf()2.4- Lectura de datos con la función scanf()

Objetivos

Al terminar éste capítulo, el alumno será capaz de utilizar:

1. Caracteres y cadenas2. Leer y escribir caracteres y cadenas.3. Formatos para lectura y exhibición de datos.4. Constantes.

Página 35 de 207

Page 36: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

2.0- Introducción

El desarrollo de algoritmos (solución a un problema) pone en juego nuestra capacidad de abstracción a diferentes niveles y a nuestra capacidad de discernimiento en diferentes contextos. En la actividad de la programación se implementa la solución con una especial atención a los detalles, sintaxis del lenguaje y otros. El desarrollo de algoritmos y la actividad de la programación deben de ser una practica constante. En este capítulo hacemos más énfasis en la sintaxis del lenguaje C que en estrategias para el desarrollo de algoritmos.

2.1- La estructura de un programa en C

Todo programa en C debe incluir al menos a la función principal main. La estructura general de un programa en C que incluye al menos a la función principal es la siguiente:

#include <stdio.h>

void main(void){ /* declaraciones de datos */

/* instrucciones ejecutables */ }

La primera línea contiene a la directiva #include, la que se utiliza para incluir archivos especiales llamados archivos cabecera (header files) que contienen funciones predeclaradas que usted usa en su programa. En este caso se incluye la utilería stdio.h la cual contiene las funciones de lectura y exhibición de datos.

La línea void main(void) especifica el inicio de la función principal, llamada así porque esta se ejecuta primero antes que cualquier otra función en el programa. Entre las llaves { y }, que indican el inicio y final respectivamente de la función principal en la que se encuentran las declaraciones de datos que intervienen en el programa y las instrucciones ejecutables que los manipulan.

2.1.1- Exhibición de una cadena de caracteres

Nuestro primer programa exhibe una cadena de caracteres en la pantalla. Este programa no incluye declaraciones, sólo una instrucción ejecutable (fondo gris).

#include <stdio.h>

void main(void){

Página 36 de 207

Page 37: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

puts("Mi primer programa en C"); }

Observése que el programa, luego de su ejecución, exhibe la cadena, esta aparece entre dobles comillas y como un argumento de la función puts (put string, es decir, exhibir cadena).

2.1.2- Cadenas muy largas

Los siguientes dos programas ilustran el manejo de cadenas muy largas. En el primer caso se utiliza una diagonal invertida " \ " para indicar continuidad de la instrucción en la siguiente línea.

#include <stdio.h>

void main(void){

puts("Mi segundo \ programa en C"); }

En el siguiente programa se coloca toda la instrucción en una línea.

#include <stdio.h>

void main(void){

puts("Mi tercer programa en C"); }

2.1.3- Uso de varias salidas con la función puts() (exhibe o muestra cadena)

El siguiente programa usa la instrucción puts para mostrar un mensaje en la pantalla.

#include <stdio.h>

void main(void){

puts("Mi cuarto"); puts("programa en C"); }

2.2- Identificadores variables y constantes

Un identificador variable (o variable por brevedad) es un nombre que tiene asociado un valor que puede modificarse asignandole otro valor del mismo tipo, o uno que no cambia (identificador constante, o constante por brevedad). Los

Página 37 de 207

Page 38: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

identificadores deben empezar con una letra o un subguión y pueden tener hasta 64 caracteres; letras minúsculas y mayúsculas, dígitos y subguiones.

2.2.1- El Identificador variable de tipo carácter (char)El ejemplo siguiente ilustra el uso de cinco variables que almacenan cada una un carácter, es decir, se trata de variables de tipo carácter que se inician con un valor especifico en su declaración, también se dice que se inician en tiempo de compilación, lo cual significa que estas variables se inician cuando se compila el programa. Notése que las variables con sus valores aparecen en una lista precedida por la palabra reservada char y separadas por , (comas). Se indica el final de la lista con ; (punto y coma).

include <stdio.h>

void main(void){char ACa = 'H', BCa = 'o', CCa = 'l', DCa = 'a', ECa = '\0';

putchar(ACa); putchar(BCa); putchar(CCa); putchar(DCa); putchar(ECa); }

A la variable ACa se hace igual (=) al valor ’H’ (entre comillas simples para indicar un caracter) luego viene una , (coma ) y asi sucesivamente hasta que la lista termina con el carácter de control ‘\0’, el cual indica fin de cadena de caracteres (Hola). El punto y coma ; indica fin de lista.Este programa también ilustra el uso de la función putchar, la cual nos permite exhibir un carácter a la vez.

El siguiente ejemplo ilustra como iniciar cada variable de manera independiente, es decir, cada variable esta precedida del tipo char, se les asiga su valor correspondiente y termina con ; (punto y coma).

include <stdio.h>

void main(void){char ACa = 'H';char BCa = 'o'; char CCa = 'l';char DCa = 'a';char ECa = '\0';

putchar(ACa); putchar(BCa); putchar(CCa); putchar(DCa); putchar(ECa); }

Página 38 de 207

Page 39: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Otra forma alternativa del ejemplo, es el siguiente:

include <stdio.h> void main(void){

putchar('H'); putchar('o'); putchar('l'); putchar('a'); putchar('\0'); }

Los valores, no las variables, aparecen explícitamente como argumentos de la función putchar, en consecuencia no hay declaraciones.

2.2.2- Diferencias entre el carácter A y la cadena A

El carácter A se almacena en una variable de tipo carácter como el carácter A, pero la cadena A se almacena como una A seguida del carácter de control de fin de cadena.

caracter cadenaA A\0

Considérese las siguientes declaraciones, las cuales inician en tiempo de compilación a las variables correspondientes.

char AlfaCa = 'A'; char BetaCd[2] = "A";

En el primer caso se almacena el carácter A en la variable Alfa de tipo carácter. Notese que el carácter A esta entre comillas simples y que la cadena A esta entre comillas dobles. El siguiente diagrama ilustra esto.

AlfaCa

En el segundo caso se declara una cadena de caracteres, es decir, un vector con dos componentes de tipo carácter. El siguiente diagrama ilustra esto.

BetaCd[0]

BetaCd[1]

Obsérvese que en la posición 0 de la variable BetaCd[0] se almacena el carácter A, y en la posición 1 de la variable BetaCd[1], el carácter de control ( \0 ) que significa fin de cadena.

Considérese las siguientes observaciones:

+ Un carácter aparece entre comillas simples.

Página 39 de 207

A

\0

A

Page 40: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

+ Una cadena de caracteres aparece entre comillas dobles, en el ejemplo la + Un carácter se asigna a una variable simple, en este caso Alfa.

+ Una cadena de caracteres asigna a una variable compuesta de varias posiciones para los caracteres, en este caso dos, una posición para el carácter A, y otra para el carácter de fin de cadena ('\0'), de ahí que la variable BetaCd aparezca antecedida por [2].

+ Un vector, arreglo de una dimensión en C, tiene como primer posición el 0, luego el 1, etc. En el ejemplo, la posición BetaCd[0] contiene el carácter A y la posición BetaCd[1] contiene el carácter de control de fin de cadena \0. Este último carácter lo asigna el compilador automáticamente, por lo que siempre hay que proporcionar una posición adicional, además de las correspondientes a las de la cadena.

El siguiente programa inicia a la variable CadenaCd, en tiempo de compilación con la cadena “Hola” (entre doble comillas). Se indica que la variable tiene 5 posiciones [5] (5 entre corchetes), cuatro para la cadena y una posición adicional para el carácter de control que indica fin de cadena. Aunque este último no aparece explicitamente, el compilador se lo asigna automáticamente.

#include <stdio.h>

void main(void){ char CadenaCd[5] = "Hola";

puts (CadenaCd); }

La cadena Hola se almacena en la variable CadenaCd como sigue:

CadenaCd [0] = ‘H’CadenaCd [1] = ‘o’CadenaCd [2] = ‘l’CadenaCd [3] = ‘a’CadenaCd [4] = ‘\0’

Un carácter por posición. Obsérvese que el compilador asigna el carácter de control \0 (fin de cadena) al final de la misma.

En el ejemplo que sigue se omite el número de posiciones que puede tener como máximo la variable CadenaCd[], esto puede hacerse siempre y cuando la variable se inicie en tiempo de compilación como sigue:

#include <stdio.h>

void main(void){ char CadenaCd[] = "Hola";

Página 40 de 207

Page 41: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

puts(CadenaCd);}

Es un error tratar de hacer la siguiente asignación (tiempo de ejecución):

#include <stdio.h>

void main(void){ char CadenaCd[5];

CadenaCd = "Hola"; puts(CadenaCd);}

Notese que ahora es necesario declarar a la variable CadenaCd de 5 posiciones explicitamnete porque no se inicia en tiempo de compilación.

Es necesario hacer la asignación carácter por carácter tal como lo ilustra el siguiente ejemplo:

#include <stdio.h>

void main(void){ char Cadena[5];

CadenaCd[0] = ‘H’; CadenaCd[1] = ‘o’; CadenaCd[2] = ‘l’; CadenaCd[3] = ‘a’; CadenaCd[4] = ‘\0’;

puts(CadenaCd);}

o bien haciendo uso de la función de utilería strcpy.

#include <stdio.h>#include <string.h>

void main(void){ char CadenaCd[5];

strcpy(CadenaCd, "Hola"); puts(CadenaCd);}

Obsérvese que se ha incluido el archivo cabecera string.h, ya que la función strcpy se encuentra definida en este. La función tiene la siguiente forma general:

strcpy(cadena destino, cadena fuente)

Página 41 de 207

Page 42: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

la cadena fuente es la cadena que se quiere copiar en la cadena destino. La cadena fuente puede ser una cadena constante, como "Hola", o bien una variable arreglo de tipo char.

2.2.3- Lectura de una cadena de caracteres con la función gets() (lee cadena)

La instrucción gets (get string) nos permite leer una cadena que digitemos con el teclado.

#include <stdio.h>

void main(void){ char CadenaCd[] = "Digite una cadena"; puts (CadenaCd); gets (CadenaCd); puts (CadenaCd);}

El ejemplo siguiente exhibe carácter por carácter de la cadena.

#include <stdio.h>

void main(void){ char CadenaCd[] = "Hola";

putchar(CadenaCd[0]); putchar(CadenaCd[1]); putchar(CadenaCd[2]); putchar(CadenaCd[3]); putchar(CadenaCd[4]);}

2.2.4- Las funciones de lectura para un carácter

C tiene varias funciones para leer un carácter, estas se muestran a continuación:

Función Operacióngetchar() Lee un carácter de teclado. Espera un RETURNgetche() Lee un carácter con eco. No espera un RETURNgetch() Lee un carácter sin eco. No espera un RETURN

Todas estas funciones se utilizan para leer un carácter de teclado.

2.2.5- Exhibición de una cadena con la función printf()

Notése, en el ejemplo que sigue, que la función printf utiliza el formato s de string (cadena) para exhibir el valor de la variable CadenaCd.

Página 42 de 207

Page 43: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

#include <stdio.h>

void main(void){ char CadenaCd[] = "Digite un cadena";

printf("%s", CadenaCd); }

2.2.6- Cambio de línea con la función printf()

El siguiente ejemplo es el anterior, solo que ahora incluye el carácter de control \n (cambio de línea), con lo cual, luego de aparecer en pantalla Digite un cadenael cursor se posiciona al inicio de la siguiente línea.

#include <stdio.h>

void main(void){ char CadenaCd[] = "Digite un cadena";

printf("%s\n", CadenaCd); }

2.2.7- El formato s(string) para cadenas

La función printf puede incluir formatos que le indican al compilador de qué tipo es el valor de la variable que se va a exhibir. El siguiente programa ilustra esto para cadenas.

#include <stdio.h>

void main(void){ char CadenaCd[] = "Digite una cadena";

printf("%s", CadenaCd);}

2.3- Exhibición de datos con la función printf()

La forma general para la exhibición de datos con printf es la siguiente:

printf(cadena de control, arg1, ..., argn);

Donde la cadena de control contiene información de formato para arg1,..., argn que representan los datos de salida.

La información del formato consiste en caracteres de conversión precedidos por el símbolo %. Hay un carácter de conversión por cada argumento. La tabla siguiente lista estos caracteres de conversión.

Página 43 de 207

Page 44: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Caracter de

conversión

Significado

%c El valor del dato se exhibe como un caracter.%d El valor del dato se exhibe como un entero con signo.%e El valor del dato se exhibe como un real con exponente.%f El valor del dato se exhibe como un real sin exponente.%g El valor del dato se exhibe como un real usando conversión e o f lo

que resulte más corto.%i El valor del dato se exhibe como un real con signo.%o El valor del dato se exhibe como un entero octal.%s El valor del dato se exhibe como una cadena.%u El valor del dato se exhibe como un entero sin signo.%x El valor del dato se exhibe como un entero haxadecimal.

Enseguida se dan ejemplos que ilustran el uso de estos formatos.

El primer ejemplo ilustra el uso del formato para variables de tipo entero las cuales se inician en tiempo de compilación.

#include <stdio.h>

void main(void){ int AEn = 5, BEn = 7, CEn;

CEn = AEn +BEn; printf("%d + %d = %d", AEn, BEn, CEn);

}

El segundo ejemplo ilustra el uso del formato real.

#include <stdio.h> void main(void){ float AEn, BEn, CEn;

AEn = 5.2; BEn = 7.4; Cen = AEn + BEn; printf("%f + %f = %f", AEn, BEn, CEn);

}

2.4- Lectura de datos con la función scanf()

La forma general para la lectura de datos con scanf es

scanf(cadena de control, arg1, ... , argn);

Página 44 de 207

Page 45: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

donde la cadena de control contiene la información del formato para los arg1,..., argn, los que representan las variables para los datos de entrada.

La cadena de control contiene caracteres de conversión precedidos por el símbolo %. Hay un carácter de conversión por cada argumento. La tabla siguiente lista estos caracteres de conversión.

Caracter de

conversión

Significado

%c El valor del dato es un carácter.%d El valor del dato es un entero con signo.%e El valor del dato es un real con exponente.%f El valor del dato es real.%g El valor del dato es real.%h El valor del dato es un entero corto.%i El valor del dato es un entero.%o El valor del dato es un octal.%s El valor del dato es una cadena seguida de un carácter nulo (se

agrega al final automáticamente).%u El valor del dato es un entero sin signo.%x El valor del dato es un entero haxadecimal.

El ejemplo siguiente ilustra el uso de formatos con la función scanf, observe que las variables están precedidas por el símbolo &, con la excepción de las variables de tipo cadenas.

#include <stdio.h>

void main(void){ int AEn, BEn, CEn;

puts("Digite los valores de AEn y BEn"); scanf("%d %d", &AEn, &BEn); cEn = aEn + bEn; printf("%d + %d = %d", AEn, BEn, CEn);

}

He aquí otro ejemplo:

#include <stdio.h>

void main(void){ char CadenaCd[] = "El resultado es: ";

float ARe, BRe, CRe; puts("Dame los valores de ARe y BRe"); scanf("%f %f", &ARe, &BRe);

Página 45 de 207

Page 46: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

CRe = ARe + BRe; printf("%s %f", CadenaCd, CRe);

}

El ejemplo siguiente ilustra el uso de comentarios y del identificador constante const.

#include <stdio.h>

void main(void){ const PIReCn = 3.1416;

float RadioReCn = 5, LongitudRe, AreaRe, VolumenRe;

/* Cálculo de la longitud de la circunferencia: */ LongitudRe = RadioRe*PIReCn; /* Cálculo del área del circulo: */ AreaRe = RadioRe*RadioRe*PIReCn; /* Cálculo del volumen de la esfera: */

VolumenRe = (3/4)*PIReCn*RadioRe*RadioRe*RadioRe; /* Exhibición de los valores calculados: */ printf("Radio = %f\n", RadioRe); printf("Longitud = %f\n", LongitudRe); printf("Área = %f\n", AreaRe); printf("Volumen = %f\n", VolumenRe);

}

Página 46 de 207

Page 47: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 3

Arreglos y la Categoría de Figuras de Iteración

Página 47 de 207

Page 48: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 48 de 207

Page 49: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno modelara, codificara y correrá programas que incluyen algoritmos que utilizan la categoría de figuras de iteración.

Contenido

3.- Iteración3.0.-Introducción3.1.- Arreglos

3.1.1- Arreglos unidimensionales3.1.2- Arreglos multidimensionales3.1.3- Operadores de relación3.1.4- Los operadores de pre y post autoincremento3.1.5- Los operadores de pre y post autodecremento3.1.6- Notación corta

3.2.- Ciclos3.2.1- La instrucción for y sus variantes3.2.2- La instrucción while y sus variantes3.2.3- La instrucción while-do y sus variantes

3.3.- Diseño de programas con ciclos3.4.- Resumen3.5.- Ejercicios

Objetivos particulares

Al terminar éste capítulo, el alumno será capaz de utilizar:

1. Arreglos2. Los operadores de relación3. Los operadores de autoincremento4. Las figuras de iteración

Página 49 de 207

Page 50: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

3.0 Introducción

Los arreglos son estructuras compuestas homogeneas que pueden llegar a almacenar grandes volumenes de datos de un mismo tipo, por ejemplo, o enteros, o caracteres, o flotantes, o apuntadores etc. El lenguaje C, incluye a los arreglos como parte de su sintaxis así como las operaciones que pueden realizarse con ellos. Esto es muy conveniente ya que esto nos permite manipular con ellos estructuras matematicas de gran importancia en la ingeniería como son los vectores, las matrices, etc. y otras estructuras no matemáticas (simbolicas) de gran relevancia en la ingeniería y ciencias de la computación. En el lenguaje C tenemos asociados con los arreglos a los enunciados ciclicos y con estos a las expresiones de relación, así como a los operadores de pre y post autoincremento y de pre y post autodecremento.

3.1 Arreglos

Suponga que codifica un programa que lee 10 valores enteros para calcular su valor promedio y luego mostrar estos valores y su promedio, para ello ud. requiere declarar un total de 11 identificadores variables, 10 para los valores leidos y uno para el promedio. Lo mejor es declarar un arreglo, los cuales son estructuras de datos compuestas homogéneas (más de un valor del mismo tipo) con 10 elementos, uno por cada valor entero del promedio calculado.

3.1.1 Arreglos unidimensionales (vectores)

Un vector es una colección de valores del mismo tipo, es decir, una colección homogénea de valores. A cada valor se hace referencia por un nombre común a todos y un índice único para diferenciarlos entre si. El primer valor tiene asociado el índice 0, y el último el índice n -1, donde n es el número de valores del vector.

La forma general para declarar un vector es la siguiente:

tipo nombre_comun[nro de valores];

Ejemplo:

int AVcEn[10]; // El identificador AVcEn significa A es un Vector Entero.

El vector se declara con un total de 10 entradas, en las que se puede almacenar un entero en cada una de ellas, como se muestra enseguida, en el que se asigna un valor en cada entrada del vector.

AVcEn[0] = 3; AVcEn[1] = 7; AVcEn]2] = 1;

Página 50 de 207

Page 51: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

AVcEn[3] = 7; AVcEn[4] = 3; AVcEn[5] = 5; AVcEn[6] = 4; AVcEn[7] = 0; AVcEn[8] = 2; AVcEn[9] = 6;

Notese que en el lenguaje C el primer indice de todo vector es 0 y el último es n – 1.La Figura X siguiente muestra al vector AVcEn con 10 entradas – valores de tipo entero. Notese, en el listado de arriba y la Figura X, que el nombre del vector -AVcEn - designa una colección de valores enteros (3, 1, ... ,2, 6) y el indice (0, 1, ..., 8, 9) hace la difrencia de cada elemento, de modo que el primer elemento tiene como nombre – identificador variable – el de AVcEn[0] y el último el de AVcEn[9].

¿ Que es un vector (arreglo unidimensional) ?Es un identificador variable o constante que almacena un conjunto de datos homogéneos, es decir, del mismo tipo.

¿ El porque de la importancia de los arreglos ?permite realizar operaciones con grandes volúmenes de datos homogéneos con gran economia de codigo. Los arreglos son las estructuras de datos básicas para el computo científico.

¿ Como son los arreglos ?el nombre del vector -AVcEn - designa una colección de valores enteros (3, 1, ... ,2, 6) y el indice (0, 1, ..., 8, 9) hace la difrencia de cada elemento, de modo que el primer elemento tiene como nombre – identificador variable – el de AVcEn[0] y el último el de AVcEn[9].

3.1.2 Arreglos multidimensionales

Página 51 de 207

3

7

1

0

2

6

AVcEn[0]

AVcEn[n – 1]

Fig. Arreglo unidimensional – vector – de nombre AVcEn con 10 elementos homogéneos (de tipo entero) almacenados en cada entrada del vector.

Page 52: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

3.1.3- Operadores de relación

La tabla siguiente muestra los operadores de relación utilizados en C.

operador significado < menor que

<= menor o igual que > mayor

>= mayor o igual que == igual que =! difrente a

Por ejemplo:

A < B la expresión es verdadera si el valor de A es menor al valor en B, es decir; 5 < 7, en caso contrario es falsa, es decir; 7 < 5

A <= B la expresión es verdadera si el valor de A es menor o igual al valor en B, es decir; 5 <= 7 también es verdadera 5 <= 5,en caso contrario es falsa, es decir; 7 < = 5

A > B la expresión es verdadera si el valor de A es mayor al valor en B, es decir; 9 > 7, en caso contrario es falsa, es decir; 7 > 9

A >= B la expresión es verdadera si el valor de A es mayor o igual al valor en B, es decir; 9 >= 7 también es verdadera 9 >= 9,en caso contrario es falsa, es decir; 7 >= 9

A == B la expresión es verdadera si el valor de A es igual al valor en B, es decir; 7 == 7, en caso contrario es falsa, es decir; 7 == 5

A =! B la expresión es verdadera si el valor de A es diferente al valor en B, es decir; 5 =! 7 tambien es verdadera 7 =! 5,en caso contrario es falsa, es decir; 7 =! 7

3.1.4 Los operadores de pre y post autoincremento

Los operadores de pre y post autoincremento y autodecremento suman o restan uno respectivamente a una variable entera antes o después de usarse. Para ejemplificar, supongamos que la variable entera BetaEn fue iniciada con el valor de 5 para cada uno de los casos que se muestran enseguida.Los identificadores AlfaEn y BetaEn significan Alfa es un Entero y Beta es un Entero respectivamente.

Página 52 de 207

Page 53: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Ejemplo con el operador de post autoincremento

int BetaEn = 5, AlfaEn;AlfaEn = BetaEn++;

post significa que la variable BetaEn está precedida del operador de autoincremento (++). El efecto es el siguiente; primero la variable BetaEn asigna su valor de 5 a la variable AlfaEn y después se autoincrementa en uno. Es decir, AlfaEn acaba con el valor de 5 y BetaEn con el valor de 6.

Ejemplo con el operador de pre autoincremnto

int BetaEn = 5, AlfaEn;AlfaEn = ++BetaEn;

pre significa que la variable BetaEn está precedida por el operador de autoincremento (++). El efecto es el siguiente; primero la variable BetaEn se autoincrementa en uno su valor, de 5 a 6, luego asigna este valor a la varibale AlfaEn. Es decir, AlfaEn y BetaEn acaban con el valor de 6.

3.1.5 Los operadores de pre y post autodecremento

Ejemplo con el operador de post autodecremento

int BetaEn = 5, AlfaEn;AlfaEn = BetaEn--;

post significa que la variable BetaEn está precedida del operador de autodecremento (--). El efecto es el siguiente; primero la variable BetaEn asigna su valor de 5 a la variable AlfaEn y después se autodecrementa en uno. Es decir, AlfaEn acaba con el valor de 5 y BetaEn con el valor de 4.

Ejemplo con el operador de pre autodecremento

int BetaEn = 5, AlfaEn;AlfaEn = --BetaEn;

pre significa que la variable BetaEn está precedida por el operador de autodecremento (--). El efecto es el siguiente; primero la variable BetaEn se autodecrementa en uno su valor, de 5 a 4, luego asigna este valor a la varibale AlfaEn. Es decir, AlfaEn y BetaEn acaban con el valor de 4.

3.1.6 Notación corta

Los operadores anteriores incrementan y decrementan de 1 en 1, con los operadores de suma y resta respectivamente. C permite, además, simplificar la notación de algunas expresiones aritméticas que incluyen a los operadores aritméticos de suma, resta, producto y división.

Página 53 de 207

Page 54: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Considerese la expresión:

i = i + 5;

esta puede simplificarse anteponiendo el símbolo + al simbolo = y suprimiendo la segunda i que aparece en la asignación.

i += 5;

las mismas reglas pueden aplicarse a la resta, producto y división.

resta

i = i – 5;i -= 5

producto

i = i * 5;i *= 5

división

i = i / 5;i /= 5;

3.2 Ciclos

Los ciclos son una categoría de encunciados de figuras de control que nos permiten realizar un enunciado o una secuencia de estos una o más veces, es decir, podemos repetir la realización de un enunciado o de una secuencia de ellos n veces, donde n esta determinada por una relación. En esta categoria tenemos tres enunciados iterativos

3.2.1 El enunciado iterativo for

El enunciado for es una figura de control iterativa que nos permite la ejecución repetida de uno o más enunciados, que se encuentran en su alcance.

Su forma general, del enunciado for, es el siguiente:

for(iniciación; condición; incremento/decremento) enunciado(s)

El diagrama siguiente ilustra el flujo de control de esta figura iterativa.

Primero la variable de control (VarCon) se inicia con un valor inicial (Inicia VarCon), luego se verifica si la Condición es cierta, si es así el flujo de control pasa a el (los) Enunciado(s), enseguida la variable de control se

Página 54 de 207

Page 55: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

autoincrementa o autodecrementa y se inicia otro ciclo. Si la condición es falsa, el flujo de control esta fuera del alcance de la instrucción for.

Considerese el ejemplo siguiente:

// Este programa asigna 10 valores enteros a los elementos de un arreglo // AVcEn, luego los exhibe en el monitor.

#include <stdio.h>

void main(void){ int AVcEn[10], IndiceEn;

/* Se asignan valores, del 0 al 9, al vector AVcEn */ for(IndiceEn = 0; IndiceEn < 10; IndiceEn ++)

AVcEn[IndiceEn] = IndiceEn; /* Se exhiben los valores del vector AVcEn */ for(IndiceEn = 0; IndiceEn < 10; IndiceEn ++) printf("%d", AVcEn[IndiceEn]);}

El diagrama siguiente ilustra el flujo de control, o la ejecución, del primer ciclo.

Página 55 de 207

VarConEn < 10

VarConEn = 0

AVcEn[VarConEn] = VarConEn

VarConEn++

Condición

Enunciado(s)

CondiciónInc/Dec

VarCon

Inicia

VarCon FalsaVerdadera

Page 56: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El siguiente diagrama ilustra el flujo de control o de ejecución del segundo ciclo.

El siguiente programa calcula el promedio de 10 valores enteros. Obsérvese que todos los valores (asignados y calculados) son enteros.

#include <stdio.h>

void main(void){ int IndiceEn, PromedioEn, TempEn, AVcEn[10];

/* Se leen los elementos de AVcEn: */ puts("Dame los elementos de A separados por un blanco"); for(IndiceEn = 0; IndiceEn < 10; IndiceEn ++)

scanf("%d", &AVcEn[IndiceEn]); /* Se suman los valores de AVcEn en TempEn: */ for(IndiceEn = 0; IndiceEn < 10; IndiceEn ++)

TempEn += AVcEn[IndiceEn]; /* Se calcula el valor promedio: */

PromedioEn = TempEn/10; /* Se imprime el valor promedio */

printf("%d", PromedioEn); }

La directiva define

Esta directiva usualmente se utiliza para sustituir identificadores crípticos (poco legilbles) por otros más legibles. El ejemplo siguiente ilustra el uso de la directiva define, en este caso se sustituye al operador de relación != por la frase más legible NO_ES y el carácter fin de cadena ‘\0’ se sustituye por la frase más legible FIN_DE_CADENA. Los identificadores NO_ES y FIN_DE_CADENA actúan como sustitutos de los identificadores != y ‘\0’ respectivamente. Notése que la condición

cadenaCd[iEn] NO_ES FIN_DE_CADENA

es más legible que la condición equivalente (pero más críptica)

Página 56 de 207

IndiceEn < 10

IndiceEn = 0

printf("%d", AVcEn[IndiceEn])

IndiceEn ++

Page 57: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

cadenaCd[iEn] != ‘\0’ #include <stdio.h> #define NO_ES != #define FIN_DE_CADENA ‘\0’

void main(void){ char CadenaCd[] = "Este es un mensaje"; int IndiceEn;

for(IndiceEn = 0; CadenaCd[IndiceEn] NO_ES FIN_DE_CADENA; IndiceEn++)

printf("%c", CadenaCd[IndiceEn]);}

El siguiente ejemplo usa otra directiva define para definir al sustituto BLANCO. Los sustitutos definidos por un define no son variables. Por otra parte este ejemplo ilustra el uso de la instrucción for sin instrucciones a su alcance.

#include <stdio.h>#define BLANCO ' '#define NO_ES !=

void main(void){ char CadenaCd[10];

int IndiceEn;

puts("Digite una cadena"); gets(CadenaCd); for(IndiceEn = 0; CadenaCd[iEn] NO_ES BLANCO; IndiceEn++); printf("La posición del primer blanco es: %d ", IndiceEn);

}

El ejemplo que sigue ilustra el uso de la instrucción for sin la parte de iniciación.

#include <stdio.h>#define NO_ES !=

void main(void){ char CaraCa;

for(CaraCa = 'X'; NO_ES 'A';) CaraCa = getche();

}

El ejemplo que sigue ilustra el uso de la instrucción for sin la parte de iniciación y de autoincremento/autodecremento.

#include<stdio.h>main()#define NO_ES !=void main(void){ char CaraCa = 'X';

for(;CaraCa NO_ES 'A';)

Página 57 de 207

Page 58: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

CaraCa = getche();}

El programa siguiente invierte la cadena ABCDEF a FEDCBA.

#include<stdio.h>void main(void){

char CadenaCd[] = "ABCDEF", TempCa; int IndiceIEn, IndiceJEn = 6;

puts(CadenaCd); for(IndiceIEn = 0; IndiceIEn < 3; IndiceIEn++){

TempCa = CadenaCd[IndiceIEn];CadenaCd[IndiceIEn] = CadenaCd[IndiceJEn];

CadenaCd[IndiceJEn--] = TempCa; }

puts(CadenaCd); }

El programa siguiente hace lo mismo que el anterior, pero ilustra el hecho de que en la parte de iniciación pueden iniciarse más de una variable, y en la parte de autoincremento/autodecremento pueden autoincrementarse/autodecrementarse más de una variable.

#include<stdio.h>

void main(void){ char CadenaCd[] = "ABCDEF", TempCa;

int IndiceIEn, IndiceJEn = 6;

puts(CadenaCd); for(IndiceIEn = 0; IndiceJEn =6; IndiceIEn < 3; IndiceIEn++, IndiceEn--){

TempCa = CadenaCd[IndiceIEn];CadenaCd[IndiceIEn] = CadenaCd[IndiceJEn];

CadenaCd[IndiceJEn--] = TempCa; }

puts(CadenaCd); }

El siguiente ejemplo ilustra la lectura y exhibición de un vector.

#include <stdio.h> #include <conio.h>

void main(void){ int AVcEn[5], IndiceEn;

clrscr(); for(IndiceEn = 0; IndiceEn < 4; IndiceEn++) scanf("%d", &AVcEn[IndiceEn]);

for(IndiceEn = 0; IndiceEn < 4; IndiceEn++) printf("%d", AVcEn[IndiceEn]);

}

Página 58 de 207

Page 59: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El siguiente ejemplo ilustra la iniciación de vectores en tiempo de compilación. En este caso no es necesario especificar explícitamente el número de elementos de los vectores que se inician en tiempo de compilación, ya que el compilador se encarga de hacer esto.

#include <stdio.h>

void main(void){ int AVcEn[] = {3, 7, 8, 9, 15, 2}, BVcEn[] = {3, 4, 6, 5, 2, 0}, CVcEn[6] ; int IndiceEn;

for(IndiceEn = 0; IndiceEn < 6; IndiceEn IndiceEn++) CVcEn[IndiceEn] = AVcEn[IndiceEn] + BVcEn[IndiceEn]; for(IndiceEn = 0; IndiceEn < 6; IndiceEn++) printf("%d ", CVcEn[IndiceEn]); }

El ejemplo que sigue ilustra la lectura y exhibición de una matriz.

#include <stdio.h>

void main(void){ int AMtEn[3][3], IndiceIEn, IndiceKEn;

/* Lectura de la matriz AMtEn */ for(IndiceIEn = 0; IndiceIEn < 3; IndiceIEn++) for(IndiceKEn = 0; IndiceKEn < 3; IndiceKEn++) scanf("%d", &AMtEn[IndiceIEn][ IndiceKEn]); /* Exhibicion de la matriz AmtEn */ for(IndiceIEn = 0; IndiceIEn < 3; IndiceIEn++){ for(IndiceKEn = 0; IndiceKEn < 3; IndiceKEn++)

printf("%d", AMtEn[IndiceIEn][ IndiceKEn]); printf("\n");

} }

El ejemplo siguiente suma dos matrices, e ilustra también la iniciación de arreglos de dos dimensiones (matrices), obsérvese que se omite especificar la primera dimensión de las matrices, esto es opcional.

#include <stdio.h>

void main(void){ int AMtEn[][3] = {3, 4, 6, 6, 7, 8, 7, 8, 5},

BMtEn[][3] = {0, 3, 5, 6, 7, 4, 11, 10, 5},

CMtEn[3][3]; int IndiceIEn, IndiceKEn;

Página 59 de 207

Page 60: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

/* Suma de las matrices AMtEn y BMtEn */ for(IndiceIEn = 0; IndiceIEn <3; IndiceEn IndiceIEn++) for(IndiceKEn = 0; IndiceKEn < 3; IndiceKEn++)

CMtEn[IndiceIEn][IndiceKEn] = AMtEn[IndiceIEn][IndiceKEn] + BMtEn[IndiceIEn][IndiceKEn];

/* Exhibición de la matriz resultante: CMtEn */ for(IndiceIEn = 0; IndiceIEn < 3; IndiceIEn++){ for(IndiceKEn = 0; IndiceKEn < 3; IndiceKEn++)

printf("%d", CMtEn[IndiceIEn][IndiceKEn]); printf("\n ");

} }

3.2.2 El enunciado iterativo while

El enunciado while es otro enunciado iterativo que nos permite ejecutar uno o más enunciados, que se encuentran en su alcance, cero o una ó mas veces. El siguiente diagrama muestra el curso del flujo en la ejecución de este enunciado. Si la condicion es verdadera se ejecutan los enunciados en su alcance, de lo contrario el curso del flujo pasa al siguiente enunciado al while.

La sintaxis de este enunciado es la siguiente:

while (condición) enunciado(s)

El siguiente ejemplo hace uso de un enunciado while.

#include <stdio.h>

void main(void){ char CaraCa = ‘A’;

while(CaraCa != 'X');CaraCa = getche()

}

Página 60 de 207

Condición

Enunciado(s)

FalsaVerdadera

Page 61: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El ejemplo que sigue es equivalente al anterior. Notese que el enunciado bajo el alcance del while ahora aparece como parte de la condición del enunciado while.

#include <stdio.h>

void main(void){ char CaraCa;

while((CaraCa = getche()) != 'X');}

El enunciado for es completamente equivalente al enunciado while cuando no tiene parte de iniciación y de autoincremento/autodecremento. Como se ilustra en el siguiente ejemplo:

#include <stdio.h>

void main(void){ char CaraCa;

for(; (CaraCa = getche()) != 'X' ;);}

3.2.3 El enunciado iterativo do-while

Página 61 de 207

Page 62: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El enunciado do-while es también otro enunciado iterativo que nos permite ejecutar uno o más enunciados, que se encuentran en su alcance, una ó mas veces. El siguiente diagrama muestra el curso del flujo en la ejecución de este enunciado. Si la condición es verdadera se ejecutan los enunciados en su alcance, de lo contrario el curso del flujo pasa al siguiente enunciado al del do-while.

y la sintaxis del enunciado do-while es la siguiente:

doenunciado(s)

while (condición);

El siguiente ejemplo simple ilustra el uso del enunciado do-while. En el alcance del enunciado del do-while solo se encuentra un enunciado: la lectura de un número entero (gris oscuro). La condición (gris claro) verifica si ese número es menor o igual a 10, si es el caso, se vuelve a realizar la lectura, en caso contrario termina la ejecución del programa.

#include <stdio.h>

void main(void){ int NroEn;

do{ scanf("%d", &NroEn); }while(NroEn <= 10); }

El ejemplo que sigue, algo más elaborado que el anterior, muestra en la pantalla del monitor un menú con tres opciones y una salida que indica el fin de la ejecución del programa. La condición verifica que la elección hecha este entre 1 y 4, en caso contrario vuele a mostrarse el menú solicitando una nueva elección de parte del usuario#include <stdlib.h>#include <conio.h>

Página 62 de 207

Condición

Enunciado(s)

Page 63: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

void main(void){char LeyendasArCa[4][16] = {{"Soy la opcion 1"},

{"Soy la opcion 2"}, {"Soy la opcion 3"}, {"Se acabo ......"}};

int OpcionEn;

do{printf("1. Opción_1\n");printf("2. Opción_2\n");printf("3. Opción_3\n");printf("4. Salida\n");printf("Seleccione un numero: ");scanf("%d", &OpcionEn);printf("\n");

}while (!((OpcionEn >= 1) && (OpcionEn <= 4)));

printf("%s\n", LeyendasArCa[OpcionEn - 1]);}3.9 Las instrucciones break y continue

Estas instrucciones, clasificadas como de salida, son una forma de gotos. El ejemplo siguiente ilustra el uso de estas instrucciones.

Se procesa una cadena de texto de la siguiente manera; se lee un carácter de una cadena y se exhibe en pantalla excepto por las tres condiciones siguientes:

1. Si el caracter es un punto " . " se inserta un blanco después del punto en la cadena de salida.

2. Si el caracter es una diagonal " / " avanzamos el cursor a la siguiente posición del tabulador.

3. Si hay dos diagonales consecutivas, se avanza el cursor al inicio de la siguiente línea.

Ejemplo:

#include <stdio.h>#include <conio.h>

void main(void){ char sCd[] = " Este/ es/ un// mensaje. Para/ todo/ mundo.// "; int iEn, xEn, yEn; char cxCa;

clrscr(); iEn = 0; gotoxy(1, 10); while (1){

Página 63 de 207

Page 64: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

cxCa = sCd[iEn++]; if(cxCa == '/'){ printf("\n"); continue; }else{ xEn = wherex(); yEn = wherey(); }

} if (cxCa == '.') printf(" "); getche(); }

Página 64 de 207

Page 65: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 4

Página 65 de 207

Page 66: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Operadores de Relación, Lógicos y la Categoría de Figuras de Decisión

Objetivo general

El alumno modelara, codificara y correrá programas que incluyen algoritmos que requieren enunciados condicionales derivados del uso de árboles sistémicos.

Página 66 de 207

Page 67: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Contenido

4.0.- Introducción4.1.- Los operadores lógicos básicos

4.1.1 I ntroducción4.1.2 La tabla de verdad para el operador lógico OR4.1.3 La tabla de verdad para el operador lógico AND4.1.4 La tabla de verdad para el operador lógico NOT

4.2.- Diagramas de flujo y el enunciado if-else4.2.1 Introducción4.2.2 Diagramas de flujo4.2.3 El enunciado if_else

4.3.- Diseño de decisiones con árboles sistémicos, parte I4.3.1 Introducción4.3.2 El árbol básico4.3.3 Ejemplos

4.4.- Diseño de decisiones con árboles sistémicos, parte II4.4.1 Introducción4.4.2 Ejemplos

4.5.- Diseño de decisiones con árboles sistémicos, parte III4.5.1 Introducción4.5.2 Reglas 1 y 24.5.3 El proceso cosecuencial

4.6.- Diseño de decisiones con árboles sistémicos, parte IV4.5.1 Introducción4.5.2 Los enunciados switch y break4.5.3 El enunciado continue

Objetivos especificos

Luego de leer y estudiar cuidadosamente el material de esta unidad, usted tendrá las habilidades necesarias para:

1. Escribir expresiones lógicas correctas que utilizan operadores de relación y/ooperadores lógicos.

2. Hacer la prueba de escritorio de programas que usen enunciados de decisión 3. Planificar y escribir código correcto utilizando como referencia el árbol

sistémico4. Reconocer la estrategia de divide y venceras en los árboles sistémicos.5. Reconocer y valorar la utilidad del árbol sistémico en algoritmos que requieren

enunciados condicionales.

4.1 Los operadores lógicos básicos

Página 67 de 207

Page 68: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.1.1 Introducción

Un identificador lógico o boleano en el lenguaje C/C++ solo puede asumir uno de dos valores, el valor entero 0 (Falso) o el valor entero 1 (Verdadero). El operador lógico || es binario porque tiene dos operandos, uno a cada lado, por ejemplo en la expresión A || B, es decir A o B, los operandos son A y B.

La tabla siguiente muestra los operadores lógicos o boleanos en el lenguaje C/C++.

4.1.2 La tabla de verdad para el operador lógico OR

A continuación tenemos la tabla de verdad de la expresión lógica A || B. Las dos primeras columnas muestran todas las combinaciones posibles (horizontalmente, lo sombreado) de valores de verdad para la expresión. La última columna es el resultado de evaluar la expresión para cada combinación correspondiente.

Por ejemplo, si consideramos la primera combinación, es decir; si A = 0 (Falso) y B = 0 (Falso), entonces la expresión A || B, es decir A o B, se evalua como 0 (Falso), Para las siguientes tres combinaciones observése que la expresión se evalua como 1 (Verdadero).

Otro ejemplo, si en la expresión lógica

A || (B || C), tenemos que A = 1, B = 0 y C = 0

por prioridad primero se evalua la subexpresión

(B || C)

Notese que hay coincidencia entre los valores de B y C, y los de la primera combinación en la tabla del y lógico, por lo que tenemos como resultado 0. Luego se evalua la expresión

A || (0)

Operador Significado || O lógico && Y lógico ¡ No lógico

Valor lógico asignado al operando A

Valor lógico asigando al operando B

Resultado de evaluar la expresión lógica A || B

A = 0 B = 0 0 A = 0 B = 1 1 A = 1 B = 0 1 A = 1 B = 1 1

Página 68 de 207

Page 69: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Notese que hay coincidencia entre los valores de A y (0), y los de la tercera combinación en la tabla del o lógico, con lo que tenemos como resultado para toda la expresión el valor de verdad 1 (Verdadero).

4.1.3 La tabla de verdad para el operador lógico AND

A continuación se muestra la tabla de verdad de la expresión lógica A && B, es decir A y B. Al igual que en la tabla para el operador lógico ||, las dos primeras columnas muestran todas las combinaciones posibles (horizontalmente, lo sombreado) de valores de verdad para la expresión. La última columna es el resultado de evaluar la expresión para cada combinación correspondiente.

Por ejemplo, ahora consideramos la última combinación, es decir; si A = 1 (Verdadero) y B = 1 (Verdadero), entonces la expresión A && B, es decir A y B, se evalua como 1 (Verdadera), Para las primeras tres combinaciones observese que la expresión se evalua como 0 (Falso).

Otro ejemplo, si en la expresión lógica

A && (B || C), tenemos que A = 1, B = 0 y C = 0

por prioridad primero se evalua la subexpresión

(B || C)

Notese que hay coincidencia entre los valores de B y c, y los de la primera combinación en la tabla del o lógico, por lo que tenemos como resultado 0. Luego se evalua la expresión

A && (0)

Notese que hay coincidencia entre los valores de A y (0), y los de la tercera combinación en la tabla del y lógico, con lo que tenemos como resultado para toda la expresión el valor de verdad 0 (Falso).

4.1.4 La tabla de verdad para el operador lógico NOT

Por último, tenemos a la tabla de verdad de la negación lógica, por ejemplo, en la expresión lógica !A, si el valor entero de A es 0, su negación lógica da como

Valor lógico asigando al operando A

Valor lógico asigando al operando B

Resultado de evaluar la expresión lógica A && B

A = 0 B = 0 0 A = 0 B = 1 0 A = 1 B = 0 0 A = 1 B = 1 1

Página 69 de 207

Page 70: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

resultado 1. Si el valor entero de A es 1, su negación lógica da como resultado 0. Esto se resume en la siguiente tabla.

Consideremos la siguiente expresión lógica para su evaluación de acuerdo a las tablas de verdad básicas previas

A || (¡B && C), donde A = 0, B = 0 y C = 1

Primero se evalua, por razones de prioridad, la subexpresión

¡B

la que de acuerdo a la primera combinación de la tabla de la negación lógica el resultado es 1.

Luego se evalua la subexpresión

(1 && C)

la que de acuerdo con la cuarta combinación de la tabla de verdad para el y lógico el resultado es 1. Finalmente se evalua la expresión

A || (1)

la que acuerdo con la segunda combinación de la tabla de verdad para el o lógico el resultado es 1.

Cualquier otra expresión lógica que incluya solo operadores lógicos puede ser evaluada de manera similar.

4.2 Diagramas de flujo y el enunciado if – else

4.2.1 Introducción

Valor lógico asigando al operando A

Resultado de evaluar la expresión lógica ¡ A

A = 0 1 A = 1 0

Página 70 de 207

Page 71: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Suponga que esta codificando un programa que admite una larga lista de números enteros. El programa debe de contar el número de enteros pares (Contador_pares) y el número de enteros impares (Contador_nones) que ingresan. Antes de incrementar uno de los contadores debe tomarse una decisión para determinar que contador incrementar cada vez que ingresa un entero. Este es un ejemplo en el que se requiere de un enunciado condicional.

4.2.2 Diagramas de flujo

Es característico de un enunciado condicional ejecutar otro(s) enunciado(s) si se cumple una condición predeterminada como lo muestra el siguiente diagrama de flujo: si la Condición es Verdadera se ejecuta(n) los Enunciado(s)_B, en caso contrario se ejecutan los Enunciado(s)_A

Como un ejemplo consideremos el problema enunciado en la introducción de esta unidad, el cual queda como sigue - en términos de un diagrama de flujo. Notése que en la condición - Nro%2 == 0 - se utiliza el operador módulo (%) para verificar si el valor es par o impar. El operador módulo es un operador binario por tener dos operandos, uno a la izquierda (en nuestro caso Nro) y otro a la derecha (en nuestro caso 2).

Página 71 de 207

Nro%2 == 0

Contador_Nones++ Contador_Pares++

Falso Verdadero

Condición

Enunciado(s)_A Enunciado(s)_B

Falsa Verdadera

Page 72: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

En esta unidad el alumno aprendera a diseñar decisiones utilizando el árbol sistémico. Esta habilidad será particularmente de gran importancia en algoritmos en los que intervienen enunciados de decisión.

4.2.3 El enunciado if - else

La instrucción if nos permite tomar una de dos acciones, la forma general de la instrucción if es la siguiente:

if(condición) instrucción(es)_Aelse instrucción(es)_B

Esta forma de dos alternancias tiene una forma particular: una alternancia.

if(condición) instrucció(es)

La primera forma tiene también una forma general que aparece con frecuencia en las aplicaciones: la alternancia múltiple, la cual tiene la forma siguiente:

if(condición_A) instrucción(es)_Aelse if(condición_B) instrucción(es)_Belse if(condición_C)- - - - - - - - -else if(condición_Y) instrucción(es)_Yelse instrucción(es)_A

El ejemplo siguiente usa una instrucción if de dos alternancias para comparar dos valores enteros. Se imprime el valor menor.

#include <stdio.h>void main(void){ int AEn, BEn;

Página 72 de 207

Page 73: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

/* Lectura de los valores de AEn y BEn */ scanf("%d %d", &AEn, &BEn); /* Comparación de los valores de AEn y BEn */ if(AEn <= BEn) printf("%d ", AEn); else /* AEn > BEn */ printf("%d ", BEn);}

El ejemplo siguiente es una generalización del anterior, incluye un if con alternancias múltiples, se exhibe el valor de la variable que sea menor ó los valores de las dos variables si estos son iguales.

#include <stdio.h>

void main(void){ int AEn, BEn;

/* Lectura de los valores de AEn y BEn */ scanf("%d %d", &AEn, &BEn); /* Comparación de los valores de AEn y BEn */

if(AEn < BEn) printf("%d ", AEn);

else if(AEn == BEn) printf("%d %d", AEn, BEn);

else /* AEn > Ben */ printf("%d ", BEn);

}

4.3 Diseño de decisiones con árboles S, parte I

4.3.1 Introducción

Página 73 de 207

Page 74: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Los árboles de decisión han sido una de las herramientas de la ingeniería programática (sistemas de software) de poco uso en la practica. En la literatura el diseño de un árbol de decisión se presenta de manera prácticamente intuitiva, se enfatiza más su aspecto gráfico como una gran ventaja y no su planteamiento sistemático. En esta unidad y las tres siguientes, hacemos uso de los árboles sistémicos – árboles S – los cuales son estructuras formales que modelan, la solución de un problema. Estas estructuras utilizan intrinsicamente la estrategia de divide y vencerás. Por lo que son un excelente ejemplo de esta estrategia, la cual es de uso común en todo diseño e implementación de cualquier algoritmo, por lo que el dominio de esta estrategia y su herramienta de parte del aprendiente debe de otorgarle una mayor habilidad para el diseño e implementación de estos.

El nombre de árbol sistémico – o árbol S - es en realidad el nombre de un modelo didáctico ontológico, derivado con la metodología de la programática educacional. Este MODO consta de una definición, cuatro reglas y por supuesto de la estructura de árbol al cual se aplican la definicón y las reglas.

El aprendiente debe estar consciente de que su éxito en el diseño de árboles S depende de que sea disciplinado (dedicado y sistemático) en el uso de ellos, es decir, debe resolver suficientes problemas de esta categoría aplicando las reglas rigurosamente en cada caso.

4.3.2 El árbol básico

Se introducen dos definiciones y tres reglas para la obtención y síntesis de un árbol S.

La figura siguiente muestra un árbol S simple (un solo nivel de nodos o puntos de descisión). Bajo el alcance (debajo) de cada nodo de descisión se encuentra la hoja o acción que se toma bajo la descisión correspondiente.

Se ilustra ahora, con un ejemplo simple, la definición dada.

4.3.3 Ejemplos

Página 74 de 207

Definición 1. Un árbol S básico es una jerarquía de nodos (puntos de decisión), los que a su vez originan otros nodos u hojas (acciones). Es condición necesaria y suficiente que en un árbol S básico solo aparezcan en sus nodos los operadores de relación <, =

opdoA < opdoB opdoA = opdoB opdoA > opdoB

acción A acción B acción C

Page 75: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Sean AEn y BEn dos enteros, se exhibe el menor de ellos o ambos si son iguales.

Al comparar a AEn y BEn para saber cual es menor o si son iguales, solo caben las tres siguientes posiblidades:

AEn < BEn AEn = BEn AEn > BEn

Para el primer caso, AEn resulta ser la variable con el menor valor, por lo que se exhibe este valor. En el segundo caso resulta que los valores de AEn y BEn son iguales por lo que se exhiben ambos, y en el tercer caso, la variable con el menor valor es BEn por lo ser exhibe el valor de esta variable. El árbol S básico resultante es el siguiente:

Lo sorprendente es que un arbol de decision es la forma grafica de un condicional, para apreciar esto integremos al arbol el condicional correspondiente como sigue:

El codigo correspondiente a este árbol se muestra enseguida

if(AEn < BEn) printf(“%d”, AEn); else if(AEn == BEn)

Página 75 de 207

AEn < BEn AEn = BEn AEn > BEn

Exhibir AEn Exhibir AEn y BEn Exhibir CEn

If(AEn < BEn) else If(AEn == BEn) else // (AEn > BEn)

Exhibir AEn Exhibir AEn y BEn Exhibir CEn

Page 76: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf(“%dn %d”, AEn, BEn); else//AEn > BEn printf(“%d”, BEn); Notése la correspondencia tan directa que existe entre el arbol de decision y el codigo que le corresponde. Observe tambien que el problema es resuelto mediante el árbol y no directamente con el código. Estas cualidades, y otras, son las que hacen tan útiles a los árboles de decisión en el diseño de decisiones.

Para mostrar otra de las cualidades de los arboles de decisión, la de subdividir un problema en subproblemas más simples de resolver, consideremos una generalización del problema anterior.

Sean AEn, BEn y CEn variables enteras, se exhibe la menor de ellas, o dos de ellas si son iguales y menores a la tercera, o las tres si son iguales.

Considerar todas las posibles comparaciones que puedan darse entre las tres variables puede ser problematico, por lo que consideremos primero comparar a las variables AEn y BEn, por el ejemplo anterior nos percatamos que este problema (subproblema) ya lo tenemos resuelto

Ahora consideremos uno a uno, los tres posibles casos, yendo de izquierda a derecha. Empecemos con AEn < BEn, la comparación nos dice que AEn tiene un valor menor que BEn, por lo que en el siguiente nivel inferior debemos comparar a AEn con CEn, es decir :

Consideremos ahora a A = B, puesto que ambos son iguales podemos tomar a cualquiera de las dos variables y compararla con C, por ejemplo:

Página 76 de 207

AEn < BEn AEn = BEn AEn > BEn

A > CA < C A = C

A < B A = B A > B

A < C A = C A > CA > CA < C A = C

A < B A = B A > B

Page 77: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Consideremos ahora a A > B, la comparacion nos dice que la variable con el menor valor es B, por lo que debemos comparar a B con C en el siguiente nivel, es decir:

Notese que el problema original lo hemos subdividido en dos subproblemas mas faciles de tratar, en el primero comparamos solo a A y B, primer nivel del arbol, en el segundo subproblema, comparamos a C con quien resulte menor al comparar a A y B, segundo nivel del arbol.

Finalmente consideremos las acciones que se deben de tomar bajo cada una de las rutas de las condiciones, empezando desde la raiz hasta la accion correspondiente. Por ejemplo, la ruta dada por las decisiones A < B y A < C nos dice que la variable A tiene el valor menor, considerando de la misma manera cada ruta tenemos por consiguiente:

Página 77 de 207

B > CB < C B = CA < C A = C A > CA > CA < C A = C

A < B A = B A > B

ExhibeA

A > CA < C A = C

ExhibeA y C ExhibeC ExhibeB ExhibeB y C ExhibeC

B > CB < C B = C

ExhibeA y B ExhibeCExhibe A,B y C

A < C A = C A > C

A < B A = B A > B

Page 78: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El siguiente ejemplo es una generalización del anterior, incluye 3 if con alternancias múltiples anidadas en otro if con alternancia múltiple, se imprime el valor de la variable que resulte menor, o los valores de dos de ellas si estos son iguales y menores a la tercera, o los valores de las tres si estas son iguales.

#include <stdio.h>void main(void){ int AEn, BEn, CEn;

/* Lectura de los valores de AEn, BEn, CEn */ scanf("%d %d %d", &Aen, &BEn, &Cen); /* Comparación de los valores de AEn, BEn, CEn */ if(AEn < BEn) if(AEn < CEn) printf("%d ", AEn); else if(AEn == CEn) printf("%d %d ", AEn, CEn);

else /* Aen > CEn */ printf("%d ", CEn) else if(AEn == BEn) if(Aen < Cen) printf("%d %d ", AEn, BEn); else if(AEn == CEn) printf("%d %d %d ", AEn, BEn, CEn); else /* AEn > CEn */ printf("%d ", CEn); else /* AEn > BEn */ if (BEn < CEn) printf("%d ", BEn); else if(BEn == CEn) printf("%d %d ", BEn, CEn); else /* BEn > CEn */ printf("%d ", CEn);

}

4.4 Diseño de decisiones con árboles S, parte II

4.4.1 Introducción

En los ejemplos anteriores hemos vistyo que los árboles sistémicos son una excelente herramienta para el diseño de desiciones en la programación estructurada. Por otra parte es una herramienta que incorpora e manera intrinsica la estrategia de divede y vencerás. Esta estrategia es de uso muy común en el diseño de algoritmos. En esta segunda parte continuamos con el diseño de descisiones con árboles S. Se presentan dos ejemplos, el primero es una generalización del último ejemplo visto en la parte I y el segundo es una generalización del primer ejemplo visto en esta segunda parte.

Página 78 de 207

Page 79: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.4.2. Ejemplos

Se intercalan los valores enteros de dos vectores en un tercer vector. Los elementos enteros de los vectores AVcEn y BVcEn están ordenados de menor a mayor. Los elementos del vector resultante CVcEn también están ordenados de menor a mayor. Se permiten que aparezcan enteros repetidos en los vectores.

#include <stdio.h>

void main(void){ int AVcEn[10], BVcEn[10], CVcEn{20]; int IndiceIEn, IndiceJEn, IndiceKEn, LonAVcEn = 5, LonBVcEn = 8;

/* Lectura de los valores del vector AVcEn */ for(IndiceIEn = 0; IndiceIEn < LonAVcEn; IndiceEn++) scanf("%d", &AVcEn[IndiceIEn]);

/* Lectura de los valores del vector BVcEn */ for(IndiceJEn = 0; IndiceJEn < LonBVcEn; IndiceJEn++) scanf("%d", &BVcEn[IndiceJEn]);

IndiceIEn = IndiceJEn = IndiceKEn =0;

/* Comparación de los valores de los vectores AVcEn y BVcEn */ for(;IndiceIEn <= LonAVcEn;) if(AVcEn[IndiceIEn] < BVcEn[IndiceJEn]) CVcEn[IndiceKEn++] = AVcEn[IndiceIEn++]; else if(AVcEn[IndiceIEn] == BVcEn[IndiceJEn]){ CVcEn[IndiceKEn++] = AVcEn[IndiceIEn++]; CVcEn[IndiceKEn++] = BVcEn[IndiceJEn++]; }else /* AVcEn[IndiceIEn] > BVcEn[IndiceJEn] */ CVcEn[IndiceKEn++] = BVcEn[IndiceJEn++];

/* Exhibición del vector resultante*/ for(IndiceIEn = 0; IndiceIEn < (LonAVcEn + LonBVcEn); IndiceIEn++) printf("%d ", CVcEn[IndiceIEn]);

}

Página 79 de 207

AVcEn < BVcEnj AVcEni = BVcEnj AVcEni > BVcEnj

DVcEn [lEn] BVcEn [jEn]lEn lEn+1jEn jEn+1

DVcEn [lEn] AVcEn [iEn]lEn lEn+1

DVcEn [lEn] BVcEn [jEn]iEn iEn+1jEn jEn+1IEn iEn+1

DVcEn [lEn] AVcn [iEn]lEn lEn+1iEn iEn+1

Page 80: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Este ejemplo asume la presencia de un centinela al final de los vectores AVcEn y BVcEn. Los centinelas son el valor mas grande que es posible asignar y deben tener el mismo valor. Esto asegura que los dos vectores, independientemente del número de elementos que tengan, se agotan al mismo tiempo.

El siguiente ejemplo es una generalización del anterior. Tres vectores: AVcEn, BVcEn y CVcEn, con sus valores enteros ordenados ascendentemente, se intercalan sus valores en orden ascendente en un cuarto vector: DVcEn. Tanto en el árbol S como en el código, el sombreado oscuro corresponde a los

Página 80 de 207

Page 81: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

condicionales externos y el sombreado claro a los condicionales internos (anidados).

#include <stdio.h>/* Tres vectores con valores enteros; AVcEn, BVcEn y CVcEn, ordenados ascendentemente, se intercalan también en orden ascendente en un cuarto vector resultante; DVcEn. Se exhibe el vector resultante.

Página 81 de 207

DVcEn [lEn] AVcEn [iEn]

l l+1I i+1

Dl Ail l+1

Dl Ckl l+1I i+1k k+1

Dl Ckl l+1

k k+1

AVcEn [iEn[<

CVcEn [kEn]

AVcEn [iEn]<

CVcEn [kEn]

AVcEn [iEn]=

CVcEn [kEn]

Dl Ail l+1I i+1

Dl Ail l+1

Dl Ckl l+1I i+1k k+1

Dl Ckl l+1

k k+1

AVcEn [iEn]<

CVcEn [kEn]

AVcEn [iEn]<

CVcEn [kEn]

AVcEn [iEn]=

CVcEn [kEn]

Dl Ail l+1I i+1

Dl Ail l+1

Dl Ckl l+1I i+1k k+1

Dl Ckl l+1

k k+1

BVcEn [jEn]<

CVcEn [kEn]

BVcEn [jEn]<

CVcEn [kEn]

BVcEn [jEn]=

CVcEn [kEn]

AVcEn [iEn]<

BVcEn [jEn]

AVcEn [iEn]=

BVcEn [jEn]

AVcEn [iEn]<

BVcEn [jEn]

Page 82: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

*/void main(void){ int AVcEn[10], BVcEn[10], CVcEn[20], DVcEn[10]; int iEn, jEn, kEn, dimAVcEn = 5, dimBVcEn = 8 dimCVcEn = 7,

dimDVcEn;

// Lectura de los valores del vector AVcEn for(iEn = 0; iEn < dimAVcEn; iEn++) scanf("%d", &AVcEn[iEn]);

// Lectura de los valores del vector BVcEn for(jEn = 0; jEn <dimBVcEn; jEn++) scanf("%d", &BVcEn[jEn]);

// Lectura de los valores del vector CVcEn for(kEn = 0; kEn < dimCVcEn; kEn++) scanf("%d", &CVcEn[kEn]);

// Se inician en ceros las variable enteras: iEn, jEn, kEn, lEn iEn = jEn = kEn = lEn = 0;

// Comparación de los valores de los vectores AVcEn, BVcEn y CVcEn for(;iEn <= dimAVcEn;) if(AVcEn[iEn] < BVcEn[jEn]) if(AVcEn[iEn] < CVcEn[kEn]) DVcEn[lEn++] = AVcEn [iEn++]; else if(AVcEn[iEn] == CVcEn[kEn]){ DVcEn[lEn++] = AVcEn[iEn++]; DVcEn[lEn++] = CVcEn[kEn++]; }else /* AVcEn[iEn] > CVcEn[kEn] */ DVcEn[lEn++] = CVcEn[kEn++]; else if(AVcEn[iEn] == BVcEn[jEn]) if(AVcEn[iEn] < CVcEn[kEn]){ DVcEn[lEn++] = AVcEn[iEn++]; DVcEn[lEn++] = BVcEn[jEn++]; }else if(AVcEn[iEn] == CVcEn[kEn]){ DVcEn[lEn++] = AVcEn[iEn++]; DVcEn[lEn++] = BVcEn[jEn++]; DVcEn[lEn++] = CVcEn[kEn++]; }else /* AVcEn[iEn] > CVcEn[kEn */ DVcEn[lEn++] = CVcEn [kEn++]; else /* AVcEn[iEn] > BVcEn[jEn] */ if(BVcEn[jEn] < CVcEn[kEn]) DVcEn[lEn++] = BVcEn[jEn++]; else if(BVcEn[jEn] == CVcEn[kEn]){ DVcEn[lEn++] = BVcEn[jEn++]; DVcEn[lEn++] = CVcEn[kEn++]; }else /* BVcEn[iEn] > CVcEn[kEn] */ DVcEn[lEn++] = CVcEn[kEn++];

/* Exhibición del vector resultante*/ dimDVcEn = dimAVcEn + dimBVcEn + dimCVcEn;

for(iEn = 0; iEn < dimDVcEn; iEn++) printf("%d ", CVcEn[iEn]); }

Página 82 de 207

Page 83: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.5 Diseño de decisiones con árboles S, parte III

4.5.1 Introducción

Página 83 de 207

Page 84: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

En esta parte III introducimos dos reglas de simplificación, la primera de ellas es intuitiva, la segunda no. Las ilustramos con dos ejemplos, siendo el segundo una generalización del primero.

4.5.2 Reglas 1 y 2

Considere la siguiente matriz esparcida (una con la mayoría de las entradas iguales a cero).

Se almacenan las entradas diferentes de cero con su posición en un vector como sigue:

Se ha colocado el vector en forma horizontal, no vertical, por razones de espacio. Nótese que la tríada 1 1 3, corresponde a la posición 1 1 del valor 3, en la matriz A, y así sucesivamente. Nótese también que el valor con su posición correspondiente se han almacenado en el vector barriendo la matriz por hileras. La tríada 5 5 0 es el centinela.

El problema consiste en localizar el valor en la posición h(ilera), c (olumna). i(ndice) es el indice del vector X. Notese que el primer componente de las triadas en el vector es la hilera de la matriz A, la segunda componente es la columna y la tercera es el valor en esa hilera y columna.

Página 84 de 207

0 0 0 0 00 3 0 0 0

A = 7 0 0 1 0

0 2 0 0 00 0 0 0 0

X = 1 1 3 | 2 0 7 | 2 3 1 | 3 1 2 | 5 5 0

while(1)If(X[i] < h)i = i + 3;else if(X[i] == h)if(X[i+1] < c)

i = i + 3;else if(X[i+1] == c){

Valor = X[i+2];escape;

}else{ // X[i+1] >cValor = 0;escape;

}else{ // X[i] < hValor = 0;escape;}Figura 4. Nótese que el primer nivel de condicionales resuelve el subproblema de localizar la

hilera h, y el segundo nivel resuelve el subproblema de localizar la columna c. El sombreado en los nodos es para aplicarles la Regla 1 la cual se define enseguida.

XVcEn [iEn+1] =cEn

XVcEn [iEn+1] < cEn XVcEn [iEn+1] > cEn

XVcEn [iEn] < hEn XVcEn [iEn] = hEn XVcEn [iEn] > hEn

iEn iEn+3 iEn iEn+3 ValorEn 0ValorEn XVcEn [iEn+2] ValorEn 0

Page 85: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Después de aplicar la Regla 1 al árbol anterior (Figura 4) obtenemos el siguiente árbol S (Figura 5)

La regla siguiente no resulta ser nada intuitiva para la mayoría de la gente.

Página 85 de 207

Regla 1. Un árbol S puede simplificarse (contraerse) verticalmente si sus puntos de decisión a lo largo de una rama se unen mediante la conectiva lógica y.

Regla 2 . Un árbol S puede simplificarse (contraerse) horizontalmente mediante la conectiva o inclusiva, si dos o más puntos de decisión provienen de un mismo punto de decisión y sus respectivos subárboles son idénticos.

XVcEn [iEn] < hEn

XVcEn [iEn] = En y Xi+1 < c XVcEn [iEn] >hEn

Xi = hy

Xi+1 = c

Xi = hy

Xi+1 > c

IEn iEn+3 IEn iEn+3 ValorEn 0ValorEn XVcEn [iEn+2] ValorEn 0

Figura 5. Árbol S resultante después de aplicar la Regla 1 a los nodos sombreados de la Figura 4. Los nuevos nodos en el árbol son los 2, 3 y 4. En esta figura se muestran dos pares de nodos sombreados; dos a la izquierda y dos a la derecha a los cuales se les aplica la Regla 2, la que se define más adelante.

Page 86: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Esta regla se puede aplicarse a las ramas 1 y 2, y a las ramas 4 y 5, del árbol anterior ya que cumplen con esta regla. Como consecuencia de aplicar esta regla tenemos el siguiente árbol equivalente al anterior.

El código correspondiente para esta árbol simplificado es el siguiente:

Este código es completamente equivalente al anterior, es decir, realizan la misma tarea. Observese que la definición de árbol básico siempre nos permite el diseño de decisiones con condiciones sin negaciones.

4.5.3 El proceso cosecuencial

Ahora consideremos tres ejemplos que nos van a llevar a la idea de procesos cosecuenciales, es decir, a una pauta de diseño que parece ser más común de lo que se podría pensar.

Primero consideremos un generalización del ejemplo 2. Tenemos dos vectores, X y Y, con enteros almacenados en orden ascendente, pueden repetirse

Página 86 de 207

(XVcEn [iEn] < hEn) O(XVcEn[iEn] = hEn y

XVcEn [iEn+1] < cEn)

(Xi > h)O

(Xi = hy

Xi+1 > c)

(Xi = h)y

(Xi+1 = c)

i i+3 Valor Xi+2 valor 0

while(1)If((X[i] < h) || ((X[i] == h) && (X[i+1] <

c)))i = i + 3;

else if((X[i] == h) && (X[i+1] < c)){valor = X[i+2];escape;

}else // (X[i] > h || ((X[i] = h) && (X[i+1] > c))){

Page 87: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

algunos valores. La idea es intercalar en orden ascendente, en un tercer vector, los valores contenidos en los vectores X

Considere como ejemplos particulares los vectores X y Y siguientes. Nótese que al final aparece el centinela, 100, el mismo valor más grande que se puede colocar alfinal de ambos vectores. También se muestra el vector resultante W, el cual contiene los valores de X y Y también en orden ascendente.

Como un segundo ejemplo consideremos una generalización del ejemplo XXX.

Tenemos dos matrices esparcidas, A y B, representadas en forma vectorial, la idea es sumar las dos matrices, pero usando su forma vectorial, X y Y, para obtener un tercer vector, W, que representa a la matriz resultante C, la suma de las matrices A y B.

Consideremos, como un ejemplo particular, a las siguientes matrices

Página 87 de 207

Dl Ail l+1I i+1

A < Bj Ai = Bj Ai > Bj

Ai > CkAi < Ck Ai = Ck Ai = CkAi < Ck Ai > Ck Bi > CkBi < Ck Bi = Ck

Dl Ail l+1

Dl Ckl l+1I i+1k k+1

Dl Bjl l+1j j+1

Dl Ckl l+1

k k+1

Dl Ail l+1Dl Bjl l+1i l+1j j+1

Dl Ckl l+1

k k+1

Dl Ail l+1Dl Bjl l+1

Dl Ckl l+1i l+1j j+1

k k+1

Dl BjDl Ckl l+1j j+1k j+1

Dl Ckl l+1

k k+1

Fig. X Árbol S que muestra la lógica para intercalar los valores de dos vectores en uno tercero, los dos vectores X y Y, y el vector resultante W, están ordenados ascendentemente

X = {2 5 7 12 23 100}Y = {3 5 5 8 16 45 50 100}W = {2 3 5 5 5 7 8 12 16 23 45 50 100 100}

0 0 0 0 00 2 0 4 00 0 0 0 00 7 0 0 10 0 0 0 0

0 0 0 5 00 0 0 0 00 8 0 0 00 -7 0 0 00 0 3 0 0

0 0 0 5 00 2 0 4 00 8 0 0 00 0 0 0 10 0 3 0 0

+ =

A B C

Page 88: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Los vectores correspondientes que representan a estas matrices son los siguientes:

Por razones de espacio los vectores se representan horizontalmente, separando con una línea vertical (|) cada tres de números; el primero representa la hilera, el segundo la columna y el tercero el valor en esa hilera y columna. Cada tríada de números se almaceno barriendo las matrices de izquierda a derecha y de arriba hacia abajo es decir por hileras. La tríada 550 es el centinela, representa una hilera y columna ficticias con una entrada igual a cero.

Unamos ahora las tres condiciones sombreadas del segundo nivel con la condición sombreada del primer nivel aplicando la regla 1. Obtenemos el siguiente árbol equivalente

Página 88 de 207

112|134|317|341|550 + 035|218|31-7|423|550 = 035|112|134|218|341|423|550

Xi > YkXi < Yk Xi = Yk

Xi+1 =Yk+1Xi+1 < Yk+1 Xi+1 > Yk+1

Wj Xij j+3i i+3

Wj Xik k+3i i+3

Wj Ykj j+3

k k+3

i i+3k k+3

Wj Ykj k+3k k+3

Xi+2 +Yk+2<> 0

Xi+2 +Yk+2= 0

Wj Xi+2 + yk+2i I+3k k+3j j+3

Fig, X Árbol S que muestra la lógica de sumar dos matrices esparcidas, A y B, utilizando la representación vectorial, X y Y, de las matrices A y B, para obtener un tercer vector resultante W, que se corresponde con la matriz resultante C.

Page 89: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Si ahora aplicamos la regla 2, a las dos condiciones sombreadas a la izquierda y a las dos sombreadas de la derecha, obtenemos el siguiente árbol simplificado:

Página 89 de 207

Xi > YkXi < Yk (Xi = Yk) y (Xi+1 =Yk+1)

(Xi = Yk) y

(Xi+1 < Yk+1)

(Xi = Yk) y

(Xi+1 > Yk+1)

Wj Xij j+3i i+3

Wj Xik k+3i i+3

Wj Ykj j+3

k k+3

i i+3k k+3

Wj Ykj k+3k k+3

Xi+2 +Yk+2<> 0

Xi+2 +Yk+2= 0

Wj Xi+2 + yk+2i I+3k k+3j j+3

(Xi > Yk) o (Xi+1 > Yk+1)(Xi < Yk) o (Xi+1 < Yk+1)

(Xi = Yk) y (Xi+1 =Yk+1)

Wj Xij j+3i i+3

i i+3k k+3

Wj Ykj k+3k k+3

Xi+2 +Yk+2<> 0

Xi+2 +Yk+2= 0

Wj Xi+2 + Yk+2i I+3k k+3j j+3

Page 90: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.6 Diseño de programas con árboles S, parte IV

Página 90 de 207

Page 91: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La siguiente regla la ilustraremos también mediante un ejemplo.Considere el caso en el que el cursor debe permanecer dentro de los limites de una ventana, como se ilustra a continuación.

Los movimientos del cursor permitidos son: arriba, abajo, a la derecha y a la izquierda. Este problema puede dividirse en cinco subproblemas como sigue:

El primer subproblema es determinar que tecla de flecha se pulsó. El árbol S siguiente resuelve el primer subproblema.

Notese que no aparecen completas las condiciones de un árbol básico, faltan las siguientes:

Página 91 de 207

X0

Y0

Xf

Yf

Xc

Yc

TECLA= TECLA = TECLA =

SUBPROA

SUBPROB

SUBPROD

SUBPROC

TECLA=

Page 92: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

(TECLA , TECLA ) (TECLA )(TECLA , TECLA ) (TECLA )(TECLA , TECLA ) (TECLA )(TECLA , TECLA ) (TECLA )

El símbolo significa “es equivalente a”, y el símbolo “es diferente a”. Todas estas condiciones no nos interesan, es decir, son condiciones que no importan, estas condiciones pueden suprimirse o agregarse al final del árbol como un sola, mediante conectivas o inclusivos, para que sea la condición que se da por omisión (del condicional ) como sigue:

(TECLA ) o (TECLA ) o (TECLA ) o (TECLA )

las acciones bajo estas condiciones pueden ser cualesquiera y se igualan entre si, es decir si las acciones bajo las 8 condiciones son: A, B, C, D, E, F, G y H, entonces A=B=C=D=E=F=G=H = X, donde X es una acción conveniente al problema, por ejemplo en nuestro caso que nos ocupa podría ser el siguiente mensaje al usuario:

mensaje(Presione una tecla de flecha)

Donde C.P.O. significa Condición Por Omisión y el símbolo significa “no importa”, es decir:

C.O.P. = (TECLA ) o (TECLA ) o (TECLA ) o (TECLA )

= mensaje(Presione una tecla de flecha)

Página 92 de 207

TECLA = TECLA = TECLA =

SUBPROA

SUBPROB

SUBPROD

SUBPROC

TECLA = C.P.O.

While(Bandera ¡= Escape)switch(TeclaPulsadaN){case Cero: switch(TeclaPulsada0){

case <-: Subproblema A, mantener el cursor a la derecha de

x0;break;

case ->: Subproblema B, mantener el cursor a la izquierda de xf

break;case |: Subproblema C,

mantener el cursor debajo de y0break;

case |: Subproblema D,mantener el cursor arriba de yfbreak;

default: printf(“Presione una tecla de

Page 93: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Consideremos ahora la solución del subproblema A; mantener el cursor a la derecha de x0, esto significa que la coordenada xc del cursor nunca debe estar sobre x0 (debemos evitarla), o a la izquierda de x0 (esta es una condición no importa). Para evitar que xc este sobre x0 debemos anticiparlo restándole 1 a xc, ya que el incremento en la coordenada x es hacia la derecha y el cursor avanza en sentido contrario, es decir:

Página 93 de 207

While(Bandera ¡= Escape)switch(TeclaPulsadaN){case Cero: switch(TeclaPulsada0){

case <-: Subproblema A, mantener el cursor a la derecha de

x0;break;

case ->: Subproblema B, mantener el cursor a la izquierda de xf

break;case |: Subproblema C,

mantener el cursor debajo de y0break;

case |: Subproblema D,mantener el cursor arriba de yf

default: printf(“Presione una tecla de flecha”);

break;

Page 94: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La condición por omisión es una condición no importa, por lo que su acción se hace igual a la acción de la izquierda (suena campana) y podemos aplicar la regla 2.

Podemos integrar el código correspondiente al de este árbol, al código que resuelve el primer subproblema como sigue:

Página 94 de 207

X0 < Xc - 1 C.P.O. = X0 > Xc - 1X0 = Xc -1

Avanza cursor a la izquierda

Suena campana = Suena campana

X0 < Xc - 1 X0 >= Xc -1

Avanza cursor a la izquierda

Suena campana

While(Bandera ¡= Escape)switch(TeclaPulsadaN){case Cero: switch(TeclaPulsada0){

case <-: Subproblema A, //mantener el cursor a la derecha

de x0if(x0 < xc – 1)

gotoxy(--xc, yc);else // x0 >= Xc – 1

Suena campanabreak;

case ->: Subproblema B, mantener el cursor a la izquierda de xf

break;case |: Subproblema C,

mantener el cursor debajo de y0break;

Page 95: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

De manera similar pueden resolverse los tres subproblemas restantes. Este ejemplo nos permite establecer una tercera regla.

4.6.1 Introducción

4.6.2 Los enunciados switch y break

La instrucción switch es una alternativa a condicionales anidados. La cual tiene la siguiente forma general:

switch(caso){ case constante_1: enunciado(s)_1 break; case constante_2: enunciado(s)_2 break;- - - - - - - - - - - - case constante_N: enunciado(s)_N break; default:

enunciado(s)_X}

Este enunciado switch anterior es equivalente al siguiente enunciado de if anidados:

Página 95 de 207

Regla 3 Una condición no importa en un árbol S, puede omitirse o se integra como una condición por omisión con una acción conveniente al problema o se le aplica la regla 2.

Page 96: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

If (caso == constante_1)enunciado(s)_1

else if(caso == constante_2)enunciado(s)_2

_ _ _ _ _ _ _ _ _

else if(caso == constante_N)enunciado(s)_N

else // defalut:enunciado(s)_X

A continuación se presenta un ejemplo donde se ilustra el uso del enunciado y switch.

void main(void){char OpcionCa, SsNn;int AEn, BEn;

while(1){do{

printf("\n (S)uma de dos numeros enteros ");printf("\n (R)esta de dos numeros enteros ");printf("\n (P)roducto de dos numeros enteros ");printf("\n (D)ivision de dos numeros enteros ");printf("\n (N)o mas ");printf("\n\nSeleccione o S, o R, o P, o D, o N: ");fflush(stdin);scanf("%c", &OpcionCa);printf("\n");

}while (OpcionCa != 'S' && OpcionCa != 'R' && OpcionCa != 'P' && OpcionCa != 'D' && OpcionCa != 'N');

if(OpcionCa == 'N'){puts("Hasta la vista !\n");break;

}

puts("\nDame el par de valores de AEn y BEn separados por un espacio en blanco\n");

scanf("%d %d", &AEn, &BEn);

switch (OpcionCa) {case 'S': printf("%d + %d = %d\n",AEn, BEn, AEn + BEn);

break;case 'R': printf("%d - %d = %d\n",AEn, BEn, AEn - BEn);

break;case 'P': printf("%d * %d = %d\n",AEn, BEn, AEn * BEn);

break;case 'D': printf("%d / %d = %d\n",AEn, BEn, AEn / BEn);

break;}

puts("\nOtro Ejemplo ? S o s = Ssi, N o n = Nno: ");fflush(stdin);scanf("%c", &SsNn);

Página 96 de 207

Page 97: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

if((SsNn == 'N') || (SsNn == 'n')){puts("\nSe acabo el veinte !");break;

}}

}

4.6.4 El enunciado continue#include <stdlib.h>#include <conio.h>

/*void IngresarFn(void){

printf("Estoy en Ingresar\n");}

void SuprimirFn(void){printf("Estoy en Suprimir\n");

}

void RevisarFn(void){printf("Estoy en Revisar\n");

}

void SalirFn(void){printf("Estoy en Salir\n");exit(1);

}*/int MenuFnEn(void){ int OpcionEn;

do{printf("1. Ingresar\n");printf("2. Suprimir\n");printf("3. Revisar\n");printf("4. Salir\n");printf("Seleccione un numero: ");scanf("%d", &OpcionEn);printf("\n");

}while (!((OpcionEn >= 1) && (OpcionEn <= 4)));return OpcionEn - 1;

}

void main(void){char LeyendasArCd[4][16] = {{"Soy la opcion 1"},

{"Soy la opcion 2"},

Página 97 de 207

Page 98: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

{"Soy la opcion 3"}, {"Soy la salida "}};

//void (*OpcionesArApFn[])(void) = {IngresarFn, SuprimirFn, RevisarFn, SalirFn};

//(*OpcionesArApFn[MenuFnEn()])();printf("%s\n", LeyendasArCd[MenuFnEn()]);

}

Pautas de Diseño: Procesos CosecuencialesAhora consideremos tres ejemplos que nos van a llevar a la idea de procesos cosecuenciales, es decir, a una pauta de diseño que parece ser más común de lo que se podría pensar.

Brevario

La estrategia de Divide y Venceras (D&V)

Página 98 de 207

Page 99: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La estrategia de D&V no es una capacidad cognitiva exclusiva del Homo Sapiens, también la utilizan cotidianamente las especies “inferiores”. Por ejemplo, los delfines al atacar un cardumen lo dividen para alimentarse de el con el menor de los riesgos. Por supuesto que el cardumen responde con una estrategia que es la contra estrategia de D&V: “El cardumen unido jamás será vencido”.Los delfines utilizan otras tecnicas más refinadas de la estrategia de divide y vencerás, En algunas latitudes del mundo los delfines cooperan con los pescadores para atrapar peces, Esta es una estrategia de D&V de cooperación entre dos especies diferentes mucho más refinada.

Las leonas al atacar una manada de bufalos, eligen al bufalo menos capaz de defenderse con el proposito de hacer una caza rápida y con el menor de los riesgos. El bufalo objetivo es separado de la manada. Este usualmente emprende la huida por lo que las leonas lo conducen por un sendero para emboscarlo. Aquí tenemos otra estrategia de divide y venceras refinada.

Los primates: gorilas, chimpances, orangutanes, etc., hacen un uso muy amplio de esta estrategia, pero es sin duda, que el Homo Sapiens es quien hace el uso más refinado de la estrategia de D&V.

La estrategia de D&V es una pauta recurrente o generica, ya que esta se presenta con diferentes ropajes en diferentes contextos, Por ejemplo, en árboles de fallas, en árboles de probabilidad, en el principio de separación de niveles de interes, el proceso de refinamiento a pasos, en la división de trabajo, etc.

En el diseño de todo algoritmo, siempre esta presente la estrategia de D&V.

Capítulo 5

Página 99 de 207

Page 100: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Funciones

Página 100 de 207

Page 101: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

Página 101 de 207

Page 102: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El alumno modelara, codificara y correrá programas que incluyen funciones que segmentan a los programas en jerarquias de modulos para fácilitar su diseño.

Contenido

5.1 La estructura de una función5.2 El alcance de las funciones5.3 Variables locales y globales5.4 Funciones sin argumento5.5 Pase de argumentos por valor y por referencia5.6 Funciones en expresiones5.7 Arreglo como argumentos como funciones5.8 Iniciación de arreglos en tiempo de compilación5.9 Los argumentos de main5.10 Funciones en línea5.11 Argumentos por omisión5.12 Argumentos por omisión múltiples

Objetivos:

Al terminar esta unidad, el alumno será capaz de utilizar:

1.- Funciones con argumentos2.- Funciones sin argumentos3.- Argumentos por valor y referencia4.- Funciones en expresiones5.- Funciones en línea6.- Argumentos por omisión7.- Argumentos por omisión múltiple

Página 102 de 207

Page 103: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

3.1 La estructura de una función

Una función es un conjunto de instrucciones con un propósito bien definido. Como por ejemplo:

Sumar dos matrices. Producto de dos matrices. Producto de dos vectores.

. Las funciones tienen la siguiente estructura:

tipo nombre_función(argumentos){ //Encabezado o prototipo declaración de variables locales

instrucciones ejecutables //Sumar dos matrices, producto //de dos matrices, producto de //dos vectores, etc.

}

Una función consta de un encabezado o prototipo y de un cuerpo. El prototipo consta de una lista de variables llamadas ficticias o, argumentos o, parámetros formales, separados por comas. El cuerpo consta de declaraciones de variables locales e instrucciones ejecutablesLas funciones evitan la duplicidad de código y contribuyen a modularizar (dividen en partes bien definidas) los programas.

3.2 Formas de declarar las funciones

Hay dos formas de declarar una función. Se declara el prototipo terminado con punto y coma (;) antes de main, luego se declara el prototipo y el cuerpo de la función después de main, como se ilustra enseguida.

#include <stdio.h>

void SumaFn( int , int , int); //Solo se declara el prototipo void main(void){ int AEn = 5, BEn = 4;

SumaFn(AEn, BEn); }

void SumaFn(int AEn, int BEn){ //Prototipo y cuerpo declarados

Página 103 de 207

Page 104: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf("%d", AEn + BEn) ; }

Notése que el nombre de los parámetros formales se pueden omitir en el prototipo. No así en la declaración completa que aparece después de main. Los parámetros le indican al compilador de que tipo y cuantos son, sin importar el nombre que tengan, por lo que la variable CEn en suma y main son distintas.

En la segunda forma de declarar una función, esta se declara por completo antes de main, como se muestra enseguida.

#include <stdio.h>

void SumaFn(int AEn, int BEn){ printf ("%d", AEn + BEn); }

void main(void){ int AEn = 5, BEn = 4;

SumaFn(AEn, BEn); }

3.3 Variables locales y globales

Las variables AEn, y BEn declaradas en la función principal main del ejemplo anterior, son locales a esta, es decir solo pueden usarse en main y no en suma. Por otra parte, los parámetros formales en la función SumaFn son locales a la función.

#include <stdio.h>

void SumaFn(int, int);

void main(void){ int AEn = 5, BEn = 4;

SumaFn(AEn, BEn); }

void SumaFn(int AEn, int BEn){ printf ("%d", AEn + BEn); }

En el ejemplo siguiente, modificación del anterior, son locales a la función main, las variables AEn, mientras que la variable CEn en la función suma es

Página 104 de 207

Page 105: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

local a ésta. Es decir, ambas variables aún cuando tienen el mismo nombre son diferentes por estar declaradas en ámbitos diferentes.

#include <stdio.h>

int CEn = 4; //CEn es una variable global a la función

//SumaFn porque aparece antes de la //declaración de esta.

void SumaFn(int, int);

void main(void){ int AEn = 5;

SumaFn(AEn, CEn); //Aquí se utliza la variable global CEn en //main

} void SumaFn(int AEn, int BEn){ int CEn; //CEn es una variable local a SumaFn. En

//ámbito no tiene validez la variable global

//CEn CEn = AEn + BEn; printf ("%d", CEn); }

Ahora tenemos declarada a la variable c antes de main, por lo que ahora es global, es decir, puede ser reconocida por cualquier función, sin embargo, tenemos declarada como local en la función suma, también a una variable de nombre c, para evitar un conflicto, el compilador, en este caso, le dá prioridad a la variable local c de la función suma durante su ejecución, es decir invalida la global.

#include <stdio.h>

void SumaFn(int, int); void main(void){ int AEn = 5;

SumaFn(xEn, cEn); }

int cEn; void sumaFn(int aEn, int bEn){

Página 105 de 207

Page 106: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

cEn = aEn + bEn; printf ("%d", cEn); }

Ahora tenemos declarada a la variable c en main, por lo que es local a main, pero también aparece en suma, se dice que esta variable es global a suma por estár declarada antes y fuera del ámbito de suma, por lo que puede usarse en suma. Esta variable no es global ni local a main por estar declarada después de esta.

#include <stdio.h>

void sumaFn(int, int)

void main(void){

suma(5, 4); }

int cEn; void sumaFn(int aEn, int bEn){

cEn = aEn + bEn; printf ("%d", cEn);

}

Este ejemplo ilustra que podemos tener valores constantes como argumentos en las llamadas de las funciones.

3.4 Funciones sin argumentos

Las funciones pueden no tener argumentos, como es el caso siguiente.

#include <stdio.h>

int aEn = 5, bEn = 11, cEn; void sumaFn(void);

void main(void){

suma(); }

int cEn; void sumaFn(void){

cEn = aEn + bEn;

Página 106 de 207

Page 107: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf ("%d", cEn); }

3.5 Pase de argumentos por valor y por referencia

En el ejemplo siguiente la intención es intercambiar los valores de A y B, mediante la función cambia.

#include <stdio.h>

void cambiaFn(int xEn, int yEn){ int tempEn;

tempEn = xEn; xEn = yEn; yEn = tempEn; }

void main(void){ int AEn = 5, BEn = 10;

printf("%d %d", AEn, BEn); cambia(AEn, BEn); printf("%d %d", AEn, BEn); }

Sin embargo, no sucede así debido a que los argumentos se pasaron por valor, es decir, las dos exhibiciones mostraran 5 y 10.

Para lograr que el intercambio requerido, debemos pasar los argumentos por referencia, es decir, hay que anteponerles a los argumentos, en la llamada de la función cambia, el símbolo &, y en la declaración de la misma el símbolo *.

#include <stdio.h>

void cambiaFn(int *xEn, int *yEn){ int tempEn;

tempEn = *xEn; *xEn = *yEn; *yEn = tempEn; }

void main(void){ int AEn = 5, BEn = 10;

printf("%d %d", AEn, BEn); cambiaFn(&AEn, &BEn);

Página 107 de 207

Page 108: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf(“%d %d, AEn, BEn); }

3.6 Funciones en expresiones

Hasta ahora, las funciones que hemos empleado se llaman escribiendo su nombre con sus argumentos, si los hay, esto es debido a que no hemos asociado un valor al nombre de las mismas. Una función puede aparecer en una expresión si asociamos un valor a su nombre mediante un return en su ámbito.

#include <stdio.h>

int sumaFnEn(int aEn, int bEn){

return aEn + bEn; }

void main(void){ int xEn = 5, yEn = 12, wEn;

wEn = 0.5*sumaFnEn(xEn, yEn) printf("%d %d", sumaFnEn(xEn, yEn), wEn); }

Si una función tiene asociado un valor entero a su nombre, se puede omitir el tipo de la función, si no es tipo entero el valor asociado con el nombre, entonces se debe anteponer al nombre de la función el tipo, como en el siguiente ejemplo.

#include <stdio.h>

float sumaFnRe(float aRe, float bRe){

return aRe + bRe; }

void main (void){ float xRe = 5.0, yRe = 12.0, wRe;

printf ("%f %f", suma(xRe, yRe), wRe); }

3.7 Arreglos como argumentos en funciones

Los arreglos se pasan por referencia, es decir, no es necesario usar los símbolos & y * con los nombres de los arreglos.

#include <stdio.h>

void sumaFn(int xVcEn[10], int yVcEn[10], wVcEn[10]) {

Página 108 de 207

Page 109: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int iEn;

for(iEn = 0; iEn < 10; iEn++) wVcEn[iEn] = xVcEn[iEn] + yVcEn[iEn] }

void leeFn(int xVcEn[10]); void exhibeFn(int xVcEn[10]);

void main(void){ int AVcEn[10], BVcEn[10], CVcEn[10];

lee(AVcEn); lee(BVcEn); suma(AVcEn, BVcEn, CVcEn); exhibe(BVcEn); exhibe(CVcEn); }

int iEn; void leeFn(int xVcEn[10]){

for(iEn = 0; iEn < 10; iEn++) scanf (“%d”, &xVcEn[iEn]); }

void exhibeFn(int xVcEn[10]){

for(iEn = 0; iEn < 10; iEn++) printf (“%d”, xVcEn[iEn]); }

3.8 Iniciación en tiempo de compilación

El ejemplo que sigue ilustra como iniciar arreglos con valores en tiempo de compilación.

#include <stdio.h>

void sumaFn(int xVcEn[5][5], int yVcEn[5][5], wVcEn[5][5]){ int iEn, jEn;

for(iEn = 0; iEn < 5; iEn++) for(jEn = 0; jEn < 5; jEn++) wVcEn[iEn][jEn] = xVcEn[iEn][jEn] + yVcEn[iEn][jEn] } void leeFn(int xVcEn[10]);

Página 109 de 207

Page 110: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

void exhibeFn(int xVcEn[10]);

void main(void){ int AVcEn[][3] ={{l,2,3,4,5}, {l,2,3,4,5}, {l,2,3,4,5}, {l,2,3,4,5}, {l,2,3,4,5}}, BVcEn[][3] ={6,7,8,9,0}, {6,7,8,9,0}, {6, 7,8,9, 0} {6,7,8,9,0}, {6,7,8,9,0}} CVcEn[5][5];

leeFn(AVcEn); leeVcEn(BVcEn); sumaFn(AVcEn, BVcEn, CVcEn) ; exhibeFn(AVcEn); exhibeFn(BVcEn); exhibeFn(CVcEn); }

int iEn, jEn; void leeFn(int xVcEn[5][5]){

for(iEn = 0; iEn < 5; jEn++) for(jEn = 0; jEn < 5; iEn++) printf (“%d”, xVcEn[iEn][jEn]) ; }

3.9 Los argumentos de main

La función principal main tiene dos argumentos. Estos son argc y argv, los que permiten pasar argumentos en la línea de comando. Un argumento en la línea de comando es la información que sigue al nombre del programa ejecutable en la indicación de MS-DOS.

argv contiene el número de argumentos en la línea de comando y es un entero. Al menos siempre séra 1 porque se toma en cuenta el nombre del programa.

argv es un apuntador a un arreglo de apuntadores a cadenas. Cada elemento de este arreglo señala a un argumento de la línea de comando.

#include <stdio.h>

void main(int argc, char *argv[]){

Página 110 de 207

Page 111: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

if(argc < 2) printf("Olvido dar su nombre !\n"); else if(argc < 3) printf("No dio su nombre completo !\n"); else printf("Hola %s %s" argv[1], argv[2]); }

Suponiendo que está en la indicación A:>, usted digita:

A: >linecoma Juan Pérez

y se muestra el mensaje

Hola Juan Pérez

Pero si usted digita

A:>linecoma

se exhibe el mensaje

olvida su nombre!

o si digita

A:>linecoma Juan

entonces exhibe el mensaje

No dio su nombre completo!

3.10 Funciones en línea

Una función en línea se declara igual y define igual que una función ordinaria. Su propósito es una alternativa a las funciones ordinarias con pocas líneas de código para reducir el costo de las llamadas.

En una función en línea

* El prototipo esta precedido por la palabra reservada inline.* Su llamada se reemplaza por su código.

#include <stdio.h>

inline float sumaFnRe(float aRe, float bRe){

Página 111 de 207

Page 112: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

return aRe + bRe; }

inline void exhibeFn(float aFn){

printf("%f", aRe); }

void main(void){ int xEn = 5, yEn = 4, WEn;

wEn = sumaFnRe(xEn, yEn); exhibeFn(wEn); }

3.11 Argumentos por omisión

El uso de argumentos por omisión es útil cuando se requiere llamar a una función varias veces con el mismo argumento la más de las veces. El ejemplo siguiente ilustra esto.

#include <stdio.h>

void exhibemsjeFn(char msjeCd[ ] = "Active la impresora"){ puts(msjeCd); }

void main(void){

exhibemsjeFn(); exhibemsjeFn("Presione una tecla para continuar"); exhibemsjeFn("el valor es invalido "); exhibetnsjeFn() }

3.12 Argumentos por omisión múltiple

Es posible especificar mas de un argumento por omisión. Como lo muestra el siguiente ejemplo.

#include <stdio.h> void fnFn(int kEn = 5, char caraCa = 'X', float xRe = 7.5){ printf("%d\n", kEn); printf("%c\n", caraCa); printf("%f\n", xRe);

Página 112 de 207

Page 113: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

}

void main(void){

fnFn(); fnFn(15); fnFn(15, 'B'); fnFn(15, 'B', 0.5); }

Si solo una parte de los argumentos son por omisión, entonces estos deben aparecer en el extremo derecho. Por ejemplo, no es valido el siguiente prototipo de función:

void fnFn(int kEn = 5, charCa cara, float xRe = 0.5);

sin embargo es valido el siguiente:

void fnFn(char caraCa, int kEn = 5, float xRe = 7.5);

Página 113 de 207

Page 114: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 6Página 114 de 207

Page 115: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La Programación Estructurada y el Lenguaje de Programación C

Página 115 de 207

Page 116: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

Página 116 de 207

Page 117: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El alumno modelara, codificara y correrá programas de acuerdo a los principos de la programción estructurada.

Contenido

6.1 La Programación Estructurada.6.2 La Praxis 6.3. Seudocódigo6.4 Un Ejemplo de Diseño Usando Español Estructurado6.5 Diagramas Estructurados6.6 La Controversia del GoTo

Objetivos particulares

1. Al terminar éste capítulo, el alumno será capaz de utilizar2. El proceso de refinamiento a pasos como una herramienta de abstracción

mental en el diseño de programas.3. El seudocodigo como una herramienta o lenguaje de diseño de programas

para concretar en firme el proceso de refinamiento a pasos.

4.1 La Programación Estructurada

Página 117 de 207

Page 118: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La programación estructurada es una metodología para el diseño de programas. Nace como una necesidad para resolver los problemas que se originan durante y después del desarrollo de los programas. Esta consta de conceptos, metódos y diagramas. Su énfasis esta en la estructura de los programas, es decir, en los bloques básicos que los constituyen; las figuras de control. Estas representan el flujo o secuencia lógica en que se ejecutan los programas en una computadora. Son una herramienta útil, pues nos ayudan a modelar soluciones de problemas que van desde los más simples hasta los más complejos. Las figuras de control se clasifican en las siguientes cuatro categorías:

Secuencia, Iteración, Decisión y Salida.

La programación estructurada clásica considera las tres primeras. Las cuales tienen la característica común de tener un punto de entrada y uno de salida. La cuarta categoría se introdujo posteriormente y modificó esta característica común a la de un punto de entrada y varios de salida.

4.2 La Praxis

En la práctica, nuestra principal herramienta en la programación estructurada es nuestro propio proceso mental de abstracción. Mediante este visualizamos un problema como una colección de problemas más pequeños (subprogramas) y por lo tanto menos complicados. Este proceso se aplica reiterativamente hasta llegar a un punto en que ningún subprograma esté en términos de otros. Este proceso genera rápidamente una gran cantidad de detalles que es imposible de retener todos a la vez en nuestra memoria, aún tratándose de un problema simple. Por lo que requerimos de una notación que nos ayude a concretar, sin confusión, los diferentes niveles de abstracción a medida que estos se derivan.Al proceso que combina el uso de la abstracción mental para reducir un problema a un conjunto de subproblemas más tratables y el uso de una notación que nos permita documentar este proceso y con ello reducir nuestra sobrecarga mental de detalles generados, se le conoce como proceso de refinamiento a pasos, y es central a la programación estructurada.

Diversas herramientas se han propuesto para la concreción de este proceso de abstracción iterativo, como son:

Seudocódigo. Diagramas.

+ De flujo estructurado. + De acción y

+ Otros

Página 118 de 207

Page 119: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Siendo, posiblemente, el seudocodigo y los diagramas de flujo estructurado los más ampliamente usados hasta hoy día. Al seudocódigo también se le llego a conocer como Lenguaje de Diseño de Programas (PDL por sus siglas en Inglés). Cada una de estas herramientas es realmente una alternativa de Lenguaje de Diseño de Programas (LDP por sus siglas en Español). Alternativa dictada solamente por la preferencia del programdor. Las figuras de control correspondientes al seudocódigo y a los diagramas deben caer en las cuatro categorías ya mencionadas en la primera parte.

Normas de la programación estructurada

El programa se divide en piezas independientes llamadas módulos. Un módulo es una unidad autocontenida cuyo código es físicamente y

lógicamente separado del código de cualquier otro módulo en el programa.

Un módulo representa una función lógica única en el programa, por ejemplo, SUMA DE MATRICES

El tamaño de un módulo no debe de exceder las 100 instrucciones (enunciados) .

Un módulo esta limitado por un punto de entrada y un punto de salida. Durante la ejecución, el control de programa puede ingresar a un módulo solo en su punto de entrada y puede salir del módulo solo de su punto de salida.

Los módulos están relacionados con otros solo mediante una estructura de control jerárquica. Cada nivel en la estructura de control representa una descripción más detallada de lo que el programa hace. Esto también dicta la transferencia de programa de módulo a módulo durante la ejecución.

Ninguna circularidad se permite en la estructura de control. Esto significa que un módulo no puede llamarse a si mismo, ni puede este llamar a otro que lo haya llamado.

Cada módulo debe comenzar con un bloque de comentario que explique la función que ese módulo realiza, los valores pasados al módulo, los valores devueltos, los módulos que llaman a este módulo y los módulos que este módulo llama.

Los comentarios embebidos en el código del módulo deben separarse de las instrucciones mediante una línea en blanco.

Todod los comentarios deben ser significativos (a saber, no deben repetir información que es obvia del código).

Evite etiquetas innecesarias; no usa las etiquetas como comentarios. Todas los nombres de las variables y módulos deben ser significativos.

Los nombres de los módulos deben de sugerir la función lógica que realizan (a saber, EDITAR), y y losnombres de las variables deben sugerir su propósito en el programa (a saber, ERROR).

4.3 Seudocódigo

El seudocódigo ó prosa estructurada, ó Español estructurado como también se le conoce, representa o describe de manera informal a los programas, cada parte de esta descripción se corresponde con el código fuente. La siguiente tabla, muestra las tres figuras de control básicas (en seudocódigo).

Página 119 de 207

Page 120: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

2 Figura SeudocódigoI.

SecuenciaInstrucción 1. . . . . . .instrucción n

II. Decisión 1. si (condición) instrucción(es) 1 o_bien instrucción(es) 2 fin2. si (condición) instrucción(es) fin3. si (condición 1) instrucción(es) 1 o_si (condición 2) instrucción(es) 2 . . . . . . . . . . . o_si (condición n) instrucción(es) n o_bien instrucción(es) x fin4. casar (caso) con caso 1: instrucción(es) 1 caso 2: instrucción(es) 2 . . . . . . . . . . . caso n: instrucción(es) n o_bien: instrucción(es) x fin

IIIIII Iterativas 1. mientras (condición) instrucción(es) fin2. repetir instrucción(es) hasta (condisión)3. desde (índice = expart1 a expart 2) instrucción(es) fin

Tabla 1. Las tres figuras de control clásicas.

Mientras que la programación estructurada clásica solo consideraba tres categorías de figuras de control básicas, la programación estucturada moderna considera una cuarta categoría de figuras de control; las de Salida, las cuales se muestran en la siguiente tabla.

Página 120 de 207

Page 121: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

IV Salida 1. escape repetir instrucción 1 si (condisión 1) escape fin instrucción 2 hasta (condición 2)1 iterar repetir instrucción 1 si (condisión 1) iterar fin instrucción 2 hasta (condición 2)

Tabla 2. La cuarta categoría de figuras de control.

4.4 Un Ejemplo de Diseño Usando Español Estructurado como LDP

Quizás convenga en este punto ilustrar el proceso de refinamiento a pasos con un ejemplo usando como LDP al Español estructurado. Consideremos el siguiente problema:

Diseñe un programa que lea dos matrices y valide si son sumables y multiplicables. En caso de serlo deben hacerse las operaciones correspondientes y exhibir las dos matrices y la matriz resultante, en caso de no ser una o la otra o las dos, que se hagan las operaciones y se exhiban los mensajes correspondientes.

Una primera reflexión (abstracción) nos dice claramente que debemos primero establecer las reglas de cuando las dos matrices son sumables y multiplicables y cuando no.

SumablesDos matrices son sumables cuando sean de las mismas dimensiones, es decir, deben tener igual número de columnas y de hileras.

MultiplicablesDos matrices son multiplicables cuando el número de columnas de la primer matriz coincide con el número de hileras de la segunda matriz.

Por supuesto esto ya lo sabemos de nuestros cursos de Álgebra tomados con anterioridad.

Una segunda reflexión nos dice que primero debemos leer las dimensiones de las matrices, luego a las matrices mismas para exhibirlas y luego procedemos a evaluar si son operables en cuanto a suma o multiplicación. Es decir:

Página 121 de 207

Page 122: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Lectura de las dimensiones de las matricesLectura de las dos matricesExhibición de ambas matricesSe procede a evaluar si son operables respecto a la suma y el producto.

Una tercera reflexión nos dice que las tres primeras líneas son lo suficientemente claras y estan bien establecidas, no así la tercer línea, con la cual debemos de tomar la decisión de si primero evaluamos y luego hacemos las operaciones correpondientes que resulten o evaluamos para una operación y de ser valida la realizamos y exhibimos lo que resulte, de no ser válida se exhibe el mensaje correspondiente, luego procedemos de la misma manera con la segunda operación.

Nos inclinamos por la segunda opción, esto puede ser una cuestión de gustos.

Lectura de las dimensiones de las matricesLectura de las dos matricesExhibición de ambas matricesSi(la suma de las matrices es valida) entonces

Sumaralas yExhibir la matriz resultante.

ObienMensaje(la suma es invalida)

Si(el producto de las matrices es valido) entoncesMultlipicarlas yExhibir la matriz resultante.

ObienMensaje(el producto es invalido)

Notese que esta ultima abstracción es de hecho casi una copia al carbón de lo dicho en el parrafo anterior.

Otra reflexión nos dice que debemos afinar más, acercar más al lenguaje de programación en que finalmente vamos a implementar este modelo de programa, las expresiones

la suma de las matrices es validael producto de las matrices es valido

Aquí evidentemente que debemos de tomar en cuenta, en primer lugar, las reglas de suma y producto de matrices y en segundo lugar, hacer una elección cuidadosa de los nombres de las funciones que van a realizar las comparaciones correspondientes de las dimensiones de las matrices para validarlas. De modo que:

Página 122 de 207

Page 123: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

SumaValida(HiA, CoA, HiB, CoB)ProductoValido(CoA, HiB)

Donde HiA = Hilera de A, CoA = Columna de A, HiB = Hilera de B y CoB = Columna de B.Sustituyendo estas dos líneas en sus posiciones correspondientes tenemos:

Lectura de las dimensiones de las matricesLectura de las dos matricesExhibición de ambas matricesSi(SumaValida(HiA, CoA, HiB, CoB)) entonces

Sumaralas yExhibir la matriz resultante.

ObienMensaje(la suma es invalida)

Si(ProductoValido(CoA, HiB)) entoncesMultlipicarlas yExhibir la matriz resultante.

ObienMensaje(el producto es invalido)

Consideraciones similares debemos hacer con las líneas:

Sumarlas o multiplicarlas yExhibir la matriz resultante

Las omitimos puesto que la consideración anterior puede servir de referencia para hacerlo, de modo que finalmente tenemos.

Lectura de las dimensiones de las matricesLectura de las dos matricesExhibición de ambas matricesSi(SumaValida(HiA, CoA, HiB, CoB)) entonces

SeSuma(MatrizA, MatrizB, MatrizC, HiA, CoA)SeExhibe(MatrizC, HiC, CoC)

ObienMensaje(la suma es invalida)

Si(ProductoValido(CoA, HiB)) entoncesSeMultiplica(MatrizA, MatrizB, MatrizC, HiA, CoA, HiB)SeExhibe(MatrizC, HiC, CoC)

ObienMensaje(el producto es invalido)

Notese que comenzamos con un nivel detalle bajo, alto nivel de abstracción, y finalizamos con un nivel de detalle alto, bajo nivel de abstracción. En otras

Página 123 de 207

Page 124: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

palabras, nuestro modelo de programa esta lo sufcientemente “cocinado” como para pasarlo directamente al lenguaje de nuestra elección, en nuestro caso el lenguaje C.

void main(void){int HiA, CoA, HiB, CoB;int MatrizA[10][10], MatrizB[10][10], MatrizC[10][10];

//Lectura de las dimensiones de las matricesputs(“Dame las dimensiones de la matrizA”)scanf(“%d %d”, &HiA, &CoA);

puts(“Dame las dimensiones de la matrizB”)scanf(“%d %d”, &HiB, &CoB);

//Lectura de las dos matricesSeLee(MatrizA, HiA, CoA);SeLee(MatrizB, HiB, CoB);

//Exhibición de ambas matricesSeExhibe(MatrizA, HiA, CoA);SeExhibe(MatrizB, HiB, CoB);

if(SumaValida(HiA, CoA, HiB, CoB)){SeSuma(MatrizA, MatrizB, MatrizC, HiA, CoA);SeExhibe(MatrizC, HiC, CoC);

}elseprintf(“la suma es invalida\n”);

if(ProductoValido(CoA, HiB)){SeMultiplica(MatrizA, MatrizB, MatrizC, HiA, CoA, HiB);SeExhibe(MatrizC, HiC, CoC);

}elseprintf(“el producto es invalido\n”)

}4.5 Diagramas Estructurados

Los diagramas juegan un papel importante en el diseño de sistemas y en particular en el desarrollo de programas. Son una forma de lenguaje que nos ayudan a visualizar e idear procesos que van desde sencillos a complicados, y son una herramienta de comunicación escencial en un equipo de trabajo.En el capítulo 3 trataremos los diagramas estructurados para ilustrar el flujo de control básico, sin embargo, no usaremos los diagramas estructurados en el diseño de procesos debido al amplio espacio que se requiere para se uso, en lugar de ellos, utilizaremos el seudocógio o lenguaje de diseño de programas (PDL por sus siglas en Inglés) por ser más consciso.

Página 124 de 207

Page 125: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Que el alumno haga una investigación para contestar a las siguientes preguntas

1. ¿ Prohíbe el uso de goto’s la P,E. ?

2. ¿ Es el seudocódigo (también conocido como Español Estructurado o Lenguaje de Diseño de Programas: LDP) un lenguaje universal ?

3. ¿ Que es central a la P. E. ?

4. ¿ Cuales son las categorías de las Figuras de Control en un LDP ?

5. ¿ Enuncie, por categorías, las figuras de control del lenguaje C ?

6. ¿ Enuncie, por categorías, las figuras de control del LDP ?

7. ¿ Que caracteriza a las figuras de control ?

8. ¿ Explique el proceso de refinamiento a pasos de la P.E. ?

9. ¿ Un programa sin goto’s es un programa estructurado ?

10.¿ Mencione otras alternativas al seudocódigo ?

11.¿ Cuales serían las figuras de control básicas necesarias para construir cualquier programa ?

12.Defina el concepto de P.E.

13.¿ Sustituye la P.O.O. a la P.E. ? Explique.

14.¿ Cuando un lenguaje esta basado en objetos y cuando es orientado a objetos ? Ejemplifique.

15.¿ Que enfatiza la P.E. y que la P.O.O. ?

16.¿ Realmente que es P.O.O. ?

17.Defina el concepto de P.O.O.

18.Defina los conceptos de clase y objeto, herencia simple y compuesta, y polimorfismo en el contexto de la P.O.O.

19.Defina encapsulamiento y cubrimiento de la información

20.¿ Que son los mensajes en la P. O. O. ?

Página 125 de 207

Page 126: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

4.6 La controversia del Goto

Debido a que inicialmente se vió a los polémicos gotos como la causa principal de todos los males de la programación y a que la aplicación del proceso de refinamiento a pasos al diseño de programas produce programas sin gotos. Muchos progamadores hicieron suyas las siguientes reglas falaces:

La programación estructurada prohibe el uso de gotos.

Un programa estructurado es un programa sin gotos

Estas observaciones establecidas como reglas son incorrectas. Si ya establecimos como un principio que el proceso de refinamiento a pasos es central a la programación estructurada entonces podemos establecer el siguiente corolario

Todo programa estructurado debe de ser el resultado de aplicar el proceso de refinamiento a pasos al diseño de programas.

Esta afirmación no prohibe el uso de gotos, sino que promueve su uso sistemático (uso de pocas categorías de gotos con un propósito bien definido) y prohibe su uso indiscriminado (innumerables gotos sin un propósito sistemático insertos en el codigo de los programas). El uso indiscriminado de gotos produce el llamado código espagueti el cual oscurece la lógica de los programas. El código espagueti es ilegible y casi imposible de darle mantenimiento, en consecuencia el costo, el esfuerzo y el tiempo para darle mantenimiento se incrementan considerablemente.

Página 126 de 207

Page 127: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Brevario

La crisis del software

A fines de la década de los 60, se hizo obvio que los sistemas de software eran sistemas muy complejos, que resultaban difíciles de diseñar, codificar, probar y prácticamente imposibles de entenderlos y de darles mantenimiento. Esto da origen a la llamada crisis del software. Esta condición fue tan severa que demando con urgencia la creación de nuevas metodologías para abatirla. Dos grandes disciplinas emergen de esta crisis: La programación estructurada primero y la ingeniería del software después.

La programación estructurada nace como consecuencia de esta crisis, que es propiciada en gran medida por el llamado código espagueti, mucho esfuerzo se dedico a eliminarlo y sustituirlo por otro más estructurado (programación estructurada). Se culpo en buena medida de esto al uso de los enunciados go to’s, por lo que muchos autores propusieron su eliminación de los lenguajes de programación. Esta situación da origen a una controversia de los go to’s, si se deben conservar o eliminar. Si bien el uso, mal uso y uso excesivo, de estos enunciados propiciaba en buena medida el código espagueti, esto no justificaba su desaparición de los lenguajes, sino que por el contrario, había que propiciar un uso más sistemático de ellos, usarlos menos y con un propósito bien definido. La programación estructurada enfatiza mucho el empleo más sistemático de los enunciados de control de flujo, de ahí nacen los diagramas de flujo estructurados, los cuales en realidad se usaron poco, debido a que ocupan demasiado espacio al describir la lógica de los programas en comparación del código que generan. Una alternativa fue el seudocódigo o prosa o Español estructurado, que se utilizó como un lenguaje de diseño de programas (LDP). Inicialmente el LDP, en la programación estructurada clásica, utilizo tres categorías básicas de figuras de control de flujo: secuencia, condicionales e iteraciones. Posteriormente se integro una cuarta categoría, la de escapes. Esta categoría no son otra cosa que go to´s que se utilizan sistemáticamente. El lenguaje C, en particular, siempre las incluyo en su sintaxis.

Durante este periodo siempre se considero que nuestra principal herramienta para tratar con la complejidad, era nuestra capacidad de abstracción, aún hoy esta sigue siendo una premisa válida para cualquier actividad intelectual, sin ella la humanidad jamás hubiera salido de las cavernas. Se le llamo procesamiento de refinamiento a pasos a una forma sistemática de utilizar esta intrinsica capacidad de abstracción y se incorporo a la naciente programación estructurada como central a la misma. El LDP se utilizó como una herramienta para concretar este proceso, durante

Página 127 de 207

Page 128: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

el proceso de creación de un programa, por el gran número de detalles que había que cubrir durante el diseño de estos. Muchos programadores llegaron a afirmar que sus programas eran estructurados porque estos no contenían go to´s. Esta afirmación con frecuencia era falsa, ya que sus diseños de programa no eran derivados del proceso de refinamiento a pasos. Sino de un diseño ad hoc (pobremente metodológico). En realidad para que el diseño de programa fuese considerado estructurado este debió ser el resultado de aplicar el proceso de refinamiento a pasos, lo cual no implicaba no usar go to’s, por el contrario, estos podían usarse metodológicamente.El propósito de la programación estructurada fue el de resolver la crisis del software mediante el logro de los siguiente objetivos:

Mejorar la legibilidad de los programasHacer la correspondencia entre el programa fuente y los procesos de ejecución tan trivial como sea posible (Dijkstra [5]).

Mejorar la eficiencia de los programasEnfatizar la

Minimizar la complejidad de los programas Simplificar el mantenimiento de los programas Incrementar la productividad del programador Proporcionar una disciplina metodológica de la programación

La formalización de la programación en la programación estructurada abrió el camino a la ingeniería del software y después a las herramientas CASE (Computer Aided Systems Engineering = Ingeniería de Sistemas Asistida por Computadora) por sus siglas en Inglés.

La ingeniería del software involucra tres fases en el desarrollo de los sistemas de información (software); el análisis estructurado, el diseño estructurado y las técnicas estructuradas.Las herramientas CASE es un intento de automatizar las fases de la ingeniería del software. Inicialmente esta herramienta es vista como una panacea, ya que se pensaba que esta herramienta iba a generar todo el código de una aplicación, esto resultó ser demasiado, ya que en el esquema de:

entrada y formateo de datos -> procesos -> salida y exhibición de datos

lo que verdaderamente se automatizó fueron los dos extremos. Los procesos probaron ser difíciles de automatizar por lo que siguieron codificándose a mano en gran medida.

Página 128 de 207

Page 129: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 7

Los Tipos de Variables Predefinidos: Uniones y Estructuras

Página 129 de 207

Page 130: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 130 de 207

Page 131: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno modelara, codificara y correrá programas que incluyen tipos de variables predefinidos por el usuario como son las uniones y las estructuras.

Contenido

7.1 Estructuras7.2 Como acceder a los elementos de una estructura7.3 Lectura y exhibición de los elementos de una estructura7.4 Elementos de estructura como argumentos en funciones7.5 Estructuras como argumentos en funciones7.6 Simplificación de la notación de las estructuras7.7 Estructuras en estructuras7.8 Arreglos en estructuras7.9 Estructuras con campos en bits7.10 Uniones

Objetivos

Al terminar esta unidad, el alumno será capaz de utilizar:

1. Estructuras2. Referenciar los elementos de una estructura3. Leer y exhibir los elementos de una estructura4. Elementos de una estructura como argumentos en una función5. Estructuras como argumentos en funciones6. Estructuras anidadas7. Arreglos de estructuras8. Estructuras en campos de bits9. Uniones

Página 131 de 207

Page 132: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

5.1 Estructuras

Una estructura es una colección de variables a las que se hace referencia mediante un nombre. Las variables en las estructuras, por regla general, están relacionadas lógicamente. La declaración de una estructura nos permite crear variables de estructura.

Una estructura tiene la siguiente forma general:

struct nomb_estructura{ tipo nomb variablel; - - - - - - - - - - - -

tipo nomb_variablen; };

El ejemplo siguiente ilustra esto:

struct EsEmpdo{ char NombreCd[30]; char DireccionCd[30]; float SueldoRe; int CategoriaEn; }; - - - - - - - - - - struct EsEmpdo JuanEsEmpdo, PedroEsEmpdo, JoséEsEmpdo;

Puede declararse una o más variables de estructura en la declaración de una estructura, como se ilustra enseguida.

struc EsEmpdo{ char NombreCd[30];

char DireccionCd[30]; float SueldoRe; int CategoriaEn;

} JuanEsEmpdo, PedroEsEmpdo, JoséEsEmpdo;

Si la aplicación solo requiere el uso de la variable de estructura, no se requiere el nombre de la estructura, por ejemplo.

struct{ char NombreCd[30); char DireccionCd[30]; float SueldoRe; int CategoriaEn; } JuanEsEmpdo;

5.1 Como referenciar los elementos de un estructura

Página 132 de 207

Page 133: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Una estructura es útil cuando hacemos una referencia explícita a los elementos de la misma.

JuanEsEmpdo.CategoriaEn = 3;

Asigna el valor de 3 a la variable (campo) Categoría de la estructura Juan.

JuanEsEmpdo.SueldoRe = 1090.50;

Asigua el valor de 1090.50 al campo Sueldo de la estructura Juan.

JoseEsEmpdo.CategoriaEn = JuanEsEmpdo.CategoriaEn;

Asigna el valor del campo CategoríaEn de la estructura JuanEsEmpdo, al campo CategoríaEn de la estructura JoséEsEmpdo.

PedroEsEmpdo = JoséEsEmpdo;

Todos los valores de los campos en la estructura JoséEsEmpdo, se asignan a los campos correspondientes en la estructura PedroEsEmpdo.

5.2 Lectura y exhibición de los elementos de una estructura

A los campos de una estructura pueden asignárseles valores mediante una lectura y así mismo exhibirlos.

Ejemplos:

scanf(“%d %s”, JoseEsEmpdo.CategoriaEn, JoséEsEmpdo.NombreCd);

Asigna, mediante una lectura, valores a los campos CategoríaEn y NombreCd de la estructura JoséEsEmpdo.

printf (“%s %d”, JoséEsEmpdo.NombreCd, JoseEsEmpdo.CategoriaEn);

Exhibe los valores de los campos NombreCd y CategoríaEn de la estructura JoséEsEmpdo.

gets(PedroEsEmpdo.NombreCd);

Asigna, mediante una lectura, un valor al campo. Nombre de la estructura PedroEsEmpdo.

puts(PedroEsEmpdo.NombreCd);

Exhibe el valor del campo Nombre de la estructura PedroEsEmpdo.

Página 133 de 207

Page 134: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

puts(PedroEsEmpdo.NombreCd);

Exhibe el valor del campo Nombre de la estructura PedroEsEmpdo.

5.3 Elementos de estructura como argumentos en funciones

Los campos de las estructuras pueden aparacer como argumentos en funciones y ser pasados por valor y dirección.

Por valor

fnFn(JuanEsEmpdo.NombreCd[0]);

Pasan el valor carácter en la posición 0, del campo nombre de la estructura Juan.

fnFn(JuanEsEmpdo.CategoríaEn);

Pasan el valor entero del capo CategoríaCd de la estructura JuanEsEmpdo.

fnFn(juanEsEmpdo.SueldoRe);

Pasan el valor real del campo Sueldo de la estructura JuanEsEmpdo.

Por dirección

fnFn(JuanEsEmpdo.NombreCd);

Pasan la dirección del campo Nombre de la estructura JuanEsEmpdo.

fnFn(&JuanEsEmpdo.SueldoRe);

Pasan la dirección del campo Sueldo en la estructura JuanEsEmpdo.

5.4 Estructuras como argumentos en funciones

Una estructura como argumento puede ser pasada por valor o dirección.

Ejemplo:

Por valor

fnFn(struct Empdo LeticiaEsEmpdo);

Por dirección, en la definición de la funcion

fnFn(struct Empdo *LeticiaEsEmpdo);

Página 134 de 207

Page 135: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

en la llamada de la funcion

fnFn(&JuanaEsEmpdo);

5.5 Simplificación de la notación de las estructuras

La directiva typedef nos permite simplificar la notación de las estructuras en las declaraciones.

Ejemplo:

#typedef struct{ char NombreCd[30]; char Direccion[30]; float SueldoRe;

int CategoríaEn; } EMPDO;

- - - - - - - - - - - EMPDO JuanEsEMPDO, PedroEsEMPDO, JoséEsEMPDO;

5.6 Estructuras en estructuras

Es posible declarar una estructura dentro de otra (estructuras anidadas).

#typedef struct{ int DiaEn,

MesEn AñoEn;

} FECHA;

#typedef struct{ char NombreCd[30];

char DireccionCd[30]; float SueldoRe; int categoríaEn; FECHA FechaIngEsFECHA; } EMPDO;

- - - - - - - - - - - - - EMPDO JuanEsEMPDO; JuanEsEMPDO.fechaIngEsFECHA.DiaEn = 15; JuanEsEMPDO.fechaIngEsFECHA.DiaEn = 07; JuanEsEMPDO.fechaIngEsFECHA.DiaEn = 93;

5.7 Arreglos de estructuras

Página 135 de 207

Page 136: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Para definir un arreglo cuyos elementos sean estructuras, primero se define una estructura y luego se declara un arreglo de este tipo.

#typedef struct{ char NombreCd[30];

char DireccionCd[30]; float SueldoRe; int CategoríaEn;

} EMPDO; - - - - - - - - - - - - - - EMPDO NominaVcEsEMPDO[10]; NominaVcEsEMPDO[3].SueldoRe = 1325.251;

Una estructura puede tener un campo del tipo de un arreglo, hace referencia a los elementos del arreglo en la estructura como lo ilustra el ejemplo siguiente.

#typed struct{ int XVcEn[12], ConteoEn; } VECTOR; - - - - - - - - VECTOR AlfaEsVECTOR;

- - - - - - - - - - - for (iEn = 0, iEn < 12; iEn++){ scanf (“%d”, &AlfaEsVECTOR.XVcEn[iEn]); AlfaEsVECTOR.ConteoEn = --i; }

5.8 Estructuras con campos bits

La forma general de un campo de bit en una estructura es la siguiente:

Struct nomb_estructura{ tipo nom_campo: longitud; - - - - - - - - - - - - - - -

};

Un campo de bits puede tener de 1 a 16 bits. Un campo de bits puede ser de tipo int, unsigned o signed. Se el campo es un bit debe declararse como unsigned, debido a que un bit no puede tener signo.

5.9 Uniones

La declaración de una unión es muy similar a la de una estructura, sin embargo, funcionalmente son muy diferentes. La forma general de una unión es como se presenta:

Página 136 de 207

Page 137: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

union nomb_union{ tipo nomb_variablel;

- - - - - - - - - - - - - tipo nomb_variablen; };

El compilador para una unión, sólo reserva área de memoria para el campo con el mayor número de bytes. Esta área es común para todos los campos de la unión. Por ejemplo en la declaración:

union Uno{ char caraCa; int EnteroEn; };

Debido a que un carácter ocupa un byte un entero dos, se reservan dos bytes para la union Uno.

La declaración,

unión Uno BetaUnUno;

nos permite asignar a Beta un entero o un carácter en partes diferentes de un programa.

BetaUnUno.CaraCa = ‘A’; - - - - - - - - - BetaUnUno.EnteroEn = 12;

Página 137 de 207

Page 138: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 138 de 207

Page 139: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 8

Definición de Nuevos Tipos de Datos:Enumeraciones

Página 139 de 207

Page 140: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 140 de 207

Page 141: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno modelara, codificara y correrá programas que incluyen tipos de variables predefinidos por el usuario como son las enumeraciones.

Contenido

8.1 Enumeraciones8.2 Como referenciar los elementos de una estructura8.3 Lectura y exhibición de los elementos de una enumeración8.4 Elementos de estructura como argumentos en funciones8.5 Estructuras como argumentos en funciones8.6 Simplificación de la notación de las estructuras8.7 Estructuras en estructuras8.8 Arreglos en estructuras

Objetivos

Al terminar esta unidad, el alumno será capaz de utilizar:

1. Enumeraciones2. Referenciar los elementos de una estructura3. Leer y exhibir los elementos de una estructura4. Elementos de una estructura como argumentos en una función5. Estructuras como argumentos en funciones6. Estructuras anidadas7. Arreglos de estructuras8. Estructuras en campos de bits9. Uniones

Página 141 de 207

Page 142: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 142 de 207

Page 143: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

5.10 Enumeraciones

Introducción

Suponga que al codigo de un programa quiere darle mayor claridad para facilitar su lectura del mismo por otras personas. Digamos que para ello necesita variables de valores de verdad False y True (falso y cierto respectivamente) para obtener el máximo valor de un vector entero con diez elementos. Puesto que C carece de este tipo de variables, ud. tiene que crearlas recurriendo a las enumeraciones.

Enumeraciones

Una enumeración es un lista de valores constantes predefinidas por el programador. Una enumeración tiene la siguiente estructura general:

enum nomb_enumeración{ valor_constante0; - - - - - - - - - - - valor_constanteN;} lista de variables separadas por comas;

El compilador asocia un valor entero ordenado y consecutivo a la lista de valores constantes. Por ejemplo, el valor entero 0 lo asocia con valor_constante0, el valor entero 1 a valor_constante1 y así sucesivamente. El ejemplo siguiente declara la enumeracion Bool con False y True como valores constantes.

enum Boo{False, True};

Boo EsMayorFnBo(ValorEn1, ValorEn2){return Boo(ValorEn1 > ValorEn2);

}

void main(void){int XArEn[] = {2, 7, 3, 9, 45, 95, 23, 76, 12, 90};int ValorMayorEn = 2;

for(int iEn = 1; iEn <= 9; iEn++)if(EsMayorFnBo(XArEn[iEn], ValorMayorEn))

ValorMayorEn = XArEn[iEn];

printf(“El valor mayor es: %d\n”, ValorMayorEn);

Página 143 de 207

Page 144: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

}

A partir de la siguiente declaración ejemplo

enum dias{lunes, martes, miercoles, jueves, viernes, sabado, domingo};

podemos definir un subrango como sigue:

enum diaslabor lunes ... viernes;

otro subrango que podemos definir a partir de la primera declaración es la siguiente:

enum fin_semana sabado ... domingo;

El siguiente programa ilustra varios conceptos

enum dias{lunes, martes, miercoles, jueves, viernes, sabado, domingo};enum diaslabor lunes ... viernes;enum Boo{False, True};

struct Empdo{char NombreArCa[12];Boo DiasLaboradosArBoo[5];

};

void main(void){Empdo NominaEmpdo[3] = {{“Pepe”, {True, False, True, True, True}},

{“Juana”, {True, False, True, False, True}},{“Julia”, {True, True, True, True, True}}};

diaslabor laboroEm;

printf(“%s trabajo los días:\n”, Juan_Perez.NombreArCa);for(laboroEm = lunes; laboroEm <= viernes; laboroEm++) switch laboroEm { case lunes: (NominaEmpdo.[laboroEm])? printf(“lunes\n”):;

case martes: (Juan_Perez.[laboroEm])? printf(“martes\n”):; case miercoles: (Juan_Perez.[laboroEm])? printf(“miercoles\n”):;

case jueves: (Juan_Perez.[laboroEm])? printf(“jueves\n”):;case viernes: (Juan_Perez.[laboroEm])? printf(“viernes\n”):;

}}

- - - - - - - - - - -

enum dias semanal, semana2; - - - - - - - - - - - semana1 = lunes; semana2 = semanal; - - - - - - - - - - - if(semanal == martes)

Página 144 de 207

Page 145: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf(“Es martes \n”); - - - - - - - - - - - - - - - - - - - - - -

Es posible asignar, en la declaración, un valor entero especifico para uno o más de los identificadores que aparecen en una enumeración.

enum dias{ lunes; martes = 10; miercoles = 15; jueves; viernes; sabado = 100; domingo = 200; };

Los valores enteros asociados a los identificadores son:

lunes 0 martes 10 miercoles 15 jueves 16 viernes 17 sabado 100 domingo 200

Es un error intentar lo siguiente:

Semanal = viernes; printf(“%s”, semanal); Semana2 = “lunes”;

Página 145 de 207

Page 146: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 9

Archivos

Página 146 de 207

Page 147: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 147 de 207

Page 148: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno modelara, codificara y correrá programas que incluyan las operaciones más básicas de los archivos como son la apretura, la lectura, la escritura y el cierre.

Contenido

9.1 Apertura, Escritura y Cierre de un Archivo de Texto9.2 Apertura, Lectura y Cierre de un Archivo de Texto9.3 Apertura, Lectura y Escritura en Archivos Distintos y Cierre de Ambos

Archivos de Texto

Objetivos

Al terminar esta unidad, el alumno será capaz de:

1. Abrir, escribir en y cerrar un archivo de texto2. Abrir, leer y cerrar un archivo de texto3. Abrir, leer, escribir en distintos archivos de texto y cierre de estos

Página 148 de 207

Page 149: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Apertura, Escritura y Cierre de un Archivo de Texto

Con el conjunto de funciones fopen(), getc(), putc(), y fclose podemos ejemplificar la apertura, lectura, escritura y cierre de un archivo de texto. El siguiente es un ejemplo del uso de de las funciones fopen(), putc() y fclose(), ArchisEs es el nombre del programa que lee caracteres de teclado y los escribe en un archivo en disco hasta que que se digita un signo de pesos. El nombre del archivo se especifica en la línea de comando. Por ejemplo, si digita ArchisEs Prueba le permite ingresar lineas de texto en un archivo de nombre Prueba.

Include <stdio.h>

Main(int argc, char *argv[]){FILE *fp;Char ch;

If(argc != 2){Printf(“Olvido ingresar el nombre del archivo\n”);Return 1

}

if(fp = fopen(argv[1], “w”)) == NULL){printf(“No se puede abrir el archivo\n”);return 1;

}

do{ch = getchr();putc(ch, fp);

}while (ch != ‘$’);

fclose(fp);return 0;

}

Apertura, Lectura y Cierre de un Archivo de Texto

El programa complementario ArchisLee lee cualquier archivo de texto y muestra el contenido en la pantalla. Usted debe de especificar el nombre del archivo en la línea de comando.

Include <stdio.h>

Main(int argc, char *argv[]){FILE *fp;

Página 149 de 207

Page 150: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Char ch;

If(argc != 2){Printf(“Olvido ingresar el nombre del archivo\n”);Return 1

}

if(fp = fopen(argv[1], “r”)) == NULL){printf(“No se puede abrir el archivo\n”);return 1;

}

ch = getc(fp);

while(ch != EOF){putchar(ch);ch = getc(fp);

}

fclose(fp);return 0;

}

Apertura, Lectura y Escritura en Archivos Distintos y Cierre de Ambos Archivos de Texto

El siguiente programa copia un archivo de cualquier tipo. Observe que los Archivos están abiertos en modo binario y que se usa feof() para verificar el fina de archivo.

Include <stdio.h>

Main(int argc, char *argv[]){FILE *in, *out;Char ch;

If(argc != 3){Printf(“Olvido ingresar el nombre del archivo\n”);Return 1

}

if(in = fopen(argv[1], “rb”)) == NULL){printf(“No se puede abrir el archivo fuente\n”);return 1;

}

if(out = fopen(argv[1], “wb”)) == NULL){printf(“No se puede abrir el archivo destino\n”);return 1;

}

while(!foef(in)){ch getc(in);

Página 150 de 207

Page 151: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

if()!feof(in)) putc(ch, out);}

fclose(in);fclose(out);return 0;

}

Página 151 de 207

Page 152: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 10

El Apuntador a Variables Simples

Página 152 de 207

Page 153: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 153 de 207

Page 154: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno explicara los conceptos de identificadores estáticos, dinámicos, señalamiento directo, indirecto. Explicara la diferencia entre un apuntador y una referencia. Usara estos conceptos en sus programas.

Contenido

13.- El apuntador a variables simples13.1.- Introducción

13.1.1.- La notación Mex13.1.2.- La metodología

13.2.- Representación en memoria física del un apuntador13.2.1.- El apuntador a un carácter13.2.2.- El apuntador a un entero13.2.3.- El apuntador a un flotante13.2.4.- El apuntador a otro apuntador13.2.5.- Variables estáticas y dinámicas

Página 154 de 207

Page 155: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

13.1 Introducción

El uso de estructuras de datos complejas, que incluyen apuntadores, siempre ha dado innumerables dolores de cabeza aun a los programadores mas experimentados. Incluso a desalentado a muchos buenos programadores a aprender los lenguajes C y C++. Esta situación contribuye a acentuar el analfabetismo programático que parece darse con frecuencia entre los estudiantes de informática y computación y aun entre algunos profesionales de dichos campos del conocimiento. Una de las metas que nos hemos propuesto en el Laboratorio de Telemática es contribuir a abatir este analfabetismo mediante la aplicación rigurosa de estrategias de enseñanza aprendizaje. En el laboratorio hemos diseñado el lenguaje de modelos didácticos ontológicos (LeMoDOs), con el propósito de crear o diseñar entornos de enseñanza que facilitan el aprendizaje de un tópico de interés. Por cierto, esta es la idea central del proyecto DEEA (Diseño de Entornos para Enseñanza Aprendizaje). Con el LeMoDOs queremos incidir, primero, en aquellos tópicos que parecen ser de difícil asimilación por los estudiantes de la carrera de Ingeniero en Computación, por ejemplo en la práctica de la programación con el lenguaje C hemos identificado diversos dominios de problemas que hemos resuelto con el LeMoDOs de árboles sistémicos y la notación Méx, solo por mencionar dos. Esta investigación nos ha llevado a trabajar en un campo de conocimiento más amplio que hemos denominado Programática Educacional, en otras palabras, en una didáctica de los sistemas de software.

La notación Mex o notamex por brevedad, junto con los diagramas Mex o diagramex por brevedad, ofrecen las siguientes bondades:

Nemónica .- Su valor nemónico es invaluable, ya que nos proporciona información explicita del tipo y estructuras de datos involucrados en los identificadores. Un identificador derivado con las reglas de la notación Mex, consiste de un calificador, este es un nombre antepuesto al constructor, indica el propósito del identificador y conduce a nombres únicos. El constructor, una serie de postfijos al calificador, que indica los tipos de datos involucrados y finalmente el tipo base que indica el tipo del identificador.

calificador, constructor, tipo base Alfa, ApArApFnAp, En

Beta, ApArApFnAp, En

Sugestiva .- La metáfora visual que proporcionan los diagramas Méx junto con el valor nemónico de los identificadores, facilitan enormemente la comprensión de los tipos y estructuras de datos asociados con estos últimos. Esta es una cualidad muy valiosa cuando se trabaja en equipo, todos hablan el mismo idioma y hay menos errores de comunicación. Eleva el nivel del conocimiento de la codificación de los programas.

Consistente .- La notación es simple porque se obtiene de manera natural de un enunciado coloquial o de su equivalente, el diagrama Méx. Es general por ser independiente de cualquier lenguaje de programación y, es sistemática porque se basa en reglas precisas que

Página 155 de 207

Page 156: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

cualquiera puede seguir sin dificultad. Estas características la hacen una notación robusta y con un gran potencial para extender sus aplicaciones, por ejemplo, en la abstracción de datos. Facilita el seguimiento de los identificadores a lo largo y ancho de los programas.

Normativa .- La notación puede establecerse como una de las normas en los ambientes de desarrollo de software, (1) por ser un valioso auxiliar en la depuración de software, (2) por promover la autodocumentación de los mismos (3) por facilitar la comunicación entre los desarrolladores (todos hablan el mismo lenguaje) y (4) por ser una valiosa herramienta de auditoría.

Didáctica .- El valor didáctico de la notación es incuestionable, de sobra son conocidas las complejidades en C/C++ con los apuntadores, particularmente cuando estos aparecen combinados con otras estructuras de datos, aún para los programadores más experimentados. El uso de la notación simplifica enormemente esta complejidad. Los alumnos informan que la notación Méx eleva su nivel del lenguaje C, programan con más agilidad y les ayuda a comprender mejor la POO.

Profesional.- No solo el valor didáctico de la notación es incuestionable, sino que también lo es en el campo profesional. Aquí el impacto sería considerable en el ahorro de costos, tiempo y esfuerzo.

El uso de la notación Méx es muy simple, podría decirse que su uso es trivial, sin embargo, la practica es esencial para dominar el uso de la notación.

La notación Méx

La notación Méx es un entorno de enseñanza que facilita el aprendizaje de estructuras de datos complejas que incluyen apuntadores en el lenguaje C/C++. La notación ya ha sido ampliamente probada en el salón de clase donde ha

Página 156 de 207

Page 157: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

mostrado ser de amplia utilidad en la práctica de la programación. Los alumnos informan de que la notación eleva su nivel de C, programan con mayor agilidad y les facilita la comprensión de la POO. En algunos casos, la aplicabilidad de los modelos didácticos, va más allá del ámbito de las aulas, tal es el caso de la notación Méx, la cual es también de gran utilidad en la practica profesional de la programación con los lenguajes C y C++ y aún con otros lenguajes como Delphi. Por lo que, y este es el caso, se hace una doble contribución; tanto en el ámbito académico como el profesional.

13.1.2 La metodología (Reglas de Asociación)

El modelo didáctico para la notación Mex es un método o conjunto de reglas simples, generales y sistemáticas. La notación se origina con un enunciado coloquial acerca de una declaración inicial (la primer semilla) de una estructura compleja, por ejemplo, considérese el siguiente ejemplo:

      p es un Apuntador a un Arreglo de dos Apuntadores a Enteros.

Yuxtaponiendo las partículas resaltadas tenemos lo que llamamos la primer semilla

pApArApEn

donde

calificador constructor tipo base

p ApArAp En

la expresión pApArApEn, es la notación Méx, tiene la propiedad de representar, de manera única, a un identificador de un tipo específico de una variable. Si se requiere de más de una variable del mismo tipo basta con introducir diferentes calificadores, por ejemplo:

      pApArApEn, qApArApEn, xApArApEn, wApArApEn, etc.

Nótese que la primera partícula es el calificador. El siguiente paso consiste en asociar a la notación Méx con la sintaxis de C, o con la sintaxis de Delphi, o la sintaxis de cualquier otro lenguaje de programación. Esta flexibilidad hace de la notación independiente del lenguaje a utilizar en un proyecto.

13.2 Representación en memoria física de un apuntador

Página 157 de 207

Page 158: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La memoria física principal de una computadora es una ristra de localidades contiguas y numeradas del 0 al n – 1 como muestra el siguiente diagrama

Notése que la primera localidad tiene asociado el entero 0 y la ultima el entero n – 1, por lo que el número total de localidades es n. Cada localidad representa un byte, la unidad minima de información. Por consición imaginemos a la memoria como un arreglo de (n/2)x2, es decir:

Un apuntador en memoria física lo representamos de la siguiente manera. Notése que este ocupa tres hileras. Para no sobrecargar el diagrama de memoria física, omitimos, en las siguientes secciones, la numeración de la izquierda, esta queda sobreentendida.

Página 158 de 207

0

n - 1

0

n/2 - 2

2

n/2 - 1

1

3

Page 159: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

6.4 Apuntador a un carácter

Un apuntador señala o apunta a una localidad de memoria donde esta almacenado un valor dado. En el diagrama siguiente – localidades de memoria - se muestran dos apuntadores SenalaApCa – Senala es un Apuntador a un Carácter – y ApuntaApCa - Apunta es un Apuntador a un Carácter – que señalan a la localidad de memoria CaraCa – Cara es un Carácter - en la cual se encuentra almacenado el carácter A.

El código del siguiente programa implementa la situación del diagrama anterior después de haber corrido o ejecutado el programa.

#include <stdio.h>

void main(void){char CaraCa = ‘A’; // se inicia en tiempo de compilación

Página 159 de 207

ApuntaApCa

SenalaApCa

CaraCa AAA

3

n/2 - 2

2

4

0

6

Page 160: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

char *ApuntaApCa;char *SenalaApCa = &CaraCa; // se inicia en tiempo de

compilación

ApuntaApCa = &CaraCa; // se inicia en tiempo de corridaprinft(“%c”, *SenalaApCa, *ApuntaApCa, CaraCa);

}

en la declaración

char CaraCa = ‘A’;

tenemos una expresión de igualdad que indica al compilador – y al programador – que el identificador variable a la izquierda – CaraCa - es una variable de tipo carácter y el de la derecha – ‘A’ - es un identificador constante de tipo carácter con el que se inicia en tiempo de compilación a la variable CaraCa.En la segunda declaración

char *ApuntaApCa;

el asterisco antepuesto al identificador variable ApuntaApCa es un operador unario que indica al compilador y al programador, que esta es una variable apuntador, es decir, una variable que va a contener la dirección de una localidad de memoria. La frase coloquial

Apunta es un Apuntador a un Carácter.

Se condensa como ApuntaApCa de acuerdo a lo subrayado. Este nombre de variable lo tomamos como un identificador variable porque tiene la propiedad de ser único. La particula Apunta es el cualificador de la variable que expresa en forma consisa y legible el propósito de esta. La última particula Ca nos indica el tipo de la variable. Lo que tenemos ahora es la notación Mex respecto a apuntadores, a la cual podemos asociar la sintaxis de apuntadores del lenguaje C, con lo que obtenemos la regla del apuntador a un carácter como sigue:

Leemos la variable de izquierda a derecha comenzando con la particula Ap y le anteponemos un asterisco y encerramos a toda la expresión con un par de paréntesis redondos

(*ApuntaApCa)

si estos paréntesis son los más externos pueden omitirse, como este es el caso los omitimos

*ApuntaApCa

Página 160 de 207

Page 161: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

continuamos con la particula Ca, la última, que es la que expresa el tipo de la variable. Anteponemos a toda la expresión el tipo de acuerdo a la sintaxis de C.

int *ApuntaApCa

finalmente ponemos el punto y coma al final de toda la expresión.

int *ApuntaApCa;

Las reglas para un apuntador a un entero y un apuntador a un flotante son muy similares.

En la tercera declaración

char *SenalaApCa = &CaraCa;

Tenemos una expresión de igualdad con una variable apuntador, a la derecha, que se inicia, en tiempo de compilación, con la dirección de la localidad de memoria de nombre CaraCa, a la derecha de la expresión, que contiene al carácter ‘A’.La variable de tipo carácter CaraCa esta precedida por el operador unario &, el cual indica al compilador y al programador, que obtiene la dirección de CaraCa y la igualdad indica que se asigna al apuntador.

En la instrucción

ApuntaApCa = &CaraCa;

La variable apuntador se inicia, en tiempo de corrida, con la dirección de la localidad de memoria de nombre CaraCa.

Notése que las sintaxis de las variables SenalaApCa y ApuntaApCa en sus declaraciones

char *ApuntaApCa;char *SenalaApCa = &CaraCa;

son muy similares en la instrucción

prinft(“%c”, *SenalaApCa, *ApuntaApCa, CaraCa);

Página 161 de 207

Page 162: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

en ambos casos los nombres de las variables estan precedidas por un asterisco, sin embargo, estan en contextos diferentes, en el primer caso en el de las declaraciones y en el segundo en el de las instrucciones. En el contexto de las declaraciones su significado es el que expresa la notación Mex. En el contexto de las instrucciones significa el valor señalado por, es decir

*ApuntaApCa el valor señalado por ApuntaApCa

este valor señalado es el carácter ‘A’. El símbolo significa “es equivalnte a”

6.5 Apuntador a un entero

El apuntador a un entero es muy similar al de un carácter, mientras que un carácter ocupa un byte, un entero ocupa dos bytes.

El código del siguiente programa implementa la situación del diagrama anterior después de haber corrido o ejecutado el programa..

#include <stdio.h>

void main(void){int ValorEn = 10;int *ApuntaApEn;int *SenalaApEn = &ValorEn;

ApuntaApEn = &ValorEn;prinft(“%d”, *SenalaApEn, *ApuntaApEn, ValorEn);

}

6.6 Apuntador a un flotante

Página 162 de 207

ApuntaApEn

SenalaApEn

ValorEn AA 10

Page 163: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El apuntador a un flotante es muy similar al de un entero, mientras que un entero ocupa dos bytes, un flotante ocupa cuatro bytes.

El código del siguiente programa implementa la situación del diagrama anterior después de haber corrido o ejecutado el programa..

#include <stdio.h>

void main(void){float ValorRe = 1.45;float *ApuntaApRe;float *SenalaApRe = &ValorRe;

ApuntaApRe = &ValorRe;prinft(“%f”, *SenalaApRe, *ApuntaApRe, ValorRe);

}

6.6’ Apuntador a un apuntador

El diagrama siguiente muestra gráficamente, da una idea, de lo que es un apuntador que señala a otro apuntador que, a su vez señala a una variable fotante.

Página 163 de 207

ApuntaApRe

SenalaApRe

ValorRe AA1.45

ApuntaApRe

SenalaApApRe

ValorReAA15.07

Page 164: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El código del siguiente programa implementa la situación del diagrama anterior después de haber corrido o ejecutado el programa..

#include <stdio.h>

void main(void){int ValorRe = 15.07;int *ApuntaApRe = &ValorRe;int *(*SenalaApApRe) = &ApuntaApRe;

prinft(“%f”, *(*SenalaApApRe), *ApuntaApRe, ValorRe);}

Página 164 de 207

Page 165: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 11

Arreglos y Apuntadores

Página 165 de 207

Page 166: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 166 de 207

Page 167: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno explicara la relación entre un apuntador constante y el nombre de los arreglos. Usara apuntadores a arreglos, arreglos de apuntadores y usara identificadores en los que intervienen apuntadores, arreglos y otros en sus programas.

Contenido

14.- Arreglos y apuntadores14.1- Introducción

14.1.1- La relación entre un apuntador variable y el nombre de un arreglo

14.2.- Representación en memoria física del arreglo14.2.1.- El apuntador variable a un arreglo14.2.2.- Identificadores en los que intervienen apuntadores y arreglos

14.3.- Resumen14.4.- Ejercicios

Página 167 de 207

Page 168: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

14.0 Introducción

Entre los apuntadores y los arreglos, en el lenguaje C / C++, existe una sinergia que potencia enormemente la flexibilidad de uso de ambos cuando aparecen yuxtapuestos en una expresión de la notación Méx. La regla a seguir es muy simple, sin embargo, su aplicación demanda del aprendiente una sostenida actitud de autodisciplina.

14.1 La sinergia entre un apuntador variable y el nombre de un arreglo

El siguiente enunciado expresa la relación que hay entre un apuntador y el nombre de un arreglo en el lenguaje C / C++:

Hacemos hincapié en que elEl nombre de un arreglo es un apuntador constante que señala al primer elemento del mismo y no al arreglo como un todo.

Ahora, para efectos de discernimiento, considere los dos siguientes enunciados y sus semillas correspondientes

Senala es un Apuntador a un Entero SenalaApEnSenala es un Apuntador a un Arreglo de Enteros SenalaApArEn

¿ Que enunciado es compatible con el de hincapié ? Obviamente el primero, ya que el segundo indica que el apuntador señala al arreglo como un todo. Esto significa que si el nombre de un arreglo de enteros es; XArEn – X es el Arreglo de Enteros – y el nombre de un apuntador a un entero es; pApEn - p es un Apuntador a un Entero - entonces los identificadores variables XArEn y pApEn son compatibles.En la siguiente Figura aparecen XArEn y pApEn como apuntadores que señalan al primer elemento del arreglo en memoria.

Página 168 de 207

SenalaApEn

XArEn

1542

Page 169: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

El código del siguiente programa implementa la situación del diagrama anterior después de haber corrido o ejecutado el programa.

#include <stdio.h>

void main(void){int *SenalaApEn;int XArEn[2] = {15, 42}; // XArEn se inicia en tiempo de

compilación

SenalaApEn = XArEn; // SenalaApEn se inicia en tiempo de corrida

printf(“%d %d\n”, XArEn[0], XArEn[1]);printf(“%d %d\n”, SenalaApEn[0], SenalaApEn[1]);

}

Notese que en

int XArEn[2] = {15, 42};

el arreglo XArEn se inicia - en tiempo de compilación - con los valores de 15 y 42, y en

SenalaApEn = XArEn;

la variable apuntador SenalaApEn se inicia con el valor del nombre del arreglo - en tiempo de corrida - debido a que como ya se señaló son compatibles.

Por otra parte, notese que en

printf(“%d %d\n”, SenalaApEn[0], SenalaApEn[1]);

la variable apuntador SenalaApEn puede asumir el papel del nombre del arreglo, con la diferencia de que este nombre es una variable y no una constante.

Las notaciones del arreglo y del apuntador son intercambiales cuando son compatibles, por ejemplo:

XArEn[1] ≡ *(XArEn + 1)

*(SenalaApEn + 1) ≡ SenalaApEn[1]

El símbolo ≡ significa ... es igual a ... , esta intercambiabilidad se ilustra con el programa anterior y el siguiente. Ambos son idénticos en su codificación, salvo en los enunciados que muestran los resultados, pero realizan las mismas funciones debido a que son intercambiables.

Página 169 de 207

Page 170: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

#include <stdio.h>

void main(void){int *SenalaApEn;int XArEn[2] = {15, 42}; // XArEn se inicia en tiempo de

compilación

SenalaApEn = XArEn; // SenalaApEn se inicia en tiempo de corrida

printf(“%d %d\n”, *(XArEn + 0), *(XArEn + 1));printf(“%d %d\n”, *(SenalaApEn + 0), *(SenalaApEn +

1));}

14.2 La regla del arreglo

La regla del arreglo es muy simple, asocia la sintaxis de los arreglos a la semilla. Considere el enunciado:

X es un Arreglo de dos Enteros

Su semilla correspondiente es:

XArEn

Examinamos la expresión de izquierda a derecha, comenzando con la segunda partícula (Ar), esta nos indica que debemos yuxtaponer a la derecha la sintaxis correspondiente de un arreglo, es decir:

XArEn[2]

La siguiente y última partícula es la base, la base siempre se coloca a la izquierda de la expresión siguiendo la sintaxis de C.

int XArEn[2];

Pasemos ahora a resolver tres problemas básicos en los que intervienen arreglos y apuntadores

14.2.1.- Identificadores en los que intervienen apuntadores y arreglos

En esta sección se resuelven tres problemas que incluyen apuntadores y arreglos. Cada problema contiene un enunciado, su diagrama Méx correspondiente y la solución al mismo.

Problema 1

Página 170 de 207

Page 171: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

EnunciadoEl enunciado es una declaración coloquial de cómo diferentes tipos de datos estan asociados, por ejemplo:

X es un Arreglo de dos Apuntadores a Enteros.

Solamente aparecen parcialmente subrayados los sustantivos correspondientes a los tipos de datos que intervienen en la declaración. A estas letras subrayadas, las denominamos partículas y nos sirven como una abreviatura para obtener una notación concisa única.

DiagramaEs una notación concisa única – consiste de caracteres ASCCI - obtenida a partir del enunciado coloquial

XAr[2] -> En

SoluciónEl enunciado se separa con paréntesis angulados como sigue: Solo aparece una palabra subrayada en cada separación, excepto en la primera, la que contiene el verbo ser o estar es.

<X es un Arreglo de dos> <Apuntadores a> <Enteros>

Ahora, solo considerando las partículas, concatene toda la expresión como sigue:

<XAr><Ap><En>

Aplique la regla del arreglo a la primera partícula como sigue:

XAr<Ap><En>[2]

Nótese que se ha postconcatenado el elemento [2] al final de la expresión y se han suprimido los paréntesis correspondientes de la partícula XAr. Enseguida aplicamos la regla del apuntador a toda la expresión

*XArAp<En>[2]

Ahora se ha preconcatenado el elemento * a la expresión y se han suprimido los paréntesis correspondientes de la partícula Ap. Luego aplicamos la regla del tipo base como sigue:

int *XArApEn[2];

Obsérvese que hemos antepuesto, separado por un blanco, la palabra reservada int, suprimido los paréntesis y finalmente hemos colocado al final de la expresión el punto y coma (;). Hasta aquí hemos obtenido la primera semilla; el arreglo,

Página 171 de 207

Page 172: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

ahora vamos por la segunda; el apuntador. Ahora iniciamos un proceso de reducción. Escribiendo el identificador del resultado anterior como sigue:

<XarAp><En>int *XArApEn[2];

Ahora lo subrayado se sustituye por un nombre elegido por el programador, por ejemplo; Alfa

<AlfaAp><En> // <Alfa es un Apuntador a un> <Entero>int *XArApEn[2];

pero notese que necesitamos dos apuntadores porque el arreglo es de dos apuntadores, entonces

<AlfaAp><En> // {Alfa es un Apuntador a un} {Entero}<BetaAp><En> // {Beta es un Apuntador a un} {Entero}int *XArApEn[2];

Ahora aplicamos primero la regla del apuntador y luego la del tipo – quitamos lo subrayado - y obtenemos

int *AlfaApEn; // Alfa es un Apuntador a un Enteroint *BetaApEn; // Beta es un Apuntador a un Enteroint *XArApEn[2]; // X es un Arreglo de dos Apuntadores a Enteros

<AlfaApEn><BetaApEn>int *AlfaApEn; // Alfa es un Apuntador a un Enteroint *BetaApEn; // Beta es un Apuntador a un Enteroint *XArApEn[2]; // X es un Arreglo de dos

Apuntadores a Enteros

<AEn><BEn>int *AlfaApEn; // Alfa es un Apuntador a un Enteroint *BetaApEn; // Beta es un Apuntador a un Enteroint *XArApEn[2]; // X es un Arreglo de dos

Apuntadores a Enteros

int *AEn;int *BEn;int *AlfaApEn; // Alfa es un Apuntador a un Enteroint *BetaApEn; // Beta es un Apuntador a un Enteroint *XArApEn[2]; // X es un Arreglo de dos

Apuntadores a Enteros

Página 172 de 207

Page 173: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int *AEn = 5;int *BEn = 10;int *AlfaApEn; // Alfa es un Apuntador a un Enteroint *BetaApEn; // Beta es un Apuntador a un Enteroint *XArApEn[2]; // X es un Arreglo de dos

Apuntadores a Enteros

int *AEn = 5;int *BEn = 10;int *AlfaApEn = &AEn; // Alfa es un Apuntador a un

Enteroint *BetaApEn = &BEn; // Beta es un Apuntador a un

Enteroint *XArApEn[2]; // X es un Arreglo de dos

Apuntadores// a Enteros

int *AEn = 5;int *BEn = 10;int *AlfaApEn = &AEn; // Alfa es un Apuntador a un

Enteroint *BetaApEn = &BEn; // Beta es un Apuntador a un

Enteroint *XArApEn[2] = {AlfaApEn, BetaApEn }; // X es un

Arreglo de dos// Apuntadores a Enteros

#include <stdio.h>#include <conio.h>

void main(void){ int AEn = 5; int BEn = 10; int *AlfaApEn = &AEn; int *BetaApEn = &Ben; int *XArApEn[2] = {AlfaApEn, BetaApEn};

clrscr(); printf("%d %d", AEn, BEn); printf("%d %d", *AlfaApEn, *BetaApEn); printf("%d %d", *XArApEn[0], *XArApEn[1]); getch();}

Problema 2

Página 173 de 207

Page 174: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Enunciado

p es un Apuntador a un Arreglo de dos Enteros.

Diagrama

p -> Ar[2] En

Solución

#include <stdio.h>#include <conio.h>

void main(void){ int XArEn[2] = {1, 2}; int (*pApArEn)[2] = (int ((*)[2]))XArEn;

clrscr(); printf("%d %d\n", XArEn[0], XArEn[1]); printf("%d %d", (*pApArEn)[0], (*pApArEn)[1]); getch();}

Se propone el siguiente problema del cual se proporciona la solución. El lector debe aplicar sistematicamente las reglas previamente utilizadas en los dos ejemplos anteriores. Este tercer problema combina a los dos anteriores. Problema 3

Enunciado

p es un Apuntador a un Arreglo de dos Apuntadores a Enteros.

Diagrama

p->Ar[2]->En

Solución

// p es un Apuntador a un Arreglo de dos Apuntadores a Enteros

// p->Ar[2]->En

#include <stdio.h>#include <conio.h>

Página 174 de 207

Page 175: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

void main(void){ int AEn = 1; int BEn = 2; int *AlfaApEn = &Aen; int *BetaApEn = &Ben; int *XArApEn[2] = AlfaApEn, BetaApEn}; int *(*pApArApEn)[2] = (int (*(*)[2]))XArApEn;

clrscr(); printf("%d %d\n", AEn, BEn); printf("%d %d\n", *AlfaApEn, *BetaApEn); printf("%d %d\n", *XArApEn[0], *XArApEn[1]); printf("%d %d", *(*pApArApEn)[0], *(*pApArApEn)[1]); getch();}

Página 175 de 207

Page 176: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 12

Funciones y Apuntadores

Página 176 de 207

Page 177: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 177 de 207

Page 178: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno explicara la relación entre un apuntador constante y el nombre de las funciones. Usara apuntadores a funciones, funciones que devuelven apuntadores y usara identificadores en los que intervienen apuntadores, arreglos, funciones y otros en sus programas.

Contenido

16.- Funciones y apuntadores16.1- Introducción16.2.- Representación física (memoria) y lógica (visual) de la función

16.2.1.- El nombre de una función como un apuntador constante16.2.2.- El identificador apuntador a una función16.2.3.- Identificadores en los que intervienen apuntadores, arreglos y funciones

16.3.- Resumen16.4.- Ejercicios

Página 178 de 207

Page 179: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

15.0 Introducción

Entre los apuntadores y las funciones, en el lenguaje C / C++, también existe una sinergia que potencia enormemente la flexibilidad de uso de ambos cuando aparecen yuxtapuestos en una expresión de la notación Méx. La regla a seguir también es simple, sin embargo, su aplicación demanda del aprendiente una sostenida actitud de autodisciplina.

14.1 La sinergia entre un apuntador variable y el nombre de una función

El siguiente enunciado expresa la relación que hay entre un apuntador y el nombre de una función en el lenguaje C / C++:

El nombre de una función es un apuntador constante que señala a la primer instrucción de la función.

Considere los dos enunciados siguientes:

Alfa es una Función(dos argumentos enteros) Entera {devuelve la suma de sus dos argumentos Enteros}

P es un Apuntador a una Función(dos argumentos Enteros) Entera {devuelve la suma de sus dos argumentos Enteros}

Obtenemos

int AlfaFnEn(int AEn, int BEn){return (AEn + BEn);

}

void main(void){int (*PApFnEn)(int, int);

PApFnEn = AlfaFnEn;

printf(“%d”, PApFnEn(5, 5));}

La segunda partícula nos indica que debemos yuxtaponer a la derecha de la expresión la sintaxis para una función, es decir:

AlfaFnEn(...)

Colocamos el argumento

AlfaFnEn(AEn)

Luego la base y el punto y coma.

Página 179 de 207

Page 180: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Int AlfaFnEn(AEn);

Con lo que hemos obtenido el prototipo de una función.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++6.7 La Regla del Apuntador.

Esta regla asocia la sintaxis de apuntadores a la notación. Considere el enunciado:

p es un Apuntador a un Entero.

Tenemos

pApEn

la segunda partícula nos indica que debemos yuxtaponer a la derecha de la notación un asterisco y luego parentizar toda la expresión.

(*pApEn)

consideremos la base y el punto y coma.

int (*pApEn);

El paréntesis más externo siempre se omite, este es el caso, luego:

Int *pApEn;

Expresiones más complejas. Le sorprenderá la flexibilidad que se logra con tan solo estas tres reglas simples, para mostrarlo consideremos un ejemplo más elaborado.

q es un Apuntador a un Arreglo de dos Apuntadores a Enteros.

La notación Mex es:

qApArApEn

Utilizando dos de las tres reglas

int *(*qApArApEn)[2];

Otro ejemplo. Considere el siguiente:

p es un Apuntador a un Arreglo de Apuntadores a Funciones Apuntador a dos Enteros.

Página 180 de 207

Page 181: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

La notación es:

pApArApFnApEn

aplicando las tres reglas dadas antes.

int *(*(*pApArApFnApEn)[2])(void);

Si duda de la veracidad de una de las expresiones obtenidas verifíquelas en su compilador C o C++ de su preferencia.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

14.2.2.- Identificadores en los que intervienen apuntadores y funciones

En esta sección se resuelven tres problemas que incluyen apuntadores y funciones. Cada problema contiene un encunciado, su diagrama Mex correspondiente y la solución al mismo.

Problema 1/*Enunciado

y es una Función Apuntador a un Entero.-----------------------------------------------Diagrama

y Fn() -> EnSolución*/

#include <stdio.h>#include <conio.h>

int *yFnApEn(void){ int *AApEn = new int;

*AApEn = 8; return AApEn;}

void main(void){ clrscr(); printf("%d", *yFnApEn()); getch();

}

Página 181 de 207

Page 182: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Problema 2/*Enunciado

q es un Apuntador a una Función Entera.---------------------------------------------Diagrama

q -> Fn() EnSolución*/

#include <stdio.h>#include <conio.h>

int AFnEn(void){ return 12;}

void main(void){ int (*qApFnEn)(void) = AFnEn;

clrscr(); printf("%d ", AFnEn()); printf("%d", (*qApFnEn)()); getch();}

Problema 3/*Enunciado

q es un Apuntador a una Función Apuntador a un Entero.------------------------------------------------------------Diagrama

q -> Fn() -> EnSolución*/

#include <stdio.h>#include <conio.h>

int *wFnApEn(void){ int *AApEn = new int;

*AApEn = 8; return AApEn;}

void main(void){ int *(*qApFnApEn)(void) = wFnApEn;

clrscr(); printf("%d ", *wFnApEn()); printf("%d", *(*qApFnApEn)()); getch();}

Problema 4/*

Página 182 de 207

Page 183: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

EnunciadoX es un Arreglo de dos Apuntadores a Funciones Enteras.

-------------------------------------------------------------

DiagramaX Ar[2] -> Fn() En

Solución*/

#include <stdio.h>#include <conio.h>

int AFnEn(void){ return 5;}

int BFnEn(void){ return 10;}

void main(void){ int (*XArApFnEn[2])(void) = {AFnEn, BFnEn};

clrscr(); printf("%d %d\n", AFnEn(), BFnEn()); printf("%d %d", (*XArApFnEn[0])(), (*XArApFnEn[1])()); getch();}

Problema 5/*Enunciado

X es un Arreglo de dos Apuntadores a Funciones Apuntador a Enteros.-------------------------------------------------------------------------Diagrama

X Ar[2] -> Fn() -> En Solución*/

#include <stdio.h>#include <conio.h>

int *AFnEn(void){ int *AApEn = new int; *AApEn = 5; return AApEn;}

int *BFnEn(void){ int *BApEn = new int; *BApEn = 10; return BApEn;}

void main(void){ int *(*XArApFnApEn[2])(void) = {AFnEn, BFnEn};

clrscr(); printf("%d %d\n", *AFnEn(), *BFnEn());

Página 183 de 207

Page 184: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

printf("%d %d", *(*XArApFnApEn[0])(), *(*XArApFnApEn[1])()); getch();}

Problema 6/*Enunciado

p es un Apuntador a un Arreglo de dos Apuntadores a Funciones Enteras.

Diagrama

p -> Ar[2] -> Fn() En

Solución*/

#include <stdio.h>#include <conio.h>

int AFnEn(void){ return 5;}

int BFnEn(void){ return 10;}

void main(void){ int (*XArApFnEn[2])(void) = {AFnEn, BFnEn}; int (*(*pApArApFnEn)[2])() = (int (*(*)[2])())XArApFnEn;

clrscr(); printf("%d %d\n", AFnEn(), BFnEn()); printf("%d %d\n", (*XArApFnEn[0])(), (*XArApFnEn[1])()); printf("%d %d", (*(*pApArApFnEn)[0])(), (*(*pApArApFnEn)[1])()); getch();}

Problema 7/*Enunciado

p es un Apuntador a un Arreglo de dos Apuntadores a FuncionesApuntador a Enteros.

Diagrama

p |-> Ar[2] |-> Fn() |-> En

Solución*/

#include <stdio.h>#include <conio.h>

int *AFnApEn(void){

Página 184 de 207

Page 185: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int *AApEn = new int; *AApEn = 5; return AApEn;}

int *BFnApEn(void){ int *AApEn = new int; *AApEn = 10; return AApEn;}

void main(void){ int *(*XArApFnApEn[2])(void) = {AFnApEn, BFnApEn}; int *(*(*pApArApFnApEn)[2])() = (int *(*(*)[2])())XArApFnApEn;

clrscr(); printf("%d %d\n", *AFnApEn(), *BFnApEn()); printf("%d %d\n", *(*XArApFnApEn[0])(), *(*XArApFnApEn[1])());

printf("%d %d", *(*(*pApArApFnApEn)[0])(), *(*(*pApArApFnApEn)[1])());

getch();}

Página 185 de 207

Page 186: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 13

Estructuras y Apuntadores

Página 186 de 207

Page 187: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 187 de 207

Page 188: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno explicara la diferencia entre la notación de flecha y la notación de punto. Usara apuntadores a estructuras e identificadores en los que intervienen apuntadores, arreglos, funciones y estructuras en sus programas.

Contenido

17.- Estructuras y apuntadores17.1.- Introducción17.2.- Representación física (memoria) y lógica (visual) de la estructura

17.2.1.- Apuntadores y estructuras17.2.2.- Identificadores en los que intervienen apuntadores y estructuras 17.2.3.- Identificadores en los que intervienen apuntadores, estructuras, arreglos y funciones

Página 188 de 207

Page 189: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Esta regla asocia la sintaxis de apuntadores a la notación. Considere el enunciado:

p es un Apuntador a X Estructura con:q es un apuntador a un Vector de dos Enteros yr es una Función Entera.

La notación Mex es:

pApXEs

aplicando las reglas vistas con anterioridad tenemos

XEs *pApXEs;

Nótese que hemos usado XEs como la partícula base. Ahora hay que declarar a la estructura (variable) a la que ha de señalar el apuntador.

XEs LaXEs;XEs *pApXEs;

Finalmente declaramos a la estructura (tipo de variable) utilizando la palabra reservada struct.

int AlfaFnEn(void){return 10;

}

struct XEs{int *qApVcEn[2];Int rFnEn(void);

};

XEs LaXEs;XEs *pApXEs;

Ahora iniciamos en tiempo de compilación a todas las variables correspondientes en las declaraciones.

int AlfaFnEn(void){return 10;

}

struct XEs{

Página 189 de 207

Page 190: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int *qApVcEn[2];Int rFnEn(void);

};

XEs LaXEs = {&{5, 7}, AlfaFnEn};XEs *pApXEs = &LaXEs;

Página 190 de 207

Page 191: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Problema 1/* Enunciado

Una Es W con q es un Apuntador a un Carácter y

B es un Entero.++++++++++++++++++++++++++++++++++++++++++++++Diagrama

Es X { q -> Ca

B En}

Solución

*/#include <stdio.h>#include <conio.h>

typedef struct{ char *qApCa; int BEn;}EsX;

void main(void){ char ACa = 'A'; EsX XEsEsX = {&ACa, 10};

clrscr(); printf("%c %d", *EsX.qApCa, EsEsX.BEn); getch();}

Problema 2/*Enunciado

p es un Apuntador a una Es X con A es un Carácter y B es un Entero.++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

B En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int BEn;

Página 191 de 207

Page 192: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

}EsX;

void main(void){ EsX XEsX = {'A', 10}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c %d\n", XEsX.ACa, XEsX.BEn); printf("%c %d", (*pApEsX).ACa, (*pApEsX).BEn); getch();}

Problema 3/*Enunciado

p es un Apuntador a una Estructura X con: A es un Carácter y q es un Apuntador a un Entero.+++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *qApEn;}EsX;

void main(void){ int AEn = 5; EsX XEsX = {'A', &AEn}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c %d\n", XEsX.ACa, *XEsX.qApEn); printf("%c %d", (*pApEsX).ACa, *(*pApEsX).qApEn); getch();}

Problema 4/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y X es un Arreglo de dos Enteros.+++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

Página 192 de 207

Page 193: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

X Ar[2] En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int XArEn[2];

}EsX;

void main(void){ EsX AEsX = {'A', {5, 10}}; EsX *pApEsX = &AEsX;

clrscr(); printf("%c %d %d\n", AEsX.ACa, AEsX.XArEn[0], AEsX.XArEn[1]); printf("%c %d %d", (*pApEsX).ACa, (*pApEsX).XArEn[0],

*pApEsX).XArEn[1]); getch();}

Problema 5/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y X es un Arreglo de dos Apuntadores a Enteros.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

X Ar[2] -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *XArApEn[2];

}EsX;

void main(void){ int AEn = 5, BEn = 10; EsX AEsX = {'A', {&AEn, &BEn}}; EsX *pApEsX = &AEsX;

clrscr(); printf("%c %d %d\n", AEsEsX.ACa, *AEsX.XArApEn[0],

*AEsX.XArApEn[1]); printf("%c %d %d", (*pApEsX).ACa, *(*pApEsX).XArApEn[0],

*(*pApEsX).XArApEn[1]); getch();

Página 193 de 207

Page 194: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

}

Problema 6/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y q es un Apuntador a un Arreglo de dos Enteros.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> Ar[2] En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int (*qApArEn)[2];

}EsX;

void main(void){ int XArEn[2] = {5, 10}; EsX AEsX = {'A', (int (*)[2])XArEn}; EsX *pApEsX = &AEsX;

clrscr(); printf("%c %d %d\n", AEsX.ACa, (*AEsX.qApArEn)[0],

(*AEsX.qApArEn)[1]); printf("%c %d %d", (*pApEsX).ACa, (*(*pApX).qApArEn)[0],

(*(*pApEsX).qApArEn)[1]); getch();}

Problema 7/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y q es un Apuntador a un Arreglo de dos Apuntadores a Enteros.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> Ar[2] -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct {

Página 194 de 207

Page 195: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

char ACa; int *(*qApArApEn)[2];

}EsX;

void main(void){ int AEn = 5, BEn = 10; int *XArApEn[2] = {&AEn, &BEn}; EsX AEsX = {'A', (int *(*)[2])XArApEn}; EsX *pApEsX = &AEsX;

clrscr(); printf("%c %d %d\n", AEsX.ACa, *XArApEn[0], *XArApEn[1]); printf("%c %d %d\n", AEsX.ACa, *(*AEsX.qApArApEn)[0],

*(*AEsX.qApArApEn)[1]); printf("%c %d %d", (*pApEsX).ACa, *(*(*pApEsX).qApArApEn)[0],

*(*(*pApEsX).qApArApEn)[1]); getch();}

Problema 8/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y q es un Apuntador a una Función.+++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> Fn()}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; void (*qApFn)(void);}EsX;

void AFn(void){ puts("Esta es la función A");}

void main(void){ EsX XEsElem = {'A', AFn}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c ", XEsX.ACa); (*XEsX.qApFn)(); printf("%c ", (*pApEsX).ACa); (*(*pApEsX).qApFn)(); getch();}

Problema 9

Página 195 de 207

Page 196: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y q es un Apuntador a una Función Entera.++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> Fn() En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct X{ char ACa; int (*qApFnEn)(void);}EsX;

int AFnEn(void){ return 12;}

void main(void){ EsX AlfaEsX = {'A', AFnEn}; EsX *pApEsX = &AlfaEsX;

clrscr(); printf("%c %d\n", AlfaEsX.ACa, (*AlfaEsX.qApFnEn)()); printf("%c %d", (*pApEsElemX).ACa, (*(*pApEsX).qApFnEn)()); getch();}

Problema 10/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y q es un Apuntador a una Función Apuntador a un Entero.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

q -> Fn() -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *(*qApFnApEn)(void);}EsX;

Página 196 de 207

Page 197: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int *AFnApEn(void){ int *AApEn = new int; *AApEn = 12; return AApEn;}

void main(void){ EsX XEsX = {'A', AFnApEn}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c %d\n", XEsX.ACa, *(*XEsX.qApFnApEn)()); printf("%c %d", (*pApEsX).ACa, *(*(*pApEsX).qApFnApEn)()); getch();}

Problema 11/*Enunciado

p es un Apuntador a una Estructura Elem con: A es un Carácter y X es un Arreglo de dos Enteros.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X {A Ca

X Ar[2] En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int XArEn[2];}EsX;

void main(void){ EsX BetaEsX ={'A', {1, 2}}; EsX *pApEsX = &BetaEsX;

clrscr(); printf("%c %d %d\n", BetaEsX.ACa, BetaEsX.XArEn[0],

BetaEsElem.XArEn[1]); printf("%c %d %d", *pApEsX).ACa, (*pApEsX).XArEn[0],

(*pApEsX).XArEn[1]); getch();}

Problema 12/*Enunciado

p es un Apuntador a una Estructura X con: A es un Carácter y X es un Arreglo de dos Apuntadores a Enteros.

Página 197 de 207

Page 198: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X { A Ca

X Ar[2] -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *XArApEn[2];}EsX;

void main(void){ int AEn = 1, BEn = 2; EsX AesX ={'A', {&AEn, &BEn}}; EsX *pApEsX = &AEsX;

clrscr(); printf("%c %d %d\n", AEsX.ACa, *AEsX.XArApEn[0],

*XEsX.XArApEn[1]); printf("%c %d %d", (*pApEsX).ACa, *(*pApEsX).XArApEn[0],

*(*pApEsX).XArApEn[1]); getch();}

Problema 13/*Enunciado

p es un Apuntador a una Estructura X con: A es un Carácter y X es un Arreglo de dos Apuntadores a Funciones Enteras.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Diagrama

p -> Es X {A Ca

X Ar[2] -> Fn() En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int (*XArApFnEn[2])();}EsX;

int AFnEn(void){ return 5;}

int BFnEn(void){ return 10;

Página 198 de 207

Page 199: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

}

void main(void){

EsX BEsEsX ={'A', {AFnEn, BFnEn}}; EsX *pApEsX = &BEsX;

clrscr(); printf("%c %d %d\n", AEsX.ACa, (*AEsX.XArApFnEn[0])(),

(*AEsX.XArApFnEn[1])()); printf("%c %d %d", (*pApEsX).ACa, (*(*pApEsX).XArApFnEn[0])(),

(*(*pApEsElem).XArApFnEn[1])()); getch();}

Problema 14/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y

X es un Arreglo de dos Apuntadores a Funciones Apuntador a Enteros.

-----------------------------------------------------------------------Diagrama

p -> Es X { A Ca

X Ar[2] -> Fn() -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *(*XArApFnApEn[2])();}EsX;

int *AFnEn(void){ int *AApEn = new int; *AApEn = 5; return AApEn;}

int *BFnEn(void){ int *AApEn = new int; *AApEn = 10; return AApEn;}

void main(void){

EsX XEsX ={'A', {AFnEn, BFnEn}}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c %d %d\n", XEsX.ACa, *(*XEsX.XArApFnApEn[0])(),

Página 199 de 207

Page 200: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

*(*XEsX.XArApFnApEn[1])()); printf("%c %d %d", (*pApEsX).ACa,

*(*(*pApEsX).XArApFnApEn[0])(), *(*(*pApEsX).XArApFnApEn[1])());

getch();}

Problema 15/*Enunciado

p es un Apuntador a una Estructura X con A es un Carácter y

q es un Apuntador a un Arreglo de dos Apuntadores a Funciones Enteras.

-------------------------------------------------------------------------Diagrama

p -> Es X { A Caq -> Ar[2] -> Fn() En

}Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int (*(*qApArApFnEn)[2])();}EsX;

int AFnEn(void){ return 5;}

int BFnEn(void){ return 10;}

void main(void){ int (*XArApFnEn[2])() = {AFnEn, BFnEn}; EsX XEsX ={'A', (int (*(*)[2])())XArApFnEn}; EsX *pApEsX = &XEsX;

clrscr(); printf("%c %d %d\n", XEsX.ACa, (*(*XEsX.qApArApFnEn)[0])(),

(*(*XEsElem.qApArApFnEn)[1])()); printf("%c %d %d", (*pApEsX).ACa,

(*(*(*pApEsX).qApArApFnEn)[0])(), (*(*(*pApEsX).qApArApFnEn)[1])());

getch();}

Problema 16/*Enunciado

p es un Apuntador a una Estructura X con

Página 200 de 207

Page 201: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

A es un Carácter y q es un Apuntador a un Arreglo de dos Apuntadores a Funciones Apuntador a Enteros.-------------------------------------------------------------------------Diagrama

p -> Es X { A Ca

q -> Ar[ 2 ] -> Fn() -> En}

Solución*/

#include <stdio.h>#include <conio.h>

typedef struct { char ACa; int *(*(*qApArApFnApEn)[2])();}EsX;

int *AFnEn(void){ int *AApEn = new int; *AApEn = 5; return AApEn;}

int *BFnEn(void){ int *AApEn = new int; *AApEn = 10; return AApEn;}void main(void){ int *(*XArApFnApEn[2])() = {AFnEn, BFnEn}; EsX XEsX ={'A', (int *(*(*)[2])())XArApFnApEn}; EsX *pApEsX= &XEsX;

clrscr(); printf("%c %d %d\n", XEsX.ACa, *(*(*XEsX.qApArApFnApEn)[0])(),

*(*(*XEsX.qApArApFnApEn)[1])()); printf("%c %d %d", (*pApEsX).ACa,

*(*(*(*pApEsX).qApArApFnApEn)[0])(),*(*(*(*pApEsX).qApArApFnApEn)[1])());

getch();}

Página 201 de 207

Page 202: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Capítulo 14

Referencias y Apuntadores

Página 202 de 207

Page 203: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Página 203 de 207

Page 204: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

Objetivo general

El alumno explicara el propósito y concepto de la referencia en el lenguaje C. Explicara también la diferencia entre un apuntador y una referencia. Usara estos conceptos en sus programas.

Contenido

16.- La Representación en memoria física de una referencia16.1.- Introducción16.2.- El propósito de las referencias en el lenguaje C16.3.- Referencias16.4.- Excepciones en el uso de referencias16.5.- Resumen16.6.- Ejercicios

Página 204 de 207

Page 205: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

16.1 Introducción

16.2 El propósito de las referencias en el lenguaje C

Las referencias se introducen con el lenguaje C++, con el propósito de proporcionar un alias a una variable. Es simple y sencillamente un nombre alterno para una variable, por lo que una referencia no tiene existencia física. Con frecuencia los programadores confunden las referencias con apuntadores. En realidad las referencias se introducen en C++ [], porque no se puede sobrecargar un operador sin ellas []. Este punto se tratara con amplitud en el volumen II.

16.3 Referencias

Considérese el siguiente ejemplo:

A es un EnteroR es una Referencia de un Entero

Su correspondiente notación Méx es (identificadores)

AEnAlfaRfEn

La notación Mex asociada con la sintaxis de cada identificador es:

int AEn;int &AlfaRfEn;

Los identificadores iniciados en tiempo de compilación son:

int AEn = 5;int &AlfaRfEn = AEn;

La primer línea asigna el valor de 5 al identificador AEn, y en la segunda el identificador AlfaRfEn es un nombre alterno para AEn. En realidad, la asignación

int &AlfaRfEn = AEn;

no es una iniciación normal. Simplemente RRfEn especifica a la variable a la que hace referencia, en este caso a: AEn. Toda referencia debe referenciar a una variable real en tiempo de declaración (tiempo de compilación) usando la sintaxis semejante a una asignación tal como se muestra. La variable y la referencia a ella se tratan idénticamente. La situación (al menos con respecto a las referencias) es similar a []

union {int AEn;

Página 205 de 207

Page 206: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int &AlfaRfEn;}

Sin embargo las referencias no son uniones

Es desafortunado que los diseñadores del lenguaje hayan utilizado el símbolo & que usualmente significa “dirección de”, en vez de introducir otro símbolo que signifique “referencia a”, según [] el símbolo @ es un buen candidato.

Si RRfEn = 10;

Entonces AEn también contiene este valor de 10, y a la inversa, si por ejemplo

AEn = 25;

Ahora la referencia y la variable contienen el valor de 25.

Consideremos ahora:

int AEn = 5;int &AlfaRfEn = AEn;int *pApEn = &AEn;

Nótese que en la tercer línea hemos declarado el apuntador pApEn al entero AEn. Nótese también que el símbolo & aparece en la segunda y tercer línea, pero en los lados opuestos al símbolo de igualdad =.

16.4 Excepciones en el uso de referencias en el lenguaje C.

No existen referencias de referencias: ...RfRf..., ni apuntadores a referencias: ...ApRf..., recuérdese que las referencias no tienen existencia física, en otras palabras, no podemos tener una referencia a algo que no tiene existencia física, ni un apuntador a algo que no tiene existencia física. Por ejemplo, si tenemos:

int AEn = 5;int &AlfaRfEn = AEn;

entonces

int &(&BetaRfRfEn) = AlfaRfEn;

no es válido, y si por otra parte tenemos:

int &(*pApRfEn) = &AlfaRfEn;

Tampoco es válido.

Sin embargo si podemos tener apuntadores referencia a (...ApRf...), por ejemplo:

Página 206 de 207

Page 207: Principios de Programacion en C LibroC

Ingeniería y Ciencia de la Computación Hugo Rangel

int *(&pApRfEn) = &AlfaEn; es válido.Bibliografía

[Tharp, 2008] Creativity step by stepA conversation with the choreographer Twyla TharpHBR, April 2008.

[Csikszentmihalyi, 1998] Csikszentmihalyi, MihalyCreatividad: El fluir y la sicología del descubrimiento y la invenciónPaidós

[Rubinstein, 1995] Rubinstein, Moshe F. & Firstenberg, Iris R.Patterns of problem solving, 2d editionPrentice Hall, 1995

[Dijkstra, 1989] Dijkstra, W.A method of programmingAddison-Wesley Publishing Company, 1989

[Chesbrough, 2008] Chesbrough, Henry, Win Vanhaverbeke & West, JoelOpen innovation: Researching a new paradigmOxford University Press, 2008

[Foster, 1986] Foster, RichardInnovation: The attacker´s advantageSummit books, 1986

[López, 2005] López, Alfredo, AustinEl modelo en la ciencia y en la culturaSiglo veintiuno editores y UNAM, 2005

[Rangel, 2008] Rangel, Hugo, Carreón, Juan José, Granados, Hdz, Luciralia, Hdz., Arellano, Lucila Patricia,| Mendoza. Libros en línea (eL) y bibliotecas digitales4to Seminario de Ingeniería Lingüística, Facultad de Ingeniería, UNAM, 2008.

[Rangel, 2008] Rangel, Hugo, Carreón, Juan José, Granados, Hdz, Luciralia, Hdz., Arellano, Lucila Patricia, Mendoza. Los principios del aprendizaje en línea4to Seminario de Ingeniería Lingüística, Facultad de Ingeniería, UNAM, 2008.

[Segré, 1982] Segre, EmilioFermiConsejo Nacional de Ciencia y Tecnología

Página 207 de 207