5. Funciones con punteros (apuntes en pdf)

5.1 Argumentos de entrada/salida

Los punteros son al C lo que el Everest a los alpinistas, el sumum de la programación. Realmente no es para tanto, pero siempre se han visto rodeados de un halo de misterio y dificultad con el que los alumnos veteranos asustan a los nuevos. Los punteros tienen una dificultad intrínseca y otra debido a su abuso y mal uso por numerosas generaciones de profesores de programación. El principal uso de los punteros en C es establecer un mecanismo que permite que las funciones puedan modificar un argumento de entrada. Por ejemplo, al ejecutarse el siguiente programa la consola mostraría “a vale 8” y “x vale 7”
 
 
 
 
 
 
 
 
 
 


Esto quiere decir que el argumento real x ha copiado su valor en a al invocarse la función, pero que el valor de a no se ha copiado en x al terminar la función y por tanto, x permanece invariable. Hasta ahora este problema se ha soslayado porque nuestras funciones sólo devolvían un valor en el nombre de la función o bien devolvían su valor en una array al que no ponemos la cláusula const. Es decir, los arrays tienen un comportamiento diferente al de las variables “normales”. Así por ejemplo, el siguiente código escribirá en la consola 2 3 4 modificando los valores del array tab, ya que los cambios en el argumento formal t de la función cambiaValores afectan a tab.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

¿Por qué se produce ese efecto colateral en los arrays y no en las variables de tipo int? La respuesta es simple y compleja a la vez: porque un array es un puntero.
Pero antes de entrar en más dificultades, volvamos al problema original. ¿Cómo hacer que una función en C cambie el valor de un argumento de entrada? Insisto en que este problema hasta ahora lo hemos resuelto haciendo que el valor cambiado se devuelva en el nombre de la función, pero ¿Qué pasa si queremos devolver dos valores?
 
5.1.1 Función que reciba tres valores enteros y sumara el primero al segundo y tercero, modificándolos. Esto es, queremos hacer que el programa siguiente escribiera, v: 11 w: 10 y n: 13 m: 14.
 

 








Tal y como está escrito el programa anterior los argumentos v, w, n y m valdrán lo mismo antes que después de invocar a sumaValores. ¿Cómo se puede conseguir entonces que cambien? Pues haciendo que los parámetros formales x e y sean punteros. Esto es, no sean variables “normales” sino las direcciones de memoria donde se guardan variables de tipo int. De esta forma cuando se invoque con los argumentos v y w ó n y m no sólo estaremos haciendo una copia de sus valores sino que estaremos proporcionando a sumaValores su dirección de memoria, de esta forma los cambios en x e y tendrán efectos laterales sobre v, w, n y m. El código debe quedar así:











Nótense las siguientes cuestiones:

1.       x e y son variables punteros, pero v, w, n y m siguen siendo variables “normales”.

2.       El operador * tiene un doble significado: en la cabecera y prototipo de sumaValores indica que x e y se definen como direcciones de memoria (punteros) y en el código de la función indican “contenido” de variable puntero.

3.       Los * y los & no se mezclan. Los * están en la función y los & en la invocación de la función.

4.       Los parámetros reales (en las invocaciones del main) deben ser direcciones de memoria, por eso se pone el símbolo & que indica dirección de memoria de una variable “normal”.

5.       En las sentencias printf los argumentos v, w, n y m son los de siempre, esto es no tienen & y mucho menos *.


5.1.2 Función tal que dados dos valores de tipo entero n y m los intercambia. Esto es, al finalizar la función el primer argumento toma el valor del segundo y el segundo el primero.












Y su salida por pantalla sería

v: 7 w: 8
n: 10 m: 9

 

 5.1.3 Usando esta función 5.1.2  implemente una función tal que dados dos valores reales los devuelve ordenados, esto es, después de invocarse el segundo argumento siempre será mayor que el primero. De esta manera si la función se invoca con v=7.0 y w=8.0 (en ese orden) devolverá v=7.0 y w=8.0 porque ya estaban ordenados, sin embargo si v=8.0 y w=7.0 (en ese orden) entonces devolverá v=7.0 y w=8.0.
 



 


5.1.4 Función que recibe un entero indicando una cantidad de segundos y devuelve el equivalente en horas, minutos y segundos.









5.1.5 Función que recibe dos enteros indicando minutos y segundos y devuelve el equivalente en horas, minutos y segundos.









5.1.6 Disponemos de un array con las medidas de la presión sanguínea de un paciente tomadas hora a hora durante un mes (24*30=720 valores). Implemente una función tal que dado un índice a dicho array devuelva el día y la hora en que se tomó la muestra que ocupa ese índice. Tenga en cuenta que la primera hora es la 0 y el primer día el 1. Por ejemplo el índice 0 es la primera hora del primer día y devolvería hora=0 y día=1; el índice 23 es la última hora del primer día y devolvería hora=23 y día=1; el número 27 la cuarta hora del segundo día y devolvería hora=3 y día=2 y así sucesivamente. Por ejemplo, el valor 52 daría hora=4 y día=3.






 

No hay comentarios:

Publicar un comentario