PRACTICAS de Lenguaje C E.P.S. Lenguajes de Programación

Anuncio
INGENIERIA INFORMATICA
Lenguajes de Programación
E.P.S.
PRACTICAS de Lenguaje C
Tema: Funciones
Funciones
Preparación Previa

Editar + Compilar + Depurar errores Sintácticos y Semánticos

Declarar variables con tipos simples y usarlas en expresiones simples

Entrada/Salida reducida con printf y scanf

Iniciación y motivación a la programación estructurada

Estructuras de Control

Arrays y estructuras
Objetivos de la Sesión
Principales

Concepto de función

Declaración y definición de funciones sencillas

Argumentos de una función. Paso por valor

Variables locales y globales
Secundarios

Aprender a analizar el código desarrollado por otras personas

Aprender a modificar el código desarrollado por otras personas

Motivación
Las aplicaciones informáticas que habitualmente se utilizan, incluso a nivel de informática
personal, suelen contener decenas y aún cientos de miles de líneas de código fuente. A medida
que los programas se van desarrollando y aumentan de tamaño, se convertirían rápidamente en
sistemas poco manejables si no fuera por la modularización, que es el proceso consistente en
dividir un programa muy grande en una serie de módulos mucho más pequeños y manejables.
A estos módulos se les ha denominado de distintas formas (subprogramas, subrutinas,
procedimientos, funciones, etc.) según los distintos lenguajes. El lenguaje C hace uso del
concepto de función (function). Sea cual sea la nomenclatura, la idea es sin embargo siempre
la misma: dividir un programa grande en un conjunto de subprogramas o funciones más
pequeñas que son llamadas por el programa principal; éstas a su vez llaman a otras funciones
más específicas y así sucesivamente.
La división de un programa en unidades más pequeñas o funciones presenta –entre otras– las
ventajas siguientes:
1. Modularización. Cada función tiene una misión muy concreta, de modo que nunca
tiene un número de líneas excesivo y siempre se mantiene dentro de un tamaño
manejable. Además, una misma función (por ejemplo, un producto de matrices, una
resolución de un sistema de ecuaciones lineales, ...) puede ser llamada muchas veces en
un mismo programa, e incluso puede ser reutilizada por otros programas. Cada función
puede ser desarrollada y comprobada por separado.
2. Simplificación de código y localización de errores. En la medida en que una
misma función es utilizada muchas veces, el número total de líneas de código del
programa disminuye, y también lo hace la probabilidad de introducir errores en el
programa.
Una función de C es una porción de código o programa que realiza una determinada tarea. Una
función está asociada con un identificador o nombre, que se utiliza para referirse a ella desde el
resto del programa. En toda función utilizada en C hay que distinguir entre su definición, su
declaración y su llamada. Para explicar estos conceptos hay que introducir los conceptos de
valor de retorno y de argumentos.

Declaración
De la misma manera que en C es necesario declarar todas las variables, también toda función
debe ser declarada antes de ser utilizada en la función o programa que realiza la llamada. En C
la declaración de una función se debe hacer de la siguiente forma:

Mediante una declaración explícita, previa a la llamada. Esta es la práctica más
segura y la que hay que tratar de seguir siempre. La declaración de la función se
hace mediante el prototipo de la función, bien fuera de cualquier bloque, bien en la
parte de declaraciones de un bloque.
La forma general del prototipo de una función es la siguiente:
tipo_valor_de_retorno nombre_funcion(lista de tipos de argumentos);
Esta forma general coincide sustancialmente con la primera línea de la definición –el
encabezamiento-, con dos pequeñas diferencias: en vez de la lista de argumentos formales o
parámetros, en el prototipo basta incluir los tipos de dichos argumentos. Se pueden incluir
también identificadores a continuación de los tipos, pero son ignorados por el compilador.
Además, una segunda diferencia es que el prototipo termina con un carácter (;). Cuando no hay
argumentos formales, se pone entre los paréntesis la palabra void, y se pone también void
precediendo al nombre de la función cuando no hay valor de retorno. Es decir, cuando una
función es ejecutada, puede devolver al programa que la ha llamado un valor (el valor de
retorno), cuyo tipo debe ser especificado en el encabezamiento de la función (si no se especifica,
se supone por defecto el tipo int). Si no se desea que la función devuelva ningún valor, el tipo
del valor de retorno deberá ser void.
Los prototipos permiten que el compilador realice correctamente la conversión del tipo del valor
de retorno, y de los argumentos actuales a los tipos de los argumentos formales. La declaración
de las funciones mediante los prototipos suele hacerse al comienzo del fichero, después de los
#define e #include. En muchos casos –particularmente en programas grandes, con muchos
ficheros y muchas funciones–, se puede crear un fichero (con la extensión .h) con todos los
prototipos de las funciones utilizadas en un programa, e incluirlo con un #include en todos los
ficheros en que se utilicen dichas funciones.

Definición de una función
La definición de una función consiste en la definición del código necesario para que ésta
realice las tareas para las que ha sido prevista. La definición de una función se debe realizar en
alguno de los ficheros que forman parte del programa. La forma general de la definición de una
función es la siguiente:
tipo_valor_de_retorno nombre_funcion(lista de argumentos con tipos)
{
declaración de variables y/o de otras funciones
codigo ejecutable
return (expresión); // optativo
}
La primera línea recibe el nombre de encabezamiento (header) y el resto de la definición –
encerrado entre llaves– es el cuerpo (body) de la función.
La sentencia return permite devolver el control al programa que llama. Si no hay ningún return,
el control se devuelve cuando se llega al final del cuerpo de la función. La palabra clave return
puede ir seguida de una expresión, en cuyo caso ésta es evaluada y el valor resultante devuelto
al programa que llama como valor de retorno (si hace falta, con una conversión previa al tipo
declarado en el encabezamiento). Los paréntesis que engloban a la expresión que sigue a return
son optativos. Recordad que en el programa principal si queremos hacer uso de este valor
deberemos guardarlo en una variable.
Por ejemplo, el siguiente código utiliza la función valor_abs para calcular el valor absoluto de
una variable.
#include <stdio.h>
double valor_abs(double); // declaración
void main (void)
{
double z, y;
y = -30.8;
z = valor_abs(y) + y*y; // llamada en una expresion
}
double valor_abs(double x)
{
double absX;
if (x < 0.0)
absX = -x;
else
absX = x;
return absX;
}
La función valor_abs() recibe un valor de tipo double (x). El valor de retorno de dicha función
(el valor absoluto de y), es introducido en la expresión aritmética que calcula z.

Ejercicio 1: Compilad y ejecutad el código anterior. Debugad paso a paso (F7) para ver el
funcionamiento de una llamada a una función. Mirad como cambia el valor de las variables.

Ejercicio 2: Dado el siguiente programa, realizar uno de equivalente que utilice tres
funciones, es decir, una función para cada párrafo. (Recordar incluir todo los programas que
escribais con vuestra práctica)
#include <stdio.h>
void main()
{
/* Primer párrafo de la explicación. */
puts("Este es un programa en C que ilustra el tipico");
puts("ejemplo de programa no estructurado");
/* Fin del primer párrafo de la explicación. */
/* Segundo párrafo de explicación. */
puts("Cuando el programa se ejecuta, el usuario no");
puts("puede decir si el programa esta o no estructurado,");
puts("solo puede hacerlo el programador.");
/* Fin del segundo párrafo de explicación. */
/* Tercer párrafo de explicación.. */
puts("Por tanto, un programa en C estructurado solo es");
puts("util al programador, al jefe del programador,");
puts("al profesor del programador, a aquellos que ");
puts("necesiten modificar el programa y a aquellos");
puts("que convivan con el programador mientras este");
puts("intenta encontrar errores en el programa");
/* Fin del tercer párrafo de explicación. */
}

Paso de argumentos por valor
La manera más simple de pasar los argumentos a una función es copiándolos ( paso por
valor). Los argumentos con que se llama a la función son copiados en las variables especificadas
en la definición de la función. Por lo tanto, los cambios que la función realiza no se
trasmiten a las variables (originales) del programa que la ha llamado: lo que ha recibido
son copias. Aunque se llamen igual son variables diferentes, ya que el espacio en memoria que
se usa para guardar las variables del main() y para una función no es el mismo. Intuitivamente
podéis pensar que nuestras variables tienen nombre y apellido (= el nombre de la función a la
que pertenecen). La siguiente tabla representa la gestión de memoria cuando ejecutamos el
programa del ejemplo:
Ejemplo:
float valor_abs(float );
main()
{
float x,y;
y=2 ;
x=valor_abs(y) ;
x=x+1;
}
MEMORIA DEL MAIN
A
B
C
G
A
B
C
float valor_abs(float y)
{
float x;
D
if(y<0) x=-y;
else x=y;
D
y=x+2;
E
return y;
F
Declaración variables:
y= Õ
x= æ
Inicalización de y:
y= -2
x= æ
Llamamos a valor_abs
con el valor de y:
y= -2
x= æ
y=-2
x= æ
E
y=-2
x= æ
F
y= -2
x= 2
G
y= -2
x= 3
}

Ejercicio 3: Es correcto el siguiente programa?
#include <stdio.h>
void permutar(double, double); /* declaración */
void main(void)
{
double a=1.0, b=2.0;
printf("a = %lf, b = %lf\n", a, b);
permutar(a, b);
printf("a = %lf, b = %lf\n", a, b);
}
void permutar(double x, double y)
{
double temp;
temp = x;
x = y;
y = temp;
}
MEMORIA FUNCIONES
AUXILIARES
Inicio
de
la
valor_abs:
y= -2
x= Đ
y=-2
x= 2
y= 0
memoria
de
x= 2
Volvemos a main devolviendo x.
Fin de la memoria de valor_abs
Fijaos que después de retornar al main( ), las variables pertenecientes a la función valor_abs
han dejado de existir. Són variables locales a la función. No uséis nunca una variable local para
controlar un proceso del main.

Variables locales y globales
Acabamos de ver que las variables de las funciones auxiliares de nuestro programa sólo tienen
existencia dentro del cuerpo de la función. Las únicas que sobreviven durante todo el programa
son las variables del main. Sin embargo, el valor de las variables declaradas dentro de una
función sólo puede modificarse dentro del cuerpo de dicha función. Si queremos que una
variable / definición de un nuevo tipo de datos pueda ser usada por cualquier función, debemos
hacer una declaración/ definición global, eso es, fuera del main (donde declaramos las
funciones). Usaremos definiciones globales para nuestras estructuras. NO ES DE BUEN
PROGRAMADOR USAR VARIABLES GLOBALES. Nosotros sólo utilizaremos variables globales
momentáneamente para evitar el paso por referencia.

Ejercicio 4: Crea un programa que utilice el programa endevina, pero ahora utilizando una
función que realice todo el calculo del juego endevina.

Ejercicio 5: Crea un programa que realice el calculo de la siguiente función:
f(x) = (2x + a(x+1))/(x-1)
Con a un entero y x un float introducidos por el usuario. Primero hazlo sin utilizar ninguna
función y luego utilizando una función que haga el cálculo. Es decir que la declaración de la
función sea
double funcion(double, int);

Ejercicio 6: Definid globalmente la estructura de CD’s de la práctica anterior, así como el
array de 10 CD’s. Modificad el programa de la práctica anterior añadiendo las siguientes
funciones:



Una para la entrada de datos de los CD’s.
Otra que englobe el cuerpo del while. Deberá leer el grupo, comparar y peguntar al
usuario si quiere otro grupo. La respuesta será retornada al main.
Ejercicio 7: Crear un programa que pida un numero (decimal) al usuario y que calcule el
cuadrado del numero y su raíz cuadrada (función sqrt de C), mostrando siempre el resultado
por pantalla. Utilizar dos funciones, una para realizar el cuadrado y la otra para realizar la
raíz cuadrada. En el interior de estas funciones es donde se debe imprimir por pantalla el
resultado de cada operación. Tened en cuenta que no se puede realizar una raíz cuadrada de
un numero negativo. Controlad este caso.
Documentos relacionados
Descargar