Sunteți pe pagina 1din 13

Lenguaje C++

Funciones 5
05.01 Introducción
Inicialmente los lenguajes de programación permitían que la lógica de los programas salte libremente de una a otra parte, a tal punto que
se le llamó programación espagueti, esto complicaba la lógica. Para superar este problema se desarrolló la programación
estructurada, que solo tiene las 3 primitivas lógicas, que acabamos de aprender:
1) Programación secuencial,
2) Estructuras de decisión,
3) Estructuras de repetición.

Se demuestra que aplicando estas 3 primitivas de programación se puede escribir cualquier programa: GENIAL!!! esto simplifica mucho;
pero aún tenemos efectos colaterales para programar en modo profesional: los anidamientos múltiples complican la lógica; los bloques
de instrucciones no son re-utilizables en situaciones similares y hay que repetir el código, por lo que los programas se hacen extensos;
no se agrupa con precisión bloques de instrucciones que ejecutan una tarea específica. Para resolver estas dificultades se desarrollaron
las funciones, veamos una panorámica que nos ubica, utilicemos una función muy sencilla, suma():
Atento:
Un programa compila de inicio a fin, línea 01 a la 16, de izquierda a derecha: si se usa una variable o función no definida
previamente reporta error de compilación.
La ejecución de un programa sigue un orden distinto al de la compilación; inicia al comenzar la main() -línea 08- y termina al
finalizar la main() -línea 16; las otras líneas se ejecutan solo si son llamadas desde la main(), la función suma() -líneas 03 a la
06- se ejecuta 6 veces por que es llamada en las líneas 10, 11, 12, 13, 14 y 15.
01 #include<cstdio>
02 // Definición de la función suma()
03 int suma(int m, int n){ // recibe valores y los aloja en las variables int m y n y retorna un valor int.
04 printf("suma: %d + %d = %d\n", m, n, m+n);
05 return m+n; // retorna el valor int m+n
06 }
07 // Definición de la main():
08 main(){
09 int m=3, n=2, k;
10 k = suma(2, 1+4); // llama y envía los valores 2 y 5 y k recibe 7
11 suma(m, n); // llama y envía los valores 3 y 2 y no utiliza el valor de retorno
12 suma(m, n*2); // llama y envía los valores 3 y 4 y no utiliza el valor de retorno
13 suma(4, m+1); // llama y envía los valores 4 y 4
14 suma(k, 2*3); // llama y envía los valores 7 y 6
15 printf("Final : %d + %d = %d\n", 2,1, suma(2,1)); // suma(2,1) retorna int 3
16 }
La salida es:
suma: 2 + 5 = 7
suma: 3 + 2 = 5
suma: 3 + 4 = 7
suma: 4 + 4 = 8
suma: 7 + 6 = 13
suma: 2 + 1 = 3
Final : 2 + 1 = 3

05.02 Definición de Función


Una función es un bloque de instrucciones que tiene un nombre, una entrada, ejecuta una tarea, y retorna una salida:

Sintaxis:
tipoSalida miFun(tipo1 var1, tipo2 var2, …) { … }

Salida Nombre Entradas Tarea


el nombre miFun, cumple las mismas reglas que el nombre de una variable.
Entradas: pueden tener 0 ó más variables var1, var2, ... de tipo1, tipo2, … respectivamente.
A las variables se les llama parámetros
Salida (retorno): Solo puede retornar 0 ó 1 valor de tipoSalida
Notas:
• Para indicar que no hay entradas o salida se usa void:
void miFun(void) { …}
• Si se requiere un solo valor de salida,se describe el tipo de salida, por ejemplo:
int miFun(…) // la salida es de tipo int

PÁGINA: 1
Lenguaje C++
• Para tener más de un valor de salida, vea el capítulo de apuntadores.
Ejemplo:
float cenAFar(float cen) { // convierte grados Centigrados a Farenheith
return cen * 1.8 + 32; // retorna un valor de tipo float especificado al definir la función
}
Función : cenAFar, convierte grados Centigrados a Fahrenheit
Entrada : un valor de tipo flotante que es asignado a la variable cen.
Salida : retorna el valor de tipo flotante: cen * 1.8 + 32

Llamando a una función


Una función no hace nada por si sola; para ejecutarla debe ser invocada (llamada), una o más veces desde otras funciones.
Dada una función genérica:
tipoSal miFun(tipo1 var1, tipo2 var2, …) {…}

Para llamarla, se puede usar una de las dos sintaxis:


miFun(exp1, exp2, ...); // donde el valor de exp1 debe ser de tipo1, el de exp2 de tipo2, …
// a los valores de exp1, exp2, … se les llama argumentos
Y = miFun(exp1, exp2, ...); // Y debe ser de tipoSal

Regla: El número, tipo y orden de los argumentos debe ser igual al número, tipo y orden de parámetros respectivamente:
Definición de la función Llamando a la función

float miFun(int n, float x, ..) {….} y = miFun(exp1, exp2, ...);

Ejemplo:
float miFun(int n, float x, ...) {….} // n, x, … son los parámetros. La salida de tipo float
...
miFun(2, 4.3, ...); // los argumentos 2, 4.3 … de tipo int y float respectivamente son asignados a n y x
Tambien se puede llamar:
Y = miFun(2+1, 4.3*z, ...); // Y debe ser de tipo float
Tenga en cuenta que al llamar a una función:
en el paso de argumentos a parámetros y al retornar valor de una función llamada
se aplica casting automático de ser necesario, lo cual puede producir los errores lógicos descritos en el capítulo de Programación
Secuencial.

Ejemplo:
int n = 4;
float t = 20, x;
Definición de función Llamadas válidas Llamadas no válidas
float cenAFar(float cen){ x = cenAFar(t); x = cenAFar(); // falta argumento
return cen * 1.8 + 32; x = cenAFar(20); x = cenAFar(3, 4); // demasiados argumentos
} x = cenAFar(10+10); printf("%d\n", cenAFar(10));
cenAFar(10+10); // el formato es int y cenAFar retorna float
cenAFar(2*n);
printf("%.2f\n", cenAFar(10));
cenAFar(otraFun()); // otraFun()
retorna float

Lo ideal es mantener el tipo de dato en las entradas y la salida:


Programa Entrada Salida
Los números 1, 2, 3 y 4 indican el flujo de ejecución del programa
#include<cstdio>
float cenAFar(float cen){ 3: el parámetro cen es tipo float
return cen * 1.8 + 32;
}
main(){
float t = 36; 1: t es float
printf("Grados Fahrenheit = %.2f\n", cenAFar(t)); 2: el argumento t= 36 es float 4: El retorno float de cenAFar()
} se imprime con formato %.2f

PÁGINA: 2
Lenguaje C++
A parte de la correspondencia de tipos en las entradas y la salida; una función es independiente (encapsulada) en su interior:
1) Desde cenAFar() no podemos acceder a la variable t en la main(), y viceversa, desde la main() no podemos acceder a la variable
cen de cenAfar().
2) Los nombres de las variables son independientes, por ejemplo, podemos programar:
float cenAFar(float t){ // la t de cenAFar( ) es independiente de la t de la main(), simplemente son tocayas.
return t * 1.8 + 32;
}
Muchas veces se usa el mismo nombre de variables en diferentes funciones para mantener la mnemonía, por ejemplo t representa
temperatura dentro de varias funciones, pero la t de una función no tiene ninguna relación con la t de las otras funciones.
3) Las variables globales son vistas desde todas las funciones.

Ejemplos de funciones:
Función que no hace nada:
void nada(void){ }
main(){
nada();
}

Función que hace mucho:


int mucho(int i, float f, char c){
… // hace mucho
return 3+2;
}
main(){
int n;
n = mucho(1, 3.4. 'a' );
}

Leer un entero positivo:


int leerPositivo(void) {
int n;
do {
printf("Ingrese un entero positivo: ");
scanf("%d", &n);
while(n<=0);
return n;
}
Su descripción es:
Componente Descripción
función LeerPositivo: Lee un entero > 0
Entradas ninguna
Salida Retorna el valor leído

Ejemplo:
Sintaxis : int printf("format", exp1, exp2, …);
Descripción: Imprime una lista de expresiones
Entradas: format: formato para escribir las expresiones
exp1, exp2, … : lista de expresiones a imprimir
Salida: Imprime en el monitor y retorna el número de caracteres escritos.
Ejemplo:
int n, var = 12;
n = printf("\nvar = %d", var); // imprime: var = 12; se imprimen 8 caracteres → n = 8.
printf("\nNúmero caracteres impresos = %d", n);
Salida:
var = 12
Número caracteres impresos = 8

Llamando a printf( ) y scanf( ):


int a;
float b;
scanf("%d %f" , &a, &b); // tipee: 12 5.621<enter>
printf("a = %d, b = %.2f\n", a, b); // compare la sintaxis de las dos funciones
PÁGINA: 3
Lenguaje C++
Salida:
a = 12, b = 5.62

05.03 Sobrecarga de Funciones


Hemos establecido la regla:
El número, tipo y orden de los argumentos debe ser igual al número, tipo y orden de parámetros respectivamente.
Cumpliremos la regla; pero podemos definir varias funciones con el mismo nombre y diferentes: Número y/o tipo de parámetros; por
ejemplo:
// área de rectángulo y cuadrado
float area(float largo, float ancho){return largo*ancho;} // definición: área de un rectángulo
float area(float largo) {return largo*largo;} // definición: área de un cuadrado

x = area(2,4); // llama a área de rectángulo
y = area(2); // llamada a área de cuadrado

a esto se llama sobrecargar la función. Al llamar a una función, el compilador determina a cual función llamar según el procedimiento:
1) Busca la coincidencia exacta entre los tipos y número de valores de argumentos y parámetros; si no, sigue a 2.
2) Se hace la promoción integral de C++ de tipos de datos:
char → int
float → double etc.
se busca la coincidencia; si no, sigue a 3.
3) Se hace la promoción built-in de C++ de asignación a los parámetros:
Si una promoción coincide con dos definiciones ejemplo, si se define:
long area(long n);
double area( double n);
y se llama:
area(2);
la cual coincide con las dos definiciones, se producirá un error debido a la anbiguedad para escoger la función llamada. Si no hay
coincidencia, sigue a 4.
4) Se hace la promoción de tipos definidos por el usuario, esto se verá al definir objetos de clases.

05.04 Estructura de un Programa Complejo


Imagine un unidad de trabajadores en la vida real con un jefe y dos subordinados: juan y jose, un programa funciona de modo similar,
reemplazando personas por funciones: el jefe es la main(), juan() y jose() son funciones.

Escritura y compilación
1) Se lee y compila de arriba hacia abajo y de izquierda a derecha.
2) Primero se define una variable o función y luego se utiliza en cualquier parte.
3) El rango de visibilidad de una variable o función inicia en el lugar de su definición y termina al final del bloque que la contiene.

Ejemplo de programa que contiene todas las componentes:


#include<miLibrería> // incluye el archivo miLibrería que contiene funciones a ser usadas
...
#define PI 3.1416 // Define constantes de dos modos, su rango inicia acá y termina al final del programa
const float E = 2.7172;
...
int miGlobal = 4; // define variables globales, cuyo rango de visibilidad es todo el programa
...
tipo fun1(….) { … } // define funciones, su rango inicia acá y termina al final del programa
tipo fun2(….) { … }

PÁGINA: 4
Lenguaje C++
fun1, fun2, … se llaman entre sí, y suelen formar una red como:

El diagrama anterior facilita la compresión de la lógica a los desarrolladores; pero al momento de programar, las funciones se deben
definir de abajo para arriba, para que no hayan errores de compilación:
#include<cstdio>
int fun12(...){...}
float funAB(.. ){..... }
char fun21(.. ){...}
void fun1(.. ){...}
int fun2(.. ){...}
main(){
….
}
Esto dificulta la comprensión del programa; para facilitar se introduce el concepto de:
prototipo de función el cual indica los tipos de entrada y el tipo de salida de la función que se definirá más abajo. Se escribe al inicio:
#include<cstdio>
void fun1(int, float, ... ); // prototipo de fun1 : observe el final con ;
int fun2(... ); // prototipo de fun2 : observe el final con ;
int fun12(... ); // prototipo de fun12 : observe el final con ;
float funAB(.. ); // prototipo de funAB : observe el final con ;
char fun21(... ); // prototipo de fun21 : observe el final con ;
main(){

fun2(... ); // llamando a fun2()

}
void fun1(int n, float x, …) {…} // define a fun1()
int fun2(.. ){…} // define a fun2()
int fun12(.. ){…} // define a fun12()
float funAB(.. ){..... } // define a funAB()
char fun21(.. ){...} // define a fun21()

Los prototipos deben indicar los tipos de datos; opcionalmente, pueden indicar nombres de variables, solo como referencia:
Definición de función Prototipos válidos Prototipos no válidos
int miFun(float x, int m){…} int miFun(float x, int m); // el más usado float miFun(float y, int n);
int miFun(float m, int x); int miFun(int y, int n);
int miFun(float, int); int miFun(int, float);

Finalmente, la correspondencia de tipos de datos dentro de un programa será:


Programa Entradas Salida
Los números 1, 2, 3a, 3b, 4a, 4b y 5 indican el flujo de ejecución
#include<cstdio>
float cenAFar(float cen); // prototipo 3a: el parámetro cen es tipo float 4a: retorno es float
main(){
float t = 36; 1: t es float
printf("Grados Fahrenheit = %.2f\n", cenAFar(t)); 2: el argumento t= 36 es float 5: El retorno es float = cenAFar(t)
} // se imprime con formato %.2f
float cenAFar(float cen){ 3b: el parámetro cen es float 4b: retorno es float
return cen * 1.8 + 32;
}

Ejecución de un programa
• Un programa inicia su proceso en la main(), sin importar donde esté ubicada: al inicio, al final o al medio.
• El programa termina al finalizar el bloque de la main().
PÁGINA: 5
Lenguaje C++
• En tiempo de ejecución: las variables de la main() son alojadas en la Random Acces Memory (RAM: memoria de acceso aleatorio) y
se desalojan al terminar la ejecución; las variables de las otras funciones son alojadas cada vea que son llamadas y se desalojan
inmediatamente al terminar su ejecución, para ahorrar memoria. Por lo tanto la main() sa aloja una sola vez, las otras funciones se
pueden alojar y desalojar varias veces, son volátiles.

ATENCION, ATENCION, Gran cambio de mentalidad: Hasta este momento, el uso de funciones puede parecer artificioso, trabajoso y
confuso; sin embargo nos da orden, independencia, división del trabajo, facilita el mantenimiento, parametrización (una función se
ejecuta para cualquier valor de los argumentos), y en muchos casos simplifica la lógica dentro de las funciones. De acá en adelante
usaremos funciones casi siempre.

// 05_01.c : Leer dos números m. n > 0 y divídir m/n


#include<cstdio>
// prototipos
int leerNumero(void); // 4) prototipo
float dividir(int m, int n); // 4) prototipo

// funciones
main(){
int m, n; // 1) Definir variables
m = leerNumero(); // 2) llama a leerNumero: no envía valor, recibe valor int
n = leerNumero(); // 2) llama a leerNumero
printf("m = %d, n = %d, m/n = %.2f\n",m, n, dividir(m, n)); //
}
int leerNumero(void){ // 3) Definir función: Entrada: no hay; salida: valor int
int n=0;
do {
printf("Ingrese un entero positivo: ");
scanf("%d", &n);
} while(n<=0);
return n;
}
float dividir(int m, int n){ // 3) Definir función: Entrada, salida
return m/(float)n;
}
Salida:
Ingrese un número positivo: 3
Ingrese un número positivo: 2
m = 3; n = 2; m/n = 1.50

2 Ejemplos del cambio de paradigma de programación a funciones

Ejemplo 1: Lea un entero m >= 2, imprima los primos menores o iguales a m.


Vamos a programar el mismo algoritmo de números primos en 2 contextos. Observe cuidadosamente los cambios:
//05_02a.c: Sin usar funciones //05_02b.c: Utilizando funciones
#include<cstdio> #include<cstdio>
int primo(int n);
main(){ main(){
int m, n, primo, i; int m, n;
printf("Ingrese un número > 1: "); printf("Ingrese un número > 1: ");
scanf("%d", &m); scanf("%d", &m);
for(n = 2; n<= m; n++){ for(n = 2; n<= m; n++)
primo = 1; // algoritmo para número primo
i = 2;
while(i*i <= n && primo) if(n%i++==0) primo=0;
if(primo) printf("%d es primo\n", n); if(primo(n)) printf("%d es primo\n", n);
else printf("%d no es primo\n", n); else printf("%d no es primo\n", n);
} }
} int primo(int n){ // algoritmo primo
int i=2; // algoritmo para número primo
while(i*i <= n) if(n%i++==0) return 0;
return 1;
}
El programa es más complejo: Contiene la lógica general y El programa es más simple: Contiene la lógica general y
PÁGINA: 6
Lenguaje C++
los algoritmos llama a las funciones (algoritmos)
El algoritmo no es reusable: Definido dentro del programa Una función es reusable: puede ser llamada de otras
general, no puede ser llamado de otras partes. partes.
La comunicación parece más simple La comunicación parece más compleja

Ejemplo 2: El programa para ejecutar las 4 operaciones aritméticas ya fue presentado, a diferentes niveles, en los tres capítulos
anteriores, ahora vamos a completarlo profesionalmente. Escriba un programa que lea dos enteros m > 0 y n > 0, y presente el menú:
Operación que requiere:
1) Sumar: m + n
2) Restar: m – n
3) Multiplicar: m * n
4) Dividir: m/n
5) Salir
Elija su opción: _
Ejecute la opción seleccionada, repita el proceso y salga (termine) con la opción 5.

Requerimientos:
Valide que la opción esté entre 1 y 5 // Use do.
Repita la operación completa hasta que se elija 5. // Use do.
Use funciones // prototipo, definición y llamar
Para ejecutar la operación seleccionada, use switch.

Análisis (Qué hacer): ya lo sabemos


Matriz de casos de prueba: ya la sabemos

Diseño (Cómo hacer):


Diagrama de funciones
main

leerEntero operaciones

menu suma ...


Definición de funciones
main( ): Ejecuta el control general del programa.
leerEntero( ): lee un número entero y retorna el valor leído.
operaciones( ): controla el flujo de ejecución repetitiva de las 4 operaciones.
menu(): despliega el menú y retorna la opción seleccionada.
suma(): recibe 2 números, los suma e imprime.

Programa:
// 05_03.c : 4 operaciones
#include<cstdio>
// prototipos
int leerEntero(void);
void operaciones(int m, int n);
int menu(void);
void suma(int m, int n);
void resta(int m, int n);
void multiplicacion(int m, int n);
void division(int m, int n);

main(){ // main() solo ejecuta funciones de control


int m, n;
m = leerEntero();
n = leerEntero();
operaciones(m, n);
}

int leerEntero(void){
int m;
PÁGINA: 7
Lenguaje C++
printf("Ingrese un entero > 0: ");
scanf("%d",&m);
return m;
}
void operaciones(int m, int n){
int op; // op = opción
do { // Repetición de operación completa hasta que se elija 5.
op = menu();
switch(op){ // Ejecute de operación seleccionada.
case 1: suma(m,n); break;
case 2: resta(m,n); break;
case 3: multiplicacion(m,n); break;
case 4: division(m,n); break;
default: printf("Gracias por su visita\n");
}
} while(op!=5);
}
int menu(void){
int op;
printf("\nOperación que requiere:\n");
printf("1) Sumar: m + n\n");
printf("2) Restar: m – n\n");
printf("3) Multiplicar: m * n\n");
printf("4) Dividir: m/n\n");
printf("5) Salir:\n");
do { // Valida la opción entre 1 y 5
printf("Elija su opción: "); scanf("%d",&op);
} while (op<1 || op > 5);
return op;
}
void suma(int m, int n) {printf("suma = %d\n", m+n);}
void resta(int m, int n) {printf("resta = %d\n", m-n);}
void multiplicacion(int m, int n) {printf("multiplicación = %d\n", m*n);}
void division(int m, int n) {
if(n==0) printf("No se puede dividir, divisor = 0");
else printf("división = %.2f\n", (float)m/n);
}

05.05 Paso de Argumentos de Tipo Función


Esta capacidad da mayor flexibilidad a la parametrización, ejemplo:
// 05_04.c : Paso de argumento de tipo función
#include<cstdio>
void suma (int m, int n);
void resta(int m, int n);
void por (int m, int n);
void div (int m, int n);
void operaciones(int m, int n, void f(int m, int n));
main(){
int m= 3, n =2;
operaciones(m, n, suma); // Se pasa una función como argumento
operaciones(m, n, resta);
operaciones(m, n, por);
operaciones(m, n, div);
}
void operaciones(int m, int n, void f(int m, int n)){f(m, n);}
void suma (int m, int n){printf("%d + %d = %d\n", m, n, m+n);}
void resta (int m, int n){printf("%d - %d = %d\n", m, n, m-n);}
void por (int m, int n){printf("%d * %d = %d\n", m, n, m*n);}
void div (int m, int n){
if(n==0) printf("No se puede dividir entre 0\n");
else if(m%n==0) printf("%d / %d = %d\n", m, n, m/n);
else printf("%d / %d = %f\n", m, n, (float)m/n);

PÁGINA: 8
Lenguaje C++
}
Salida:
3+2=5
3-2=1
3*2=6
3 / 2 = 1.500000

05.06 Función en Línea


En tiempo del ejecución, al llamar a una función se consume tiempo: cargándola en la RAM, pasando argumentos recibiendo el resultado
y descargandola de la RAM; si la función es pequeña y es llamada muchas veces, este consumo de tiempo puede ser significativo; para
mejorar el desempeño se define una función en línea:
inline tipo miFun(…); // prototipo

n = miFun(4); // llamada
...
inline tipo miFun(…) {….} // definición
en este caso miFun() no es procesada como función: en tiempo de compilación, el código de la función es desplegado dentro de la
función que llama. La petición inline es un requerimiento NO un comando, el compilador analiza el caso y decide finalmente si la hace
en línea o no; no la definirá en línea si el código:
• Contiene un bucle, switch o goto, para funciones que retornan valor.
• Contiene variables static.
• Es función recursiva.
Ejemplo:
inline double cuarta( double a) {return a*a*a*a;} // eleva a la cuarta.

05.07 Función Recursiva


Un programa puede contener varias funciones, las cuales suelen tener una estructura casi jerárquica:

Se podría tener una red muy grande y compleja de funciones que formarían bucles (loops), lo cual sería muy complejo de resolver en
tiempo de ejecución, por lo que debe evitarse, en lo posible. También se puede tener funciones que que se llaman a sí mismas
(recursivas), por ejemplo fun21() es llamada por fun2() y también se auto-llama.

Notas
 La recursividad es una forma particular de repetición, generalmente implanta una repetición o una inducción matemática al revés,
ejemplo: sumar los n primeros números enteros a partir de 1:
Foŕmula Repetición Inducción
Suma = [n*(n+1)]/2 Suma = 1 + 2 + … + n Suma = n + (n-1) + .. + 1
 La función debe terminar en algún momento: No auto-llamarse más, e iniciar el proceso de cierre de auto-llamadas.
 Muchas veces se resuelven fácilmente procesos de repetición complejos; pero no siempre es recomendable usarla porque cada
vez que se auto-llama, la función ocupa un espacio adicional en memoria y esto puede superar el espacio disponible.

// 05_05.c : Calcular la suma de los n primeros números enteros de tres formas distintas
#include<cstdio>
int sumar(int n){
if(n==1) return 1; // fin de función, no se auto-llama
return n + sumar(n-1);
}
main(){ main(){ main(){
int n = 5; int n = 5, i, suma; int n = 5;
suma = 0;
PÁGINA: 9
Lenguaje C++
suma = n*(n+1)/2; for(i=1; i<n; i++) suma = += i; suma = sumar(n);
printf("La suma de los %d primeros enteros es: %d\n", n, suma);
}
Salida:
La suma de los 5 primeros enteros es: 15

La función sumar() se ejecuta en dos tiempos:


1 2
n sumar(n) Cierre de sumar()
5 5 + sumar(4) 5 + 10 = 15
4 4 + sumar(3) 4 + 6 = 10
3 3 + sumar(2) 3+3=6
2 2 + sumar(1) 2+1=3
1 1 1

Estrategia para programar funciones recursivas


Observe la función recursiva sumar() anterior:
int sumar(int n){
if(n == 1) return 1; // 1) Poner la condiciones de fin de recursividad al inicio
return n + sumar(n-1); // 2) Poner las autollamadas al final
}
/* 05_06.c : Programar dos funciones recursivas con estructuras similares:
1) Hallar el máximo común divisor de dos enteros positivos m y n utilizando el método de Euclides.
2) Hallar el factorial de m.
*/
#include<cstdio>
int mcd(int m, int n);
int fac(int m);
main(){
int m=22, n=4, temp;
printf("Ingrese dos números enteros mayores que cero: "); scanf("%d %d", &m, &n);
printf("El factorial de %d es: %d\n", m, fac(m)); // atento si m es grande se produce un overflow de fac()
if(m<n){ // primer número >= segundo número
temp = m;
m = n;
n = temp;
}
printf("El mcd de %d y %d es: %d\n", m, n, mcd(m,n));
}
int mcd(int m, int n){
if(m%n==0) return n; // sale de la función
mcd(n,m%n);
}
int fac(int m){
if(m==1) return 1;
return m*fac(m-1);
}

Observe que la estructura de las dos funciones es similar, ¿Por qué una función recursiva fac( ) tiene return y mcd( ) no?
Sugerencia:
1) Compare las definiciones de mcd y factorial.
2) Compare los ciclos recursivos:
m n r mcd(m, n) Cierre mcd() n fact(n) Cierre de Fact()
22 4 2 4 4 * fact(3) 4* 6= 24
4 2 0 3 3 * fact(2) 3 * 2 = 6
4 2 0 2 2 2 2 *fact(1) 2 * 1 = 2
1 1 1

PÁGINA: 10
Lenguaje C++

Confirma tu poder:
/* 05_07.c : Verificar si un número n es primo o perfecto (n es perfecto,
si n = suma de sus divisores, ejemplo: 6 = 1 + 2 + 3; 28 también lo es)
*/
#include<cstdio>
int primo(int n){
int i=2;
while(i*i <= n) if(n%i++==0) return 0;
return 1;
}

int perfecto(int n){


int i, suma = 1;
for (i=2;i<=n/2; i++) if(n%i==0) suma += i;
if(suma==n) return 1;
return 0;
}

main(){
int n, i=2;
printf("Ingrese un entero > 0: ");
scanf("%d", &n);

if(primo(n)) printf("%d es primo\n", n);


else printf("%d no es primo\n", n);
if(perfecto(n)) printf("%d es perfecto\n", n);
else printf("%d no es perfecto\n", n);
}

Matriz de Pruebas
Descripción Entrada Salida Chequeo
1 Valor inicial 1 1 es primo 1 es perfecto √
2 Valor inicial 2 2 es primo 2 no es perfecto √
3 Valor medio 3 3 es primo 3 no es perfecto √
4 Valor medio 5 5 es primo 5 no es perfecto √
5 Valor significativo 6 6 no es primo 6 es perfecto √
6 Valor significativo 28 28 no es primo 28 es perfecto √
7 Valor mayor 29 29 es primo 29 no es perfecto √
8 Valor mayor 30 30 no es primo 30 no es perfecto √

¡Perfecto, Admírate!:
¡Qué fácil! : Fíjate en los return de las funciones.
¡Qué óptimo!: Fíjate el uso de las repeticiones:
Para primo() : while(i<n && i*i <= n) if(n%i++==0) return 0;
Para perfecto(): for (i=2;i<=n/2; i++) if(n%i==0) suma += i;
Aunque la máquina es rapídisima y no protesta; en ambos casos, no hicimos ni un cálculo demás.
¡Qué claro! : Fíjate en la main(), solo ordena; y las funciones solo ejecutan, y no hay chismes (corrupción de información): Lo que
está en la main(), se queda en la main; lo que está en una función se queda en la función; solo se comunica lo indispensable.
¡Qué ingenioso!: Fíjate como se manejaron las estructuras repetitivas. Pronto serás diestro en eso.
¡Qué bien probado!: mmm; eso no es verdad; está comprobado para 8 valores; pero eso no significa que esté probado para todos
los valores; pero se probó para los puntos críticos y eso es un buen indicador.

Las reglas aprendidas en este mundo virtual, también se aplican en el mundo real, por ejemplo, haga la sinonimia:
Mundo Virtual Mundo Real
Funciones Personas
Programas, sistemas Actividades, tareas

PÁGINA: 11
Lenguaje C++
Ya conoce con precisión el fundamento, para integrar en el mundo virtual; lo mismo funciona en el mundo real, además debe añadir el
sentimiento y la acción de las personas.

Ubícate: Ya no eres un minino en computación:

Fuente: https://www.google.com.pe/url

¡Felicitaciones! Ya no dices miau y se te ve muy bien.


A la pinta se le suele dar más valor del que debiera y lo sabes bien; por eso no se te suben los humos, ni aunque en el espejo
apareciera Einstein: Tú eres tú.

Atent@: Tu mamá le contará a todo el mundo: ¡Mi niñ@ es tod@ un@ profesional de la computación!
Espero que tengas a la mamá; ella tiene algo de razón. Hemos avanzado bastante en la teoría, luego manejaremos tipos de datos más
complejos y útiles.

05.08 Preguntas de Teoría


1) ¿Qué es una función y cuál es su sintaxis?
2) ¿Qué se pasa como argumentos al llamar a una función, y en qué los aloja al recibirlos?
3) ¿Cómo contribuyen las funciones a simplificar y a gestionar un programa complejo?, ¿qué dificultad genera el uso de funciones?
4) ¿Qué hacer para superar la dificultad de que una función solo puede retornar 0 o 1 valor?
5) Esbozar un programa que tiene una función, con y sin prototipo.
6) ¿Cuál es la secuencia de un programa en tiempo de compilación y de ejecución?
7) ¿Cómo se carga en la RAM la main() y las otras funciones en tiempo de ejecución?
8) Al recibir y al retornar valores de una función se debe mantener el mismo tipo de los valores, ¿cuál es el flujo que garantiza dicho
mantenimiento?
9) En el código:
int m=2, mm[] = {1, 2, 3}, n;
n = miFun(m, mm);

int miFun(int m, int mm[ ]) {return 2+2;}
¿qué se pasa a miFun() en el primer y segundo argumento; y que retorna?
10) En tiempo de ejecución, ¿Cuántas veces se carga en la RAM una función recursiva, y cuántas veces la main()?

05.09 Ejercicios de Programación


Escriba, compile y ejecute los programas.

1) Ingresar un entero positivo, imprima todos los primos menores o iguales al mismo, utilice funciones.

2) Escriba 4 funciones, cuyos prototipos son:


int suma(int n, int m); // retorna n + m
int resta(int n, int m), // retorna n - m
int multiplica(int n, int m), // retorna n * m
float divide(int n, int m), // retorna n / m si m no es cero
Desde main(), llámelas e imprima los resultados.

3) Responda a las preguntas y argumente su respuesta:


a. ¿Puede una función llamar a main()? // Sí
b. ¿Es posible que una función a() llame a una función b(), esta a una función c(); y esta llame nuevamente a a()? // Sí
c. ¿Es posible que una función se llame a si misma? // Sí

4) Calcule el factorial de n fac(n) utilizando una función recursiva; pruebe con fac(4) y fac(40).

5) Utilice una función recursiva para calcular la función de Ackermann A(m,n), donde m >=0, n>=0 y:
n +1, Si m = 0;
A(m, n) = A(m-1,1), Si m > 0 y n = 0;
A(m-1, A(m, n-1)), Si m > 0 y n > 0
PÁGINA: 12
Lenguaje C++

6) Utilice una función recursiva para hallar el mínimo de un arreglo.

PÁGINA: 13

S-ar putea să vă placă și