Funciones

Anuncio
Departamento de Computación
Funciones
UNAN - LEON
Funciones
•Una función es una colección independiente de
declaraciones y sentencias, enfocadas a realizar una tarea
específica.
•Todo programa C consta al menos de una función, la
función main, por donde empieza siempre la ejecución de un
programa.
void main( )
int fn1(int z)
void fn2( )
{
{
{
n = fn1(x);
//........
m = fn1(y);
fn2( );
}
}
//........
}
Departamento de Computación
1
Funciones
UNAN - LEON
Pasar un array a una función
• 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.
• 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).
2
1
Departamento de Computación
Funciones
UNAN - LEON
• 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);
• 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
pero en lugar
podemos usar
comienzo del
mismo.
un array y un puntero no son lo mismo,
del nombre de una array unidimensional,
un puntero que almacene la dirección de
array para acceder a los elementos del
3
Departamento de Computación
Funciones
UNAN - LEON
/********************** 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);
4
2
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;
case 3: /* Búsqueda por los apellidos */
system("cls");
printf("Apellidos.......... "); gets(dato);
buscar(lista, dato, n, opcion);
break;
}
}
else
break;
}
}
Funciones
5
Funciones
/****************************************************************
Función para visualizar el menú
****************************************************************/
int menu(void)
{
int op;
do
{
system("cls");
printf("\n\t1. Entrada de datos de alumnos\n");
printf("\n\t2. Búsqueda por nro. de matrícula\n");
printf("\n\t3. Búsqueda por apellidos\n");
printf("\n\t4. Fin\n");
printf("\n\nTeclee la opción deseada ");
scanf("%d", &op);
fflush(stdin);
}
while (op < 1 || op > 4);
return (op);
}
6
3
/****************************************************************
Función para leer los datos correspondientes a un alumno
****************************************************************/
int leer(ficha *lista, const int NMAX)
{
int n = 0;
char resp = 's';
while (tolower(resp) == 's' && n < NMAX)
{
do
{
system("cls");
printf("Alumno número %d\n\n", n+1);
printf("Número 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("\n\n¿ Datos correctos ? s/n ");
resp = getchar();
fflush(stdin);
} while (tolower(resp) != 's');
n++;
printf("\n\n¿ Más datos a introducir ? s/n ");
resp = getchar();
fflush(stdin);
}
return (n);
}
7
Funciones
/****************************************************************
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
4
Funciones
if (existe)
printf("\n%s\n%s %s\n%s\n", lista[i-1].matricula,
lista[i-1].apellidos,
lista[i-1].nombre,
lista[i-1].direccion);
else
printf("\n%s no existe", x);
printf("\n\nPulse <Entrar> para continuar ");
resp = getchar( );
fflush(stdin);
}
• 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.
9
Funciones
/************** 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" };
10
5
Funciones
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);
Departamento de Computación
11
Funciones
UNAN - LEON
/* Escribir el array resultante */
if (r)
{
for (ind = 0; ind < dimA+dimN; ind++)
printf("%s\n", listaFinal[ind]);
}
else
Error( );
/* Liberar la memoria ocupada por el array listaFinal */
for (ind = 0; ind < dimA+dimN; ind++)
free(listaFinal[ind]);
free(listaFinal);
}
12
6
Funciones
/****************************************************************
FUSIONAR
****************************************************************/
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++]);
}
13
Funciones
/* 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);
}
14
7
Departamento de Computación
Funciones
UNAN - LEON
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.
15
/**************** 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 yi\n");
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%+gi\n", cc.real, cc.imag);
}
void SumarComplejos(tcomplejo c1, tcomplejo c2, tcomplejo *p)
{
p->real = c1.real + c2.real;
p->imag = c1.imag + c2.imag;
}
16
8
Departamento de Computación
Funciones
UNAN - LEON
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);
17
void main( )
{
tcomplejo ca, cb, *pcr;
printf("\nIntroducir datos de la forma: x yi\n");
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%+gi\n", 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;
}
18
9
Departamento de Computación
Funciones
UNAN - LEON
• 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.
• 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.
19
/**************** 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 yi\n");
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%+gi\n", pcr->real, pcr->imag);
/* Liberar la memoria asignada */
free(pcr);
}
20
10
tcomplejo *SumarComplejos(tcomplejo c1, tcomplejo c2)
{
tcomplejo *pcx;
/* Asignar memoria para el complejo suma */
pcx = (tcomplejo *)malloc(sizeof(tcomplejo));
if ( pcx = = NULL )
{
printf("Memoria insuficiente\n");
exit(-1);
}
pcx->real = c1.real + c2.real;
pcx->imag = c1.imag + c2.imag;
return pcx;
}
21
Departamento de Computación
Funciones
UNAN - LEON
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)!
22
11
/************* 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 %ld\n", numero, fac);
}
unsigned long factorial(int n)
{
if (n = = 0)
return 1;
else
return n*factorial(n-1);
}
23
• Para n = 4, el proceso seguido por la función es:
Nivel de recursión
Proceso de ida
Proceso de vuelta
0
1
2
3
4
factorial(4)
24
4 * factorial(3)
4*6
3 * factorial(2)
3*2
2 * factorial(1)
2*1
1 * factorial(0)
1*1
factorial(0)
1
• 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.
24
12
Departamento de Computación
Funciones
UNAN - LEON
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
Funciones
Funciones
Funciones
trigonométricas
hiperbólicas.
exponencial y logarítimica.
varias.
25
Departamento de Computación
Funciones
UNAN - LEON
• cos
Resultado: el coseno de x ( x en radianes).
#include <math.h>
double cos(double x);
• sin
Resultado: seno de x ( x en radianes).
#include <math.h>
double sin(double x);
• tan:
Resultado: tangente de x ( x en radianes).
#include <math.h>
double tan(double x);
26
13
Departamento de Computación
Funciones
UNAN - LEON
• exp
Da como resultado el valor de ex ( e = 2.718282)
#include <math.h>
double exp(double x);
• 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);
27
Departamento de Computación
Funciones
UNAN - LEON
•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 %g\n”,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);
28
14
Departamento de Computación
Funciones
UNAN - LEON
•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 %g\n”,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;
29
printf(“%g\n”,pow(x,y));
Departamento de Computación
Funciones
UNAN - LEON
•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);
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);
30
15
Departamento de Computación
Funciones
UNAN - LEON
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 131
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
%ld\n",time(&segundos));
printf("La fecha actual es %s",ctime(&segundos));
}
• El tipo time_t está definido así:
typedef long time_t;
32
16
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á.
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);
33
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 datos\n”);
else
printf(“Las matrices no contienen los mismos datos\n”);
34
17
Descargar