28 de octubre de 2019

Ejemplos de definición de funciones.

   Considere el Ejemplo 4.2. Las líneas 7 y 8 constituyen los prototipos de funciones y constituyen la firma de la función, en cuanto a que le indican al compilador que se definirán dos funciones: mayor y menor, mismas que recibirán tres parámetros enteros (int) y regresarán un valor entero.

   Tanto los tipos de datos como el número de parámetros así como el identificador de la función, están en relación directa con las necesidades del problema a resolver. Para el caso del Ejemplo 4.2, se definirán dos funciones que determinan (regresan), el mayor y menor respectivamente, de tres números enteros.

   Note que en las líneas 18 y 19 se realiza el llamado de las funciones mayor y menor respectivamente, y que el valor regresado por cada una de ellas se utiliza en el contexto del especificador de formato “%d” de la función printf correspondiente, el cual está asociado al tipo de dato de retorno de la función (int).

   Note también en las líneas 18 y 19, que a las funciones mayor y menor se les están pasando los datos a, b y c, los cuales son variables de la función main (línea 11), que a su vez contienen valores específicos (línea 15), y que son transferidos o enviados a las funciones mayor y menor respectivamente como sus argumentos.

   Por otro lado, las líneas 24-46 corresponden a la definición de las funciones mayor y menor. Las líneas 24-34 definen el grupo de sentencias que componen a la función mayor (note las llaves que definen el inicio y fin del bloque de función). Observe la estructura que sigue esta función, compárela con la estructura general de una función en C, y asegúrese de comprender la equivalencia.

   La línea 24 establece (define) que la función identificada como mayor, el cual es el identificador o nombre de la función, regresa un valor de tipo entero (int), y recibe tres parámetros de tipo entero (int) identificados por x, y y (x, y y z constituyen la lista de parámetros de la función).

   Ahora bien, la línea 25 define una variable local a la función mayor identificada como max. En C es posible definir variables al inicio de cada bloque ( { ... } ), y los bloques de función no son la excepción. Se pueden definir tantas variables locales como se necesiten y del tipo que se necesiten, y se siguen las mismas reglas de declaración de variables que para la función main.

   Las líneas 27-31 son sentencias de comparación que, a través de estructuras de selección, sirven para determinar el mayor de tres números distintos. La idea subyacente es la siguiente:
  1. Se selecciona a una de las variables como la mayor, supongamos que es x, y por lo tanto la asignamos a max (línea 25).
  2. Se compara la segunda variable y con el valor de la variable supuestamente mayor (max), si y > max (línea 27), entonces max no es la mayor y se almacena en max el valor mayor hasta ese momento (línea 28). En caso contrario, max tiene el valor mayor entre x y y y no hay necesidad de intercambiar.
  3. Se compara la tercera variable z con el valor de la variable hasta el momento mayor (max), si z > max (línea 30), entonces max no es la mayor y se almacena en max el valor mayor (línea 31). En caso contrario, no hay necesidad de intercambiar, max tiene el valor mayor de x, y y z.
   La línea 33 contiene la palabra reservada return seguida de la variable max, y al igual que en main, regresa el valor contenido en max a quien llamó a la función mayor, que para el caso del Ejemplo 4.2 ocurrió en la línea 18.

   Las líneas 36-46 para la función menor, se describen de manera análoga a las de la función mayor de las líneas 24-34.

   Una posible salida para el Ejemplo 4.2 se muestra en la siguiente figura:

Una posible salida del Ejemplo 4.2.
 
    Finalmente, note que es posible definir más de una función en un programa, de hecho no hay un límite en ese sentido, por lo que se pueden definir tantas funciones como sean necesarias, y todas siguen las mismas reglas descritas hasta aquí.

   Por otro lado, el Ejemplo 4.3 implementa una calculadora básica con las cuatro operaciones aritméticas. Las líneas 6-10 muestran los prototipos de las funciones que se definirán en las líneas 37-58. Dichos prototipos deberían ser claros en lo que expresan, con excepción quizá del prototipo de la línea 6.

   El prototipo de función de la línea 6, le indica al compilador que se definirá una función que no regresa nada (void). En en lenguaje de programación C, las funciones que sólo realizan alguna labor (como la presentación de un mensaje por ejemplo), pero que no necesitan regresar algún valor, usan éste tipo de dato. El tipo void es un tipo de dato muy importante, y su utilidad se retomará en la entrada referente a apuntadores, por ahora, basta con saber que ésta es una de sus utilidades.

   Ahora bien, el bloque (cuerpo) de la función principal main se encarga de leer los datos (línea 19), de verificar que sean los apropiados o que cumplan con ciertas características (ciclo do-while), y de tomar la decisión de qué servicio (función) solicitar (llamar), en respuesta (estructura switch) al operador op leído (línea 19), para finalmente presentar el resultado (línea 32).

   La definición de funciones está de las líneas 37-58, y se describen de la siguiente manera:
  • La función instrucciones (líneas 37-42), se utiliza para mostrar un mensaje en la salida estándar que contiene instrucciones básicas del uso del programa. 
  • La función suma (líneas 44-46) es bastante simple, ya que regresa a quien la llame, el valor de la expresión de suma (a + b) de los parámetros a y b. Observe que aunque es posible, no es necesario guardar el resultado de dicha expresión en una variable local y después regresarla, de hecho, es muy común en C  escribir este tipo de expresiones como valor de retorno. 
  • Las funciones resta (líneas 48-50), multiplica (líneas 52-54), y divide (líneas 56-58), se describen de manera análoga a la función suma.
   Note que la función divide no hace ningún tipo de verificación del denominador para realizar la operación de división, debido a que asume que ya se ha realizado dicha verificación en alguna otra parte del programa (main línea 20), y que el denominador es distinto de cero. El programa del Ejemplo 4.3 es sólo un posible diseño a dicha situación, mismo que no es el único ni necesariamente el mejor, sin embargo funciona y refuerza el concepto de programación modular que se ha venido mencionado.

   Finalmente, tome en cuenta que para el programa del Ejemplo 4.3 ninguna de sus funciones, excepto main, hace uso de otra función para completar su tarea debido a su simplicidad, sin embargo, es posible hacerlo y se mostrará en ejemplos posteriores. Una posible salida para el Ejemplo 4.3 se muestra en la siguiente figura:
Una posible salida del Ejemplo 4.3.