2. Variables
3. Paso de parámetros
4. Recursividad
5. ¿Cómo pasar Parámetros a Funciones?
1. CONCEPTO DE FUNCIÓN
Las funciones
son los bloques constructores de C y el lugar donde se da toda la actividad del
programa.
La forma
general de definición de una función es:
tipo nombre (lista
de parámetros)
{
cuerpo de la
función
}
El tipo
especifica el tipo de valor que devuelve la sentencia return de la función. El
valor puede ser cualquier tipo válido; si no se especifica ninguno, se asume un
resultado entero.
La lista de
parámetros es la lista de nombres de variables separados por comas con sus
tipos asociados que reciben los valores de los argumentos cuando se llama a la
función.
Una función
puede no tener parámetros, en cuyo caso la lista de parámetros está vacía; sin
embargo, los paréntesis son necesarios.
Declaración
Cada función
debe ser declarada. Su forma general es:tipo nombre_función (lista de tipos (y
nombres) de los argumentos); Si una función va usar argumentos, debe declarar
variables que acepten los valores de los argumentos. Estas variables se llaman
parámetros formales de la función y se comportan como variables locales dentro
de la función, creándose al entrar en la función y destruyéndose al salir. La
declaración de parámetros aparece después del nombre de la función al
definirla.
Los
parámetros formales tienen que ser del mismo tipo que los argumentos usados al
llamar una función (el compilador no dará error pero los resultados serán
inesperados).
Una función
es visible para ella misma y otras funciones desde el momento en que se define.
Es visible para el propio cuerpo de la función, es decir, la recursividad esta permitida.
El código de una función es privado a esa función y sólo se puede acceder a él
mediante una llamada a esa función. Las variables definidas dentro de una
función son locales (a no ser que las definamos globales) por lo que no
conservan su valor de una llamada a otra (excepto si se declaran como static,
entonces el compilador no las destruye y almacena su valor para la próxima
llamada, aunque la variable tiene limitado el ámbito al interior de la
función).
En C, todas
las funciones están al mismo nivel, es decir, no se puede definir una función
dentro de otra función. Esto es por lo que C no es técnicamente un lenguaje
estructurado por bloques.
El código de
una función es privado a esa función y sólo se puede acceder a él mediante una
llamada a esa función. Las variables definidas dentro de una función son
locales (a no ser que las definamos globales) por lo que no conservan su valor
de una llamada a otra (excepto si se declaran como static, entonces el
compilador no las destruye y almacena su valor para la próxima llamada, aunque
la variable tiene limitado el ámbito al interior de la función).
Llamadas a funciones
Las funciones
son llamadas para su ejecución desde cualquier parte del código, teniendo en
cuenta que antes deben haber sido declaradas (y por supuesto definidas).
La llamada de
una función se produce mediante el uso de su nombre en una sentencia, pasando
una lista de argumentos que deben coincidir en número y tipo con los
especificados en la declaración (en otro caso se produciría una conversión de
tipos o resultados inesperados). Llamadas por valor y por referencia En
general, se pueden pasar argumentos a las funciones de dos formas, por valor y
por referencia.
La llamada
por valor copia el valor de un argumento en el parámetro formal de la función.
De esta forma, los cambios en los parámetros de la función no afectan a las
variables que se usan en la llamada (es la llamada más usual, es decir, en
general no se pueden alterar las variables usadas para llamar a la función).
La llamada
por referencia copia la dirección del argumento en el parámetro. Dentro de la
función se usa la dirección para acceder al argumento usado, significando que
los cambios hechos a los parámetros afectan a la variable usada en la llamada.
Es posible
simular una llamada por referencia pasando un puntero al argumento, entonces,
al pasar la dirección, es posible cambiar el valor de la variable usada en la
llamada.
2. VARIABLES
Una variable
es un nombre que empieza con una letra y varios caracteres más (el total de
caracteres depende de la versión del lenguaje y la computadora que se emplea);
se recomienda usar solo letras minúsculas, dígitos y el subguión.
Las variables
del lenguaje C están clasificadas en:
Enteras
Reales
De cadena
(alfanuméricas)
OTROS DATOS
Variables con
índice.
Parámetros
asociados a las variables y se emplean para almacenar los valores definidos por
constantes de tipo: entero, real y alfanumérico.
VARIABLES ENTERAS
Las variables
enteras son aquellas cuyo nombre está mencionado en una declaración de tipo
incluida en algún lugar del programa, por ejemplo:
Int a,b,c; unsigned int x,y,z;
También se
puede definir la doble precisión para enteras. Por ejemplo:
Long int a,b,c;
VARIABLES REALES
Las variables
reales son aquellas cuyo nombre está mencionado en una declaración de tipo
incluida en algún lugar del programa, por ejemplo con precisión simple:
float a,b,c;
float d=1.0, e=0.5, f=0.0;
y con doble
precisión:
double i,j,k;
double g=1.567845645,h=-0.54666,f=-1.0;
Las variables
alfanuméricas son aquellas cuyo nombre esta mencionado en una declaración de
tipo incluida en algún lugar del programa, por ejemplo:
Char
g[4]="uno",h[10]="siguiente",index='O';
VARIABLES CON INDICE
Las variables
con indice pueden ser de cualquiera de los tipos previamente vistos. Su uso en
la ingeniería está relacionado con el manejo de arreglos en una y mas
dimensiones (vectores y matrices principalmente). La declaración de ellas se
hace como se muestra a continuación:
Tiponombre_de_la_variable
[número de elementos];
Todos los
arreglos inician con el elemento cero, por consiguiente la declaración que
sigue:
Int W[4],
z[6][5];
Indica que el
vector de valores enteros w[4] cuenta con elementos w[0],w[1],w[2] y w[3],
mientras que el siguiente arreglo es una matriz de 6x5, es decir de 30
elementos con valores de tipo entero, con elementos z[0][0],z[0][1]...z[0][4];
z[1][0],z[1][1]...z[1][4];...;z[5][0],z[5][1]...z[5][4].
Observe que
en el caso de las variables alfanuméricas se debe considerar el elemento nulo
que se agrega automáticamente al final de la cadena.
3. PASO DE PARÁMETROS.
El
lenguaje C utiliza el Paso de Parámetros por Valor al pasar argumentos; esto
quiere decir que el módulo que es llamado trabaja con una copia de las
variables , y por lo tanto cualquier modificación que se quiera hacer a los
parámetros no afectará a las variables originales.
Para
realizar un Paso de Parámetros por Referencia se hace pasando un apuntador a un
argumento, esto implica que se pase la dirección del argumento a la función,
entonces es posible cambiar el valor argumento fuera de la función.
#include <stdio.h>
main()
{
int edad;
printf (“Dame tu edad \n”);
scanf (“%d”, &edad);
imprime (edad) ;
suma (&edad);
imprime (edad);
}
imprime (int b) /* Paso de Parámetros por Valor */
{
printf (“Tu edad es %d \n”, b);
return;
}
suma
(int *a) /* Paso de Parámetros por Referencia */
{
*a=*a+1;
}
Parámetros asociados a las variables.
Todas las
variables tienen asociados tres parámetros muy importantes:
Su nombre, su
dirección en memoria, su contenido o valor asignado
Recuerde que
cada byte tiene asociada una dirección que permite localizar su contenido en
memoria; de igual forma las variables se les asociar esos parámetros.
4. RECURSIVIDAD
La
recursividad es una técnica de programación importante. Se utiliza para
realizar una llamada a una función desde la misma función. Como ejemplo útil se
puede presentar el cálculo de números factoriales. Él factorial de 0 es, por
definición, 1. Los factoriales de números mayores se calculan mediante la
multiplicación de 1 * 2 * ..., incrementando el número de 1 en 1 hasta llegar
al número para el que se está calculando el factorial.
El siguiente
párrafo muestra una función, expresada con palabras, que calcula un factorial.
"Si el
número es menor que cero, se rechaza. Si no es un entero, se redondea al
siguiente entero. Si el número es cero, su factorial es uno. Si el número es
mayor que cero, se multiplica por él factorial del número menor
inmediato."
Para calcular
el factorial de cualquier número mayor que cero hay que calcular como mínimo el
factorial de otro número. La función que se utiliza es la función en la que se
encuentra en estos momentos, esta función debe llamarse a sí misma para el
número menor inmediato, para poder ejecutarse en el número actual. Esto es un
ejemplo de recursividad.
La
recursividad y la iteración (ejecución en bucle) están muy relacionadas,
cualquier acción que pueda realizarse con la recursividad puede realizarse con
iteración y viceversa. Normalmente, un cálculo determinado se prestará a una
técnica u otra, sólo necesita elegir el enfoque más natural o con el que se
sienta más cómodo.
Claramente,
esta técnica puede constituir un modo de meterse en problemas. Es fácil crear
una función recursiva que no llegue a devolver nunca un resultado definitivo y
no pueda llegar a un punto de finalización. Este tipo de recursividad hace que
el sistema ejecute lo que se conoce como bucle "infinito".
Para entender
mejor lo que en realidad es el concepto de recursión veamos un poco lo
referente a la secuencia de Fibonacci.
Principalmente
habría que aclarar que es un ejemplo menos familiar que el del factorial, que
consiste en la secuencia de enteros.
0,1,1,2,3,5,8,13,21,34,...,
Cada elemento
en esta secuencia es la suma de los precedentes (por ejemplo 0 + 1 = 0, 1 + 1 =
2, 1 + 2 = 3, 2 + 3 = 5, ...) sean fib(0) = 0, fib (1) = 1 y así sucesivamente,
entonces puede definirse la secuencia de Fibonacci mediante la definición
recursiva (define un objeto en términos de un caso mas simple de si mismo):
fib (n) = n if n = = 0 or n = = 1
fib (n) = fib (n - 2) + fib (n - 1) if n >= 2
Por ejemplo,
para calcular fib (6), puede aplicarse la definición de manera recursiva para
obtener:
Fib (6) = fib
(4) + fib (5) = fib (2) + fib (3) + fib (5) = fib (0) + fib (1) + fib (3) + fib
(5) = 0 + 1 fib (3) + fib (5)
1. + fib (1) + fib (2) + fib(5) =
1. + 1 + fib(0) + fib (1) + fib (5) =
2. + 0 + 1 + fib(5) = 3 + fib (3) + fib (4)
=
3 + 1 + fib (0) + fib (1) + fib (4) =
3. + fib (1) + fib (2) + fib (4) =
4. + 0 + 1 + fib (2) + fib (3) = 5 + fib (0)
+ fib (1) + fib (3) =
5. + 0 + 1 + fib (1) + fib (2) = 6 + 1 + fib
(0) + fib (1) =
6. + 0 + 1 = 8
Programación Recursiva:
Es mucho más difícil desarrollar una solución recursiva en C para resolver un problema especifico cuando no se tiene un algoritmo. No es solo el programa sino las definiciones originales y los algoritmos los que deben desarrollarse. En
Volviendo a examinar la función factorial. El factor es, probablemente, un ejemplo fundamental de un problema que no debe resolverse de manera recursiva, dado que su solución iterativa es directa y simple. Sin embargo, examinaremos los elementos que permiten dar una solución recursiva. Antes que nada, puede reconocerse un
Examinaremos que significa lo anterior cuando se aplica la función factorial. 4! Es un caso más complejo que 3!. La transformación que se aplica al número a para
n! = n * (n – 1)!
Así, 4! = 4 * 3! = 4 * 3 * 2! = 4 * 3 * 2 *
1! = 4 * 3 * 2 * 1 * 0! = 4 * 3 * 2] * ] = 24
Estos son
los ingredientes esenciales de una rutina recursiva: poder definir un caso
"complejo" en términos de uno más "simple" y Otra forma de aplicar estas ideas a otros ejemplos antes explicados. En la definición de a * b, es trivial el caso de b = 1, pues a * b es igual a a. En general, a + b puede definirse en términos de a * (b – 1) mediante la definición a * b = a * (b – 1) + a. De nuevo, el caso complejo se transforma en un caso más simple al restar 1, lo que lleva, al final, al caso trivial de b = 1. Aquí la recursión se basa únicamente en el segundo parámetro, b.
Con respecto al ejemplo de la función de Fibonacci, se definieron dos casos triviales: fib(0) = 0 y fib(1) = 1. Un caso complejo fib(n) se reduce entonces a dos más simples: fib(n –1) y fib(n –2). Esto se debe a la definición de fib(n) como fib(n –1) + fib(n – 2), donde se requiere de dos casos triviales definidos de manera directa. Fib(1) no puede definirse como fib(0) + fib(-1) porque la función de Fibonacci no está definida para números negativos.
5. ¿CÓMO PASAR PARÁMETROS A FUNCIONES?
Una
función puede recibir tantos parámetros como queramos y para expresarlo se
colocan los nombres de los parámetros separados por comas, dentro de los
paréntesis. Veamos rápidamente la sintaxis para que la función de antes, pero
hecha para que reciba dos parámetros, el primero el nombre al que saludar y el
segundo el color del texto.
function escribirBienvenida(nombre,colorTexto){
document.write("<FONT color='" + colorTexto + "'>")
document.write("<H1>Hola " + nombre + "</H1>")
document.write("</FONT>")
}
Llamaríamos a la función con esta sintaxis. Entre los paréntesis colocaremos los valores de los parámetros.
var miNombre = "Pepe"
var miColor = "red"
escribirBienvenida(miNombre,miColor)
He colocado entre los paréntesis dos variables en lugar de dos textos entrecomillados. Cuando colocamos variables entre los parámetros en realidad lo que estamos pasando a la función son los valores que contienen las variables y no las mismas variables.
function escribirBienvenida(nombre,colorTexto){
document.write("<FONT color='" + colorTexto + "'>")
document.write("<H1>Hola " + nombre + "</H1>")
document.write("</FONT>")
}
Llamaríamos a la función con esta sintaxis. Entre los paréntesis colocaremos los valores de los parámetros.
var miNombre = "Pepe"
var miColor = "red"
escribirBienvenida(miNombre,miColor)
He colocado entre los paréntesis dos variables en lugar de dos textos entrecomillados. Cuando colocamos variables entre los parámetros en realidad lo que estamos pasando a la función son los valores que contienen las variables y no las mismas variables.
Los parámetros se pasan por valor.
Al hilo
del uso de parámetros en nuestros programas Javascript, tenemos que saber que
los parámetros de las funciones se pasan por valor. Esto quiere decir que
estamos pasando valores y no variables. En la práctica, aunque modifiquemos un
parámetro en una función, la variable original que habíamos pasado no cambiará
su valor. Se puede ver fácilmente con un ejemplo.
function pasoPorValor(miParametro){
miParametro = 32
document.write("he cambiado el valor a 32")
}
var miVariable = 5
pasoPorValor(miVariable)
document.write ("el valor de la variable es: " + miVariable)
En el ejemplo tenemos una función que recibe un parámetro y que modifica el valor del parámetro asignándole el valor 32. También tenemos una variable, que inicializamos a 5 y posteriormente llamamos a la función pasándole esta variable como parámetro. Como dentro de la función modificamos el valor del parámetro podría pasar que la variable original cambiase de valor, pero como los parámetros no modifican el valor original de las variables, ésta no cambia de valor.
function pasoPorValor(miParametro){
miParametro = 32
document.write("he cambiado el valor a 32")
}
var miVariable = 5
pasoPorValor(miVariable)
document.write ("el valor de la variable es: " + miVariable)
En el ejemplo tenemos una función que recibe un parámetro y que modifica el valor del parámetro asignándole el valor 32. También tenemos una variable, que inicializamos a 5 y posteriormente llamamos a la función pasándole esta variable como parámetro. Como dentro de la función modificamos el valor del parámetro podría pasar que la variable original cambiase de valor, pero como los parámetros no modifican el valor original de las variables, ésta no cambia de valor.
De este modo,
una vez ejecutada la función, al imprimir en pantalla el valor de miVariable se
imprimirá el número 5, que es el valor original de la variable, en lugar de 32
que era el valor con el que habíamos actualizado el parámetro.