• No se han encontrado resultados

CONTENIDO DE LA LECCIÓN 10

N/A
N/A
Protected

Academic year: 2021

Share "CONTENIDO DE LA LECCIÓN 10"

Copied!
53
0
0

Texto completo

(1)

CONTENIDO DE LA LECCIÓN 10

CONOCIMIENTOS BÁSICOS SOBRE FUNCIONES

1. Introducción 2

2. Funciones que regresan un solo valor: funciones sin void 3 2.1. Formato de funciones definidas por el usuario 4

2.2. Encabezado de la función 4

2.3. La clase de datos return 5

2.4. El nombre de la función 5

2.5. Lista de parámetros 6

2.6. Ejemplo 10.1 7

2.7. Sección de enunciado 7

2.8. Ejemplos 10.2, 10.3 8 2.9. Llamada a las funciones sin void 9

2.10. Argumentos reales en comparación con parámetros formales 10 2.11. Retorno de un resultado al programa que invoca a la función 11 2.12. Ejemplo 10.4 11

2.13. Examen breve 27 52

3. Funciones void 12

3.1. Parámetros de valor en comparación con parámetros de referencia 13

3.2. Parámetros de valor 13

3.3. Ejemplos 10.5, 10.6, 10.7, 10.8, 10.9 14

3.4. Parámetros de referencia 17

3.5. Ejemplos 10.10, 10.11 19

4. Localizaciones de las funciones dentro de su programa 20

5. Examen breve 28 52

6. Prototipo de funciones 22

6.1. Ejemplos 10.12, 10.13 23

7. Solución de problemas en acción: Programación estructurada, ley de Ohm 25

7.1. Problema 25

7.2. Definición del problema 25

7.3. Planeación de la solución 26

7.4. Codificación del programa 28

8. Solución de problemas en acción: Estado de cuenta de una cuenta de ahorros 36

8.1. Problema 36

8.2. Definición del problema 36

8.3. Planeación de la solución 36

8.4. Codificación del programa 40

9. Examen breve 29 52

10. Lo que necesita saber 42

11. Preguntas y problemas 44

11.1. Preguntas 44 11.2. Problemas 47

(2)

LECCIÓN 10

CONOCIMIENTOS BÁSICOS SOBRE FUNCIONES

INTRODUCCIÓN

Cuando los programas se vuelven más complejos, los programadores descomponen el programa en pequeños subprogramas llamados funciones. Cada función debe realizar una tarea específica. Cuando el programa requiere de la tarea, llama a la función, proporcionándole toda la información que requiera para llevar a cabo la tarea.

Objetivos de esta lección:

•••• Aprender a construir programas de manera modular, a partir de piezas pequeñas llamadas

funciones.

•••• Crear funciones nuevas.

•••• Entender los mecanismos para pasar información entre funciones.

•••• Comprender las clases de retorno de una función.

•••• Crear prototipos de funciones.

En lecciones anteriores se ha presentado el diseño estructurado usando el refinamiento

sucesivo (paso a paso) y las funciones estándar de C++. También se han desarrollado diseños descendentes de programas estructurados, pero se ha empleado una programación lineal

cuando se codifican estos diseños. Como resultado, hemos estado codificando programas C++

que consisten en una sección principal definida por la función main() Es tiempo de aprender cómo

codificar diseños estructurados usando un programa C++ estructurado que emplea

funciones. Como se sabe, las funciones son la base de la programación estructurada en el lenguaje

C++. Además, las funciones proporcionan el único método de comunicación con objetos en programación orientada a objetos. Por lo tanto, esta lección es importante para

aprender la programación estructurada y la orientada a objetos en el lenguaje C++.

Ya se han utilizado funciones estándar 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 programación 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 función definida por el usuario es un bloque de enunciados o un subprograma, que se escribe para realizar una tarea específica 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) {

declaraciónVariables;

enunciados;

}

(3)

A una función 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 función 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 más de una vez, los enunciados, se escriben sólo una vez para la función. Entonces se llama a la función cada vez que se desee realizar la tarea. Además, el uso de las funciones mejora la claridad y la legibilidad de la lista del programa. Y lo que es más importante, el uso de las funciones dentro de un lenguaje estructurado, como C++, permite solucionar problemas complejos y muy largos usando un enfoque de diseño de programación de

arriba-abajo, así como la construcción de clases y objetos en programación orientada a objetos. En C++ es posible hacer que una función sirva para dos propósitos. Puede hacerse una

función para que regrese un solo valor al programa llamador. En C++, este tipo de función se conoce como sin void. También es posible escribir funciones que realicen tareas específicas 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 estándar que se utilizaron antes como sqrt(),

sin() y cos(), por

mencionar algunas. Vimos que C++ incluye funciones para el manejo de cadenas y funciones matemáticas, así como funciones para el manejo de E/S. Sin embargo, suponga que quiere realizar alguna operación que no es una función predefinida en C++, por ejemplo elevar al

cubo. Debido a que C++ no incluye ninguna función estándar para tal operación, es posible

codificar en el programa la operación con un enunciado como el siguiente:

cubo = x * x * x

Después, insertar este enunciado dentro del programa cada vez que se quiera elevar al cubo el valor de x. Sin embargo, ¿no sería más 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 cómo ejecutar

sqrt(x)? Puede hacer esto definiendo su propia función cubo(x). A esta función se le conoce con

el nombre de función definida por el usuario, por razones obvias.

Una

función 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 función en cualquier parte que se utilice el nombre en el programa llamador. De esta manera, si cubo(x) es una función

definida por el usuario que calculará un valor, por decir, x, el enunciado cout << cubo(x);

invocará la función y hará que se muestre el cubo de x. Ahora será necesario aprender a crear funciones definidas por el usuario.

(4)

FORMATO DE FUNCIONES DEFINIDAS POR EL USUARIO

// Encabezado de la función

<claseRetorno> <nombreFunción> (<listaParámetros>) {// Empieza el bloque de enunciados de la función

// Variables y constantes locales

<los objetos variables y las constantes locales deberán ir aquí>

// Enunciados de la función o cuerpo enunciado #1;

enunciado #2;

...

enunciado #n;

return <valor de regreso>;

} // Final del bloque de enunciados de la función

El

formato de la definición de una función consiste en tres secciones principales: una línea de encabezado de la función, cualquier variable local u objetos constantes requeridos por

la función y una sección de enunciados.

ENCABEZADO DE LA FUNCIÓN

El

encabezado de la función proporciona la interfaz de datos para la función. Una interfaz de función o encabezado de la función es un enunciado que forma un marco común

entre la función y su programa llamador. Esta idea se muestra en la figura 10.1. Observe que el

encabezado indica que datos de la función aceptarán desde el programa llamador y qué datos de la función regresarán al programa llamador. Cuando desarrolle los encabezados de las funciones, su perspectiva necesita ser relativa a la función. Deberá preguntarse dos cosas:

1. ¿Qué datos debe aceptar la función desde el programa llamador para realizar la tarea designada?

2. ¿Qué datos, si los hay, deberán regresar la función al programa llamador para cumplir la tarea designada?

Programa llamador

Encabezado Cuerpo de la

de la función

función [proceso]

[interfaz]

Figura 10.1. El encabezado de la función forma la interfaz entre el programa llamador y la función Acepta

Regresa

(5)

En general, el encabezado de la función consiste en las tres partes siguientes:

•••• La clase de dato que regresará la función, si lo hay.

•••• El nombre de la función.

•••• Una lista de parámetros.

LA CLASE DE DATOS return

Lo primero que aparece en el encabezado de la función es la clase de datos del valor

regresado. Recuerde que la función puede regresar un solo valor que reemplace el nombre de la

función en donde aparece el nombre en el programa llamador. El valor que reemplaza el

nombre de la función en el programa llamador se conoce con el nombre de valor de retorno o

de regreso. Cuando se usa una función para este propósito, la clase de datos del valor de regreso

se deberá especificar en el encabezado de la función. Por ejemplo, suponga que nuestra función

cubo() regresa el cubo de un entero. Debido a que el cubo de un entero es un entero, la función regresará un valor entero. Como resultado, la clase de datos del valor regresado deberá ser int y especificarse en el encabezado de la función, como sigue:

int cubo(<listaParámetros>)

De otra manera, si nuestra función 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(<listaParámetros>)

Cuando una función no regresa ningún valor al programa llamador deberá usar la palabra reservada void como la clase de regreso, como se muestra a continuación:

void funcionMuestra(<listaParámetros>)

Las funciones que no regresan ningún valor al programa llamador se usan para realizar tareas específicas, como E/S.

EL NOMBRE DE LA FUNCIÓN

El

nombre de la función puede ser cualquier identificador legal en C++. Sin embargo, el nombre de la función no deberá empezar con un subguión (guión bajo), porque algunos depuradores colocan un subguión frente al nombre de la función si se encuentra un error en la

función. El nombre de la función describirá la operación que la función realiza, al igual que cubo() describe el cubo de un valor. Cuando invoque la función dentro de un programa

llamador, usará este nombre.

Cada función 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:

(6)

Nombre de la función Propósito de la función

imprimirCalificacion Imprimir calificación de los alumnos.

cuentasPorPagar Procesa las deudas de una compañía.

pedirNombre Solicita el nombre del usuario.

imprimirDocumento Imprime el archivo correspondiente al documento.

calcularImpuesto Calcula el impuesto del cliente.

Recuerde dos cosas:

1. El nombre de la función nunca se puede usar dentro de la función. En otras palabras, el siguiente enunciado dentro de la función cubo() generará un error:

cubo = x * x * x;

Hay una excepción a esta regla que se llama recursividad, la cual se explicará en la siguiente lección.

2. El identificador de la función nunca se usará del lado izquierdo del símbolo de asignación fuera de la función. Por tanto, el siguiente enunciado causará un error en el programa llamador:

cubo = x * x * x;

LISTA DE PARÁMETROS

La

lista de parámetros de la función incluye variables, llamadas parámetros, que pasarán desde el programa llamador y serán evaluados por la función. Piense en un parámetro

como una variable de la función que espera recibir un valor desde el programa llamador cuando se invoca la función. Para determinar los parámetros de la función, pregúntese ¿qué datos deberá aceptar la función para realizar su tarea? Suponga que nuestra función cubo() elevará al cubo valores enteros. La función deberá aceptar un valor entero desde el programa llamador y

regresará un valor entero al programa llamador. De esta manera, nuestra interfaz de función se

puede describir como sigue:

Función cubo(): Un entero al cubo.

Acepta: Un valor entero.

Regresa: Un valor entero.

Vamos a diseñar x como un objeto entero que aceptará la función. En C++, un

parámetro dado deberá especificarse en el encabezado de la función indicando su clase de datos

seguido por su identificador. Como resultado, la lista de parámetros apropiados para la función

cubo() deberá ser (int x). Colocando todo junto, el encabezado de la función deberá ser:

int cubo(int x)

Clase regreso Parámetro de la función Nombre de la función

Sí la

función

cubo() elevara al cubo valores de punto flotante, el encabezado de la

función apropiado deberá ser:

(7)

float cubo(float x)

Clase regreso Parámetro de la función Nombre de la función

Ejemplo 10.1

Suponga que quiere escribir una función definida por el usuario para calcular el voltaje en un circuito de cd usando la ley de Ohm. Escriba el encabezado de la función:

Para desarrollar el encabezado de la función, trataremos a la función como a una caja negra y nos haremos las siguientes preguntas: (1) ¿Qué dato deberá aceptar la función desde el programa llamador para realizar la tarea de aplicación? (2) ¿Qué deberá regresar al programador llamador? Las respuestas a estas preguntas dictarán el encabezado de la función o interfaz. Para contestar la primera pregunta, piense en qué deberá evaluar la función. Para calcular el voltaje usando la ley de Ohm, la función deberá evaluar dos cosas: corriente y resistencia. Así que utilicemos las palabras corriente y resistencia como nuestros parámetros. ¿De esta manera, la función deberá aceptar un valor de punto flotante de corriente y un valor de punto flotante de resistencia,

Después, deberá decidir qué datos regresará la función al programa llamador. Debido a que la función evalúa valores de punto flotante, tiene sentido matemático que el valor regresado también deba ser un valor de punto flotante.

Ahora, la interfaz de función se puede describir como sigue:

Función voltaje(): Calcula el voltaje usando la ley de Ohm.

Acepta: Un valor de punto flotante para corriente y un valor de punto flotante para resistencia.

Regresa: Un valor de punto flotante para voltaje.

Una vez que se ha decidido lo que acepta y lo que regresa la función, el encabezado de la función se construye fácilmente con la sintaxis de C++ como sigue:

float voltaje(float corriente, float resistencia) SECCIÓN DE ENUNCIADO

La

sección de enunciado de la función incluye aquellas operaciones que la función

deberá realizar para regresar un valor al programa llamador. Observe otra vez el formato general

para la función definida por el usuario. Como puede observar, la sección de enunciado

completa está enmarcada dentro de llaves. Después de abrir una llave, deberá empezar la sección

de enunciado declarando cualquier objeto constante y definiendo objetos variables que se

usarán dentro de la función. Cualquier objeto constante o variable listado aquí se llama local,

porque se definen sólo para uso local dentro de la misma función. Las constantes y variables

locales no tienen significado fuera de la función en la cual se definen. No duplique ninguno de sus parámetros de

función

aquí. Liste solamente constantes o variables adicionales que la

función requiera durante su ejecución. Un ejemplo común 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 función. En

realidad, puede declarar constantes locales y definir variables locales en cualquier lugar dentro

de la función siempre y cuando se listen antes de usarlas. Sin embargo, el buen estilo dicta que

éstas sean declaradas o definidas al principio de la sección de enunciado de la función.

(8)

No confunda las variables locales con los parámetros de la función. Una variable local se define después de abrir la llave de una función para usarle dentro de ésta. Un parámetro de función se define en el encabezado de la función como un lugar que mantiene el espacio para los

valores del argumento que pasan a la función cuando se llama a la misma. También se

usará dentro de la función para suministrar datos desde el programa llamador a la función.

Los

enunciados ejecutables de la función siguen a cualquier enunciado o definición local. El último enunciado en una función sin void es el return. Este se usa cuando se regrese un

solo valor al programa llamador. Así, si nuestra función cubo() regresa el cubo de x, un enunciado de regreso apropiado deberá ser:

return (x * x * x);

Combinando el encabezado de la función y la sección de enunciado para la función

cubo(), dará la función completa como sigue:

int cubo(int x) {

return(x * x * x);

} // Fin de cubo()

Obviamente, ésta es una función relativamente sencilla que no requiere ningún enunciado de definición local o ejecutable que no sea el enunciado return.

Ejemplo 10.2

Complete la función voltaje() cuyo encabezado se desarrolló en el ejemplo 10.1 Solución

La ley de Ohm requiere la función para multiplicar la corriente por la resistencia para obtener el voltaje.

De esta manera, el único enunciado requerido en la función es un enunciado return que regresará el producto de corriente y resistencia. Colocando todo junto, la función completa se convierte en:

float voltaje(float corriente, float resistencia) {

return (corriente * resistencia);

} // Fin de voltaje()

Una fuente común de error durante la codificación de una función sin void es hacer la asignación al nombre de la función dentro de ésta, como sigue:

float voltaje(float corriente, float resistencia) {

return voltaje = corriente * resistencia;

} // Fin de voltaje()

Esto siempre causará un error de compilación, porque se intenta regresar el nombre de la función. Deberá regresar un valor que, en este caso, es el producto de corriente y resistencia.

Ejemplo 10.3

Escriba una función que regrese la suma de todos los enteros desde 1 a algún valor máximo entero, llamado maximo. La función deberá obtener el valor de maximo desde el programa llamador.

(9)

Solución

Vamos a llamar a esta función suma(). Ahora, la función deberá aceptar un valor entero llamado maximo desde el programa llamador. Debido a que la función es para sumar todos los enteros desde 1 hasta maximo, ésta regresará un valor entero. De esta manera nuestra interfaz de función se puede describir como sigue:

Función suma(): Suma todos los enteros desde 1 hasta maximo.

Acepta: Un valor entero: maximo.

Regresa: Un valor entero.

Utilizando esta información, el encabezado de la función se convierte en:

int suma(int maximo)

El siguiente paso es determinar si hay alguna variable local requerida por los enunciados de la función. 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 aplicación clásica para una variable local. Vamos a llamar a esta variable utilizada como contador local contador. Después, también 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 función 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 función sin void en cualquier parte de su programa de la misma

manera que llama las funciones estándar en

C++. Por ejemplo, puede llamar una función

usando un operador de asignación o un enunciado cout como el siguiente:

y = cubo(2);

o cout << cubo(2);

En ambos casos, el valor 2 se pasa a la función que se va a elevar al cubo. De esta manera, en nuestra función cubo(), el parámetro

x toma el valor 2. Y la función regresará el

cubo de 2, que es 8. Con el enunciado de asignación, la variable y asignará el valor 8, y el enunciado cout hará que el valor 8 se muestre en pantalla.

Aquí están otras dos formas en que nuestra función cubo() se puede llamar:

int a = 2;

y = cubo(a);

o

(10)

En estos casos, la función 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 función. En nuestra función cubo() el parámetro x toma el valor de a.

Las funciones también pueden ser llamadas como parte de expresiones aritméticas o enunciados relacionales. Por ejemplo, nuestra función cubo() puede ser llamada como parte de una expresión aritmética, como ésta:

int a = 1;

y = 1 + cubo(a) * 2;

¿Qué se asignará a y? Bien, primero C++ evalúe la función cubo() para obtener 8, después realiza la operación de multiplicación para obtener 16 y por último suma 1 a 16 para obtener 17.

También puede usar funciones como parte de operaciones relacionales, como ésta:

if(cubo(a) >= 27)

¿Cuándo será verdadera la relación? 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 función se

diseña para regresar un solo valor al programa llamador, el valor regresado

reemplaza el nombre de la función donde quiera que se use el nombre en el programa llamador.

Generalmente se llamarán las funciones sin void dentro de su programa usando un enunciado de asignación, un objeto cout o como parte de una operación aritmética. Recuerde pensar en la llamada de función como un valor. Esto es, un valor reemplaza la llamada de función donde ésta aparece en el programa. Pregúntese: ¿Tiene sentido un valor aquí? Por ejemplo, todos los siguientes enunciados tienen sentido, porque un valor puede sustituirse fácilmente por la llamada de función:

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 compilación.

cubo(a);

ARGUMENTOS REALES EN COMPARACIÓN CON PARÁMETROS 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 función se llama parámetro formal. Los argumentos reales son valores o variables que se

utilizan dentro de la llamada de la función y los parámetros formales son variables que se utilizan dentro del encabezado de la función y que reciben valores del argumento real.

De esta manera, decimos que el parámetro formal en nuestra función cubo(), x, toma el

valor del argumento real

a, utilizado en la llamada de

función. Estas son algunas cosas que

querrá recordar de los argumentos reales y los parámetros formales:

(11)

•••• Las variables de argumento real se deberán definir en el programa llamador. Estará en la función main(), a menos que las funciones sean llamadas por otras funciones.

•••• La clase de datos de los argumentos reales correspondientes y los parámetros formales deberán ser

los mismos.

•••• Los parámetros formales mantienen el espacio para los valores del argumento real durante la

ejecución de la función. Los parámetros formales siempre se listan en la sección de parámetros del encabezado de la función.

•••• El número de argumentos reales usado durante la llamada de función deberá ser el mismo que el

número de parámetros formales listados en el encabezado de la función, excepto cuando se usan parámetros predeterminados. Los parámetros predeterminados se explicarán posteriormente.

•••• La correspondencia entre argumentos reales y parámetros 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 parámetro formal a menudo tienen diferentes nombres

de variable, pueden ser las mismas. Cuando éste es el caso, los objetos variables respectivos deberán definirse en el programa llamador y también tendrán que aparecer en la lista de parámetros de la función.

RETORNO DE UN RESULTADO AL PROGRAMA QUE INVOCA A LA FUNCIÓN

En algunas ocasiones la función ejecutará cierto tipo de cálculos. La función posteriormente devolverá este valor a quién la llama. Cuando una función 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 función, simplemente preceda al nombre de

la

función con la clase correspondiente. Por ejemplo, la siguiente función

sumaValores suma

dos números enteros y regresa un resultado entero.

Ejemplo 10.4

El siguiente programa SUMAVAL.CPP, utiliza la función sumaValores, para sumar valores diferentes:

/* El siguiente programa: SUMAVAL.CPP, llama a una función llamada sumaValores, la cual calcula la suma de dos números enteros.

*/

#include <iostream.h> //Para cout

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()

EXAMEN BREVE 27

(12)

FUNCIONES void

Las funciones que no regresan un solo valor al programa llamador a menudo se escriben para realizar alguna tarea específica. Estas se llaman funciones void.

Cuando una función no regresa un solo valor al programa llamador, se deberá usar la palabra reservada void como el regreso de la clase de datos. Además, estas funciones pueden o

no requerir parámetros. Cuando no se requieren parámetros, simplemente deje la lista de parámetros en blanco para indicar al compilador que la función no necesita recibir ningún valor

desde el programa llamador. Las funciones que no regresen un valor o no requieran ningún

parámetro son del tipo de funciones más simples en C++. Por ejemplo, suponga que quiere

escribir una función que mostrará el siguiente encabezado en la pantalla cada vez que se le

llama:

NOMBRE CALLE DIRECCIÓN ESTADO CIUDAD CÓDIGO POSTAL

Vamos a llamar a esta función muestraEncabezado() Para desarrollar el encabezado de

la función, pregúntese que deberá aceptar la función para realizar la tarea diseñada y que deberá regresar. En este caso, la función simplemente muestra la información constante de la línea de encabezado y no necesita aceptar ni regresar ningún dato. De esta manera, nuestra interfaz de

función puede escribirse como sigue:

Función muestraEncabezado(): Muestra la información fija del encabezado.

Acepta: Nada.

Regresa: Nada.

Usando esta información, el encabezado de la función se convierte en:

void muestraEncabezado(void)

Observe el

encabezado de la función 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. También, note que no hay parámetros requeridos para esta función, porque la lista

de

parámetros también contiene void o se deja en blanco. En otras palabras, la función no regresa un valor y no requiere ningún 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 función. Colocando todo junto, la función 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 función, porque la función no

regresa ningún valor.

¿Cómo puede

llamar a esta función en su programa? Simple, sólo use el nombre de la

función como un enunciado dentro del programa llamador cada vez que el encabezado se muestre, por ejemplo:

muestraEncabezado();

(13)

Ningún argumento real se lista en la llamada de la función, porque la función no evalúa ningún argumento.

Cuando

llame una función void, simplemente liste el nombre de la función y los argumentos requeridos como un enunciado sencillo dentro de su programa. No llame una

función void con un operador de asignación u objeto cout como lo hace para las funciones sin

void. La siguiente llamada muestraEncabezado() deberá causar un error de compilación.

encabezado = muestraEncabezado(); // Error cout << muestraEncabezado(); // Error

La llamada correcta es simplemente:

muestraEncabezado();

PARÁMETROS DE VALOR EN COMPARACIÓN CON PARÁMETROS DE REFERENCIA

La función anterior muestraEncabezado() no requiere ninguna lista de parámetros

formal, porque para evaluar no necesita recibir ningún argumento desde el programa llamador.

Cuando se requieren evaluar parámetros formales por la función, éstos deberán listarse en el

encabezado de la función en una de dos formas: como parámetros de valor o como parámetros de referencia.

PARÁMETROS DE VALOR

Hasta el momento, se han usado parámetros de valor en esta lección. Los parámetros de

valor permiten una comunicación de datos en un sentido desde el programa llamador a la

función. Una primera aproximación de este concepto se muestra en la figura 10.2a.

Programa llamador Función

Figura 10.2a. Paso de parámetros mediante un valor

Observe que los valores de los argumentos reales en el programa llamador se pasan (por medio de un valor) a parámetros formales en la función. Otra forma de pensar con respecto a esto es que el parámetro formal recibe una copia del valor del argumento real. Cuando la función opera sobre un parámetro de valor, está operando en una copia, más 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 función. Algo que se debe recordar cuando

se usan parámetros de valor es que cualquier manejo de los parámetros formales dentro de la función no afecta el valor del argumento real usado por la llamada de la función. Por ejemplo, considere la siguiente función:

Parámetros formales Argumentos reales “Copia”

(14)

void pasaValor(int x, int y);

{

// Incrementa y decrementa parámetros formales ++x;

--y;

// Muestra los valores del parámetro formal cout << “x = ” << x << endl;

cout << “y = ” << y << endl;

} // Fin de pasaValor()

Aquí, los

parámetros x y y son parámetros de valor. Observe que, dentro de la función,

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 función 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 función pasaValor(a, b);

// Muestra los valores de argumento real cout << “a = ” << a << endl;

cout << “b = ” << b << endl;

} // Fin del main()

Primero, observe cómo se hace el llamado a la función. Es simplemente un enunciado en el programa llamador. El nombre de la función se lista seguido por los argumentos reales requeridos dentro de paréntesis. Los argumentos reales son a y b, porque éstos se listan en la

llamada de la

función. Cuando se ejecuta la llamada de la función, el valor de a

pasa al parámetro 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 función, 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 función después 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 después de la llamada de la función, el programa llamador muestra los valores de a y b. ¿Qué se verá en la pantalla al ejecutar el programa? Bien, la función pasaValor() muestra x y y, después main() muestra a y b. De esta manera, el resultado que se exhibe es:

x = 1 y = -1 a = 0 b = 0

A continuación veamos algunos ejemplos en los que se muestren los conceptos antes aprendido.

Ejemplo 10.5

El siguiente programa, MSTRMSJ.CPP utiliza una función para enviar un mensaje:

(15)

Ejemplo 10.6

El siguiente programa, DOSMSJ.CPP, utiliza las funciones muestraTitulo() y muestraLeccion() para visualizar información acerca de las lecciones:

Para incrementar la capacidad de las funciones,

C++ le permite a sus programas pasar

información (argumentos) a sus funciones. Cuando una función utiliza parámetros, debe indicarle a C++ la clase de cada uno de los parámetros, tales como int,

float, char y así

sucesivamente.

/* El siguiente programa: MSTRMSJ.CPP, crea una función 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 función" << endl << endl;

muestraMensaje();

cout << endl << "Regreso del llamado a la función" << endl;

} //Fin de main()

/* 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 básicos sobre funciones" << endl;

} //Fin de muestraLeccion()

void main(void) {

muestraTitulo();

muestraLeccion();

} //Fin de main()

(16)

Ejemplo 10.7

El siguiente programa: USOPAR.CPP, utiliza la función mostrarNumero, varias veces, en cada ocasión se le pasa un valor diferente.

En la mayoría de los casos, sus programas pueden pasar varios valores a la función. Para cada valor pasado, su función debe declarar su nombre y clase.

Ejemplo 10.8

El siguiente programa: GDEPEQ.CPP, utiliza la función mostrarGdeYPeq para visualizar el número más grande y el más pequeño de tres enteros que recibe.

/* El siguiente programa: USOPAR.CPP, elabora una función que muestra los diferentes parámetros que le son enviados.

*/

#include <iostream.h> //Para cout

void mostrarNumero(int valor) {

cout << "El valor del parámetros es: " << valor << endl;

} //Fin de mostrarNumero()

void main(void) {

mostrarNumero(1);

mostrarNumero(1001);

mostrarNumero(-532);

} //Fin de main()

/* El siguiente programa: GDEPEQ.CPP, crea una función 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 más grande es: " << grande << endl;

cout << "El valor más pequeño es: " << pequeno << endl;

} //Fin de mostrarGdeYPeq()

(17)

Ejemplo 10.9

El siguiente programa: MSTEMP.CPP, utiliza la función mostrarEmpleado para visualizar la edad de un empleado (clase int) y su salario (clase float)

PARÁMETROS DE REFERENCIA

Los

parámetros de referencia, algunas veces llamados parámetros de variable, difiere

de los de valor en que éstos proporcionan una combinación en dos sentidos entre el programa

llamador y la función, como se ilustra en la figura 10.2b.

Programa llamador Función

void main (void) {

mostrarGdeYPeq (1, 2, 3);

cout << endl;

mostrarGdeYPeq (500, 0, -500);

cout << endl;

mostrarGdeYPeq (1001, 1001, 1001);

} //Fin de main()

/* El siguiente programa: MSTEMP.CPP, muestra una función 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 << " años" << endl;

cout << "El empleado gana $" << salario << endl;

} //Fin de mostrarEmpleado()

void main(void) {

mostrarEmpleado(32, 25000.00);

} //Fin de main()

Parámetros formales Argumentos reales “Dirección”

(18)

Un parámetro de referencia proporciona una comunicación de ida y vuelta de datos entre el programa llamador y la función. Observe el camino de comunicación de ida y

vuelta: los valores de los argumento reales pasan a los parámetros formales en la función y después los valores de parámetros formales regresan a los argumentos reales. Esto permite a la función cambiar los valores de argumento real en el programa llamador. Recuerde que un parámetro de valor es simplemente una copia del valor del argumento real; por lo tanto, cualquier operación

sobre el parámetro dentro de la función no tiene efecto en el valor del argumento original. De otra manera, un parámetro de referencia representa la dirección del valor de argumento real en la memoria. Como resultado, cualquier cambio que se haga al parámetro de referencia dentro de la función cambiará lo que está almacenado en esa dirección. Esto obviamente modifica el valor

original del argumento real en el programa llamador.

Para crear un

parámetro de referencia, simplemente inserte un ampersand (&) antes de

los identificadores de

parámetro apropiados en el encabezado de la función. Vamos a cambiar

nuestro ejemplo pasaValor() para usar parámetros de referencia, como sigue:

void pasaReferencia(int &x, int &y);

{

// Incrementa y decrementa parámetros formales ++x;

--y;

// Muestra los valores del parámetro 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

función. Seguro, el nombre de la

función también se ha cambiado para reflejar la nueva aplicación. ¿Qué deberá ver en la pantalla como resultado de la ejecución del siguiente programa?

void main(void) {

// Se definen las variables de argumento real int a = 0;

int b = 0;

// Se llama a la función 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 parámetros de referencia y no parámetros de valor,

cualquier operación que afecta a x y y dentro de la función también afectará los valores de los

argumentos reales a y b que se utilizan en la llamada de la función. Estos son los valores que

muestra el programa:

x = 1

y = -1

a = 1

b = -1

(19)

Como puede ver, los nuevos valores de x y y pasan de regreso a a y b respectivamente.

Usamos la expresión pasan de regreso para describir la acción. Sin embargo, recuerde que en realidad nada pasa de regreso, porque la función 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 función muestraParametros(a,b);

// Muestra los valores de argumento real cout << “a = ” << a << endl;

cout << “b = ” << b << endl;

} // Fin de main()

/**********************************************************

Esta función muestra el uso de valores en comparación con parámetros de referencia.

**********************************************************/

void muestraParametros(int &x, int y) {

// Incremente y decrementa parámetros formales ++x;

--y;

//Muestra valores de parámetro formal cout << “x = ” << x << endl;

cout << “y = ” << y << endl;

} // Fin de muestraParametro() Solución

Aquí se ve un programa completo que incorpora una función. La función está localizada inmediatamente después de la llave que encierra la función main() La función se llama entonces dentro de la sección de enunciado main() simplemente listando su nombre seguido por una relación 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 función. Los parámetros formales son x y y. Ambos son enteros; sin embargo, x es un parámetro de referencia mientras que y es un parámetro de valor. Observe el uso de ampersand antes de x. Esto define x como un parámetro de referencia. Sigue una coma después de x finalizando esta definición. Después y se define por separado como un parámetro 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

(20)

Ejemplo 10.11

Escriba una función llamada intercambio() que acepte dos objetos enteros desde el programa llamador y regrese los objetos con sus valores intercambiados.

Solución

Esta es una aplicación ideal para parámetros de referencia porque, para intercambiar los valores, el proceso de intercambio dentro de la función deberá tener un efecto sobre los valores original en el programa llamador. Así, la función deberá aceptar dos objetos enteros y regresar los mismos dos objetos con los valores intercambiados. A continuación se muestra una descripción de la interfaz de la función:

Función intercambio(): Intercambia los valores de dos objetos enteros.

Acepta: Dos objetos enteros.

Regresa: Los mismos dos objetos enteros.

Debido a que la función deberá regresar las mismas dos variables enteras que los que acepta, ambos serán parámetros de referencia. Vamos a etiquetar los parámetros como objeto1 y objeto2. El encabezado de la función entonces se convierte en:

void intercambio(int &objeto1, int &objeto2)

Observe el uso de ampersand para indicar que los parámetros son parámetros de referencia. Debido a que objeto1 y objeto2 son parámetros de referencia, se intercambiarán los valores de los objetos de argumento real usados en la llamada de la función. Ahora, para intercambiar los dos valores dentro de la función, deberá crear un objeto variable local temporal para que no se pierda uno de los valores. De acuerdo con esta idea, la función 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 función en un programa, simplemente liste el nombre de la función y proporcione dos objetos variables para intercambiar, por ejemplo:

intercambio(a, b)

Por supuesto, a y b deberán definirse e inicializarse con valores dentro del programa llamador, en algún lugar antes de esta llamada de la función.

LOCALIZACIÓN DE LAS FUNCIONES DENTRO DE SU PROGRAMA

Antes de que su programa pueda llamar a una función, C++ debe saber la clase de valor que la función

regresa y el número y clase de parámetros que la función 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, después de cerrar la llave de la función main() No hay límite en el

(21)

número de funciones definidas por el usuario que se puedan usar en un programa. Para llamar una función que regresa un valor, deberá insertar el nombre de la función donde se quiera que

regrese el valor. Para llamar una función void, simplemente liste su nombre como un enunciado

dentro del programa llamador. En ambos casos, los argumentos reales requeridos por la función deberá listarse dentro de paréntesis después del nombre de la función cuando ésta se llama.

Además, el número de argumentos reales que se utilizan en la llamada de función deberá ser el mismo que el número de parámetros formales definidos en el encabezado de la función respectiva, a menos que se usen parámetros predeterminados.

La colocación de las funciones en un programa C++ se resume en la figura 10.3.

Observe la estructura en bloques de un programa general. La función 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 función main() por medio de las llamadas de las funciones.

Esta es la razón de que C++ sea conocido como lenguaje estructurado en bloques. De ahora en adelante, cuando desarrollemos programas C++, intentaremos dividir el problema de programación general en un grupo de subproblemas más sencillos cuya solución combinada soluciona el problema original. ¿Cómo se codificarán estos subproblemas? Ya sabe, ¡Cómo

funciones! Esta es la esencia de la programación estructurada y diseño descendente de software.

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

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()

(22)

PROTOTIPO DE FUNCIONES

Para asegurarse de que C++ conoce las características de cada función que utiliza su programa, debe colocar prototipos de las funciones al principio de su programa fuente, algunas veces, se conoce como un enunciado de función; es un modelo de interfaz para la función que usa el compilador para verificar el número apropiado de argumentos y las clases de datos de los

argumentos en las llamadas de la función.

Los prototipos fuerzan al compilador a realizar verificaciones adicionales a sus llamadas de función, de esta manera ayudan en la detección de errores de programación asociados con

llamadas de

función. Por ejemplo, si una función 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 función prototipo se especifique antes de la llamada de la función.

Dado que los prototipos obligan al compilador a verificar errores durante la compilación, esto no afecta el tamaño ni la velocidad del tiempo de ejecución del programa. Aunque tome al compilador ligeramente más tiempo en realizar esta tarea de verificación de errores, cualquier error detectado por medio de los prototipos puede ahorrar horas de depuración, que serían necesarias si no se emplearan los prototipos. Por estas razones, el lenguaje C++ requiere las funciones

prototipo. Sin embargo, conviene saber que la función prototipo es opcional en el

lenguaje C.

En la definición anterior de prototipo, se infiere que éste proporciona un modelo de

interfaz para la función. Bien, la interfaz de la función es el encabezado de la función; por lo

tanto, el prototipo de la función es sólo una

copia del encabezado de la función que utiliza el

compilador para verificar las llamadas a la función. Así el prototipo dicta las clases de datos que

aceptará la

función desde el programa llamador y las que regresará la función al programa

llamador.

Los

prototipos de

función se localizan antes de la función

main(). El prototipo de

función puede ser sólo una copia del

encabezado de la función 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 función estudiante() no regresará un valor al programa llamador. Además, estudiante() espera recibir tres parámetros cuando se le llama.

El primer parámetro se interpretará como un entero, el segundo como un valor de punto flotante y el tercero como un carácter. Si se hace un llamado de la función con más o menos el número de parámetros listados en el prototipo, el compilador generará un error, a menos que se especifiquen

parámetros predeterminados. Si se llama a la

función con parámetros que pertenecen a clases de datos diferentes que las listadas en el prototipo, los parámetros se tratarán como si éstos fueran la lista de clases de datos respectivos.

En general un prototipo de función, contiene información acerca del tipo de retorno y de

sus

parámetros. Los siguientes enunciados ilustran prototipo de

función para varias de las

funciones ya utilizadas:

(23)

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 función estudiante() cuyo prototipo ya se mostró:

La salida generada por este programa es:

Hay 5 exámenes, que dan como resultado un promedio de 85.6 y una calificación alfabética de B.

Cómo puede observar, los argumentos reales en la llamada de la función pasaron a estudiante() y se utilizaron para construir el enunciado cout. Si se han utilizado más o menos parámetros en la llamada de la función, el resultado será un error de compilación. Pero, ¿qué pasaría si las clases de datos del argumento no fueran las mismas que las listadas en el prototipo? Considere la siguiente llamada a la función:

estudiante(‘B’, ‘A’, 67);

Esta llamada no deberá producir un error de compilación, porque el número de parámetros es correcto. Sin embargo, el compilador interpretará el primer parámetro como un entero, el segundo como un valor de punto flotante y el tercero como un valor carácter. El resultado que genera la llamada de función será:

Hay 66 exámenes, que dan como resultado un promedio de 65.0 y una calificación alfabética de C.

/* El siguiente programa: ESTUDIANTE.CPP, ilustra una función que muestra el número de exámenes realizados, el promedio y la calificación alfabética del estudiante.

*/

#include <iostream.h> //Para cout

// Prototipo de la función

void estudiante(int numeroExamenes, float promedio, char calificacion);

void main(void) {

estudiante(5, 85.6, 'B');

} // Fin del main()

/***********************************************************************************

Esta función mostrará un promedio del estudiante y su calificación.

***********************************************************************************/

void estudiante(int numeroExamenes, float promedio, char calificacion) {

cout.setf(ios::fixed);

cout.precision(1);

cout << "Hay " << numeroExamenes << " exámenes, que dan como resultado "

<< "un promedio de " << promedio << endl;

cout << "y una calificación alfabética de " << calificacion << '.' << endl;

} // Fin de estudiante()

Referencias

Documento similar

La campaña ha consistido en la revisión del etiquetado e instrucciones de uso de todos los ter- mómetros digitales comunicados, así como de la documentación técnica adicional de

You may wish to take a note of your Organisation ID, which, in addition to the organisation name, can be used to search for an organisation you will need to affiliate with when you

Where possible, the EU IG and more specifically the data fields and associated business rules present in Chapter 2 –Data elements for the electronic submission of information

The 'On-boarding of users to Substance, Product, Organisation and Referentials (SPOR) data services' document must be considered the reference guidance, as this document includes the

In medicinal products containing more than one manufactured item (e.g., contraceptive having different strengths and fixed dose combination as part of the same medicinal

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)