Chapter 7 Functions Dale/Weems/Headington. 2 Tópicos Capítulo 7 l Writing a Program Using...

Post on 02-Apr-2015

108 views 3 download

Tags:

transcript

Chapter 7

Functions

Dale/Weems/Headington

2

Tópicos Capítulo 7

Writing a Program Using Functional Decomposition

Writing a Void Function for a Task Using Function Arguments and Parameters Differences between Value Parameters and

Reference Parameters Using Local Variables in a Function Function Preconditions and Postconditions

3

Funciones

Cada programa en C++ debe tener una función llamada “main”

La ejecución del programa siempre comienza con la función “main”

Cualquier otra función es un subprograma y necesita ser invocada (llamada)

4

Function Calls (Llamadas de Funciones)

Una función llama a otra utilizando el nombre de la función llamada seguido de los paréntesis () los cuales podrían incluir una lista de argumentos.

Una llamada de función (“function call”) transfiere temporeramente control de la función que invoca a la función invocada.

5

FunctionName ( Argument List )

La lista de argumentos (“argument list”) es una forma de las funciones poder comunicarse entre si y de pasar información.

La lista de argumentos (“argument list”) puede contener o, 1 o más argumentos separados por coma, dependiendo de la función.

Function Call Syntax

6

Las Dos Partes de la Definición de una Función

int Cube ( int n ) heading{

body return n * n * n ;

}

7

¿Qué es el “heading”?

int Cube ( int n )

tipo de valor que devuelve nombre de la

función

Lista de parametros

8

¿ Qué es un prototipo (“prototype”)?

Un prototipo se ve similar al “heading”, sin embargo termina con un punto y coma (;) y se necesita identificar en el, los tipos de datos de los parámetros que va a utilizar la función como tal.

int Cube( int ); // prototype

9

Cuando se invoca una función…Se define una memoria temporera ( para los valores de los parámetros y cualquier variable local. También se define para el valor que devuelve si la función no es “void”).

Entonces el flujo de control pasa al primer enunciado (“statement”) en el cuerpo (“body”) de la función invocada. Las demas instrucciones del cuerpo son invocadas hasta que ocurre una de las siguientes condiciones:

return statement (con o sin un “return value”),

or,

se encuentra las llaves que indican el final del “body”.

Entonces el control se devuelve a la función que invoco.

10

#include <iostream>using namespace std; int Cube ( int ) ; // prototype

void main ( ){ int yourNumber ; arguments int myNumber ; yourNumber = 14 ; myNumber = 9 ;

cout << “My Number = “ << myNumber ; cout << “its cube is “ << Cube (myNumber) << endl ; cout << “Your Number = “ << yourNumber ; cout << “its cube is “ << Cube (yourNumber) << endl ;}

11

Para Compilar exitosamente…

Antes de que se invoque una función en el programa, el compilador debe procesar previamente el prototipo de la función o la definición de la función (“heading and body”)

12

Una función de C++ puede devolver

En su enunciado, un valor del tipo especificado (llamado “return type”) en su “heading” y “prototype”.

Sin embargo, una función “void” no puede devolver ningún valor en sus enunciados.

13

Escribir una función “void”

llamada DisplayMessage ( ) que sea invocada de la función main ( ) para describir el índice de contaminación el cual recibe como parámetro.

Tu ciudad clasifica los niveles de contaminación como: Menor que 35 como “Placentero”, 35 a 60 como “Desagradable”, y sobre 60 como “Peligroso”

14

parametro

void DisplayMessage( int index )

{

if ( index < 35 )

cout << “Pleasant”;

else if ( index <= 60 )

cout << “Unpleasant”;

else

cout << “Health Hazard”;

}

15

#include <iostream>using namespace std; void DisplayMessage (int); // prototype

int main ( ) argument{

int pollutionIndex;

cout << “Enter air pollution index”;cin >> pollutionIndex;DisplayMessage(pollutionIndex); // callreturn 0;

}

Resto del Programa

15

16

return;

Es válido solamente en el “body block”de las funciones que no sean “void”

Causa que el control deje la función y vuelva al bloque que la llamo dejando las subsequentes instruciones (si quedaban) sin ejecutarse.

17

Los “Header files” contienen declaraciones de…

Definir constantes como..const int INT_MAX = 32767;

Prototipos de funciones como…float sqrt( float );

clases como….

string, ostream, istream

Objetos como….

cin, cout

18

Programa con varias Funciones

Square function

Cube function

function prototypes

main function

19

Funciones que devuelven un valor

#include <iostream>

int Square ( int ) ; // prototypesint Cube ( int ) ;using namespace std;

int main ( ){ cout << “The square of 27 is “

<< Square (27) << endl; // function call cout << “The cube of 27 is “ << Cube (27) << endl; // function call

return 0;}

19

20

Resto del Programa

int Square ( int n ) // header and body{ return n * n;}

int Cube ( int n ) // header and body{ return n * n * n;}

21

Una función “void” se invoca ella sola

#include <iostream>

void DisplayMessage ( int ) ; // prototype

using namespace std;

int main ( ) argument{ DisplayMessage(15); // function call

cout << “Good Bye“ << endl;

return 0;} 21

22

Una función “void” no devuelve un valor

parameter void DisplayMessage ( int n ){ cout << “I have liked math for “ << n << “ years” << endl ;

return ;}

23

Lista de Parametros

Es el medio que utiliza una función para compartir datos con el bloque que contiene la llamada

24

Clasificación por Localización

Siempre aparecen en el “function call“ dentro del bloque que llama.

Siempre aparece en la función “heading”, o en la función “prototype”.

Argumentos Parametros

25

Algunos Términos importantes

use el termino “actual parameters” para los argumentos

algunos libros se refieren a los parámetros como “formal parameters”.

26

“Value Parameter” “Reference Parameter”

El valor (25) del argumento se pasa a la funciónCuando es invocada.

La dirección de memoria (4000)del argumento se pasa a lafunción cuando es invocada.

25

4000

age

En este caso, el argumento puede ser una variable, constante,o expresión.

En este caso, el argumentodebe ser una variable.

Argumento

en el Bloque que llama

26

27

Por “default”, los parametros… simples (como int, char, float, double) son siempre parametros por valor (“value parameters”), a menos que se haga algo para cambiar eso. Para obtener un parámetro por referencia (“reference parameter”) se necesita poner un & despues de tipo de dato en la función “heading” y “prototype”.

28

Cuando usar Parámetros por Referencia (“Reference Parameters”)

Los parámetros por referencia deben ser usados cuando se quiere modificar el valor de una de las variables del bloque que invoca sin que se asigne el valor al volver de la llamada.

29

Utilizar un Parámetro por Referencia

Es como darle a alguien la llave de la casa.

La llave puede ser usada por la otra persona para cambiar el contenido de la casa.

30

MEMORIA EN EL “MAIN PROGRAM”

25

4000

age

Si sólo se pasa una copia del valor 25 a una función, se le llama “pass-by-value” y la función no será capaz de cambiar el contenido de age. Seguirá siendo 25 cuando el control vuelva a la función que invoco.

31

MEMORIA EN EL “MAIN PROGRAM”

PERO, si pasas la dirección (4000), de age a la función, se le llama “pass-by-reference” y la función será capaz de cambiar el contenido de age. Puede ser 23 o 90 cuando se devuelva el control.

25

4000

age

32

“Pass-by-reference” también se le llama . . .

“pass-by-address”, o

“pass-by-location”

33

Ejemplo de “Pass-by-Reference”

Queremos encontrar 2 raizes cuadradas de una ecuación cuadrática con coeficientes a,b,c. Escribiremos un prototipo para una función “void” llamada GetRoots( ) con 5 parámetros. Los primeros 3 parámetros son tipo float. Los próximos 2 son parámetros por referencia de tipo float.

34

void GetRoots ( float , float , float , float& , float& );

Ahora escribiremos la definición de la función utilizando esta información.

Esta función usa 3 valores de entrada (a,b,c) que vienen del bloque que invoca. Calcula como resultado dos valores que tiene que devolver. Esos valores son las dos raizes cuadradas de la ecuación cuadrática con coeficientes a,b,c.

// prototype

35

void GetRoots( float a, float b, float c, float& root1, float& root2)

{ float temp; // local variable

temp = b * b - 4.0 * a * c;

root1 = (-b + sqrt(temp) ) / ( 2.0 * a );

root2 = (-b - sqrt(temp) ) / ( 2.0 * a );

return;}

Definición de la Función

35

36

#include <iostream>

#include <fstream>

#include <cmath>

void GetRoots(float, float, float, float&, float&);

using namespace std;

void main ( )

{ ifstream myInfile;

ofstream myOutfile;

float a, b, c, first, second;

int count = 0;

...... // open files

while ( count < 5 ) { myInfile >> a >> b >> c;

GetRoots(a, b, c, first, second); //call

myOutfile << a << b << c << first << second << endl;

count++ ;

} // close files

...... }

36

37

“Pass-by-value”

CALLINGBLOCK

FUNCTION CALLED

“incoming”

value ofargument

38

“Pass-by-reference”

CALLINGBLOCK FUNCTION

CALLED

“incoming”

valor original del argumento

“outgoing”

Valor cambiadodel argumento O,

39

“Pass-by-reference”

CALLINGBLOCK FUNCTION

CALLED

El argumento no tiene valor todavía cuando ocurre la llamada

“outgoing”

Nuevo valor delargumento

40

El Flujo de Datos Determina el Mecanismo para pasar los Datos

Incoming /* in */ Pass-by-value

Outgoing /* out */ Pass-by-reference

Incoming/outgoing Pass-by-reference

/* inout */

Parameter Data Flow Passing-Mechanism

41

Preguntas

¿Porqué se utlizan las funciones para las tareas?

Para acortar la cantidad de detalles en el modulo principal (encapsulation).

¿Puede una función llamar a otra función?

Si ¿Puede una función llamarse a si misma?

Si, eso se llama recursión.

42

Más Preguntas

¿Hace diferencia los nombres que se utilizan para los parámetros?

NO. Solo se utilizan en el “body”. ¿Los nombres de los parámetros y

argumentos tienen que ser los mismos?

NO. ¿ Qué ventaja hay en eso? Ninguna,

eso tiende a confundir.

43

Ejemplo – escribe el prototipo y definnición de función para…

Una función void llamadaGetRating( ) con un parámetro de referencia de tipo char

La función repetídamente pide al usuario que entre un caracter por el teclado hasta que una de estas letras se entre: E, G, A, P que representan “Excellent”, ”Good”, ”Average”, ”Poor”.

44

void GetRating( char& ); // prototype

void GetRating (char& letter)

{ cout << “Enter employee rating.” << endl;

cout << “Use E, G, A, or P : ” ;

cin >> letter;

while ( (letter != ‘E’) && (letter != ‘G’) && (letter != ‘A’) && (letter != ‘P’) )

{

cout << “Rating invalid. Enter again: ”;

cin >> letter;

}

}44

45

¿Qué es un driver?

Es un programa corto (main) cuyo único propósito es llamar una función que se haya escrito. De este modo se puede determinar si cumple con las especificaciones y trabaja como se desea.

Escriba un “driver”para la función GetRating( )

46

#include <iostream>

void GetRating( char& ); // prototype

using namespace std;

int main( ){ char rating; rating = ‘X’;

GetRating(rating); // call

cout << “That was rating = “ << rating << endl;

return 0;}

46

47

Un “Assertion”

es un “truth-valued statement”que puede ser cierto o falso (no necesariamente in código de C++)

EJEMPLOS

studentCount > 0

sum is assigned && count > 0

response == ‘y’ or ‘n’

0.0 <= deptSales <= 25000.0

beta == beta @ entry * 2

48

“Preconditions” y “Postconditions” El “precondition” es un “assertion” que

describe todo lo que la función requiere para ser cierto al momento de la función ser invocada.

El “postcondition” describe el estado en el momento que la función termina de ejecutarse.

El que llama es responsable de cotejar la “precondition”, y la función llamada, la “postcondition”. EJEMPLO . . .

49

Function con “Postconditions”

void GetRating ( /* out */ char& letter)

// Precondition: None

// Postcondition: User has been prompted to enter a character

// && letter == one of these input values: E,G,A, or P

{ cout << “Enter employee rating.” << endl;

cout << “Use E, G, A, or P : ” ;

cin >> letter;

while ( (letter != ‘E’) && (letter != ‘G’) && (letter != ‘A’) && (letter != ‘P’) )

{

cout << “Rating invalid. Enter again: ”;

cin >> letter;

}

} 49

50

Función con Preconditions y Postconditions

void GetRoots( /* in */ float a, /* in */ float b, /* in */ float c, /* out */ float& root1, /* out */ float&

root2 )// Precondition: a, b, and c are assigned// && a != 0 && b*b - 4*a*c != 0// Postcondition: root1 and root2 are assigned // && root1 and root2 are roots of quadratic with coefficients a, b, c{

float temp;

temp = b * b - 4.0 * a * c;

root1 = (-b + sqrt(temp) ) / ( 2.0 * a );

root2 = (-b - sqrt(temp) ) / ( 2.0 * a );

return;}

50

51

Función con Preconditions y Postconditions

void Swap( /* inout */ int& firstInt,

/* inout */ int& secondInt )

// Precondition: firstInt and secondInt are assigned

// Postcondition: firstInt == secondInt@entry

// && secondInt == firstInt@entry

{ int temporaryInt ;

temporaryInt = firstInt ;

firstInt = secondInt ;

secondInt = temporaryInt ;

} 51

52

G etD ata () C a lcD ivis ion () S h ow R esu lts ()

m a in ()a, bParámetros por referencia

a, b q, r

q, rParámetros por valor

Laboratorio # 1- ParámetrosDe acuerdo al siguiente Structure Chart

Pasa el siguiente código al compilador y pruebalo

53

Laboratorio 1 – (cont.)// Programa: división.cpp// Calcula el cociente y el residuo de 2 numeros enteros# include <iostream>using namespace std;// Prototiposvoid GetData (int &a, int &b)void CalcDivision (int a, int b, int &q, int &r);void ShowResults (int q, int r);int main(){

int num1, num2, quotient, remainder;GetData (num1, num2);CalcDivision(num1, num2, quotient, remainder);ShowResults(quotient, remainder);return 0;

}

54

Laboratorio 1 – (cont.)void GetData(int &a, int &b){

cout << “Enter two integres: “;cin >> a >> b;

}void CalcDivision(int a, int b, int &q, int &r){

q = a / b;r = a % b;

}void ShowResults(int q, int r){

cout << “The quotient is “ << q << “and the remainder is “ << r << endl;

}

55

Laboratorio 1 – completo// Programa: división.cpp// Calcula el cociente y el residuo de 2 numeros enteros# include <iostream>using namespace std;// Prototiposvoid GetData (int &a, int &b)void CalcDivision (int a, int b, int &q, int &r);void ShowResults (int q, int r);int main(){

int num1, num2, quotient, remainder;GetData (num1, num2);CalcDivision(num1, num2, quotient, remainder);ShowResults(quotient, remainder);return 0;

}void GetData(int &a, int &b){

cout << “Enter two integres: “;cin >> a >> b;

}void CalcDivision(int a, int b, int &q, int &r){

q = a / b;r = a % b;

}void ShowResults(int q, int r){

cout << “The quotient is “ << q << “and the remainder is “ << r << endl;}

56

Laboratorio 1 – (cont.)

Si queremos devolver uno de los valores de forma directa, podemos poner:int CalcDivision (int a, int b, int &q){

q = a / b;return a % b;

}

Y en la instrucción se tiene que poner:remainder = CalcDivision(num1, num2, quotient) Se puede aunque es

un poco confuso.

main() GetData() CalcDivision()

num1 [6] a [dirección num1] a [6]

num2 [3] b [dirección num2] b [3]

quotient [2] q [dirección quotient]

remainder [0] r [dirección remainder]

57

Laboratorio # 2 – Archivos y Parámetros

Vamos a leer de un archivo (rectángulo.dat) el id del rectángulo (numero), la base y altura. Finalmente guardamos el id del rectángulo y su area en un archivo llamado areas.dat.

a:\rectangulo.dat a:\areas.dat1 4.3 5.82 6.7 2.43 5.6 6.5

1 24.92 16.03 36.4

58

Laboratorio # 2 – (cont.)

G etD ataF rom F ile () C a lcA rea() W riteR esu lts In toF ile ()

m a in ()while ¡eof

59

Laboratorio # 2 – (cont.)// Programa: rect.cpp// Este programa lee de un archivo la base y altura de un

rectángulo y calcula el area.// El área se guarda en otro archivo. Este programa utiliza

funciones, parámetros por valor y por// referencia y manejo de archivo. También utiliza ciclo while.# include <fstream># include <iomanip>using namespace std;// Prototiposvoid GetDataFromFile(ifstream &ArchDatos, int &id, float

&base, float &altura);float CalcArea(float base, float altura);void WriteDataIntoFile(ofstream &ArchResultado, int id, float

area);

60

Laboratorio # 2 – (cont.)int main(){

ifstream ArchRectangulos;ofstream ArchAreas;int IdRect;float BaseRect, AlturaRect, AreaRect;ArchRectangulos.open(“a:\\rectangulos.dat”);ArchAreas.open(“a:\\areas.dat”);ArchAreas << fixed << Showpoint << setpresicion(1);GetDataFromFile(ArchRectangulos, IdRect, BaseRect, AlturaRect);while (¡ArchRectangulos.eof()){

AreaRect = CalcArea(BaseRect, AlturaRect);WriteDataIntoFile(ArchAreas, IdRect);GetDataFromFile(ArchRectangulos, IdRect, BaseRect,

AlturaRect);}ArchRectangulos.close();ArchAreas.close();return 0;}

61

Laboratorio # 2 – (cont.)

void GetDataFromFile (ifstream &ArchDatos, int &id, float &base, float &altura)

{ArchDatos >> id >> base >> altura;

}float CalcArea(float base, float altura){

return base * altura;}void WriteDataIntoFile(ofstream &ArchResultados, int id, float area){

ArchResultados << id << “ “ << area << endl;}

62

Laboratorio # 2 completo– (cont.)// Programa: rect.cpp// Este programa lee de un archivo la base y altura de un rectángulo y calcula el area.// El área se guarda en otro archivo. Este programa utiliza funciones, parámetros por valor y por// referencia y manejo de archivo. También utiliza ciclo while.# include <fstream># include <iomanip>using namespace std;// Prototiposvoid GetDataFromFile(ifstream &ArchDatos, int &id, float &base, float &altura);float CalcArea(float base, float altura);void WriteDataIntoFile(ofstream &ArchResultado, int id, float area);int main(){

ifstream ArchRectangulos;ofstream ArchAreas;int IdRect;float BaseRect, AlturaRect, AreaRect;ArchRectangulos.open(“a:\\rectangulos.dat”);ArchAreas.open(“a:\\areas.dat”);ArchAreas << fixed << Showpoint << setpresicion(1);GetDataFromFile(ArchRectangulos, IdRect, BaseRect, AlturaRect);while (¡ArchRectangulos.eof()){

AreaRect = CalcArea(BaseRect, AlturaRect);WriteDataIntoFile(ArchAreas, IdRect);GetDataFromFile(ArchRectangulos, IdRect, BaseRect, AlturaRect);

}ArchRectangulos.close();ArchAreas.close();return 0;}

void GetDataFromFile (ifstream &ArchDatos, int &id, float &base, float &altura){

ArchDatos >> id >> base >> altura;}float CalcArea(float base, float altura){

return base * altura;}void WriteDataIntoFile(ofstream &ArchResultados, int id, float area){

ArchResultados << id << “ “ << area << endl;}