Programación 1 Tema II. Diseño de los primeros programas Lección 4. Diseño de algunos programas elementales 1 Objetivos de la lección: • Aprender, paso a paso, una metodología de programación descendente • Aprender las nociones de ámbito o visibilidad y duración o vida de los elementos definidos en un programa • Aprender técnicas para comunicar información entre funciones: – Mediante datos globales – Mediante parámetros transmitidos por valor – Mediante parámetros transmitidos por referencia 2 1. Metodología de diseño descendente de programas Qué tabla desea escribir (0 para acabar) : 7 LA TABLA DEL 7 7 x 0 = 0 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70 Qué tabla desea escribir (0 para acabar) : 4 . . . 3 . . . Qué tabla desea escribir (0 para acabar) : 4 LA TABLA DEL 4 4 x 0 = 0 4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16 4 x 5 = 20 4 x 6 = 24 4 x 7 = 28 4 x 8 = 32 4 x 9 = 36 4 x 10 = 40 Qué tabla desea escribir (0 para acabar) : 0 4 Estructura del programa El programa C++ a diseñar se estructura a dos niveles: • Nivel de abstracción superior. La función main() que gestiona la interacción entre el computador y el usuario (nivel de abstracción superior). Qué tabla desea escribir (0 para acabar) : 7 … y muestra por pantalla la tabla del 7 • Siguiente nivel de abstracción. La función presentarTabla(n) que gestiona la presentación por pantalla de cualquier tabla de multiplicar. LA TABLA DEL 7 7 x 0 = 0 7 x 1 = 7 . . . 7 x 10 = 70 5 . . . Qué tabla desea escribir (0 para acabar) : 4 LA TABLA DEL 4 4 x 0 = 0 4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16 4 x 5 = 20 4 x 6 = 24 4 x 7 = 28 4 x 8 = 32 4 x 9 = 36 4 x 10 = 40 presentarTabla(4) Qué tabla desea escribir (0 para acabar) : 0 6 Código de programa (su estructura) /* * Autores: Miguel Angel Latre y Javier Martinez * Ultima revisión: 20 de marzo de 2014 * Resumen: Programa interactivo que presenta por pantalla las tablas de * multiplicar seleccionadas por el operador */ #include <iostream> #include <iomanip> using namespace std; /* Pre: ‐‐‐ */ /* Post: Presenta por pantalla la tabla de multiplicar del [n] … */ void presentarTabla (int n) { … } /* Pre: ‐‐‐ */ /* Post: Pregunta reiteradamente al operador qué tabla de … */ int main () { … } 7 /* * Pre: ‐‐‐ * Post: Pregunta reiteradamente al operador qué tabla de multiplicar desea * escribir y la escribe a continuación, salvo que su respuesta sea un 0, * en cuyo caso el programa termina */ int main() { // Plantea la primera pregunta al operador cout << "Que tabla desea escribir (0 para acabar): " << flush; // Asigna a [multiplicando] el primer valor escrito por el operador int multiplicando; cin >> multiplicando; // Itera hasta que el operador responda con un valor cero while (multiplicando != 0) { presentarTabla(multiplicando); // Plantea de nuevo la pregunta al operador cout << endl << "Que tabla desea escribir (0 para acabar): " << flush; // Asigna a [multiplicando] un nuevo valor escrito por el operador cin >> multiplicando; } return 0; } 8 /* * Pre: ‐‐‐ * Post: Presenta por pantalla la tabla de multiplicar del [n] de la forma: * * LA TABLA DEL n * n x 0 = 0 * n x 1 = n * n x 2 = … * ... * n x 9 = … * n x 10 = … */ void presentarTabla (int n) { // Escribe el encabezamiento de la tabla de multiplicar del [n] cout << endl << "LA TABLA DEL " << n << endl; // Escribe las 11 lineas de la tabla de multiplicar del [n] for (int i = 0; i <= 10; ++i) { cout << setw(3) << n << " x " << setw(2) << i << " = “ << setw(3) << n * i << endl; } } 9 2. Nociones de ámbito o visibilidad y de duración o vida de los elementos definidos en un programa Constantes, variables, funciones, etc. de un programa tienen asociado un ámbito o visibilidad (scope) y una duración o vida (lifetime). • Ámbito o visibilidad de un elemento: parte o zona del código del programa en la que el elemento es accesible y, por lo tanto, el programador puede hacer uso de él. – Ámbito local de los elementos definidos dentro de un bloque. Son visibles desde el punto en que se han definido hasta el final del bloque. – Ámbito global de las funciones definidas en el fichero y de los elementos definidos en el fichero fuera de las funciones. Son visibles desde el punto en que se han definido hasta el final del fichero. • Duración o vida de un elemento: tiempo en el que el elemento está disponible durante la ejecución del programa. 10 /* Ejemplo ilustrativo sobre ámbitos locales de datos */ { . . . int i = 10; // A partir de aquí es visible i . . . // Aquí solo es visible i { double r = 1.47; // Desde aquí es visible r y sigue siéndolo i . . . // Aquí son visibles i y r } // Fin de la visibilidad de r . . . // Aquí solo es visible i char c = 'J'; // Desde aquí es visible c y sigue siéndolo i . . . // Aquí son visibles i y c } // Fin de la visibilidad de i y c 11 /* Visibilidad de los parámetros de una función */ void f (int i, double r, double c) { . . . // Aquí son visibles i, r y c { . . . // Aquí son visibles i, r y c } . . . // Aquí son visibles i, r y c } // Fin de la visibilidad de i, r y c 12 /* Ejemplo ilustrativo sobre ámbitos locales y globales de datos */ #include <iostream> // Desde aquí son visibles los elementos // definidos en la biblioteca "iostream" using namespace std; int fechaAmerica = 1492; // Desde aquí es visible fechaAmerica void mostrarFechas () { // Desde aquí es visible mostrarFechas() int fechaLuna = 1969; // Desde aquí es visible fechaLuna cout << "America fue descubierta en " << fechaAmerica << " y el hombre llego a la Luna en " << fechaLuna << endl; } // Fin de la visibilidad de fechaLuna /* Se limita a invocar la función mostrarFechas() */ int main() { // Desde aquí es visible main mostrarFechas(); return 0; } // Fin de la visibilidad de fechaAmerica, mostrarFechas() y main() 13 /* Enmascaramiento de nombres */ #include <iostream> // Desde aquí son visibles los elementos // definidos en la biblioteca "iostream" using namespace std; int fecha = 1492; // Desde aquí es visible fecha (var. global) void mostrarFechas () { // Desde aquí es visible mostrarFechas() int fecha = 1969; // Desde aquí es visible fecha (var. local) cout << "America fue descubierta en " << ::fecha << " y el hombre llego a la Luna en " << fecha << endl; } // Fin visibilidad de fecha (var. local) /* Se limita a invocar la función mostrarFechas() */ int main() { // Desde aquí es visible main mostrarFechas(); return 0; } // Fin de la visibilidad de fecha (v. global), mostrarFechas() y main() 14 3. Técnicas de comunicación entre funciones Vamos a presentar tres técnicas: • • • Mediante variables globales [técnica prohibida en este curso] Mediante parámetros transmitidos por valor Mediante parámetros transmitidos por referencia Un primer problema. Diseñar un programa C++ que mantenga el siguiente diálogo con el operador: Escriba los extremos de un intervalo entero [a,b] siendo a<=b: 100 150 Los enteros del intervalo [100,150] suman 6375 15 #include <iostream> using namespace std; Comunicación de datos mediante variables globales int desde, hasta; // datos globales: extremos del un intervalo /* Pre: … Post: … */ int sumarDatos () { … } /* Pre: … Post: … */ void mostrarResultado () { … } /* Pre: … Post: … */ int main() { … } 16 #include <iostream> using namespace std; Comunicación de datos mediante variables globales int desde, hasta; // datos globales: extremos del un intervalo ... /* * Pre: ‐‐ * Post: Pide al operador que defina los extremos de un intervalo entero y * ordena presentar por pantalla el valor de la suma de todos los * enteros de dicho intervalo */ int main() { cout << "Escriba los extremos de un intervalo entero [a,b] siendo a<=b: " << flush; cin >> desde >> hasta; mostrarResultado(); return 0; } 17 #include <iostream> using namespace std; Comunicación de datos mediante variables globales int desde, hasta; // datos globales: extremos del un intervalo ... /* * Pre: desde <= hasta * Post: Infoma por pantalla de la suma de los datos del intervalo entero * [desde,hasta] del siguiente modo, por ejemplo: * Los enteros del intervalo [100,150] suman 6375 */ void mostrarResultado () { cout << "Los enteros del intervalo [" << desde << "," << hasta << "] suman " << sumarDatos() << endl; } ... 18 #include <iostream> using namespace std; Comunicación de datos mediante variables globales int desde, hasta; // datos globales: extremos del un intervalo /* * Pre: desde <= hasta * Post Devuelve la suma de los datos del intervalo entero [desde,hasta] */ int sumarDatos () { return (desde + hasta) * (hasta – desde + 1) / 2; } ... 19 #include <iostream> using namespace std; Comunicación de datos mediante parámetros por valor /* Pre: … Post: … */ int sumarDatos (int desde, int hasta) { … } /* Pre: … Post: … */ void mostrarResultado (int principio, int fin) { … } /* Pre: … Post: … */ int main() { … } 20 #include <iostream> using namespace std; Comunicación de datos mediante parámetros por valor . . . /* * Pre: ‐‐ * Post: Pide al operador que defina los extremos de un intervalo entero * y ordena presentar por pantalla el valor de la suma de todos los * enteros de dicho intervalo */ int main() { int minimo, maximo; cout << "Escriba los extremos de un intervalo entero [a,b] siendo a<=b: " << flush; cin >> minimo >> maximo; mostrarResultado(minimo, maximo); return 0; } 21 #include <iostream> using namespace std; Comunicación de datos mediante parámetros por valor . . . /* * Pre: principio <= fin * Post: Informa por pantalla de la suma de los datos del intervalo * entero [principio,fin] del siguiente modo. Ejemplo: * Los enteros del intervalo [100,150] suman 6375 */ void mostrarResultado (int principio, int fin) { cout << "Los enteros del intervalo [" << principio << "," << fin << "] suman " << sumaDatos(principio,fin) << endl; } . . . 22 #include <iostream> using namespace std; Comunicación de datos mediante parámetros por valor /* * Pre: desde <= hasta * Post: Devuelve la suma de los datos comprendidos en el intervalo entero * [desde,hasta] */ int sumaDatos (int desde, int hasta) { return (desde + hasta) * (hasta – desde + 1) / 2; } . . . 23 Las tres técnicas de comunicación consideradas: • • • Mediante variables globales [técnica prohibida en este curso] Mediante parámetros transmitidos por valor Mediante parámetros transmitidos por referencia Un segundo problema. Diseñar una función C++ que intercambie los valores de dos variables: int a, b; . . . /* Si ahora: a = X y b = Y */ intercambiar(a,b); /* Entonces ahora: a = Y y b = X */ 24 Intento fallido: comunicación de datos /* mediante parámetros por valor * Pre: uno = X y otro = Y * Post: uno = Y y otro = X */ void intercambiar (int uno, int otro) { int aux = uno; uno = otro; otro = aux; } 25 Intento fallido: comunicación de datos /* mediante parámetros por valor * Pre: uno = X y otro = Y * Post: uno = Y y otro = X */ void intercambiar (int uno, int otro) { int aux = uno; uno = otro; otro = aux; } /* Intento válido: comunicación de datos * Pre: uno = X y otro = Y mediante parámetros por referencia * Post: uno = Y y otro = X */ void intercambiar (int& uno, int& otro) { int aux = uno; uno = otro; otro = aux; } 26 Comunicación de datos mediante /* parámetros por referencia * Pre: a = X y b = Y * Post: a almacena el menor de los valores {X,Y} y b almacena el mayor * de los valores {X,Y} */ void ordenar (int& a, int& b) { if (a > b) { intercambiar(a,b); } } /* * Pre: a = X, b = Y y c = Z * Post: a almacena el menor de los valores {X,Y,Z}, c almacena el mayor * de los valores {X,Y,Z} y b almacena el valor intermedio de {X,Y,Z} */ void ordenar (int& a, int& b, int& c) { if (a >= b && a >= c) { intercambiar(a,c); } else if (b >= a && b >= c) { intercambiar(b,c); } ordenar(a,b); } 27 /* Comunicación de datos mediante parámetros por referencia * Pre: ‐‐‐ * Post: Asigna a nombre, nacimiento, estatura y peso los valores * determinados por el operador como respuesta a cuatro * preguntas que le son formuladas: * Su nombre: * Su anyo de nacimiento: * Su estatura: * Su peso: */ void preguntar (string& nombre, int& nacimiento, double& estatura, double& peso) { cout << "Su nombre: " << flush; // 1ª pregunta cin >> nombre; // lee la respuesta cout << "Su anyo de nacimiento: " << flush; // 2ª pregunta cin >> nacimiento; // lee la respuesta cout << "Su estatura: " << flush; // 3ª pregunta cin >> estatura; // lee la respuesta cout << "Su peso: " << flush; // 4ª pregunta cin >> peso; // lee la respuesta } 28 29