Anda di halaman 1dari 60

MIGUEL .

TOLEDO MARTNEZ

CONTENIDO DE LA LECCIN 10
CONOCIMIENTOS BSICOS SOBRE FUNCIONES
1. Introduccin 2. Funciones que regresan un solo valor: funciones sin void
2.1. 2.2. 2.3. 2.4. 2.5. 2.6. 2.7. 2.8. 2.9. 2.10. 2.11. 2.12. 2.13. Formato de funciones definidas por el usuario Encabezado de la funcin La clase de datos return El nombre de la funcin Lista de parmetros Ejemplo 10.1 Seccin de enunciado Ejemplos 10.2, 10.3 Llamada a las funciones sin void Argumentos reales en comparacin con parmetros formales Retorno de un resultado al programa que invoca a la funcin Ejemplo 10.4 Examen breve 27

2 3
4 4 5 5 6 7 7 8 9 10 11 11 52

3. Funciones void
3.1. 3.2. 3.3. 3.4. 3.5. Parmetros de valor en comparacin con parmetros de referencia Parmetros de valor Ejemplos 10.5, 10.6, 10.7, 10.8, 10.9 Parmetros de referencia Ejemplos 10.10, 10.11

12
13 13 14 17 19

4. Localizaciones de las funciones dentro de su programa 5. Examen breve 28 6. Prototipo de funciones


6.1. Ejemplos 10.12, 10.13

20 52 22
23

7. Solucin de problemas en accin: Programacin estructurada, ley de Ohm


7.1. 7.2. 7.3. 7.4. Problema Definicin del problema Planeacin de la solucin Codificacin del programa

25
25 25 26 28

8. Solucin de problemas en accin: Estado de cuenta de una cuenta de ahorros


8.1. 8.2. 8.3. 8.4. Problema Definicin del problema Planeacin de la solucin Codificacin del programa

36
36 36 36 40

9. Examen breve 29 10. Lo que necesita saber 11. Preguntas y problemas


11.1. Preguntas 11.2. Problemas

52 42 44
44 47

FUNCIONES - LECCIN - 10

10-1

MIGUEL . TOLEDO MARTNEZ

LECCIN 10
CONOCIMIENTOS BSICOS SOBRE FUNCIONES
INTRODUCCIN Cuando los programas se vuelven ms complejos, los programadores descomponen el programa en pequeos subprogramas llamados funciones. Cada funcin debe realizar una tarea especfica. Cuando el programa requiere de la tarea, llama a la funcin, proporcionndole toda la informacin que requiera para llevar a cabo la tarea.
Objetivos de esta leccin: Aprender a construir programas de manera modular, a partir de piezas pequeas llamadas funciones. Crear funciones nuevas. Entender los mecanismos para pasar informacin entre funciones. Comprender las clases de retorno de una funcin. Crear prototipos de funciones.

En lecciones anteriores se ha presentado el diseo estructurado usando el refinamiento sucesivo (paso a paso) y las funciones estndar de C++. Tambin se han desarrollado diseos descendentes de programas estructurados, pero se ha empleado una programacin lineal cuando se codifican estos diseos. Como resultado, hemos estado codificando programas C++ que consisten en una seccin principal definida por la funcin main() Es tiempo de aprender cmo codificar diseos estructurados usando un programa C++ estructurado que emplea funciones. Como se sabe, las funciones son la base de la programacin estructurada en el lenguaje C++. Adems, las funciones proporcionan el nico mtodo de comunicacin con objetos en programacin orientada a objetos. Por lo tanto, esta leccin es importante para aprender la programacin estructurada y la orientada a objetos en el lenguaje C++. Ya se han utilizado funciones estndar preconstruidas o predefinidas, en los programas. Todas estas funciones forman parte de los diversos archivos de encabezado incluidos en C++. Ahora es momento de desarrollar sus propias funciones y emplearlas para crear programas C++ bien estructurados y modulares, as como sus propias clases y objetos cuando estudie la programacin orientada a objetos. Las funciones que se crean para uso propio en un programa se conocen con el nombre de funciones definidas por el usuario. En este sentido, el usuario es usted, el programador. Una funcin definida por el usuario es un bloque de enunciados o un subprograma, que se escribe para realizar una tarea especfica requerida por el programador. Las funciones en C++ tienen la misma estructura del programa main() que ha utilizado a lo largo de estas lecciones: claseRetorno nombreFuncion(listaParametros)
{ declaracinVariables; enunciados; }
FUNCIONES - LECCIN - 10

10-2

MIGUEL . TOLEDO MARTNEZ

A una funcin se la da un nombre y se le llama o invoca usando su nombre cada vez que se va a realizar la tarea dentro del programa. El programa que llama o invoca una funcin suele conocerse con el nombre de programa llamador. Las funciones eliminan la necesidad de duplicar enunciados dentro de un programa. Dada una tarea que se va a realizar ms de una vez, los enunciados, se escriben slo una vez para la funcin. Entonces se llama a la funcin cada vez que se desee realizar la tarea. Adems, el uso de las funciones mejora la claridad y la legibilidad de la lista del programa. Y lo que es ms importante, el uso de las funciones dentro de un lenguaje estructurado, como C++, permite solucionar problemas complejos y muy largos usando un enfoque de diseo de programacin de arriba-abajo, as como la construccin de clases y objetos en programacin orientada a objetos. En C++ es posible hacer que una funcin sirva para dos propsitos. Puede hacerse una funcin para que regrese un solo valor al programa llamador. En C++, este tipo de funcin se conoce como sin void. Tambin es posible escribir funciones que realicen tareas especficas sin que regrese valor alguno o regrese varios valores, a estas funciones se les conocen con el nombre de funciones void. FUNCIONES QUE REGRESAN UN SOLO VALOR: funciones sin void Ya se cuenta con alguna experiencia en funciones que regresan un valor en C++. Recuerde las funciones estndar que se utilizaron antes como sqrt(), sin() y cos(), por mencionar algunas. Vimos que C++ incluye funciones para el manejo de cadenas y funciones matemticas, as como funciones para el manejo de E/S. Sin embargo, suponga que quiere realizar alguna operacin que no es una funcin predefinida en C++, por ejemplo elevar al cubo. Debido a que C++ no incluye ninguna funcin estndar para tal operacin, es posible codificar en el programa la operacin con un enunciado como el siguiente:
cubo = x * x * x

Despus, insertar este enunciado dentro del programa cada vez que se quiera elevar al cubo el valor de x. Sin embargo, no sera ms sencillo insertar el comando cubo(x) cada vez que se quiera elevar x al cubo, de tal manera que C++ sepa qu hacer al igual que sabe cmo ejecutar sqrt(x)? Puede hacer esto definiendo su propia funcin cubo(x). A esta funcin se le conoce con el nombre de funcin definida por el usuario, por razones obvias. Una funcin definida por el usuario es un subprograma que, cuando se invoca, realiza alguna tarea o regresa un solo valor que se asigna al nombre de la funcin en cualquier parte que se utilice el nombre en el programa llamador. De esta manera, si cubo(x) es una funcin definida por el usuario que calcular un valor, por decir, x, el enunciado cout << cubo(x); invocar la funcin y har que se muestre el cubo de x. Ahora ser necesario aprender a crear funciones definidas por el usuario.

FUNCIONES - LECCIN - 10

10-3

MIGUEL . TOLEDO MARTNEZ

FORMATO DE FUNCIONES DEFINIDAS POR EL USUARIO


// Encabezado de la funcin <claseRetorno> <nombreFuncin> (<listaParmetros>) {// Empieza el bloque de enunciados de la funcin // Variables y constantes locales <los objetos variables y las constantes locales debern ir aqu> // Enunciados de la funcin o cuerpo enunciado #1; enunciado #2; ....................................... enunciado #n; return <valor de regreso>; } // Final del bloque de enunciados de la funcin

El formato de la definicin de una funcin consiste en tres secciones principales: una lnea de encabezado de la funcin, cualquier variable local u objetos constantes requeridos por la funcin y una seccin de enunciados.
ENCABEZADO DE LA FUNCIN

El encabezado de la funcin proporciona la interfaz de datos para la funcin. Una interfaz de funcin o encabezado de la funcin es un enunciado que forma un marco comn entre la funcin y su programa llamador. Esta idea se muestra en la figura 10.1. Observe que el encabezado indica que datos de la funcin aceptarn desde el programa llamador y qu datos de la funcin regresarn al programa llamador. Cuando desarrolle los encabezados de las funciones, su perspectiva necesita ser relativa a la funcin. Deber preguntarse dos cosas:
1. Qu datos debe aceptar la funcin desde el programa llamador para realizar la tarea designada? Qu datos, si los hay, debern regresar la funcin al programa llamador para cumplir la tarea designada?

2.

Programa llamador

Acepta

Encabezado de la funcin [interfaz]

Cuerpo de la funcin [proceso]

Regresa

Figura 10.1. El encabezado de la funcin forma la interfaz entre el programa llamador y la funcin
FUNCIONES - LECCIN - 10

10-4

MIGUEL . TOLEDO MARTNEZ

En general, el encabezado de la funcin consiste en las tres partes siguientes:


La clase de dato que regresar la funcin, si lo hay. El nombre de la funcin. Una lista de parmetros.

LA CLASE DE DATOS return

Lo primero que aparece en el encabezado de la funcin es la clase de datos del valor regresado. Recuerde que la funcin puede regresar un solo valor que reemplace el nombre de la funcin en donde aparece el nombre en el programa llamador. El valor que reemplaza el nombre de la funcin en el programa llamador se conoce con el nombre de valor de retorno o de regreso. Cuando se usa una funcin para este propsito, la clase de datos del valor de regreso se deber especificar en el encabezado de la funcin. Por ejemplo, suponga que nuestra funcin cubo() regresa el cubo de un entero. Debido a que el cubo de un entero es un entero, la funcin regresar un valor entero. Como resultado, la clase de datos del valor regresado deber ser int y especificarse en el encabezado de la funcin, como sigue:
int cubo(<listaParmetros>)

De otra manera, si nuestra funcin cubo() fuera el cubo de un valor de punto flotante, la clase regresada deber ser float y el encabezado deber verse como sigue:
float cubo(<listaParmetros>)

Cuando una funcin no regresa ningn valor al programa llamador deber usar la palabra reservada void como la clase de regreso, como se muestra a continuacin:
void funcionMuestra(<listaParmetros>)

Las funciones que no regresan ningn valor al programa llamador se usan para realizar tareas especficas, como E/S.
EL NOMBRE DE LA FUNCIN

El nombre de la funcin puede ser cualquier identificador legal en C++. Sin embargo, el nombre de la funcin no deber empezar con un subguin (guin bajo), porque algunos depuradores colocan un subguin frente al nombre de la funcin si se encuentra un error en la funcin. El nombre de la funcin describir la operacin que la funcin realiza, al igual que cubo() describe el cubo de un valor. Cuando invoque la funcin dentro de un programa llamador, usar este nombre. Cada funcin que cree dentro de su programa debe de tener un nombre nico. Como ocurre con los nombres de variables, los nombres de las funciones deben corresponder con la tarea que realiza. Por ejemplo:

FUNCIONES - LECCIN - 10

10-5

MIGUEL . TOLEDO MARTNEZ

Nombre de la funcin
imprimirCalificacion cuentasPorPagar pedirNombre imprimirDocumento calcularImpuesto

Propsito de la funcin
Imprimir calificacin de los alumnos. Procesa las deudas de una compaa. Solicita el nombre del usuario. Imprime el archivo correspondiente al documento. Calcula el impuesto del cliente.

Recuerde dos cosas:


1. El nombre de la funcin nunca se puede usar dentro de la funcin. En otras palabras, el siguiente enunciado dentro de la funcin cubo() generar un error: cubo = x * x * x; Hay una excepcin a esta regla que se llama recursividad, la cual se explicar en la siguiente leccin. 2. El identificador de la funcin nunca se usar del lado izquierdo del smbolo de asignacin fuera de la funcin. Por tanto, el siguiente enunciado causar un error en el programa llamador: cubo = x * x * x;

LISTA DE PARMETROS

La lista de parmetros de la funcin incluye variables, llamadas parmetros, que pasarn desde el programa llamador y sern evaluados por la funcin. Piense en un parmetro como una variable de la funcin que espera recibir un valor desde el programa llamador cuando se invoca la funcin. Para determinar los parmetros de la funcin, pregntese qu datos deber aceptar la funcin para realizar su tarea? Suponga que nuestra funcin cubo() elevar al cubo valores enteros. La funcin deber aceptar un valor entero desde el programa llamador y regresar un valor entero al programa llamador. De esta manera, nuestra interfaz de funcin se puede describir como sigue:
Funcin cubo(): Acepta: Regresa: Un entero al cubo. Un valor entero. Un valor entero.

Vamos a disear x como un objeto entero que aceptar la funcin. En C++, un parmetro dado deber especificarse en el encabezado de la funcin indicando su clase de datos seguido por su identificador. Como resultado, la lista de parmetros apropiados para la funcin cubo() deber ser (int x). Colocando todo junto, el encabezado de la funcin deber ser:
int cubo(int x) Clase regreso Nombre de la funcin Parmetro de la funcin

S la funcin cubo() elevara al cubo valores de punto flotante, el encabezado de la funcin apropiado deber ser:
FUNCIONES - LECCIN - 10

10-6

MIGUEL . TOLEDO MARTNEZ

float cubo(float x)
Clase regreso Nombre de la funcin Parmetro de la funcin

Ejemplo 10.1
Suponga que quiere escribir una funcin definida por el usuario para calcular el voltaje en un circuito de cd usando la ley de Ohm. Escriba el encabezado de la funcin: Para desarrollar el encabezado de la funcin, trataremos a la funcin como a una caja negra y nos haremos las siguientes preguntas: (1) Qu dato deber aceptar la funcin desde el programa llamador para realizar la tarea de aplicacin? (2) Qu deber regresar al programador llamador? Las respuestas a estas preguntas dictarn el encabezado de la funcin o interfaz. Para contestar la primera pregunta, piense en qu deber evaluar la funcin. Para calcular el voltaje usando la ley de Ohm, la funcin deber evaluar dos cosas: corriente y resistencia. As que utilicemos las palabras corriente y resistencia como nuestros parmetros. De esta manera, la funcin deber aceptar un valor de punto flotante de corriente y un valor de punto flotante de resistencia, Despus, deber decidir qu datos regresar la funcin al programa llamador. Debido a que la funcin evala valores de punto flotante, tiene sentido matemtico que el valor regresado tambin deba ser un valor de punto flotante. Ahora, la interfaz de funcin se puede describir como sigue: Funcin voltaje(): Acepta: Regresa: Calcula el voltaje usando la ley de Ohm. Un valor de punto flotante para corriente y un valor de punto flotante para resistencia. Un valor de punto flotante para voltaje.

Una vez que se ha decidido lo que acepta y lo que regresa la funcin, el encabezado de la funcin se construye fcilmente con la sintaxis de C++ como sigue: float voltaje(float corriente, float resistencia)

SECCIN DE ENUNCIADO

La seccin de enunciado de la funcin incluye aquellas operaciones que la funcin deber realizar para regresar un valor al programa llamador. Observe otra vez el formato general para la funcin definida por el usuario. Como puede observar, la seccin de enunciado completa est enmarcada dentro de llaves. Despus de abrir una llave, deber empezar la seccin de enunciado declarando cualquier objeto constante y definiendo objetos variables que se usarn dentro de la funcin. Cualquier objeto constante o variable listado aqu se llama local, porque se definen slo para uso local dentro de la misma funcin. Las constantes y variables locales no tienen significado fuera de la funcin en la cual se definen. No duplique ninguno de sus parmetros de funcin aqu. Liste solamente constantes o variables adicionales que la funcin requiera durante su ejecucin. Un ejemplo comn de una variable local es un contador de ciclo que se emplea como parte de un ciclo while, do/while o for dentro de la funcin. En realidad, puede declarar constantes locales y definir variables locales en cualquier lugar dentro de la funcin siempre y cuando se listen antes de usarlas. Sin embargo, el buen estilo dicta que stas sean declaradas o definidas al principio de la seccin de enunciado de la funcin.

FUNCIONES - LECCIN - 10

10-7

MIGUEL . TOLEDO MARTNEZ

No confunda las variables locales con los parmetros de la funcin. Una variable local se define despus de abrir la llave de una funcin para usarle dentro de sta. Un parmetro de funcin se define en el encabezado de la funcin como un lugar que mantiene el espacio para los valores del argumento que pasan a la funcin cuando se llama a la misma. Tambin se usar dentro de la funcin para suministrar datos desde el programa llamador a la funcin. Los enunciados ejecutables de la funcin siguen a cualquier enunciado o definicin local. El ltimo enunciado en una funcin sin void es el return. Este se usa cuando se regrese un solo valor al programa llamador. As, si nuestra funcin cubo() regresa el cubo de x, un enunciado de regreso apropiado deber ser:
return (x * x * x);

Combinando el encabezado de la funcin y la seccin de enunciado para la funcin cubo(), dar la funcin completa como sigue:
int cubo(int x) { return(x * x * x); } // Fin de cubo()

Obviamente, sta es una funcin relativamente sencilla que no requiere ningn enunciado de definicin local o ejecutable que no sea el enunciado return. Ejemplo 10.2
Complete la funcin voltaje() cuyo encabezado se desarroll en el ejemplo 10.1

Solucin
La ley de Ohm requiere la funcin para multiplicar la corriente por la resistencia para obtener el voltaje. De esta manera, el nico enunciado requerido en la funcin es un enunciado return que regresar el producto de corriente y resistencia. Colocando todo junto, la funcin completa se convierte en: float voltaje(float corriente, float resistencia) { return (corriente * resistencia); } // Fin de voltaje() Una fuente comn de error durante la codificacin de una funcin sin void es hacer la asignacin al nombre de la funcin dentro de sta, como sigue: float voltaje(float corriente, float resistencia) { return voltaje = corriente * resistencia; } // Fin de voltaje() Esto siempre causar un error de compilacin, porque se intenta regresar el nombre de la funcin. Deber regresar un valor que, en este caso, es el producto de corriente y resistencia.

Ejemplo 10.3
Escriba una funcin que regrese la suma de todos los enteros desde 1 a algn valor mximo entero, llamado maximo. La funcin deber obtener el valor de maximo desde el programa llamador.
FUNCIONES - LECCIN - 10

10-8

MIGUEL . TOLEDO MARTNEZ

Solucin
Vamos a llamar a esta funcin suma(). Ahora, la funcin deber aceptar un valor entero llamado maximo desde el programa llamador. Debido a que la funcin es para sumar todos los enteros desde 1 hasta maximo, sta regresar un valor entero. De esta manera nuestra interfaz de funcin se puede describir como sigue: Funcin suma(): Acepta: Regresa: Suma todos los enteros desde 1 hasta maximo. Un valor entero: maximo. Un valor entero.

Utilizando esta informacin, el encabezado de la funcin se convierte en: int suma(int maximo) El siguiente paso es determinar si hay alguna variable local requerida por los enunciados de la funcin. Se puede usar un ciclo for para calcular la suma de enteros desde 1 hasta maximo. Sin embargo, el enunciado for requiere una variable contador. Esta es una aplicacin clsica para una variable local. Vamos a llamar a esta variable utilizada como contador local contador. Despus, tambin necesita una variable temporal dentro del ciclo for para mantener un subtotal de la suma cada vez que el ciclo se ejecuta. Denominaremos a esta variable local subTotal. De acuerdo con lo anterior, la funcin es: int suma(int maximo) { int subTotal = 0; for(int contador = 1; contador <= maximo; ++ contador) subTotal = subTotal + contador; return subTotal; } // Fin de suma()

LLAMADA A LAS FUNCIONES sin void

Se llama o invoca a una funcin sin void en cualquier parte de su programa de la misma manera que llama las funciones estndar en C++. Por ejemplo, puede llamar una funcin usando un operador de asignacin o un enunciado cout como el siguiente:
y = cubo(2); o cout << cubo(2);

En ambos casos, el valor 2 se pasa a la funcin que se va a elevar al cubo. De esta manera, en nuestra funcin cubo(), el parmetro x toma el valor 2. Y la funcin regresar el cubo de 2, que es 8. Con el enunciado de asignacin, la variable y asignar el valor 8, y el enunciado cout har que el valor 8 se muestre en pantalla. Aqu estn otras dos formas en que nuestra funcin cubo() se puede llamar:
int a = 2; y = cubo(a); o cout << cubo(a);

FUNCIONES - LECCIN - 10

10-9

MIGUEL . TOLEDO MARTNEZ

En estos casos, la funcin es la variable a elevada al cubo, donde a a se le ha asignado previamente el valor 2. De esta manera el valor de a o 2, pasa a la funcin. En nuestra funcin cubo() el parmetro x toma el valor de a. Las funciones tambin pueden ser llamadas como parte de expresiones aritmticas o enunciados relacionales. Por ejemplo, nuestra funcin cubo() puede ser llamada como parte de una expresin aritmtica, como sta:
int a = 1; y = 1 + cubo(a) * 2;

Qu se asignar a y? Bien, primero C++ evale la funcin cubo() para obtener 8, despus realiza la operacin de multiplicacin para obtener 16 y por ltimo suma 1 a 16 para obtener 17. Tambin puede usar funciones como parte de operaciones relacionales, como sta:
if(cubo(a) >= 27)

Cundo ser verdadera la relacin? Cuando a sea mayor o igual a 3, correcto? Cuando a es mayor o igual a 3, el cubo(a) es mayor o igual a 27. Recuerde que cuando una funcin se disea para regresar un solo valor al programa llamador, el valor regresado reemplaza el nombre de la funcin donde quiera que se use el nombre en el programa llamador. Generalmente se llamarn las funciones sin void dentro de su programa usando un enunciado de asignacin, un objeto cout o como parte de una operacin aritmtica. Recuerde pensar en la llamada de funcin como un valor. Esto es, un valor reemplaza la llamada de funcin donde sta aparece en el programa. Pregntese: Tiene sentido un valor aqu? Por ejemplo, todos los siguientes enunciados tienen sentido, porque un valor puede sustituirse fcilmente por la llamada de funcin:
resultado = cubo(a): cout << cubo(a); solucion = x * cubo(a) + 5;

Por otra parte, el siguiente enunciado no tendr sentido y causar un error de compilacin.
cubo(a);

ARGUMENTOS REALES EN COMPARACIN CON PARMETROS FORMALES

En el ejemplo anterior del cubo(), la variable a que se usa en el programa llamador se llama argumento real. Por otra parte, la variable correspondiente x que se usa en el encabezado de la funcin se llama parmetro formal. Los argumentos reales son valores o variables que se utilizan dentro de la llamada de la funcin y los parmetros formales son variables que se utilizan dentro del encabezado de la funcin y que reciben valores del argumento real. De esta manera, decimos que el parmetro formal en nuestra funcin cubo(), x, toma el valor del argumento real a, utilizado en la llamada de funcin. Estas son algunas cosas que querr recordar de los argumentos reales y los parmetros formales:

FUNCIONES - LECCIN - 10

10-10

MIGUEL . TOLEDO MARTNEZ

Las variables de argumento real se debern definir en el programa llamador. Estar en la funcin main(), a menos que las funciones sean llamadas por otras funciones. La clase de datos de los argumentos reales correspondientes y los parmetros formales debern ser los mismos. Los parmetros formales mantienen el espacio para los valores del argumento real durante la ejecucin de la funcin. Los parmetros formales siempre se listan en la seccin de parmetros del encabezado de la funcin. El nmero de argumentos reales usado durante la llamada de funcin deber ser el mismo que el nmero de parmetros formales listados en el encabezado de la funcin, excepto cuando se usan parmetros predeterminados. Los parmetros predeterminados se explicarn posteriormente. La correspondencia entre argumentos reales y parmetros formales se establece sobre las bases de uno a uno de acuerdo con el orden de la lista respectiva. Aunque las variables del argumento real y del parmetro formal a menudo tienen diferentes nombres de variable, pueden ser las mismas. Cuando ste es el caso, los objetos variables respectivos debern definirse en el programa llamador y tambin tendrn que aparecer en la lista de parmetros de la funcin.

RETORNO DE UN RESULTADO AL PROGRAMA QUE INVOCA A LA FUNCIN

En algunas ocasiones la funcin ejecutar cierto tipo de clculos. La funcin posteriormente devolver este valor a quin la llama. Cuando una funcin regresa un valor, debe indicarle a C++ la clase del valor que devuelve, tal como int, float, char y as sucesivamente. Para informarle a C++ de la clase de retorno de la funcin, simplemente preceda al nombre de la funcin con la clase correspondiente. Por ejemplo, la siguiente funcin sumaValores suma dos nmeros enteros y regresa un resultado entero.
Ejemplo 10.4
El siguiente programa SUMAVAL.CPP, utiliza la funcin sumaValores, para sumar valores diferentes: /* El siguiente programa: SUMAVAL.CPP, llama a una funcin llamada sumaValores, la cual calcula la suma de dos nmeros enteros. */ #include <iostream.h> int sumaValores(int a, int b) { return (a+b); } //Fin de sumaValores() void main(void) { cout << "100 + 200 = " << sumaValores(100, 200) << endl; cout << "500 + 501 = " << sumaValores(500, 501) << endl; cout << "-1 + 1 = " << sumaValores(-1, 1) << endl; } //Fin de main() //Para cout

EXAMEN BREVE 27

FUNCIONES - LECCIN - 10

10-11

MIGUEL . TOLEDO MARTNEZ

FUNCIONES void Las funciones que no regresan un solo valor al programa llamador a menudo se escriben para realizar alguna tarea especfica. Estas se llaman funciones void. Cuando una funcin no regresa un solo valor al programa llamador, se deber usar la palabra reservada void como el regreso de la clase de datos. Adems, estas funciones pueden o no requerir parmetros. Cuando no se requieren parmetros, simplemente deje la lista de parmetros en blanco para indicar al compilador que la funcin no necesita recibir ningn valor desde el programa llamador. Las funciones que no regresen un valor o no requieran ningn parmetro son del tipo de funciones ms simples en C++. Por ejemplo, suponga que quiere escribir una funcin que mostrar el siguiente encabezado en la pantalla cada vez que se le llama:
NOMBRE CALLE DIRECCIN ESTADO CIUDAD CDIGO POSTAL

Vamos a llamar a esta funcin muestraEncabezado() Para desarrollar el encabezado de la funcin, pregntese que deber aceptar la funcin para realizar la tarea diseada y que deber regresar. En este caso, la funcin simplemente muestra la informacin constante de la lnea de encabezado y no necesita aceptar ni regresar ningn dato. De esta manera, nuestra interfaz de funcin puede escribirse como sigue:
Funcin muestraEncabezado(): Acepta: Regresa: Muestra la informacin fija del encabezado. Nada. Nada.

Usando esta informacin, el encabezado de la funcin se convierte en:


void muestraEncabezado(void)

Observe el encabezado de la funcin y ver que se usa la palabra void como la clase de regreso. La palabra reservada void se emplea aqu para indicar al compilador que no hay valor de regreso. Tambin, note que no hay parmetros requeridos para esta funcin, porque la lista de parmetros tambin contiene void o se deja en blanco. En otras palabras, la funcin no regresa un valor y no requiere ningn argumento para evaluar. Simplemente realiza una tarea determinada, en este caso mostrando un encabezado. Para mostrar el encabezado, lo que necesita es un enunciado cout en el cuerpo de la funcin. Colocando todo junto, la funcin se convierte en:
void muestraEncabezado(void) {
cout << \tNOMBRE\tCALLE\tDIRECCION\tESTADO\tCIUDAD\tCODIGO POSTAL

\n\t______\t_____\t_________\t______\t______\t______ ______ << endl; } // Fin de muestraEncabezado()

Por ltimo, no ver un enunciado return al final de la funcin, porque la funcin no regresa ningn valor. Cmo puede llamar a esta funcin en su programa? Simple, slo use el nombre de la funcin como un enunciado dentro del programa llamador cada vez que el encabezado se muestre, por ejemplo:
muestraEncabezado();
FUNCIONES - LECCIN - 10

10-12

MIGUEL . TOLEDO MARTNEZ

Ningn argumento real se lista en la llamada de la funcin, porque la funcin no evala ningn argumento. Cuando llame una funcin void, simplemente liste el nombre de la funcin y los argumentos requeridos como un enunciado sencillo dentro de su programa. No llame una funcin void con un operador de asignacin u objeto cout como lo hace para las funciones sin void. La siguiente llamada muestraEncabezado() deber causar un error de compilacin.
encabezado = muestraEncabezado(); cout << muestraEncabezado(); // Error // Error

La llamada correcta es simplemente:


muestraEncabezado();

PARMETROS DE VALOR EN COMPARACIN CON PARMETROS DE REFERENCIA

La funcin anterior muestraEncabezado() no requiere ninguna lista de parmetros formal, porque para evaluar no necesita recibir ningn argumento desde el programa llamador. Cuando se requieren evaluar parmetros formales por la funcin, stos debern listarse en el encabezado de la funcin en una de dos formas: como parmetros de valor o como parmetros de referencia.
PARMETROS DE VALOR

Hasta el momento, se han usado parmetros de valor en esta leccin. Los parmetros de valor permiten una comunicacin de datos en un sentido desde el programa llamador a la funcin. Una primera aproximacin de este concepto se muestra en la figura 10.2a. Programa llamador Funcin

Argumentos reales

Copia

Parmetros formales

Figura 10.2a. Paso de parmetros mediante un valor

Observe que los valores de los argumentos reales en el programa llamador se pasan (por medio de un valor) a parmetros formales en la funcin. Otra forma de pensar con respecto a esto es que el parmetro formal recibe una copia del valor del argumento real. Cuando la funcin opera sobre un parmetro de valor, est operando en una copia, ms que en el valor original en el programa llamador. De esta manera, el valor del argumento real en el programa llamador se protege de un cambio accidental por la funcin. Algo que se debe recordar cuando se usan parmetros de valor es que cualquier manejo de los parmetros formales dentro de la funcin no afecta el valor del argumento real usado por la llamada de la funcin. Por ejemplo, considere la siguiente funcin:

FUNCIONES - LECCIN - 10

10-13

MIGUEL . TOLEDO MARTNEZ

void pasaValor(int x, int y); { // Incrementa y decrementa parmetros formales ++x; --y; // Muestra los valores del parmetro formal cout << x = << x << endl; cout << y = << y << endl; } // Fin de pasaValor()

Aqu, los parmetros x y y son parmetros de valor. Observe que, dentro de la funcin, el valor de x se incrementa y el de y se decrementa. As, los valores resultantes se muestran usando un enunciado cout. Ahora, suponga que la funcin anterior se llama por medio del programa siguiente:
void main(void) { // Se definen las variables de argumento real int a = 0; int b = 0; // Se llama a la funcin pasaValor(a, b); // Muestra los valores de argumento real cout << a = << a << endl; cout << b = << b << endl; } // Fin del main()

Primero, observe cmo se hace el llamado a la funcin. Es simplemente un enunciado en el programa llamador. El nombre de la funcin se lista seguido por los argumentos reales requeridos dentro de parntesis. Los argumentos reales son a y b, porque stos se listan en la llamada de la funcin. Cuando se ejecuta la llamada de la funcin, el valor de a pasa al parmetro de valor x y el de b pasa al de y. Otra forma de decir esto es que x recibe una copia de a y y recibe una copia de b. Observe que antes de la llamada de la funcin, el programa llamador inicializa ambos valores a y b a 0. Como resultado, x y y reciben el valor de 0 desde el programa llamador. La funcin despus incrementa el valor de x, decrementa el valor de y y muestra los nuevos valores de x y y. Sin embargo, las operaciones sobre x y y no tienen efecto en los argumentos reales (a y b) en el programa llamador. Los valores de a y b permanecen en 0. Observe que despus de la llamada de la funcin, el programa llamador muestra los valores de a y b. Qu se ver en la pantalla al ejecutar el programa? Bien, la funcin pasaValor() muestra x y y, despus main() muestra a y b. De esta manera, el resultado que se exhibe es:
x=1 y = -1 a=0 b=0

A continuacin veamos algunos ejemplos en los que se muestren los conceptos antes aprendido.
Ejemplo 10.5
El siguiente programa, MSTRMSJ.CPP utiliza una funcin para enviar un mensaje:
FUNCIONES - LECCIN - 10

10-14

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: MSTRMSJ.CPP, crea una funcin muestraMensaje(), para visualizar un mensaje. */ #include <iostream.h> //Para cout

void muestraMensaje(void) { cout << "Hola, he sido rescatado por C++" << endl; } //Fin de muestraMensaje() void main(void) { cout << "Llamado a una funcin" << endl << endl; muestraMensaje(); cout << endl << "Regreso del llamado a la funcin" << endl; } //Fin de main()

Ejemplo 10.6
El siguiente programa, DOSMSJ.CPP, utiliza las funciones muestraTitulo() y muestraLeccion() para visualizar informacin acerca de las lecciones: /* El siguiente programa: DOSMSJ.CPP, utiliza dos funciones para enviar cada una un mensaje. */ #include <iostream.h> //Para cout

void muestraTitulo(void) { cout << "APUNTES: Apuntes de COMPUTACION I" << endl; } //Fin de muestraTitulo() void muestraLeccion(void) { cout << "LECCION: Conocimientos bsicos sobre funciones" << endl; } //Fin de muestraLeccion() void main(void) { muestraTitulo(); muestraLeccion(); } //Fin de main()

Para incrementar la capacidad de las funciones, C++ le permite a sus programas pasar informacin (argumentos) a sus funciones. Cuando una funcin utiliza parmetros, debe indicarle a C++ la clase de cada uno de los parmetros, tales como int, float, char y as sucesivamente.

FUNCIONES - LECCIN - 10

10-15

MIGUEL . TOLEDO MARTNEZ

Ejemplo 10.7
El siguiente programa: USOPAR.CPP, utiliza la funcin mostrarNumero, varias veces, en cada ocasin se le pasa un valor diferente. /* El siguiente programa: USOPAR.CPP, elabora una funcin que muestra los diferentes parmetros que le son enviados. */ #include <iostream.h> //Para cout void mostrarNumero(int valor) { cout << "El valor del parmetros es: " << valor << endl; } //Fin de mostrarNumero() void main(void) { mostrarNumero(1); mostrarNumero(1001); mostrarNumero(-532); } //Fin de main()

En la mayora de los casos, sus programas pueden pasar varios valores a la funcin. Para cada valor pasado, su funcin debe declarar su nombre y clase.
Ejemplo 10.8
El siguiente programa: GDEPEQ.CPP, utiliza la funcin mostrarGdeYPeq para visualizar el nmero ms grande y el ms pequeo de tres enteros que recibe. /* El siguiente programa: GDEPEQ.CPP, crea una funcin que determina y muestra cual es el mayor y el menor de tres enteros que le son enviados. */ #include <iostream.h> //Para cout void mostrarGdeYPeq (int a, int b, int c) { int pequeno = a; int grande = a; if (b > grande) grande = b; if (b < pequeno) pequeno = b; if (c > grande) grande = c; if (c < pequeno) pequeno = c; cout << "El valor ms grande es: " << grande << endl; cout << "El valor ms pequeo es: " << pequeno << endl; } //Fin de mostrarGdeYPeq()

FUNCIONES - LECCIN - 10

10-16

MIGUEL . TOLEDO MARTNEZ

void main (void) { mostrarGdeYPeq (1, 2, 3); cout << endl; mostrarGdeYPeq (500, 0, -500); cout << endl; mostrarGdeYPeq (1001, 1001, 1001); } //Fin de main()

Ejemplo 10.9
El siguiente programa: MSTEMP.CPP, utiliza la funcin mostrarEmpleado para visualizar la edad de un empleado (clase int) y su salario (clase float) /* El siguiente programa: MSTEMP.CPP, muestra una funcin que visualiza la edad, y el salario de un empleado. */ #include <iostream.h> //Para cout

void mostrarEmpleado(int edad, float salario) { cout << "El empleado tiene " << edad << " aos" << endl; cout << "El empleado gana $" << salario << endl; } //Fin de mostrarEmpleado() void main(void) { mostrarEmpleado(32, 25000.00); } //Fin de main()

PARMETROS DE REFERENCIA

Los parmetros de referencia, algunas veces llamados parmetros de variable, difiere de los de valor en que stos proporcionan una combinacin en dos sentidos entre el programa llamador y la funcin, como se ilustra en la figura 10.2b. Programa llamador Funcin

Argumentos reales

Direccin

Parmetros formales

Figura 10.2b. Paso de parmetros mediante referencia


FUNCIONES - LECCIN - 10

10-17

MIGUEL . TOLEDO MARTNEZ

Un parmetro de referencia proporciona una comunicacin de ida y vuelta de datos entre el programa llamador y la funcin. Observe el camino de comunicacin de ida y vuelta: los valores de los argumento reales pasan a los parmetros formales en la funcin y despus los valores de parmetros formales regresan a los argumentos reales. Esto permite a la funcin cambiar los valores de argumento real en el programa llamador. Recuerde que un parmetro de valor es simplemente una copia del valor del argumento real; por lo tanto, cualquier operacin sobre el parmetro dentro de la funcin no tiene efecto en el valor del argumento original. De otra manera, un parmetro de referencia representa la direccin del valor de argumento real en la memoria. Como resultado, cualquier cambio que se haga al parmetro de referencia dentro de la funcin cambiar lo que est almacenado en esa direccin. Esto obviamente modifica el valor original del argumento real en el programa llamador. Para crear un parmetro de referencia, simplemente inserte un ampersand (&) antes de los identificadores de parmetro apropiados en el encabezado de la funcin. Vamos a cambiar nuestro ejemplo pasaValor() para usar parmetros de referencia, como sigue:
void pasaReferencia(int &x, int &y); { // Incrementa y decrementa parmetros formales ++x; --y; // Muestra los valores del parmetro formal cout << x = << x << endl; cout << y = << y << endl; } // Fin de pasaReferencia()

El cambio principal aqu es insertar un ampersand antes de x y y en el encabezado de la funcin. Seguro, el nombre de la funcin tambin se ha cambiado para reflejar la nueva aplicacin. Qu deber ver en la pantalla como resultado de la ejecucin del siguiente programa?
void main(void) { // Se definen las variables de argumento real int a = 0; int b = 0; // Se llama a la funcin pasaReferencia(a, b); // Muestra los valores de argumento real cout << a = << a << endl; cout << b = << b << endl; } // Fin del main()

Debido a que x y y son ahora parmetros de referencia y no parmetros de valor, cualquier operacin que afecta a x y y dentro de la funcin tambin afectar los valores de los argumentos reales a y b que se utilizan en la llamada de la funcin. Estos son los valores que muestra el programa:
x y a b
FUNCIONES - LECCIN - 10

=1 = -1 =1 = -1 10-18

MIGUEL . TOLEDO MARTNEZ

Como puede ver, los nuevos valores de x y y pasan de regreso a a y b respectivamente. Usamos la expresin pasan de regreso para describir la accin. Sin embargo, recuerde que en realidad nada pasa de regreso, porque la funcin est simplemente operando sobre las direcciones de los argumentos reales a y b.
Ejemplo 10.10
Qu se mostrar como resultado del siguiente programa? void main(void) { // Define variables de argumento real int a = 0; int b = 0; // Llama a la funcin muestraParametros(a,b); // Muestra los valores de argumento real cout << a = << a << endl; cout << b = << b << endl; } // Fin de main() /********************************************************** Esta funcin muestra el uso de valores en comparacin con parmetros de referencia. **********************************************************/ void muestraParametros(int &x, int y) { // Incremente y decrementa parmetros formales ++x; --y; //Muestra valores de parmetro formal cout << x = << x << endl; cout << y = << y << endl; } // Fin de muestraParametro()

Solucin
Aqu se ve un programa completo que incorpora una funcin. La funcin est localizada inmediatamente despus de la llave que encierra la funcin main() La funcin se llama entonces dentro de la seccin de enunciado main() simplemente listando su nombre seguido por una relacin de los argumentos reales requeridos. Observe que los argumentos reales (a y b) se definen como objetos enteros en main() Ahora vea el encabezado de la funcin. Los parmetros formales son x y y. Ambos son enteros; sin embargo, x es un parmetro de referencia mientras que y es un parmetro de valor. Observe el uso de ampersand antes de x. Esto define x como un parmetro de referencia. Sigue una coma despus de x finalizando esta definicin. Despus y se define por separado como un parmetro de valor (sin ampersand) Como resultado, el valor de x pasa de regreso a main() pero no el valor de y. Esto es lo que se ver en la pantalla: x=1 y = -1 a=1 b=0

FUNCIONES - LECCIN - 10

10-19

MIGUEL . TOLEDO MARTNEZ

Ejemplo 10.11
Escriba una funcin llamada intercambio() que acepte dos objetos enteros desde el programa llamador y regrese los objetos con sus valores intercambiados.

Solucin
Esta es una aplicacin ideal para parmetros de referencia porque, para intercambiar los valores, el proceso de intercambio dentro de la funcin deber tener un efecto sobre los valores original en el programa llamador. As, la funcin deber aceptar dos objetos enteros y regresar los mismos dos objetos con los valores intercambiados. A continuacin se muestra una descripcin de la interfaz de la funcin: Funcin intercambio(): Acepta: Regresa: Intercambia los valores de dos objetos enteros. Dos objetos enteros. Los mismos dos objetos enteros.

Debido a que la funcin deber regresar las mismas dos variables enteras que los que acepta, ambos sern parmetros de referencia. Vamos a etiquetar los parmetros como objeto1 y objeto2. El encabezado de la funcin entonces se convierte en: void intercambio(int &objeto1, int &objeto2) Observe el uso de ampersand para indicar que los parmetros son parmetros de referencia. Debido a que objeto1 y objeto2 son parmetros de referencia, se intercambiarn los valores de los objetos de argumento real usados en la llamada de la funcin. Ahora, para intercambiar los dos valores dentro de la funcin, deber crear un objeto variable local temporal para que no se pierda uno de los valores. De acuerdo con esta idea, la funcin completa es: void intercambio(int &objeto1, int &objeto2) { // Define como local la variable temporal int temp; // Intercambia los valores temp = objeto1; objeto1 = objeto2; objeto2 = temp; } // Fin de intercambio() Para llamar a esta funcin en un programa, simplemente liste el nombre de la funcin y proporcione dos objetos variables para intercambiar, por ejemplo: intercambio(a, b) Por supuesto, a y b debern definirse e inicializarse con valores dentro del programa llamador, en algn lugar antes de esta llamada de la funcin.

LOCALIZACIN DE LAS FUNCIONES DENTRO DE SU PROGRAMA Antes de que su programa pueda llamar a una funcin, C++ debe saber la clase de valor que la funcin regresa y el nmero y clase de parmetros que la funcin utiliza. En los ejemplos antes presentados las definiciones de las funciones preceden a las llamadas que se hacen a las mismas. Sin embargo, en muchos casos, las funciones pueden aparecer en diversos lugares de su programa fuente, por ejemplo, despus de cerrar la llave de la funcin main() No hay lmite en el
FUNCIONES - LECCIN - 10

10-20

MIGUEL . TOLEDO MARTNEZ

nmero de funciones definidas por el usuario que se puedan usar en un programa. Para llamar una funcin que regresa un valor, deber insertar el nombre de la funcin donde se quiera que regrese el valor. Para llamar una funcin void, simplemente liste su nombre como un enunciado dentro del programa llamador. En ambos casos, los argumentos reales requeridos por la funcin deber listarse dentro de parntesis despus del nombre de la funcin cuando sta se llama. Adems, el nmero de argumentos reales que se utilizan en la llamada de funcin deber ser el mismo que el nmero de parmetros formales definidos en el encabezado de la funcin respectiva, a menos que se usen parmetros predeterminados. La colocacin de las funciones en un programa C++ se resume en la figura 10.3. Observe la estructura en bloques de un programa general. La funcin main() forma el bloque externo general del programa y las funciones definidas por el usuario forman los bloques internos que se anidan dentro de la funcin main() por medio de las llamadas de las funciones. Esta es la razn de que C++ sea conocido como lenguaje estructurado en bloques. De ahora en adelante, cuando desarrollemos programas C++, intentaremos dividir el problema de programacin general en un grupo de subproblemas ms sencillos cuya solucin combinada soluciona el problema original. Cmo se codificarn estos subproblemas? Ya sabe, Cmo funciones! Esta es la esencia de la programacin estructurada y diseo descendente de software.
prototipo funcion1(); prototipo funcion2(); void main(void) { Llamada a la funcion1(); Llamada a la funcion2(); } // Fin de main()

funcion1() { enunciado1; enunciado2; ...................; enunciadoN; } // Fin de la funcion1()

funcion2() { enunciado1; enunciado2; ...................; enunciadoN; } // Fin de la funcion2()

Figura 10.3. Las funciones por lo general se colocan despus de main() en un programa C++

EXAMEN BREVE 28
FUNCIONES - LECCIN - 10

10-21

MIGUEL . TOLEDO MARTNEZ

PROTOTIPO DE FUNCIONES Para asegurarse de que C++ conoce las caractersticas de cada funcin que utiliza su programa, debe colocar prototipos de las funciones al principio de su programa fuente, algunas veces, se conoce como un enunciado de funcin; es un modelo de interfaz para la funcin que usa el compilador para verificar el nmero apropiado de argumentos y las clases de datos de los argumentos en las llamadas de la funcin. Los prototipos fuerzan al compilador a realizar verificaciones adicionales a sus llamadas de funcin, de esta manera ayudan en la deteccin de errores de programacin asociados con llamadas de funcin. Por ejemplo, si una funcin espera recibir un valor entero y el programador trata de pasar una cadena de caracteres, el compilador puede detectar el error porque C++ requiere que la funcin prototipo se especifique antes de la llamada de la funcin. Dado que los prototipos obligan al compilador a verificar errores durante la compilacin, esto no afecta el tamao ni la velocidad del tiempo de ejecucin del programa. Aunque tome al compilador ligeramente ms tiempo en realizar esta tarea de verificacin de errores, cualquier error detectado por medio de los prototipos puede ahorrar horas de depuracin, que seran necesarias si no se emplearan los prototipos. Por estas razones, el lenguaje C++ requiere las funciones prototipo. Sin embargo, conviene saber que la funcin prototipo es opcional en el lenguaje C. En la definicin anterior de prototipo, se infiere que ste proporciona un modelo de interfaz para la funcin. Bien, la interfaz de la funcin es el encabezado de la funcin; por lo tanto, el prototipo de la funcin es slo una copia del encabezado de la funcin que utiliza el compilador para verificar las llamadas a la funcin. As el prototipo dicta las clases de datos que aceptar la funcin desde el programa llamador y las que regresar la funcin al programa llamador. Los prototipos de funcin se localizan antes de la funcin main(). El prototipo de funcin puede ser slo una copia del encabezado de la funcin seguida por un punto y como, como lo que sigue:
void estudiante(int numero, float promedio, char calificacion);

Aqu, el prototipo le dice al compilador que la funcin estudiante() no regresar un valor al programa llamador. Adems, estudiante() espera recibir tres parmetros cuando se le llama. El primer parmetro se interpretar como un entero, el segundo como un valor de punto flotante y el tercero como un carcter. Si se hace un llamado de la funcin con ms o menos el nmero de parmetros listados en el prototipo, el compilador generar un error, a menos que se especifiquen parmetros predeterminados. Si se llama a la funcin con parmetros que pertenecen a clases de datos diferentes que las listadas en el prototipo, los parmetros se tratarn como si stos fueran la lista de clases de datos respectivos. En general un prototipo de funcin, contiene informacin acerca del tipo de retorno y de sus parmetros. Los siguientes enunciados ilustran prototipo de funcin para varias de las funciones ya utilizadas:

FUNCIONES - LECCIN - 10

10-22

MIGUEL . TOLEDO MARTNEZ

void muestraMensaje(void); void mostrarNumero(int); void mostrarEmpleado(int, float); int sumaValores(int, int); float valorPromedio(int, int);

Ejemplo 10.12
El siguiente programa: ESTUDIANTE.CPP, utiliza la funcin estudiante() cuyo prototipo ya se mostr: /* El siguiente programa: ESTUDIANTE.CPP, ilustra una funcin que muestra el nmero de exmenes realizados, el promedio y la calificacin alfabtica del estudiante. */ #include <iostream.h> //Para cout

// Prototipo de la funcin void estudiante(int numeroExamenes, float promedio, char calificacion); void main(void) { estudiante(5, 85.6, 'B'); } // Fin del main() /*********************************************************************************** Esta funcin mostrar un promedio del estudiante y su calificacin. ***********************************************************************************/ void estudiante(int numeroExamenes, float promedio, char calificacion) { cout.setf(ios::fixed); cout.precision(1); cout << "Hay " << numeroExamenes << " exmenes, que dan como resultado " << "un promedio de " << promedio << endl; cout << "y una calificacin alfabtica de " << calificacion << '.' << endl; } // Fin de estudiante() La salida generada por este programa es: Hay 5 exmenes, que dan como resultado un promedio de 85.6 y una calificacin alfabtica de B. Cmo puede observar, los argumentos reales en la llamada de la funcin pasaron a estudiante() y se utilizaron para construir el enunciado cout. Si se han utilizado ms o menos parmetros en la llamada de la funcin, el resultado ser un error de compilacin. Pero, qu pasara si las clases de datos del argumento no fueran las mismas que las listadas en el prototipo? Considere la siguiente llamada a la funcin: estudiante(B, A, 67); Esta llamada no deber producir un error de compilacin, porque el nmero de parmetros es correcto. Sin embargo, el compilador interpretar el primer parmetro como un entero, el segundo como un valor de punto flotante y el tercero como un valor carcter. El resultado que genera la llamada de funcin ser: Hay 66 exmenes, que dan como resultado un promedio de 65.0 y una calificacin alfabtica de C. Advierte lo que sucede? La funcin us el equivalente entero del carcter B para el primer parmetro, el equivalente a punto flotante del carcter A para el segundo parmetro y el equivalente del carcter del
FUNCIONES - LECCIN - 10

10-23

MIGUEL . TOLEDO MARTNEZ

entero 67 para el tercer parmetro. Desde luego, estas equivalencias se derivan del cdigo de caracteres ASCII. As, la leccin aqu es asegurarse que la clase de datos de los argumentos coincida con las clases de datos de los parmetros formales, de lo contrario obtendr resultados impredecibles. Observe nuevamente el prototipo de funcin estudiante() y ver que slo es una copia del encabezado de la funcin. Debido a esto, los prototipos son fcilmente codificados en su programa usando la caracterstica de copia de bloque de su editor. Una vez que ha codificado una funcin, simplemente marque el encabezado de la funcin y cpiela al rea prototipo justo antes de la funcin main() No olvide aadir un punto y coma al final del prototipo, porque el encabezado de la funcin copiado no la tiene. Tambin puede listar sus prototipo de funciones sin ningn identificador de parmetros, como el siguiente: void estudiante(int, float, char) Despus de todo, al compilador no le interesan los nombres de los parmetros, slo el nmero de parmetros y sus clases de datos. Un punto final: si olvida incluir un prototipo para una funcin obtendr un error familiar: prototype expected cuando compile su programa. Tambin obtendr este error si olvida incluir un archivo de encabezado para una funcin estndar en su programa debido a que los prototipos para las funciones estndar en C++ estn incluidos en los archivos de encabezado.

Ejemplo 10.13
El siguiente programa, PROTO.CPP, ilustra el uso de prototipo de funcin. /* El siguiente programa: PROTO.CPP, ilustra el uso de prototipos */ #include <iostream.h> float valorPromedio(int, int); void main(void) { cout << "El promedio de 2000 y 2 es " << valorPromedio(2000, 2) << endl; } //Fin de main() float valorPromedio(int a, int b) { return ((a + b) / 2.0); } //Fin de valorPromedio() //Para cout // Prototipo funcin

Como hemos dicho una de las caractersticas de los prototipos de funcin es forzar a que los argumentos sean del tipo adecuado. Estas conversiones pueden producir resultados incorrectos si no se siguen las reglas de asignacin de tipos de C++. Dichas reglas especifican la manera de convertir un tipo de datos a otro sin perder informacin. Las reglas de asignacin se aplican a expresiones que contienen valores de dos o ms clases de datos; tales expresiones tambin se conocen como expresiones de tipo mixto. El tipo de cada valor de una expresin de tipo mixto se promueve al tipo ms alto de la expresin (de hecho, se crea una versin temporal de cada valor que se utiliza para la expresin; los valores originales permanecen sin cambio) Otro uso comn de la promocin es cuando el tipo de un argumento para una funcin no es igual al tipo de parmetro especificado en la definicin de la funcin. En la tabla 10.1 se listan en los tipos de datos integrados, desde el tipo mas alto al tipo ms bajo.

FUNCIONES - LECCIN - 10

10-24

MIGUEL . TOLEDO MARTNEZ

La conversin de valores hacia tipos menores puede dar como resultado valores incorrectos. Por lo tanto, slo puede convertirse un valor de un tipo menor asignando especficamente dicho valor a una variable de menor tipo o empleando un operador de conversin mediante cast. Los valores de los argumentos de las funciones se convierten a los tipos de parmetros de un prototipo de funcin como si se estuvieran asignando directamente a variables dichos tipos. Clase de datos long double double float unsigned long int (sinnimo de unsigned long) long int (sinnimo de long) unsigned int (sinnimo de unsigned) Int unsigned short int (sinnimo de unsigned short) short int (sinnimo de short) unsigned char Short Char
Tabla 10.1. Jerarqua de promociones de las clases de datos estndar de C++

SOLUCIN DE PROBLEMAS EN ACCIN: Programacin estructurada LEY DE OHM


PROBLEMA
En lecciones anteriores, hemos desarrollado un programa de la ley de Ohm que maneja mens, controlado por un ciclo. Sin embargo, aunque desarrollamos un diseo estructurado, empleamos una implementacin lineal para codificar el diseo. Es tiempo de hacer lo correcto y emplear programacin estructurada por medio de las funciones para instrumentar el diseo estructurado. Esta es la definicin del problema que desarrollamos anteriormente:

DEFINICIN DEL PROBLEMA


Salida: El men que pida al usuario seleccionar una opcin de clculo de voltaje, corriente o resistencia. Se necesita un mensaje para entradas no vlidas. Un valor de voltaje, corriente o resistencia, dependiendo de la opcin del programa que el usuario seleccione. Una respuesta del usuario al men (V, C, R o S) Si selecciona V: el usuario escribe los valores para corriente y resistencia. Si selecciona C: el usuario escribe los valores para voltaje y resistencia. Si selecciona R: el usuario escribe los valores para voltaje y corriente. Si selecciona S: el programa termina. Calcula la opcin seleccionada. Case V: Voltaje = Corriente x Resistencia. Case C: Corriente = Voltaje / Resistencia. Case R: Resistencia = Voltaje / Corriente. Case S: Termina el programa. El men se repite hasta que el usuario decide terminar el programa
FUNCIONES - LECCIN - 10

Entrada:

Procesamiento:

10-25

MIGUEL . TOLEDO MARTNEZ

PLANEACIN DE LA SOLUCIN
Con el uso del diseo de programacin estructurada, dividiremos el problema en subproblemas individuales para solucionar el problema general. Hay dos tareas importantes que surgen directamente a partir de la definicin del problema: Mostrar el men y leer la opcin del usuario. Realizar los clculos seleccionados y mostrar los resultados.

Primero, el programa deber mostrar un men de selecciones al usuario. El usuario escribir su eleccin desde el men y dependiendo de su opcin, se har uno de los tres clculos para determinar la cantidad solicitada. El diagrama de estructura en la figura 10.4 muestra el diseo descendente. ohm() Llama a muestraMenu() Llama a leyDeOhm()

opcin opcin

muestraMenu() Muestra el men y obtiene la opcin del usuario

leyDeOhm() Realiza el clculo seleccionado y muestra los resultados

calculaVoltaje() si opcin V: calcula y muestra el voltaje.

calculaCorriente() si opcin C: calcula y muestra la corriente

calculaResistencia() si opcin R: calcula y muestra la resistencia

Figura 10.4. Diagrama de estructura para el problema de la ley de Ohm Observe que hay ahora tres niveles de solucin del problema. En el primer nivel ohm(), llama a una funcin para mostrar el men y obtener la seleccin del usuario. La funcin muestraMenu() realiza esta tarea y enva la seleccin del usuario de regreso a main() como se indica en el diagrama. La funcin ohm () enviar la seleccin a la funcin llamada leyDeOhm(), que llamar una de las tres funciones, dependiendo de la seleccin, para realizar los clculos requeridos. Ahora, la descripcin del proceso requiere que agreguemos al programa una caracterstica de control del ciclo. Aqu se muestra el conjunto de algoritmos revisados a travs del primer nivel de refinamiento ALGORITMO INICIAL ohm () INICIO hacer Llama a la funcin muestraMenu(). Llama a la funcin leyDeOhm(). mientras (opcin != s Y opcin != S) FIN. El primer nivel de refinamiento muestra el contenido de muestraMenu() y leyDeOhm(), como sigue:
FUNCIONES - LECCIN - 10

10-26

MIGUEL . TOLEDO MARTNEZ

PRIMER NIVEL DE REFINAMIENTO muestraMenu() Inicio Muestra el men del programa que pide al usuario seleccionar la opcin de voltaje (V), corriente (I), resistencia (R) o salir (S). Leer(opcion). Fin.. leyDeOhm() Inicio Caso V: Llama a la funcin calculaVoltaje(). Caso C: Llama a la funcin calculaCorriente(). Caso R: Llama a la funcin calculaResistencia(). Case S: Termina el programa. sino: escribir(Entrada no vlida, seleccionar de nuevo). Fin. Observe que la caracterstica de control del ciclo se adiciona al nivel del algoritmo inicial ohm () Los algoritmos muestraMenu() y leyDeOhm() del primer nivel de refinamiento no han cambiado respecto de nuestra solucin anterior. As es que, enfoqumonos en el control del ciclo en ohm () Recordemos que la funcin muestraMenu() obtiene la opcin del men del usuario. Si el usuario introduce una s o S para salir del programa, se romper el ciclo y el programa termina. Pero, hay algn error aqu? La seudocodificacin dice si el usuario introduce una s o S el programa se termina, sin embargo, la verificacin del ciclo emplea la operacin Y. Entonces, por qu se utiliza la operacin Y en lugar de la operacin O para realizar esta verificacin? Este es un candidato clsico para explicar en el escritorio la lgica del algoritmo antes de codificar el programa. Pregntese cundo se romper el ciclo? Un ciclo do/while se rompe cuando el estado verificado es falso, correcto? Recuerde que el resultado de una operacin Y es falso cuando alguno de sus estados es falso. Como resultado, el ciclo se romper cuando opcion sea una s o una S. El ciclo continuar cuando sean verdaderos ambos lados de la operacin Y. Por tanto, el ciclo continuar siempre y cuando opcion no sea una s y opcion no sea S. No es esto lo que queremos hacer? Qu pasara si errneamente usara la operacin O en la prueba del ciclo anterior? Una operacin O produce un resultado verdadero cuando alguna de sus condiciones es verdadera. Una de estas condiciones podra ser siempre verdadera, dado que opcin no puede ser s y S. El resultado de este descuido ser un ciclo infinito. Necesitamos hacer otra aclaracin aqu. Esta aplicacin es un candidato clsico para el ciclo do/while en vez de un ciclo while, porque siempre querr que el men se muestre por lo menos una vez para permitirle al usuario la seleccin de una opcin. Ahora, necesitamos un segundo nivel de refinamiento para mostrar el contenido de las funciones de clculo: SEGUNDO NIVEL DE REFINAMIENTO calculaVoltaje() Inicio Escribir(Favor de introducir un valor para la corriente). Leer(corriente). Escribir(Favor de introducir un valor para la resistencia). Leer(resistencia). si resistencia < 0 escribir(Entrada no vlida, ejecutar el programa de nuevo). sino Calcula voltaje = corriente x resistencia. escribir(voltaje). Fin. calculaCorriente() Inicio
FUNCIONES - LECCIN - 10

10-27

MIGUEL . TOLEDO MARTNEZ

Escribir(Favor de introducir un valor para el voltaje). Leer(voltaje). Escribir(Favor de introducir un valor para la resistencia). Leer(resistencia). si resistencia <= 0 escribir(Entrada no vlida, ejecutar el programa de nuevo). sino Calcula corriente = voltaje / resistencia. escribir(corriente). Fin. calculaResistencia() Inicio Escribir(Favor de introducir un valor para el voltaje). Leer(voltaje). Escribir(Favor de introducir un valor para la corriente). Leer(corriente). si corriente == 0 escribir(Entrada no vlida, ejecutar el programa de nuevo). sino Calcula resistencia = voltaje / corriente. escribir(resistencia). Fin. Cada funcin de clculo obtiene los datos necesarios para los clculos respectivos de la ley de Ohm. La funcin hace los clculos y muestra el resultado. Observando ms de cerca estos algoritmos, encontrar algunas caractersticas de proteccin. Los enunciados si/sino dentro de cada funcin protegen contra entradas de datos no vlidos. Un valor de resistencia negativa no es vlido porque no hay tal cosa. Adems, no podr dividir entre 0. Como resultado, las funciones calculaCorriente() y calculaResistencia() cada una verifica las entradas cero para los valores que se usan como divisor en clculo de la ley de Ohm. CODIFICACIN DEL PROGRAMA Ahora, para instrumentar el diseo, necesitamos construir las funciones. La tarea principal es desarrollar las interfaces de la funcin. Para hacerlo, debemos desarrollar la definicin del problema para cada funcin. La definicin del problema desarrollado anteriormente dirige la salida, entrada y procesamiento del programa general, ohm (). Esto es todava necesario para definir el problema para el programa como un todo. Sin embargo, para construir las interfaces de la funcin, debemos dirigir la definicin del problema desde la perspectiva de la funcin. En otras palabras, debemos considerar la salida, entrada y procesamiento de cada funcin individual. La entrada a la funcin es lo que la funcin debe aceptar para realizar su tarea designada, la salida de la funcin es lo que la funcin regresa, y el procesamiento es la tarea que realizar la funcin. Empezaremos con la funcin muestraMenu(). Es necesario preguntar dos cosas 1) Qu necesita aceptar (entrada) la funcin para realizar su tarea designada? y 2) Qu necesita regresar (salida) la funcin al programa llamador? La tarea de la funcin muestraMenu() es mostrar el men y regresar la opcin del usuario a su funcin de llamada, ohm (). De esta manera, esta funcin no necesita aceptar nada desde ohm () para realizar su tarea, pero requiere regresar un valor sencillo para ohm (), que es la opcin del men del usuario. Esto se muestra en el diagrama de estructura por medio de la variable opcin que viene de muestraMenu(). Observe que nada va dentro de esta funcin. Aqu est la definicin del problema desde la perspectiva de esta funcin: Funcin muestraMenu(): Acepta: Regresa: Muestra el men y obtiene la entrada del usuario. Nada. La opcin del men obtenida del usuario.

La definicin de la funcin describe la interfaz de la funcin. La primera decisin que necesita tomar es si se usar una funcin void o una sin void. Emplee una funcin sin void si la funcin produce un valor sencillo que regrese al programa llamador. Use una funcin void si la funcin no acepta o regresa nada o
FUNCIONES - LECCIN - 10

10-28

MIGUEL . TOLEDO MARTNEZ

acepta una(s) variable(s), cambia y regresa la(s) variable(s) modificada(s) al programa llamador. En otras palabras, si el diagrama de estructura indica que la funcin produce un valor sencillo, utilice una funcin sin void. Si el diagrama de estructura indica que la funcin no acepta ni regresa nada, o si la funcin acepta y regresa una variable determinada, utilice una funcin void. Estos lineamientos se resumen en la tabla 10.1. Debido a que nuestra funcin muestraMenu() no acepta nada, pero regresa la opcin del men del usuario, deber ser una funcin sin void. As, la clase de regreso deber ser char, porque la opcin del usuario ser un carcter desde el men. TABLA 10.1 CLASE DE REGRESO DE LA FUNCIN

Regresa
Un valor sencillo Nada Valores mltiples

Clase de datos return


Sin void void void

Despus, decidiremos los parmetros de la funcin. La tabla 10.2 proporciona las pautas para determinar si un parmetro determinado deber ser un valor o un parmetro de referencia. TABLA 10.2 PARMETROS DE FUNCIONES

Acepto o regresa
No acepta Acepta sin regresar (en un sentido) Acepta y regresa (en dos sentidos)

Parmetro
Ninguno Valor Referencia

Ningn parmetro se requiere para muestraMenu(), porque no acepta nada, de esta manera la interfaz de la funcin es solamente: char muestraMenu(void) Ahora, simplemente colocamos el cdigo muestraMenu(void) desarrollado al principio dentro de la funcin. Aqu est la funcin completa: char muestraMenu() { // Define la variable local opcion char opcion = S; // Genera el men y obtiene la opcin del usuario cout << "\n\n\t\t\tEscriba V para encontrar el voltaje." << endl << endl << "\t\t\tEscriba C para encontrar la corriente." << endl << endl << "\t\t\tEscriba R para encontrar la resistencia." << endl << endl << "\t\t\tEscriba S para salir." << endl << endl << "\tPor favor escriba su opcin: "; cin >> opcion; // Regresa la opcin return opcion; } // Fin de muestraMenu()

FUNCIONES - LECCIN - 10

10-29

MIGUEL . TOLEDO MARTNEZ

Observe que nuestra variable opcion ahora est definida como una variable local dentro de la funcin. Adems, un enunciado return se coloca al final de la funcin para regresar opcion a su funcin de llamada ohm (). Despus, vamos a desarrollar la funcin leyDeOhm(). Empecemos a desarrollar la interfaz de la funcin. En el diagrama de estructura es fcil de ver lo siguiente: Funcin leyDeOhm(): Acepta: Regresa: Realiza el clculo de la opcin y muestra los resultados. La entrada opcin del men, obtenida desde main(). Nada.

A partir de la descripcin de la interfaz, es fcil ver que se deber usar una funcin void porque la funcin no regresa nada. Aunque la funcin muestre los resultados, no est regresando ningn valor a su funcin de llamada ohm (). Sin embargo, esta funcin necesita aceptar la opcin del men desde ohm (). Esto significa que necesitamos un parmetro de funcin. Ahora la pregunta es: El parmetro es de valor o de referencia?. Bien, si es de un sentido dentro de la funcin, el parmetro deber ser de valor. Si es en dos sentidos, entrada y salida de la funcin, deber ser un parmetro de referencia. Debido a que acepta este parmetro, pero no lo regresa, deber ser un parmetro de valor, correcto? El parmetro necesario es un carcter, as la interfaz de la funcin se convierte en: void leyDeOhm(char opcion) Ahora, al insertar nuestro cdigo de enunciado de intercambio en el cuerpo de la funcin, se obtendr: void leyDeOhm(char opcion) { // Establecer la precisin de la salida. cout.setf(ios::fixed); cout.precision(2); switch(opcion) { case 'v' case 'V':
cout << "\n\nEl valor del voltaje es: << calculaVoltaje()

<< volts. << endl; break; case c: case C:


cout << \n\nEl valor de la corriente es: << calculaCorriente() << miliamperes. << endl; break;

case r: case R:
cout << \n\nEl valor de la resistencia es: << calculaResistencia() << kilohms. << endl; break;

case s: // Termina el programa case S: cout << El programa terminado << endl; break; // Muestra el mensaje de entrada no vlida default:
cout << \n\nEsta es una entrada no vlida. << endl;

} // Fin de switch() } // Fin de leyDeOhm()


FUNCIONES - LECCIN - 10

10-30

MIGUEL . TOLEDO MARTNEZ

Observe que la funcin emplea el enunciado switch, que acta en la seleccin del usuario, opcion, que se recibe como un parmetro desde la funcin de llamada, ohm (). Despus, veremos que cada caso de la ley de Ohm llama a otra funcin como parte de un enunciado cout para calcular el voltaje, corriente o resistencia requeridos, dependiendo del valor de opcion. Cada funcin de la ley de Ohm regresar un valor sencillo de voltaje, corriente o resistencia, dependiendo del case que se ejecute. Esto le sugiere el tipo de funciones (void o sin void)? Por ltimo, observe que no hay enunciado return en nuestra funcin leyDeOhm() porque es una funcin void. Enseguida se presentan las descripciones de interfaz para cada una de las funciones de la ley de Ohm: Funcin calculaVoltaje(): Acepta: Regresa: Funcin calculaCorriente(): Acepta: Regresa: Funcin calculaResistencia(): Acepta: Regresa: Obtiene del usuario la corriente y resistencia y usa le ley de Ohm para calcular el voltaje. Nada. Voltaje. Obtiene del usuario el voltaje y resistencia y usa la ley de Ohm para calcular la corriente. Nada. Corriente. Obtiene del usuario el voltaje y corriente y usa la ley de Ohm para calcular la resistencia. Nada. Resistencia.

Cada una de estas funciones tendr la misma interfaz, excepto, desde luego, para el nombre de la funcin. Cada funcin ser una funcin sin void, porque la funcin produce y regresa un solo valor. Ningn parmetro se requiere, porque ninguna de las funciones necesita aceptar ningn dato de la funcin de llamada leyDeOhm(). Probablemente piense que cada una de las funciones necesita las dos cantidades desconocidas en la ecuacin de la ley de Ohm para hacer el clculo necesario. Sin embargo, estas cantidades se obtienen del usuario dentro de cada una de las funciones y no desde la funcin de llamada leyDeOhm(). A continuacin se dan las interfaces de la funcin resultante: float calculaVoltaje(void); float calculaCorriente(void); float calculaResistencia(void); Ahora, todas las funciones completas: float calculaVoltaje() { // Define variables locales float corriente = 0.0; float resistencia = 0.0;

// Corriente en miliamperes // Resistencia en Kilo-ohms.

// Obtiene la corriente y la resistencia cout << \nEscriba el valor de la corriente en miliamperes\tC = ; cin >> corriente; cout << \nEscriba el valor de la resistencia en kilo-ohms\t\R = ; cin >> resistencia; // Verifica que la resistencia sea < 0 y calcula el voltaje if(resistencia < 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" "seleccione de nuevo." << endl; return 0.0; } // Fin del if else
FUNCIONES - LECCIN - 10

10-31

MIGUEL . TOLEDO MARTNEZ

return corriente * resistencia; } // Fin de calculaVoltaje() float calculaCorriente() { // Define variables locales float voltaje = 0.0; float resistencia = 0.0;

// Voltaje en volts // Resistencia en kilo-ohms

// Obtiene el voltaje y resistencia cout << "\nEscriba el valor del voltaje en volts\tV = "; cin >> voltaje; cout << "\nEscriba el valor de la resistencia en KiloOhms\tR = "; cin >> resistencia; // Verifica que la resistencia sea <= 0 y calcula la corriente if(resistencia <= 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; return 0.0; } // Fin del if else return voltaje / resistencia; } // Fin de calculaCorriente() float calculaResistencia() { // Define variables locales float voltaje = 0.0; float corriente = 0.0;

// Voltaje en volts // Corriente en miliamperes

// Obtiene el voltaje y la corriente cout << "\nEscriba el valor del voltaje en volts\tV = "; cin >> voltaje; cout << "\nEscriba el valor de la corriente en miliamperes\tI = "; cin >> corriente; // Verifica que la corriente sea == 0 y calcula la resistencia if(corriente == 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; return 0.0; } // Final del if else return voltaje / corriente; } // Fin de calculaResistencia() Observe que cada una de las funciones obtiene del usuario los datos necesarios para el clculo. Los datos de entrada son verificados. Si no son vlidos, se genera un mensaje apropiado; de otra manera, la funcin regresa el valor requerido. Observe que hay dos enunciados return en cada funcin. Dado que hemos definido las funciones como sin void, stas deben regresar un valor, sin importar ninguna condicin de terminacin. Esto es la razn por la que hay un enunciado return 0.0 despus del mensaje de entrada no vlida en cada funcin. Se ha elegido regresar el valor 0.0 en esta situacin, porque debe regresar un valor de punto flotante.
FUNCIONES - LECCIN - 10

10-32

MIGUEL . TOLEDO MARTNEZ

Estamos listos para combinar todo en un programa completo. Es el siguiente: /* El siguiente programa: MENU.CPP, muestra el concepto de programacin estructurada */ Salida: Un men del programa le pide al usuario seleccionar una opcin para calcular el Voltaje, Corriente o Resistencia. Se debe enviar un mensaje en el caso de hacer una seleccin invlida. Mostrar un valor del Voltaje, Corriente o resistencia dependiendo de la opcin que el usuario seleccione. Entrada: Una respuesta del usuario al men (V, C, R o S). Si se selecciona V: escribe un valor para la corriente y la resistencia. Si selecciona C: escribe un valor para voltaje y resistencia. si selecciona R: escribe un valor para voltaje y corriente. Si selecciona S: el programa termina. Procesamiento: Clculo de la opcin seleccionada Case V: Voltaje = Corriente x Resistencia. Case C: Corriente = Voltaje / Resistencia. Case R: Resistencia = Voltaje / Corriente. Case S: Termina el programa. */ #include <iostream.h> // Funciones prototipo char muestraMenu(void); void leyDeOhm(char opcion); float calculaVoltaje(void); float calculaCorriente(void); float calculaResistencia(void); // Para cin y cout. // Muestra el men de la ley de Ohm // Obtiene la opcin del men y llama la funcin // de la ley de Ohm necesaria // Calcula el voltaje // Calcula la corriente // Calcula la resistencia

void main(void) { // Definicin de variables argumentos de la funcin. char opcion = 'S'; // Entrada del usuario desde el men. // Muestra el mensaje de la descripcin del programa. cout << "Este programa calcular el voltaje de cd, corriente, o\n" "resistencia proporcionando los otros dos valores." << endl << endl; do { opcion = muestraMenu(); // Llama a muestraMenu() leyDeOhm(opcion); // Llama a la leyDeOhm() } // Fin del do/while while((opcion != 's') && (opcion != 'S')); } // Fin del main() // Funcin para mostrar el men y regresar la opcin del usuario char muestraMenu() { // Define la variable local char opcion = 'S';

FUNCIONES - LECCIN - 10

10-33

MIGUEL . TOLEDO MARTNEZ

// Genera el men y obtiene la opcin del usuario cout << "\n\n\t\t\tEscriba V para encontrar el voltaje." << endl << endl << "\t\t\tEscriba C para encontrar la corriente." << endl << endl << "\t\t\tEscriba R para encontrar la resistencia." << endl << endl << "\t\t\tEscriba S para salir." << endl << endl << "\tPor favor escriba su opcin: "; cin >> opcion; // Regresa la opcion return opcion; } // Fin de muestraMenu() // Funcion para llamar la funcion de la ley de Ohm requerida void leyDeOhm(char opcion) { // Establecer la precisin de la salida. cout.setf(ios::fixed); cout.precision(2); switch(opcion) { case 'v': case 'V': cout << "\n\nEl valor del voltaje es: " << calculaVoltaje() << " volts." << endl; break; case 'c': case 'C': cout << "\n\nEl valor de la corriente es: " << calculaCorriente() << " miliamperes." << endl; break; case 'r': case 'R': cout << "\n\nEl valor de la resistencia es: " << calculaResistencia() << " KiloOhms." << endl; break; case 's': // Termina el programa case 'S': cout << "Programa terminado" << endl; break; // Muestra el mensaje de entrada no vlida. default: cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; } // Fin del switch } // Fin de leyDeOhm() // Funcin para el clculo del voltaje float calculaVoltaje(void) { // Define variables locales float corriente = 0.0; float resistencia = 0.0;

// Corriente en miliamperes // Resistencia en KiloOhms

FUNCIONES - LECCIN - 10

10-34

MIGUEL . TOLEDO MARTNEZ

// Obtiene la corriente y resistencia cout << "\nEscriba el valor de la corriente en miliamperes\tC = "; cin >> corriente; cout << "\nEscriba el valor de la resistencia en KiloOhms\tR = "; cin >> resistencia; // Verifica que la resistencia sea < 0 y calcula el voltaje if(resistencia < 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; return 0.0; } // Fin de if else return corriente * resistencia; } // Fin de calculaVoltaje // Funcin para el clculo de la corriente float calculaCorriente() { // Define variables locales float voltaje = 0.0; float resistencia = 0.0;

// Voltaje en volts // Resistencia en KiloOhms

// Obtiene el voltaje y resistencia cout << "\nEscriba el valor del voltaje en volts\tV = "; cin >> voltaje; cout << "\nEscriba el valor de la resistencia en KiloOhms\tR = "; cin >> resistencia; // Verifica que la resistencia sea <= cero y calcula la corriente if(resistencia <= 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; return 0.0; } // Fin del if else return voltaje / resistencia; } // Fin de calculaCorriente() // Funcin para calcular la resistencia float calculaResistencia() { // Define variables locales float voltaje = 0.0; float corriente = 0.0;

// Voltaje en volts // Corriente en miliamperes

// Obtiene el voltaje y la corriente cout << "\nEscriba el valor de voltaje en volts\tV = "; cin >> voltaje; cout << "\nEscriba el valor de la corriente en miliamperes\tI = "; cin >> corriente;

FUNCIONES - LECCIN - 10

10-35

MIGUEL . TOLEDO MARTNEZ

// Verifica que la corriente sea == 0 y calcula la resistencia if(corriente == 0) { cout << "\n\nEsta es una entrada no vlida. Por favor" " seleccione de nuevo." << endl; return 0.0; } // Fin de if else return voltaje / corriente; } // Fin de calculaResistencia() Lo primero que se ve en la parte superior del programa son las funciones prototipo. Estas slo se copiaron del encabezado de la funcin agregando un punto y coma al final de cada una. El buen estilo dice que cada prototipo deber comentarse de acuerdo con el propsito de la funcin. Recuerde que C++ requiere un prototipo para cada funcin para que pueda verificar la precisin de las llamadas de la funcin. A continuacin, se sorprender de la simplicidad de la funcin main(). Todo lo que hace es escribir un mensaje de descripcin del programa y llamar nuestras dos funciones principales dentro de un ciclo de control del programa. La mayor parte del trabajo real del programa se hace dentro de las funciones. Esto es la programacin estructurada! El resto del programa contiene cada una de las funciones que hemos explicado anteriormente.

SOLUCIN DE PROBLEMAS EN ACCIN: Estado de cuenta de una cuenta de ahorros.


En la leccin 4, empleamos el refinamiento sucesivo (paso a paso) para disear una solucin para una aplicacin de cuentas de ahorro. Codificamos la solucin usando implementacin lineal porque, en ese momento, no se conoca cmo aplicar un diseo estructurado usando las funciones C++. Vamos a revisar esta aplicacin con nuestro reciente conocimiento de funciones. Aqu est el enunciado del problema otra vez:

PROBLEMA
Su banco local lo contrat para disear un programa estructurado que procese datos de las cuentas de ahorro. Desarrolle una serie de algoritmos relacionados con el uso del mtodo de diseo estructurado de arriba-abajo (descendente) que se pueda codificar en un lenguaje de programacin estructurada.

DEFINICIN DEL PROBLEMA


Salida El programa debe generar un reporte que muestre las transacciones (balance del mes anterior, depsitos y retiros del mes actual) de la cuenta y el balance actual para una cuenta de ahorro en un mes determinado. Supondremos que el usuario ingresar la informacin de las transacciones mensualmente e incluir el balance del mes anterior, los depsitos y retiros del mes actual. El programa debe agregar al balance del mes anterior los depsitos, restar los retiros, calcular y agregar el inters del mes para determinar el balance actual.

Entrada

Procesamiento

PLANEACIN DE LA SOLUCIN
Con el uso del diseo estructurado, empezaremos en dividir el problema en subproblemas para solucionar el problema bancario. Trate de identificar las tareas individuales para solucionar el problema. Primero, el usuario debe ingresar los datos de la transaccin requerida, las cuales incluirn el balance del mes anterior, depsitos y retiros del mes actual. Una vez que se ingresan los datos de la transaccin, el programa debe adicionar los depsitos al balance de la cuenta, restar los retiros de la cuenta, calcular el inters y generar el reporte necesario. Como resultado, podemos identificar cinco tareas del programa como sigue:
FUNCIONES - LECCIN - 10

10-36

MIGUEL . TOLEDO MARTNEZ

Obtener del usuario los datos de la transaccin. Agregar los depsitos al balance anterior de la cuenta. Restar los retiros del balance anterior de la cuenta. Calcular el inters de la cuenta. Generar el reporte mensual de la cuenta.

La figura 10.5 muestra el diagrama de la estructura en donde se ven los bloques necesarios para el programa: estadoCuenta()
Determinacin del balance mensual de una cuenta de ahorros

obtenerDatos()
Obtencin de los datos de las transacciones

agregarDepositos()
Adicin de los depsitos

restarRetiros()
Substraccin de retiros

calcularInteres()
Clculo del interes

generarReporte()
Generar el reporte

Figura 10.5. Diagrama de estructura para el problema bancario. Debido a que usaremos la tcnica estructurada de bloques para disear el programa, debemos emplear el refinamiento paso a paso para desarrollar el algoritmo. El nivel de algoritmo inicial, main(), reflejar la definicin del problema y llama a los mdulos de los subprogramas individuales o funciones como sigue: ALGORITMO INICIAL estadoCuenta () INICIO Llamar a la funcin obtenerDatos() para obtener los datos de la transaccin. Llamar a la funcin agregarDepositos() para adicionar los depsitos en la cuenta. Llamar a la funcin restarRetiros() para restar los retiros de la cuenta. Llamar a la funcin calcularInteres para calcular el inters de la cuenta. Llamar a la funcin generarReporte() para mostrar el reporte de la cuenta. FIN. El primer nivel de refinamiento requiere que mostremos un algoritmo detallado para cada mdulo del subprograma o funcin. Estos son como sigue: PRIMER NIVEL DE REFINAMIENTO obtenerDatos() Inicio Escribir (Introducir balance del mes anterior). Leer(balanceAnterior). Escribir (Introducir los depsitos del mes actual). Leer(depositos). Escribir (Introducir los retiros del mes actual). Leer(retiros). Fin.

FUNCIONES - LECCIN - 10

10-37

MIGUEL . TOLEDO MARTNEZ

agregarDepositos() Inicio Calcular balanceActual = balanceAnterior + depositos. Fin. restarRetiros() Inicio Calcular balanceActual = balanceActual retiros. Fin. calcularInteres() Inicio Calcular balanceActual = balanceActual + (balanceActual * interes). Fin. generarReporte() Inicio Escribir(balanceActual). Escribir(depositos). Escribir(retiros). Fin. Con nuestro conocimiento de funciones podemos modificar el diagrama de estructura, como se muestra en la figura 10.6. Observe lo que se ha adicionado. Primero, el cuadro en la parte superior est etiquetado como estadoCuenta () y simplemente llama a las funciones individuales en el orden en que stas se necesitan para solucionar el problema. Segundo, los objetos de datos que pasan a las funciones, o desde stas, se muestran en las lneas que conectan a estadoCuenta () con las funciones. Los objetos que acepta la funcin se muestran a la izquierda de la lnea de conexin y los objetos que regresa la funcin se muestran a la derecha de la lnea como sigue: Si un objeto de datos va en un sentido dentro de la funcin, es un parmetro de valor. Si un objeto de datos va en un sentido fuera de la funcin, es un valor de regreso. Si un objeto de datos va en dos sentidos dentro y fuera de la funcin, es un parmetro de referencia.

Para construir el diagrama estructurado extendido, deber considerar una definicin de problema para cada funcin describiendo la interfaz de funcin en trminos de lo que acepta y regresa. Vamos a empezar con la funcin obtenerDatos(). Funcin obtenerDatos(): Obtiene del usuario el balance actual de la cuenta, depositos y retiros. Acepta: Conserva el lugar para un objeto variable para balance, depositos y retiros. Regresa: Balance, depositos y retiros. La funcin obtenerDatos() deber obtener entradas del usuario y regresarlas al programa llamador estadoCuenta (). Como resultado, la funcin deber aceptar un lugar para un objeto variable colocado para cada entrada del usuario. La funcin obtendr del usuario un valor para llenar cada lugar para la variable y despus regresar la variable a estadoCuenta (). Esta descripcin de interfaz se representa en el diagrama de estructura de la figura 10.6, mediante la muestra de las variables balance, depositos y retiros que van dentro y fuera del mdulo de la funcin obtenerDatos(). Esto significa que los tres debern ser parmetros de referencia, dando origen a una interfaz de funcin de: void obtenerDatos(float &balance, float &depositos, float &retiros)

FUNCIONES - LECCIN - 10

10-38

MIGUEL . TOLEDO MARTNEZ

estadoCuenta ()
Determinacin del balance mensual de una cuenta de ahorros

balance depositos retiros

balance Depositos Retiros

balance depositos

balance

balance retiros

balance

balance

balance

balance Depositos retiros

obtenerDatos()
Obtencin de los datos de transacciones

agregarDepositos()
Adicin de los depsitos

restarRetiros()
Substraccin de retiros

calcularInteres()
Clculo del interes

generarReporte()
Generar el reporte

Figura 10.6. Diagrama de estructura extendido que muestra los elementos de datos fluyendo hacia o desde las funciones de la cuenta bancaria. La interfaz de funcin agregarDepositos() se puede describir como sigue: Funcin agregarDepositos(): Acepta: Regresa: Aade los depositos al balance actual. El balance y los depositos de la cuenta actual. Un nuevo balance de cuenta.

Esta funcin necesita que reciba el balance y los depositos actuales de la cuenta para calcular y regresar el nuevo balance. Como resultado, la funcin acepta balance y depositos; balance entonces cambia por la adicin de los depositos y balance regresa a estadoCuenta (), como se muestra en el diagrama de estructura. Observe que balance va en dos sentidos, dentro y fuera de la funcin, mientras que depositos va solamente en un sentido, dentro de la funcin. Esto significa que balance deber ser un parmetro de referencia y depositos, un parmetro de valor. Por lo tanto, la funcin interfaz resultante ser: void agregarDepositos(float &balance, float depositos) La funcin restarRetiros() recibe el balance y el retiro actual de la cuenta, resta los retiros y regresa el nuevo balance de la cuenta. Con esta informacin, esta interfaz se puede describir como sigue: Funcin restarRetiros(): Acepta: Regresa: Resta los retiros del balance actual. El balance y los retiros actuales de la cuenta. Un nuevo balance de la cuenta.

El diagrama de estructura ejemplifica esta informacin mostrando balance que va en dos sentidos, dentro y fuera de la funcin, mientras retiros va solamente en un sentido, dentro de la funcin. De esta manera, balance ser un parmetro de referencia, y retiros un parmetro de valor. La interfaz de la funcin resultante es: void restarRetiros(float &balance, float retiros) Despus, la funcin calcularInteres() recibe el balance de la cuenta, calcula el inters mensual lo adiciona al balance y regresa el balance. Esta funcin se puede describir como sigue:

Funcin calcularInteres(): Acepta: Regresa:

Adiciona el inters mensual al balance de la cuenta El balance actual de la cuenta. Un nuevo balance de la cuenta.

FUNCIONES - LECCIN - 10

10-39

MIGUEL . TOLEDO MARTNEZ

Aqu, la funcin acepta el balance de la cuenta, que ha cambiado por la adicin del inters mensual y regresa a estadoCuenta () por medio de la funcin. Transcribiendo esta informacin al diagrama de estructura, se encuentra que balance va dentro y fuera del mdulo de la funcin calcularInteres(). La interfaz resultante es: void calcularInteres(float &balance) Por ltimo, la funcin generarReporte() recibe el balance, depositos y retiros de la cuenta para generar el informe de la cuenta. Por lo tanto, esta funcin se describe como sigue: Funcin generarReporte(): Acepta: Regresa: Genera el informe de la cuenta. El balance, depositos y retiros de la cuenta. Nada.

Para generar el informe de la cuenta, la funcin debe recibir el balance, depositos y retiros de la cuenta desde estadoCuenta (). Sin embargo, estos valores no se modifican ni regresan; slo se muestran como parte del informe por medio de la funcin. De esta manera, el diagrama de estructura indica balance, depositos y retiros en un solo sentido, dentro del mdulo de la funcin. Esto significa que stos debern ser parmetros de valor, correcto? La interfaz de la funcin resultante es: void generarReporte(float balance, float depositos, float retiros) Cercirese de ver cmo se muestra la descripcin en el diagrama de estructura de la interfaz para cada funcin y cmo se traduce el diagrama de estructura directamente al cdigo interfaz C++. Si un objeto de datos solamente se presenta fuera de la funcin, es un valor de regreso. Observe que no hay variables que slo estn presentes fuera de cualquiera de las funciones. Como resultado, todas las funciones tienen clases de regreso void. Si un objeto slo va dentro de la funcin, es un parmetro de valor. Si un objeto est dentro y fuera de la funcin, es un parmetro de referencia y debe estar precedido de un smbolo ampersand en el prototipo. Por ltimo, empleando las interfaces de la funcin, los algoritmos y combinando todo, obtenemos el siguiente cdigo:

CODIFICACIN DEL PROGRAMA


La solucin del problema anterior se puede codificar fcilmente en cualquier lenguaje de programacin estructurada. A continuacin los algoritmos anteriores se codifican en C++. /* El siguiente programa: ESTRUC1.CPP, muestra la naturaleza estructurada en bloques de C++. */ #include <iostream.h> // Para cin y cout.

// Define INTERES como una constante global. const float INTERES = 0.001; // Impuesto mensual actual.

// Prototipo de funciones. void obtenerDatos(float &, float &, float &); void agregarDepositos(float &, float); void restarRetiros(float &, float); void calcularInteres(float &); void generarReporte(float, float, float);

FUNCIONES - LECCIN - 10

10-40

MIGUEL . TOLEDO MARTNEZ

void main(void) { // Define las variables del argumento de la funcin float balance = 0.0; // Balance de la cuenta. float depositos = 0.0; // Depsitos mensuales. float retiros = 0.0; // Retiros mensuales. // Muestra el mensaje de descripcin del programa. cout << "Este programa generar un reporte de la cuenta bancaria con\n" "base en la informacin proporcionada por el usuario" << endl << endl; // Funciones llamada obtenerDatos(balance, depositos, retiros); agregarDepositos(balance, depositos); restarRetiros(balance, retiros); calcularInteres(balance); generarReporte(balance, depositos, retiros); } // Final de main() // Esta funcin obtiene la informacin mensual de la cuenta por el usuario. void obtenerDatos(float &balance, float &depositos, float &retiros) { cout << "Ingrese el balance de la cuenta : $"; cin >> balance; cout << "Ingrese los depsitos de este mes: $"; cin >> depositos; cout << "Ingrese los retiros de este mes : $"; cin >> retiros; } // Fin obtenerDatos() // Esta funcin adiciona los depsitos mensuales al balance de la cuenta. void agregarDepositos(float &balance, float depositos) { balance = balance + depositos; } // fin agregarDepositos() / Esta funcin sustrae los retiros mensuales desde el balance de la cuenta. void restarRetiros(float &balance, float retiros) { balance = balance - retiros; } // Fin restarRetiros() // Esta funcin adiciona los intereses mensuales al balance de la cuenta. void calcularInteres(float &balance) { balance = balance + (balance * INTERES); } // Fin calcularInteres() // Esta funcin muestra el reporte mensual de la cuenta. void generarReporte(float balance, float depositos, float retiros) { cout << endl; cout << "El balance de la cuenta actualmente es: $" << balance << endl; cout << "Los depsitos fueron : $" << depositos << endl; cout << "Los retiros fueron : $" << retiros << endl; } // Fin generarReporte()

FUNCIONES - LECCIN - 10

10-41

MIGUEL . TOLEDO MARTNEZ

Eso es todo! Ahora debe tener el conocimiento para comprender todas las facetas de este problema, desde el diseo estructurado al programa estructurado C++.

EXAMEN BREVE 29

LO QUE NECESITA SABER Antes de continuar con la siguiente leccin, asegrese de haber comprendido los siguientes conceptos:
!"La mejor manera de desarrollar y dar mantenimiento a un programa grande es dividirlo en varios mdulos ms pequeos, que son ms fciles de manejar que el programa completo. Los mdulos se escriben en C++ como clases y funciones. !"Conforme sus programas se hacen ms complejos, puede dividirlos en partes ms pequeas llamadas funciones. !"Una funcin se invoca por medio de una llamada de funcin. Dicha llamada menciona la funcin por su nombre y proporciona la informacin (en forma de argumentos) que necesita para realizar su tarea. !"El propsito de la ocultacin de informacin es que las funciones tengan acceso nicamente a la informacin que necesitan para completar su tarea. Esta es una manera de implementar el principio de menor privilegio, uno de los ms importantes para la buena ingeniera de software. !"Las funciones se invocan normalmente en los programas escribiendo su nombre seguido de sus argumentos entre parntesis. !"Todas las funciones definidas por el usuario que se usan en main() se definen despus de cerrar la llave de main(). !"La funcin se define escribiendo un encabezado de funcin, que incluye la clase de regreso, el nombre de la funcin y una lista de parmetros. El cuerpo o seccin de enunciado de la funcin sigue al encabezado de la funcin. !"Cada funcin debe de tener un nombre nico. !"Las funciones pueden regresar un valor al programa llamador y pueden recibir informacin llamadas parmetros. !"Si una funcin regresa un valor, debe definir el tipo del valor regresado (int, char, etc.) antes del nombre de la funcin; en caso contrario tiene que preceder al nombre de la funcin con void. !"Si la funcin recibe parmetros, debe definir un nombre nico para cada parmetro as como su tipo. Si la funcin no recibe parmetros, debe colocar la palabra reservada void dentro de los parntesis que siguen al nombre de la funcin. !"C++ debe saber el tipo de valor que regresa la funcin y el nmero y tipo de parmetros que la funcin recibe. Si la definicin de la funcin se encuentra posteriormente a la utilizacin de la misma, debe de colocar un prototipo de funcin al principio de su programa fuente. !"A diferencia del lenguaje C, el lenguaje C++ necesita que cada funcin tenga un prototipo. Los prototipos de las funciones deben listarse antes que main() e incluir las clases de datos de regreso de la funcin, el nombre de la funcin y una lista de las clases de datos de parmetro. !"Los prototipos se usan por el compilador para verificar el nmero apropiado de argumentos cuando se llama a la funcin. !"Las funciones en C++ se pueden hacer para regresar un valor sencillo para el programa llamador o realizar alguna tarea especfica. !"Cuando se disea una funcin para regresar un valor sencillo al programa llamador, el valor regresado reemplaza el nombre de la funcin en donde se use el nombre en el programa llamador. De esta manera, el nombre de la funcin puede aparecer como parte de un operador de asignacin, un enunciado cout, un operador aritmtico o una verificacin de enunciado.

FUNCIONES - LECCIN - 10

10-42

MIGUEL . TOLEDO MARTNEZ

!"Cuando se disea una funcin para realizar una tarea especfica, se llama a la funcin empleando el nombre de la funcin (seguido por una lista de argumentos reales) como un enunciado en el programa. !"Los argumentos reales son datos que pasan a la funcin cuando se llama a la funcin. Los parmetros formales se definen dentro del encabezado de la funcin y toman el (los) valor (valores) de los argumentos reales cuando se llama a la funcin. !"Los parmetros pueden pasar entre el programa llamador y la funcin por medio de valor o referencia. Cuando pasan parmetros por medio de valor, los argumentos reales en el programa llamador no se afectan por las operaciones sobre los parmetros formales dentro de la funcin. Cuando pasan los parmetros por medio de referencia, los argumentos reales en el programa llamador reflejarn cualquier cambio a los parmetros formales dentro de la funcin. !"De esta manera, el paso de los parmetros por medio de valor es una comunicacin de datos en un sentido desde el programa llamador a la funcin. El paso de los parmetros por referencia es una comunicacin de datos en dos sentidos desde el programa llamador a la funcin y de regreso al programa llamador. !"Los argumentos de una funcin pueden ser constantes, variables y expresiones. !"Las variables locales slo son conocidas dentro de la definicin de una funcin. No se permite que las funciones conozcan los detalles de implementacin de las dems funciones (incluyendo sus variables locales). !"El formato general de una definicin de funcin es: claseValorDevuelto nombreFuncion(listaParametros) { cuerpoFuncion; } La claseValorDevuelto es la clase del valor que se le devuelve al invocador. Si una funcin no devuelve un valor, claseValorDevuelto se declara void. El nombreFuncion es cualquier identificador vlido. La listaParametros es una lista separada por comas que contiene las declaraciones de las variables que se pasarn a la funcin. Si la funcin no recibe valores, listaParametros se declara como void. El cuerpoFuncion es el conjunto de declaraciones e instrucciones que constituyen la funcin. !"El nmero, clase y orden de los argumentos pasados a una funcin debe ser iguales a los parmetros de la definicin de la funcin. !"Cuando un programa llega a una funcin, el control se transfiere desde el punto de invocacin a la funcin llamada, se ejecuta dicha funcin y el control se devuelve al indicador. !"Las funciones llamadas pueden devolverle el control al llamador de cualquiera de tres formas. Si la funcin no devuelve un valor, el control se devuelve al llegar a la llave derecha de terminacin de la funcin, o ejecutando la instruccin: return; Si la funcin devuelve un valor, la instruccin: return expresin; devuelve el valor de expresin. !"Las funciones que no devuelven un valor se declaran con una clase de devolucin void. Cualquier intento por devolver un valor desde la funcin o por emplear el resultado de la invocacin de la funcin en la funcin invocadora genera un error de sintaxis. !"Las listas de parmetros vacas se especifican con parntesis vacos o con void entre ellos. !"Los prototipos de funcin declaran la clase de devolucin de la funcin y el nmero, clase y orden de los parmetros que espera recibir la funcin. !"Los prototipos de funcin le permiten al compilador verificar que las funciones se llamen correctamente. !"El compilador ignora los nombres de variables que se mencionen en el prototipo de funcin.

FUNCIONES - LECCIN - 10

10-43

MIGUEL . TOLEDO MARTNEZ

!"Cada biblioteca estndar tiene un archivo de encabezado correspondiente, el cual contiene los prototipos de funcin de todas sus funciones, as como las definiciones de varias constantes simblicas requeridas por dichas funciones. !"Los programas en C++ no se compilan a menos que se haya indicado un prototipo de funcin para cada funcin o que se defina la funcin antes de utilizarla. !"Los programadores pueden y deben crear e incluir sus propios archivos de encabezado. !"Al pasar un argumento utilizando una llamada por valor, se copia el valor de la variable para pasarla a la funcin llamada. Los cambios a la copia que sucedan en dicha funcin no afectan el valor de la variable original. !"En C++, los parmetros de referencia se definen usando un signo ampersand (&), antes del nombre del parmetro en el encabezado de la funcin. !"C++ ofrece una forma directa de llamada por referencia, empleando parmetros de referencia. Para indicar que el parmetro de una funcin se pasa por referencia, ponga en el prototipo de funcin, despus del tipo de parmetro, un &. En la llamada de la funcin, mencione por nombre a la variable y ser pasada como una llamada por referencia. En la funcin llamada, la mencin de la variable con su nombre local en realidad hace referencia a la variable original del invocador. Por lo tanto, la funcin llamada puede modificar la variable original. !"Tambin se pueden crear parmetros de referencia para utilizarlos localmente como alias de otras variables dentro de una funcin. Las variables de referencia deben inicializarse en sus declaraciones y no se pueden reasignar como alias de otras variables. Una vez declarada una variable de referencia como alias de otra variable, todas las operaciones supuestamente efectuadas sobre el alias en realidad se llevan a cabo en la variable.

PREGUNTAS Y PROBLEMAS
PREGUNTAS 1. 2. 3. Cules son las tres cosas que se deben especificar en el encabezado de una funcin? Explique la diferencia entre un argumento real y un parmetro formal. Llene los siguientes espacios en blanco: a) Los componentes de los programas C++ se llaman ______________ y _____________. b) Las funciones se llaman por medio de _____________________. c) Las variables que slo son conocidas dentro de la funcin en la que se definen se llaman ______________________. d) La instruccin ________________ en una funcin llamada sirve para devolverle el valor de una expresin al invocador. e) f) La palabra clave ___________ sirve en los encabezados de funcin para indicar que la funcin no devuelve un valor que sta no contiene parmetros. El _________________ de un identificador es la parte del programa en la que dicho identificador puede utilizarse.

g) Las tres maneras de devolverle el control al invocador desde una funcin llamada son ____________, _________________ y __________________. h) Un ____________ le permite al compilador revisar el nmero, clase y orden de los argumentos pasados a la funcin. 4. Cules de las siguientes encabezado de funciones no son vlidas? Explique por qu no son vlidas. a. float promedio(num1, num2) b. int masGrande(x, y: int) c. float masPequeno(float a, b) d. string resultado (char carcter) Escribir el encabezado apropiado para las siguientes funciones: a. inverso de x: 1/x 10-44

5.

FUNCIONES - LECCIN - 10

MIGUEL . TOLEDO MARTNEZ

b. c. d. e. f. g. h. i.

6. 7. 8. 9.

j. D los prototipos de funcin de la pregunta 4. Verdadero o falso: Cuando una funcin no tiene una clase de datos de regreso, deber indicar esto con la palabra reservada null. Explique la diferencia entre un parmetro de valor y un parmetro de referencia. Cuando pasa un parmetro por referencia a una funcin. a. b. c. d. e. f. El argumento real toma el valor del parmetro formal. El parmetro formal toma el valor del argumento real. El argumento real refleja cualquier cambio al parmetro formal despus de la ejecucin de la funcin. ayb byc ayc

tan(x) Convierta un valor entero a una letra de calificacin. Convierta grados Fahrenheit a grados Celsius. Calcule el factorial de cualquier entero N (N!). Calcule el promedio de tres enteros. La funcin hipotenusa, que toma dos argumentos de punto flotante de doble precisin, lado1 y lado2, y devuelve un resultado de punto flotante de doble precisin. La funcin masPequea(), que toma tres enteros, x, y y z, y devuelve un entero. La funcin instrucciones(), que no recibe ningn argumento y no devuelve ningn valor. (Nota: tales funciones sirven por lo general para desplegarle instrucciones al usuario). La funcin flotante(), que toma un argumento entero, numero, y devuelve un resultado de punto flotante.

10. Cundo usa un operador de asignacin para llamar a una funcin, la funcin debe incluir un enunciado ________________. 11. Cules de los siguientes prototipo de funciones no son vlidas? Explique por qu no son vlidas. a. b. c. d. e. void imprimeEncabezado(); int error(float num1, char num2); void obtenDato(&int cantidad, char fecha); float promedio(int numero, float total); char muestra(int, char, float);

12. Verdadero o falso: Un objeto variable definido en main() es visible en todas las funciones llamadas por main(). 13. Cules de los siguientes son parmetros de valores y cules son parmetros de referencia? a. char probA(char &A, char &B, float X, int Y); b. int probB(int num1, int num2, int num3, float &prom); c. float probC(int, float, char &); 14. Escriba el encabezado apropiado para las siguientes funciones: a. Una llamada de funcin muestra() que deber regresar un valor de punto flotante y recibir un entero, un valor de punto flotante y un carcter (en ese orden) cuando se llama. b. Una llamada a la funcin saltar() que har que la impresora salte un determinado nmero de lneas, donde el nmero de lneas para saltar se obtiene desde el programa llamador. c. Una llamada a la funcin intercambiar() que intercambiar los valores de dos variables enteras obtenidas desde el programa llamador y regresar los valores intercambiados al programa llamador. d. Una llamada de funcin hipot() que regresar la hipotenusa de un tringulo rectngulo, dados los valores de los catetos desde el programa llamador. 15. Escriba prototipos para las funciones en la pregunta 12. 16. Escriba enunciados C++ que llamarn las cuatro funciones de la pregunta 12. 17. Dada la siguiente funcin: void intercambia(int &x, int &y) { int temp; temp = x; x = y;
FUNCIONES - LECCIN - 10

10-45

MIGUEL . TOLEDO MARTNEZ

y = temp; } // Fin de intercambia() Determine la salida para cada uno de los siguientes segmentos de cdigo que llama a la funcin intercambia(). a. A = 2; B = 10; cout << A = << A << B = << B << endl; intercambia(A,B); cout << A = << A << B = << B << endl; A = 20; B = -5; cout << A = << A << B = << B << endl; if (A < B) intercambia(A,B); else intercambia(B,A); cout << A = << A << B = << B << endl; num1 = 1; num2 = 5; for(int cuenta = 5; cuenta; -- cuenta) { intercambia(num1, num2); cout << Num1 = << num1 << Num2 = << num2 << endl; ++ num1; --num2; } // Fin del for

b.

c.

18. Encuentre los errores en los siguientes segmentos de programa y explique cmo pueden corregirse. a) int g(void) { cout << Dentro de la funcin g << endl; int h(void) { cout << Dentro de la funcin h << endl; }//Fin de h() }//Fin de g() b) int sum( int x, int y) { int resultado; resultado = x + y; } c) int sum( int n ) { if ( n == 0 ) return 0 else n + sum ( n 1 ): } d) void f( float a ); { float a;

FUNCIONES - LECCIN - 10

10-46

MIGUEL . TOLEDO MARTNEZ

cout << a << endl; } e) void producto ( void ) { int a, b, c, resultado; cout << Introduzca tres enteros: ; cin >> a >> b >> c; resultado = a * b * c; cout << El resultado es << resultado; return resultado; }

float cubo( float ); /* prototipo de funcin */ .......... cubo( float numero ) /* definicin de la funcin */ { return numero * numero * numero; } g) float y = 123.45678; int x; f) x = y; cout << static_cast<float> (x) << endl; h) double cuadrado(double numero) { double numero; return numero * numero; } i) void producto ( void ) }

19. Por qu un prototipo de funcin contendra una declaracin de tipo de parmetro como float &? 20. (Verdadero/falso) Todas las llamadas de C++ se realizan mediante llamadas por valor.

PROBLEMAS Escriba las funciones para realizar las siguientes tareas: 1. 2. 3. 4. 5. 6. 7. 8. Convierta una temperatura en grados Fahrenheit a grados Celsius. Busque xy, donde x es un valor real e y un valor entero. Calcule la tan(), para un ngulo en grados. Busque el inverso (1/x) de cualquier valor real x. Busque el mximo de dos valores enteros. Busque el mnimo de dos valores enteros. Calcule n! usando iteracin.

Examine un rango de valores y regrese el valor booleano verdadero si un valor est dentro del rango y falso si est fuera del rango. 9. Encuentre el balance bancario al final de un mes determinado para un valor inicial de depsito y tasa de inters. Defina el nmero de meses, depsito y tasa de inters variables en main() y pselos a su funcin. 10. Muestre su nombre, clase, instructor y hora. Nota: Para mostrar su nombre e instructor la funcin deber aceptar un arreglo de caracteres. Para hacer que la funcin acepte un arreglo, simplemente proporcione una

FUNCIONES - LECCIN - 10

10-47

MIGUEL . TOLEDO MARTNEZ

definicin de arreglo en el encabezado de la funcin. Por ejemplo, suponga que define un arreglo en main() para contener su nombre, como sigue: char nombre[MAX]; Para recibir este arreglo desde main(), simplemente repita la definicin de arreglo en su encabezado de funcin, como sigue: muestra(char nombre[MAX], ...) 11. Qu hace que la impresora salte un determinado nmero de lneas, en donde el nmero de lneas que se va a saltar pasa a la funcin? 12. Intercambie dos valores de punto flotante cualesquiera. 13. Un estacionamiento pblico cobra una tarifa mnima de $2.00 por estacionarse hasta tres horas; luego cobra $0.50 adicionales por hora o fraccin a partir de las tres horas. La tarifa mxima por periodo de 24 horas es de $10.00. Suponga que ningn automvil se estaciona por ms de 24 horas a la vez. Escriba un programa que calcule e imprima las cuentas por estacionamiento de tres clientes que dejaron all sus autos ayer. Usted introduce las horas de estacionamiento de cada cliente. Su programa imprimir los resultados en forma tabular y con orden, y calcular e imprimir el total de los recibos de ayer. Tambin determinar el cargo por cliente utilizando la funcin calculaCargo(). Sus salidas debern aparecer en el siguiente formato: 14. 15. 16. 17. 18. Carro 1 2 3 TOTAL Horas 1.5 4.0 24.0 29.5 Cargo 2.00 2.50 10.00 14.50

14. Compare algn nuevo valor de punto flotante a un valor mximo obtenido desde el programa llamador. Reemplace el valor mximo con el nuevo valor si el nuevo valor es ms grande que el valor mximo. Use la funcin que desarroll en el problema 12 para la operacin de intercambio. En los problemas 15 al 17, escriba tres funciones independientes para cada problema, como sigue: Una funcin para leer los valores de entrada necesarios. Una segunda funcin para realizar los clculos necesarios usando los valores de entrada desde la primera funcin. Una tercera funcin para mostrar los resultados de la segunda funcin.

15. Revise el programa de nmina que desarroll para ACME, S.A. DE C.V. en el problema 12 de la leccin 6 para emplear funciones. Recuerde que el programa de nmina calcular el pago neto de Jos dada la siguiente informacin: Nombre del empleado Nmero de horas trabajadas a la semana Salario por hora ISR (7.15%) Retencin federal (16%) Retencin estatal (4.75%) Suponga que ACME, S.A. DE C.V. solamente requieren escribir los primeros tres artculos cuando se ejecuta el programa. Genere un informe usando el siguiente formato: Nombre del empleado: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX Salario por hora: Nmero de horas trabajadas a la semana: Pago bruto:
FUNCIONES - LECCIN - 10

$XXX.XX XX.XX $XXXX.XX 10-48

MIGUEL . TOLEDO MARTNEZ

Deducciones: ISR: Retencin federal: Retencin estatal: Total de deducciones: Pago neto:

$XXX.XX XXX.XX XXX.XX -------------$XXX.XX $XXXX.XX

Nota: Para obtener el nombre del empleado, la funcin deber aceptar y regresar un arreglo de caracteres. Para hacer que la funcin acepte y regrese un arreglo, simplemente proporcione una definicin de arreglo en el encabezado de la funcin. Por ejemplo, suponga que define un arreglo en main() para obtener su nombre, como sigue:

char nombre[MAX]; Para aceptar este arreglo desde main() y regresarlo a main(), simplemente repita la definicin del arreglo en el encabezado de la funcin, como sta: muestra(char nombre[MAX], ...) 16. Encuentre la altura a la cual la escalera en la figura 10.10 hace contacto con el muro, dada la longitud de la escalera y la distancia de la base de la escalera al muro.

Altura de la escalera

Longitud de la escalera

Distancia al muro Figura 10.10. Una escalera para el problema 17 17. Una secuencia de nmeros Fibonacci se define como sigue: F0 = 0 F1 = 1 ......... Fn = Fn-1 + Fn-2 para n 2 Esto quiere decir que los primeros dos nmeros en la secuencia son 0 y 1. Entonces, cada nmero Fibonacci adicional es la suma de los dos nmeros anteriores en la secuencia. De esta manera, los primeros 10 nmeros Fibonacci son:

FUNCIONES - LECCIN - 10

10-49

MIGUEL . TOLEDO MARTNEZ

0, 1, 1, 2, 3, 5, 8, 13, 21, 34 Aqu, decimos que el primer nmero ocupa la posicin 0 en la secuencia, el segundo nmero la posicin 1 en la secuencia, y as sucesivamente. As, la ltima posicin en una secuencia de 10 nmeros es la posicin 9. Desarrolle un programa que emplee una funcin iterativa para generar una secuencia Fibonacci de todos los nmeros hasta alguna posicin n escrita por el usuario. 18. Escriba una funcin potenciaEntera(base, exponente) que devuelva el valor de: baseexponente Por ejemplo, potenciaEntera(3, 4) = 3 * 3 * 3 * 3. Suponga que exponente es un entero positivo diferente de cero y que base es un entero. La funcin potenciaEntera() debera utilizar for o while para controlar el clculo. No utilice funciones de la biblioteca matemtica. 19. Defina una funcin hipotenusa que calcule la longitud de la hipotenusa de un tringulo rectngulo cuando se dan los otros dos lados. Emplee esta funcin en un programa para determinar la longitud de la hipotenusa de los siguientes tringulos. La funcin deber tomar dos argumentos del tipo double y devolver la hipotenusa como double. Tringulo 1 2 3 Lado 1 3.0 5.0 8.0 Lado2 4.0 12.0 15.0

20. Escriba una funcin mltiplo() que tome dos enteros y determine si el segundo es un mltiplo del primero. La funcin deber tomar dos argumentos enteros y devolver verdadero si el segundo es un mltiplo del primero y falso si no. Utilice esta funcin en un programa que acepte como entrada una serie de pares de enteros. 21. Escriba un programa que acepte como entrada una serie de enteros y los pase, uno a la vez, a la funcin par(), que se vale del operador de mdulo para determinar si un entero es par. La funcin deber tomar un argumento entero y devolver verdadero si es par y falso si es non. 22. Escriba una funcin que presente en el margen izquierdo de la pantalla un cuadrado de asteriscos cuyo lado est especificado en el parmetro entero lado. Por ejemplo, si lado es 4, la funcin presentar: **** **** **** **** 23. Modifique la funcin del problema 22 para formar el cuadrado con el carcter contenido en el parmetro de carcter llenaCaracter. Por lo tanto, si lado es 5 y llenaCaracter es #, entonces la funcin imprimir: #### #### #### #### 24. Utilice tcnicas parecidas a las desarrolladas en los problemas 22 y 23 para generar un programa que trace una amplia gama de formas. 25. Escriba segmentos de programa que realicen lo siguiente: a. Calcule la parte entera del cociente cuando el entero a se divida entre el entero b. b. c. Calcule el residuo entero cuando el entero a se divida entre el entero b. Utilice las partes de programa desarrolladas en a) y b) para escribir una funcin que acepte un entero entre 1 y 32767 y lo imprima como una serie de dgitos, separando cada uno con dos espacios. Por ejemplo, el entero 4563 deber imprimirse como:

FUNCIONES - LECCIN - 10

10-50

MIGUEL . TOLEDO MARTNEZ

4 5 6 2 26. Escriba una funcin que tome el tiempo como tres argumentos enteros (horas, minutos y segundos) y devuelva el nmero de segundos transcurridos desde que el reloj dio las 12. Con esta funcin, calcule el tiempo en segundos entre dos horas, ambas comprendidas dentro de un ciclo de 12 horas del reloj. 27. Implemente las siguientes funciones enteras: a. La funcin celsius() devuelve el equivalente en grados centgrados de una temperatura eh Fahrenheit. b. c. La funcin fahrenheit() devuelve el equivalente en grados Fahrenheit de una temperatura en grados centgrados. Con estas funciones, escriba un programa para imprimir grficos que muestren el equivalente en grados centgrados de todas las temperaturas Fahrenheit entre 32 y 212 grados. Imprima las salidas de forma tabular, para minimizar la cantidad de lneas de salida y simplificar la lectura.

28. Escriba una funcin que devuelva el menor de tres nmeros de punto flotante. 29. Se dice que un nmero entero es un nmero perfecto si la suma de sus factores, incluyendo el 1 (pero no el nmero mismo), da tal nmero. Por ejemplo, el 6 es un nmero perfecto porque 6 = 1 + 2 + 3. Escriba una funcin perfecto() que determine si el parmetro numero es un nmero perfecto. Utilice esta funcin en un programa que determine e imprima todos los nmeros perfectos entre 1 y 1000. Imprima los divisores de todos los nmeros perfectos, para confirmar que, de hecho, se trata de un nmero perfecto. Pruebe el poder de su computadora probando con nmeros mucho mayores que 1000. 30. Se dice que un nmero es primo si slo se puede dividir entre 1 y entre s mismo. Por ejemplo, 2, 3, 5 y 7 son primos, pero 4, 6, 8 y 9 no. a. Escriba una funcin que determine si un nmero es primo. b. Con esta funcin, haga un programa que determine e imprima todos los nmeros primos entre 1 y 10,000. Cuntos de estos 10,000 nmeros debe probar en realidad antes de tener la seguridad de haber encontrado todos los primos? Inicialmente podra pensar que n/2 es el lmite superior que debera probar para ver si se trata de un nmero primo, pero slo necesita llegas hasta la raz cuadrada de n. Por qu? Rescriba el programa y ejectelo de ambas manera. Estime la mejora de desempeo.

c.

31. Escriba una funcin que tome un valor entero y devuelva el nmero con sus dgitos en reversa. Por ejemplo, dado el nmero 7631, la funcin deber devolver 1367. 32. El mximo comn divisor de dos enteros es el mayor entero que divide ambos nmeros. Escriba una funcin mcd() que devuelva el mximo comn divisor de dos enteros. 33. Escriba una funcin puntosCalidad() que acepte el promedio de un estudiante y devuelva 4 si su promedio est entre 90 y 100, 3 si est entre 80 y 89, 2 si est entre 70 y 79, 1 si est entre 60 y 69 y 0 si es menor que 60. 34. Escriba una funcin distancia() que calcule la distancia entre dos puntos (x1, y1) y (x2, y2). Todos los nmeros y valores devueltos deben ser de clase float.

FUNCIONES - LECCIN - 10

10-51

MIGUEL . TOLEDO MARTNEZ

EXAMEN BREVE 27
1. Cul es el papel de una funcin en un programa C++? 2. Las tres secciones principales de una funcin son las secciones________________, ________________ y ________________________. 3. Cul es el propsito del encabezado de la funcin en un programa C++? 4. Liste las tres partes del encabezado de una funcin. 5. A una variable de funcin que espera recibir un valor del programa llamador, se conoce como ___________________________. 6. Cul es el propsito de un enunciado return en una funcin? 7. Explique la diferencia entre un argumento real en un programa llamador y un parmetro formal en el encabezado de una funcin.

EXAMEN BREVE 28
1. Qu deber usar como clase de datos de regreso cuando una funcin no regresa un solo valor al programa llamador? 2. Cules son las dos cosas que deben considerarse cuando se desarrolle un encabezado de funcin? 3. La comunicacin de datos en un sentido desde el programa llamador a la funcin se proporciona por medio de los parmetros de ______________________________. 4. La comunicacin de datos de ida y vuelta entre el programa llamador y una funcin se proporciona por medio de los parmetros de ______________________________. 5. Para especificar un parmetro de referencia en un encabezado de funcin, debe usarse el smbolo _____________ antes del identificador del parmetro. 6. Dnde se localiza el cuerpo de una funcin en un programa C++?

EXAMEN BREVE 29
1. Cul es el propsito principal de una funcin prototipo? 2. Dnde se localiza normalmente una funcin prototipo en un programa C++? Verdadero o falso: Los parmetros listados en un prototipo de funcin se pueden integrar en la relacin solamente por las clases de datos, sin ningn identificador correspondiente.

RESPUESTA EXAMEN BREVE 27


1. El papel de una funcin en un programa C++ es eliminar la necesidad de duplicar los enunciados. El uso de las funciones permite resolver problemas grandes y complicados dividiendo el problema en subproblemas ms pequeos, que se manejan con ms facilidad (mtodo descendente) 2. Las tres secciones principales de una funcin son las secciones encabezado de la funcin, variables o constantes locales y enunciado. 3. En C++, el encabezado de la funcin en un programa es la interfaz de datos para la funcin. Este forma una frontera comn entre la funcin y el programa llamador. 4. Las tres partes del encabezado de una funcin son las siguientes:
FUNCIONES - LECCIN - 10

10-52

MIGUEL . TOLEDO MARTNEZ

La clase de datos del valor que regresar la funcin, si hay alguno. El nombre de la funcin. Una lista de parmetros.

5. A una variable de funcin que espera recibir un valor del programa llamador, se conoce con el nombre de parmetro. 6. El enunciado return en una funcin se usa cuando se va a regresar un solo valor al programa llamador. 7. La diferencia entre un argumento real en un programa llamador y un parmetro formal en un encabezado de funcin es que el argumento real contiene el valor que pasa al parmetro formal en el encabezado de la funcin. En otras palabras, el parmetro formal recibe el valor del argumento real en el programa llamador.

RESPUESTA EXAMEN BREVE 28


1. void se debe usar como la clase de datos de regreso cuando una funcin no regresa un valor al programa llamador. 2. Las dos cosas que se deben considerar cuando se desarrolla el encabezado de la funcin son las siguientes:
Qu aceptar la funcin para realizar su tarea. Qu regresar la funcin.

3. La comunicacin de datos en un sentido desde el programa llamador a la funcin se proporciona por medio de los parmetros de valor. 4. La comunicacin de datos de ida y vuelta entre el programa llamador y una funcin se proporciona por medio de los parmetros de referencia. 5. Para especificar un parmetro de referencia en un encabezado de funcin, debe usarse el smbolo ampersand (&) antes del identificador del parmetro. 6. El cuerpo de una funcin normalmente se localiza despus de cerrar la llave de la funcin main()

RESPUESTA EXAMEN BREVE 29


1. El propsito principal de un prototipo de funcin es permitir que el compilador verifique la correspondencia entre los argumentos reales en una llamada de funcin y los parmetros formales que la funcin espera recibir. 2. Un prototipo de funcin normalmente se localiza despus de las instrucciones del preprocesador y antes de la funcin main() en un programa de C++. Verdadero: Los parmetros que se listan en un prototipo de funcin se pueden integrar en la relacin solamente por las clases de datos, sin ningn identificador correspondiente.

FUNCIONES - LECCIN - 10

10-53

MIGUEL . TOLEDO MARTNEZ

CONTENIDO DE LA LECCIN 16
USO DE REFERENCIAS EN C++
1. Introduccin 2. Parmetros de referencia como alias
2.1. Ejemplo 16.1

2 2
3

3. Variables de referencia como alias


3.1. Ejemplos 16.2, 16.3, 16.4, 16.5

4
4

4. Utilice comentarios en sus programas para explicar las referencias 5. Reglas para trabajar con referencias 6. Lo que necesita saber

6 6 7

FUNCIONES LECCIN 16

16-1

MIGUEL . TOLEDO MARTNEZ

LECCIN 16
USO DE REFERENCIAS EN C++
INTRODUCCIN Dos maneras de invocar funciones en muchos lenguajes de programacin son mediante llamada por valor y llamada por referencia. Cuando se pasa un argumento utilizando una llamada por valor, se hace una copia del argumento, la cual se pasa a la funcin llamada. Los cambios a la copia no afectan el valor de la variable original en el invocador. Con esto se evitan los efectos secundarios que tanto minan el desarrollo de sistemas de software correctos y confiables. En esta leccin presentaremos los parmetros de referencia, que son el primero de dos medios que tiene C++ para efectuar una llamada por referencia. Con una llamada por referencia, el invocador le da a la funcin llamada la capacidad de acceder directamente a la informacin del usuario y de modificarla si as lo desea. Mostraremos cmo lograr la ventaje de desempeo de una llamada por referencia mientras, de manera simultnea, se logra la ventaja de ingeniera de software de proteger contra la corrupcin a la informacin del invocador. Un parmetro de referencia es un alias de su argumento correspondiente.
Objetivos de esta leccin: Declarar e inicializar una variable de referencia dentro de su programa. Usar variables de referencia para cambiar el valor de un parmetro dentro de una funcin.

PARMETROS DE REFERENCIA COMO ALIAS Un parmetro de referencia es un alias de su argumento correspondiente. Para indicar que el parmetro de una funcin se pasa por referencia, simplemente ponga un ampersand (&) despus de la clase de datos del parmetro en el prototipo de la funcin; utilice la misma convencin al listar la clase de datos del parmetro en el encabezado de la funcin. Por ejemplo, la declaracin
int &contador

en un encabezado de funcin se leera como contador es una referencia a un int. En la llamada de funcin, basta con mencionar por nombre a la variable y sta se pasar por referencia. Despus, mencionar a la variable por su nombre de parmetro en el cuerpo de la funcin llamada, de hecho har referencia a la variable original del invocador, la cual podr ser modificada directamente en la funcin llamada. Como siempre el prototipo de la funcin debe coincidir con su encabezado.

FUNCIONES LECCIN 16

16-2

MIGUEL . TOLEDO MARTNEZ

Ejemplo 16.1
El siguiente programa, REFERENCIA.CPP, compara una llamada por valor y una llamada por referencia con parmetros de referencia. Los estilos de los argumentos de las llamadas a cuadradoPorValor() y cuadradoPorReferencia(), son idnticos, es decir, ambas variables se mencionan simplemente por su nombre. Sin revisar los prototipos de las funciones ni las definiciones de las funciones, es imposible saber, a partir de las llamadas mismas, si las funciones pueden modificar sus argumentos. No obstante, debido a que los prototipos de funcin son obligatorios, el compilador no tiene ningn problema para resolver esta ambigedad. /* El siguiente programa: REFERENCIA.CPP, hace una comparacin entre llamada por valor y llamada por referencia con referencia. */ #include <iostream.h> //Para cout y cin

int cuadradoPorValor(int); void cuadradoPorReferencia(int &); void main(void) { int x = 2, z = 4; cout << "x = " << x << " antes de cuadradoPorValor()" << endl; cout << "Valor devuelto por cuadradoPorValor(): " << cuadradoPorValor(x) << endl; cout << "x = " << x << " despus de cuadradoPorValor()" << endl << endl; cout << "z = " << z << " antes de cuadradoPorReferencia()" << endl; cuadradoPorReferencia(z); cout << "z = " << z << " despus de cuadradoPorReferencia()" << endl; }//Fin de main() int cuadradoPorValor(int a) { return a * a; }//Fin de cuadradoPorValor() void cuadradoPorReferencia(int &cRef) { cRef *= cRef; }//Fin de cuadradoPorValor()

//El argumento del invocador no se modifica

//El argumento del invocador se modifica

En otra leccin estudiaremos los apuntadores; veremos que los apuntadores permiten una forma alterna de realizar una llamada por referencia donde el estilo de la llamada indica con claridad que se trata de una llamada por referencia (as como el potencial de modificar los argumentos del invocador) Para especificar una referencia a una constante, ponga el calificador const antes de la especificacin de clase de dato en la declaracin del parmetro. Observe la colocacin de & en la lista de parmetros de la funcin cuadradoPorReferencia. Algunos programadores de C++ prefieren escribir int& cRef, en lugar de int &cRef.

FUNCIONES LECCIN 16

16-3

MIGUEL . TOLEDO MARTNEZ

VARIABLES DE REFERENCIA COMO ALIAS Las referencias tambin pueden servir como alias de otras variables de la funcin. Por ejemplo, el cdigo:
int contador = 1; int &cRef = contador; ++cRef; //Declara la variable entera contador //Crea cRef como alias de contador //Incrementa contador (utilizando su alias)

Incrementa la variable contador por medio de su alias cRef. Las variables de referencia deben inicializarse en sus declaraciones y no pueden reasignarse como alias a otras variables. Una vez que una referencia se declara como alias de otra variable, todas las operaciones efectuadas sobre dicho alias (es decir, la referencia) de hecho se realizan en la propia variable original. El alias simplemente es otro nombre de la variable. Si se toma la direccin de una referencia y se comparan las referencias, no sucede un error de sintaxis; en cambio, todas las operaciones suceden en la variable para la que la referencia es un alias. Las funciones pueden devolver referencias, pero esto puede ser peligroso. Al devolverle una referencia a una variable declarada en la funcin llamada, la variable debe estar declarada como static dentro de dicha funcin. De otra forma, la referencia es hacia una variable automtica que se descarta al terminar la funcin; se dice que tal variable esta indefinida y el comportamiento del programa ser impredecible (algunos compiladores emiten avisos cuando esto sucede) Las referencia a variables indefinidas se llaman referencias colgantes.
Ejemplo 16.2
El siguiente programa REFINI1.CPP, ilustra el hecho de que toda variable referenciada debe de ser inicializada. /* El siguiente programa: REFINI1.CPP, ilustra el hecho de que toda variable referenciada debe de ser inicializada. */ #include <iostream.h> void main(void) { int x = 3; int &y = x; //Ahora ya es un alias de x //Para cout y cin

cout << "x = " << x << endl << "y = " << y << endl << endl; y = 7; cout << "x = " << x << endl << "y = " << y << endl << endl; }//Fin de main()

FUNCIONES LECCIN 16

16-4

MIGUEL . TOLEDO MARTNEZ

Ejemplo 16.3
El siguiente programa REFINI2.CPP, ilustra el hecho de no inicializar una variable de referencia. /* El siguiente programa: REFINI2.CPP, ilustra el hecho de no inicializar una variable por referencia. */ #include <iostream.h> void main(void) { int x = 3; int &y; //Ahora ya es un alias de x //Para cout y cin

cout << "x = " << x << endl << "y = " << y << endl << endl; y = 7; cout << "x = " << x << endl << "y = " << y << endl << endl; }//Fin de main()

El compilador enviar el siguiente mensaje de error:


Reference variable y must be initialized

Ejemplo 16.4
El siguiente programa: REFVAR.CPP, despliega y altera los valores de una variable usando la variable misma o su referencia. /* El siguiente programa: REFVAR.CPP, ilustra el uso de variables de referencia */ #include <iostream.h> void main(void) { int x = 10; int &rx = x; // despliega x usando x y rx cout << "x contiene " << x << endl; cout << "x contiene (usando la referencia rx) " << rx << endl; // altera x y despliega su valor usando rx x *= 2; cout << "x contiene (usando la referencia rx) " << rx << endl; // altera rx y despliega el valor usando x rx *= 2; cout << "x contiene " << x << endl; }//Fin de main() //Para cout y cin

FUNCIONES LECCIN 16

16-5

MIGUEL . TOLEDO MARTNEZ

Ejemplo 16.5
El siguiente programa, INTCREF.CPP, utiliza referencias a dos datos de punto flotante para intercambiar sus valores. /* El siguiente programa: INTCREF.CPP, intercambia el valor entre dos variables utilizando variables de referencia. */ #include <iostream.h> //Para cout y cin

void intercambiaValores(float &a, float &b) { float temp; temp = a; a = b; b = temp; }//Fin de intercambiaValores() void main(void) { float grande float pequeno = 10000.0; = 0.00001;

intercambiaValores(grande, pequeno); cout << "Grande contiene: " << grande << endl; cout << "Pequeo contiene: " << pequeno << endl; }//Fin de main()

Como puede observar, la funcin intercambiaValores, se vuelve ms fcil de comprender.


UTILICE COMENTARIOS EN SUS PROGRAMAS PARA EXPLICAR LAS REFERENCIAS

Como las referencias dentro de una funcin no utilizan asterisco, puede pensarse que el valor de los parmetros no cambian, razn por la cual se hace necesario escribir comentarios antes y dentro de las funciones que cambian parmetros utilizando referencias. REGLAS PARA TRABAJAR CON REFERENCIAS Una referencia no es una variable. Una vez que asigna un valor a la referencia, la referencia no puede cambiar. Adems, a diferencia de los apuntadores, no puede realizar las operaciones siguientes en las referencias:
No puede obtener la direccin de la referencia utilizando el operador de direccin de C++. No puede asignarle un apuntador a una referencia. No puede comparar valores de referencias utilizando los operadores relacionales de C++. No puede realizar operaciones aritmticas con una referencia, tal como agregarle un desplazamiento. No puede cambiar una referencia.

FUNCIONES LECCIN 16

16-6

MIGUEL . TOLEDO MARTNEZ

LO QUE NECESITA SABER Antes de continuar con la siguiente leccin, asegrese de haber comprendido los siguientes conceptos:
!"C++ ofrece una forma directa de llamada por referencia, empleando parmetros de referencia. Para indicar que el parmetro de una funcin se pasa por referencia, ponga en el prototipo de funcin, despus del tipo del parmetro, un &. En la llamada de la funcin, mencione por nombre a la variable y ser pasada como una llamada por referencia. En la funcin llamada, la mencin de la variable con su nombre local en realidad hace referencia a la variable original del invocador. Por lo tanto, la funcin llamada puede modificar la variable original. !"Tambin se pueden crear parmetros de referencia para utilizarlos localmente como alias de otras variables dentro de una funcin. Las variables de referencia deben inicializarse en sus declaraciones y no se pueden reasignar como alias de otras variables. Una vez declarada una variable de referencia como alias de otra variable, todas las operaciones supuestamente efectuadas sobre el alias en realidad se llevan a cabo en la variable. !"Una referencia en C++ es un alias (o segundo nombre) al nombre de una variable. !"Para declarar una referencia, coloque el carcter ampersand (&) inmediatamente despus del tipo de variable y luego especifique el nombre de la referencia seguido por un signo igual y el nombre de la variable a la que la referencia le dar un alias. !"Una vez que asigna un valor a la referencia, no puede cambiar el valor de la misma. !"Debe de incluir comentarios antes y dentro de las funciones que utilizan referencias para cambiar el valor de un parmetro. De esta manera se asegura que otro programador que lea su programa pueda reconocer los cambios que est realizando. !"Un sobreuso de referencias puede conducir a programas poco legibles.

FUNCIONES LECCIN 16

16-7

Anda mungkin juga menyukai