En la anterior entrega de funciones se explicaba de una forma un poco por encima como utilizarlas. En este tutorial explicaremos a fondo como utilizarlas y algunas características para usarlas correctamente. Con el tiempo, te darás cuenta que las funciones son las mejores amigas que puedes tener en el ámbito de estructurar un programa. Si todavía no sabes C, puedes empezar a aprender desde aquí.
Soy P22 y voy a continuar los tutoriales de programación en C que inició nuestro compañero tanos hace un tiempo. Os daréis cuenta que mi forma de programar es distinta a la de tanos, pero no os costará acostumbraros a mí.
Para hacer más ameno este tutorial, lo estructuraré en diversos apartados, siendo así más legible.
Las funciones sirven para estructurar un programa correctamente, haciendo este más legible y de fácil comprensión.
Una estructura de una función se expone a continuación.:
tipo nombrefuncion(argumento1, arg2, arg3, ... argn){ //Definiciones y declaraciones varias //Proceso de los argumentos y variables return; }
tipo será el tipo de la variable que devolverá la función. Donde nombrefuncion se sustituye por el nombre que se desee poner a la función; será el mismo con el que se llamará a la función. argumento1, arg2, arg3 ... argn se refieren a los argumentos que se pasarán a la función en el momento de la llamada. Esto se explicará más a fondo más adelante. return; sirve para devolver un valor al punto de llamada de la función.
Los argumentos son las variables, arrays, constantes, etc que se pasan a una variable.
Existen dos tipos de argumentos: los argumentos formales y los argumentos actuales.
En términos generales, los argumentos formales (también llamados parámetros o parámetros formales) son los que están en la línea de la definición de la función; los argumentos actuales son los que estan en la línea de la llamada a la función, y son los que en realidad se transfieren a la función. Por cada argumento formal, habrá uno actual, y siempre irán separados por comas.
Por defecto, cuando en un programa en C se le pasan unos argumentos actuales a una función, se le pasan por valor o lo que es lo mismo, se le asigna el valor al correspondiente argumento formal, pero el valor del argumento actual no variará a lo largo del proceso de la función. Se pueden pasar los argumentos por referencia, pero eso ya lo aprenderemos más adelante, cuando demos los punteros.
A continuación hay un ejemplo de un programa simple, tomado de aquí:
#include <stdio.h> #include <stdlib.h int main(){ //Declaracion de variables int sumando1 = 10; int sumando2 = 20; int c; //Prototipo de función, para más información: http://www.scenebeta.com/tutorial/datos-basicos-de-c int sumadatos(int, int); printf("Suma de dos valores.\n"); //Llamada a la función c = sumadatos(sumando1, sumando2); printf("El resultado es: %i", c); getchar(); return 0; } //Definición de Función int sumadatos(int a, int b){ int c; c = a + b; return c; }
En la llamada a la función:
c = sumadatos(sumando1, sumando2);
Se puede ver que sumando1 y sumando2 son argumentos actuales de tipo int.
En la definición a la función:
int sumadatos(int a, int b){
Se observa que a y b son parámetros formales.
Los valores de sumando1 y sumando2 se le pasan a a y b respectivamente, que luego se suman sus valores y se asignan a c. Tras esto, el valor de c es devuelto a la parte llamante del programa, y en una sentencia de asignación, se le da el valor de c de la función al c de main. Se puede ver que hay dos variables con el mismo nombre en el programa, pero como son variables locales a cada función no habrá problemas en el momento de la compilación. Tras realizarse todo esto, se retorna el control a la parte llamante del programa.
La sentencia return; sirve para retornar el valor de una variable, una constante, un número, caracter... a la parte llamante del programa, que luego se podrá imprimir, asignar a otra variable...
Recuerda el ejemplo anterior, se retornaba el valor de la variable c de la funcion sumadatos a la parte llamante del programa, donde se le asignaba el valor de este a la variable c de main.
Ahora, imagínate el mismo ejemplo, pero en vez de que se haga eso con el valor devuelto por la función, se haga lo siguiente:
#include <stdio.h> int main(){ //Declaracion de variables int sumando1 = 10; int sumando2 = 20; //Declaración de función, esto lo veremos más adelante int sumadatos(int, int); printf("Suma de dos valores.\n"); //Llamada a la función printf("El resultado es: %i", sumadatos(sumando1, sumando2)); getchar(); return 0; } //Definición de Función int sumadatos(int a, int b){ int c; c = a + b; return c; }
Ahora se ahorran un par de líneas y la definición de la variable c, que ocupa espacio en la memoria. Como no necesitaremos el dato más adelante aparte de imprimirlo, nos basta con imprimirlo y no guardarlo para más adelante, pero depende de cada caso, tú sabras lo que tienes que hacer en tu lugar.
De acuerdo, ahora observa este ejemplo:
#include <stdio.h> int main(){ //Declaracion de variables int sumando1 = 10; int sumando2 = 20; //Declaración de función, esto lo veremos más adelante int sumadatos(int, int); printf("Suma de dos valores.\n"); //Llamada a la función printf("El resultado es: %i", sumadatos(sumando1, sumando2)); getchar(); return 0; } //Definición de Función int sumadatos(int a, int b){ return (a+b); }
Ahora nos ahorramos otra variable más y una sentencia de asignación, poniendo directamente a + b en el return.
Por último, comentaros que las funciones void no devuelven ningun valor, por lo que return no sería necesario; sin embargo, se pone igualmente por ser una buena práctica de la programación. Esto se explica aquí.
Una buena forma de seleccionar que devolver con return son las sentencias switch (las veremos más adelante):
#include <stdio.h> int main(){ int valor = 0; int selector(void); printf("Estoy pensando un numero.\n"); printf("Tu tienes que introducir uno y tiene que ser igual al mio\n"); printf("ANIMO, SOLO TIENES UNA OPORTUNIDAD!!!\n"); valor = selector(); printf("\n\n"); switch(valor){ case 0: printf("Enhorabuena!! has acertado"); break; case 1: printf("El numero introducido es mayor, sigue intentandolo"); break; case -1: printf("El numero introducido es menor, sigue intentandolo"); break; } scanf("%i", &valor); return 0; } int selector(){ int a; printf("\nAhora introduce el numero que crees correcto: "); scanf("%d", &a); switch(a){ case 51: return 0; break; default: if (a < 51) return -1; else return 1; } }
Las declaraciones de función sirven para avisar al compilador de que existe una función más adelante, que será llamada antes de ser definida. Las declaraciones de función son solamente obligatorias si la función declarada está después de la función que llama y devuelve un valor no entero (por lo tanto, se engloban también las funciones que retornan un caracter, por incluirse en el código ASCII). Tener en cuenta, que si una función es llamada desde distintas funciones que la preceden, vais a necesitar poner una declaración por función.
Aunque las declaraciones de función no sean necesarias en las que preceden a la llamante, es preferible ponerlas, pues es una buena práctica de programación. Eso se explica aquí.
No te preocupes, las declaraciones de función son mucho más fáciles de pensar de lo que puedas creer. De hecho, ya las hemos utilizado repetidas veces en este tutorial. Repasemos el último ejemplo:
#include <stdio.h> int main(){ //Declaracion de variables int sumando1 = 10; int sumando2 = 20; //Declaración de función, esto lo veremos más adelante int sumadatos(int, int); printf("Suma de dos valores.\n"); //Llamada a la función printf("El resultado es: %i", sumadatos(sumando1, sumando2)); getchar(); return 0; } //Definición de Función int sumadatos(int a, int b){ return (a+b); }
Ahora observa esta línea:
int main(){ ... //Declaración de función int sumadatos(); ... return 0; } //Definición de Función int sumadatos(int a, int b){ return (a+b); }
Fíjate en como está construida la declaración, básicamente es el nombre de la función precedido de su tipo y seguido de unos paréntesis y un punto y coma.
Las declaraciones se ponen porque tienen más aplicaciones que saber que una función existe y está después. A continuación escribimos unas de las aplicaciones de las declaraciones:
Si volvemos atrás y vemos los ejemplos anteriores, podremos ver que en todos los ejemplos (salvo el último, para ahorrar confusiones) se ha especificado el tipo de los argumentos en la declaración. Esto sirve para evitar errores de compilación, y se explica aquí.
Es una aplicación de las declaraciones, y sirve para facilitar comprobaciones de errores entre la llamada y la definición de una función correspondiente.
La estructura de un prototipo de función es la siguiente:
tipo nombrefuncion(tipo1 arg1, tipo2 arg2, tipo3, arg3, ..., tipon, argn)
Donde tipo, va e tipo del valor devuelto por la función, en nombrefuncion va el nombre de la función declarada, y donde tipo1 arg1, tipon argn, va el tipo y nombre de los argumentos. Cabe destacar que a los argumentos de la declaración se les puede poner el nombre que se quiera pues solo serán reconocidos en la misma, aunque es preferible que tengan el mismo nombre que los argumentos actuales a usar. Sólamente deben concordar los tipos entre la definición, llamada y declaración (en este caso, prototipo).
Una aplicación de las funciones es la recursividad, que se explica aquí.
Comentarios
Un detalle
En el primer ejemplo te has dejado > en el include y // en el comentario.
Un detalle.
A este y al tutorial anterior les falta el enlace en el icono de la cabecera.
sAlud0s!
Gracias, muy bien explicado,
Gracias, muy bien explicado, cabe decir que se nota el esfuerzo que has hecho en estos tutoriales.
Salu2
Bueno, yo creo que
para aprender a programar, necesitas que te lo expliquen todo bien, o sino, mal vamos.
Por otro lado, gracias :)
¬¬
Pues tú no estás explicando muy bien que digamos. El problema es que dices cada término como si se diera por hecho que cada uno de ellos es perfectamente entendido por los que leen esto y los que intentas explicar los explicas "por encima" como si le estuvieras explicando a un amigo tuyo y no se entiende nada, y no me refiero a términos como funciones o variables, obviamente. O es que simplemente no sabes redactar el tutorial porque es el primero de los de C en el que no he entendido absolutamente nada. Piensa que hay personas que saben poco o nada de programación leyendo estos tutoriales, que no conocen toda la terminología y que, siendo un tutorial, debe ser fácil de entender.