1ª PARTE: FUNCIONES

Anuncio
INTRODUCCIÓN A LA PROGRAMACIÓN 1
PRÁCTICA 3: FUNCIONES Y PROCEDIMIENTOS
1ª PARTE: FUNCIONES
TRANSFORMACIÓN DE LEA A C
LEA
C
DEFINICIÓN DE UNA FUNCIÓN
func nombre (e1:T1; e2:T2; ...; en:Tn) dev (r:Tr)
Pre: {P(e1, e2, ..., en)}
Post: {Q(e1, e2, ..., en, r)}
cons
definición de constantes
var
declaración de variables
prin
sentencias
fin
Tr nombre (T1 e1, T2 e2, ..., Tn en)
{
Tr r;
declaración de variables
func factorial (n: entero) dev (f: entero)
Pre: {n≥0}
Post: {f=n!}
var
i: entero
prin
<f,i> := <1,0>
mientras i < n
i := i+1
f := f*i
fmientras
fin
int factorial (int n)
{
int f, i;
instrucciones
return r;
}
f = 1;
i = 0;
while (i < n)
{
i++;
f = f*i;
}
return f;
}
LLAMADA A UNA FUNCIÓN
En una asignación:
variable := nombre (lista de parámetros)
En una asignación:
variable = nombre (lista de parámetros);
Dentro de una expresión:
E (x, nombre(lista de parámetros))
Dentro de una expresión:
E (x, nombre(lista de parámetros))
a, b, f, año, ndias: entero
int a, b, f, anyo, ndias;
f := factorial (5)
f := factorial (a) / factorial (a-b)
f = factorial (5);
f = factorial (a) / factorial (a-b);
si esBisiesto(año)
ndias := 366
fsi
if (esBisiesto(anyo))
ndias = 366;
Práctica 3: Funciones y Procedimientos
2
EXPERIMENTOS
E.3.1
Escriba el siguiente programa, compílelo y ejecútelo. ¿Por qué no funciona correctamente? Corríjalo.
#include <stdio.h>
float max_doble(float,float);
void main(void)
{
float x,y;
printf("\nDeme dos números separados por un blanco: ");
scanf("%f%f",&x,&y);
printf("El doble-máximo de %f y %f es %f\n",x,y,max_doble(x,y));
}
float max_doble(float a, float b)
{
float max;
if (a>b)
max=a;
else
max=b;
max=max*2;
}
E.3.2
El siguiente programa da tres “warning”, de los cuales uno de ellos asegura que la función cuadrado está
"redeclarada". ¿Cuál es el problema? Corríjalo.
#include <stdio.h>
void main(void)
{
float x;
printf("\nDeme un número: ");
scanf("%f",&x);
printf("El cuadrado de %f es %f\n",x,cuadrado(x));
}
float cuadrado(float y)
{
float z;
z=y*y;
return(z);
}
EJERCICIOS DE SINTAXIS PROPUESTOS
S.3.1
El siguiente programa indica si un número leído desde la entrada estándar es par:
#include <stdio.h>
void main (void)
{
int numero;
scanf ("%d", &numero);
if (numero%2 == 0)
printf ("Es un número par");
else
printf ("Es un número impar");
}
Convierta el programa en una función que reciba como parámetro el número y devuelva como resultado un valor
de tipo lógico que indique si el número es o no par.
S.3.2
Modifique la función anterior para que sirva para comprobar si el número es múltiplo de un número variable n,
que será otro parámetro de entrada de la función.
Práctica 3: Funciones y Procedimientos
S.3.3
3
El siguiente programa calcula el factorial de un número:
#include <stdio.h>
void main (void)
{
int n, i;
long factorial;
printf ("\nIntroduzca un número entero positivo: ");
scanf ("%d", &n);
factorial = 1;
for (i=1; i<=n; i++)
factorial = factorial * i;
printf ("\nEl factorial de %d es: %ld",n, factorial);
}
Modifíquelo transformándolo en una función que reciba el número como parámetro de entrada y devuelva el
resultado como salida. Utilice el código que se proporciona a continuación.
#include <stdio.h>
void main (void)
{
int n;
printf ("\nIntroduzca un número entero positivo: ");
scanf ("%d", &n);
printf ("\nEl factorial de %d es: %ld",n, factorial(n));
}
S.3.4
Utilizando la función creada en el apartado anterior, escriba una función que calcule el número combinatorio dado
por la fórmula siguiente:
⎛ n⎞
n!
⎜⎜ ⎟⎟ =
⎝ m ⎠ m! (n - m)!
donde debe cumplirse que n > m. El prototipo de la función será
int numero_combinatorio (int n, int m);
S.3.5
El siguiente programa calcula la potencia n-ésima xn de un número entero x.
#include <stdio.h>
void main (void)
{
int n, i;
double x, potencia;
printf ("\nIntroduzca la base y el exponente: ");
scanf ("%lf%d", &x, &n);
potencia = 1;
for (i=0; i<n; i++)
potencia = potencia * x;
printf ("\nLa potencia es %lf", potencia);
}
Modifíquelo transformándolo en una función que reciba los valores de x y n comos parámetro de entrada y
devuelva el resultado como salida.
S.3.6
El siguiente programa lee dos números enteros de la entrada estándar y calcula e imprime el mayor de ellos:
#include <stdio.h>
void main (void)
{
int a, b, maximo;
scanf ("%d%d", &a, &b);
if (a> b)
maximo = a;
Práctica 3: Funciones y Procedimientos
4
else
maximo = b;
printf ("\nEl máximo de %d y %d es %d", a, b, maximo);
}
Convierta el programa en una función que reciba ambos números como parámetros de entrada y devuelva el
mayor de ellos como resultado.
EJERCICIOS DE ALGORITMICA PROPUESTOS
A.3.1
Realizar una función de nombre Siguiente tal que, recibiendo un número primo mayor que uno, devuelva el
número primo inmediatamente siguiente y superior a dicho número primo. Por ejemplo, si se invoca Siguiente(7),
la función devolverá el número 11.
A.3.2
Sea el siguiente programa incompleto:
#include <stdio.h>
void main (void)
{
int x1, x2, suma;
printf ("\nIntroduce dos valores: ");
scanf ("%d%d", &x1, &x2);
suma = suma_intervalo (x1, x2);
printf ("\nLa suma de los valores del intervalo es: %d", suma);
}
Complete el programa escribiendo la función suma_intervalo que calcula la suma de todos los números enteros
comprendidos entre los dos parámetros de entrada, ambos inclusive.
A.3.3
Escriba una función que reciba como parámetro de entrada el valor de un año y devuelva como resultado un valor
de tipo lógico que indique si es o no un año bisiesto. Recuerde, una vez más, la regla:
"Un año es bisiesto si es divisible por 400, o bien si es divisible por 4 pero no por 100"
A.3.4
Escriba una función que reciba como parámetros de entrada dos fechas dadas por un día, mes y año y devuelva
como resultado el número de días transcurridos entre ambas. Tenga en cuenta los posibles años bisiestos que
puedan existir entre ellas (utilice la función realizada en el ejercicio anterior).
A.3.5
Desarrolle una función que reciba como parámetros las dos coordenadas cartesianas (x, y) de un punto del plano y
devuelva como resultado un número del 1 al 4 que indique el cuadrante al cual pertenece al punto (no considere
los ejes de coordenadas).
A.3.6
Escriba una función que reciba como parámetro de entrada un número entero y devuelva como resultado el
número de cifras del número. Para ello, considere lo siguiente: dado un número cualquiera, como por ejemplo el
173, se tiene que
173 / 10 = 17
(todas las cifras salvo la última)
Habrá que repetir pues este proceso hasta que el número resultante de la división tenga una sola cifra.
A.3.7
Escriba una función que reciba como parámetros de entrada un valor entero y compruebe si se encuentra
comprendido entre dos valores constantes OPMIN y OPMAX. La función devolverá un valor lógico cierto en
caso afirmativo, y falso en caso contrario.
A.3.8
Modifique la función anterior para que los dos límites del intervalo sean sendos parámetros de la función. Escriba
varias posibles llamadas a la función, e indique el valor devuelto en cada caso.
A.3.9
Escriba una función que reciba como parámetros de entrada dos instantes de tiempo expresados en horas, minutos
y segundos y devuelva como resultado un 1 o un 2 según el primer instante de tiempo sea anterior al segundo o
Práctica 3: Funciones y Procedimientos
5
viceversa.
A.3.10 Escriba una función que reciba como parámetros de entrada tres números enteros que representan las longitudes
de tres segmentos rectilíneos, y devuelva como resultado un valor de tipo lógico que indique si dichos segmentos
pueden formar o no un triángulo (la condición necesaria pero no suficiente es que ninguno de los segmentos tenga
una longitud superior a la suma de los otros dos).
A.3.11 Desarrolle una función que presente en la salida estándar los múltiplos de n menores que m. Tanto n como m
serán dos parámetros de entrada de la función.
A.3.12 Construya una función que imprima la suma de los cuadrados de los n primeros números naturales, siendo n un
valor recibido como parámetro.
A.3.13 Recuerde el programa que calcula de forma aproximada el seno de un ángulo comprendido entre -π/2 y π/2
radianes, según la fórmula
3
angulo angulo
seno = angulo +
6
120
5
propuesto en la práctica 4. Transforme este programa escribiendo las siguientes funciones:
·
·
·
·
lee_datos lee el valor del ángulo, asegurándose de que se encuentra en el rango adecuado.
calcula_seno calcula el seno del ángulo, aplicando la fórmula aproximada.
presenta_seno presenta en la salida estándar los resultados obtenidos con un formato adecuado.
potencia calcula la potencia de un número real elevado a un exponente entero positivo.
El diagrama de bloques del nuevo programa es el siguiente:
programa
lee_datos
calcula_seno
presenta_seno
potencia
A.3.14 Recuerde el programa de cálculo de superficies del tema anterior. Transforme este programa escribiendo las
siguientes funciones:
·
·
·
lee_opcion lee la opción deseada y comprueba su validez (repase los ejercicios anteriores).
menú muestra el menú en la pantalla.
cuadrado, circulo, rectángulo, trapecio, triángulo calculan la superficie correspondiente.
==========================================
CÁLCULO DE SUPERFICIES (versión 3.0)
==========================================
1. Cuadrado
lado*lado
2. Círculo
pi*radio*radio
3. Rectángulo
base*altura
4. Trapecio
(base1+base2)*altura/2
5. Triángulo
(base*altura)/2
0. Salir del programa
==========================================
El diagrama de bloques del programa es el siguiente:
Práctica 3: Funciones y Procedimientos
6
programa
lee_opción
menú
cuadrado
círculo
rectángulo
trapecio
triángulo
A.3.15 Escriba un programa que permita llevar los gastos e ingresos menores de un millón de pesetas de una empresa. El
programa recogerá estos datos desde la entrada estándar y presentará un menú como el siguiente:
=================================
CONTROL DE GASTOS (versión 1.0)
=================================
1. Ingresos
2. Gastos
3. Salida
=================================
El diagrama de bloques es el siguiente:
programa
menú
lee_opción
ingresos
gastos
salida
Donde las funciones realizan las siguientes operaciones:
·
·
·
·
·
menú muestra el menú en la pantalla.
lee_opcion lee la opción del teclado.
ingresos lee nuevos ingresos y los suma al saldo actual.
gastos lee nuevos gastos y los resta del saldo actual (que nunca podrá ser negativo).
salida muestra el saldo actual (ingresos - gastos).
A.3.16 Escriba un programa realice la siguiente operación:
1.
2.
3.
4.
generará un número aleatorio de cuatro cifras.
leerá desde la entrada estándar un número de cuatro cifras diferentes.
comparará el número leído con el número generado por la máquina
Mostrará en la pantalla un número que indicará cuántas cifras del número leído existen y están colocadas
en su posición correcta en el número generado, y cuántas cifras existen pero no están colocadas en su
posición correcta.
El programa repetirá los pasos 2 a 4 hasta que el número de cifras en posición correcta sea 4. Sea el siguiente
ejemplo de ejecución (para el número generado 5234)
Introduza
Cifras
Cifras
Introduza
Cifras
Cifras
...
su
en
en
su
en
en
número: 2754
su posición:
otra posición:
número: 1534
su posición:
otra posición:
1
2
2
1
A.3.17 Realice un programa que lea de la entrada estándar un número de hasta 8 cifras y muestre por la salida estándar la
cifra resultante de aplicar el siguiente proceso:
Práctica 3: Funciones y Procedimientos
a)
b)
7
Sumar el valor absoluto de todas las cifras del número.
Si el valor resultante tiene más de una cifra, volver a sumar todas sus cifras sucesivamente hasta obtener
un valor de una única cifra.
Ejemplos:
Valor introducido por el usuario: 68543210
68543210 -> 6+8+5+4+3+2+1+0 = 29
29 -> 2+9 = 11
11 -> 1+1 = 2
Valor a mostrar: 2
Valor introducido por el usuario: 10000
10000 -> 1+0+0+0+0 = 1
Valor a mostrar: 1
Práctica 3: Funciones y Procedimientos
8
2ª PARTE: PROCEDIMIENTOS
TRANSFORMACIÓN DE LEA A C
LEA
C
DEFINICIÓN DE UN PROCEDIMIENTO
proc nombre (ent e1:Te1; e2:Te2; ...; en:Ten;
sal s1:Ts1; s2:Ts2; ...; sm:Tsm;
ent/sal r1:Tr1; r2: Tr2; ...; rp:Trp)
Pre: {P(e1, ..., en, r1, ..., rp)}
Post: {Q(e1, ..., en, s1, ..., sm, r1, ..., rp)}
cons
definición de constantes
var
declaración de variables
prin
sentencias
exp (ei, si, ri, x)
sentencias
fin
#include <assert.h>
typedef Ts1 * PTs1;
...
typedef Tsm * PTsm;
typedef Tr1 * PTr1;
...
typedef Trp * PTrp;
void nombre (Te1 e1, Te2 e2, ..., Ten en,
PTs1 s1, PTs2 s2, ..., PTsm sm,
PTr1 r1, PTr2 r2, ..., PTrp rp)
{
declaración de variables
assert (P(e1, ..., en, r1, ..., rp));
instrucciones
exp (ei, *si, *ri, x);
instrucciones
}
proc multDiv (ent op1:entero; op2:entero;
ent/sal mult:entero; div:entero)
Pre: { op2 ≠ 0 }
Post: { mult = op1 * op2 ∧ div = op1 / op2 }
Prin
mult := op1 * op2
div := op1 / op2
fin
typedef int *Pint;
void multDiv (int op1, int op2, Pint mult, Pint div)
{
assert (op2 != 0);
*mult = op1 * op2;
*div = op1 / op2;
}
Nota: distinguir entre * de multiplicación y * como
operador unario para representar el contenido.
LLAMADA A UN PROCEDIMIENTO
nombre (lista de parámetros)
nombre (lista de parámetros);
operando1, operando2, producto, cociente: entero
int operando1, operando2, producto, cociente;
multDiv (5, 9, producto, cociente)
multDiv (operando1, operando2, producto, cociente)
multDiv (5, 9, &producto, &cociente);
multDiv (operando1, operando2, &producto, &cociente);
Práctica 3: Funciones y Procedimientos
9
EXPERIMENTOS
E.3.3
La función intercambia pretende intercambiar los valores de sus dos parámetros.
#include <stdio.h>
void intercambia (int, int);
void main (void)
{
int a=3, b=5;
printf ("\na vale %d y b vale %d", a, b);
intercambia (a, b);
printf ("\na vale %d y b vale %d", a, b);
}
void intercambia (int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
¿Realiza la función su cometido? En caso contrario modifíquela adecuadamente para que lo haga.
E.3.4
El siguiente programa debe mostrar en pantalla el mensaje
El código es 12 y el tipo es B
Complete los huecos del programa para que funcione correctamente.
#include <stdio.h>
typedef int * Pint;
typedef char * Pchar;
void inicializa (Pint, Pchar);
void main (void)
{
int codigo;
char tipo;
inicializa ( ______ codigo, ______ tipo);
printf ("\nEl código es %d y el tipo es %c", codigo, tipo);
}
void inicializa (______ c, ______ t)
{
______ c = 12;
______ t = 'B';
}
E.3.5
Al compilar el siguiente programa el compilador nos informa de unos errores. ¿Qué indican estos errores?
Modifique el código para que funcione correctamente.
#include <stdio.h>
#define PI 3.1416
typedef double * Pdouble;
void areaLong(double, Pdouble, Pdouble);
void main(void)
{
double r,a,l;
printf("\nIntroduzca el rádio de la circunferencia: ");
scanf("%lf",&r);
areaLong(r,&a,&l);
printf("El área es %lf, y la longitud es %lf.\n",a,l);
}
void areaLong(double radio, Pdouble area, Pdouble longi)
{
Práctica 3: Funciones y Procedimientos
10
area = PI*radio*radio;
longi = 2*PI*radio;
}
EJERCICIOS DE SINTAXIS PROPUESTOS
S.3.7 Una función de nombre logaritmo recibe como parámetros un número real de doble precisión y un entero que
representa la base, y calcula el logaritmo de dicho número en dicha base. Escriba los prototipos en lenguaje C de
dicha función en los dos casos siguientes:
a)
b)
La función devuelve el valor del logaritmo obtenido.
El logaritmo es un parámetro de salida de la función.
Realice una llamada para cada prototipo, declarando las variables adecuadas.
S.3.8 Escriba una función
void maxmin (int x1, int x2, Pint max, Pint min);
que reciba como parámetros de entrada dos números enteros x1 y x2 y devuelva a través de los parámetros de
salida max y min el máximo y el mínimo, respectivamente, de ambos números.
S.3.9 Modifique la función anterior para que calcule también el valor medio de ambos números. El nuevo prototipo de
la función será ahora el siguiente:
void maxmin (int x1, int x2, Pint max, Pint min, Pint media);
S.3.10 Realice una función que reciba como parámetros dos números enteros y los devuelva ordenados conteniendo el
primer parámetro el mayor de los dos números y el segundo el menor de ellos. El prototipo de la función es el
siguiente:
void ordena_dos_numeros (Pint mayor, Pint menor);
S.3.11 La función
int valida_dato (int dato, int min, int max, int defecto)
{
int resul=defecto;
if (dato >= min && dato <= max)
resul = dato;
return (resul);
}
comprueba si el parámetro de entrada dato se encuentra comprendido entre los dos límites min y max. En caso
afirmativo, devuelve el propio valor dato como resultado, mientras que en caso negativo devuelve el valor del
parámetro defecto. Modifique esta función para que adopte el siguiente prototipo:
void valida_dato (Pint dato, int min, int max, int defecto);
es decir, que dato pase a ser un parámetro de entrada y salida.
S.3.12 La función
Logico fecha_valida (int dia, int mes, int anyo);
recibe como entrada una fecha (día, mes y año) y devuelve Cierto si la fecha es válida y Falso si no lo es.
Modifique el prototipo de esta función para que el valor devuelto pase a ser un parámetro de salida.
S.3.13 Sea la siguiente función
Práctica 3: Funciones y Procedimientos
11
void feliz_navidad (int n)
{
int i, j;
i = 1;
while (i <= n)
{
for (j=i; j<n; j++)
putchar (' ');
for (j=1; j<=2*i-1; j++)
putchar ('*');
i++;
printf ("\n");
}
for (i=1; i<n; i++)
putchar (' ');
printf ("#\n");
}
Siga la traza de la ejecución de la misma cuando se invoca con la llamada
feliz_navidad (5);
Hágalo primero a mano y compruébelo después ejecutándola en el ordenador.
EJERCICIOS DE ALGORÍTMICA
A.3.18 El siguiente programa incompleto imprime todas las tablas de multiplicar del 1 al 10.
#include <stdio.h>
void main (void)
{
int i;
for (i=1; i<=10; i++)
{
printf ("\nTabla de multiplicar del %d:\n", i);
tabla_multiplicar (i);
}
}
Complete el programa escribiendo la función tabla_multiplicar que imprime la tabla de multiplicar del número
que recibe como parámetro.
A.3.19 Dadas las definiciones de tipo
typedef int * Pint;
typedef enum {sumar, restar} Modo;
escriba una función
void incrementa (Modo m, int cantidad, Pint numero);
que sume o reste el valor de la variable cantidad a la variable numero en función de que la variable m tome el
valor sumar o restar, respectivamente. Por ejemplo, si cantidad=3 y numero=5, tras la llamada
incrementa (sumar, cantidad, &numero);
el valor de la variable numero será 5+3=8, mientras que tras la llamada
incrementa (restar, cantidad, &numero);
el valor de la variable numero será 5-3=2.
Práctica 3: Funciones y Procedimientos
12
El programa principal es:
void main (void)
{
int cant, num;
scanf(“%d%d”, &cant, &num);
printf ("\n1. El valor del número es: %d", num);
incrementa (sumar, cant, &num);
printf ("\n2. El valor del número es: %d", num);
incrementa (restar, cant, &num);
printf ("\n3. El valor del número es: %d", num);
}
A.3.20 Realice una función que reciba como parámetros tres números enteros y los devuelva ordenados conteniendo el
primer parámetro el mayor de los tres números, el segundo el valor intermedio y el tercero el menor. El prototipo
de la función es el siguiente:
void ordena_tres_numeros (Pint mayor, Pint medio, Pint menor);
A.3.21 Escriba una función
Logico fecha_valida (int dia, int mes, int anyo);
que reciba como entrada una fecha (día, mes y año) y devuelva Cierto si la fecha es válida y Falso si no lo es. Para
que una fecha sea válida el valor del mes debe estar comprendido entre 1 y 12 y el valor del día debe estar de
acuerdo con el mes (en el caso del mes de febrero, debe tenerse en cuenta además si el año es bisiesto o no).
Reescriba la función para que el valor devuelto pase a ser un parámetro de salida (véase ejercicio S.6.6).
A.3.22 Realice una función
void siguiente_fecha (Pint dia, Pint mes, Pint anyo);
que reciba a través de los parámetros dia, mes y anyo una fecha válida y devuelva a través de los mismos la
siguiente fecha válida del calendario. Por ejemplo,
Entrada
31
1
28
2
31
12
2
1
1996
1996
1996
1997
Salida
1 2
29 2
1 1
3 1
1996
1996
1997
1997
A.3.23 Realice una función
void siguiente_instante (Pint seg, Pint min, Pint hor);
que reciba a través de los parámetros seg, min y hor un instante de tiempo válido y devuelva a través de los
mismos el siguiente instante de tiempo válido. Por ejemplo,
Entrada
11
25
11
25
11
59
23
59
36
59
59
59
Salida
11 25
11 26
12
0
0
0
37
0
0
0
A.3.24 Escriba una función
void anterior_fecha (Pint dia, Pint mes, Pint anyo, int ndias);
que reciba a través de los parámetros dia, mes y anyo una fecha válida y devuelva a través de los mismos la fecha
anterior en ndias dias. Por ejemplo,
Práctica 3: Funciones y Procedimientos
Entrada
6
12
6
12
3
1
3
3
1998
1998
1999
2000
13
5
10
5
5
Salida
1 12
26 11
29 12
27
2
A.3.25 Escriba una función que imprima la pirámide
1
121
12321
1234321
123454321
La declaración de la función será la siguiente:
void piramide (int niveles);
siendo niveles el número de filas de la pirámide (5 en el ejemplo).
1998
1998
1998
2000
Descargar