SlideShare uma empresa Scribd logo
1 de 30
Baixar para ler offline
ProgramaciónEstructurada
2013
Descomposiciónfuncional.Parte
II
M.Sc. Ana María Salgado G.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 2
Más sobre funciones
Todo programa C está formado además de por la función main, que es el punto de entrada y de
salida del programa, por otras funciones, las cuales se comunican entre sí pasándose argumentos
siempre que sean requeridos.
Vamos a centrarnos en cuestiones más específicas como pasar argumentos a funciones que sean,
matrices, estructuras y punteros, o bien devolver estos tipos de datos.
Pasar una matriz como argumento a una función
En C todos los arrays se pasan por referencia(dirección). Cuando se llama a una función y se utiliza
un array como parámetro, se debe tener cuidado de no modificar los arrays en una función
llamada. C trata automáticamente la llamada a la función como si hubiera situado el operador de
dirección & delante del nombre del array.
#include <stdio.h>
#include <string.h>
void cambiar(char c[4]);
int main()
{
char palabra[4] = "ABC";
cambiar(palabra);
puts(palabra);
return 0;
}
void cambiar(char c[4])
{
puts(c);
strcpy(c,"AMA");
}
Cuando se pasa un array a una función, se pasa realmente sólo la dirección de la celda de
memoria donde comienza el array. Este valor se representa por el nombre del array. La función
puede cambiar entonces el contenido del array accediendo directamente a las celdas de memoria
en donde se almacenan los elementos del array. Los elementos del array se pueden cambiar como
si se pasara por referencia.
Cuando pasamos un array a una función lo que se escribe como argumento en la llamada a esa
función es el nombre del array, es decir, el argumento que se pasa es la dirección del array, por lo
que el parámetro formal correspondiente tiene que ser también un array, el cual, después de la
llamada, queda inicializado con esa dirección.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 3
Los arrays son siempre pasados por referencia, porque no se pasa una copia de todos sus
elementos. Tanto la función que invoca, como la función invocada trabajan sobre el mismo
espacio de memoria(sobre el mismo array).
#include <stdio.h>
#define L 10
void leerArray(double a[], int *);
void imprimirArray(const double [], int);
int main()
{
double a[L];
int n;
leerArray(a, &n);
printf("nEl array a tiene %d elementos, estos sonn",n);
imprimirArray(a,n);
return 0;
}
void leerArray(double a[], int *num)
{
int n ;
puts("Introduzca datos. Para terminar pulsar 0.n");
for(n = 0; n < L; n++)
{
printf("%d: ",n);
scanf("%lf",&a[n]);
if(a[n] == 0)
break;
}
*num = n;
}
void imprimirArray(const double a[], int n)
{
int i;
for(i = 0; i<n; i++)
printf("t%d: %gn",i,a[i]);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 4
Cuando se declara un array unidimensional como parámetro de una función, no se requiere que se
especifique su dimensión(no se hace una reserva de memoria para una copia total del array), ya
que lo que se pasa es la dirección del array.
int leer(tficha bibli[ ], int NMAX);
Precauciones
Cuando se utiliza una variable array como argumento, la función receptora puede no conocer
cuántos elementos existen en el array. Sin su conocimiento una función no puede utilizar el array.
Aunque la variable array puede apuntar al comienzo de él, no proporciona ninguna indicación de
dónde termina el arreglo.
La función SumaDeEnteros() suma los valores de todos los elementos de un array y devuelve el
total.
int SumaDeEnteros(int *ArrayEnteros)
{
…
}
int main()
{
int lista[5] = {10, 11, 12, 13, 14};
SumaDeEnteros(lista);
…
}
Aunque SumaDeEnteros() conoce dónde comienza el array, no conoce cuántos elementos hay en
el array, en consecuencia, no sabe cuántos elementos hay que sumar.
Se pueden utilizar dos métodos alternativos para permitir que una función conozca el número de
argumentos asociados con un array que se pasa como argumento de una función:
• Situar un valor de señal al final del array, que indique a la función que se ha de detener el
proceso en ese momento.
• Pasar un segundo argumento que indica el número de elementos del array.
Todas las cadenas utilizan el primer método ya que terminan en nulo. Una segunda alternativa es
pasar el número de elementos del array siempre que se pasa el array como un argumento. El
array y el número de elementos se convierten entonces en una pareja de argumentos que se
asocian con la función llamada. La función SumaDeEnteros(), por ejemplo, se puede actualizar así:
int SumaDeEnteros(int ArrayEnteros[], int noElementos)
{
…
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 5
El segundo argumento, noElementos, es un valor entero que indica a la función int
SumaDeEnteros() cuántos elementos se procesarán en el array ArrayEnteros. Este método suele
ser el utilizado para arrays de elementos que no son caracteres.
Ejemplo:
/********************** Programa Alumnos **********************/
// Versión con punteros
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define N 100 /* número máximo de alumnos */
typedef struct
{
char matricula[10];
char apellidos[30];
char nombre[20];
char direccion[30];
} ficha;
int leer(ficha *, const int);
void buscar(ficha *, char *, int, int);
int menu(void);
void main( )
{
static ficha lista[N];
char dato[30]; /* dato a buscar */
int opcion; /* opción elegida en el menú */
int n = 0; /* número de alumnos leídos */
while (1) /* bucle infinito. Se sale con break. */
{
opcion = menu( );
if (opcion != 4)
{
switch (opcion)
{
case 1: /* entrada de los datos de los alumnos */
n = leer(lista, N);
break;
case 2: /* búsqueda por el número de matrícula */
system("cls");
printf("Número de matrícula "); gets(dato);
buscar(lista, dato, n, opcion);
break;
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 6
case 3: /* Búsqueda por los apellidos */
system("cls");
printf("Apellidos.......... "); gets(dato);
buscar(lista, dato, n, opcion);
break;
}
}
else
break;
}
}
/****************************************************************
Función para visualizar el menú
****************************************************************/
int menu(void)
{
int op;
do
{
system("cls");
printf("nt1. Entrada de datos de alumnosn");
printf("nt2. Busqueda por nro. de matriculan");
printf("nt3. Busqueda por apellidosn");
printf("nt4. Finn");
printf("nnTeclee la opcion deseada: ");
scanf("%d", &op);
fflush(stdin);
}
while (op < 1 || op > 4);
return (op);
}
/****************************************************************
Función para leer los datos correspondientes a un alumno
****************************************************************/
int leer(ficha *lista, const int NMAX)
{
int n = 0;
char resp = 's';
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 7
while (tolower(resp) == 's' && n < NMAX)
{
do
{
system("cls");
printf("Alumno numero %dnn", n+1);
printf("Numero de matrícula: "); gets(lista[n].matricula);
printf("Apellidos.......... "); gets(lista[n].apellidos);
printf("Nombre............. "); gets(lista[n].nombre);
printf("Dirección.......... "); gets(lista[n].direccion);
printf("nn¿ Datos correctos ? s/n ");
fflush(stdin);
resp = getchar();
} while (tolower(resp) != 's');
n++;
printf("nn¿ Más datos a introducir ? s/n ");
resp = getchar();
fflush(stdin);
}
return (n);
}
/****************************************************************
Función para buscar si existe o no un dato
****************************************************************/
void buscar(ficha *lista, char *x, int alumnos, int opcion)
{
const int NO = 0;
const int SI = 1;
int existe = NO, i = 0;
char resp;
switch(opcion)
{
case 2: /* búsqueda por número de matrícula */
while (!existe && i < alumnos)
if (strcmp(lista[i++].matricula, x) == 0)
existe = SI;
break;
case 3: /* Búsqueda por apellidos */
while (!existe && i < alumnos)
if (strcmp(lista[i++].apellidos, x) == 0)
existe = SI;
break;
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 8
if (existe)
printf("n%sn%s %sn%sn", lista[i-1].matricula, lista[i-1].apellidos, lista[i-
1].nombre, lista[i-1].direccion);
else
printf("n%s no existe", x);
printf("nnPulse <Entrar> para continuar ");
resp = getchar( );
fflush(stdin);
}
Si el array es multidimensional, no es necesario especificar la primera dimensión, pero sí las
restantes.
void CopiarArray(float destino[ ][COLS], float origen[ ][COLS]);
El nombre de un array y un puntero no son lo mismo, pero en lugar del nombre de una array
unidimensional, podemos usar un puntero que almacene la dirección de comienzo del array para
acceder a los elementos del mismo.
El identificador de un array y un puntero no son lo mismo, lo que imposibilita en el caso de arrays
de dos dimensiones utilizar en lugar del nombre del array, un puntero a un puntero que almacene
la dirección de comienzo del array para acceder a los elementos del mismo.
/************** Fusionar dos listas clasificadas **************/
/* Versión con punteros */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NML 120 /* número máximo de líneas */
#define CPL 60 /* caracteres por línea */
int fusionar(char **, int, char **, int, char **, const int);
void Error(void);
void main( )
{
/* Inicializamos las listas a clasificar con el fin de no tener
* que leer los datos y realizar así una prueba rápida. */
static char *listaActual[ ] =
{ "Ana", "Carmen", "David",
"Francisco", "Javier", "Jesús",
"José", "Josefina", "Luís",
"María", "Patricia", "Sonia" };
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 9
static char *listaNueva[ ] =
{ "Agustín", "Belén",
"Daniel", "Fernando", "Manuel",
"Pedro", "Rosa", "Susana" };
/* Calcular el número de elementos de los arrays anteriores */
const int dimA = sizeof(listaActual)/sizeof(listaActual[0]);
const int dimN = sizeof(listaNueva)/sizeof(listaNueva[0]);
/* Definir el array resultante de fusionar los anteriores */
static char **listaFinal; // referencia el array resultante
int ind, r;
/* Asignar memoria para el array de punteros listaFinal */
listaFinal = (char **)malloc((dimA+dimN) * sizeof(char *));
if (listaFinal = = NULL) Error( );
/* Inicializa el array de punteros. Esto evita problemas al
liberar memoria, en el supuesto de un error por falta de
memoria */
for (ind = 0; ind < dimA+dimN; ind++)
listaFinal[ind] = NULL;
/* Fusionar listaActual y listaNueva y almacenar en resultado en
* listaFinal. La función "fusionar" devuelve un 0 si no se
* pudo realizar la fusión. */
r = fusionar(listaActual, dimA, listaNueva, dimN, listaFinal, NML);
/* Escribir el array resultante */
if (r)
{
for (ind = 0; ind < dimA+dimN; ind++)
printf("%sn", listaFinal[ind]);
}
else
Error( );
/* Liberar la memoria ocupada por el array listaFinal */
for (ind = 0; ind < dimA+dimN; ind++)
free(listaFinal[ind]);
free(listaFinal);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 10
/****************************************************************
F U S I O N A R
****************************************************************/
int fusionar(char **listaA, int dimA,
char **listaN, int dimN,
char **listaF, const int nml)
{
int ind = 0, indA = 0, indN = 0, indF = 0;
while (indA < dimA && indN < dimN)
if (strcmp(listaA[indA], listaN[indN]) < 0)
{
listaF[indF] = (char *)malloc(strlen(listaA[indA]) + 1);
if (listaF[indF] = = NULL) return 0;
strcpy(listaF[indF++], listaA[indA++]);
}
else
{
listaF[indF] = (char *)malloc(strlen(listaN[indN]) + 1);
if (listaF[indF] = = NULL) return 0;
strcpy(listaF[indF++], listaN[indN++]);
}
/* Los dos lazos siguientes son para prever el caso de que,
* lógicamente una lista finalizará antes que la otra.
*/
for (ind = indA; ind < dimA; ind++)
{
listaF[indF] = (char *)malloc(strlen(listaA[indA]) + 1);
if (listaF[indF] = = NULL) return 0;
strcpy(listaF[indF++], listaA[ind]);
}
for (ind = indN; ind < dimN; ind++)
{
listaF[indF] = (char *)malloc(strlen(listaN[indN]) + 1);
if (listaF[indF] = = NULL) return 0;
strcpy(listaF[indF++], listaN[ind]);
}
return(1);
}
void Error(void)
{
puts("Longitud no válida de la lista resultante");
exit(1);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 11
Pasar una estructura a una función
Una estructura puede ser pasada a una función por valor o por referencia.
Cuando pasamos una estructura por valor, el parámetro actual que representa la estructura se
copia en el correspondiente parámetro formal, produciéndose un duplicado. Si alguno de los
miembros del parámetro formal se modifica, los cambios no afectan al parámetro actual
correspondiente.
Si pasamos la estructura por referencia, lo que recibe la función es el lugar de la memoria donde
se localiza dicha estructura.
/**************** Operaciones con complejos ****************/
#include <stdio.h>
typedef struct
{
float real;
float imag;
} tcomplejo;
void SumarComplejos(tcomplejo c1, tcomplejo c2, tcomplejo *p);
void main( )
{
tcomplejo ca, cb, cc;
printf("nIntroducir datos de la forma: x yin");
printf("ca = ");
scanf("%f %f", &ca.real,&ca.imag); fflush(stdin);
printf("cb = ");
scanf("%f %f", &cb.real,&cb.imag); fflush(stdin);
SumarComplejos(ca, cb, &cc);
printf("Resultado: %g%+gin", cc.real, cc.imag);
}
void SumarComplejos(tcomplejo c1, tcomplejo c2, tcomplejo *p)
{
p->real = c1.real + c2.real;
p->imag = c1.imag + c2.imag;
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 12
Función que retorna un puntero
Cuando una función retorna un puntero a un objeto, el objeto debe persistir después de finalizar la
función.
/**************** Operaciones con complejos ****************/
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float real;
float imag;
} tcomplejo;
tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2);
void main( )
{
tcomplejo ca, cb, *pcr;
printf("nIntroducir datos de la forma: x yin");
printf("ca = ");
scanf("%f %f", &ca.real,&ca.imag); fflush(stdin);
printf("cb = ");
scanf("%f %f", &cb.real,&cb.imag); fflush(stdin);
pcr = SumarComplejos(ca, cb);
printf("Resultado: %g%+gin", pcr->real, pcr->imag);
}
tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2)
{
tcomplejo cx;
cx.real = c1.real + c2.real;
cx.imag = c1.imag + c2.imag;
return &cx;
}
El programa anterior presenta resultados inesperados. La función SumarComplejos, utiliza un
complejo local cx del cual retorna su dirección. Cuando la función finalice el complejo cx se
destruirá automáticamente, con lo que el puntero pcr que apunta al resultado, estará apuntando a
un objeto inexistente.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 13
La solución radica en hacer que la función SumarComplejos cree un objeto que persista a lo largo
de la ejecución del programa, asignando memoria dinámicamente para el objeto.
/**************** Operaciones con complejos ****************/
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float real;
float imag;
} tcomplejo;
tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2);
void main( )
{
tcomplejo ca, cb, *pcr;
printf("nIntroducir datos de la forma: x yin");
printf("ca = ");
scanf("%f %f", &ca.real,&ca.imag); fflush(stdin);
printf("cb = ");
scanf("%f %f", &cb.real,&cb.imag); fflush(stdin);
pcr = SumarComplejos(ca, cb);
printf("Resultado: %g%+gin", pcr->real, pcr->imag);
/* Liberar la memoria asignada */
free(pcr);
}
tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2)
{
tcomplejo *pcx;
/* Asignar memoria para el complejo suma */
pcx = (tcomplejo *)malloc(sizeof(tcomplejo));
if ( pcx = = NULL )
{
printf("Memoria insuficienten");
exit(-1);
}
pcx->real = c1.real + c2.real;
pcx->imag = c1.imag + c2.imag;
return pcx;
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 14
Funciones recursivas
Una función recursiva es aquella que se llama a sí misma.
El compilador C permite cualquier número de llamadas recursivas a una función. Cada vez que la
función es llamada, los parámetros formales son inicializados.
Se utiliza una función recursiva, cuando el proceso a programar es por definición recursivo. Por
ejemplo, el cálculo del factorial de un número por definición es un proceso recursivo.
n! = n(n-1)!
/************* Cálculo del factorial de un número *************/
#include <stdio.h>
unsigned long factorial(int n);
void main( )
{
int numero;
unsigned long fac;
do
{
printf("¿Número? ");
scanf("%d", &numero);
} while (numero < 0 || numero > 12);
fac = factorial(numero);
printf("nEl factorial de %d es %ldn", numero, fac);
}
unsigned long factorial(int n)
{
if (n == 0)
return 1;
else
return n*factorial(n-1);
}
Para n = 4, el proceso seguido por la función es:
Nivel de recursión Proceso de ida Proceso de vuelta
0 factorial(4) 24
1 4 * factorial(3) 4 * 6
2 3 * factorial(2) 3 * 2
3 2 * factorial(1) 2 * 1
4 1 * factorial(0) 1 * 1
factorial(0) 1
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 15
El uso de la recursión debe evitarse cuando haya una solución obvia por iteración.
La llamada a una función recursiva consume mucho espacio de pila debido a que por cada llamada
las variables que intervienen en la función son salvadas en la pila para posteriormente poder
iniciar la vuelta.
Funciones predefinidas en c
Funciones matemáticas: Las declaraciones para estas funciones están en el fichero math.h
Los argumentos y el resultado son de tipo double.
En muchos casos utilizaremos conversión cast para convertir explícitamente los argumentos al tipo
deseado. Ejemplo:
a = tan((double)valor);
Las funciones matemáticas se clasifican en:
• Funciones trigonométricas
• Funciones hiperbólicas.
• Funciones exponencial y logarítimica.
• Funciones varias.
• cos: La función cos da como resultado el coseno de x ( x en radianes).
#include <math.h>
double cos(double x);
• sin: La función sin da como resultado el seno de x ( x en radianes).
#include <math.h>
double sin(double x);
• tan: La función tan da como resultado la tangente de x ( x en radianes).
#include <math.h>
double tan(double x);
• cosh: La función cosh da como resultado el coseno hiperbólico de x ( x en radianes).
#include <math.h>
double cosh(double x);
• sinh: La función sinh da como resultado el seno hiperbólico de x ( x en radianes).
#include <math.h>
double sinh(double x);
• tanh: La función tanh da como resultado la tangente hiperbólica de x ( x en radianes).
#include <math.h>
double tanh(double x);
• exp
Da como resultado el valor de ex
( e = 2.718282)
#include <math.h>
double exp(double x);
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 16
• log
Da como resultado el logaritmo natural de x .
#include <math.h>
double log(double x);
• log10
Da como resultado el logaritmo en base 10 de x .
#include <math.h>
double log10(double x);
• ceil
Resultado: un valor double, que representa el entero
más pequeño que es mayor o igual que x.
#include <math.h>
double ceil(double x);
double x = 2.8, y = -2.8;
printf(“%g %gn”,ceil(x),ceil(y));
• fabs
Calcula el valor absoluto de x( siendo x un valor real en doble precisión). Las funciones abs y labs
calculan el valor absoluto de un int y un long respectivamente.
#include <math.h>
double fabs(double x);
• floor
Resultado: un valor double, que representa el entero más grande que es menor o igual que x.
double floor(double x);
double x = 2.8, y = -2.8;
printf(“%g %gn”,floor(x),floor(y));
• pow
Resultado: xy
. Si x es 0 e y es negativo o si x e y son 0 o si x es negativo e y no es entero, se
obtiene un error(argumento fuera del dominio da la función). Si xy
da un resultado superior al
valor límite para el tipo double, el resultado es el valor límite(1.79769e+308)
double pow(double x);
double x = 2.8, y = -2.8;
printf(“%gn”,pow(x,y));
• sqrt
Calcula la raíz cuadrada de x. Si x es negativo, ocurre un error(argumento fuera del dominio de la
función).
#include <math.h>
double sqrt(double x);
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 17
Números seudoaleatorios
• rand
Da como resultado un número seudoaleatorio entero, entre 0 y el valor máximo para un int.
#include <stdlib.h>
int rand(void);
Funciones de fecha y hora
• time
Resultado: el número de segundos transcurridos desde las 0 horas del 1 de Enero de 1970.
#include <time.h>
time_t time(time_t *seg);
• ctime
Convierte un tiempo almacenado como un valor de tipo time_t, en una cadena de caracteres de la
forma:
Thu Jul 08 12:01:29 2010
#include <time.h>
char *ctime(const time_t *seg);
Devuelve un puntero a la cadena de caracteres resultante o un puntero nulo si seg representa un
dato anterior al 1 de Enero de 1970.
#include <stdio.h>
#include <time.h>
main( )
{
time_t segundos;
printf("El numero de segundos transcurridos desde el 01/01/1970 es
%ldn",time(&segundos));
printf("La fecha actual es %s",ctime(&segundos));
}
• El tipo time_t está definido así:
typedef long time_t;
Funciones para manipular bloques de memoria
• memset
Permite iniciar un bloque de memoria.
#include <string.h>
void *memset(void *destino, int b, size_t nbytes);
destino: dirección del bloque de memoria que se desea inicializar.
b: valor empleado para iniciar cada byte del bloque.
nbytes: número de bytes del bloque que se iniciará.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 18
double a[10][10];
memset(a, 0, sizeof(a));
• memcpy
Copia un bloque de memoria en otro.
#include <string.h>
void *memcpy(void *destino, const void *origen, size_t nbytes);
destino: es la dirección del bloque de memoria destino de los datos.
origen: es la dirección del bloque de memoria origen de los datos.
nbytes: número de bytes que se copiarán desde el origen al destino.
double a[10][10], b[10][10];
memcpy(b, a, sizeof(a));
• memcmp
Compara byte a byte dos bloques de memoria.
#include <string.h>
int memcmp(void *bm1, const void *bm2, size_t nbytes);
bm1, bm2: son las direcciones de los bloques de memoria a comparar .
nbytes: número de bytes que se compararán.
double a[10][10], b[10][10];
if(memcmp(a, b, sizeof(a)) == 0)
printf(“Las matrices contienen los mismos datosn”);
else
printf(“Las matrices no contienen los mismos datosn”);
Ejercicios resueltos
1. Realice un programa que utilice la siguiente función:
struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2);
Haga uso de la siguiente estructura:
struct fraccion
{
int numerador;
int denominador;
};
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 19
/**************** Operaciones con fracciones ****************/
/* fraccion.c
*/
#include <stdio.h>
#include <stdlib.h>
struct fraccion
{
int numerador;
int denominador;
};
struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2);
void main()
{
struct fraccion f1, f2, *fr;
printf("Fraccion # 1: n");
printf("Numerador = ");
scanf("%d",&f1.numerador);
fflush(stdin);
printf("Denominador = ");
scanf("%d",&f1.denominador);
fflush(stdin);
printf("nFraccion # 2: n");
printf("Numerador = ");
scanf("%d",&f2.numerador);
fflush(stdin);
printf("Denominador = ");
scanf("%d",&f2.denominador);
fflush(stdin);
fr = MultiplicarFracciones(f1,f2);
printf("Resultado: %d/%dn", fr->numerador, fr->denominador);
/* Liberar la memoria asignada */
free(fr);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 20
struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2)
{
struct fraccion *producto;
/* Asignar memoria para el racional producto */
producto = (struct fraccion *)malloc(sizeof(struct fraccion));
if ( producto == NULL )
{
printf("Memoria insuficienten");
exit(-1);
}
producto->numerador = f1.numerador * f2.numerador;
producto->denominador = f1.denominador * f2.denominador;
return producto;
}
2. Dado un array constituido de números enteros que contiene N elementos, siendo N
>=1, realice una función recursiva que calcule la suma de todos los elementos del array.
//recur2.c
#include <stdio.h>
void main( )
{
int numeros[25];
int N, i;
printf("Cuantos numeros tiene el arreglo? n");
scanf("%d",&N);
printf("Introduzca el arreglo: ");
for(i = 0; i < N; i++)
scanf("%d",&numeros[i]);
printf("%d n", sumarray(numeros,0,N));
}
int sumarray(int numeros[ ], int posicion, int N)
{
if(posicion == N - 1)
return numeros[posicion];
else
return(numeros[posicion] + sumarray(numeros, posicion + 1 , N));
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 21
3. El calendario Gregoriano actual obedece a la reforma del calendario juliano que ordenó el
Papa Gregorio XIII en 1582. Se decidió, después de algunas modificaciones, que en los
sucesivo fuesen bisiestos todos los años múltiplos de 4, pero que de los años seculares(los
acabados en dos ceros) sólo fuesen bisiestos aquellos que fuesen múltiplos de 400.
Construir un programa para que dada una fecha(día, mes y año) devuelva como resultado
el día correspondiente de la semana.
/*********************************************************
CALENDARIO PERPETUO
*********************************************************/
/* Dada una fecha (dia, mes, año)
* indicar el día correspondiente de la semana.
*/
#include <stdio.h>
#include <stdlib.h>
void LeerFecha (int *dia, int *mes, int *anyo);
void EntradaDatos(int *dia, int *mes, int *anyo);
int DatosValidos(int dia, int mes, int anyo);
int AnyoBisiesto(int anyo);
void EscribirFecha( int dd, int mm, int aa);
int DiaSemana(int dia, int mes, int anyo);
void main(void) /* Función Principal */
{
int dia, mes, anyo;
LeerFecha(&dia, &mes, &anyo);
EscribirFecha(dia, mes, anyo);
}
/*********************************************************
FUNCIONES
*********************************************************/
void LeerFecha(int *dia, int *mes, int *anyo)
{
int datos_validos;
do
{
EntradaDatos(dia, mes, anyo);
datos_validos = DatosValidos(*dia, *mes, *anyo);
}
while (!datos_validos);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 22
void EntradaDatos(int *dia, int *mes, int *anyo)
{
printf("Día (1 - 31) "); scanf("%d", dia);
printf("Mes (1 - 12) "); scanf("%d", mes);
printf("Año (1582 -->) "); scanf("%d", anyo);
}
int DatosValidos(int dia, int mes, int anyo)
{
int r, anyoB, mesB, diaB;
anyoB = (anyo >= 1582);
mesB = (mes >= 1) && (mes <= 12);
switch (mes)
{
case 2:
if (r = AnyoBisiesto(anyo))
diaB = (dia >= 1) && (dia <= 29);
else
diaB = (dia >= 1) && (dia <= 28);
break;
case 4: case 6: case 9: case 11:
diaB = (dia >= 1) && (dia <= 30);
break;
default:
diaB = (dia >= 1) && (dia <= 31);
}
if (!(diaB && mesB && anyoB))
{
printf("nDATOS NO VALIDOSnn");
printf("Pulse <Entrar> para continuar ");
r = getchar( ); fflush(stdin);
return (0);
}
else
return (1);
}
int AnyoBisiesto(int anyo)
{
int verdad = 1, falso = 0;
if ((anyo % 4 == 0) && (anyo % 100 != 0) || (anyo % 400 == 0))
return (verdad);
else
return (falso);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 23
void EscribirFecha(int dd, int mm, int aa)
{
int d;
static char dia[7][10] = { "Sábado", "Domingo", "Lunes",
"Martes", "Miércoles", "Jueves",
"Viernes" };
static char mes[12][11] = { "Enero", "Febrero", "Marzo",
"Abril", "Mayo", "Junio", "Julio",
"Agosto", "Septiembre", "Octubre",
"Noviembre", "Diciembre" };
d = DiaSemana(dd, mm, aa);
printf("n%s %d de %s de %dn",dia[d], dd, mes[mm-1], aa);
}
int DiaSemana(int dia, int mes, int anyo)
{
if (mes <= 2)
{
mes = mes + 12;
anyo = anyo - 1;
}
return ((dia+2*mes+3*(mes+1)/5+anyo+anyo/4-anyo/100+anyo/400+2)%7);
}
4. El siguiente ejercicio, lee dos tablas de enteros, calcula la suma de los elementos
correspondientes, e imprime la nueva tabla que contiene esta suma.
#include <stdio.h>
#define MAXFIL 20
#define MAXCOL 30
/*Calcular la suma de los elementos de dos tablas de enteros */
main( )
{
int nfilas, ncols;
static int a[MAXFIL][MAXCOL], b[MAXFIL][MAXCOL],c[MAXFIL][MAXCOL];
/* prototipos de funcion */
void leerentrada(int a[ ][MAXCOL], int nfilas, int ncols);
void calcularsuma(int a[ ][MAXCOL], int b[ ][MAXCOL], int c[ ][MAXCOL], int nfilas, int ncols);
void sacarsalida(int c[ ][MAXCOL], int nfilas, int ncols);
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 24
printf("Cuantas filas?");
scanf("%d",&nfilas);
printf("Cuantas columnas?");
scanf("%d",&ncols);
printf("nnPrimera tabla: n");
leerentrada(a,nfilas,ncols);
printf("nnSegunda tabla: n");
leerentrada(b,nfilas,ncols);
calcularsuma(a,b,c,nfilas,ncols);
printf("nnSumas de los elementos: nn");
sacarsalida(c,nfilas,ncols);
}
void leerentrada(int a[ ][MAXCOL], int m, int n)
{
int fila,col;
for(fila = 0; fila < m ; ++fila)
{
printf("nIntroducir datos para la fila no. %2d n",fila+1);
for(col = 0; col < n; col++)
scanf("%d",&a[fila][col]);
}
return;
}
void calcularsuma(int a[ ][MAXCOL], int b[ ][MAXCOL], int c[ ][MAXCOL], int m, int n)
{
int fila,col;
for(fila = 0; fila < m ; ++fila)
for(col = 0; col < n; col++)
c[fila][col] = a[fila][col] + b[fila][col];
return;
}
void sacarsalida(int a[ ][MAXCOL], int m, int n)
{
int fila,col;
for(fila = 0; fila < m ; ++fila)
{
for(col = 0; col < n; col++)
printf("%dt",a[fila][col]);
printf("n");
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 25
return;
}
5. El cálculo de los números de Fibonacci es un ejemplo de una definición matemática
recursiva que se enuncia así: el número de Fibonacci f(i), siendo i el número de orden(0, 1, 2, 3, 4,
5, ...) del número a calcular, es igual al número de Fibonacci f(i – 1) más el número de Fibonacci f(i
– 2), sabiendo que f(0) es 0 y f(1) = 1.
f(0) = 0
f(1) = 1
f(2) = f(1) + f(0)
f(3) = f(2) + f(1)
.
.
.
f(i) = f(i - 1) + f(i – 2)
Realizar un programa que pregunte: cuántos números de Fibonacci, a partir del primero,
se quieren calcular?, almacene esos números en una matriz del tamaño necesario y finalmente los
muestre. Para ello se deberá utilizar una función recursiva con el prototipo indicado a
continuación:
int fibonacci(int n);
La función fibonacci devolverá como resultado el número de Fibonacci cuyo número de orden(0, 1,
2, ...) sea n.
Una ejecución del programa podría ser:
Cuántos números de Fibonacci, a partir del primero, se quieren calcular?
n = 10
0 1 1 2 3 5 8 13 21 34
// fibonacci.c
//
#include <stdio.h>
#include <stdlib.h>
int fibonacci(int);
int main()
{
int n = 0, i = 0, *f;
printf("¿Cuántos números de Fibonacci, a partir del ");
printf("primero, se quieren calcular?n");
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 26
do
{
printf("n = ");
i = scanf("%d", &n);
fflush(stdin);
}
while ( i == 0 || n < 1);
// Crear una matriz dinámicamente
f = (int *)malloc(n * sizeof(int));
if (f == NULL)
{
printf("Insuficiente memorian");
return -1;
}
// Obtener los números de la serie
for (i = 0; i < n; i++)
f[i] = fibonacci(i);
// Visualizar la matriz
for (i = 0; i < n; i++)
printf("%5d", f[i]);
printf("n");
// Liberar la memoria asignada a la matriz
free(f);
return 0;
}
int fibonacci(int n)
{
if ( n == 0 )
return 0;
else if ( n == 1 )
return 1;
else
return fibonacci(n-1) + fibonacci(n-2);
}
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 27
Ejercicios propuestos
1. Escribir una función que calcule el máximo de los primeros n elementos de un
array especificado. Use la siguiente función prototipo:
double maximo(const double a[], int n);
2. Realice un programa que introduzca una lista de 10 números enteros y calcule su
suma y el valor máximo. Utilice los siguientes prototipos:
int SumaDeEnteros(const int ArrayEnteros[], int noElementos);
int máximo(const int ArrayEnteros[], int noElementos);
3. Diseñe una función que convierta los caracteres de sus argumentos a mayúsculas.
Use el prototipo:
void convierte_mayus(char cad[]);
Utilice un bucle en la definición de la función, que termine cuando se alcance el fin
de cadena(carácter nulo).
4. Haciendo uso de la siguiente estructura:
struct info_persona
{
char nombre[20];
char calle[30];
char ciudad[25];
char provincia[25];
char codigopostal[6];
};
Y de los prototipos de funciones:
void entrada_pna(struct info_persona *pp);
void ver_info(struct info_persona p);
Lea e imprima los campos de la estructura haciendo uso de las funciones
anteriores.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 28
5. Realice la simulación y salida del siguiente programa:
#include <stdio.h>
void contar(int cima);
void main(void)
{
contar(10);
return;
}
void contar(int cima)
{
if(cima >1)
contar(cima - 1);
printf("%d ",cima);
}
6. Dados dos números a (número entero) y b(número natural mayor o igual que cero).
Realice una función recursiva para determinar a^b
7. Realice un programa para reordenar una lista de n enteros en una secuencia de
valores algebraicos crecientes. El programa contendrá un array unidimensional de
enteros llamado x, en el que se reordenará un elemento cada vez.
La reordenación empezará recorriendo todo el array para encontrar el menor de los
números, el cual será intercambiado con el primer elemento del array , colocando así el
menor elemento en el principio de la lista. El resto de los n - 1 elementos del array se
recorrerán para encontrar el menor, que se intercambiará con el segundo número. El
resto de los n – 2 números se recorrerán buscando el menor, que se intercambia con el
tercer número, y así sucesivamente, hasta que el array completo sea reordenado.
La función prototipo a utilizar es:
void reordenar(int n, int x[ ]);
Donde n indica la cantidad de enteros a introducir, y el array x es el arreglo donde se
almacenarán dichos números.
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 29
Una salida típica podría ser:
Cuantos números serán introducidos? 6
i = 1 x = 595
i = 2 x = 78
i = 3 x = -1505
i = 4 x = 891
i = 5 x = -29
i = 6 x = -7
Lista de números reordenada:
i = 1 x = -1505
i = 2 x = -29
i = 3 x = -7
i = 4 x = 78
i = 5 x = 595
i = 6 x = 891
8. Modificar el ejercicio anterior, de tal forma, que la función prototipo sea:
void reordenar(int n, int *x);
Utilice un array unidimensional de enteros como parámetro actual en la llamada a
dicha función. En otra ejecución, use como parámetro actual un puntero a entero.
Qué sucede con cada uno de los cambios?
9. Las torres de Hanoi son un conocido juego de niños, se juega con tres pivotes y un
cierto número de discos de distintos tamaños. Los discos tienen un agujero en el centro,
con lo que se pueden apilar en cualquiera de los pivotes. Inicialmente, los discos se
amontonan en el pivote extremo de la izquierda por tamaño decreciente, es decir, el más
grande abajo y el más pequeño arriba, como se ilustra en la figura.
4
3
2
1
Izquierda Centro Derecha
Descomposición funcional. Parte II
M.Sc. Ana María Salgado G. Página 30
El objeto del juego es conseguir llevar los discos del pivote más a la izquierda al de más a
la derecha, sin colocar nunca un disco sobre otro más pequeño. Sólo se puede mover un
disco cada vez, y cada disco debe encontrarse siempre en uno de los pivotes.
La estrategia a seguir es considerar uno de los pivotes como origen, y el otro como
destino. El tercer pivote se utilizará para almacenamiento auxiliar, con lo que podemos
mover los discos sin poner ninguno sobre otro más pequeño. Supongamos que hay n
discos, numerados del más pequeño al más grande. Si los discos se encuentran apilados
inicialmente en el pivote izquierdo, el problema de leer los n discos al pivote derecho se
puede formular de la siguiente forma recursiva:
Mover los n – 1 discos superiores del pivote izquierdo al del centro.
Mover el n-ésimo disco(el más grande) al pivote de la derecha.
Mover los n – 1 discos del pivote del centro al de la derecha.
Recuerde utilizar recursividad.

Mais conteúdo relacionado

Mais procurados

Mais procurados (19)

08 - Punteros en lenguaje C
08 - Punteros en lenguaje C08 - Punteros en lenguaje C
08 - Punteros en lenguaje C
 
Maple v comandos
Maple v comandosMaple v comandos
Maple v comandos
 
Arreglos. lidia
Arreglos. lidiaArreglos. lidia
Arreglos. lidia
 
Ada 4 DEL SEMESTRE 2
Ada 4 DEL SEMESTRE 2Ada 4 DEL SEMESTRE 2
Ada 4 DEL SEMESTRE 2
 
Algoritmos y lenjuage de programacion
Algoritmos y  lenjuage de programacionAlgoritmos y  lenjuage de programacion
Algoritmos y lenjuage de programacion
 
Perl6 expresiones regulares
Perl6 expresiones regularesPerl6 expresiones regulares
Perl6 expresiones regulares
 
Funciones en C++
Funciones en C++Funciones en C++
Funciones en C++
 
C++ y sus librerias
C++ y sus libreriasC++ y sus librerias
C++ y sus librerias
 
Fundamentos de programación librería string C++
Fundamentos de programación librería string C++Fundamentos de programación librería string C++
Fundamentos de programación librería string C++
 
Unidad6 funciones
Unidad6 funcionesUnidad6 funciones
Unidad6 funciones
 
Funciones
FuncionesFunciones
Funciones
 
FUNCIONES LENGUAJE C
FUNCIONES LENGUAJE CFUNCIONES LENGUAJE C
FUNCIONES LENGUAJE C
 
Abstracción en programación
Abstracción en programaciónAbstracción en programación
Abstracción en programación
 
Funciones C++ modificado
Funciones C++ modificadoFunciones C++ modificado
Funciones C++ modificado
 
2 punteros y lenguaje c
2 punteros y lenguaje c2 punteros y lenguaje c
2 punteros y lenguaje c
 
Notación infija postfija
Notación infija postfijaNotación infija postfija
Notación infija postfija
 
Tema 7 www.fresymetal.com
Tema 7 www.fresymetal.comTema 7 www.fresymetal.com
Tema 7 www.fresymetal.com
 
Funciones de grupo
Funciones de grupoFunciones de grupo
Funciones de grupo
 
Listas enlazadas
Listas enlazadasListas enlazadas
Listas enlazadas
 

Semelhante a Descomposicion funcional parte ii 2013 2

Semelhante a Descomposicion funcional parte ii 2013 2 (20)

arrays
arraysarrays
arrays
 
Sesion 5
Sesion 5Sesion 5
Sesion 5
 
Arreglos
ArreglosArreglos
Arreglos
 
Arreglos en C++
Arreglos en C++Arreglos en C++
Arreglos en C++
 
06 - Arrays y matrices en lenguaje C
06 - Arrays y matrices en lenguaje C06 - Arrays y matrices en lenguaje C
06 - Arrays y matrices en lenguaje C
 
Temas programacion java_2
Temas programacion java_2Temas programacion java_2
Temas programacion java_2
 
Arreglos
ArreglosArreglos
Arreglos
 
Funciones en lenguage c
Funciones en lenguage cFunciones en lenguage c
Funciones en lenguage c
 
Arrays C++
Arrays C++Arrays C++
Arrays C++
 
Lenguaje de Programacion - Java
Lenguaje de Programacion - JavaLenguaje de Programacion - Java
Lenguaje de Programacion - Java
 
Estructura de Datos
Estructura de DatosEstructura de Datos
Estructura de Datos
 
Práctica 12
Práctica 12Práctica 12
Práctica 12
 
Unidad educativa
Unidad educativaUnidad educativa
Unidad educativa
 
Clase 9- programacion
Clase 9- programacionClase 9- programacion
Clase 9- programacion
 
ARRAYS (LISTAS Y TABLAS) EN C++
ARRAYS (LISTAS Y TABLAS) EN C++ARRAYS (LISTAS Y TABLAS) EN C++
ARRAYS (LISTAS Y TABLAS) EN C++
 
UTPL-PROGRAMACIÓN AVANZADA-II-BIMESTRE-(OCTUBRE 2011-FEBRERO 2012)
UTPL-PROGRAMACIÓN AVANZADA-II-BIMESTRE-(OCTUBRE 2011-FEBRERO 2012)UTPL-PROGRAMACIÓN AVANZADA-II-BIMESTRE-(OCTUBRE 2011-FEBRERO 2012)
UTPL-PROGRAMACIÓN AVANZADA-II-BIMESTRE-(OCTUBRE 2011-FEBRERO 2012)
 
18 tipos-de-datos
18 tipos-de-datos18 tipos-de-datos
18 tipos-de-datos
 
Grupo
GrupoGrupo
Grupo
 
Tutorial de php
Tutorial de phpTutorial de php
Tutorial de php
 
Implementacion de punteros
Implementacion de punterosImplementacion de punteros
Implementacion de punteros
 

Descomposicion funcional parte ii 2013 2

  • 2. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 2 Más sobre funciones Todo programa C está formado además de por la función main, que es el punto de entrada y de salida del programa, por otras funciones, las cuales se comunican entre sí pasándose argumentos siempre que sean requeridos. Vamos a centrarnos en cuestiones más específicas como pasar argumentos a funciones que sean, matrices, estructuras y punteros, o bien devolver estos tipos de datos. Pasar una matriz como argumento a una función En C todos los arrays se pasan por referencia(dirección). Cuando se llama a una función y se utiliza un array como parámetro, se debe tener cuidado de no modificar los arrays en una función llamada. C trata automáticamente la llamada a la función como si hubiera situado el operador de dirección & delante del nombre del array. #include <stdio.h> #include <string.h> void cambiar(char c[4]); int main() { char palabra[4] = "ABC"; cambiar(palabra); puts(palabra); return 0; } void cambiar(char c[4]) { puts(c); strcpy(c,"AMA"); } Cuando se pasa un array a una función, se pasa realmente sólo la dirección de la celda de memoria donde comienza el array. Este valor se representa por el nombre del array. La función puede cambiar entonces el contenido del array accediendo directamente a las celdas de memoria en donde se almacenan los elementos del array. Los elementos del array se pueden cambiar como si se pasara por referencia. Cuando pasamos un array a una función lo que se escribe como argumento en la llamada a esa función es el nombre del array, es decir, el argumento que se pasa es la dirección del array, por lo que el parámetro formal correspondiente tiene que ser también un array, el cual, después de la llamada, queda inicializado con esa dirección.
  • 3. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 3 Los arrays son siempre pasados por referencia, porque no se pasa una copia de todos sus elementos. Tanto la función que invoca, como la función invocada trabajan sobre el mismo espacio de memoria(sobre el mismo array). #include <stdio.h> #define L 10 void leerArray(double a[], int *); void imprimirArray(const double [], int); int main() { double a[L]; int n; leerArray(a, &n); printf("nEl array a tiene %d elementos, estos sonn",n); imprimirArray(a,n); return 0; } void leerArray(double a[], int *num) { int n ; puts("Introduzca datos. Para terminar pulsar 0.n"); for(n = 0; n < L; n++) { printf("%d: ",n); scanf("%lf",&a[n]); if(a[n] == 0) break; } *num = n; } void imprimirArray(const double a[], int n) { int i; for(i = 0; i<n; i++) printf("t%d: %gn",i,a[i]); }
  • 4. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 4 Cuando se declara un array unidimensional como parámetro de una función, no se requiere que se especifique su dimensión(no se hace una reserva de memoria para una copia total del array), ya que lo que se pasa es la dirección del array. int leer(tficha bibli[ ], int NMAX); Precauciones Cuando se utiliza una variable array como argumento, la función receptora puede no conocer cuántos elementos existen en el array. Sin su conocimiento una función no puede utilizar el array. Aunque la variable array puede apuntar al comienzo de él, no proporciona ninguna indicación de dónde termina el arreglo. La función SumaDeEnteros() suma los valores de todos los elementos de un array y devuelve el total. int SumaDeEnteros(int *ArrayEnteros) { … } int main() { int lista[5] = {10, 11, 12, 13, 14}; SumaDeEnteros(lista); … } Aunque SumaDeEnteros() conoce dónde comienza el array, no conoce cuántos elementos hay en el array, en consecuencia, no sabe cuántos elementos hay que sumar. Se pueden utilizar dos métodos alternativos para permitir que una función conozca el número de argumentos asociados con un array que se pasa como argumento de una función: • Situar un valor de señal al final del array, que indique a la función que se ha de detener el proceso en ese momento. • Pasar un segundo argumento que indica el número de elementos del array. Todas las cadenas utilizan el primer método ya que terminan en nulo. Una segunda alternativa es pasar el número de elementos del array siempre que se pasa el array como un argumento. El array y el número de elementos se convierten entonces en una pareja de argumentos que se asocian con la función llamada. La función SumaDeEnteros(), por ejemplo, se puede actualizar así: int SumaDeEnteros(int ArrayEnteros[], int noElementos) { … }
  • 5. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 5 El segundo argumento, noElementos, es un valor entero que indica a la función int SumaDeEnteros() cuántos elementos se procesarán en el array ArrayEnteros. Este método suele ser el utilizado para arrays de elementos que no son caracteres. Ejemplo: /********************** Programa Alumnos **********************/ // Versión con punteros #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #define N 100 /* número máximo de alumnos */ typedef struct { char matricula[10]; char apellidos[30]; char nombre[20]; char direccion[30]; } ficha; int leer(ficha *, const int); void buscar(ficha *, char *, int, int); int menu(void); void main( ) { static ficha lista[N]; char dato[30]; /* dato a buscar */ int opcion; /* opción elegida en el menú */ int n = 0; /* número de alumnos leídos */ while (1) /* bucle infinito. Se sale con break. */ { opcion = menu( ); if (opcion != 4) { switch (opcion) { case 1: /* entrada de los datos de los alumnos */ n = leer(lista, N); break; case 2: /* búsqueda por el número de matrícula */ system("cls"); printf("Número de matrícula "); gets(dato); buscar(lista, dato, n, opcion); break;
  • 6. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 6 case 3: /* Búsqueda por los apellidos */ system("cls"); printf("Apellidos.......... "); gets(dato); buscar(lista, dato, n, opcion); break; } } else break; } } /**************************************************************** Función para visualizar el menú ****************************************************************/ int menu(void) { int op; do { system("cls"); printf("nt1. Entrada de datos de alumnosn"); printf("nt2. Busqueda por nro. de matriculan"); printf("nt3. Busqueda por apellidosn"); printf("nt4. Finn"); printf("nnTeclee la opcion deseada: "); scanf("%d", &op); fflush(stdin); } while (op < 1 || op > 4); return (op); } /**************************************************************** Función para leer los datos correspondientes a un alumno ****************************************************************/ int leer(ficha *lista, const int NMAX) { int n = 0; char resp = 's';
  • 7. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 7 while (tolower(resp) == 's' && n < NMAX) { do { system("cls"); printf("Alumno numero %dnn", n+1); printf("Numero de matrícula: "); gets(lista[n].matricula); printf("Apellidos.......... "); gets(lista[n].apellidos); printf("Nombre............. "); gets(lista[n].nombre); printf("Dirección.......... "); gets(lista[n].direccion); printf("nn¿ Datos correctos ? s/n "); fflush(stdin); resp = getchar(); } while (tolower(resp) != 's'); n++; printf("nn¿ Más datos a introducir ? s/n "); resp = getchar(); fflush(stdin); } return (n); } /**************************************************************** Función para buscar si existe o no un dato ****************************************************************/ void buscar(ficha *lista, char *x, int alumnos, int opcion) { const int NO = 0; const int SI = 1; int existe = NO, i = 0; char resp; switch(opcion) { case 2: /* búsqueda por número de matrícula */ while (!existe && i < alumnos) if (strcmp(lista[i++].matricula, x) == 0) existe = SI; break; case 3: /* Búsqueda por apellidos */ while (!existe && i < alumnos) if (strcmp(lista[i++].apellidos, x) == 0) existe = SI; break; }
  • 8. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 8 if (existe) printf("n%sn%s %sn%sn", lista[i-1].matricula, lista[i-1].apellidos, lista[i- 1].nombre, lista[i-1].direccion); else printf("n%s no existe", x); printf("nnPulse <Entrar> para continuar "); resp = getchar( ); fflush(stdin); } Si el array es multidimensional, no es necesario especificar la primera dimensión, pero sí las restantes. void CopiarArray(float destino[ ][COLS], float origen[ ][COLS]); El nombre de un array y un puntero no son lo mismo, pero en lugar del nombre de una array unidimensional, podemos usar un puntero que almacene la dirección de comienzo del array para acceder a los elementos del mismo. El identificador de un array y un puntero no son lo mismo, lo que imposibilita en el caso de arrays de dos dimensiones utilizar en lugar del nombre del array, un puntero a un puntero que almacene la dirección de comienzo del array para acceder a los elementos del mismo. /************** Fusionar dos listas clasificadas **************/ /* Versión con punteros */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define NML 120 /* número máximo de líneas */ #define CPL 60 /* caracteres por línea */ int fusionar(char **, int, char **, int, char **, const int); void Error(void); void main( ) { /* Inicializamos las listas a clasificar con el fin de no tener * que leer los datos y realizar así una prueba rápida. */ static char *listaActual[ ] = { "Ana", "Carmen", "David", "Francisco", "Javier", "Jesús", "José", "Josefina", "Luís", "María", "Patricia", "Sonia" };
  • 9. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 9 static char *listaNueva[ ] = { "Agustín", "Belén", "Daniel", "Fernando", "Manuel", "Pedro", "Rosa", "Susana" }; /* Calcular el número de elementos de los arrays anteriores */ const int dimA = sizeof(listaActual)/sizeof(listaActual[0]); const int dimN = sizeof(listaNueva)/sizeof(listaNueva[0]); /* Definir el array resultante de fusionar los anteriores */ static char **listaFinal; // referencia el array resultante int ind, r; /* Asignar memoria para el array de punteros listaFinal */ listaFinal = (char **)malloc((dimA+dimN) * sizeof(char *)); if (listaFinal = = NULL) Error( ); /* Inicializa el array de punteros. Esto evita problemas al liberar memoria, en el supuesto de un error por falta de memoria */ for (ind = 0; ind < dimA+dimN; ind++) listaFinal[ind] = NULL; /* Fusionar listaActual y listaNueva y almacenar en resultado en * listaFinal. La función "fusionar" devuelve un 0 si no se * pudo realizar la fusión. */ r = fusionar(listaActual, dimA, listaNueva, dimN, listaFinal, NML); /* Escribir el array resultante */ if (r) { for (ind = 0; ind < dimA+dimN; ind++) printf("%sn", listaFinal[ind]); } else Error( ); /* Liberar la memoria ocupada por el array listaFinal */ for (ind = 0; ind < dimA+dimN; ind++) free(listaFinal[ind]); free(listaFinal); }
  • 10. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 10 /**************************************************************** F U S I O N A R ****************************************************************/ int fusionar(char **listaA, int dimA, char **listaN, int dimN, char **listaF, const int nml) { int ind = 0, indA = 0, indN = 0, indF = 0; while (indA < dimA && indN < dimN) if (strcmp(listaA[indA], listaN[indN]) < 0) { listaF[indF] = (char *)malloc(strlen(listaA[indA]) + 1); if (listaF[indF] = = NULL) return 0; strcpy(listaF[indF++], listaA[indA++]); } else { listaF[indF] = (char *)malloc(strlen(listaN[indN]) + 1); if (listaF[indF] = = NULL) return 0; strcpy(listaF[indF++], listaN[indN++]); } /* Los dos lazos siguientes son para prever el caso de que, * lógicamente una lista finalizará antes que la otra. */ for (ind = indA; ind < dimA; ind++) { listaF[indF] = (char *)malloc(strlen(listaA[indA]) + 1); if (listaF[indF] = = NULL) return 0; strcpy(listaF[indF++], listaA[ind]); } for (ind = indN; ind < dimN; ind++) { listaF[indF] = (char *)malloc(strlen(listaN[indN]) + 1); if (listaF[indF] = = NULL) return 0; strcpy(listaF[indF++], listaN[ind]); } return(1); } void Error(void) { puts("Longitud no válida de la lista resultante"); exit(1); }
  • 11. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 11 Pasar una estructura a una función Una estructura puede ser pasada a una función por valor o por referencia. Cuando pasamos una estructura por valor, el parámetro actual que representa la estructura se copia en el correspondiente parámetro formal, produciéndose un duplicado. Si alguno de los miembros del parámetro formal se modifica, los cambios no afectan al parámetro actual correspondiente. Si pasamos la estructura por referencia, lo que recibe la función es el lugar de la memoria donde se localiza dicha estructura. /**************** Operaciones con complejos ****************/ #include <stdio.h> typedef struct { float real; float imag; } tcomplejo; void SumarComplejos(tcomplejo c1, tcomplejo c2, tcomplejo *p); void main( ) { tcomplejo ca, cb, cc; printf("nIntroducir datos de la forma: x yin"); printf("ca = "); scanf("%f %f", &ca.real,&ca.imag); fflush(stdin); printf("cb = "); scanf("%f %f", &cb.real,&cb.imag); fflush(stdin); SumarComplejos(ca, cb, &cc); printf("Resultado: %g%+gin", cc.real, cc.imag); } void SumarComplejos(tcomplejo c1, tcomplejo c2, tcomplejo *p) { p->real = c1.real + c2.real; p->imag = c1.imag + c2.imag; }
  • 12. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 12 Función que retorna un puntero Cuando una función retorna un puntero a un objeto, el objeto debe persistir después de finalizar la función. /**************** Operaciones con complejos ****************/ #include <stdio.h> #include <stdlib.h> typedef struct { float real; float imag; } tcomplejo; tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2); void main( ) { tcomplejo ca, cb, *pcr; printf("nIntroducir datos de la forma: x yin"); printf("ca = "); scanf("%f %f", &ca.real,&ca.imag); fflush(stdin); printf("cb = "); scanf("%f %f", &cb.real,&cb.imag); fflush(stdin); pcr = SumarComplejos(ca, cb); printf("Resultado: %g%+gin", pcr->real, pcr->imag); } tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2) { tcomplejo cx; cx.real = c1.real + c2.real; cx.imag = c1.imag + c2.imag; return &cx; } El programa anterior presenta resultados inesperados. La función SumarComplejos, utiliza un complejo local cx del cual retorna su dirección. Cuando la función finalice el complejo cx se destruirá automáticamente, con lo que el puntero pcr que apunta al resultado, estará apuntando a un objeto inexistente.
  • 13. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 13 La solución radica en hacer que la función SumarComplejos cree un objeto que persista a lo largo de la ejecución del programa, asignando memoria dinámicamente para el objeto. /**************** Operaciones con complejos ****************/ #include <stdio.h> #include <stdlib.h> typedef struct { float real; float imag; } tcomplejo; tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2); void main( ) { tcomplejo ca, cb, *pcr; printf("nIntroducir datos de la forma: x yin"); printf("ca = "); scanf("%f %f", &ca.real,&ca.imag); fflush(stdin); printf("cb = "); scanf("%f %f", &cb.real,&cb.imag); fflush(stdin); pcr = SumarComplejos(ca, cb); printf("Resultado: %g%+gin", pcr->real, pcr->imag); /* Liberar la memoria asignada */ free(pcr); } tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2) { tcomplejo *pcx; /* Asignar memoria para el complejo suma */ pcx = (tcomplejo *)malloc(sizeof(tcomplejo)); if ( pcx = = NULL ) { printf("Memoria insuficienten"); exit(-1); } pcx->real = c1.real + c2.real; pcx->imag = c1.imag + c2.imag; return pcx; }
  • 14. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 14 Funciones recursivas Una función recursiva es aquella que se llama a sí misma. El compilador C permite cualquier número de llamadas recursivas a una función. Cada vez que la función es llamada, los parámetros formales son inicializados. Se utiliza una función recursiva, cuando el proceso a programar es por definición recursivo. Por ejemplo, el cálculo del factorial de un número por definición es un proceso recursivo. n! = n(n-1)! /************* Cálculo del factorial de un número *************/ #include <stdio.h> unsigned long factorial(int n); void main( ) { int numero; unsigned long fac; do { printf("¿Número? "); scanf("%d", &numero); } while (numero < 0 || numero > 12); fac = factorial(numero); printf("nEl factorial de %d es %ldn", numero, fac); } unsigned long factorial(int n) { if (n == 0) return 1; else return n*factorial(n-1); } Para n = 4, el proceso seguido por la función es: Nivel de recursión Proceso de ida Proceso de vuelta 0 factorial(4) 24 1 4 * factorial(3) 4 * 6 2 3 * factorial(2) 3 * 2 3 2 * factorial(1) 2 * 1 4 1 * factorial(0) 1 * 1 factorial(0) 1
  • 15. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 15 El uso de la recursión debe evitarse cuando haya una solución obvia por iteración. La llamada a una función recursiva consume mucho espacio de pila debido a que por cada llamada las variables que intervienen en la función son salvadas en la pila para posteriormente poder iniciar la vuelta. Funciones predefinidas en c Funciones matemáticas: Las declaraciones para estas funciones están en el fichero math.h Los argumentos y el resultado son de tipo double. En muchos casos utilizaremos conversión cast para convertir explícitamente los argumentos al tipo deseado. Ejemplo: a = tan((double)valor); Las funciones matemáticas se clasifican en: • Funciones trigonométricas • Funciones hiperbólicas. • Funciones exponencial y logarítimica. • Funciones varias. • cos: La función cos da como resultado el coseno de x ( x en radianes). #include <math.h> double cos(double x); • sin: La función sin da como resultado el seno de x ( x en radianes). #include <math.h> double sin(double x); • tan: La función tan da como resultado la tangente de x ( x en radianes). #include <math.h> double tan(double x); • cosh: La función cosh da como resultado el coseno hiperbólico de x ( x en radianes). #include <math.h> double cosh(double x); • sinh: La función sinh da como resultado el seno hiperbólico de x ( x en radianes). #include <math.h> double sinh(double x); • tanh: La función tanh da como resultado la tangente hiperbólica de x ( x en radianes). #include <math.h> double tanh(double x); • exp Da como resultado el valor de ex ( e = 2.718282) #include <math.h> double exp(double x);
  • 16. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 16 • log Da como resultado el logaritmo natural de x . #include <math.h> double log(double x); • log10 Da como resultado el logaritmo en base 10 de x . #include <math.h> double log10(double x); • ceil Resultado: un valor double, que representa el entero más pequeño que es mayor o igual que x. #include <math.h> double ceil(double x); double x = 2.8, y = -2.8; printf(“%g %gn”,ceil(x),ceil(y)); • fabs Calcula el valor absoluto de x( siendo x un valor real en doble precisión). Las funciones abs y labs calculan el valor absoluto de un int y un long respectivamente. #include <math.h> double fabs(double x); • floor Resultado: un valor double, que representa el entero más grande que es menor o igual que x. double floor(double x); double x = 2.8, y = -2.8; printf(“%g %gn”,floor(x),floor(y)); • pow Resultado: xy . Si x es 0 e y es negativo o si x e y son 0 o si x es negativo e y no es entero, se obtiene un error(argumento fuera del dominio da la función). Si xy da un resultado superior al valor límite para el tipo double, el resultado es el valor límite(1.79769e+308) double pow(double x); double x = 2.8, y = -2.8; printf(“%gn”,pow(x,y)); • sqrt Calcula la raíz cuadrada de x. Si x es negativo, ocurre un error(argumento fuera del dominio de la función). #include <math.h> double sqrt(double x);
  • 17. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 17 Números seudoaleatorios • rand Da como resultado un número seudoaleatorio entero, entre 0 y el valor máximo para un int. #include <stdlib.h> int rand(void); Funciones de fecha y hora • time Resultado: el número de segundos transcurridos desde las 0 horas del 1 de Enero de 1970. #include <time.h> time_t time(time_t *seg); • ctime Convierte un tiempo almacenado como un valor de tipo time_t, en una cadena de caracteres de la forma: Thu Jul 08 12:01:29 2010 #include <time.h> char *ctime(const time_t *seg); Devuelve un puntero a la cadena de caracteres resultante o un puntero nulo si seg representa un dato anterior al 1 de Enero de 1970. #include <stdio.h> #include <time.h> main( ) { time_t segundos; printf("El numero de segundos transcurridos desde el 01/01/1970 es %ldn",time(&segundos)); printf("La fecha actual es %s",ctime(&segundos)); } • El tipo time_t está definido así: typedef long time_t; Funciones para manipular bloques de memoria • memset Permite iniciar un bloque de memoria. #include <string.h> void *memset(void *destino, int b, size_t nbytes); destino: dirección del bloque de memoria que se desea inicializar. b: valor empleado para iniciar cada byte del bloque. nbytes: número de bytes del bloque que se iniciará.
  • 18. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 18 double a[10][10]; memset(a, 0, sizeof(a)); • memcpy Copia un bloque de memoria en otro. #include <string.h> void *memcpy(void *destino, const void *origen, size_t nbytes); destino: es la dirección del bloque de memoria destino de los datos. origen: es la dirección del bloque de memoria origen de los datos. nbytes: número de bytes que se copiarán desde el origen al destino. double a[10][10], b[10][10]; memcpy(b, a, sizeof(a)); • memcmp Compara byte a byte dos bloques de memoria. #include <string.h> int memcmp(void *bm1, const void *bm2, size_t nbytes); bm1, bm2: son las direcciones de los bloques de memoria a comparar . nbytes: número de bytes que se compararán. double a[10][10], b[10][10]; if(memcmp(a, b, sizeof(a)) == 0) printf(“Las matrices contienen los mismos datosn”); else printf(“Las matrices no contienen los mismos datosn”); Ejercicios resueltos 1. Realice un programa que utilice la siguiente función: struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2); Haga uso de la siguiente estructura: struct fraccion { int numerador; int denominador; };
  • 19. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 19 /**************** Operaciones con fracciones ****************/ /* fraccion.c */ #include <stdio.h> #include <stdlib.h> struct fraccion { int numerador; int denominador; }; struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2); void main() { struct fraccion f1, f2, *fr; printf("Fraccion # 1: n"); printf("Numerador = "); scanf("%d",&f1.numerador); fflush(stdin); printf("Denominador = "); scanf("%d",&f1.denominador); fflush(stdin); printf("nFraccion # 2: n"); printf("Numerador = "); scanf("%d",&f2.numerador); fflush(stdin); printf("Denominador = "); scanf("%d",&f2.denominador); fflush(stdin); fr = MultiplicarFracciones(f1,f2); printf("Resultado: %d/%dn", fr->numerador, fr->denominador); /* Liberar la memoria asignada */ free(fr); }
  • 20. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 20 struct fraccion *MultiplicarFracciones(struct fraccion f1, struct fraccion f2) { struct fraccion *producto; /* Asignar memoria para el racional producto */ producto = (struct fraccion *)malloc(sizeof(struct fraccion)); if ( producto == NULL ) { printf("Memoria insuficienten"); exit(-1); } producto->numerador = f1.numerador * f2.numerador; producto->denominador = f1.denominador * f2.denominador; return producto; } 2. Dado un array constituido de números enteros que contiene N elementos, siendo N >=1, realice una función recursiva que calcule la suma de todos los elementos del array. //recur2.c #include <stdio.h> void main( ) { int numeros[25]; int N, i; printf("Cuantos numeros tiene el arreglo? n"); scanf("%d",&N); printf("Introduzca el arreglo: "); for(i = 0; i < N; i++) scanf("%d",&numeros[i]); printf("%d n", sumarray(numeros,0,N)); } int sumarray(int numeros[ ], int posicion, int N) { if(posicion == N - 1) return numeros[posicion]; else return(numeros[posicion] + sumarray(numeros, posicion + 1 , N)); }
  • 21. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 21 3. El calendario Gregoriano actual obedece a la reforma del calendario juliano que ordenó el Papa Gregorio XIII en 1582. Se decidió, después de algunas modificaciones, que en los sucesivo fuesen bisiestos todos los años múltiplos de 4, pero que de los años seculares(los acabados en dos ceros) sólo fuesen bisiestos aquellos que fuesen múltiplos de 400. Construir un programa para que dada una fecha(día, mes y año) devuelva como resultado el día correspondiente de la semana. /********************************************************* CALENDARIO PERPETUO *********************************************************/ /* Dada una fecha (dia, mes, año) * indicar el día correspondiente de la semana. */ #include <stdio.h> #include <stdlib.h> void LeerFecha (int *dia, int *mes, int *anyo); void EntradaDatos(int *dia, int *mes, int *anyo); int DatosValidos(int dia, int mes, int anyo); int AnyoBisiesto(int anyo); void EscribirFecha( int dd, int mm, int aa); int DiaSemana(int dia, int mes, int anyo); void main(void) /* Función Principal */ { int dia, mes, anyo; LeerFecha(&dia, &mes, &anyo); EscribirFecha(dia, mes, anyo); } /********************************************************* FUNCIONES *********************************************************/ void LeerFecha(int *dia, int *mes, int *anyo) { int datos_validos; do { EntradaDatos(dia, mes, anyo); datos_validos = DatosValidos(*dia, *mes, *anyo); } while (!datos_validos); }
  • 22. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 22 void EntradaDatos(int *dia, int *mes, int *anyo) { printf("Día (1 - 31) "); scanf("%d", dia); printf("Mes (1 - 12) "); scanf("%d", mes); printf("Año (1582 -->) "); scanf("%d", anyo); } int DatosValidos(int dia, int mes, int anyo) { int r, anyoB, mesB, diaB; anyoB = (anyo >= 1582); mesB = (mes >= 1) && (mes <= 12); switch (mes) { case 2: if (r = AnyoBisiesto(anyo)) diaB = (dia >= 1) && (dia <= 29); else diaB = (dia >= 1) && (dia <= 28); break; case 4: case 6: case 9: case 11: diaB = (dia >= 1) && (dia <= 30); break; default: diaB = (dia >= 1) && (dia <= 31); } if (!(diaB && mesB && anyoB)) { printf("nDATOS NO VALIDOSnn"); printf("Pulse <Entrar> para continuar "); r = getchar( ); fflush(stdin); return (0); } else return (1); } int AnyoBisiesto(int anyo) { int verdad = 1, falso = 0; if ((anyo % 4 == 0) && (anyo % 100 != 0) || (anyo % 400 == 0)) return (verdad); else return (falso); }
  • 23. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 23 void EscribirFecha(int dd, int mm, int aa) { int d; static char dia[7][10] = { "Sábado", "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes" }; static char mes[12][11] = { "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" }; d = DiaSemana(dd, mm, aa); printf("n%s %d de %s de %dn",dia[d], dd, mes[mm-1], aa); } int DiaSemana(int dia, int mes, int anyo) { if (mes <= 2) { mes = mes + 12; anyo = anyo - 1; } return ((dia+2*mes+3*(mes+1)/5+anyo+anyo/4-anyo/100+anyo/400+2)%7); } 4. El siguiente ejercicio, lee dos tablas de enteros, calcula la suma de los elementos correspondientes, e imprime la nueva tabla que contiene esta suma. #include <stdio.h> #define MAXFIL 20 #define MAXCOL 30 /*Calcular la suma de los elementos de dos tablas de enteros */ main( ) { int nfilas, ncols; static int a[MAXFIL][MAXCOL], b[MAXFIL][MAXCOL],c[MAXFIL][MAXCOL]; /* prototipos de funcion */ void leerentrada(int a[ ][MAXCOL], int nfilas, int ncols); void calcularsuma(int a[ ][MAXCOL], int b[ ][MAXCOL], int c[ ][MAXCOL], int nfilas, int ncols); void sacarsalida(int c[ ][MAXCOL], int nfilas, int ncols);
  • 24. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 24 printf("Cuantas filas?"); scanf("%d",&nfilas); printf("Cuantas columnas?"); scanf("%d",&ncols); printf("nnPrimera tabla: n"); leerentrada(a,nfilas,ncols); printf("nnSegunda tabla: n"); leerentrada(b,nfilas,ncols); calcularsuma(a,b,c,nfilas,ncols); printf("nnSumas de los elementos: nn"); sacarsalida(c,nfilas,ncols); } void leerentrada(int a[ ][MAXCOL], int m, int n) { int fila,col; for(fila = 0; fila < m ; ++fila) { printf("nIntroducir datos para la fila no. %2d n",fila+1); for(col = 0; col < n; col++) scanf("%d",&a[fila][col]); } return; } void calcularsuma(int a[ ][MAXCOL], int b[ ][MAXCOL], int c[ ][MAXCOL], int m, int n) { int fila,col; for(fila = 0; fila < m ; ++fila) for(col = 0; col < n; col++) c[fila][col] = a[fila][col] + b[fila][col]; return; } void sacarsalida(int a[ ][MAXCOL], int m, int n) { int fila,col; for(fila = 0; fila < m ; ++fila) { for(col = 0; col < n; col++) printf("%dt",a[fila][col]); printf("n"); }
  • 25. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 25 return; } 5. El cálculo de los números de Fibonacci es un ejemplo de una definición matemática recursiva que se enuncia así: el número de Fibonacci f(i), siendo i el número de orden(0, 1, 2, 3, 4, 5, ...) del número a calcular, es igual al número de Fibonacci f(i – 1) más el número de Fibonacci f(i – 2), sabiendo que f(0) es 0 y f(1) = 1. f(0) = 0 f(1) = 1 f(2) = f(1) + f(0) f(3) = f(2) + f(1) . . . f(i) = f(i - 1) + f(i – 2) Realizar un programa que pregunte: cuántos números de Fibonacci, a partir del primero, se quieren calcular?, almacene esos números en una matriz del tamaño necesario y finalmente los muestre. Para ello se deberá utilizar una función recursiva con el prototipo indicado a continuación: int fibonacci(int n); La función fibonacci devolverá como resultado el número de Fibonacci cuyo número de orden(0, 1, 2, ...) sea n. Una ejecución del programa podría ser: Cuántos números de Fibonacci, a partir del primero, se quieren calcular? n = 10 0 1 1 2 3 5 8 13 21 34 // fibonacci.c // #include <stdio.h> #include <stdlib.h> int fibonacci(int); int main() { int n = 0, i = 0, *f; printf("¿Cuántos números de Fibonacci, a partir del "); printf("primero, se quieren calcular?n");
  • 26. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 26 do { printf("n = "); i = scanf("%d", &n); fflush(stdin); } while ( i == 0 || n < 1); // Crear una matriz dinámicamente f = (int *)malloc(n * sizeof(int)); if (f == NULL) { printf("Insuficiente memorian"); return -1; } // Obtener los números de la serie for (i = 0; i < n; i++) f[i] = fibonacci(i); // Visualizar la matriz for (i = 0; i < n; i++) printf("%5d", f[i]); printf("n"); // Liberar la memoria asignada a la matriz free(f); return 0; } int fibonacci(int n) { if ( n == 0 ) return 0; else if ( n == 1 ) return 1; else return fibonacci(n-1) + fibonacci(n-2); }
  • 27. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 27 Ejercicios propuestos 1. Escribir una función que calcule el máximo de los primeros n elementos de un array especificado. Use la siguiente función prototipo: double maximo(const double a[], int n); 2. Realice un programa que introduzca una lista de 10 números enteros y calcule su suma y el valor máximo. Utilice los siguientes prototipos: int SumaDeEnteros(const int ArrayEnteros[], int noElementos); int máximo(const int ArrayEnteros[], int noElementos); 3. Diseñe una función que convierta los caracteres de sus argumentos a mayúsculas. Use el prototipo: void convierte_mayus(char cad[]); Utilice un bucle en la definición de la función, que termine cuando se alcance el fin de cadena(carácter nulo). 4. Haciendo uso de la siguiente estructura: struct info_persona { char nombre[20]; char calle[30]; char ciudad[25]; char provincia[25]; char codigopostal[6]; }; Y de los prototipos de funciones: void entrada_pna(struct info_persona *pp); void ver_info(struct info_persona p); Lea e imprima los campos de la estructura haciendo uso de las funciones anteriores.
  • 28. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 28 5. Realice la simulación y salida del siguiente programa: #include <stdio.h> void contar(int cima); void main(void) { contar(10); return; } void contar(int cima) { if(cima >1) contar(cima - 1); printf("%d ",cima); } 6. Dados dos números a (número entero) y b(número natural mayor o igual que cero). Realice una función recursiva para determinar a^b 7. Realice un programa para reordenar una lista de n enteros en una secuencia de valores algebraicos crecientes. El programa contendrá un array unidimensional de enteros llamado x, en el que se reordenará un elemento cada vez. La reordenación empezará recorriendo todo el array para encontrar el menor de los números, el cual será intercambiado con el primer elemento del array , colocando así el menor elemento en el principio de la lista. El resto de los n - 1 elementos del array se recorrerán para encontrar el menor, que se intercambiará con el segundo número. El resto de los n – 2 números se recorrerán buscando el menor, que se intercambia con el tercer número, y así sucesivamente, hasta que el array completo sea reordenado. La función prototipo a utilizar es: void reordenar(int n, int x[ ]); Donde n indica la cantidad de enteros a introducir, y el array x es el arreglo donde se almacenarán dichos números.
  • 29. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 29 Una salida típica podría ser: Cuantos números serán introducidos? 6 i = 1 x = 595 i = 2 x = 78 i = 3 x = -1505 i = 4 x = 891 i = 5 x = -29 i = 6 x = -7 Lista de números reordenada: i = 1 x = -1505 i = 2 x = -29 i = 3 x = -7 i = 4 x = 78 i = 5 x = 595 i = 6 x = 891 8. Modificar el ejercicio anterior, de tal forma, que la función prototipo sea: void reordenar(int n, int *x); Utilice un array unidimensional de enteros como parámetro actual en la llamada a dicha función. En otra ejecución, use como parámetro actual un puntero a entero. Qué sucede con cada uno de los cambios? 9. Las torres de Hanoi son un conocido juego de niños, se juega con tres pivotes y un cierto número de discos de distintos tamaños. Los discos tienen un agujero en el centro, con lo que se pueden apilar en cualquiera de los pivotes. Inicialmente, los discos se amontonan en el pivote extremo de la izquierda por tamaño decreciente, es decir, el más grande abajo y el más pequeño arriba, como se ilustra en la figura. 4 3 2 1 Izquierda Centro Derecha
  • 30. Descomposición funcional. Parte II M.Sc. Ana María Salgado G. Página 30 El objeto del juego es conseguir llevar los discos del pivote más a la izquierda al de más a la derecha, sin colocar nunca un disco sobre otro más pequeño. Sólo se puede mover un disco cada vez, y cada disco debe encontrarse siempre en uno de los pivotes. La estrategia a seguir es considerar uno de los pivotes como origen, y el otro como destino. El tercer pivote se utilizará para almacenamiento auxiliar, con lo que podemos mover los discos sin poner ninguno sobre otro más pequeño. Supongamos que hay n discos, numerados del más pequeño al más grande. Si los discos se encuentran apilados inicialmente en el pivote izquierdo, el problema de leer los n discos al pivote derecho se puede formular de la siguiente forma recursiva: Mover los n – 1 discos superiores del pivote izquierdo al del centro. Mover el n-ésimo disco(el más grande) al pivote de la derecha. Mover los n – 1 discos del pivote del centro al de la derecha. Recuerde utilizar recursividad.