Funciones Tipos de funciones y Recursividad SESION 4 Definición Una función es una subrutina o subprograma que forman un programa que realiza tareas bien definidas. Todo programa en C consta de una o más funciones. Una de estas funciones se llama main. La ejecución del programa siempre comenzará por la de las instrucciones contenidas en main. A la función se le puede “pasar” información mediante unos identificadores denominados argumentos o parámetros. Mónica E. García 1 Sintaxis tipo_dato nombre (tipo1 arg1,tipo2 arg2,...,tipon arg n) { Accion1; Accion2; . . . Accion N } Donde arg1 es el nombre de una variable Mónica E. García Funciones sin argumento Son funciones que no toman ni devuelven ningún valor // Prototipo de la función void funcion1(void); void main() { int conta; funcion1( ); for (conta=0;conta<10;cont a++) { funcion1( ); } //Cuerpo de la función void funcion1( ) { printf(“\nFunción que imprime un mensaje”); } Mónica E. García 2 Tipos de paso de parámetros Paso de parámetros por valor No se modifica el valor de ninguno de los parámetros que son pasados, es decir, cuando se produce el paso de parámetros, se hace una copia de cada parámetro y se modifica y se evalúan las copias dentro de la función, hasta que se ejecuta la sentencia return o se sale de la función es cuando se eliminan las copias existentes y se siguen utilizando las variables que se habían pasado (por valor) con los valores que tenían cuando se produjo la llamada a la función. Mónica E. García Tipos de paso de parámetros Paso de parámetros por referencia En este tipo, sí que se modifica el valor de los parámetros, lo que se pasa no es el valor de la(s) variable(s), sino la dirección de memoria que ésta(s) ocupa(n), con lo que al modificar su valor dentro de la función, se modifica también el valor fuera de la función. Cuando se ejecuta la sentencia return o se salga de la función las variables que se pasaron (por referencia) tienen el valor que tenían una vez se sale de la función. Mónica E. García 3 Funciones con paso de parámetros por valor Son funciones que toman uno o más parámetros del mismo o de distinto tipo. Ejemplo: void factorial (int n) { long int f=1; int i; for (i=2;i<=n;++i) La invocación en el main sería: factorial(n); f*=i; printf("el factorial de %d es %ld\n",n,f); } Mónica E. García Funciones con paso de parámetro por referencia Ejemplo : int suma( int &a, int b ) { int c; //nota: Valido para c++ c = a + b; a = 0; b= 55; return c; } void main() { int var1, var2; var1 = 5; var2 = 8; printf(" \n Antes de la invocación "); printf(" \n var1 vale: %i y var2 vale: %i\n", var1,var2); printf( "\n\nLa suma es: %i ", suma(var1, var2)); printf(" \ny var1 vale: %i y var2 vale: %i\n", var1,var2); getch(); } Mónica E. García 4 Funciones con apuntadores como paso de parámetros Son funciones que reciben es una variable de tipo apuntador. Ejemplo 1 : void factorial (int *n) { long int f=1; int i; for (i=2;i<=*n;++i) La invocación en el main sería: factorial(&n); f = f * i; printf("el factorial de %d es %ld\n",*n,f); } Mónica E. García Funciones con apuntadores como paso de parámetros Ejemplo 2 : #include <stdio.h> #include <conio.h> int suma( int *a, int b ) int c; c = *a + b; *a = 0; return c; } { void main() { int var1, var2; var1 = 5; var2 = 8; printf(" \n Antes de la invocación "); printf(" \n var1 vale: %i y var2 vale: %i\n", var1,var2); printf( "\n\nLa suma es: %i ", suma(&var1, var2)); printf(" \ny var1 vale: %i y var2 vale: %i\n", var1,var2); } Mónica E. García 5 Función que devuelve un valor long int factorial (int n) { long int f=1; int i; for (i=2;i<=n;++i) f*=i; return (f); } Mónica E. García Invocación de una función a otra función void uno(); void dos(); void main() { uno(); } void uno() { printf(“\nUNO”); dos(); } void dos() { printf(“\nDOS2”); } Mónica E. García 6 Recursividad La recursividad es la propiedad de una función de poder llamarse a si mismo cuando así se requiera. Si una función ( o Subfunción) requiere volver a ejecutar alguna parte de su código (sin hacer uso de ciclos de repetición), tan solo se llama a si misma . Mónica E. García Partes de la recursión 1 Caso base o de fin de la recursión: Es un caso donde el problema puede resolverse sin tener que hacer uso de una nueva llamada a sí mismo. Evita la continuación indefinida de las partes recursivas. 2 Parte recursiva: Relaciona el resultado del algoritmo con resultados de casos más simples. Se hacen nuevas llamadas a la función, pero están más próximas al caso base. Mónica E. García 7 Los algorítmos recursivos son mas simples y compactos que sus correspondientes iterativos, sin embargo su ejecución en una computadora es más lenta y requiere más recursos. Mónica E. García Ejemplo Iterativo Recursivo int Factorial( int n ) { int i, res=1; for(i=1; i<=n; i++ ) res = res*i; return(res); } int Factorial( int n ) { if(n==0) return(1); return(n*Factorial(n-1)); } Mónica E. García 8 Tipos de Recursión Recursividad simple: Aquella en cuya definición sólo aparece una llamada recursiva. Se puede cambiar a una función con ciclo iterativo. Recursividad múltiple: Se da cuando hay más de una llamada a sí misma dentro del cuerpo de la función Mónica E. García Tipos ... Recursividad anidada: En algunos de los argumentos de la llamada recursiva hay una nueva llamada a sí misma. Recursividad cruzada o indirecta: Son algoritmos donde una función provoca una llamada a sí misma de forma indirecta, a través de otras funciones. Mónica E. García 9 Ejemplos de recursión Función que retorna la longitud de una cadena. int longitud(char cadena[],int offset) { if(cadena[offset]==NULL) return offset; else return longitud(cadena,offset+1); } Mónica E. García Ejemplos de recursión Función que convierte un valor en base 10 a base 2 void binario(int n) { if (n==1) printf( "1”); else { binario(n/2); printf(“%i”, n%2); } } Mónica E. García 10 Consejos para diseñar un algorimo recursivo Suponer que ya existe un algoritmo para resolver una versión reducida del problema. Identificar subproblemas atómicos(casos base) Descomponer el problema en subproblemas que se puedan resolver con el algoritmo que se sabe existe y cuya solución vaya aproximándose a los casos base. Probar de "manera informal", que los casos base y los generales encuentren solución con el algoritmo diseñado. Mónica E. García 11