Download - UNIDAD_I_P6_FUNCIONES.pdf
UNIVERSIDAD DE EL SALVADOR
FACULTAD DE MULTIDISCIPLINARIA PARACENTRAL
DEPARTAMENTO DE EDUCACION
INFORMÁTICA ESPECIAL DE MATEMATICA CICLO I1/2015
UNIDAD I P6 MODULARIDAD
OBJETIVO GENERAL: Que Al finalizar esta unidad el estudiante sea capaz de:
Aplicar la teoría relacionada a la declaración de prototipos y definición de
funciones con sus parámetros.
OBJETIVO ESPECÍFICOS: Al finalizar la temática el estudiante será capaz de:
Identificar y desarrollar funciones en un programa
Introducir el concepto función y parámetros.
Conocer la forma de implementar la modularidad en programas.
Diferenciar variables globales y locales
Introducir el paso de parámetros por variable.
INTRODUCCIÓN
Hasta la Unidad V hemos visto las estructuras algorítmicas (secuenciales, condicionales
y cíclicas) desarrolladas dentro del programa principal llamado main(), pero no siempre
resulta conveniente trabajar de esa manera, sobre todo cuando tenemos un programa que
incluye procesos que pueden desarrollarse de manera independiente. En ese caso resulta
conveniente “dividir” el programa en una serie de sub-programas o módulos, que son
llamados dentro del programa principal, a esos miniprogramas dentro de un programa le
llamaremos funciones.
Los módulos en C se llaman funciones. Existen dos tipos de funciones con las que se
arman programas: las que son creadas por los usuarios y los paquetes de funciones
predefinidos disponibles en la biblioteca estándar de C. Estos últimos contienen cientos
de funciones básicas para el cálculo de funciones matemáticas, manipulación de cadenas
de caracteres, funciones de entrada-salida, etc. Son funciones que suelen usarse
frecuentemente en la construcción de programas y, al estar predefinidas, ahorran tiempo
a los programadores. Por eso es útil familiarizarse con las funciones de la biblioteca
estándar de C (archivos cabecera), pues al conocer estas funciones podremos ahorrarnos
de escribir mucho código, además cuentan con la ventaja de ser altamente eficientes y
generalmente portables.
En tanto las funciones creadas por el programador son aquellas escritas para resolver
tareas que generalmente no están en la biblioteca estándar y sirven para cumplir con el
propósito del programa a crearse.
Las funciones son invocadas mediante una llamada de función; esto se logra escribiendo
el nombre de la función y la información de entrada necesaria (parámetros o
argumentos) para que ésta pueda lograr su cometido. Ya hemos visto ejemplos de
funciones con sus parámetros, por ejemplo: printf(“Hola Mundo\n”); Allí se está
llamando a la función printf con el argumento “Hola Mundo\n”, que es una cadena. El
resultado es la impresión en pantalla del ese texto.
Anteriormente dijimos que los programas en C comienzan indefectiblemente desde la
función main(). Ésta es la función principal y es el hilo conductor en la ejecución de un
programa. Desde esta función se pueden llamar otras funciones para realizar tareas, y
esas funciones a su vez pueden invocar otras funciones y así sucesivamente. Por lo
general cuando una función termina su trabajo se retorna a la función que la llamó,
siguiendo la ejecución de ésta.
ESTRUCTURA DE UNA FUNCIÓN
Como ya hemos dicho una función es un conjunto de sentencias que se pueden llamar
desde cualquier parte del programa. En C todas las funciones son globales o externas, es
decir, que pueden ser llamadas desde cualquier parte del programa.
La forma genérica de definir funciones en C es:
tipo_de_retorno nombre_de_función (parametros)
{
declaraciones
sentencias
return expresión;
}
El tipo_de_retorno es el tipo de dato resultado de llamar a la función, puede ser un
entero (int), real (float), etc. o también puede ser void que indica que esa función no
devolverá ningún valor. El nombre_de_función es un identificador o nombre válido.
Por lo general se aconseja poner un nombre corto que especifique lo que hace esa
función. Luego están los parametros , que corresponden a una lista separada por comas,
que especifica si es necesario el tipo de datos recibir y el nombre del parámetro así:
(float a, float b). Si se escribe void se entiende que esa función no necesita ningún
parámetro.
La función tiene un cuerpo o bloque, donde están las declaraciones y los enunciados. En
las declaraciones se especifican variables que ámbito local, o sea, sólo podrán ser
usadas dentro de esa función. No se deben declarar las variables que llegan por
parámetro. No se pueden definir funciones dentro de otra función, pero sí se puede
llamar a una función dentro de otra función (incluso se puede llamar a sí misma, es el
caso de las funciones recursivas).
Dentro del enunciado de las funciones se debe regresar el control al punto desde donde
se invocó a dicha función. En el caso de las funciones que no regresen resultados, estas
finalizan cuando termina de ejecutarse la última línea de la función o cuando se llega al
enunciado return. Si la función devuelve un resultado, se debe especificar cuál
siguiendo la siguiente forma: return expresión.
Ejemplo: función que calcula la suma de dos números reales
Veamos a continuación un ejemplo para saber cómo definir funciones en C y utilizarlas
en un programa.
Ejemplo 1:El siguiente programa pide que ingrese un número entero y calcula el
cuadrado de dicho número.
#include <stdio.h>
#include <conio.h>
int cuadrado(int n);
main()
{
int numero;
printf(“Ingrese un entero: ”);
scanf(“%d”, &numero);
printf(“\nResultado: %d”, cuadrado(numero));
getch();
return 0;
}
int cuadrado(int y)
{
int resultado;
resultado = y * y;
return resultado;
}
En este programa hemos creado la función llamada cuadrado que recibe un entero para
calcular el cuadrado de dicho número. Analizaremos paso por paso el programa anterior
aplicando la estructura de un programa en C.
float suma(float num1, float num2)
{
float resultado;
resultado=num1+num2;
return resultado;
}
Declaración
de variables
Tipo de
resultado
Lista de
parámetros
Valor
devuelto
Nombre de la
función
I. DIRECTIVAS DE PRE- PROCESADOR
Se incluye la librería stdio.h porque utilizamos las funciones printf y scanf, además de
la conio.h por el getch().
II. DECLARACIÓN DE PROTOTIPOS
A continuación se hace la declaración de nuestra función cuadrado (lo que se llama
prototipo). Es necesario escribir el prototipo de todas las funciones que creemos. En este
caso el prototipo es: int cuadrado(int);
Un prototipo de función le da información importante al compilador. En el prototipo se
indican el tipo de dato que retorna la función, el número, tipo y orden de parámetros que
recibe la misma. El compilador utiliza los prototipos para verificar las llamadas a
funciones. Antes el prototipado no existía y el compilador no podía detectar ciertos
errores.
Este prototipo indica que la función de nombre cuadrado retorna como resultado un
valor de tipo entero. Además informa que la función debe ser llamada con un parámetro
de tipo entero también.
Las funciones de biblioteca se declaran en lo que se conocen como ficheros de cabecera
o ficheros .h (del inglés headers, cabeceras). Cuando deseamos utilizar alguna de las
funciones de biblioteca, debemos especificar el fichero .h en que se encuentra declarada
la función, al inicio de nuestro programa. Por ejemplo, si deseamos utilizar la función
printf en nuestro programa, debemos incluir el fichero stdio.h que contiene el prototipo
de esta función.
El prototipo también sirve para la coerción de argumentos, o sea, si la función es
llamada con valores de otro tipo diferentes a los definidos en el prototipo de esa
función, el compilador tratará de convertir esos valores a los tipos de datos
correspondientes declarados en el prototipo (esto funcionará siempre y cuando sea
posible la conversión entre esos tipos de datos). Por ejemplo, si la función espera un
entero y recibe un decimal, intentará convertir ese decimal al entero truncando la parte
decimal, lo cual puede generar errores si la exactitud de ese dato es importante. Por esta
razón se debe tener mucho cuidado en la coerción de tipos automática.
En el ejemplo mostrado, el primer int a la izquierda significa que la función devolverá
como respuesta a su ejecución un entero. Luego le sigue el nombre que le hemos puesto
a la función, en este caso cuadrado, y al final, entre paréntesis, los tipos de datos de los
parámetros que recibirá la función. En este caso sólo se recibirá un parámetro
(argumento) que es del tipo int (entero).
III. DECLARACIÓN DE VARIABLES GLOBALES
No hay en este caso
IV. FUNCIÓN PRINCIPAL
Se abre el programa principal main() y luego se crea la variable de tipo entero numero.
Luego se pide al usuario que ingrese un entero que se almacena en la variable numero.
Al final se llama a la función printf y dentro de esta, se llama a la función que hemos
creado nosotros: cuadrado(numero). Lo que hace ahora es ejecutar la función definida
más abajo con el parámetro numero. Esta función calcula el cuadrado de dicho número
y retorna el resultado (un entero), que luego se imprimirá en pantalla (por la función
printf dentro del main).
V. FUNCIONES DEFINIDAS POR EL USUARIO
Finalmente, fuera del main(), se define la función cuadrado que necesitamos y se
desarrollo. ES necesario aclarar que al momento de desarrollarla no se debe colocar al
final el punto y sus sentencias deben estar delimitadas por las llaves “{ }“ así: int
cuadrado(int y)
{sentencias
return expresión;
}
Donde <expresión> puede ser cualquier tipo de dato salvo un array o una función.
Además, el valor de la expresión debe coincidir con el tipo de dato declarado en el
prototipo de la función. Por otro lado, existe la posibilidad de devolver múltiples valores
mediante la utilización de punteros o estructuras.
Dentro de una función pueden existir varios return dado que el programa devolverá el
control a la sentencia que ha llamado a la función en cuanto encuentre la primera
sentencia return.
Si no existen return, la ejecución de la función continúa hasta la llave del final del
cuerpo de la función (}). Hay que tener en cuenta que existen funciones que no
devuelven ningún valor. El tipo de dato devuelto por estas funciones puede ser void,
considerado como un tipo especial de dato. En estos casos, la sentencia return se puede
escribir como return o se puede omitir directamente.
En el caso de los valores a retornar es necesario aclarar que no solo se refiere a una
variable, sino también a una operación así en el ejemplo anterior el retorno es la variable
resultado, pero una función puede retornar (y*y), donde se está multiplicando el
parámetro recibido, pero puede incluirse en la operación cualquier tipo de variable, así
el retorno sería:
return (y*y);
De esta manera se evita la declaración de variables locales dentro de la función, pero
esto no siempre resulta porque dentro de las funciones se realizan comúnmente muchos
procesos.
PARÁMETROS DE UNA FUNCIÓN
C siempre utiliza el método de parámetros por valor para pasar variables a funciones.
Los parámetros por valor reciben copias de los valores de los argumentos que se les
pasan, por lo tanto la asignación a parámetros valor de una función nunca cambian el
valor del argumento original pasado a los parámetros.
Esquema de paso de parámetros por valor en la llamada a una función.
Si la función es void funcion (void)no necesita parámetros, lo que significa que no
recibe nada y que tampoco retorna nada, por tanto dentro de la función se ejecutan las
sentencias necesarias para cumplir el objetivo de la función.
ACCESO A UNA FUNCIÓN
Para que una función realice la tarea para la cual fue creada, debemos acceder o llamar a
la misma. Cuando se llama a una función dentro de una expresión, el control del
programa se pasa a ésta y sólo regresa a la siguiente expresión de la que ha realizado la
llamada cuando encuentra una instrucción return o, en su defecto, la llave de cierre al
final de la función.
Generalmente, se suele llamar a las funciones desde la función main, lo que no implica
que dentro de una función se pueda acceder a otra función.
Cuando queremos acceder a una función, debemos hacerlo mediante su nombre seguido
de la lista de argumentos que utiliza dicha función encerrados entre paréntesis. En caso
de que la función a la que se quiere acceder no utilice argumentos, se deben colocar los
paréntesis vacíos.
Cualquier expresión puede contener una llamada a una función. Esta llamada puede ser
parte de una expresión simple, como una asignación, o puede ser uno de los operandos
de una expresión más compleja. Por ejemplo:
a=cubo(2);
calculo=b+c/cubo(3);
Debemos recordar que los argumentos que utilizamos en la llamada a una función se
denominan argumentos reales. Estos argumentos deben coincidir en el número y tipo
con los argumentos formales o parámetros de la función. No olvidemos que los
argumentos formales son los que se utilizan en la definición y/o declaración de una
función.
Los argumentos reales pueden ser variables, constantes o incluso expresiones más
main()
{
int i=6;
impri(i);
return 0;
} void impri(int i)
{
printf(“%d”,i);
i++;
}
complejas. El valor de cada argumento real en la llamada a una función se transfiere a
dicha función y se le asigna al argumento formal correspondiente.
Generalmente, cuando una función devuelve un valor, la llamada a la función suele
estar dentro de una expresión de asignación, como operando de una expresión compleja
o como argumento real de otra función.
Sin embargo, cuando la función no devuelve ningún valor, la llamada a la función suele
aparecer sola. Veamos un ejemplo:
z=potencia(a,b);
imprime_valores(x,y,z);
Ejemplo 2 : Vamos a acceder a las funciones primera y segunda desde la función
main. Estas funciones no reciben ningún parámetro ni retornan nada.
#include <stdio.h>
#include <conio.h>
void primera(void);
void segunda(void);
main()
{
printf(“Este es el inicio de la función main\n”);
primera();
segunda();
printf(“Este es el final de la función main\n”);
getch();
return 0;
}
void primera(void)
{
printf(“Llamada a la función primera\n”);
return;
}
void primera(void)
{
printf(“Llamada a la función segunda\n”);
return;
}
Resultado:
Este es el inicio de la función main
Llamada a la función primera
Llamada a la función segunda
Este es el final de la función main
ÁMBITO DE LAS VARIABLES
El alcance de un identificador es la porción del código en el cual dicho identificador
puede ser “visto” y, por lo tanto, referenciado. Un identificador puede ser una variable,
una etiqueta, un prototipo, una definición de función, etc.
En otras palabras, las reglas de alcance definen hasta dónde un identificador puede ser
usado.
Existen cuatro tipos de alcances posibles para un identificador: de programa, de
archivo, función y de bloque.
Las variables que tienen ámbito de programa pueden ser referenciadas por cualquier
función en el programa completo; tale variables se llaman variables globales. Para
hacer una variable global, hay que declararla al principio de un programa fuera de
cualquier función.
A diferencia de las variables locales cuyo ámbito estaba confinado a la función
donde estaban declaradas, el ámbito de las variables globales se extiende desde el
punto en el que se definen hasta el final del programa. En otras palabras, si
definimos una variable al principio del programa, cualquier función que forme parte
de éste podrá utilizarla simplemente haciendo uso de su nombre.
La utilización de variables globales proporciona un mecanismo de intercambio de
información entre funciones sin necesidad de utilizar argumentos. Por otra parte, las
variables globales mantienen el valor que se les ha asignado dentro de su ámbito,
incluso después de finalizar las funciones que modifican dicho valor. Debemos
tener en cuenta que el uso de variables globales para el intercambio de
informaciones entre funciones puede resultar útil en algunas situaciones (como
cuando se desea transferir más de un valor desde una función), pero su utilización
podría llevarnos a programas de difícil interpretación y complejos de depurar.
Cuando trabajamos con variables globales debemos distinguir entre la definición de
una variable global y su declaración. Cuando definimos una variable global, lo
hacemos de la misma forma en que se declara una variable ordinaria. La definición
de una variable global se realiza fuera de cualquier función. Además, las
definiciones de variables globales suelen aparecer antes de cualquier función que
desee utilizar dicha variable. La razón es que una variable global se identifica por la
localización de su definición dentro del programa. Cuando se define una variable
global automáticamente, se reserva memoria para el almacenamiento de ésta.
Además, podemos asignarle un valor inicial a la misma.
Si una función desea utilizar una variable global previamente definida, basta con
utilizar su nombre sin realizar ningún tipo de declaración especial dentro de la
función. Sin embargo, si la definición de la función aparece antes de la definición
de la variable global, se requiere incluir una declaración de la variable global dentro
de la función.
Debemos recordar que sólo se puede inicializar una variable global en su definición.
El valor inicial que se le asigne a la variable global debe expresarse como una
constante y no como una expresión. Es importante señalar que si no se asigna un
valor inicial a la variable global, automáticamente se le asigna el valor cero (0). De
esta manera, las variables globales siempre cuentan con un valor inicial.
Ejemplo 3: Utilización de variables globales como mecanismo de intercambio
de información entre funciones.
#include <stdio.h>
#include <conio.h>
void unafuncion();
void otrafuncion();
int variable;
main()
{
variable=9;
printf(“El valor de variable es: %d \n”,variable);
unafuncion();
otrafuncion();
printf(“Ahora el valor de variables es: %d \n”,variable);
getch();
return 0;
}
void unafuncion()
{ printf(“En la funcion unafuncion, el valor de variables es: %d\n”,variable);
}
void otrafuncion()
{
variuable++; printf(“En la funcion otrafuncion, el valor de variables es: %d\n”,variable);
}
Resultado:
El valor de variable es: 9
En la funcion unafuncion, el valor de variables es: 9
En la funcion otrafuncion, el valor de variables es: 10
Ahora el valor de variables es: 10
Una variable que se declara fuera de cualquier función y cuya declaración contiene
la palabra reservada static, tiene ámbito de archivo fuente. Las variables con este
ámbito se pueden referenciar desde el punto del programa en que están declaradas
hasta el final del archivo fuente.
Las variables estáticas pueden ser tanto locales como globales. Una variable estática
local, al igual que una variable automática, está únicamente asociada a la función en
la que se declara con la salvedad de que su existencia es permanente.
En otras palabras, su contenido no se borra al finalizar la función, sino que mantiene
su valor hasta el final del programa.
Ejemplo 4: en el siguiente programa declaramos la variable contador como estática
dentro de la función imprimevalor y desde la función main llamamos a esta función
varias veces:
#include <stdio.h>
#include <conio.h>
void imprimevalor();
main()
{
Imprimevalor();
Imprimevalor();
Imprimevalor();
Imprimevalor();
Imprimevalor();
getch();
return 0;
}
void imprimevalor()
{
Static int contador=0;
printf(“El valor del contador es: %d \n”, contador);
contador++;
}
La primera vez que se llama a la función imprimevalor se inicializa su valor a cero,
y tras imprimir su valor se incrementa éste. En las sucesivas llamadas, el valor de la
variable contador se mantiene y el resultado es el siguiente:
El valor de contador es: 0
El valor de contador es: 1
El valor de contador es: 2
El valor de contador es: 3
Una variable que tiene ámbito de una función se puede referenciar desde cualquier
parte de la función. Las variables declaradas dentro del cuerpo de una función se
dice que son locales a la función.
Cuando declaramos variables dentro de la función principal del programa, es decir,
dentro de la función main, están únicamente asociadas a esta función, en otras
palabras, son variables locales de la función main y no se puede acceder a ellas a
través de ninguna otra función.
Al igual que sucede con las variables declaradas dentro de la función main,
cualquier variable que declaremos dentro de una función, es local a esa función, es
decir, su ámbito esta confinado a dicha función. Esta situación permite que existan
variables con el mismo nombre en diferentes funciones y que no mantengan
ninguna relación entre sí.
Ejemplo 5: Utilización del mismo identificador de variable en diferentes funciones
mostrando su localidad.
#include <stdio.h>
#include <conio.h>
void imprimevalor();
main()
{
int contador=0;
contador++;
printf(“El valor del contador es: %d \n”, contador);
imprimevalor();
printf(“Ahora el valor de contador es: %d \n”, contador);
getch();
return 0;
}
void imprimevalor()
{
int contador=5;
printf(“El valor del contador es: %d \n”, contador);
}
Resultado:
El valor del contador es: 1
El valor del contador es: 5
Ahora el valor de contador es: 1
Una variable declarada en un bloque tiene ámbito de bloque y puede ser
referenciada en cualquier parte del bloque desde el punto en que está declarada
hasta el final del bloque. Las variables locales declaradas dentro de una función
tienen ámbito de bloque de la función; no son visibles fuera del bloque.
Ejemplo de declaración de variables y funciones en ámbitos diferentes
int total; //ámbito de programa
static int contador; //ámbito de archivo
float calculo (int dato) //ámbito de programa
{
….
{
int muestra; //ámbito de bloque
…..
}
}
FUNCIONES EN LÍNEA, MACROS CON ARGUMENTO
Las funciones de línea se usan cuando la función es una expresión (su código es
pequeño y se utiliza muchas veces en el programa). Realmente no son funciones, el
preprocesador expande o sustituye la expresión cada vez que es llamada. La sintaxis
general es:
#define Nombremacro(parámetros sin tipo) expresión_texto
La definición ocupará sólo una línea, aunque si se necesita más texto, se puede situar
una barra invertida(\) al final de la primera línea y continuar en la siguiente, en caso de
ser necesarias más líneas se procede de la misma forma; de esta manera se puede formar
una expresión más compleja. Entre el nombre de la macro y los paréntesis de la lista de
argumentos no puede haber espacios en blanco. Es importante tener en cuenta que en la
macro con argumentos no hay comprobación de tipos.
Ejemplo 6: Función en línea para definir una función matemática
#include <stdio.h>
#include <conio.h>
#define fexpresion(x) (x*x+2*x-1)
main()
{
float x;
for(x=0.0;x<6.5;x+=0.3)
printf(“\t f(%0.1f) = %6.2f ”,x,fexpresion(x));
getch();
return 0;
}
OTROS EJEMPLOS
Ejemplo 7: Función simple con transferencia de parámetros y muestra o ejecución
dentro de la función.
#include <stdio.h>
#include <conio.h>
void suma(int a, int b);
main()
{
suma(3,4);
getch();
return 0;
}
void suma(int a, int b)
{
printf("%d",a+b);
return 0;
}
Ejemplo 8: Función simple con retorno
#include <stdio.h>
#include <conio.h>
int suma();
main()
{
printf("%d",suma());
getch();
return 0;
}
int suma()
{
int a,b;
a=100; b=200;
return a+b;
}
Ejemplo 9: calcular el área de un rectángulo. El programa se descompone en dos
funciones, además del main().
#include <stdio.h>
#include <conio.h>
//Prototipos
float area_rectangulo(float b, float a);
float entrada();
//Programa principal
main()
{
float base,altura;
printf(“\n Introduzca la base del rectangulo: ”);
base=entrada();
printf(“\n Introduzca la altura del rectangulo: ”);
altura=entrada();
printf(“\n\nEl area del rectángulo es: %0.2f”,area_rectangulo(base,altura));
getch();
return 0;
}
float entrada()
{
float m;
do{
scanf(“%f”,&m);
} while (m<=0.0);
return m;
}
float area_rectangulo(float b, float a)
{
return (b*a);
}
Ejemplo 10: Escriba un programa que imprima un mensaje rodeado por un borde,
utilizando funciones para dibujar los elementos del borde.
#include <stdio.h>
#include <conio.h>
#define ANCHO 77
#define FILAS 4
void linea();
void lados();
main()
{
printf("\n\n\n\n");
linea();
lados();
printf(" *\t\t\t\t Bienvenido a C \t\t\t\t*\n");
lados();
linea();
printf("\n\n\n\n");
getch();
return 0;
}
void linea()
{
int x;
printf(" ");
for (x=0; x<=ANCHO; ++x)
putchar('*');
putchar('\n');
}
void lados()
{
int y;
for (y=0; y<=FILAS; ++y)
printf(" *\t\t\t\t\t\t\t\t\t\t*\n");
}
Ejemplo 11: Escriba un programa que calcule el cuadrado de un número mediante
una macro.
#include <stdio.h>
#include <conio.h>
#define CUAD(x) (x*x) /* Definicion de macros */
main()
{
float a;
printf("\nEscriba un numero: ");
scanf("% f",&a);
printf("\nSu cuadrado es: %f\n",CUAD(a));
getch();
return 0;
}