Prácticas de C++ Practica Nº 6 Informática II Fundamentos de Programación Prof. Dr. Paul Bustamante Practica Nº6 Programación en C++ Pág. 1 ÍNDICE ÍNDICE ........................................................................................................................................ 1 1. Introducción...................................................................................................................... 1 1.1 Ejercicio 1: Clase Fecha............................................................................................. 1 1.2 Ejercicio 2: Clase Vector............................................................................................ 3 1.3 Ejercicio 3: Clase Fraccion, versión 1.1..................................................................... 3 1.4 Ejercicio 4: Clase Complejo, versión 1.1................................................................... 5 1.5 Ejercicio 5: Mi clase String, versión 1.1 .................................................................... 5 1. Introducción. En esta práctica trataremos de hacer un ejercicio de clases con algoritmos y nos introduciremos en la sobrecarga de operadores, un concepto nuevo visto esta semana en las clases de teoría. 1.1 Ejercicio 1: Clase Fecha Para empezar a hacer uso de la sobrecarga de operadores, vamos a crear una nueva clase Fecha que nos permita pedir de forma sencilla una fecha, imprimirla, comparar dos fechas y sumarles días a una fecha, lo cual haremos gracias a la sobrecarga de los operadores respectivos ( >>, <<, + y = =). A continuación se le dará el código de este ejercicio. Como ya se les ha dicho en reiteradas ocasiones, no se dedique sólo a escribir el código, debe tratar de entenderlo: #include <iostream.h> //fichero Fecha.h class Fecha { int dia,mes,ano; public: Fecha(int d=1, int m=1, int a=1900); Fecha( Fecha &f); }; friend ostream &operator<<(ostream &co, Fecha &f); friend istream &operator>>(istream &ci, Fecha &f); friend bool operator==(Fecha &f1, Fecha &f2); Fecha operator+(int d); //fichero Fecha.cpp #include <iostream.h> #include <iomanip.h> #include “Fecha.h” Fecha::Fecha(int d, int m, int a) { dia=d; mes=m; ano=a; } Fecha::Fecha(Fecha &f) { dia = f.dia ; mes = f.mes; ano = f.ano; } Fecha Fecha::operator +(int dias) Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra Practica Nº6 Programación en C++ { Pág. 2 Fecha temp; temp.dia = dia + dias; temp.mes = mes + temp.dia/30; temp.dia = temp.dia % 30; temp.ano = ano + temp.mes/12; temp.mes = temp.mes % 12; return temp; } ostream &operator<<(ostream &co, Fecha &f) { cout << setfill('0') << setw(2) << f.dia << '/' << setw(2) << f.mes << '/' << setw(4) << f.ano; return co; } istream &operator>>(istream &ci, Fecha &f) { char ch; cout << "Escriba Fecha de la forma dd/mm/aa:"; ci >> f.dia >> ch >> f.mes >> ch >> f.ano; return ci; } bool operator==(Fecha &f1, Fecha &f2) { if (f1.dia==f2.dia && f1.mes==f2.mes && f1.ano==f2.ano) return true; else return false; } //fichero principal.cpp #include <iostream.h> #include “Fecha.h” void main() { Fecha f1(12,4,2001); //crear una fecha Fecha f2; //crear una fecha con valores por defecto cin >> f2; //pedir fecha 2 cout << "Fecha 1: " << f1 << endl; cout << "Fecha 2: " << f2 << endl; Fecha f3; f3 = f1 + 180; //sumar 180 dias cout << f1 <<" + 180 dias = " << f3 << endl; if (f3 == f2) cout << f3 << " y " << f2 << " son Fechas iguales"; else cout << f3 << " y " << f2 << " son Fechas diferentes"; } cout << " \nHe terminado.." << endl; Para el cálculo de la nueva fecha (cuando se suman los días), sólo se ha contemplado los meses de 30 días, con el fin de no emplear mucho tiempo en el algoritmo. Recuerde que debe crear 2 ficheros para la clase: Fecha.cpp y Fecha.h y un fichero para el programa principal Principal.cpp. Al proyecto puede asignarle el nombre de Ejer1. Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra Practica Nº6 Programación en C++ Pág. 3 1.2 Ejercicio 2: Clase Vector Este ejercicio consiste en hacer una clase Vector que permita crear vectores de una forma más intuitiva. En este ejercicio se hará el vector de enteros, pero se puede extender a cualquier tipo de vector. El código es el mismo que el que está en los apuntes de las transparencias de clases. Tiene una función miembro (Ordena) añadida que permitirá ordenar el vector de forma ascendente o descendente, según el argumento que se le pase. A continuación puede ver la definición de la clase, //vector.h class Vector { int *pV; int num; //numero de elementos public: Vector(int); ~Vector(); int& operator[](int index); void Ordena(bool ord); //true=asc. false=desc }; Y el código del programa principal: //principal.cpp void main() { int num; cout << "Num:"; cin >> num; Vector v(num); //crear vector for (int i=0;i<num;i++) cin >> v[i]; //imprimir vector cout << "El vector es:\n"; for (i=0;i<num;i++) cout << v[i] << endl; //ordenar char orden; cout << "Como lo quiere ordenar (A=asc D=desc):?"; cin >> orden; cout << "\nEl vector es ordenado es:\n"; if ( orden=='A' || orden=='a') v.Ordena(true); else v.Ordena(false); for (i=0;i<num;i++) cout << v[i] << endl; //asc cout << "Adios.."<<endl; } 1.3 Ejercicio 3: Clase Fraccion, versión 1.1 Para recordar, la clase Fraccion tiene dos variables miembro privadas (long num, den), para almacenar el numerador y denominador respectivamente. Debe crear un proyecto Ejer2 y los ficheros respectivos para la clase Fraccion, en los cuales va a escribir el código: 1. Debe crear una función miembro privada, llamada simplificar( ), que permita expresar la fracción en su forma más simplificada posible, manteniendo que tanto el Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra Practica Nº6 Programación en C++ Pág. 4 numerador como el denominador sean enteros. Por ejemplo, al simplificar la fracción 2/4 se debe obtener 1/2. La simplificación se basa en la división por el máximo común divisor del numerador y denominador. Para ello se puede seguir el algoritmo de Euclides presentado en las transparencias de clase de “Algoritmos de búsqueda y ordenación”. void Fraccion::simplificar() { long m, n, r; if (num<den) { m=den; n=num; } else { m=num; n=den; } while ((r=m%n) != 0) { m=n; n=r; } //n es el m.c.d num /= n; den /= n; //r=resto de m/n } Se trata de una función privada, lo que significa que sólo puede ser llamada desde las funciones miembro o funciones friend. Se pide utilizarla desde todas las funciones y operadores que modifiquen el valor del denominador o del numerador (incluidos los constructores). Esto significa que si por ejemplo inicializáramos a 4/8, el valor almacenado debería ser 1/2. 2. Trate de crear una serie de funciones friend que permitan pre/post-multiplicar y pre/post-dividir una fracción por un número entero (int). Los prototipos de estas funciones para las variables de tipo int son los siguientes: //Pre multiplicar y dividir: friend Fraccion operator* (int, const Fraccion&); friend Fraccion operator/ (int, const Fraccion&); //Post multiplicar y dividir: friend Fraccion operator* (const Fraccion&, int); friend Fraccion operator/ (const Fraccion&, int); 3. Sobrecargar el operador de extracción “>>” para poder pedir el valor de la fracción de la forma 2/6 directamente y que a su vez simplifique y guarde 1/3. También sobrecargar el operador de inserción “<<” para poder sacar directamente por consola los valores de las fracciones. 4. Finalmente, deben sobrecargar los operadores de suma y multiplicación para que permitan sumar y multiplicar dos fracciones, tal como se puede apreciar en el código de la función principal main. A continuación se da el código que debe ir en main(): void main() { Fraccion f1(1,4); Fraccion f2(1,2); Fraccion f3; cin >> f3; //pide datos para f3 Fraccion fr = f1 + f2; cout << f1 << " + " << f2 << " = " << fr << endl; Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra Practica Nº6 Programación en C++ Pág. 5 Fraccion fm = f1 * f2; cout << f1 << " * " << f2 << " = " << fm << endl; int k=4; fr = k * f1; //Pre-multip cout << k << " * "<<f1<<" = "<< fr << endl; fr = k / f3; //Pre-division cout << k << " / "<<f3<<" = "<< fr << endl; k=2; fr = cout fr = cout f2 << f3 << * k; //Post-multip f2 << " * "<<k<<" = "<< fr << endl; / k; //Post-division f3 << " / "<<k<<" = "<< fr << endl; Fraccion f4; cin >> f4; cout << f4; } 1.4 Ejercicio 4: Clase Complejo, versión 1.1 Este ejercicio consiste en sobrecargar todos los operadores que intervengan en el programa que se describe a continuación. Puede utilizar las versiones anteriores de la clase Complejo, dadas en clase o en la práctica anterior. Recuerde crear los ficheros y el proyecto correspondiente. //principal.cpp #include <iostream.h> void main() { Complejo c1(2.5,3),c2; cin >> c2; //pedir datos para c2 Complejo c3 = c1 + c2; // c1.operator+(c2) cout << c1 << " + " << c2 << " = " << c3 <<endl; c3 = c1 * c2; cout << c1 << " * " << c2 << " = " << c3 <<endl; c1==c2? cout << c1 << " y " << c2 << " son Iguales\n": cout << c1 << " y " << c2 << " son Diferentes\n"; if ( c1 > c2 ) cout << c1 << " es > que " << c2; else cout << c1 << " es < que " << c2; cout << "\nHe terminado.." << endl; } 1.5 Ejercicio 5: Mi clase String, versión 1.1 En este ejercicio vamos a continuar con la clase String, la cual permite utilizar de manera más intuitiva las cadenas, como pudo apreciarlo en la práctica anterior. Ahora sólo se dará la definición de la clase y el código de la función principal main, desde dónde se crean los objetos de la clase String. El resto debe tratar de implementarlo Ud. solo. Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra Practica Nº6 Programación en C++ Pág. 6 //String.h class String { char *str; public: String(); String(char *t); ~String(){ //cadena delete [] str; } //destructor friend istream &operator>>(istream &ci, String &n); friend ostream &operator<<(ostream &co, String &n); char operator[](int i); bool operator==(char*t); void operator=(char *t); //sobrecarga int GetLen(){ return strlen(str); } }; Se deben sobrecargar los siguientes operadores: • De inserción << y de extracción >> para poder pedir el texto e imprimirlo. • Operador = = para comparar con una cadena de texto. • El operador [ ] para poder acceder directamente a un elemento de la cadena. //main.cpp void main() { String name; cout << "Escriba un texto:"; cin >> name; cout << "El texto es: " << name << endl; int len=name.GetLen(); cout << "La longitud del texto es: " << len << endl; cout << "Ahora al reves:"; for (int i=len-1; i>=0;i--) cout << name[i]; cout << "\nEscriba SI o NO:"; cin >> name; if (name == "SI"){ cout << "Ha elegido SI" << endl; }else{ cout << "Ha elegido NO" << endl; } } Compile el proyecto y ejecútelo, observando el resultado. Escuela Superior de Ingenieros – Tecnun – Universidad de Navarra