FUNCIONES Las funciones son un conjunto de instrucciones

  • Slides: 15
Download presentation
FUNCIONES

FUNCIONES

� Las funciones son un conjunto de instrucciones que realizan una tarea específica. En

� Las funciones son un conjunto de instrucciones que realizan una tarea específica. En general toman unos valores de entrada, llamados parámetros y proporcionan un valor de salida o valor de retorno; aunque tanto unos como el otro pueden no existir. � Las funciones son los bloques constructores de C. Son las funciones las que ayudan a realizar un programa de forma estructurada y clara además de su gran utilidad cuando se desea realizar un mismo tipo de operación repetidas veces ya que el código sólo tiene que ser escrito una vez. La forma general de una función es: � � especificador. De. Tipo. De. Vuelta nombre. De. La. Funcion(lista. Parametros) { cuerpo de la función; /* Aquí se agregarán todos los comandos que se ejecutarán cada vez que se llame a la función. */ � El “especificador. De. Tipo. De. Vuelta” especifica el tipo de valor que devuelve la función a través de la sentencia return. El valor puede ser cualquier tipo de variable válido incluyendo void para especificar que no retorna ningún valor ( en caso de ser void, la función no requerirá la sentencia return ). Como se ha comentado con anterioridad, si no se define ningún tipo de vuelta, el compilador asume que es de tipo int. “lista. Parametros” es la lista de nombres de variables que recibirán los valores de los argumentos que se le pasa a la función. Las variables se encuentran separadas por comas y cada una con su tipo asociado, .

� Todas las funciones a ser desarrolladas en el programa deben tener una declaración

� Todas las funciones a ser desarrolladas en el programa deben tener una declaración anticipada de dicha función. Eso es lo que se conoce como “prototipo de la función” y se realiza antes del bloque main(). De esta forma al compilarse el programa, para cada llamada a una función se verificará la existencia de su prototipo. Esto es imprescindible. � Ese es el porque de los archivos de cabecera (. h ) que son los que contienen los prototipos de las funciones básicas de lenguaje C. Por ejemplo conio. h define el prototipo de la funciones: clrscr(), gotoxy(), textcolor(), cprintf(), etc. � � Pongamos un ejemplo. Un prototipo de una función sería: � int kbhit (void); � Este prototipo define una función llamada kbhit que no recibe ningún argumento y retorna un valor entero.

� NOTA: Comente esta función debido a que es de gran utilidad. Esta función

� NOTA: Comente esta función debido a que es de gran utilidad. Esta función verifica si se ha presionada alguna tecla. Si no se ha presionado ninguna, devuelve el valor cero ( 0 ) y cualquier otro valor en el caso de que si se haya presionado una tecla. Una forma común de usarla es: � � � do { // Instrucciones. } while (!kbhit()); � donde el bucle do-while se mantendrá en ejecución mientras NO se haya presionado alguna tecla ya que se usó el negado del valor devuelto por la función.

Hay dos formas de finalizar la ejecución de una función. Una es llegando al

Hay dos formas de finalizar la ejecución de una función. Una es llegando al final de la misma donde se encuentra la llave '}', aunque realmente no hay muchas funciones que utilicen esta forma implícita ya que ellas no retornan valores (este caso se usa cuando la función retorna void ). � La segunda forma y la generalmente usada es a través del uso del return. “return” tiene dos usos importantes. El primero es que fuerza a la salida inmediata de la función en la que se encuentra ( lo cual es útil en los casos que se requieren multiples puntos de salida ) y en segundo lugar se utiliza para devolver un valor. � Por ejemplo: � � � void imprimeme ( char *mensaje ) { printf(“%s”, mensaje); } � la función imprimeme finaliza en la llave '}'. La función no retorna valores por lo tanto return no es requerido.

int cuadrado(int x) { � X=x*x; � return X; � } � � Esta

int cuadrado(int x) { � X=x*x; � return X; � } � � Esta función recibe un valor entero y devuelve otro entero que en este caso es el cuadrado del argumento de la función

� � #include<stdio. h> � � int cuadrado(int x); // Aquí se define el

� � #include<stdio. h> � � int cuadrado(int x); // Aquí se define el prototipo de la función � � � � int main(void) { int x, z; printf(“Introduzca un número entero: ”); scanf(“%i”, &x); z = cuadrado(x); // Asignamos a z el valor devuelto por la función. printf(“El cuadrado de %i es %i”, x, z); return 0; } � � � // Finalizó el bloque main(), ahora si desarrollamos las funciones. int cuadrado(int x) { x=x*x; return x; } � Como se observa primero incluimos los archivos de cabecera. Luego definimos los prototipos de las funciones que desarrollaremos en nuestro programa que en nuestro caso es sólo la función cuadrado(). A continuación colocamos el bloque main() de nuestro programa y luego de este desarrollamos la función.

� Las instrucciones: z = cuadrado(x); � printf(“El cuadrado de %i es %i”, x,

� Las instrucciones: z = cuadrado(x); � printf(“El cuadrado de %i es %i”, x, z); � � podrían sustituirse sencillamente por: � printf(“El cuadrado de %i es %i”, x, cuadrado(x)); � ya que cuadrado(x) es sencillamente un entero.

� Llamada por Valor o por Referencia. � Existen dos formas en las que

� Llamada por Valor o por Referencia. � Existen dos formas en las que se le pueden pasar parámetros a una función. El primer método se denomina “llamada por valor”. Este método es el que hemos usado en los ejemplos anteriores y lo que hace es hacer una copia del argumentado pasado a la función dentro de los parámetros formales de dicha función. Por lo tanto, los valores con los que se realizaron las llamadas no son alterados. Vemos un ejemplo: � #include<stdio. h> � void incrementa(int x, int y); � � � � main(){ int x=2, y=3; printf(“X y Y antes de ejecutar incrementa: %i y % in”, x, y); incrementa( x, y); printf(“X y Y luego de ejecutar incrementa: %i y % in”, x, y); return 0; } � � void incrementa(int x, int y) { x++; y++; } � Aquí, los valores iniciales de 'x' y 'y' son pasados a la función incrementa la cual coloca estos valores en sus variables 'x' y 'y' locales para incrementarlas. Repito: Estos valores son LOCALES por lo que los valores de las variables del bloque main() no se alteran.

� � El programa imprimirá: � � X y Y antes de ejecutar incrementa:

� � El programa imprimirá: � � X y Y antes de ejecutar incrementa: 2 y 3 X y Y luego de ejecutar incrementa: 2 y 3 � Sin embargo, el programador podría requerir que los valores del bloque main() _SI_ se vean alterados. Para lograr ésto debe usarse la “llamada por referencia”. Los argumentos que recibe la función en este caso son referencias a las direcciones de las variables. Esto se hace pasando “punteros” al argumento. Los punteros se pasan a las funciones como cualquier otro valor pero por supuesto es necesario declarar los parámetros como de tipo puntero a través del operador *. Para definir que una variable es un puntero debe usarse el operador * antes del nombre de la variable. Esto lo que hace es indicar que “el valor que contendrá la variable es una dirección”.

� � Veamos el ejemplo anterior pero usando una “llamada por referencia” � �

� � Veamos el ejemplo anterior pero usando una “llamada por referencia” � � #include<stdio. h> void incrementa(int *x, int *y); // Declara que incrementa() recibirá las direcciones de dos � // variables enteras. � � � � � main(){ int x=2, y=3; printf(“X y Y antes de ejecutar incrementa: %i y % in”, x, y); incrementa( &x, &y); // le paso a incrementa las direcciones de 'x' y 'y' printf(“X y Y luego de ejecutar incrementa: %i y % in”, x, y); return 0; } � � void incrementa(int *x, int *y) { (*x)++; // Se incrementa el CONTENIDO de x (*y)++; // Se incrementa el CONTENIDO de y }

� En este ejemplo la función incrementar recibe dos punteros a enteros, o sea,

� En este ejemplo la función incrementar recibe dos punteros a enteros, o sea, dos direcciones de memoria que apuntan a valores enteros. Observen que los parámetros de la función se definieron como punteros a través del operador *. Observen también como se le pasaron los argumentos a la función. Se hizo: incrementa( &x, &y). El operador & es el operador complemento de *. Este operador lo que hace es devolver la dirección de la variable. Por lo tanto, aquí lo que se esta diciendo es algo como: “ejecuta la función incrementa y mándale como parámetros las direcciones de memoria de las variables 'x' y 'y' ”. Como ya dijimos, la función incrementa está definida para recibir dichas direcciones. � La función _incrementa_ incrementa en uno los valores que están contenidos dentro e 'x' y 'y'. Obsérvese que se usó (*x)++ y (*y)++ ya que lo que se quiere incrementar es el contenido de las direcciones. *x++ lo que haría sería incrementar la dirección de memoria. (*x)++ es una forma de abreviar algo como: � � int temporal; temporal = *x; temporal++; *x = temporal;

� Como se está trabajando directamente sobre las direcciones de memoria que contienen los

� Como se está trabajando directamente sobre las direcciones de memoria que contienen los datos, efectivamente se están alterando dichos datos. Por lo tanto la salida de ejecutar este programa sería: � X y Y antes de ejecutar incrementa: 2 y 3 � X y Y luego de ejecutar incrementa: 3 y 4 �

� � Recursividad. � Una de las tantas características poderosas que tiene lenguaje C

� � Recursividad. � Una de las tantas características poderosas que tiene lenguaje C es que soporta la recursividad en las funciones. Ésto es: la capacidad que tiene una función de llamarse a sí misma. Si una expresión en el cuerpo de la función llama a la propia función, se dice que es recursiva. La recursividad es el proceso de definir algo en términos de sí mismo. Es decir, que para entender la recursividad primero hay que entender la recursividad. � Existen muchísimos ejemplos de recursividad pero definitivamente el más típico es el de la función factorial. Como todos saben el factorial se aplica sólo a números naturales[1] y el factorial de un número N se define como el producto de todos los números entre 1 y N. Sabiendo ésto, veamos un ejemplo de una función recursiva: la función factorial. � � � int factorial(int x) { int resultado; � � if (x==1) return 1; resultado = factorial(x-1)*x; return resultado; } � Como se observa en la función, si x es uno, entonces la función retorna uno. Si no, ésta se llama a sí misma con el valor de x-1.

Ejemplo por uds. De Fibonacci En matemática, la sucesión de Fibonacci es la siguiente

Ejemplo por uds. De Fibonacci En matemática, la sucesión de Fibonacci es la siguiente sucesión infinita de numeros naturales: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89… � A cada elemento de esta sucesión se le llama número de Fibonacci. Esta sucesión fue descrita en Europa por Leonardo Da Pisa Fibonacci. � � La sucesión fue descrita por Fibonacci como la solución a un problema de la cría de conejos: "Cierto hombre tenía una pareja de conejos juntos en un lugar cerrado y uno desea saber cuántos son creados a partir de este par en un año cuando es su naturaleza parir otro par en un simple mes, y en el segundo mes los nacidos parir también".