![]() |
Índex |
Miguel A. Almarza
Departament d'Informàtica IES Mare de Deu de la Merce |
int i=3, j=5; Canvia(i,j); |
float x1=3.2, y1=8.1; Canvia(x1,y1); |
Funció genèrica Canvia. Rep dades d'un tipus indeterminats. |
Funció genèrica Menor Rep i torna dades d'un tipus indeterminats. |
#include <iostream.h> template <class tipus> Canvia(tipus &x, tipus &y) { tipus z; z = x; x = y; y = z; } main() { int i=3, j=5; Canvia(i,j); cout << "i=" << i << endl; cout << "j=" << j << endl; float x1=3.2, y1=8.1; Canvia(x1,y1); cout << "x1=" << x1 << endl; cout << "y1=" << y1 << endl; } |
#include <iostream.h> template <class Tipus> Tipus Menor(Tipus x, Tipus y) { return (x < y ? x : y); } main() { cout << Menor(3,1) << endl; cout << Menor(3.23,18.1) << endl; } |
Funció genèrica Canvia. Aplicada a objectes de tipus Complex. |
Funció genèrica Suma. Rep dos tipus de dades indetermitats. |
class Complex { float a,b; public: ............................... }; template <class tipus> Canvia(tipus &x, tipus &y) { tipus z; z = x; x = y; y = z; } main() { clrscr(); Complex z1(2,2), z2(3,5); Canvia(z1,z2); cout << "z1=" << z1 << endl; cout << "z2=" << z2 << endl; } | #include <iostream.h> template <class Tipus1, class Tipus2> Tipus2 Suma(Tipus1 x, Tipus2 y) { return x + y; } main() { int i=5, j=8; cout << Suma(i,j) << endl; int x=5; float y=13.45; cout << Suma(x,y) << endl; } |
Classe genèrica vector. | 1.-Vector de nombres enters. |
#include <iostream.h> template <class TipusDades> class Vector { TipusDades * V; int Longitud; public: Vector(int n) { V = new TipusDades[n]; Longitud = n; } ~Vector() { delete V;}; TipusDades & operator[](int i) { if (i >= 0 && i < Longitud) return V[i]; } }; | main() { Vector<int> v1(10); int i; for (i=0;i<10;i++) v1[i]=i; for (i=0;i<10;i++) cout << v1[i] << " "; cout << endl; } |
2.Vector d'estructures. | |
main() { struct Fitxa { char Nom[45]; char Telefon[15]; }; Vector<Fitxa> Agenda(10); cout << "Introdueix l'element 3 de l'agenda" << endl; cout << "Nom: "; cin >> Agenda[3].Nom; cout << "Telefon: "; cin >> Agenda[3].Telefon; cout << "Has posat a la posici¢ 3 del vector " << endl; cout << "Nom: " << Agenda[3].Nom << endl; cout << "Telefon: " << Agenda[3].Telefon << endl; } |
|
3.-Vector d'objectes Complex. | |
class Complex { float a,b; public: Complex(float a=0, float b=0) { this->a=a; this->b=b; } friend ostream &operator<<(ostream &flux, Complex z) { flux << z.a; flux.setf(ios::showpos); flux << z.b << 'i'; flux.unsetf(ios::showpos); return flux; } friend istream &operator>>(istream &flux, Complex &z) { cout << "Dades d'un complex" << endl; cout << "Introdueix la part real: "; flux >> z.a; cout << "Introdueix la part imagin…ria: "; flux >> z.b; return flux; } } main() { Vector<Complex> v1(10); int i; for (i=0;i<5;i++) { cout << "Element i = " << i << endl; cin >> v1[i]; } for (i=0;i<10;i++) cout << v1[i] << " "; cout << endl; } |
Una pila és una estructura de dades que simula una situació
real molt comú. Una pila de plats o una pila de cartes són
els exemples més comuns.
Una pila és una estructura de dades (Objecte en la terminologia de OOP) que es composa d'elements, anomenats nodes de la pila, del mateix tipus i que funciona de la següent manera:
| ![]() |
Classe NodoPila | |||||||||
template <class TipusDada> class NodoPila { TipusDada Informacio; NodoPila<TipusDada> * Seguent; public: NodoPila() {Seguent = NULL;} NodoPila(TipusDada V) { Informacio=V; Seguent = NULL; } NodoPila<TipusDada> * DonamSeguent() { return Seguent; } void PosaSeguent(NodoPila * p){Seguent = p;} void ObteInformacio(TipusDada &c) {c=Informacio;} void PosaInformacio(TipusDada c){Informacio=c;} }; | Ja hem comentat que les piles es fan de nodes. Un node és un element d'una classe que conté una informació i un punter que apunta a un altre node de la mateixa
classe. Si volem fer un node genèric hem de posar la informació del node com a tipus genèric de dades. Igual que abans aquest tipus podrà substituir-se en el moment de la compilació, quan declarem un node, per qualsevol tipus de dades vàlid en C++, des de ints i floats fins a estructures o objectes d'altres classes. | ||||||||
Classe Pila | |||||||||
template <class TipusDada> class Pila { NodoPila<TipusDada> *Principi; public: Pila(){Principi=NULL;} Boolean Push(TipusDada c); Boolean Pop(TipusDada &c); Boolean EstaBuida() { if (Principi==NULL) return CERT; else return FALS; } }; template <class TipusDada> Boolean Pila<TipusDada>::Push(TipusDada c) { NodoPila<TipusDada> *p; p=new NodoPila<TipusDada>; if (p) { p->PosaInformacio(c); p->PosaSeguent(Principi); Principi=p; return CERT; } else return FALS; } template <class TipusDada> Boolean Pila<TipusDada>::Pop(TipusDada &c) { if (Principi!=NULL) { NodoPila<TipusDada> * Auxiliar; Auxiliar=Principi; Principi->ObteInformacio(c); Principi = Principi->DonamSeguent(); delete Auxiliar; return CERT; } else return FALS; } |
La classe genèrica Pila té, com veiem, una única dada que és un punter a node, punter
que s'anomena Principi.
També veiem que té les funcions següents:
Nota: Al llarg d'aquest codi hem fet ús del fitxer BOOLEAN.H següent: #ifndef _BOOLEAN_ #define _BOOLEAN_ 1 typedef int Boolean; #define CERT 1 #define FALS 0 #endif |
Pila d'enters i pila de floats | |
#include <pila.h> main() { int A; Pila<int> MiPila; MiPila.Push(23); MiPila.Push(12); MiPila.Pop(A); cout << A << endl; MiPila.Pop(A); cout << A << endl; float B; Pila<float> TuPila; TuPila.Push(15.45); TuPila.Push(16.01); TuPila.Pop(B); cout << B << endl; TuPila.Pop(B); cout << B << endl; } | Segons veiem en el codi ara és molt senzill fer ús de piles en els nostres programes.
Hem declarat ara una pila de nombres enters anomenada MiPila. L'hem afegit dos nombres enters i després els hem obtingut i esborrat de la pila. Després hem declarat una pila de nombres reals (float) i hem fet ús de la mateixa manera que amb la de nombres enters, sense haver de pensar en l'estructura interna del codi de la classe pila. !!!! Quina meravella !!!! No hem de reprogramar les piles per a cada tipus de dades. |
Pila d'estructures | |
#include <pila.h> #include <string.h> typedef struct DadesPersonals { char Nom[45]; char Telefon[20]; }; main() { DadesPersonals Aux1, Aux2; Pila<DadesPersonals> MiPila; strcpy(Aux1.Nom,"Pep Palop Pelap"); strcpy(Aux1.Telefon,"931234567"); MiPila.Push(Aux1); MiPila.Pop(Aux2); cout << "Nom: " << Aux2.Nom << endl ; cout << "Telèfon: " << Aux2.Telefon << endl; } |
Pila de nombres complexos | |
#include <complex.h> #include <pila.h> main() { Complex z; Pila<Complex> MiPila; for(int i=1;i<5;i++) { cin >> z; MiPila.Push(z); } while (!MiPila.EstaBuida()) { MiPila.Pop(z); cout << z << endl; } } | Segons veiem, tenim la classe de nombre complexos ja feta al tema 6.
Només incloem els arxius de capçalera de les classes complex i pila i podem fer piles de complexos. |
Escriu la plantilla de la classe vector que ha de tenir les funcions següents:
Una cua és una estructura de dades (Objecte en la terminologia de OOP) que es composa d'elements del mateix tipus i podem dir que funciona de la següent manera:
Recorregut, Busca, InsereixDespres, InsereixAbans, EsborraElement, EsborraSeguent, EsborraLlista, VeurePrimerElement.
Com que aquestes llistes són piles haureu de fer una classe que hereti de la classe pila, i així només haureu de fer les noves funcions.
Hauràs de fer la classe amb les les funcions següents: InicialitzaLlista,
InsereixALaDreta, InsereixALaEsquerra, Busca, EsborraElement i ImprimeixNomsDreta
i ImprimeixNomsEsquerra.
Per recórrer una llista circular hem de mantenir un punter PunterAReg
que apunti a un element de la llista. Com que no té ni principi ni
fi haurem de convenir que acabarem el recorregut quan el PunterAReg torni
a estar en el lloc on va començar a moure's. Així si el punter
està apuntant a l'element Lola i el movem (Josep, Pep, Ramon,
...) haurem d'aturar el moviment quan arribem una altra vegada a Lola.
Hauràs de fer una classe amb les funcions següents: InicialitzaLlista,
InsereixALaDreta, Busca, EsborraElement i ImprimeixLlista.