Unidad 7 - Funciones en Lenguaje C

Descargar como pptx, pdf o txt
Descargar como pptx, pdf o txt
Está en la página 1de 28

FUNCIONES EN LENGUAJE C

Informática I
Luis Eduardo Toledo
FUNCIONES: INTRODUCCIÓN

Las funciones permiten modularizar un programa.

Todas las variables definidas en las definiciones de funciones son variables locales;
solo se puede acceder a ellas en la función en la que están definidas.

La mayoría de las funciones tienen una lista de parámetros que proporcionan los
medios para comunicar información entre funciones a través de argumentos en
llamadas a funciones.

Los parámetros de una función también son variables locales de esa función.

Hay varias motivaciones para "funcionalizar" un programa. El enfoque de divide y


vencerás hace que el desarrollo del programa sea más manejable. Otra motivación es
la reutilización del software: usar las funciones existentes como bloques de
construcción para crear nuevos programas.

Una tercera motivación es evitar la repetición de código en un programa.


INTRODUCCIÓN

Cada programa que presentamos ha consistido en una función llamada


main que llamó funciones de biblioteca estándar para cumplir con sus
tareas.

Ahora consideraremos cómo escribir funciones personalizadas.

Considere un programa que utiliza una función cuadrado para calcular


e imprimir los cuadrados de los enteros del 1 al 10.
CREAR Y USAR UNA FUNCIÓN DEFINIDA
POR EL PROGRAMADOR
FORMATO DE LA DEFINICIÓN DE UNA
FUNCIÓN

return-value-type function-name(parameter-list)
{
statements
}

Juntos, el tipo de valor de retorno, el nombre de la función y la lista de


parámetros a veces se denominan encabezado de una función.

El tipo de valor de retorno void indica que una función no devuelve un valor.

La lista de parámetros es una lista separada por comas que especifica los
parámetros recibidos por la función cuando se la llama.
Si una función no recibe ningún valor, la lista de parámetros es void.

Se debe enumerar un tipo explícitamente para cada parámetro.

Las sentencias entre llaves forman el cuerpo de la función, que también es un


bloque.
DEVOLVER EL CONTROL DESDE UNA
FUNCIÓN

Hay tres formas de devolver el control de una función llamada al punto en el


que se la invocó.

Si la función no devuelve un resultado, el control se devuelve simplemente


cuando se alcanza la llave derecha de finalización de la función, o al
ejecutar la sentencia return.

Si la función devuelve un resultado, la sentencia return expression;


devuelve el valor de expression a la función invocante.

Tenga en cuenta que main tiene un tipo de retorno int. El valor de retorno de
main se usa para indicar si el programa se ejecutó correctamente.

Puede devolver explícitamente valores distintos de cero desde main para


indicar que se produjo un problema durante la ejecución de su programa.
FUNCIÓN MÁXIMO
FUNCIÓN MÁXIMO: CONTINUACIÓN
STACK DE LA LLAMADA A FUNCIÓN Y LA
ESTRUCTURA DEL STACK
Para comprender cómo C realiza las llamadas a funciones, primero debemos
considerar una estructura de datos (es decir, una colección de elementos de
datos relacionados) conocida como una pila o stack.

Piense en una pila como análoga a una pila de platos.

Cuando un plato se coloca en la pila, normalmente se coloca en la parte


superior (denominado empujar el plato sobre la pila. PUSH). Del mismo
modo, cuando un plato se retira de la pila, normalmente se retira de la parte
superior (se conoce como sacar el plato de la pila. POP).

Las pilas se conocen como estructuras de datos de último en entrar, primero


en salir (LIFO): el último elemento “empujado” (insertado) en la pila es el
primer elemento sacado (eliminado) de la pila.

Esta estructura de datos, que funciona "detrás de escena", admite el


mecanismo de llamada / retorno de función. También admite la creación,
mantenimiento y destrucción de las variables locales de cada función llamada
(también llamadas variables automáticas).
PILA DE LLAMADAS A FUNCIÓN
PILA DE LLAMADAS A FUNCIÓN
PILA DE LLAMADAS A FUNCIÓN
PASAR ARGUMENTOS POR VALOR Y POR
REFERENCIA

Cuando los argumentos se pasan por valor, se realiza una copia del valor del
argumento y se los pasa a la función invocada.

Los cambios en la copia no afectan el valor original de la variable en la función


invocante.

Cuando se pasa un argumento por referencia, la función invocante (que llama)


permite que la función invocada (llamada) modifique el valor de la variable
original.

El paso por valor debe usarse siempre que la función invocada no necesite
modificar el valor original de la variable de la función invocante.

Esto evita los efectos secundarios accidentales (modificaciones de las variables)


que dificultan en gran medida el desarrollo de sistemas de software correctos y
confiables.

El paso por referencia debe usarse solo con funciones denominadas


“confiables” que necesitan modificar la variable original.
PASAR ARREGLOS A FUNCIONES

Para pasar un argumento de ARREGLO a una función, especifique el nombre del


arreglo sin corchetes.
Por ejemplo, si el arreglo hourlyTemperatures se ha definido como:
int hourlyTemperatures[HOURS_IN_A_DAY];

modifyArray(hourlyTemperatures, HOURS_IN_A_DAY)

C automáticamente pasa arreglos a funciones por referencia

El nombre del arreglo se evalúa como la dirección del primer elemento del
arreglo.
NOMBRE DE ARREGLO IGUAL A LA
DIRECCIÓN DEL PRIMER ELEMENTO

void modifyArray(int b[ ], size_t size)


USO DEL CALIFICADOR CONST CON
PARÁMETROS DE ARREGLO
GENERACIÓN DE NÚMEROS ALEATORIOS

<stdlib.h> i = rand();
La función rand genera un número entero entre 0 y RAND_MAX (una constante
simbólica definida en el encabezado <stdlib.h>).
ALEATORIZACIÓN

La función srand toma un argumento int sin signo y siembra la función rand para
producir una secuencia diferente de números aleatorios para cada ejecución del
programa.

Para aleatorizar sin ingresar una semilla cada vez, use una sentencia como:

srand(time(NULL));

La función time devuelve el número de segundos que han pasado desde la


medianoche del 1 de enero de 1970.
CLASES DE ALMACENAMIENTO

Utilizamos identificadores para nombres de variables.


Los atributos de las variables incluyen nombre, tipo, tamaño y valor.
También utilizamos identificadores como nombres para las funciones
definidas por el usuario.
En realidad, cada identificador en un programa tiene otros atributos, incluida
la clase de almacenamiento, la duración del almacenamiento, el alcance y la
vinculación.
C proporciona los especificadores de clase de almacenamiento auto
(automático), register (registro), extern (externo) y static (estático).
La duración de almacenamiento de un identificador es el período durante el
cual el identificador existe en la memoria.
El alcance de un identificador es donde se puede hacer referencia al
identificador en un programa.
La vinculación de un identificador determina para un programa de múltiples
archivos fuente si el identificador se conoce solo en el archivo fuente actual o
en cualquier archivo fuente con las declaraciones adecuadas.
CLASES DE ALMACENAMIENTO

Los especificadores de clase de almacenamiento se pueden dividir entre la


duración de almacenamiento automático y la duración de almacenamiento
estático.
La palabra clave auto se utiliza para declarar variables de duración de
almacenamiento automático.
Las variables locales tienen una duración de almacenamiento automática de
forma predeterminada, por lo que rara vez se usa la palabra clave auto.

Las variables locales declaradas con la palabra clave static se conocen solo
en la función en la que se definen, pero a diferencia de las variables
automáticas, las variables locales estáticas conservan su valor cuando se sale
de la función.

La próxima vez que se llama a la función, la variable local estática contiene


el valor que tenía cuando la función salió por última vez.

La palabra clave register es arcaico y no debe usarse.


CLASES DE ALMACENAMIENTO

Las palabras clave extern y static se utilizan en las declaraciones de


identificadores para variables y funciones de duración de almacenamiento
estático.

Los identificadores de la duración del almacenamiento estático existen desde


el momento en que el programa comienza a ejecutarse hasta que finaliza.

Las variables globales se crean colocando declaraciones de variables fuera de


cualquier definición de función, y retienen sus valores durante la ejecución
del programa.

Las variables globales y los nombres de las funciones son de clase de


almacenamiento extern por defecto.
RECURSIVIDAD

Una función recursiva es aquella que se llama a si misma en forma directa o


indirectamente a través de otra función.

Se llama a una función recursiva para resolver un problema. La función


realmente sabe cómo resolver solo el caso/s más simple, o el llamado caso/s
base.

Si la función se llama con un caso base, la función simplemente devuelve un


resultado. Si la función se llama con un problema más complejo, la función
generalmente divide el problema en dos partes conceptuales: una parte que la
función sabe cómo resolver y una parte que no sabe cómo hacerlo.

Para que la recursividad sea factible, la última parte debe parecerse al


problema original, pero debe ser una versión un poco más simple o más
pequeña. Debido a que este nuevo problema se parece al problema original, la
función inicia (llama) una copia nueva de sí misma para trabajar en el
problema más pequeño; esto se conoce como una llamada recursiva o el paso
de recursión.
RECURSIVIDAD

El paso de recursión también incluye una sentencia return, ya que su


resultado se combinará con la parte del problema que la función supo resolver
para formar un resultado que se devolverá al llamador original.

El paso de recursión se ejecuta mientras la llamada original a la función está


en pausa, esperando el resultado del paso de recursión. El paso de recursión
puede dar lugar a muchas más llamadas recursivas, ya que la función sigue
dividiendo cada problema con el que se llama en dos partes conceptuales.

Para que la recursión termine, cada vez que la función se llama a sí misma
con una versión un poco más simple del problema original, esta secuencia de
problemas más pequeños finalmente debe converger en el caso base. Cuando
la función reconoce el caso base, devuelve un resultado a la copia anterior de
la función, y se produce una secuencia de retornos en toda la línea hasta que
la llamada original de la función finalmente devuelve el resultado final a su
invocante.
RECURSIVIDAD: CÁLCULO DEL FACTORIAL
DE UN NÚMERO ENTERO POSITIVO
n! = n · (n – 1) · (n – 2) · … · 1 5! = 5 · 4 · 3 · 2 · 1
5! = 5 · (4 · 3 · 2 · 1)
n! = n · (n – 1)!
5! = 5 · (4!)
RECURSIVIDAD: CÁLCULO DEL FACTORIAL
DE UN NÚMERO ENTERO POSITIVO
RECURSIVIDAD: CÁLCULO DEL FACTORIAL
DE UN NÚMERO ENTERO POSITIVO
EJEMPLO 2: NÚMERO DE UNOS EN LA
REPRESENTACIÓN BINARIA DE N.
/
******************************************************************************E
scriba una función recursiva que devuelva el número de unos en la
representación binaria de N. Use el hecho de que es igual al número
de unos en la representación binaria de N/2, más 1 si N es impar.
*******************************************************************************/
#include <stdio.h>
int cantunos (int a);
int main()
{ int num;
printf("Ingrese un número entero positivo: ");
scanf("%d",&num);
printf("\nLa cantidad de unos en binario es: %d", cantunos (num));
return 0;
}
int cantunos (int a)
{ if (a==0)
return 0;
else
return (a%2 + cantunos (a/2));
}
EJEMPLO 3: FUNCIÓN
power (base, exponente)
/***********************************************************************************
Escriba una función recursiva power (base, exponente) que, al llamarla,
devuelva baseexponente .Por ejemplo, power ( 3,4 ) = 3 * 3 * 3 * 3. Suponga que
exponente es un entero mayor o igual que 1.
***********************************************************************************/
#include <stdio.h>
int power (int base, int exponente);
int main()
{ int base, exponente:
printf("Ingrese un número como base: ");
scanf("%d",&base);
printf("\nIngrese un número como exponente: ");
scanf("%d",&exponente);
printf("\nLa potencia es: %d", power (base, exponente));
return 0;
}
int power (int base, int exponente)
{ if (exponente==1)
return base;
else
return (base * power (base, exponente - 1));
}

También podría gustarte