Funciones en C++

Anuncio
Calculando la nota final usando
funciones
Funciones en C++
Programación Orientada a Objeto
Ing. Civil en Telecomunicaciones
Calculando la mediana usando
funciones
• Se desea convertir el cálculo de la
mediana en una función
double mediana(vector<double> v)
{
typedef vector<double>::size_type vec_size;
vec_size size = v.size();
if (size == 0)
throw domain_error(“Mediana de un vector vacio”);
sort(v.begin(), v.end());
vec_size mid = size/2;
return (size%2 == 0) ? (v[mid] + v[mid – 1])/2 : v[mid];
• Se desea convertir el cálculo de la
nota final en una función
double nota(double ex1, double ex2, double
tareas)
{
return 0.2*ex1 + 0.4*ex2 + 0.4*tareas;
}
• La función se invoca como
cout << "Su nota final es " << nota(examen1,
examen2, suma/contador) << endl;
Calculando la mediana usando
funciones
• Función mediana() recibe una copia del
vector dado como argumento
Copia del vector original es modificado por la
función sort()
• Variables size y mid son locales a la función
Variable mediana ya no es necesaria
• Si el vector está vacío, la función genera una
excepción de tipo domain_error
}
Excepción recibe un string como argumento
Calculando la mediana usando
funciones
Calculando la nota final usando
funciones
• Función nota() anterior supone que se
conoce la suma de las tareas
• Cómo hacer una función nota() que reciba
las tareas y calcule la mediana?
No sabemos el número de tareas a priori
• Se desea convertir el cálculo de la nota final
en una función
double nota(double ex1, double ex2, const
vector<double>& vec_tareas){
if (vec_tareas.size() == 0)
throw domain_error(“Estudiante no tiene
notas de tareas”);
Pasar un vector con las notas
Llamar a la función mediana() anterior
© 2015 Mario Medina C.
return nota(ex1, ex2, mediana(vec_tareas));
}
1
Sobrecarga de funciones
Verificación del tamaño del vector
• Hemos definido dos funciones nota()
• Función mediana() ya verifica si el
tamaño del vector es 0
double
nota(double ex1, double ex2, double
tareas)
double nota(double ex1, double ex2, const
vector<double>& vec_tareas)
• Cómo sabe el compilador cuál función
usar?
Por el número y tipo de los argumentos
Imprime mensaje “Mediana
de un
vector vacío”
• Función nota() verifica el tamaño del
vector de nuevo
Imprime mensaje “Estudiante
no tiene
notas de tareas”
Mensaje es más útil al usuario
Referencias a un vector
Referencias const a un vector
• Función tiene argumento const
vector<double>& vec_tareas
• Sea vector<double> v1;
Esta es una referencia a un vector
const
de tipo double
• Referencia es un alias para un objeto
vector<double> notas;
vector<double>& n = notas;
• No es un puntero!
• n es un sinónimo ó un alias para notas
Leyendo las tareas usando funciones
• Queremos leer las notas de las tareas
desde el flujo de entrada en una función
Función debe recibir el flujo de entrada
como argumento
Función debe retornar el flujo de entrada
istream& leeNotas(istream& in, vector<double>&
notas) {
// . . . . .
return in;
}
© 2015 Mario Medina C.
const
vector<double>& v2 = v1 es
una referencia const a v1
No es posible cambiar v1 a través de v2
const
vector<double>& v3 = v2
también es una referencia const a v1
Las referencias no se anidan
vector<double>&
v4 = v3 es un error
No es posible crear referencia no-const a un
objeto o referencia const
Función de lectura de notas
• Argumento in es referencia no-const
Indica que flujo de entrada in será modificado
• Argumento notas es referencia no-const
Indica que vector notas será modificado
• Función debe leer notas desde el flujo y
agregarlas al vector
Lectura termina con error o End-Of-File
• Función retorna flujo “limpio”
Limpia el posible estado de error
2
Calcula mediana con funciones (I)
Función de lectura de notas
#include
#include
#include
#include
#include
#include
• Retorna las notas en vector notas
istream& leeNotas(istream& in, vector<double>&
notas) {
if (in) {
notas.clear(); // Limpia el vector
double temp;
while (in >> temp) {
notas.push_back(temp);
}
// Limpia posible estado de error
in.clear();
}
return in;
}
using namespace std;
Calcula mediana con funciones (III)
// Funcion que calcula nota usando dos enteros y un vector
double nota(double ex1, double ex2, const vector<double>&
vec_tareas) {
if (vec_tareas.size() == 0)
throw domain_error("Estudiante no tiene notas de
tareas");
return nota(ex1, ex2, mediana(vec_tareas));
}
istream& leeNotas(istream& in, vector<double>& notas) {
if (in) {
notas.clear();
// Limpia el vector
double temp;
while (in >> temp)
notas.push_back(temp);
in.clear(); // Limpia posible estado de error
}
return in;
}
Calcula mediana con funciones (IV)
int main() {
// Solicita el nombre del alumno
cout << "Ingrese su nombre: ";
string nombre;
cin >> nombre;
cout << "Hola, " << nombre << "!" << endl;
Calcula mediana con funciones (IV)
// Lee las notas desde la entrada estandar
leeNotas(cin, notas);
// Calcula la nota final
try {
double nota_final = nota(examen1, examen2, notas);
streamsize prec = cout.precision();
cout << "Su nota final es " << fixed
<< setprecision(3) << nota_final
<< setprecision(prec) << endl;
} catch(domain_error) {
cout << "Ingrese sus notas. Intente de nuevo" << endl;
return 1;
}
return 0;
// Solicita las notas de los examenes
cout << "Ingrese las notas de sus examenes: ";
double examen1, examen2;
cin >> examen1 >> examen2;
// Solicita las notas de las tareas
cout << "Ingrese las notas de sus tareas, terminando con
^D: ";
// Vector de notas
vector<double> notas;
© 2015 Mario Medina C.
// Usamos biblioteca estándar
// Funcion notas que recibe 3 doubles
double nota(double ex1, double ex2, double tareas)
{
return 0.2*ex1 + 0.4*ex2 + 0.4*tareas;
}
Calcula mediana con funciones (II)
// Funcion que calcula mediana de un vector
double mediana(vector<double> v)
{
typedef vector<double>::size_type vec_size;
vec_size size = v.size();
if (size == 0)
{
throw domain_error("Mediana de un vector vacio");
}
sort(v.begin(), v.end());
vec_size mid = size/2;
return (size%2 == 0) ? (v[mid] + v[mid - 1])/2 : v[mid];
}
<algorithm>
<iomanip>
<iostream>
<stdexcept>
<string>
<vector>
}
3
Cálculo de notas desde archivo
Estructura de datos por alumno
• Supongamos ahora que queremos calcular
las notas finales de un grupo de estudiantes
e imprimir un listado ordenado por nombre
• Datos para cada estudiante ingresados por
teclado según el siguiente formato
• Almacenaremos la información de cada
alumno en una estructura de datos
Bonini 4.5 5.6 3.2 3.9 6.7 4.5
Vergara 6.6 4.5 7.0 7.0 3.0 6.7
Solabarrieta 3.4 2.6 4.6 6.1 5.2 5.0
Pasos a seguir
• Para resolver el problema, los pasos a
seguir son
Leer los datos de los alumnos a estructuras
InfoAlumno
Calcular la nota de cada alumno en base a la
información de la estructura
Generar una lista ordenada a partir de un
vector de estructuras InfoAlumno
Cálculo de la nota
• Invoca a función notas() anterior
const a una estructura
InfoAlumno como argumento
Evita la copia de la estructura
Recibe una referencia
double nota(const InfoAlumno& s)
{
return nota(s.examen1, s.examen2, s.notas);
}
Esto es igual a lenguaje
C
struct InfoAlumno {
string nombre;
double examen1, examen2;
vector<double> notas;
};
Lectura de los datos de los alumnos
• Similar a función leeNotas() anterior
Recibe un flujo de entrada de argumento y lo
retorna después de extraer los datos
istream& leeAlumnos(istream& in, InfoAlumno& s)
{
in >> s.nombre >> s.examen1 >> s.examen2;
leeNotas(in, s.notas);
return in;
}
Ordenando un vector de estructuras
InfoAlumno
• Usar función sort() de biblioteca de
algoritmos de C++
Si datos de alumnos se almacenan
en
vector<InfoAlumnos> alumnos, usar
sort(alumnos.begin(), alumnos.end());
• Error!
Función sort no sabe cómo comparar
estructuras InfoAlumno
© 2015 Mario Medina C.
4
Ordenando un vector de estructuras
InfoAlumno
• Necesario definir una función de comparación para
estructuras InfoAlumno
Esta función debe recibir dos estructuras InfoAlumno y
retornar una variable booleana
Usa comparación alfabética de objetos string
bool compara(const InfoAlumno& x, const
InfoAlumno& y){
return x.nombre < y.nombre;
}
Ordenar usando
Compilación separada
• Archivo fuente ha crecido bastante
Compilador C++ soporta compilación
separada de archivos fuente
• Dividiremos el archivo fuente en varios
archivos
Archivos de encabezado
(.h)
Archivos de código (.cpp)
sort(alumnos.begin(), alumnos.end(), compara);
• Comencemos con la mediana
Archivo mediana.cpp
Archivo mediana.h
#include <algorithm>
#include <stdexcept>
#include <vector>
// Necesario para sort()
// Necesario para domain_error
// Necesario para vector
using namespace std;
// Funcion que calcula mediana de un vector
double mediana(vector<double> v) {
typedef vector<double>::size_type vec_size;
vec_size size = v.size();
if (size == 0) {
throw domain_error("Mediana de un vector vacio");
}
sort(v.begin(), v.end());
vec_size mid = size/2;
return (size%2 == 0) ? (v[mid] + v[mid - 1])/2 : v[mid];
}
Archivos .cpp y .h
• Archivos de código contienen las
definiciones de las funciones
Contienen directivas #include y using
• Archivos de encabezado contienen las
declaraciones de las funciones
No deben incluir directivas using
Incluir directivas del preprocesador para
evitar inclusiones múltiples
Directivas #ifndef, #define, #endif
© 2015 Mario Medina C.
• Primeras líneas y última línea impiden inclusión
multiple de archivo de encabezado
• No es necesario incluir nombres de variables en
las declaraciones de funciones
#ifndef _mediana_h_
#define _mediana_h_
#include <vector>
double mediana(std::vector<double>);
#endif
Archivo infoAlumno.h
#ifndef _info_Alumno_h_
#define _info_Alumno_h_
#include <iostream>
#include <string>
#include <vector>
// Estructura de datos por alumno
struct InfoAlumno {
std::string nombre;
double examen1, examen2;
std::vector<double> notas;
};
std::istream& leeAlumnos(std::istream&, InfoAlumno&);
bool compara(const InfoAlumno&, const InfoAlumno&);
std::istream& leeNotas(std::istream& in,
std::vector<double>& notas);
#endif
5
Archivo infoAlumno.cpp
#include "infoAlumno.h"
using std::istream;
using std::vector;
// Funcion que lee las notas del istream in
istream& leeNotas(istream& in, vector<double>& notas) {
// Definicion de la funcion
}
// Funcion que lee los datos de los alumnos
istream& leeAlumnos(istream& in, InfoAlumno& s) {
// Definicion de la funcion
}
// Funcion que compara dos estructuras Info_Alumno
bool compara(const InfoAlumno& x, const InfoAlumno& y) {
// Definicion de la funcion
}
Archivo nota.h
#ifndef _notas_h_
#define _notas_h_
#include <vector>
#include "infoAlumno.h"
double nota(double, double, double);
double nota(double, double, const std::vector<double>&);
double nota(const InfoAlumno&);
#endif
Archivo nota.cpp
// Archivos de encabezado del sistema
#include <stdexcept>
#include <vector>
// Archivos de encabezado del proyecto
#include "notas.h"
#include "mediana.h"
#include "infoAlumno.h"
using std::domain_error;
using std::vector;
// Aqui va la definicion de las funciones ya vistas
// en clases anteriores
.
.
.
© 2015 Mario Medina C.
6
Descargar