Skip to main content

Funciones

Site: Facultad de Ingeniería U.Na.M.
Course: Computación ET-344
Book: Funciones
Printed by: Invitado
Date: Wednesday, 3 July 2024, 6:30 AM

1. Introducción

  • Las funciones son un conjunto de instrucciones que realizan una tarea específica.
  • En general reciben CERO o más valores de entrada, llamados parámetros y devuelven CERO o UN valor de salida o valor de retorno.

Durante la codificación de un programa aparecen secuencias de código que muchas veces se repiten en distintas partes del mismo.

La finalidad de utilizar funciones es agrupar esas secuencias, para poder reutilizarlas en otras partes, logrando reducir la cantidad de código repetido y minimizar el uso de memoria, al eliminar grupos de variables que realizan la misma función.

La ventaja de tener organizado el código en funciones, es que sólo es necesario verificar su correcto funcionamiento UNA vez, ya que en caso de no utilizarlas, el código que corresponde a la secuencia se debe revisar de nuevo en TODAS las ocurrencias en el programa, lo que conlleva tiempo y aumenta la posibilidad de introducir errores en el programa.


2. Generalidades

  • Al igual que con las variables, las funciones DEBEN declararse y definirse.
  • La declaración se realiza mediante el prototipo, y consiste indicar el nombre y los tipos de datos que utilizará la función (tipos de variables en los parámetros y cantidad de los mismos, y el tipo de variable de retorno).
  • La definición contiene las instrucciones que componen la función propiamente dicha.

3. Prototipos de funciones

  • El prototipo consiste en declarar la existencia de una función al compilador.
  • Consta del título de la función sin cuerpo y terminado con un ";".
La estructura de un prototipo es:

tipo nomb_func(lista de parámetros);

Ejemplos

int Mayor(int a, int b);
Sirve para indicar al compilador los tipos de retorno y los de los parámetros de una función, de modo que compruebe si son del tipo correcto cada vez que se use esta función dentro del programa.


int Mayor(int, int);
Los nombres de los parámetros son opcionales.

4. Definición de funciones

La definición consiste del código que compone la función. Usualmente se realiza LUEGO de la función "main()“, después del cierre de su última llave.

Ejemplo:

int Mayor(int a, int b)
{
if(a > b)
return a;
else
return b;
}

5. ¿Donde va Prototipo y Definición?

La estructura de un programa queda:


  • directivas del pre-procesador
    • #includes
    •  #defines
  • declaración de variables globales ( NO se recomienda USAR !!)
  • prototipos de funciones
  • función main()
  • definiciones de funciones


Prototipo :

  • Va al inicio , antes de main.
  • Finaliza con ":" la declaración del prototipo .
  • NO es necesario declarar el NOMBRE de los argumentos.
  • ES necesario declarar el TIPO de los argumentos,

Definición de la Función:

  • Va Luego de main.
  • Tiene el código fuente de la función que realiza la tarea.
  • DEBE tener el MISMO tipo de datos y ORDEN de datos que el prototipo.
  • Aqui ES NECESARIO dar nombre a las variables, si no, no se pueden invocar.
  • El orden de los argumentos IMPORTA, ya que se reciben por REFERENCIA.

Llamada  a la función.

  • Va donde se necesite invocar a la función.
  • Entre parentesis se ponen los Argumentos o parámetros de la función.
  • Si la función NO recibe argumentos se dice que es "void"


Caso especial:


#include <iostream>
using namespace std;
//Sección de declaración de Prototipos
void muestra_suma(void); //vemos que no recibe y no regresa nada
//aqui van la declaración de otros porptotipos si existen

//Inicio de Funciones, la primera es ; main
int main(int argc, char *argv[])
{
muestra_suma();
return 0;
}
// Sección de Funciones luego de main 
void muestra_suma(void)
{float a,b;
cout<<"Ingrese un numero: "<<endl;
cin>>a;
cout<<"Ingrese otro numero: "<<endl
;cin>>b;
cout<<"La suma es :"<<a+b;
//como no regresa nada NO va return!!
}
//aqui van si existen las otras definiciones de funciones

6. Llamadas a una función

  • “Llamar” una función implica ejecutarla.
  • La secuencia del programa continúa en el interior de la función, que se ejecuta secuencialmente, y cuando termina, se regresa a la instrucción siguiente al punto de llamada.
  • Las funciones a su vez, pueden invocar a otras funciones. (no existen restricciones de cuantas).
Ejemplo
mayor = Mayor(num1, num2);

7. Ámbito de las variables

  • Dependiendo dónde se declaren las variables podrán ser accesibles desde distintas partes del programa.
  • La declaración de las variables lleva asociado un ámbito, dentro del cual la variable es existe y es visible por parte de otros elementos del programa:
Global:
La variable es visible para todas las funciones del programa.
Local:
La variable es visible sólo dentro de la función. (Tiene prioridad sobre el ámbito global)

Ejemplo
int x,y;
int main()
{
float x,z; // Aquí x y z son reales.
// Aquí y es un entero.
}
//Aquí x e y son variables enteras
//La variable z no existe fuera de la función.

8. Consideraciones

  • Una función es un bloque de sentencias agrupadas bajo un nombre.
  • Toda función antes de ser utilizada tiene que ser declarada.
  • Una función puede tener 0, 1 o más parámetros.
  • Una función puede retornar 0 o 1 valor.
  • Debe existir una correspondencia entre el tipo y número de los argumentos de la llamada con los argumentos formales de la función.

9. Macros

Directivas del pre procesador 

Las directivas de preprocesador son líneas incluidas en el código de los programas precedidas por un signo de almohadilla (#).  Recordemos que #define, # include lo usan. Estas líneas no son declaraciones de programa, sino directivas para el preprocesador. 

El preprocesador examina el código antes de que comience la compilación real del código ( hace varias pasadas) y resuelve todas estas directivas antes de que cualquier código sea generado por declaraciones regulares.

Estas directivas de preprocesador se extienden solo a través de una única línea de código. 

Tan pronto como se encuentra un carácter de nueva línea, finaliza la directiva del preprocesador para esa línea y continúa con la próxima.

No se espera ningún punto y coma (;) al final de una directiva de preprocesador, por eso #define y #include no llevan ";" al final de las líneas.

La única forma en que una directiva de preprocesador puede extenderse a través de más de una línea es precediendo el carácter de nueva línea al final de la línea con una barra invertida (\).

Veamos un ejemplo de una función macro.



// function macro
#include <iostream>
using namespace std;

#define getmax(a,b) ((a)>(b)?(a):(b))

int main()
{
  int x=5, y;
  y= getmax(x,2);
  cout << y << endl;
  cout << getmax(7,x) << endl;
  return 0;
}
Vemos en este caso que el #define getmax, define una macro usando el operador ternario o condicional.  Una macro puede verse como una función y trabajar de la misma manera, pero las macros NO son usadas en tiempo de ejecución si no durante el preprocesamiento. Esto en algunas oportunidades puede arrojar resultados que no deseamos. Veamos algún ejemplo. 
El siguiente código utiliza la función rand() para generar números aleatorios. Si uso rand()%10 , esto me arroja los restos de números aleratorios divididos por 10, por lo tanto estos serán números: 0,1,2,3,4,5,6,7,8,9  => [0;9)

// function macro
#include <iostream>
//Esta macro regresa 5 o el otro argumento si es mayor a 5.
#define max(a,b) (a<b?b:a)
using namespace std;

//Muestra 20 números entre [5, 10)
int main()
{
  for (int i=0; i<20 ; i++)
  //rand()%10, genera números  [0;9)
  cout << max((rand()%10),5)<< endl;
  return 0;
}

Este código que utiliza una función macro para buscar el máximo valor entre un rango de [5,10)

5 5 5 9 2 5  9 6 6 6 8  5  5 0 3 5 5  5

 pero vemos que pese a que el código compila y corre .. la salida NO está bien, ya que claramente NO deberían aparecer números como el 0,1,2,...

Esto sucede por que el preprocesador REEMPLAZA LA MACRO en CADA línea donde aparece:

max((rand()%10),5)  por --->>>   (rand()%10,5) ? rand()%10

y esto es por que la macro se interpreta de la siguiente manera:

max((rand()%10),5)
{
if (rand()%10)<5)
    return 5
else
    return (rand()%10) 
}

Y aquí claramente podemos ver el error...en el else. Cuando llegue al else.. regresa  rand()%10 que puede ser menor a 5.


// function macro #include <iostream> using namespace std; int max(int,int); int main() { for (int i=0; i<20 ; i++) cout << max((rand()%10),5)<< endl; return 0; } int max(int a,int b) {return ((a)>(b)?(a):(b));}


Esta código si arrojaría los valores esperado. 





10. Acerca de namespace

Acerca de Namespace

Hasta el momento usamos al inicio de cada programa la línea:

using namespace std;

Vamos a tratar de justificar el por que de esta línea. Imaginemos que tenemos dos alumnos llamado "Juan Perez" en un curso, si queremos llamarlo, al mencionar el nombre se va a producir si duda una confusión. Para evitar esto imaginemos que creamos dos comisiones...y en cada una de ellas ubicamos al los alumnos "Juan Perez", en este último escenario no van a existir problemas. 

Esto se utiliza en C++ cuando los programas suelen ser MUY grandes y existe la posibilidad de que existan varias funciones, variables que tengan el mismo nombre y se consigue creando varios nombres de espacios.. veamos un ejemplo.

//Namespaces
#include <iostream>
namespace uno
{
void muestra() //Definición de la función en namespace uno
{std::cout<<"función de nombre muestra desde el espacio NS1"<<"\n";}
}
namespace dos
{
void muestra() //Definición de la función en namespace dos
{std::cout<<"función de nombre muestra desde el espacio NS2"<<"\n";}
}
long double factorial(int);
int main()
{ uno::muestra();
dos::muestra();
return 0;
}
Esto no es de uso frecuente en nuestro cursado, ya que los ejercicios son sencillos al punto de NO necesitarse.


11. Ejemplos

Ejemplo 1

#include <iostream>
using namespace std;
int Mayor(int a, int b); //Declaración de un prototipo
int main(){
   int num1, num2, mayor;
   cout << "ingrese primer numero: ";
   cin >> num1;
   cout << "ingrese segundo numero: ";
   cin >> num2;
   mayor = Mayor(num1,num2); //Llamada a la función
   cout << "El mayor es" << mayor;
   return (0);
}
int Mayor(int a, int b){ //Definición de la función
   if(a > b)
      return a;
   else
      return b;
}

Ejemplo 2

#include <iostream>
using namespace std;
float suma(float a, float b); //Prototipo
int main(){
   float s;
   s=suma( 1.8, 3.4 ); //LLamada
   cout << “La suma es" << s;
   return (0);
}

float suma(float a,float b){ //Definición
   float c;
   c=a+b;
   return (c);
}

Ejemplo 3

Escribir el código fuente de un programa que tenga una función llamada “primera” que reciba un numero entero y devuelva a “main()” el carácter “P” si el numero es positivo y “N” si es negativo.

#include<iostream>
using namespace std;
char primera(int num); /* en esta instrucción se realizan dos acciones:
-Se “llama” a la función primera y se le pasa el argumento numero.
-Se recibe el valor de retorno y se lo asigna a la variable tipo. */

int main(){
   int numero;
   char tipo;
   cout << "ingrese un numero entero: ";
   cin >> numero;
   tipo = primera(numero); /* en esta instrucción se realizan dos acciones:
      -Se “llama” a la función primera y se le pasa el argumento numero.
    -Se recibe el valor de retorno y se lo asigna a la variable tipo. */

   if (tipo=='P')
      cout << “el numero ingresado es positivo”;
   else if (tipo=='N')
      cout << “el numero ingresado es negativo”;
   else
      cout << “error”;
   return(0);
}

char primera(int N){ /*definición de la función primera*/
   if(N >= 0)
      return('P');  // la instrucción return es la que permite definir el valor de retorno de la función
   else
      return('N');
}

Podemos tener varios “return” definiendo mas de una salida de la función, pero solo se procesa la primera a la que llega el algoritmo, ya que return interrumpe la ejecución de la función y retorna a main(). En este caso la función primera posee solo una variable local: N.

Ejemplo 4

Escribir un programa que tenga una función denominada “factorial”, que recibe un numero N ingresado por teclado y calcula el factorial de N, mostrando el resultado en pantalla. La función “main()” debe verificar que el numero N ingresado sea mayor o igual a cero.
Observación: la función “factorial” no devuelve ningún valor.

El factorial de un número se define como: N!=1 x 2 x...x (N-1) x N
Ejemplo: 5! = 1 x 2 x 3 x 4 x 5 = 120

#include<iostream>
using namespace std;

void factorial (int N); /*prototipo de la función factorial, la palabra void delante
   de la función indica que esta no devuelve ningún valor*/

int main() {
   int numero;
   do{
      cout << "ingrese un numero para obtener su factorial: "<<endl;
      cin >> numero;
   } while(numero<0);
   factorial(numero);  /*llamado a la función factorial pasando el argumento numero*/
   return(0);
}
void factorial(int N) { /*definición de la función factorial*/
long int resul=1;
int i;
if(N==0)
cout <<"el factorial de 0 es: 1";
else if(N==1)
cout <<"el factorial de 1 es: 1";
else{
for(i=1;i<=N;i++)
resul=resul*i;
cout <<"el factorial de " << N << " es: "<< resul;
}
}

La función factorial no devuelve ningún valor, (no se utiliza el “return”). Nótese que se usan enteros largos, debido a los resultados que arroja un
cálculo del factorial.

Ejemplo 5

Escribir un programa que mediante una función “menu()” permita seleccionar si desea calcular una serie o salir del programa, cualquier otra tecla debe ser ignorada, y una vez mostrado el calculo de la serie se vuelve a presentar el menú al usuario. La función “serie” toma como argumento dos enteros a y b, y un flotante base, de modo que permita calcular el resultado de:

 {\displaystyle \sum_{k=a}^{k=b}base^{-k}}

El calculo es devuelto a main para su impresión en pantalla.

#include<iostream>
#include<cmath>
using namespace std;
float serie(int a, float base, int b); //prototipos de las funciones
char menu (void);

int main() {
   float resultado, base1;
   int inferior, b;
   char opcion;
   opcion = menu();
   while (opcion != 's') {
      cout << "ingrese el limite inferior de la sumatoria: ";
      cin >> inferior;
      cout << "ingrese el limite superior de la sumatoria: ";
      cin >> b;
      cin >> base1;
      resultado = serie(inferior, base1, b);
      cout << "el calculo de la serie es: " << resultado << endl << endl;
      opcion = menu();
   }
   cout << “el programa ha finalizado”;
   return(0);
}
char menu (void) {  //definición de la función menu.
char seleccion;
do{
cout << "Elija una opcion del menu:" << endl << "c - Calcula la serie" << endl << "s – Salir";
cin >> seleccion;
} while(seleccion != 's' && seleccion != 'c');
return (seleccion);
}
float serie(int a, float base, int b) {   //definición de la función serie.
float sumatoria = 0;
int i;
for(i=a; i<=b; i++)
sumatoria = sumatoria + pow (base, -i)
return (sumatoria);
}

12. Ejercicios sencillos

Ejercicio 1

Escribir el código fuente de un programa que desde main se llame a una función que recibe como argumento dos números reales, y retorna el menor que es mostrado desde main.

Ejercicio 2

Crear un código fuente que permita al usuario ingresar un numero del 1 al 10 inclusive, y una vez ingresado el numero se llame a una función denominada “tabla” que recibe el numero desde main y calcula-muestra la tabla de multiplicar del numero ingresado.
Observaciones: cuando el usuario ingresa el numero se debe verificar que se encuentre dentro del intervalo [1,10]; sino se debe pedir que se ingrese un nuevo valor.

Ejercicio 3
Escribir un programa que posibilite el ingreso de dos números enteros, X e Y, y calcule mediante una función “potencia”, X elevado al numero Y. La función potencia realiza el calculo por multiplicaciones sucesivas y retorna el valor del resultado.

Ejercicio 4

Modificar el programa del ejemplo 5 para que la potencia base−k se calcule utilizando multiplicaciones sucesivas y NO utilizando la función pow(). Para ello dentro de la función serie() se deberá llamar a una función adicional llamada potencia() que se tiene que definir adecuadamente, calcule la potencia por multiplicaciones sucesivas y retorne el resultado a serie() para computar la sumatoria.

Ejercicio 5

Realizar un programa que permita el ingreso de un número entero positivo N y pase como argumento ese número a una función denominada “serie”. La función serie calcula el resultado de: N+(N-1)+…+2+1. El resultado de la serie debe ser devuelto a “main” para su impresión en pantalla.

Ejercicio 6

Realizar un programa que mediante un menú permita llamar a dos funciones distintas, una llamada “potencia” y otra denominada “multiplicación”.
La función potencia no recibe ningún argumento y devuelve el valor de la potencia de dos números (el ingreso de los dos números se hace dentro de la función potencia.)
La función multiplicación recibe dos argumentos y no devuelve nada, mostrando el resultado antes de salir de la función.
El menú es otra función que no recibe nada y entrega el valor del menú.

Ejercicio 7

Escribir el código fuente de un programa que desde main se llame a una función pasando un argumento, esta función calcula la serie de Fibonacci y retorna la suma de los términos que son mostrado desde main.

Ejercicio 8

Escribir el código fuente de un programa que desde main se llame a una función menú que no reciba ningún argumento y que retorne la opción de menú elegida , esa se mostrará desde main. Los items del menú deberían ser por ej. 1,2,3 y s para salir, o A,B y F para Finalizar.-
Controlar que solo se salga con la opción indicada.

Ejercicio 9

Realizar un programa que mediante una función menú permita llamar a 6 funciones distintas, una llamada suma, resta, multiplicación, división, potencia y raíz cuadrada.
Al principio se ingresan por teclado 2 números, en las variables A y B, luego se presenta un menú y se realizan la operación elegida.
La función suma recibe como argumentos los 2 números y devuelve el valor de A+B.
La función resta recibe como argumentos los 2 números y devuelve el valor de A-B.
La función producto recibe como argumentos los 2 números y devuelve el valor de A x B.
La función división recibe como argumentos los 2 números y devuelve el valor del cociente de A y B. Se debe chequear dentro de la función cuando B=0, en caso de serlo, se deberá mostrar un mensaje de error y abortar la operación.
La función potencia recibe como argumentos los 2 números y devuelve el valor de la potencia  A^B .
La función raíz cuadrada recibe como argumentos un números y devuelve el valor de  \sqrt{A} . Se debe chequear que A sea positivo para poder realizar la raíz.
Observación: tener en cuenta el tipo de variable que retornan las funciones, y en que casos no pueden tomar valores nulos o negativos, por ejemplo: raíz de un numero negativo, o una división por cero. Para la raíz se puede utilizar la función sqrt(), que se encuentra en la librería “cmath”.