Está en la página 1de 14

PRÁCTICA 6

Subprogramas en C++
El objetivo de esta práctica es presentar los mecanismos que proporciona el lenguaje C++ para la
programación mediante subprogramas.

1 Los subprogramas en C++


En las clases de teoría, mediante la palabra subprograma nos hemos referido a las acciones y a las
funciones. En C++ no existe esta distinción a nivel sintáctico: en este lenguaje de programación todos
los subprogramas son funciones. Eso no quiere decir que no se pueda programar una acción en C++,
veremos más adelante cómo se hace.

1.1 Declaración, definición y llamada


Para trabajar con funciones en C++, hay que reconocer tres procesos diferenciados:
• Todas las funciones deben declararse antes de ser definidas. Como veremos con detalle más
adelante, la declaración (también llamada prototipo o cabecera) de una función incluye: el
tipo de dato principal que devuelve, el nombre de la función y la lista de los tipos de los
parámetros.
• La definición de la función es el cuerpo de la misma, es decir, el conjunto de instrucciones que
forman la función propiamente dicha, y debe ir acompañada a su vez de una cabecera.
• Por último, para utilizar una función es necesario llamarla (activarla) desde algún punto del
programa en que se necesite.

1.2 Dónde se declara, se define y se llama a una función


Dentro de un programa en C++ las funciones tienen un lugar específico donde ser declaradas y definidas.
Recordemos el cuadro que mostrábamos en la página 2 de la práctica 2:
#include <nombre_de_fichero> // directivas al preprocesador

// declaraciones de funciones
int main() // inicio del bloque principal
{
const tipo const_1 = valor_1; // definiciones de constantes
1
Informática. Práctica 6.
Subprogramas en C++

tipo_1 var_1; // declaraciones de variables


tipo_2 var_2, var_3;

...
... // cuerpo del bloque principal

// definiciones de funciones
Como ves debemos declarar las funciones justo antes del inicio del bloque principal, int main(), y
definirlas justo después del final de dicho bloque (tras la llave de cierre).
La llamada a una función puede realizarse dentro de cualquier bloque del programa, ya sea el bloque
principal u otro (es decir, es posible hacer una llamada a una función desde dentro de otra función).

1.3 Declaración de una función


La declaración de una función debe incluir:
• El tipo de valor principal que devuelve la función.
• El nombre de la función.
• La lista de tipos de los parámetros, separados por comas y encerrados entre paréntesis.
Observa que en la declaración no es necesario, aunque puede hacerse, indicar los nombres de
los parámetros (formales), sino solamente sus tipos.
• Un punto y coma final.

tipoDevuelto nombreFunción (lista de parámetros formales);

Ejemplo: Declarar una función que calcule el factorial de un número recibido como parámetro.
int factorial(int);

1.3.1 Declaración de una acción


Como hemos dicho, en C++ no existe distinción (sintáctica) entre las acciones y funciones del
seudocódigo: todos los subprogramas son funciones. ¿Cómo debemos declarar entonces una acción?
Basta con indicar que el valor principal que devuelve la función es void, que es el tipo nulo de C++, el
tipo que es “ningún tipo”.
Ejemplo: Declarar una acción que dibuje líneas en la pantalla. La línea debe comenzar y finalizar con un
carácter y en su parte central debe dibujar otro carácter un número dado de veces. Tanto el carácter
central, como el extremo, como la longitud de la línea deben ser indicados por el módulo que invoca la
acción:
void dibujaLinea (char, char, int);

En este ejemplo, los dos tipos char corresponderán a los parámetros de los caracteres central y
extremo, y el tipo int al parámetro de la longitud de la línea.

1.4 Definición de una función


La definición de una función debe incluir:

2
Informática. Práctica 6.
Subprogramas en C++

• La cabecera de la función. Esta cabecera es prácticamente idéntica a la declaración de la que


acabamos de hablar, excepto porque:
o en la lista de los parámetros formales debemos indicar no sólo el tipo de cada uno sino
también su nombre (lo veremos con detalle más adelante).
o ahora la cabecera no acaba con punto y coma.
• El cuerpo de la función encerrado entre llaves.
• El cuerpo puede incluir una serie de declaraciones de variables y tipos locales (válidas
solamente dentro de la función).

tipoPrincipal nombreFunción (lista de parámetros con su tipo)


{
// declaración de tipos de datos locales
// declaración de variables locales

// cuerpo de la función
}

Ejemplos
Definición de la función factorial declarada antes (int factorial(int);).
int factorial (int num)
{
int cont;
int fac;
cont = 1;
fac = 1;
while (cont <= num)
{
fac = fac * cont;
cont = cont + 1;
}
return (fac); // devuelve el valor principal
}

Definición de la función (conceptualmente acción) dibujaLinea declarada antes (void dibujaLinea


(char, char, int);)

void dibujaLinea (char extremo, char central, int longitud)


{
int cont;

cont = 1;
cout << extremo;

while (cont <= longitud)


{
cout << central;
cont = cont + 1;
}
cout << extremo << endl;
}

Como ves, el aspecto de la definición de una función es muy parecido al del bloque principal (main), del
programa, excepto por la introducción de los parámetros. Esto es así porque en C++, en realidad, el
bloque principal es una función, llamada función principal, que siempre es la función que se ejecuta en
primer lugar cuando se pone en funcionamiento el programa.

3
Informática. Práctica 6.
Subprogramas en C++

1.5 Cómo devuelve la función su valor principal


La manera en que una función devuelve su valor principal (si lo tiene, es decir, si no es de tipo void) es
a través de una sentencia return. Para ello, en el caso de estemos creando una función, no una acción,
escribimos la cláusula return seguida del valor que ha de ser devuelto. En el cuerpo de la función
puede aparecer más de una sentencia return (por ejemplo, en varias ramas de una estructura
condicional), pero sólo se ejecutará una de ellas (la que se ejecute terminará la ejecución de la
función).
función nombreFunción(...) devuelve tipo tipo nombreFunción(...)
... {
principio ...
bloque_de_instrucciones bloque_de_instrucciones;
deuelve ( valor ); return valor;
fin }
Si la función es de tipo void, es decir, una acción que no debe devolver ningún valor, no debe aparecer
ninguna sentencia return en el cuerpo de la misma.
acción nombreAcción(...) void nombreFunción(...)
... {
principio ...
bloque_de_instrucciones bloque_de_instrucciones;
fin }

1.6 Los parámetros


Una función es capaz de trabajar de distinta manera dependiendo de una serie de valores que le
entrega el programa o subprograma que le llama. Así la función que dibuja líneas trabajará dibujando
líneas de distintas características a voluntad del módulo llamador. A esta serie de valores les
llamaremos parámetros (son variables que se utilizan para comunicar datos entre quien llama a la
función y ésta). La tarea que realiza la función debe ser independiente de los valores concretos de los
parámetros. Es algo así como resolver un problema de matemáticas de forma paramétrica; la solución
concreta depende del valor de los parámetros.
Si bien en las clases de teoría hemos distinguido entre tres tipos de parámetros (entrada, salida y
entrada-salida), C++ solo diferencia dos tipos de parámetros:

Parámetros de Se especifican escribiendo el identificador del parámetro y el tipo del


entrada mismo.

Parámetros de salida Se especifican igual que los parámetros de entrada, pero poniendo un &
y entrada/salida detrás del tipo del parámetro y delante del identificador del parámetro.

1.6.1 Especificación de los parámetros formales


La especificación de los parámetros debe cumplir estas reglas:
• Encerrar la lista de parámetros entre paréntesis.
• Cada parámetro debe especificarse mediante un identificador precedido de su tipo (separando
ambas partes por un espacio en blanco). Si el parámetro es de salida o entrada/salida, debe
ponerse un & entre el tipo y el nombre del parámetro.
• Los parámetros se separarán mediante comas.

4
Informática. Práctica 6.
Subprogramas en C++

Especificación de parámetros:
(tipo parámetro1, tipo parámetro2, ..., tipo parámetroN)

1.6.2 Ejemplos
Ejemplos de funciones con parámetros de entrada son las funciones anteriores Factorial y
DibujaLinea.
int factorial(int);
void dibujaLinea (char, char, int);

int factorial (int num)


{
int cont;
int fac;
cont = 1;
fac = 1;
while (cont <= num)
{
fac = fac * cont;
cont = cont + 1;
}
return (fac); // devuelve el valor principal
}

void dibujaLinea (char extremo, char central, int longitud)


{
int cont;

cont = 1;
cout << extremo;

while (cont <= longitud)


{
cout << central;
cont = cont + 1;
}
cout << endl << extremo;
}

Un ejemplo de función con parámetros de entrada/salida es el siguiente: Declaración y definición de


una función que intercambia el valor de dos variables enteras.
void intercambia(int &, int &); // son de E/S

void intercambia (int & a, int & b) // son de E/S


{
int aux;

aux = a;
a = b;
b = aux;
}

1.7 Las declaraciones locales


Las funciones pueden albergar en su interior declaraciones de variables. Las llamamos locales porque
solo existen dentro del cuerpo de la función y por tanto solo se pueden utilizar en ese ámbito.

5
Informática. Práctica 6.
Subprogramas en C++

1.8 Parámetros Formales-Reales


A los parámetros enviados desde el programa o subprograma llamador hacia el subprograma llamado
se les conoce como parámetros reales en contraposición de los parámetros formales, que son los
genéricos que aparecen en la declaración de la función. Así en el ejemplo anterior de la función
dibujaLinea se tienen tres parámetros formales: extremo, central y longitud (recuerda la cabecera
de la definición de la función: void dibujaLinea (char extremo, char central, int
longitud). Sin embargo, los parámetros reales pueden ser:

• expresiones con resultado del mismo tipo que el parámetro formal correspondiente (para
parámetros de entrada).
• variables del mismo tipo que el formal correspondiente (para parámetros de salida o
entrada/salida)

1.9 Llamada a una función en C++


Una vez que se ha declarado y definido una función la llamada a esta se realiza de manera diferente si
se trata de una función propiamente dicha (devuelve un valor) o si se trata de una acción (el valor
principal de la función es void).

Para llamar a una función:


• Si la función devuelve un valor principal (función)
nombreFunción (lista parámetros reales) dentro de una expresión.
• Si la función NO devuelve un valor principal (acción)
nombreFunción (lista parámetros reales); formando ella sola una instrucción

Ejemplos
Llamada a la función factorial (escrita anteriormente)
resultado = factorial(4);

Llamada a la función dibujaLínea (escrita anteriormente)


dibujaLinea ('+','-',7);

Bloque principal con uso de la función Intercambia (escrita anteriormente)


int main()
{
int x,y;
x = 1;
y = 2;
cout << endl <<"Ahora x vale " << x << " e y vale " << y;
intercambia(x, y); //acción, llamada forma una instrucción
cout << endl << "Y ahora x vale << x << " e y vale " << y;
return(0);
}

Esta llamada a la función Intercambia(x, y) hace que las variables x e y (que contenían un valor 1 y
2 respectivamente) intercambien su valor (tras la llamada x vale 2 e y vale 1).

6
Informática. Práctica 6.
Subprogramas en C++

1.10 Correspondencia parámetros formales-reales


La correspondencia entre los parámetros reales y los formales se realiza en base al orden que los reales
ocupan en la llamada al subprograma: primer parámetro real para primer parámetro formal, segundo
parámetro real para segundo parámetro formal, etc.

Los parámetros reales deben coincidir en tipo con los formales correspondientes.

1.11 El mecanismo de la llamada


El mecanismo de la llamada supone los siguientes pasos:
1. Evaluar las expresiones de los parámetros reales (si las hubiera).
2. Hacer corresponder a cada parámetro formal el valor (si es de entrada) o la variable (si es de salida
o entrada/salida) correspondiente al real que ocupa la misma posición en la llamada.
3. Realizar las instrucciones descritas en el cuerpo de la función, actualizando los valores de los
parámetros reales de salida o entrada/salida.
4. Devolver el valor principal indicado (si no era void)
5. Resolver la expresión en el módulo llamador teniendo en cuenta al valor devuelto por la función (si
lo hubiera).
6. Continuar con la siguiente instrucción del módulo llamador que aparece tras la llamada a la función.

7
Informática. Práctica 6.
Subprogramas en C++

2 Sesión de prácticas
2.1 Primer ejercicio
Con este ejercicio aprenderás a:
• Realizar llamadas a subprogramas.
• Reconocer y ensayar con los diferentes tipos de parámetros en C++.
• Realizar programas mediante la técnica de diseño descendente.

2.1.1 Primer programa.


El siguiente programa en C++ dibuja en la pantalla un árbol de navidad con asteriscos tal como ves en
la figura. Para ello dispone de una función llamada tramo que dibuja una línea de asteriscos de
longitud n:
void tramo(int n)

Su parámetro de entrada, n, indica el número de asteriscos que tiene que dibujar en la línea.
SE PIDE:
Acabar el programa que realiza el dibujo de la figura siguiente:
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*********************
***********************
*************************
***************************
*****************************
*******************************
*********************************
***********************************
*************************************
***************************************
*****
*****
*****

Para ello toma el fichero P6EJ1 y complétalo con las llamadas al subprograma Tramo que sean
necesarias.
/*
AUTOR: profesores de Informática
DESCRIPCION:
Dibuja un árbol de navidad con asteriscos
ENTRADAS:
SALIDAS:
ERRORES:
*/
8
Informática. Práctica 6.
Subprogramas en C++

#include <iostream>

using namespace std;

void tramo(int);

int main()
{
........ // Completar

........

return(0);
}

void tramo(int n)
{
int i;

i = 1;
while ( i <= (79-n) / 2 )
{
cout<<' ';
i = i + 1;
}

i = 1;
while ( i <= n )
{
cout<<'*';
i = i + 1;
}

cout<<endl;
}

2.1.2 Segundo programa.


El siguiente programa calcula los números perfectos menores que 1000. Un número es perfecto si
coincide con la suma de sus divisores menores estrictos que él. Por ejemplo 6 es un número perfecto
puesto que sus divisores (1, 2, 3) suman 6.
Para la realización del programa (del cual se da una versión en seudocódigo) debes utilizar una función
que reciba un entero y devuelva la suma de sus divisores, cuya cabecera es esta:
int sumaDivisores(int);

SE PIDE:
Traducir el programa a C++ y completarlo realizando el subprograma sumaDivisores. Llama a este
algoritmo P6EJ2. Lo primero que deberás determinar antes de hacer el subprograma es a qué tipo de
subprograma corresponde (acción o función).
Entradas: no tiene
Salidas: muestra en pantalla los números perfectos menores que 1000

Algoritmo Números Perfectos


variables
entero num
principio

9
Informática. Práctica 6.
Subprogramas en C++

num = 1
mientras que num <= 1000 hacer
si num = sumaDivisores(num) entonces
escribir (num, “Es número perfecto”)
fsi
num = num + 1
fmq
fin

2.1.3 Tercer programa.


El siguiente programa en C++ escribe ordenadamente de forma creciente tres enteros leídos por
teclado. Para la resolución del problema el programa compara dos a dos los números, intercambiando
sus valores si están desordenados.
/* AUTOR: profesores de Informática
DESCRIPCIÓN:
Orden de forma creciente tres enteros.
ENTRADAS: n1, n2, n3: los tres números enteros.
SALIDAS: n1, n3: el mínimo será n1 y el máximo n3.
*/

#include <iostream>
using namespace std;

int main()
{
int n1, n2, n3;
int aux;

cout<<endl<<"Introduce los tres números:"<<endl;


cin>>n1;
cin>>n2;
cin>>n3;

if (n1 > n2)


{
aux = n1;
n1 = n2;
n2 = aux;
}

if (n1 > n3)


{
aux = n1;
n1 = n3;
n3 = aux;
}

if (n2 > n3)


{
aux = n2;
n2 = n3;
n3 = aux;
}

cout<<"La lista ordenada es "<< n1 << ", " << n2 << ", " << n3;

return 0;
}

10
Informática. Práctica 6.
Subprogramas en C++

SE PIDE: Realizar un programa en C++ que, utilizando algún subprograma, evite las repeticiones de
instrucciones que se dan en los bloques de las estructuras if. Llama al programa P6EJ3.
2.1.4 Cuarto programa.
El siguiente programa obtiene la suma siguiente (donde n ha de ser introducido por teclado):
1 2 3 n
suma = + 2 + 3 +3+ n
2 2 2 2
SE PIDE:
Completa el programa (P6EJ4) siguiente. Utiliza una función para calcular la potencia de una base y
exponentes cualesquiera (enteros >=0).
/*
AUTOR: profesores de Informática
DESCRIPCIÓN:
n
Suma la serie de término general n/2
ENTRADAS: n: número de términos a sumar
SALIDAS: suma: resultado de la suma de la serie
*/
#include <iostream>
using namespace std;

.................... // Poner la cabecera del subprograma

int main()
{
int i, n;
float suma;

cout<<"Introduce el número de términos a sumar ";


cin>>n;

suma = 0;
i = ......
while (i <= n)
{
suma = suma +.......
i = i + 1;
}

cout<<endl<<" La serie suma "<<suma;

return 0;
}

................ // Poner la cabecera del subprograma


{
int pot,i;

pot = 1;
i = 1;
while (i <= y)
{
pot = pot * x;
i = i + 1;
}
return(pot);
}

11
Informática. Práctica 6.
Subprogramas en C++

2.1.5 Quinto programa.


En el siguiente programa se utilizan una serie de funciones para operar con números complejos.
Debido a que no hay ningún tipo de datos (conocido hasta el momento) adecuado para almacenar
valores de tipo complejo, utilizaremos dos variables de tipo real para contener las partes real e
imaginaria del complejo. De este modo, cualquier valor complejo que se necesite pasar como
parámetro a un subprograma necesitará en realidad dos parámetros.
SE PIDE:
El propósito real del ejercicio es que averigües cuántos y de qué tipo son los parámetros de las
funciones que se utilizan en el programa. Como muestra se da la función para escritura de complejos
que tiene dos parámetros de entrada. El programa completo lee dos complejos y la operación a
realizar, y luego los opera, escribiendo el resultado. Puedes utilizar el fichero P6EJ5
/*
AUTOR: profesores de Informática
DESCRIPCION:
Operación de dos números complejos
ENTRADAS: n1pr, n1pi, n2pr, n2pi: partes reales e imaginarias de los números complejos a
sumar, operación: operación a realizar
SALIDAS: solpr, solpi: parte real e imaginaria de la solución
*/
#include <iostream>

using namespace std;

void escribirComplejo(float pr,float pi);


void leerComplejo(...........);
void suma(.........);
void resta(.........);
void multiplica(.........);
void divide(.........);

int main()
{
float n1pr, n1pi, n2pr, n2pi;
float solpr, solpi;
char operacion;

leerComplejo (........);
leerComplejo (........);

do //validamos la entrada para evitar tomar una operación no válida


{
cout<<"Introduce la operación");
cin>>operación;
} while((operación!='+') && (operación!='-') && (operación!='*') && (operación!='/'));

switch (operacion)
{
case '+':
{
suma(........);
}
break;
case '-':
{
resta(........);
}

12
Informática. Práctica 6.
Subprogramas en C++

break;
case '*':
{
multiplica(........);
}
break;
case '/':
{
divide(........);
}
break;
}

escribir_complejo(solpr, solpi);
return 0;
}

void escribirComplejo (float pr, float pi)


{
cout<<pr;
if (pi>=0.)
{
cout<<' + ';
}
cout << pi << 'i';
}

void leerComplejo (........)


{
cout << endl << "Introduce la parte real";
cin >> pr;
cout << endl << "Introduce la parte imaginaria";
cin >> pi;
}

void suma (........)


{
sr = pr1 + pr2;
si = pi1 + pi2;
}

void resta (........)


{
sr = pr1 - pr2;
si = pi1 - pi2;
}

void multiplica (........)


{
sr = pr1*pr2 - pi1*pi2;
si = pi1*pr2 + pi2*pr1;
}

void divide (........)


{
sr = (pr1*pr2 + pi1*pi2) / (pr2*pr2 + pi2*pi2);
si = (pr2*pi1 - pi2*pr1) / (pr2*pr2 + pi2*pi2);
}

13
Informática. Práctica 6.
Subprogramas en C++

2.2 Realización de programas

1. Programa calculador de fracciones (similar al de complejos hecho en esta práctica). Para ello sigue
los siguientes consejos:
A. Escribe un subprograma para reducir quebrados. Para ello se necesitará construir
previamente una función de cálculo del m.c.d. Ten en cuenta que ¼ + ¼ no son 2/4 sino ½.
B. Para la representación de las fracciones utiliza dos variables enteras.
C. Escribe subprogramas de lectura y escritura de fracciones.
D. Escribe los subprogramas para las operaciones con fracciones (sumar, restar, multiplicar y
dividir).
E. El programa preguntará por la operación a realizar y luego leerá las fracciones a operar. Una
vez resuelta la operación escribirá el resultado.

2. Programa que calcule el valor de (x + y)n , dados x, y, n por teclado. Para ello, desarrollar
funciones que permitan usar la expresión del desarrollo del binomio de Newton:

n n n  n  2 n - 2  n  1 n -1  n  n


(x + y)n =   x n +   x n -1y1 +   x n - 2 y 2 + ... +   x y +   x y +   y
0 1  2  n - 2  n - 1 n
Recuerda que

 m m!
 =
 n  n !( m - n)!
y que n ! = 1 * 2 * 3*...*( n - 1) * n si n > 0 y 0 ! = 1

14

También podría gustarte