Anuncios

Bienvenidos sean a este post, hoy veremos las funciones en un modo mucho mas complejo, tambien veremos el tema de las variables y como son las formas de crear las funciones. Como dijimos antes, las funciones son una serie de instrucciones que pueden ser complementarias al programa main().

Anuncios

Esto habitualmente se utiliza para no tener que reescribir una instruccion que debe ser utilizada en varias oportunidades dentro del programa. Como dijimos antes, en general las funciones se definen primero el tipo de variable que va a ser, luego el nombre de la misma, luego entre parentesis las variables que va a recibir como dato (o no, esto no es obligatorio), despues se abre una llave, se genera el bloque de instrucciones y se cierra con otra llave, seria algo asi:

 
int miFuncion (int X, int Y)
{
.... bloque de instrucciones ....
}
Anuncios

Ahora las instrucciones se pueden declarar de 3 formas, a traves de un archivo (la menos utilizada), antes de main() y como prototipo. La primera opcion es generar un archivo donde contenga la funcion que se van a crear y despues se llama a este archivo a traves de include. La segunda opcion es la que vinimos utilizando hasta ahora, es que se crea la funcion, se le pone todas las instrucciones y se cierra todo esto antes de main() y el ultimo es declarar el tipo y el nombre antes de main() pero despues de main() se genera la funcion en si para que pueda ser utilizada, esto puede facilitar a la depuracion de la misma. Un ejemplo de estructura del ultimo tipo de declaracion de funcion es similar a esto:

 
# include <iostream>

using namespace std;

int miFuncion(int x, int y);

int main()
{
......
miFuncion(a,b);
.....
}

int miFuncion(int X, int Y)
{
.... Instrucciones ....
}
Anuncios

Procedamos a entrar en el campo de las variables, las mismas son de 2 tipos: Globales y Locales, entiendase por globales que son aquellas que se comparten en todo el programa, tanto en main() como en el resto de las funciones y es siempre el mismo valor, y las locales son aquellas que sirven unicamente para la funcion o donde fueron declaradas (por eso son locales).

Anuncios

Tambien se puede decir que las funciones que devuelven un valor se pueden usar como los valores para otras funciones, ejemplo miFuncion(otraFuncion(valor));. Esto puede resultar poco practico en el caso de que sean muchas funciones encadenadas, lo optimo para un caso como este deberia ser como se ve a continuacion, un ejemplo de llamado de funciones como parametros:

int respuesta=doble(triple(cuadrado(cubo(miValor))));

Una mejor practica del ejemplo anterior seria la siguiente:

unsigned long miValor=2;
unsigned long alCubo=cubo(miValor);
unsigned long alCuadrado=cuadrado(alCubo);
unsigned long triplicado=triple(alCuadrado);
unsigned long Respuesta=doble(triplicado);
Anuncios

Como pueden ver queda un poco mas comprensible a la vista pero mas largo que el anterior, tambien queda mas libre de errores, recuerden en programacion no siempre es mejor escribir menos codigo sino escribir un codigo de facil lectura y depuracion para nosotros o cualquier otro que necesite modificarlo. Pasemos a hablar de parametros predeterminados, esto se pueden definir en el caso de los prototipos. Supongamos que nosotros definimos que una funcion reciba un tipo de valor y nosotros lo omitimos esto generara un error de compilacion, para evitar se puede definir un parametro predeterminado que en caso de omision del mismo el programa lo utiliza para la funcion, un ejemplo seria cuando declaramos el prototipo:

int miFuncion(int x = 50);

O lo declaramos de esta forma:

int miFuncion(int = 50);

Y luego cuando se lo define seria algo asi:

int miFuncion(int x)
{
... Instrucciones ....
}
Anuncios

Como notaran en la estructura no es necesario repetir el parametro predeterminado pero la funcion ya sabe que en caso de omision de x debe utilizar el valor de 50. Ahora supongamos que tiene la siguiente funcion:

 long miFuncion (int param1, int param2, int param3); 
Anuncios

Para poder asignar un valor predeterminado a param2, se le debe asignar un valor a param3 y en el caso de que tengamos que asignar a param1, se le debe asignar un valor a los demas parametros, en este caso param2 y param3, es decir siempre al valor que queremos predeterminar deberemos definirle un valor a los parametros siguientes pero no es necesario para los anteriores. Otra forma de funciones es la sobrecarga de funciones, esto es una forma practica de hacer que una funcion con distintos tipos de variables pueda ser ejecutada, o sea los nombres de las funciones pueden ser los mismos, pero el programa va a chequear en base a  las variables que se le definan cual es la funcion que debe utilizar, tambien se debe tener en cuenta que cuando se utiliza este tipo de funcion, los parametros deben ser distintos, no los resultados, supongamos que se declaran 2 funciones con los mismos parametros pero las instrucciones son distintas y dan resultados distintos, este generara un error de compilacion por funcion duplicada. Veamos un ejemplo de como se podria utilizar, para ello tenemos estas tres funciones:

int DuplicarEntero(int);
long DuplicarLargo(long);
float DuplicarFlotante(float);
double DuplicarDoble(double);
Anuncios

Estas cuatro funciones podriamos reemplazar por el siguiente tipo de sobrecarga:

int Duplicar(int);
long Duplicar(long);
float Duplicar(float);
double Duplicar(double);
Anuncios

Como se ve las funciones tienen el mismo nombre (Duplicar) pero el programa las diferencia atraves de los tipos de variables que se definen, esto nos dara una mayor facilidad y practicidad a la hora de implementar nuestras funciones puede parecer confuso pero se daran cuenta mas adelante la practicidad de poder utilizar este tipo de declaracion de funcion.

Anuncios

Funciones especiales

Funciones en linea

Anuncios

Se utilizan mayoritariamente para evitar que el programa vaya y venga en reiteradas ocasiones de una funcion, esto en teoria lo que hace es efectuar una copia de la funcion dentro de la parte donde se la llama, esto mejora notablemente el rendimiento dado que el programa no entra y sale constantemente pero el inconveniente que trae es que si bien no se pierde tiempo se gana en tamaño del archivo y a la larga puede salir mas caro el collar que el perro, asi que en caso de querer utilizarlo seria para una funcion pequeña y que no se repita mucho. En el dia de hoy es una practica casi obsoleta, pero en el caso de necesitarla seria algo asi:

inline int miFuncion(int); 

Puede ser algo util pero seguramente se necesitara practica y experiencia para sacarle el verdadero jugo a esto.

Anuncios

Recursion

Anuncios

Esto se genera cuando una funcion se llama a si misma, esto es util para obterner algunos parametros dado que las variables locales de la primera vez que se llama la funcion son distintas a la segunda vez que se llama. Las recursiones pueden ser de 2 tipos, directas e indirectas, las directas son las que se llaman directamente desde si misma, y las indirectas son cuando de la funcion se llama a otra funcion y esta llama a la primera funcion. Vamos a estudiar un ejemplo con la serie fibonacci para entender la recursion:

funcion02.cpp

# include <iostream>

using namespace std;

int fib(int n);

int main()
{
        int n,respuesta;
        cout << "Escriba el numero a encontrar:";
        cin >> n;
        cout << "\n\n";
        respuesta=fib(n);
        cout << respuesta << " es el numero " << n;
        cout << " en la serie de Fibonacci" << endl;
        return 0;
}

int fib(int n)
{
        cout << "Procesando Fib(" << n << ")... ";
        if (n<3)
        {
                cout << "Regresa 1!" << endl;
                return 1;
        } else {
                cout << "Llama a fib(" << n-2 << ") y a fib(";
                cout << n-1 << ") ..." << endl;
                return fib(n-2) + fib(n-1);
        }
}
Anuncios

Cuando se le asigna un valor a n y luego este es enviado a fib(), el mismo es procesado en el condicional en el caso de que que sea menor a 3 este automaticamente devuelve 1 pero de lo contrario empezara a ramificar a la funcion fib() para obtener un resultado en el cual sera solamente cuando llegue a fib(2) y fib(1) y una vez que llegue procedera a efectuar todas las sumas y finalmente devolverlo en respuesta, aca es como se veria en la salida:

tinchicus@dbn001vrt:~/programacion/c++$ ./program/funcion02
Escriba el numero a encontrar:6

Procesando Fib(6)… Llama a fib(4) y a fib(5) …
Procesando Fib(4)… Llama a fib(2) y a fib(3) …
Procesando Fib(2)… Regresa 1!
Procesando Fib(3)… Llama a fib(1) y a fib(2) …
Procesando Fib(1)… Regresa 1!
Procesando Fib(2)… Regresa 1!
Procesando Fib(5)… Llama a fib(3) y a fib(4) …
Procesando Fib(3)… Llama a fib(1) y a fib(2) …
Procesando Fib(1)… Regresa 1!
Procesando Fib(2)… Regresa 1!
Procesando Fib(4)… Llama a fib(2) y a fib(3) …
Procesando Fib(2)… Regresa 1!
Procesando Fib(3)… Llama a fib(1) y a fib(2) …
Procesando Fib(1)… Regresa 1!
Procesando Fib(2)… Regresa 1!
8 es el numero 6 en la serie de Fibonacci
tinchicus@dbn001vrt:~/programacion/c++$
Anuncios

Obviamente esto es util para averiguar un numero bajo pero a un numero mucho mas alto, por ejemplo 20, vamos a notar que le va a llevar mas tiempo y mas uso de memoria, recuerden que esto es solamente de ejemplo pero les recomiendo probar con numeros mayores para que vean como funciona. Ahora veamos otro ejemplo de funciones, en este caso de prototipo y con los 2 tipos de variables:

funcion03.cpp

# include <iostream>

using namespace std;

int Duplicador(int cantidadAduplicar);

int main()
{
        int resultado=0;
        int entrada;
        cout << "Escriba un valor entre 0 y 10000 para duplicarlo: ";
        cin >> entrada;
        cout << "\nAntes de llamar al duplicador....\n";
        cout << "Entrada: " << entrada << " duplicada: ";
        cout << resultado << endl;
        resultado = Duplicador(entrada);
        cout << "\nRegresando del duplicador...\n";
        cout << "Entrada: " << entrada << " duplicada: ";
        cout << resultado << endl;
        return 0;
}

int Duplicador(int original)
{
        if (original<=10000)
                return original * 2;
        else
                return -1;
}
Anuncios

Como se ve en el prototipo se declara una variable, que en realidad tanto al compilador como al lenguaje solo le interesa el tipo de variable, pero que despues no es utilizada y se podria haber hecho de la siguiente forma: 

int Duplicador(int); 
Anuncios

y tambien hubiera sido valido. Como ven, esto deja un poco mas ordenado porque se podria hacer el main() y luego detras todas las funciones que necesite para que podamos depurarlo mas rapido y esto tambien es practico en el caso de tener que agregar mas funciones al programa en si, en el cuerpo del main() primero definimos a resultado con el valor 0, luego pediremos que ingresen un valor para la variable entrada, observen como primero vamos a mostrar los valores de entrada y resultado, luego a resultado le asignaremos el valor obtenido por la funcion Duplicador() y le enviamos el valor en entrada:

 resultado = Duplicador(entrada);
Anuncios

En Duplicador(), recibira el valor pero observen como no es necesario que se llama igual a la variable de main() o del prototipo pero contendra el valor enviado de main(), esto es debido a que todas las variables son de tipo local y son para las funciones que son utilizadas, volviendo a Duplicador() luego chequeara si el valor de original es menor a 10000, en caso afirmativo procedera a efectuar la operacion y por medio de return devolvera el valor final de lo contrario devolvera el valor -1, con el valor devuelto y asignado a resultado mostramos nuevamente los valores y procedemos a salir del programa, si compilamos y probamos el programa la salida es como la siguiente:

tinchicus@dbn001vrt:~/programacion/c++$ ./program/funcion03
Escriba un valor entre 0 y 10000 para duplicarlo: 6

Antes de llamar al duplicador….
Entrada: 6 duplicada: 0

Regresando del duplicador…
Entrada: 6 duplicada: 12
tinchicus@dbn001vrt:~/programacion/c++$ ./program/funcion03
Escriba un valor entre 0 y 10000 para duplicarlo: 11000

Antes de llamar al duplicador….
Entrada: 11000 duplicada: 0

Regresando del duplicador…
Entrada: 11000 duplicada: -1
tinchicus@dbn001vrt:~/programacion/c++$

En este ejemplo probe los dos casos, primero hice un numero entre 0 y 10000 y luego hice otro por fuera del rango y observen como en todos los casos funciono sin inconvenientes.

Anuncios

En resumen, hoy hemos visto otras formas de funciones, hemos hablado de los prototipos, como se deben encadenar funciones, la sobrecarga de funciones, funciones en linea, recursion de las mismas, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00