Funciones en C - Programación UPB

Anuncio
Unidad VI
Funciones en C
1. Funciones estándar del C y provistas por el
compilador.
2. Funciones definidas por el usuario.
3. La programación estructurada.
4. Paso de parámetros por valor.
5. Paso de parámetros por referencia.
6. División de programas en librerías.
7. Funciones recursivas.
8. Ejercicios.
Página 1
Unidad VI
Funciones en C
Las aplicaciones escritas en lenguaje C constan de una ó más funciones siendo obligatoria la
función denominada main( ).
main( ) es la función principal donde empieza la ejecución de las instrucciones que componen el
programa. Para utilizar otras funciones, se puede invocar las funciones estándar (propias del
estándar del C y provistas por el compilador) o las funciones definidas por el usuario (desarrolladas
por el programador).
1. Funciones estándar del C y provistas por el compilador
Las funciones estándar incluyen operaciones de entrada y salida de datos, manejo de archivos,
funciones matemáticas, de conversión de tipos de datos, etc. Pueden ser utilizadas incluyendo el
archivo de cabecera correspondiente que tiene la extensión .h y que se encarga de hacer
referencia a una librería donde está implementada dicha función. Ej. Para utilizar printf( ) y
scanf( ) es necesario incluir el archivo stdio.h.
Ej.
#include <stdio.h>
void main( void )
{
int Entero, Cuadrado;
printf("Introduzca un número entero: ");
scanf("%i", &Entero);
Cuadrado = Entero * Entero;
printf("El cuadrado de %i es %i", Entero, Cuadrado);
}
No todas las funciones provistas por un compilador son estándar del C. Es decir, algunos
compiladores disponen de funciones adicionales para facilitar la vida del programador. Si bien esto
no parece ser malo también tiene su contraparte, y esto es que el código sea menos portable y
dependiente del mismo compilador. Por ejemplo el compilador del Turbo C++ provee la función
clrscr( ) y hay que hacer la inclusión del archivo de cabecera conio.h. Sin embargo, esta función
no es parte del ANSI C y esto significa que no estará disponible en otros compiladores como Visual
C++ (para desarrollar en C bajo Windows) o DJGPP (para desarrollar en C bajo Linux). Así es que,
es mejor utilizar funciones estándar para que el código sea portable y pueda ser compilado en
distintas plataformas.
Generalmente las funciones reciben uno o más datos de entrada. Los datos se transforman y se
retorna un valor que es el resultado de dicha transformación. Ej. Si se desea obtener la raíz
cuadrada de un número se puede incluir el archivo de cabecera math.h y utilizar la función sqrt( )
de la siguiente manera:
Página 2
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Ej.
#include <stdio.h>
#include <math.h>
void main( void )
{
int Resultado;
Resultado = sqrt( 9 ); // La raíz cuadrada de 9 se calculará
// y se almacenará en la variable
// Resultado
printf("La raíz de 9 es %5.2f ", Resultado);
}
Se puede representar gráficamente las funciones main( ) y sqrt( ) de la siguiente manera:
main( )
9
3
sqrt( )
Analizando solo sqrt( ):
9
sqrt( )
3
En general:
Dato de Entrada
O también:
Funcion( )
Dato de Salida
Datos de Entrada
Funcion( )
Dato de Salida
Página 3
Unidad VI
Funciones en C
a) Funciones Matemáticas
Para utilizar estas funciones debe incluirse el archivo de cabecera math.h.
Función
pow( x, y )
Descripción
Ejemplo
x a la potencia y.
Cuadrado = pow( Numero, 2 );
sqrt( x )
Raíz cuadrada de x.
Raiz = sqrt( 81 );
abs( x )
Valor absoluto de x (enteros).
Absoluto = abs( -798 ); // 798
fabs( x )
Valor absoluto de x (flotantes).
exp( x )
Exponencial de ex.
log( x )
Logaritmo natural de x.
log10( x )
Logaritmo base 10 de x.
floor( x )
Redondea x hacia abajo.
Res = floor( 2.54 ); // 2
ceil( x )
Redondea x hacia arriba.
Res = ceil( 2.54 ); // 3
b) Funciones Trigonométricas
Debe incluirse el archivo de cabecera math.h. El dato que se envía a la función debe estar en
radianes.
Función
Descripción
Ejemplo
sin( x )
Seno de x.
Resultado = sin( 0 ); // 0
cos( x )
Coseno de x.
Resultado = cos( 0 * 3.14159 / 180 )
// coseno de 0° es 1
tan( x )
Tangente de x.
asin( x )
Arco seno de x.
acos( x )
Arco coseno x.
atan( x )
Arco tangente de x.
sinh( x )
Seno hiperbólico de x.
cosh( x )
Coseno hiperbólico de x.
tanh( x )
tangente hiperbólica de x.
c) Funciones para clasificar caracteres
Debe incluirse el archivo de cabecera ctype.h.
Función
Descripción
Ejemplo
isalnum( x )
x es un alfabético o dígito.
Resultado = isalnum( ′A′ ); // 1
isalpha( x )
x es un alfabético.
Resultado = isalpha( ′5′ );
// 0
Página 4
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Función
Descripción
isascii( x )
x es un carácter ASCII.
iscntrl( x )
x es un carácter de control.
isdigit( x )
x es un dígito.
isgraph( x )
x es un carácter que se grafica.
islower( x )
x es un carácter en minúsculas.
isupper( x )
x es un carácter en mayúsculas.
isspace( x )
x es un espacio en blanco.
isspunct( x )
x es un carácter de puntuación.
Ejemplo
Resultado = isdigit( ′8′ ); // 1
Resultado = isupper( ′m′ ); // 0
d) Funciones para conversión de tipos
Debe incluirse el archivo de cabecera stdlib.h.
Función
Descripción
atoi( x )
Convierte x de carácter a entero.
Resultado = atoi( ′9′ ); // 9
atof( x )
Resultado = atof( ′5′ ); // 5.000000
fcvt( … )
Convierte x de carácter a flotante.
Convierte x de carácter a entero
largo.
Convierte x de flotante a texto.
itoa( … )
Convierte x de entero a texto.
atol( x )
Ejemplo
e) Funciones de números aleatorios
Debe incluirse el archivo de cabecera stdlib.h.
Función
randomize( )
random( x )
rand( )
Descripción
Cambia la semilla que genera los
números al azar.
Macro que genera un número
entre 0 y x–1 .
Genera un número entre pseudoaleatorio entre 0 y RAND_MAX.
Ejemplo
randomize( );
Numero = random(20);
// Genera un numero entre 0 y 19
Numero = rand( ) % 100;
// Genera un numero entre 0 y 99
f) Otras funciones
Dependiendo de la función que utilice, se deberá incluir el archivo de cabecera respectivo. Entre los
archivos de cabecera que se requerirán están: stdio.h, stdlib.h, dos.h.
Importante: Algunas de estas funciones no son estándares del C pero son provistas por el
compilador del Turbo C++.
Página 5
Unidad VI
Funciones en C
Función
Descripción
Finaliza la ejecución del
programa. No cierra archivos ni
flujos abiertos.
Finaliza la ejecución del
programa. Cierra archivos y flujos
abiertos. Retorna al sistema
operativo el valor de x.
Obtiene el tiempo del sistema. La
variable x debe ser de tipo
time_t.
Detiene la ejecución del código x
milisegundos.
Emite un sonido de frecuencia x
por el parlante del PC.
Detiene el sonido del parlante del
PC.
abort( )
exit( x )
time( &x )
delay( x )
sound( x )
nosound( )
textcolor( x )
cprintf( … )
textbackground( x )
Cambia a x el color del texto.
Muestra un texto en pantalla a
color. No utilice las constantes de
barra invertida.
Cambia a x el color de fondo del
texto.
Ejemplo
abort( );
exit( 0 ); // Finalizo sin problema
exit( 1 ); // Finalizo con problema
time_t Tiempo; // Declara variable
time( &Tiempo ); // Obtiene tiempo
delay( 1000 ); // Detiene un segundo
la ejecución del código
sound( 150 ); // Emite un sonido de
frecuencia 150
nosound( );
textcolor( LIGHTRED );
textcolor( 12 ); // El 12 es rojo claro
cprintf("El resultado es %i", Res);
textbackground( BLUE );
// BLUE es una constante de color
2. Funciones definidas por el usuario
Además de las funciones estándar y las provistas por el compilador, el lenguaje C permite que el
usuario (programador) pueda desarrollar sus propias funciones. La sintaxis que se utiliza para
implementar nuevas funciones es:
[TipoDeDato] NombreDeFunción ( [ListaDeParametros] )
{
[ DeclaraciónDeVariablesLocales ]
[
Instrucción_1;
Instrucción_2;
…
Instrucción_N; ]
}
[ return [constante_variable_estructura_puntero] ; ]
Importante:
• Los elementos que se encuentran entre corchetes [] son opcionales.
• Los puntos suspensivos representan "y así consecutivamente".
Página 6
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
•
•
•
•
•
DeclaraciónDeVariablesLocales se emplea para declarar variables que son conocidas solo
dentro de esta función. Recuerde que las variables locales se descargan de memoria
cuando termina de ejecutarse la función donde han sido declaradas.
La palabra reservada return se utiliza para retornar: Un valor que puede ser el valor de
una constante, el contenido de una variable, una estructura, una unión ó un puntero.
return también obliga a terminar la ejecución de la función forzando a la salida y dejando
de ejecutar el resto de las instrucciones.
TipoDeDato es el tipo de dato que devuelve la función por medio de return.
ListaDeParametros son los datos que se recibe la función y que se reciben y almacenan en
variables locales. Para cada uno de los elementos de la lista de parámetros, se debe
especificar el tipo de dato al que corresponde. Cada elemento se separa del elemento
siguiente por medio de una coma.
Ej. De acuerdo a la sintaxis anterior para implementar funciones, entonces la siguiente función
principal es correcta:
main( )
{
}
Ej. Implemente una función que siempre retorne un cero.
int Retorna_Cero( )
{
return 0;
}
Observe que la función Retorna_Cero( ) no recibe ningún parámetro en la ListaDeParametros. La
única instrucción que se utiliza es la instrucción return que en este caso devuelve una constante
numérica que es el 0. Como el cero es un número entero entonces en la sección TipoDeDato se
debe especificar que se va a retornar un entero (int).
Gráficamente la función puede representarse como:
Retorna_Cero( )
0
Analizando el código:
Salida de un dato por medio de
TipoDeDato y como la función
devuelve un número entero
Ingreso de datos por medio de
ListaDeParametros y como la
función no recibe ningún valor
int Retorna_Cero( )
{
return 0;
}
Página 7
Unidad VI
Funciones en C
Cuando una función no recibe parámetro alguno, se puede utilizar la palabra reservada void como
único elemento en la ListaDeParametros. También se utiliza void en TipoDeDato para especificar
que la función no devuelve ningún valor.
Entonces la función Retorna_Cero( ) puede volver a escribirse de la siguiente manera:
int Retorna_Cero( void )
{
return 0;
}
// Esta función no recibe datos y
// retorna un entero
Ej. Implemente una función que siempre muestre un saludo en la pantalla.
void Saludo( void )
{
printf("Hola...\n");
// Esta función no recibe datos y
// no retorna valor alguno
return;
}
Cuando no se retorna ningún valor, no es necesario utilizar la palabra reservada return:
void Saludo( void )
{
printf("Hola...\n");
}
// Este código sin return es
// idéntico al anterior
El programa completo con las funciones Retorna_Cero( ), Saludo( ) y main( ) es:
#include <stdio.h>
int Retorna_Cero( void )
{
return 0;
}
void Saludo( void )
{
printf("Hola...\n");
}
void main( void )
{
int NumA, NumB, NumC;
NumA = Retorna_Cero( );
NumB = Retorna_Cero( );
NumC = Retorna_Cero( );
}
Saludo( );
printf("Los valores de las variables son %i, %i y %i", NumA,
NumB, NumC );
Página 8
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
El siguiente gráfico representa las llamadas a las funciones Retorna_Cero( ), Saludo( )
main( ), además del envío y recepción de datos entre ellas:
y
Retorna_Cero( )
0
main( )
Retorna_Cero( )
0
Retorna_Cero( )
0
Saludo( )
Observe que la función Retorna_Cero( ) se implementó una sola vez, pero puede ser utilizada
muchas veces para inicializar diferentes variables.
Importante: Cuando no se especifica el tipo de dato que va a retornar una función, el lenguaje C
asume que el tipo de dato a devolver por la función es de tipo int.
Ej.
main( )
{
}
Es el anterior ejemplo no se especificó el tipo de dato devuelto por la función main( ). Entonces,
el compilador asume que main( ) debería retornar un entero (int), así es que no generará un
mensaje de error pero sí un mensaje de advertencia (warning) similar a este: “Function should
return a value”.
Lo correcto sería especificar que main( ) es de tipo void, ó también se podría hacer:
Ej.
main( )
{
return 0;
}
Página 9
Unidad VI
Funciones en C
3. La programación estructurada
La programación estructurada se basa en el concepto de dividir un problema de programación en
problemas más pequeños y más simples de resolver. Si se consigue resolver todos los problemas
pequeños entonces se ha resuelto el problema original. Esta metodología es conocida como
“Divide y Vencerás”.
El lenguaje de programación C implementa esta metodología por medio de funciones. En otros
lenguajes como el ADA y el Visual Basic se utilizan procedimientos y funciones para dividir el
programa en subprogramas. Donde los procedimientos son porciones de código que se ejecutan y
al terminar no retornan ningún valor. En cambio las funciones se ejecutan y al terminar retornan un
valor. Es importante tener en cuenta que C no hace ese tipo de distinción, pues todo se basa en
funciones. En C las funciones generalmente retornan un dato de determinado tipo, pero también
están aquellas funciones que son de tipo void y que no devuelven ningún valor.
4. Paso de parámetros por valor
Analice el siguiente código:
#include <stdio.h>
// Implementación de la función Suma
int Suma( int Numero1, int Numero2 )
{
int Resultado;
Resultado = Numero1 + Numero2;
return Resultado;
}
void main( void )
{
int NumA, NumB, Res;
printf("Introduzca un número: ");
scanf("%i", &NumA );
printf("Introduzca otro número: ");
scanf("%i", &NumB );
Res = Suma( NumA, NumB );
}
// Llamada a la función Suma.
// El resultado devuelto por la
// función se almacenará en Res.
printf("La suma de %i y %i es %i", NumA, NumB, Res );
Página 10
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Suponiendo que una persona ejecuta el programa y que introduce el valor 20 para el NumA y el
valor 30 para el NumB, entonces gráficamente se tiene:
20
Suma( )
main( )
50
30
Analizando el código:
Salida de un dato por medio de
TipoDeDato y como la función
devuelve un número entero
Ingreso de datos por medio de
ListaDeParametros. La función
recibe dos valores enteros
int Suma(int Numero1, int Numero2)
{
int Resultado;
}
Resultado = Numero1 + Numero2;
return Resultado;
Cuando se llama a la función Suma( ), se le pasan dos datos que se denominan argumentos de la
función y son NumA y NumB. Cuando estos datos son recibidos en la implementación de la función,
se almacenan dentro de las variables locales Numero1 y Numero2. Estos datos recibidos se
denominan parámetros y este uno de los mecanismos que se utilizan para que una función reciba
datos externos desde otra función. Así es como las funciones se comunican entre sí, enviándose
datos y retornándose resultados.
Este envío y recepción de datos se denomina “paso de parámetros por valor”. Debido a que no
se envían los nombres de las variables, en realidad se envía es el valor que está almacenado dentro
de las variables.
Importante: Observe que en el paso de parámetros por valor las variables locales en main( ) se
denominan NumA y NumB pero en la función Suma( ) las variables locales se denominan Numero1
y Numero2. C no tiene problema alguno con los nombres diferentes de las variables enviadas y
recibidas, las únicas consideraciones que debe tener son:
•
•
•
Si se envían N datos (argumentos), se deben recibir N datos (parámetros).
Los tipos de datos de los argumentos debe coincidir con los tipos de datos de los
parámetros.
El orden de los argumentos debe ser el mismo en los parámetros.
Página 11
Unidad VI
Funciones en C
Ej.
#include <stdio.h>
// Implementación de la función (parámetros de entrada)
void Muestra( char Letra, int Entero, float Flotante )
{
printf("Datos: %c y %i y %f", Letra, Entero, Flotante );
}
void main( void )
{
char MiLetra = 'F';
int
MiEntero = 777;
float MiFlotante = 5.55;
}
// Llamada a la función Muestra (argumentos enviados)
Muestra( MiLetra, MiEntero, MiFlotante );
¿Es posible utilizar las sentencias if, if-else if, switch, for, while, do-while en otras funciones
además de la función principal main( )?
Si es posible. Para comprobar esto, revise los siguientes programas:
Ej. Escriba una función a la que se le envíe un carácter y retorne un valor de verdad si el carácter
está en mayúsculas. En caso contrario debe retornar un valor de falsedad.
#include <stdio.h>
#define FALSO 0
#define VERDAD 1
int Es_Mayuscula( char Letra )
{
if ( Letra >= 65 && Letra <= 90 ) // 'A' es 65, 'B' es 66,
return VERDAD;
// ... 'Z' es 90
else
return FALSO;
}
void main( void )
{
char MiLetra;
}
printf("Introduzca un carácter: ");
scanf("%c", &MiLetra);
if ( Es_Mayuscula( MiLetra ) )
printf("El carácter %c es una mayúscula", MiLetra);
else
printf("El carácter %c NO es una mayúscula", MiLetra);
Página 12
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Ej. Escriba una función a la que se le envíe un valor entero positivo y devuelva la sumatoria del
número y sus predecesores.
#include <stdio.h>
int Sumatoria( int Cantidad )
{
int Contador, Suma = 0;
for( Contador = 1 ; Contador <= Cantidad ; Contador++ )
Suma += Contador;
}
return Suma;
void main( void )
{
int Numero, Resultado;
printf("Introduzca un número: ");
scanf("%i", &Numero);
if ( Numero > 0 )
{
Resultado = Sumatoria( Numero );
printf("La sumatoria de los %i primeros
enteros es %i", Numero, Resultado);
}
else
printf("Debe introducir solo números positivos");
}
Importante: Para finalizar con el paso de parámetros por valor, hay que tener en cuenta que
cuando se envían los argumentos y se transforman en parámetros de entrada de la función,
cualquier modificación a los parámetros no afecta el valor de los argumentos originales.
Ej.
#include <stdio.h>
void Muestra_Valor( int Numero )
{
while( Numero > 0 )
{
printf("El valor es %i\n", Numero);
// Decrementando el valor de número
Numero--;
}
}
Página 13
Unidad VI
Funciones en C
void main( void )
{
int Numero = 4;
}
printf("El valor es %i\n\n", Numero);
Muestra_Valor( Numero );
printf("\nEl valor es %i\n", Numero);
En el anterior ejemplo, la variable Numero de main( ) comienza con un valor de 4. Este valor se
envía a la función Muestra_Valor( ) donde el valor es decrementado en cada iteración del
bucle (ciclo). Al finalizar la función Muestra_Valor( ), el valor que tiene Numero es 0 pero al
volver a desplegar su contenido en main( ) se puede apreciar que aún mantiene el valor original
de 4.
La respuesta a esto es simple. En realidad se ha utilizado el paso de parámetros por valor y se
envían copias de los datos. Cualquier modificación que ocurra a los parámetros afecta únicamente a
las copias y no a los valores originales (argumentos).
5. Paso de parámetros por referencia
Analice el siguiente código:
#include <stdio.h>
void Intercambia( int Numero1, int Numero2 )
{
int Auxiliar;
}
Auxiliar = Numero1;
Numero1 = Numero2;
Numero2 = Auxiliar;
void main( void )
{
int NumA = 55, NumB = 77;
printf("Los valores son: %i y %i\n", NumA, NumB);
Intercambia( NumA, NumB );
// Esta función intercambia el
// contenido de ambas variables.
printf("Ahora los valores son: %i y %i", NumA, NumB);
}
En este ejemplo, inicialmente NumA tiene un valor de 55 y NumB tiene un valor de 77. Después
de enviar estos datos a la función Intercambia( ), NumA debería contener 77 y NumB 55.
Página 14
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Sin embargo, esto no funcionó como se esperaba. NumA y NumB mantienen los valores originales
que tenían antes de ser enviados a la función Intercambia( ).
Pero, ¿Por qué ocurrió esto si no es lo que se deseaba?
La respuesta es que se ha utilizado el mecanismo de paso de parámetros por valor. En la función
Intercambia( ) los parámetros recibidos son copias de los datos. Entonces, cuando la función
intercambia los valores está trabajando sobre las copias. Los valores originales están seguros en la
función main( ) (argumentos originales).
Para resolver este problema, sería de gran utilidad el poder enviar los datos originales para que las
modificaciones a las variables afecten a los valores originales. Este es otro tipo de mecanismo para
el envío y recepción de datos entre funciones y se denomina “paso de parámetros por
referencia”.
Para implementar el paso de parámetros por referencia se deben utilizar los operadores unitarios
de punteros & (ampersand) y * (asterisco), donde:
& Obtiene la dirección de memoria del operando.
* Accede al contenido de la dirección almacenada en el operando.
Los operadores & y * son complementarios. Esto significa que si se utiliza un operador, luego
deberá utilizarse el operador complementario.
Ej. Volviendo a escribir el código de Intercambia( ):
#include <stdio.h>
void Intercambia( int *Numero1, int *Numero2 )
{
int Auxiliar;
Auxiliar = *Numero1;
*Numero1 = *Numero2;
*Numero2 = Auxiliar;
}
void main( void )
{
int NumA = 55, NumB = 77;
printf("Los valores son: %i y %i\n", NumA, NumB);
Intercambia( &NumA, &NumB ); // Esta función intercambia el
// contenido de ambas variables.
printf("Ahora los valores son: %i y %i", NumA, NumB);
}
Página 15
Unidad VI
Funciones en C
Observe que en el anterior ejemplo, se utiliza el & (ampersand) al momento de enviar los
argumentos en main( ). Cuando los datos son recibidos como parámetros de entrada y son
almacenados dentro de variables en la función Intercambia( ), se utiliza de manera
complementaria el operador * (asterisco). Hay que recalcar las variables de entrada Numero1 y
Numero2, ahora se llaman *Numero1 y *Numero2. Este mecanismo permite que las funciones
envíen y reciban los valores originales almacenados en los argumentos de la función.
Gráficamente se tiene:
55
77
Intercambia( )
main( )
77
55
Analizando el código:
No hay salida de un dato por
medio de TipoDeDato, entonces
es de tipo void
Ingreso y salida de datos por
medio de ListaDeParametros
void Intercambia( int *Numero1, int *Numero2 )
{
int Auxiliar;
}
Auxiliar = *Numero1;
*Numero1 = *Numero2;
*Numero2 = Auxiliar;
Importante: El paso de parámetros por referencia permite que una función retorne más de un
resultado.
Ej. Escriba el código fuente en C para enviar un número a una función y retornar los siguientes tres
números que son correlativos al número enviado.
#include <stdio.h>
void Siguientes_Tres( int Num, int *Num1, int *Num2, int *Num3 )
{
*Num1 = Num + 1;
*Num2 = Num + 2;
*Num3 = Num + 3;
}
Página 16
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
void main( void )
{
int Num, NumA, NumB, NumC;
printf("Introduzca un número entero: ");
scanf("%i", &Num);
Siguientes_Tres( Num, &NumA, &NumB, &NumC );
}
printf("Los siguientes valores a %i ", Num);
printf("son: %i, %i y %i", NumA, NumB, NumC);
Observe que en los argumentos de la función se tiene:
• El caso del argumento Num es un paso de parámetros por valor. Por lo tanto, se está
enviando una copia y cualquier modificación a la copia no afecta al valor original.
• El caso de los argumentos &NumA, &NumB y &NumC es un paso de parámetros por
referencia. Se envían los valores originales y se deben utilizar los operadores & y *. Si la
función Siguientes_Tres( ) cambia los valores de los parámetros, entonces se están
modificando los valores originales y así serán retornados a la función main( ).
• No es necesario que los nombres entre los argumentos y los parámetros sean los mismos.
Solo debe verificar la cantidad de argumentos y parámetros, los tipos de datos y el orden.
• Es posible que una función envíe argumentos por valor y por referencia al mismo tiempo.
Ej. Siguientes_Tres( Num, &NumA, &NumB, &NumC );. Esto significa que los
parámetros recibidos por valor no serán modificados por la función, pero los parámetros
por referencia sí serán modificados por la función.
Ejercicio:
¿Que significan las siguientes llamadas a funciones?
a) Calcula_Areas( Base, Altura, &Area_Rectangulo, &Area_Triangulo );
b) scanf ( "%i", &Contador );
c) printf( "%i", Contador );
6. División de programas en librerías
Ahora que sabemos que el programador puede escribir sus propias funciones, que las puede utilizar
muchas veces y con argumentos distintos. Sería muy conveniente que por cada proyecto de
programación que vaya a desarrollar, no tenga que implementar las mismas funciones una y otra y
otra vez. Más bien, que implemente las funciones una sola vez, que las almacene dentro de otro
archivo y que dicho archivo pueda ser incluido posteriormente (como si fueran las librerías propias
del programador).
La manera más simple de realizar esto consiste en separar las funciones y guardarlas en un archivo
*.h (* significa cualquier nombre de archivo y .h que la extensión del archivo debe ser de este
tipo). Luego el archivo *.c que contiene la función principal main( ) deberá incluir al archivo *.h.
Página 17
Unidad VI
Funciones en C
Antes de trabajar con archivos *.h es necesario considerar un nuevo concepto que es el de
prototipo de función.
Un prototipo de función permite:
• Comunicarle al compilador la existencia de una función que no necesariamente estará
implementada antes de la función main( ).
• Especificarle al compilador la cantidad de parámetros de la función y sus respectivos tipos
de datos.
• Especificarle al compilador el tipo de dato retornado por la función.
Ahora veamos como se trabaja con el prototipo de función:
#include <stdio.h>
// Prototipos de funciones
int Suma ( int Numero1, int Numero2 );
int Resta( int Numero1, int Numero2 );
void main( void )
{
int NumA, NumB, ResSuma, ResResta;
printf("Introduzca un número: ");
scanf("%i", &NumA );
printf("Introduzca otro número: ");
scanf("%i", &NumB );
ResSuma = Suma( NumA, NumB );
ResResta = Resta( NumA, NumB );
}
// Llama a Suma
// Llama a resta
printf("La suma de %i y %i es %i", NumA, NumB, ResSuma );
printf("La resta de %i y %i es %i", NumA, NumB, ResResta );
// Implementación de la función Suma
int Suma( int Numero1, int Numero2 )
{
return (Numero1 + Numero2);
}
// Implementación de la función Resta
int Resta( int Numero1, int Numero2 )
{
return (Numero1 - Numero2);
}
Observe que el prototipo de función es similar a la primera línea de la implementación de la
función. La única diferencia es que el prototipo lleva un punto y coma al final. El prototipo debe
estar antes que la implementación de la función y antes que la función principal. Recuerde que con
el prototipo de función ya se puede implementar la función antes o después de main( ).
Página 18
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
Importante: Una buena práctica de programación consiste tener un prototipo de función por cada
una de las funciones que se implementen.
Con el concepto de prototipos de funciones, separemos el código en dos archivos:
Archivo MisFunc.h:
// Este archivo contiene solo los prototipos
// y las implementaciones de las funciones
// Prototipos de funciones
int Suma ( int Numero1, int Numero2 );
int Resta( int Numero1, int Numero2 );
// Implementación de la función Suma
int Suma( int Numero1, int Numero2 )
{
return (Numero1 + Numero2);
}
// Implementación de la función Resta
int Resta( int Numero1, int Numero2 )
{
return (Numero1 - Numero2);
}
Archivo Programa.c:
// Este archivo contiene la función principal
// y la inclusión del archivo *.h
#include <stdio.h>
#include "MisFunc.h"
void main( void )
{
int NumA, NumB, ResSuma, ResResta;
printf("Introduzca un número: ");
scanf("%i", &NumA );
printf("Introduzca otro número: ");
scanf("%i", &NumB );
ResSuma = Suma( NumA, NumB );
ResResta = Resta( NumA, NumB );
}
// Llama a Suma
// Llama a resta
printf("La suma de %i y %i es %i", NumA, NumB, ResSuma );
printf("La resta de %i y %i es %i", NumA, NumB, ResResta );
Con este método se implementan las funciones en varios archivos *.h y estos archivos son
incluidos cuando se requiere una función que esté implementada ahí.
Página 19
Unidad VI
Funciones en C
Importante: La inclusión del archivo *.h que ha sido desarrollada por el usuario se especifica así:
#include "Nombre.h". Observe que al utilizar las comillas dobles se le está especificando al
compilador que busque este archivo en la misma carpeta donde se encuentra el archivo *.c (Ej. En
la carpeta bin). Cuando se utiliza #include <Nombre.h> se le especifica al compilador que
primero busque el archivo *.h en la carpeta include.
Importante: Una misma función no debe estar implementada en dos archivos *.h distintos. Esto
es así porque, cuando el compilador intenta enlazar los dos archivos *.h no sabrá que función
utilizar.
7. Funciones recursivas
La recursividad es una técnica que se utiliza para resolver problemas del tipo “Divide y vencerás” y
es especialmente útil para la inteligencia artificial. Un problema resuelto con recursividad, también
puede ser resuelto con iteraciones (bucles o ciclos).
Una función es recursiva cuando cumple los siguientes puntos:
• La función tiene una sección para llamarse a sí misma (recursividad).
• La función tiene una sección para detener los llamados (condición(es) base).
• La función tiene una sección que al volver hacia atrás (backtrack) se muestran datos ó se
realizan cálculos.
• No hay una gran cantidad llamados recursivos y además son finitos.
Ej. Implemente una función recursiva en C para mostrar en pantalla la serie: 1, 2, 3, 4, 5.
#include <stdio.h>
void Muestra( int Numero )
{
if ( Numero == 0 )
// Condición base. Si se cumple, la
return;
// func. deja de llamarse a sí misma
else
{
// Recursividad. La func. se llama a sí misma
Muestra( Numero – 1 );
}
// Backtrack. Instrucciones pendientes donde se
// muestran datos ó se realizan cálculos
printf("%i\n", Numero);
}
void main( void )
{
int Num = 5;
printf("La serie es:\n");
}
Muestra( Num );
Página 20
Computación para Ingenierías I
Ing. Franz Mercado Lorberg
8. Ejercicios
Resuelva los siguientes problemas:
Funciones estándar
1. Por medio de funciones matemáticas calcule:
a. El cuadrado de un número.
b. El resultado de un número elevado a una potencia.
c. La raíz de un número.
d. El valor absoluto de un número entero negativo y flotante negativo.
e. Los redondeos hacia arriba y hacia debajo de un número flotante.
2. Por medio de funciones trigonométricas calcule:
a. El seno de un ángulo.
b. El coseno de un ángulo.
c. La tangente de un ángulo.
d. El arco seno de un ángulo.
e. El coseno hiperbólico de un ángulo.
3. Empleando funciones para clasificar caracteres muestre por pantalla si:
a. Un carácter leído desde el teclado es un dígito.
b. Un carácter leído desde el teclado es alfabético.
c. Un carácter es leído desde el teclado alfabético y si esta en mayúscula o minúscula.
d. Un carácter leído desde el teclado es un ASCII.
e. Un carácter leído desde el teclado es un espacio en blanco.
f. Un carácter leído desde el teclado es un símbolo de puntuación.
4. Empleando funciones de conversión de tipo muestre el resultado de convertir:
a. Un texto a un número entero.
b. Un texto a un número flotante.
c. Un texto a un número entero largo.
d. Un entero leído desde el teclado en texto.
e. Un flotante leído desde el teclado en texto.
5. Utilice
a.
b.
c.
d.
e.
f.
g.
otras las funciones para:
Generar 20 números al azar y mostrarlos en pantalla.
Emular el lanzamiento simultáneo de cinco dados.
Emular la salida de una carta entre el 1 al 10, J, Q, K, A y que tenga uno de los
palos Corazón, Trébol, Espada, Diamante. Muestre en pantalla la carta obtenida al
azar.
Mostrar 50 números al azar en distintas coordenadas de la pantalla (80 columnas
por 50 filas) y con distintos colores (desde el 1 hasta el 5).
Generar 10 sonidos (tono y duración son generados al azar y no son más extensos
de 1.5 segundos).
Obtenga el tiempo T1. Ejecute un bucle de 3,000,000,000 repeticiones y obtenga
un tiempo T2. Calcule y muestre la cantidad de segundos de diferencia que existen
entre T1 y T2.
Desarrollar un pequeño juego de adivinanza de un número que estará entre 10 y
100. El programa generará un número al azar y el jugador deberá ir probando
Página 21
Unidad VI
Funciones en C
hasta encontrar cuál ese número generado. Para que sea más fácil de adivinar, el
programa indicará si el número que introduce el jugador es más bajo ó más alto
con respecto al generado. Cuando el jugador encuentre el número se escuchará
una pequeña melodía por el parlante de la computadora y se congratulará al
jugador.
Funciones definidas por el usuario
1. Implemente una función que reciba tres números flotantes y devuelva como resultado el
resultado de la suma de los tres números.
2. Escriba una función que reciba tres números flotantes y devuelva el mayor de ellos.
3. Desarrolle una función que reciba una temperatura en grados Centígrados y retorne la
temperatura respectiva en grados Fahrenheit. Además de otra función que reciba una
temperatura en grados Fahrenheit y retorne la temperatura respectiva en grados
Centígrados.
4. Escriba una función que reciba un número N y muestre los siguientes 3 números impares.
La función no debe retornar nada.
Ej. Recibe 5 y muestra 7, 9, 11.
Ej. Recibe 22 y muestra 23, 25, 27.
5. Implemente una función que reciba un número entero y devuelva el carácter ‘N’ si el
número es Negativo, ‘P’ si el número es positivo y ‘O’ si es neutro.
6. Desarrolle una función que reciba un carácter y retorne el siguiente carácter en la pantalla.
Por ejemplo, si la función recibe una ‘M’ devolverá una ‘N’.
7. Escriba una función que reciba un número entero N y devuelva la suma de los N primeros
números enteros. Ej. Si N es 25 entonces la función devuelve la suma de 1 + 2 + 3 + … +
24 + 25.
8. Escriba una función que reciba un número N entero mayor o igual a 0 y que devuelva el
factorial de dicho número. Ej. Si N es 5 entonces la función devuelve el producto de 5 * 4 *
3 * 2 * 1.
9. Implemente una función que reciba un número entero largo y que retorne la cantidad de
dígitos que conforman dicho número. Ej. Si el número es 567243 entonces este consta de 6
dígitos.
10. Desarrolle una función que reciba un número entero largo y que retorne el entero invertido.
Ej. Si el número es 42317, al invertirlo será 71324.
11. Escriba una función para calcular la serie ( N debe ser mayor a 5 ):
12 + 2 2 + 3 2 + ... + N 2
Página 22
Descargar