Procedimientos y funciones

Anuncio
Procedimientos y funciones
1
Objetivos
Al final de esta actividad debes ser capaz de:
1. Describir los conceptos de procedimiento y función, la diferencias entre ellos, y su
utilidad
2. Definir los conceptos: cabecera de procedimiento o función, parámetros formales,
variables locales, resultado de la función, activación del procedimiento o función,
parámetros reales
3. Codificar convenientemente una llamada a procedimiento o función, pasando
correctamente los parámetros por valor
4. Codificar en forma de procedimiento o función una tarea convenientemente
especificada, estableciendo adecuadamente los parámetros necesarios
2
Motivación
En los programas que hemos hecho hasta ahora todo el código se encuentra en el
programa principal (a partir del void main). Esta estrategia resulta problemática
cuando tenemos programas grandes, porque al encontrarse todo el código en el
programa principal es más difícil de entender, detectar errores, hacer modificaciones,
etc.
Todos los lenguajes de programación tienen algún mecanismo que permite definir
bloques de código que se escriben aparte del programa principal. Cada bloque realiza
una cierta operación con entidad lógica (por ejemplo, ordenar un vector, o escribir unos
datos en pantalla), y el programa principal activa los bloques de código cuando necesita
realizar esas operaciones.
Organizar los programas usando bloques hace que el código esté mejor organizado y sea
más fácil de entender (y por tanto, de mantener). Incluso en algunas ocasiones, el
programa principal activa un mismo bloques varias veces, con lo cual, aunque el código
ejecuta varias veces, sólo hay que escribirlo una vez.
3
Las funciones en C
En lenguaje C, los bloques se llaman funciones. Veamos un ejemplo de una función y
cómo se usa.
1
#include <stdio.h>
#include <stdio.h>
int maximo (int x, int y)
{
if (x>y )
return x ;
else
return y ;
} ;
void main ()
{
int a,b;
int max;
printf (“Escribe los numeros:\n”);
scanf (“%d %d”,&a,&b);
if (a > b)
max = a;
else
max = b;
printf (“El maximo es %d\n”,max);
void main ()
{
int a,b;
int max;
}
printf (“Escribe los numeros:\n”);
scanf (“%d %d”,&a,&b);
max = maximo (a,b);
printf (“El maximo es %d\n”,max);
}
El cuadro de la izquierda muestra el programa original, sin funciones. Todo el código
está en el programa principal. El cuadro de la derecha muestra el programa que usa una
función. La función se llama maximo y se escribe antes del programa principal.
La función retorna como resultado el máximo de dos valores enteros. La primera línea
de la función es lo que llamamos cabecera o prototipo de la función. En esa línea, de
izquierda a derecha, lo primero que se indica es que el resultado de la función será un
número entero. Después viene el nombre de la función (en este caso maximo).
Finalmente viene una lista de parámetros formales, que nos indica qué tipos de datos
necesita la función para realizar la tarea asignada. En este caso, la función tiene dos
parámetros que son números enteros.
Después de la cabecera viene el cuerpo de la función, en el que se especifica las
operaciones que hay que realizar con los datos que se reciben como parámetros para
calcular el resultado. La sentencia return indica que la función se termina en ese
momento y el resultado de la función es el valor que se especifica a la derecha de la
palabra return.
En el programa principal, para ejecutar la función lo único que tenemos que hacer es
escribir el nombre de la función y entre paréntesis los valores que queremos pasarle a la
función como parámetros (los denominamos parámetros reales). En este caso, pasamos
a la función los números enteros contenidos en las variables a y b del programa
principal. Puesto que estamos llamando a una función, debemos especificar también qué
hay que hacer con el resultado de la función. En este caso, indicamos que el resultado de
la función se almacena en la variable max.
1.
Para comprender mejor el funcionamiento del mecanismo de funciones, construye un
proyecto con el programa de la parte derecha de la figura. Ahora ejecútalo, siguiendo
cuidadosamente las siguientes instrucciones.
2
Pulsa F10 para iniciar la ejecución paso a paso. Coloca en la
ventana del watch las variables x, y, a, b y max. La ventana
del watch tendrá el aspecto de la derecha.
El computador no entiende todavía lo que es x e y (los
parámetros formales de la función). Además, te está indicando
que todavía no se ha reservado espacio en memoria para las
variables a,b y max (porque todavía no se ha ejecutado la
declaración de esas variables).
Pulsa una vez más F10. El programa ejecuta la declaración de
variables, con lo que el computador reserva espacio en
memoria para a, b y max). La ventana del watch tendrá el
aspecto de la derecha.
El computador sigue sin saber lo que es x e y. Ahora ya sabe lo
que son a, b y max, y el valor inicial de esas variables es
“basura”.
Avanza con el F10 para ejecutar las sentencias printf y
scanf. Si introducer los valores 4 y 5 la ventana del watch
tendrá el aspecto de la derecha.
Pulsa ahora F11 para ejecutar la operación de activación de la
función. Observa que el computador ha abandonado el
programa principal y se ha quedado preparado para ejecutar la
primera sentencia de la función. La ventana del watch tiene el
aspecto de la derecha.
Por fin el computador reconoce las variables x e y (los
parámetros formales de la función). En cambio, ya no sabe lo
que es a, b ni max, porque estas son variables que pertenecen
al programa principal, que ha sido abandonado
momentáneamente.
Además, ha tenido lugar un proceso clave en el mecanismo de
las funciones: el paso de parámetros. Antes de poner en marcha
la función, el computador a copiado los valores de los
parámetros reales (a y b) en los parámetros formales
correspondientes (x e y). A partir de ese momento, la función
puede usar esos valores, trabajando con las variables x e y.
Ejecuta la función paso a paso pulsando F10 hasta que
regresemos al programa principal. En ese momento, la ventana
del watch tendrá el aspecto de la derecha.
De nuevo, el computador ha dejado de entender lo que son x e
y (la función ya acabó), y vuelve a reconocer a, b y max,
porque hemos regresado al programa principal. Además, se ha
producido la asignación del resultado de la función a la variable
max.
Habrás observado que a veces hemos avanzado en la ejecución con F10 y otras veces
con F11. Ambas opciones sirven para avanzar la ejecución paso a paso, pero hay una
diferencia muy importante. Si avanzas con F10 entonces, cuando el computador llegue a
una función la ejecutará de golpe sin enseñarte paso a paso las sentencias que hay
dentro de la función. En cambio, si avanzas con F11 el computador te mostrará paso a
paso las sentencias que hay dentro de la función.
2.
Ejecuta de nuevo paso a paso el programa anterior, avanzando siempre con F10. Verás
como la función se ejecuta de golpe en un solo paso, sin mostrarte las sentencias que hay
dentro de la función.
3.
Ejecuta ahora de nuevo el programa paso a paso pero avanzando siempre con F11. Verás
que justo cuanto das la orden de ejecutar la sentencia printf el computador te muestra
una ventana con la imagen de la izquierda. Si cierras esa ventana aparecerá una pantalla
3
con la imagen de la derecha. Lo que ha pasado es que, puesto que estás usando F11, el
computador está intentando mostrarte la ejecución paso a paso de la función printf, que
es una función como cualquier otra, aunque ya programada previamente. La imagen de la
derecha te muestra las instrucciones de la función printf escritas en el lenguaje
ensamblador del computador.
Naturalmente, a nosotros no nos interesa ejecutar paso a paso la función printf. En
realidad, muchas veces querremos ejecutar paso a paso nuestro programa pero sin ver
paso a paso algunas de nuestras funciones, porque estamos seguros que esas funciones
no tienen errores. Es por eso que va bien avanzar paso a paso a veces con F10, y otras
veces con F11 (cuando queremos ver las sentencias de las funciones).
En el ejemplo has visto la forma más obvia de usar una función. Fíjate en los siguientes
ejemplos, que también son correctos.
max = maximo (5,a);
Llamamos a la función, pero en este caso uno de
los parámetros reales es una constante, y el otro el
valor de una variable.
Llamamos a la función y en lugar de almacenar
temporalmente el resultado en una variable antes
de escribirlo, usamos el resultado de la función
directamente en la sentencia printf.
Calculamos el mayor de 3 números, llamando dos
veces a la función maximo. Primero la llamamos
para calcular el mayor entre el valor de b y 5. El
resultado lo pasamos directamente como
parámetro de nuevo a la función maximo, junto
con el valor de a, para calcular el mayor
definitivo.
printf (“El máximo es %d\n”,
maximo(a,b));
max = maximo(a, maximo(b,5));
Escribe un programa principal que use la función maximo para calcular el mayor de 4
números enteros, usando el menor número posible de sentencias.
4
Procedimientos
A veces es necesario realizar una tarea que no produce ningún resultado. Esa tarea
también se puede escribir en forma de bloque, pero en ese caso, en vez de llamarla
función la llamamos procedimiento. Fíjate en el siguiente ejemplo.
4
#include <stdio.h>
int maximo (int x, int y)
{
if (x>y )
return x ;
else
return y ;
} ;
void escribir (int r)
{
printf (“El resultado es %d\n”,r);
};
void main ()
{
int a,b;
int max;
printf (“Escribe los numeros:\n”);
scanf (“%d %d”,&a,&b);
max = maximo (a,b);
escribir (max);
}
En ese ejemplo se ha definido un procedimiento que se llama escribir, que tiene un
parámetro formal de tipo entero. Lo único que hace el procedimiento es escribir el valor
del parámetro en la pantalla. Puesto que es un procedimiento no retorna ningún valor
(no usa la sentencia return). La primera palabra de la cabecera del procedimiento es
void. Por último, el programa principal no tiene que hacer nada con el resultado del
procedimiento, porque no hay resultado. Por eso, para llamar al procedimiento
simplemente se escribe el nombre seguido de la lista de parámetros reales.
5
Las variables locales
Normalmente, una función (o un procedimiento) hace tareas más complejas que las que
hace la función maximo. Para realizar esas tareas la función necesitará algunas
variables de apoyo, que llamaremos variables locales. Las variables locales se crean en
el momento en que se activa la función, y desaparecen en el momento en que la función
termina. Veamos un ejemplo.
#include <stdio.h>
int suma_d (int x)
{
int d, suma;
suma=0;
d = x%10;
while (x >0)
{
suma = suma + d;
x = x/10;
d = x%10;
}
return suma;
} ;
void main ()
{
int a;
printf ("Escribe el numero:\n");
scanf ("%d",&a);
printf ("La suma de digitos es %d\n",suma_d(a));
}
5
La función suma_d calcula la suma de los dígitos del número entero que recibe como
parámetro. Para ello necesita las variables locales d y suma.
4.
Ejecuta el programa y comprueba que funciona correctamente. Ejecútalo después paso a
paso, observando las variables d y suma en la ventana del watch. Comprueba que antes de
llamar a la función suma_d, el computador no reconoce las variables d y suma (puesto
que son locales a la función, y todavía no se han creado). Justo cuando se inicia la función
se crean las variables, que vuelven a desaparecer cuando la función ha acabado.
6
Funciones que llaman a otras
Veamos ahora un ejemplo más complejo. En la siguiente figura tenemos la función
es_primo, que indica si el entero que recibe como parámetros es primo o no. Fíjate
que la función retorna un entero: true (o lo que es lo mismo, un 1) si el número es
primo, o false (o lo que es lo mismo, un 0) si el número no es primo.
#include <stdio.h>
int es_primo (int x)
{
int i, encontrado;
i=1;
encontrado = false;
while ((i < x) && !encontrado)
{
if ((x%i) == 0)
encontrado = true;
if (!encontrado)
i=i+1;
};
if (!encontrado)
return true;
else
return false;
} ;
int suma_primos (int vector[10])
{
int i, suma;
for (i=0; i<10; i++)
if (es_primo (vector[i]))
suma = suma+vector[i];
return suma;
};
void main ()
{
int i;
int v[10];
for (i=0; i<10; i++)
{
printf ("Escribe el numero:\n");
scanf ("%d",&v[i]);
};
printf ("La suma de primos es %d\n",suma_primos(v));
}
6
Por otra parte, la función suma_primos calcula la suma de los números primos que
hay en el vector que recibe como parámetro. Para ello, usa la función es_primo.
Por último, el programa principal lee de teclado un vector de números, y calcula la suma
de los que son primos, usando la función suma_primos.
5.
Pon en funcionamiento este programa. Comprobarás que NO funciona bien. En realidad
tiene dos errores muy tontos. Busca y corrige esos errores usando lo que has aprendido
sobre ejecución paso a paso, y visualización de variables en la ventana del watch.
Este ejemplo nos muestra:
1. Que una función puede llamar a otras
2. Cómo trabajar con funciones que retornan verdadero o falso
3. Como trabajar con funciones que reciben vectores como parámetro
7
Ejercicios
Ejercicio 1: Dado el siguiente programa en C:
int funcio1(int k1, int k2)
{
int b;
if (k1 == k2)
b=k1+k2;
else
b=k1*k2;
printf(“b=%d\n”,b);
return b;
}
void main()
{
int a,b,c;
a= 10;
b= 12;
c= funcio1(a,b);
printf(“a=%d b=%d c=%d\n”,a,b,c);
a= funcio1(12,b);
printf(“a=%d b=%d c=%d\n”,a,b,c);
}
Haz el seguimiento del programa y determina qué es lo que imprimirá por pantalla.
Ejercicio 2: Escribe una función llamada media2 que reciba dos reales y devuelva el
real que representa la media aritmética de ambos números. Escribe luego un programa
utilizando la función del ejercicio anterior que lea dos reales por teclado y devuelva la
media aritmética de ambos.
7
Ejercicio 3: Escribe un procedimiento que escriba en pantalla los n primeros números
primos. El procedimiento recibe n como parámetro. Construye una función para ver si
un número es primo o no, y usa esa función para construir el procedimiento.
Ejercicio 4: Escribe una función que reciba un número como parámetro y devuelva el
número que se obtiene al invertir el orden de los dígitos del número original. Por
ejemplo, si la función recibe el número 356 devolverá el número 653.
8
Descargar