Utilizando funciones en C++ - Información de DVDs

main1.png main2.png main3.png

Una buena manera de organizar y estructurar los programas de computadoras es dividiéndolos en partes más pequeñas utilizando funciones. Cada función realiza una tarea específica del problema que estamos resolviendo.

Haz visto que todos los programas en C++ deben contener la función main que es donde comienza el programa. Probablemente ya has utilizado funciones como pow, sin, cos o sqrt de la biblioteca de matemática cmath. Dado que en casi todas las experiencias de laboratorio futuras estarás utilizando funciones pre-definidas, necesitas aprender cómo trabajar con ellas. Más adelante aprenderás cómo diseñarlas y validarlas. En esta experiencia de laboratorio harás búsquedas y desplegarás información contenida en una base de datos de DVDs para practicar la creación de funciones simples y la invocación de funciones pre-definidas.

Objetivos:

  1. Identificar las partes de una función: tipo, nombre, lista de parámetros y cuerpo.
  2. Invocar funciones pre-definidas pasando argumentos por valor ("pass by value") y por referencia ("pass by reference").
  3. Implementar una función simple que utilice parámetros por referencia.

Pre-Lab:

Antes de llegar al laboratorio debes:

  1. Haber repasado los siguientes conceptos:

    a. los elementos básicos de la definición de una función en C++

    b. la manera de invocar funciones en C++

    c. la diferencia entre parámetros pasados por valor y por referencia

    d. cómo devolver el resultado de una función.

  2. Haber estudiado los conceptos e instrucciones para la sesión de laboratorio.

  3. Haber tomado el quiz Pre-Lab, disponible en Moodle.



Funciones

En matemática, una función es una regla que se usa para asignar a cada elemento de un conjunto llamado dominio, un (y solo un) elemento de un conjunto llamado campo de valores. Por lo general, esa regla se representa como una ecuación, . La variable es el parámetro de la función y la variable contendrá el resultado de la función. Una función puede tener más de un parámetro pero solo un resultado. Por ejemplo, una función puede tener la forma en donde hay dos parámetros y para cada par que se use como argumento de la función, y la función tendrá un solo valor de . El dominio de la función te dice el tipo de valor que debe tener el parámetro y el campo de valores dice el tipo de valor que tendrá el resultado que devuelve la función.

Las funciones en lenguajes de programación de computadoras son similares. Una función tiene una serie de instrucciones que toman los valores asignados a los parámetros y realiza alguna tarea. En C++ y en algunos otros lenguajes de programación, las funciones solo pueden devolver un resultado, tal y como sucede en matemáticas. La única diferencia es que una función en programación puede que no devuelva un valor (en este caso la función se declara void). Si la función va a devolver algún valor, se hace con la instrucción return. Al igual que en matemática tienes que especificar el dominio y el campo de valores, en programación tienes que especificar los tipos de valores que tienen los parámetros y el resultado que devuelve la función; esto lo haces al declarar la función.

El encabezado de una función

La primera oración de una función se llama el encabezado y su estructura es como sigue:

tipo nombre(tipo parámetro_1, ..., tipo parámetro_n)`

Por ejemplo,

int ejemplo(int var1, float var2, char &var3)

sería el encabezado de la función llamada ejemplo, que devuelve un valor entero. La función recibe como argumentos un valor entero (y guardará una copia en var1), un valor de tipo float (y guardará una copia en var2) y la referencia a una variable de tipo char que se guardará en la variable de referencia var3. Nota que var3 tiene el signo & antes del nombre de la variable. Esto indica que var3 contendrá la referencia a un carácter.

Invocación

La siguiente línea asigna a la variable x el resultado de la llamada a ejemplo:

Si queremos guardar el valor del resultado de la función ejemplo en la variable x (que deberá ser de tipo entero), invocamos la función pasando argumentos de manera similar a:

x = ejemplo(2, 3.5, unCar);

Nota que al invocar funciones no incluyes el tipo de las variables en los argumentos como en la definición de la función. El tercer parámetro &var3 es una variable de referencia, esto significa que lo que se está enviando es una referencia a la variable unCar. Las asignaciones que se hagan a la variable var3 dentro de la función ejemplo cambian el valor de unCar.

El resultado de una función puede ser dirigido al objeto cout para ser desplegado en el terminal, como muestra la siguiente línea:

cout << "El resultado de la función ejemplo es:" << ejemplo(2, 3.5, unCar);`

o puede ser utilizado en una expresión aritmética:

y = 3 + ejemplo(2, 3.5, unCar);`

Funciones sobrecargadas (‘overloaded’)

Las funciones sobrecargadas son funciones que poseen el mismo nombre, pero tienen firmas diferente.La firma de una función se compone del nombre de la función, y los tipos de parámetros que recibe, pero no incluye el tipo que devuelve. Los siguientes prototipos de funciones tienen firmas iguales:

int ejemplo(int, int) ;
void ejemplo(int, int) ; 
string ejemplo(int, int) ;

Nota que todas tienen el mismo nombre, ejemplo, y reciben la misma cantidad de parámetros del mismo tipo (int, int).

Los siguientes prototipos de funciones tienen firmas diferentes:

int ejemplo(int) ;
int olpmeje(int) ;

Nota que a pesar de que las funciones tienen la misma cantidad de parámetros con mismo tipo int, el nombre de las funciones es distinto.

Los siguientes prototipos de funciones son versiones sobrecargadas de la función ejemplo:

int ejemplo(int) ;
void ejemplo(char) ;
int ejemplo(int, int) ;
int ejemplo(char, int) ;
int ejemplo(int, char) ;

Todas las funciones de arriba tienen el mismo nombre, ejemplo, pero distintos tipos y/o ordenes de parámetros. La primera y segunda función tienen la misma cantidad de parámetros, pero los argumentos son de distintos tipos. La cuarta y quinta función tienen argumentos de tipo char e int, pero en cada caso están en distinto orden.

En este último ejemplo la función ejemplo está sobrecargada ya que hay cinco funciones con firmas distintas pero con el mismo nombre.

Valores predeterminados

Se pueden asignar valores predeterminados ("default") a los parámetros de las funciones comenzando desde el parámetro que está más a la derecha. No hay que inicializar todos los parámetros pero los que se inicializan deben ser consecutivos: no se puede dejar parámetros sin inicializar entre dos parámetros que estén inicializados. Esto permite la invocación de la función sin tener que enviar los valores en las posiciones que corresponden a parámetros inicializados.

Ejemplos de encabezados de funciones e invocaciones válidas:

  1. Encabezado: int ejemplo(int var1, float var2, int var3 = 10) Aquí se inicializa var3 a 10.

    Invocaciones:

    a. ejemplo(5, 3.3, 12) Esta invocación asigna el valor 5 a var1, el valor 3.3 a var2, y el valor 12 a var3.

    b. ejemplo(5, 3.3) Esta invocación envía valores para los primeros dos parámetros y el valor del último parámetro será el valor predeterminado asignado en el encabezado. Esto es, los valores de las variables en la función serán: var1 tendrá 5, var2 tendrá 3.3, y var3 tendrá 10.

  2. Encabezado: int ejemplo(int var1, float var2=5.0, int var3 = 10) Aquí se inicializa var2 a 5 y var3 a 10.

    Invocaciones:

    a. ejemplo(5, 3.3, 12) Esta invocación asigna el valor 5 a var1, el valor 3.3 a var2, y el valor 12 a var3.

    b. ejemplo(5, 3.3) En esta invocación solo se envían valores para los primeros dos parámetros, y el valor del último parámetro es el valor predeterminado. Esto es, el valor de var1 dentro de la función será 5, el de var2 será 3.3 y el de var3 será 10.

    c. ejemplo(5) En esta invocación solo se envía valor para el primer parámetro, y los últimos dos parámetros tienen valores predeterminados. Esto es, el valor de var1 dentro de la función será 5, el de var2 será 5.0 y el de var3 será 10.

Ejemplo de un encabezado de funciones válido con invocaciones inválidas:

  1. Encabezado: int ejemplo(int var1, float var2=5.0, int var3 = 10)

    Invocación:

    a. ejemplo(5, ,10) Esta invocación es inválida porque deja espacio vacío en el argumento del medio.

    b. ejemplo() Esta invocación es inválida ya que var1 no estaba inicializada y no recibe ningún valor en la invocación.

Ejemplos de encabezados de funciones inválidos:

  1. int ejemplo(int var1=1, float var2, int var3) Este encabezado es inválido porque los valores predeterminados sólo se pueden asignar comenzando por el parámetro más a la derecha.

  2. int ejemplo(int var1=1, float var2, int var3=10) Este encabezado es inválido porque no se pueden poner parámetros sin valores en medio de parámetros con valores por defecto. En este caso var2 no tiene valor pero var1 y var3 si.



Películas DVD y base de datos DVD

DVD son las siglas para “digital versatile disk” o “digital video disk” que en español significa disco versátil digital o disco de video digital. Este es un formato de disco óptico para almacenamiento digital inventado por Philips, Sony, Toshiba, y Panasonic en 1995. Los DVD ofrecen una capacidad de almacenamiento mayor que los discos compactos (CD), pero tienen las mismas dimensiones. Los DVD pueden ser utilizados para almacenar cualquier dato digital, pero son famosos por su uso en la distribución de películas.



¿Cuál de las siguentes funciones sobrecargadas será invocada si proveemos la instrucción ejemplo(42, 'a')? int ejemplo(int) ; int ejemplo(int, int) ; int ejemplo(char, int) ; int ejemplo(int, char) ; ninguna de las anteriores Los argumentos provistos son de tipo entero y char (en ese orden), por lo tanto utiliza la versión int ejemplo(int, char);.

Para una función con encabezado int foo01(int a, int b, int c = 5). ¿Sería válida la siguiente invocación? cout << foo01(1, 2) << endl; Si No Hace falta más información. Si, la invocación es válida pues la función foo01 puede aceptar que se le pasen solo los primeros dos argumentos ya que el último argumento tiene un valor por defecto.

¿Cuál será el valor de arg01 luego que se ejecuta la línea 19?

4 3 ninguno; el void lo borra Como arg01 es pasado por valor, su valor no puede ser modificado por las instrucciones de la función ejercicio. Por lo tanto su valor final es 4.

¿Cuál será el valor de arg02 luego que se ejecuta la línea 19?

5 2 ninguno; como la función ejercicio es de tipo "void" la variable no tendrá valor Como arg02 es pasado por referencia, cualquier asignación que se le haga a su parámetro correspondiente (var02) es también una asignación a arg02. Al final de la función ejercicio se le asigna 2 a var02. Por lo tanto, el valor de arg02 luego de la invocación en la línea 19 es 2.



Sesión de laboratorio:

En esta sesión de laboratorio vamos a utilizar una base de datos de películas DVD mantenida por http://www.hometheaterinfo.com/dvdlist.htm. Esta base de datos contiene 44MB de información de películas que han sido distribuidas en DVD. Algunos de los campos de esta base de datos son: título del DVD, estudio de publicación, fecha de publicación, tipo de sonido, versiones, precio, clasificación, año y género. Los campos de cada película están almacenados en un archivo de texto usando el siguiente formato:

DVD_Title|Studio|Released|Status|Sound|Versions|Price|Rating|Year|Genre|Aspect|UPC|DVD_ReleaseDate|ID|Timestamp`

Por ejemplo,

Airplane! (Paramount/ Blu-ray/ Checkpoint)|Paramount||Discontinued|5.1 DTS-HD|
LBX, 16:9, BLU-RAY|21.99|PG|1980|Comedy|1.85:1|097361423524|2012-09-11 00:00:00|
230375|2013-01-01 00:00:00

Ejercicio 1 - Familiarizarte con las funciones definidas

El primer paso en esta experiencia de laboratorio es familiarizarte con las funciones que ya están definidas en el código. Tus tareas requerirán que imites lo que hacen estas funciones, así que es importante que entiendas cómo se invocan, declaran y definen.

Instrucciones

  1. Carga a QtCreator el proyecto DVDInfo. Hay dos maneras de hacer esto:

    • Utilizando la máquina virtual: Haz doble “click” en el archivo DVDInfo.pro que se encuentra en el directorio home\eip\labs\functions-dvdinfo de la máquina virtual.
    • Descargando la carpeta del proyecto de Bitbucket: Utiliza un terminal y escribe el comando git clone http://bitbucket.org/eip-uprrp/functions-dvdinfo para descargar la carpeta functions-dvdinfo de Bitbucket. En esa carpeta, haz doble “click” en el archivo DVDInfo.pro.
  2. Configura el proyecto. El archivo main.cpp tiene la invocación de las funciones que usarás en los siguientes ejercicios. En los archivos movie.h y movie.cpp se encuentra la declaración y definición de las funciones que vas a invocar.

  3. Haz doble "click" en el archivo movie.h que contiene los prototipos de las funciones de este proyecto. Ve a movie.h e identifica cuál o cuáles funciones son sobrecargadas y describe por qué.

    Estudia los prototipos de funciones contenidas en movie.h de modo que sepas la tarea que realizan y los tipos de datos que reciben y devuelven. Identifica los tipos de datos que recibe y devuelve cada una de las siguientes funciones:

    showMovie
    showMovies
    getMovieName
    getMovieByName

    En el archivo movie.cpp encontrarás las definiciones de las funciones. Nota que algunas versiones de la función showMovie usan el objeto llamado fields de clase QStringList. El propósito de ese objeto es poder acceder cada uno de los campos de información de la película usando un índice entre 0 y 14. Por ejemplo, fields[0] accede al título de la película, fields[1] accede el estudio, fields[8] al año, etc.


¿Cuáles de las siguientes funciones están sobrecargadas en movie.h? getMovieByName showMovies getMovieInfo La función showMovies está sobrecargada. Hay dos versiones de esa función.

Ejercicio 2 - Invocar y modificar funciones

En este ejercicio modificarás la función main y algunas de las funciones pre-definidas para que desplieguen información sobre una o más películas de la base de datos.

Instrucciones

  1. Observa la siguiente línea en main:

    filemanip file("dvd_csv.txt") ; 

    Su propósito es asociar el objeto llamado file con el archivo de datos dvd_csv.txt. Cuando estamos abriendo un archivo para leer sus datos en un programa, comúnmente es necesario especificar la ruta absoluta del archivo. De esa forma, el programa encontrará al archivo sin importar desde donde sea ejecutado.

    Averigua la ruta absoluta de dvd_csv.txt y copiala reemplazando el string "dvd_csv.txt". Por ejemplo, luego del remplazo la linea podría lucir así:

    filemanip file("/home/eip/functions-dvdinfo/dvd_csv.txt") ;

    Compila y corre el programa. Si obtienes un error como: Cannot open dvd_csv.txt! se debe a que has especificado mal la ruta del archivo. Corrije la ruta hasta que no obtengas errores.

  2. Realiza las siguientes implementaciones en la función main (archivo main.cpp):

    • Añade código para que despliegue en el terminal las películas en las posiciones 80 hasta la 100.
    • Añade código para que despliegue en el terminal solo las películas que contengan “forrest gump” en el título.
    • Añade código para que despliegue en el terminal solo la película en la posición 75125 usando composición de funciones y la función showMovie.
    • Añade código para que despliegue en el terminal el nombre y el rating de la película en la posición 75125.
  3. Modifica la función getMovieInfo que se encuentra en el archivo movie.cpp para que en adición a los parámetros que ya recibe también reciba por referencia el nombre de la película y le asigne un valor. Recuerda que también debes modificar el prototipo de esta función que se encuentra en movie.h.

  4. Para la película en la posición 75125, añade código a la función main para que, utilizando getMovieInfo, despliegue el nombre, el rating, el año y el género de la película en una sola línea. Ayuda: nota que la función getMovieInfo tiene parámetros por referencia.

Ejercicio 3 - Definir e implementar funciones

Las funciones cuyos prototipos están en movie.h están implementadas en el archivo movie.cpp. En este ejercicio vas a utilizar los archivos movie.h, movie.cpp, y main.cpp para definir e implementar funciones adicionales. Al implementar las funciones, recuerda utilizar buenas prácticas de programación y documentar tu programa.

Instrucciones

  1. Estudia las funciones que ya están implementadas en movie.cpp para que te sirvan de ejemplo para las funciones que vas a crear.

  2. Implementa una función llamada getMovieStudio que reciba una cadena de caracteres ("string") con la información de una película y devuelva el nombre del estudio de la película. Recuerda añadir el prototipo de la función en el archivo movie.h. Invoca la función getMovieStudio desde main() para desplegar el nombre y el estudio de la película en la posición 75125 y así demostrar su funcionamiento.

  3. Implementa una función sobrecargada getMovieInfo que devuelva el nombre del estudio además del nombre, rating, año y género. Invoca la función getMovieInfo desde main() para desplegar el nombre, estudio, rating, año y género de la película en la posición 75125 y así demostrar su funcionamiento.

  4. Implementa una función showMovieInLine que despliegue la información que despliega showMovie pero en una sola línea. La función debe tener un parámetro de modo que reciba el "string" de información de la película. Invoca la función showMovieInLine desde main() para desplegar la información de la película en la posición 75125 y así demostrar su funcionamiento.

  5. Implementa una función showMoviesInLine que despliegue la misma información que despliega showMovies (todas las películas en un rango de posiciones) pero en una sola línea por película. Por ejemplo, una invocación a la función sería showMoviesInLine(file, 148995, 149000);. Invoca la función showMoviesInLine desde main() para desplegar la información y así demostrar su funcionamiento.



Entregas

Utiliza "Entrega" en Moodle para entregar los archivos main.cpp, movie.cpp y movie.h con las invocaciones, cambios, implementaciones y declaraciones que hiciste en los ejercicios 2 y 3. Recuerda utilizar buenas prácticas de programación, incluye el nombre de los programadores y documenta tu programa.



Referencias

[1] http://mathbits.com/MathBits/CompSci/functions/UserDef.htm

[2] http://www.digimad.es/autoria-bluray-dvd-duplicado-cd-video.html

[3] http://www.soft32.com/blog/platforms/windows/keep-your-dvd-collection-up-to-date-with-emdb-erics-movie-database/

[4] http://www.hometheaterinfo.com/dvdlist.htm




results matching ""

    No results matching ""