370 likes | 483 Views
Strumienie wejścia/wyjścia. ios istream ostream ifstream iostream ofstream istrstream istringstrem ostrstream ostringstream fstream strstream streambuf filebuf stdiobuf strstrambuf stringmbuf. Klasa ios.
E N D
Strumienie wejścia/wyjścia • ios • istream ostream • ifstream iostream ofstream • istrstream istringstrem ostrstream ostringstream • fstream strstream • streambuf • filebuf stdiobuf • strstrambuf stringmbuf Programowanie C++
Klasa ios • class ios { • public: • typedef unsigned long fmtflags; // 32-bitowy łańcuch bitowy • typedef unsigned char iostate; // 8-bitowy łańcuch bitowy • protected: • streambuf* _strbuf; // wskaźnik do bufora • ostream* _tie; // wskaźnik do ostream dołączonego do istream • int _width; // szerokość pola wyjściowego • int _prec; // dokładność dla float • char _fill; // znak wypełnienia pustych pól • fmtflags _flags; // flagi formatowania • iostate _state; // aktualny stan io • ios(streambuf* _strbuf = 0, ostream* _tie = 0); X • ~ios(); • ... • }; _width _prec _fill _flags _state _strbuf _tie 15 9 ’#’ 03240 03 Programowanie C++
Flagi formatowania • class ios { • public: • enum { skipws = 01, // pomiń białe znaki (domyślne) • left = 02, // wyrównanie lewostronne • right = 04, // wyrównanie prawostronne (domyślne) • internal = 010, // wyrównanie lewo i prawostronne • dec = 020, // konwersja dziesiątkowa • oct = 040, // konwersja ósemkowa • hex = 0100, // konwersja szesnastkowa • showbase = 0200, // pokaż podstawę konwersji • showpoint = 0400, // pokaż kropkę dziesiętną • uppercase = 01000, // duże litery w zapisie liczb • showpos = 02000, // użyj + z liczbami dodatnimi • scientific = 04000, // użyj notacji naukowej dla float i double • fixed = 010000, // użyj notacji z kropką dziesiętną • unitbuf = 020000, // buforowanie... • stdio = 040000 }; // ...współpraca z stdio • ... • }; Programowanie C++
Selektory klasy ios • class ios { • public: • streambuf* rdbuf () const { return _strbuf ; } • ostream* tie () const { return _tie; } • int width () const { return _width; } • int precision () const { return _prec; } • char fill () const { return _fill; } • long flags () const { return _flags; } • int rdstate () const { return _state; } • ... • }; main () { cout<<"cout.width = "<< cout.width( ) <<endl; cout<<"cout.precision = " << cout.precision( )<<endl; cout<<"cout.fill = "<< cout.fill( )<<endl; cout<<"cin.flags = "<<cin.flags()<<endl; cout<<"cout.flags = "<<cout.flags()<<endl; } cout.width = 0 cout.precision = 6 cout.fill = cin.flags = 1 cout.flags = 200041 Programowanie C++
Modyfikatory klasy ios • class ios { • public: • int width (int w) { int t = _width; _width = w; return t; } • int precision (int p) {int t = _precision; _precision = t; return t; } • char fill (char c) { char t = _fill; _fill = c; return t; } • long flags (long f) { long t = _flags; _flags = f; return t; } • ... • }; main () { cout.fill('#'); cout.width(40); cout<<"Hello World"<<endl; cout<<"Hello World"<<endl; double pi =3.14159265358979323946; cout<<" pi = "<<pi<<endl; cout.precision(16); cout<<" pi = "<<pi<<endl; cout<<" pi = "<<pi<<endl; cout.precision(20); cout<<" pi = "<<pi<<endl; } ############################Hello World Hello World pi = 3.141593 pi = 3.1415926535897931 pi = 3.1415926535897931 pi = 3.1415926535897931599 Programowanie C++
Zmiana flag formatowania • main () • { • int n = 234; • long oldf = cout.flags(ios::hex | ios::uppercase); • cout<<n<<endl; • cout.flags(ios::hex | ios::showbase); • cout<<n<<endl; • cout.flags(oldf); • cout<<n<<endl; • } • class ios { • public: • long setf (long f) ; • long setf( long f, long mask); • long unsetf(long mask); • ... • }; EA 0xea 234 main () { int n = 234; long oldf = cout.setf (ios::hex | ios::uppercase); cout<<n<<endl; cout.setf (ios::hex | ios::showbase); cout<<n<<endl; cout.flags (oldf); cout<<n<<endl; } EA 0xEA 234 Programowanie C++
Maski flag formatu main () { int n = 234; cout.setf(ios::hex | ios::uppercase| ios::showbase); cout<<n<<endl; cout.setf(ios::oct | ios::basefield); cout<<n<<endl; } • class ios { • public: • const long basefield = dec | oct | hex; • const long adjustfield = left | rigth | internal; • const long floatfield = scientific | fixed; • ... • }; main () { char buffer[80]; cin.unsetf(ios::skipws); //czyści domyślneustawienie flagi cin>>buffer; cout<<"["<<buffer<<"]\n"; cin>>buffer; cout<<"["<<buffer<<"]\n"; cin>>buffer; cout<<"["<<buffer<<"]\n"; int n = 234; cout.setf(ios::hex | ios::uppercase| ios::showbase; cout<<n<<endl; cout.usetf( ios::basefield); cout<<n<<endl; } 0XEA 0352 Hello, World. [ ] [ Hello,] [ World.] 0XEA 234 Programowanie C++
Zmienne stanu klasy ios • class ios { • public: • enum { goodbit = 0, // wszystko ok • eofbit = 01, // koniec pliku • failbit = 02, // ostatnia operacja zakończona niepomyślnie • badbit = 04 }; // niewłaściwa operacja • ... • }; Dostępne selektory: good(), eof(), fail(), bad(), rdstate() main () { cout<<" cin.rdstate = "<<cin.rdstate()<<endl; int n; cin>>n; cout<<" cin.rdstate = "<<cin.rdstate()<<endl; } cin.rdstate = 0 22 cin.rdstate = 0 cin.rdstate = 0 ^Z cin.rdstate = 3 Programowanie C++
Operatory dla stanu ios • class ios { • public: • operator void* () const; //operator konwersji • int operator! () const; • void clear (int ); // modyfikator - ustawia nowe słowo stanu strumienia • ... • }; main () { int n, sum=0; cin>>n; while (cin) { // pętla będzie wykonywana tak długo dopóki _state ==0 sum+=n; cin>>n; } cout<<" suma częściowa wynosi "<<sum<<endl; cin.clear(); while (cin>>n) sum+=n; cout<<" suma całkowita wynosi "<<sum<<endl; } 40 90 20 ^Z suma częściowa wynosi 150 30 50 ^Z suma całkowita wynosi 230 Programowanie C++
Klasa istream • class istream : virtual public ios { // ...} zdefiniowanie ios jako wirtualnej klasy bazowej • ułatwia wielokrotne dziedziczenie, które • posiada klasa iostream • Strumień cin oraz operator >> klasy istream obsługują formatowane operacje wejścia. • Nieformatowane funkcje wejścia: • int get ( ); • istream& get ( char& c ); • istream& get ( char* buffer, int n, char delim = ’\n’ ); • istream& getline ( char* buffer, int n, char delim = ’\n’); • istream& ignore ( int n = 1, int delim = EOF); • int peek ( ); • istream& putback (char c); • istream& read ( char* buffer, int n); • istream& read ( unsigned char* buffer, int n); • int gcount ( ); Programowanie C++
Nieformatowane wejście Litwo! Ojczyzno moja Litwo!Ojczyzno moja Ty jesteś jak zdrowie... Ty jesteś jak zdrowie... ^Z • main () • { • char c; • while((c = cin.get() ) != EOF) • cout<<c; • cout<<endl; • } Litwo! Ojczyzno moja Litwo!Ojczyzno moja Ty jesteś jak zdrowie... Ty jesteś jak zdrowie... ^Z main () { char c; while(cin.get (c) ) cout<<c; cout<<endl; } main () { char buffer[80]; cin.get(buffer,8); cout<<buffer<<endl; cin.get(buffer, sizeof(buffer)); cout<<buffer<<endl; cin.get(buffer,sizeof(buffer),'.'); cout<<buffer<<endl; } Litwo! Ojczyzno moja Litwo! Ojczyzno moja Ty jesteś jak zdrowie... Ty jesteś jak zdrowie Programowanie C++
Nieformatowane wejście c.d. main () { char buffer[80]; cin.getline(buffer,8); cout<<buffer<<endl; cin.getline(buffer, sizeof(buffer)); cout<<buffer<<endl; cin.getline(buffer,sizeof(buffer),'.'); cout<<buffer<<endl; } Litwo! Ojczyzno moja Litwo! Ojczyzno moja Ty jesteś jak zdrowie... Ty jesteś jak zdrowie • main () • { • int month,year; • cout<<"Podaj datę (mm/dd/rrrr): "; • cin>>month; • cin.ignore(); // zjada '/' • cin.ignore(80,'/'); //zjada "dd/", lub "d/" lub "/" • cin>>year; • cout<<"Miesiąc = "<<month<<”, Rok = "<<year <<endl; • } Podaj datę (mm/dd/rrrr): 1/10/2000 Miesiąc = 1, Rok = 2000 Programowanie C++
Nieformatowane wejście c.d. main () { char buffer[80],c ; cout<<cin.peek( ) <<" , "<< cin.peek( ) <<" ,"; c = cin.peek( ); cout<<c<<", "; cin.get(buffer, 5); c = cin.peek( ); cout<<c <<" , "<< cin.peek( ) <<" , "<< cin.peek( ) <<endl; cin.putback('Z'); cin.putback('Y'); cin.get(buffer,5); cout<<buffer<<endl; } • main () • { • char buffer[] = "????????????????????"; • cin.read(buffer, 8); • cout<<buffer<<" read: "<<cin.gcount( ) <<endl; • cin.read(buffer, 4); • cout<<buffer<<" read: "<<cin.gcount( ) <<endl; • } ABCDEFG 65, 65, A, E, 69, 69 YZEF ABCDEFGHIJKLMN ABCDEFGH???????????? read: 8 IJKLEFGH???????????? read: 4 Programowanie C++
Klasa ostream • class ostream : virtual public ios { // ...} • Strumienie: cout // standardowe urządzenie wyjścia • cerr // standardowe urządzenie wyjścia dla komunikatów błędów (niebuforowany) • clog // jak wyżej, strumień buforowany • wraz z operatorem << obsługują formatowane wyjście. • Nieformatowane funkcje wyjścia: • int put ( char c ); • ostream& put ( char c ); • ostream& write ( const char* buffer, int n); • ostream& write ( const unsigned char* buffer, int n ); Programowanie C++
Nieformatowane wyjście • main () • { • char c ; • while(cin.get (c) ) • cout.put(c); • cout<<endl; • cout.put('H'). put('e'). put('l'). put('l'). put('o'). put('\n'); • cout.write("ABCDEFGHIJKLMNOPRSTUWXYZ",8); • cout<<endl; • cout.write("1234567890", 4); • cout<<endl; • } Litwo! Ojczyzno moja Litwo!Ojczyzno moja Ty jesteś jak zdrowie... Ty jesteś jak zdrowie... ^Z Hello ABCDEF 1234 Programowanie C++
Manipulatory strumieni • Najbardziej popularne manipulatory strumieni: Programowanie C++
Definiowanie manipulatorów • Manipulatory strumieni definiowane są zgodnie z następującymi prototypami: • - manipulatory bezparametrowe • ios& f( ios& ostr); • ostream& f( ostream& ostr ); • istream& f ( istream& istr); • - manipulatory z parametrem • ios& f( ios& ostr , int n ); • ostream& f( ostream& ostr , int n ); • istream& f ( istream& istr , int n ); ostream& beep(ostream& ostr) { return ostr<<„\a”; } main ( ) { cout<<beep; } Programowanie C++
Operacje wejścia/wyjścia na plikach • Otwarcia plików wejściowych i wyjściowych można dokonać za pomocą • konstruktorów lub funkcji open (mają takie same parametry): • void open ( char* name, int mode = ***, int prot = filebuf::openprot ); • Tryby otwarcia plików: Programowanie C++
Wskaźnik pozycji w pliku • Każdy plik posiada swój wskaźnik (albo do czytania, albo do pisania, albo dwa niezależne wskaźniki jeden do czytania a drugi do pisania). Wskaźniki te są typu streampos • streampos tellg( ); // funkcja klasy istream pokazuje jakie jest położenie wskaźnika do czytania • streampos tellp( ); // funkcja klasy ostream pokazuje położenie wskaźnika pisania • enum seek_dir // typ wyliczeniowy zdefiniowany w klasie ios określający punkt odniesienia • { beg, // początek • cur, // aktualna pozycja • end }; // koniec • istream& seekg (streampos, seek_dir = ios::beg); • ostream& seekp(streampos, seek_dir = ios::beg); • Plik w C++ może być otwarty jednocześnie do zapisu i oczytu. Korzystamy wówczas z klasy fstream: • fstream strum(„plik.txt”, ios::in | ios::out) Programowanie C++
Funkcje wirtualne main () { DatePolish today; DatePolish::SetFormat(DatePolish::TEXT); cout<<„\n Funkcja Write : „; today.Write(); cout<<„\n Funkcja Display ; „; today.Display; Date tomrrow(2000,1,11); tomorow.Display(); cout<<„\n Funkcja Display ; „; tomorow.Display(); ; } • class Date { • ... • virtual Write (ostream& output = cout) const • ... • }; Funkcja Write : 10 Styczeń 2000 Funkcja Display : 10 1 2000 Funkcja Display: 11 1 2000 Funkcja Write : 10 Styczeń 2000 Funkcja Display : 10 Styczeń 2000 Funkcja Display : 11 1 2000 Funkcje wirtualne gwarantują tzw. dynamiczne wiązanie czyli wywołanie funkcji jest odłożone do czasu realizacji programu i jest zależne od obiektu, na rzecz którego dana funkcja jest wywoływana. Programowanie C++
Polimorfizm • Polimorfizm - pozwala by obiekty różnych typów powodowały różne działanie w wywołaniu tej samej funkcji. Jest to możliwe dzięki temu, że wskaźnik do obiektu klasy bazowej może również pokazywać na obiekty klas pochodnych. • Aby uzyskać wiązanie dynamiczne parametry muszą być przekazywane przez wskaźnik bądź referencję • Słowo virtual pojawia się tylko w deklaracji funkcji w klasie podstawowej, nie musi pojawić w klasie pochodnej • Jeśli klasa bazowa deklaruje funkcję wirtualną to musi zawierać jej definicję nawet jeśli ciało funkcji jest puste • Klasa pochodna nie musi definiować ponownie funkcji wirtualnej, wówczas domyślnie wywoływana jest funkcja z klasy bazowej • Klasa pochodna we własnej definicji nie może zmieniać typu zwracanego przez funkcję wirtualną Programowanie C++
Wirtualne destruktory • Destruktory definiujemy jako funkcje wirtualne! class X { private: int* p; public: X() {p = new int[2]; cout<<” X(). ”;} ~X() { delete [] p; cout<<”~X (). \n”;} }; class Y: public X{ private: int* q; public: Y() {q = new int[100]; cout<<”Y() : Y::q = ”<<q<<”. ”;} ~Y() { delete [] q; cout<<”~Y() ”;} }; main ( ) { for (int i = 0; i<3; i++) { X* r = new Y; delete r; } X (). Y() : Y::q = 0x0d18. ~X(). X (). Y() : Y::q = 0x0de4. ~X(). X (). Y() : Y::q = 0x0eb0. ~X(). X (). Y() : Y::q = 0x0d24. ~Y() ~X(). X (). Y() : Y::q = 0x0d24. ~Y() ~X(). X (). Y() : Y::q = 0x0d24. ~Y() ~X(). virtual ~X() { delete [] p; cout<<”~X (). \n”;} Programowanie C++
Czyste funkcje wirtualne i klasy abstrakcyjne • Media Audio Book Periodical CD Tape Record Magazine Newspaper Journal class Media{ protected: String title; public: virtual void print( ) = 0; virtual char* id( ) = 0; }; class Book: public Media{ private: String author, publisher,isbn; public: void print ( ) { cout<<title<<" by "<<author;} void id ( ) { cout<<isbn; } }; Czysta funkcja wirtualna - funkcja nie mająca w swojej klasie implementacji. virtual void f( ) = 0; Abstrakcyjna klasa bazowa - klasa posiadająca jedną lub więcej czystych funkcji wirtualnych. Programowanie C++
Szablony funkcji • Szablon - abstrakcyjny przepis na tworzenie konkretnego kodu. • T jest parametrem szablonu • Szablon musi być zdefiniowany w zakresie globalnym. void swap( int& n, int& m) { int temp = n; n = m; m = temp; } void swap(Date& d1, Date& d2) { Date temp = d1; d1 = d2; d2 = temp; } template <class T> void swap(T& x, T& y) { T temp = x; x = y; y = temp; } main ( ) { int m = 22, n = 33; cout<<" m = "<<m<<" n = "<<n<<endl; swap(m,n); cout<<" m = "<<m<<" n = "<<n<<endl; Date d1,d2(1999,9,9); cout<<"d1 = "<<d1<<" d2 = "<<d2<<endl; swap(d1,d2); cout<<"d1 = "<<d1<<" d2 = "<<d2<<endl; } m = 22 n = 33 m = 33 n = 22 d1 = 2000 1 17 d2 = 1999 9 9 d1 = 1999 9 9 d2 = 2000 1 17 Programowanie C++
Szablony klas • Szablony klas działają jak szablony funkcji generując klasy. • template <class T,...> class X {...}; • Funkcje składowe szablonu klasy są szablonami funkcji o takim samym nagłówku • jak szablon klasy. template <class T, int n> class X{}; main( ) { X <float, 22> x1; //O.K. const int n = 44; X<char, n> x2; //O.K. int m = 66; X <short, m> x3; //ERROR } template <class T> class X { T square (T t) { return t*t; } }; template <class T> T square (T t) { return t*t; } Programowanie C++
Szablon klasy stos • template <class T> • class Stack { • private: • int size; • int top; • T* data; • public: • Stack( int s = 100): size(s); top = -1; { data = new T[size]; } • ~Stack( ) {delete [ ] data}; • void push (const T& x) {data[++top] = x; } • T pop() { return data[top--];} • int isEmpty( ) const {return top = = -1;} • int isFull( ) const { return top = = size - 1; } • }; main ( ) { Stack<int> stosint(5); Stack<Data> stosdata(10); Data x, y(2000,1,17); stosint.push(13); stosint.push(2); stosdata.push(x); stosdata.push(y); cout<<stosint.pop( )<<„ „<<stosint.pop( )<<endl; stosdata.pop( ).Display( ); } 2 13 2000 1 17 Programowanie C++
Pojemniki • Pojemnik to obiekt, który zawiera inne obiekty (np.tablica, stos). • Klasa pojemnikowa (klasa - pojemnik) to klasa, której obiekty są pojemnikami. • Pojemnik zwany jest homogenicznym jeśli wszystkie jego obiekty są tego samego • typu lub heterogenicznym w przeciwnym przypadku. template <class T> class Vector{ protected: T* data; unsigned size; void copy(const Vector<T>&); public: Vector (unsigned n = 10) : size(n), data( new T[size]) { } Vector ( const Vector<T>& other) : size(other.size), data( new T[size]) { copy(other); } ~Vector {delete [ ] data;} Vector<T>& operator = (const Vector<T>&); T& operator [ ] (unsigned i) const {return data[ i ];} usigned Size( ) const {return size;} }; Programowanie C++
Definicja funkcji składowych • template <classT> • Vector<T>& Vector<T>::operator = (const Vector<T>& other) • { • size = other.size; • data = new T[size]; • copy( other); • return this*; • } • template <class T> • void Vector<T>::copy( const Vector<T>& other) • { • unsigned min_size = (size < other.size ? size : other.size); • for (int i =0; i<min_size; i++) • data[i] = other.data[i]; • } Vector<short> v; v[5] = 34; Vector<short> w = v, x(3); cout<<w.size( ); Programowanie C++
Dziedziczenie szablonów • Dziedziczenie szablonów klas działa tak samo jak dziedziczenie zwykłych klas. template <class T> class Array : public Vector<T>{ protected: int i0; public: Array(int i, int j): i0(i), Vector<T>(j-i+1) { } Array(const Array<T>& other): i0(other.i0), Vector<T>(other) { } T& operator [ ] (int i) const { return Vector<T>::operator [ ] (i-i0); } int firstSubscript( ) const { return i0;} int lastSubscript ( ) const { return i0+size - j; } }; #include<iostream.h> #include "Array.h" main ( ) { Array<float> x(1,3); x[1] = 2.22; x[2] = 3.33; x[3] = 4.44; cout<"x.Size( ) = "<<x.Size( )<<endl; cout<<x.fistSubscript( )<<".."<<lastSubscript( )<<endl; for (int i = 1, i<=3, i++) cout<<"x["<<i<<"] = "<<x[i]<<endl; } x.Size( ) = 3 1..3 x[1] = 2.22 x[2] = 3.33 x[3] = 4.44 Programowanie C++
Szablony jako parametry szablonów • Ponieważ szablony klas pracują jak zwykłe klasy to można je przekazywać jako • parametry innych szablonów. Stack <Vector<int> > a; template <class T > class Matrix{ protected: Vector<Vector<T>*> row; public: Matrix( unsigned r =1, unsigned c=1) : row { for (int i=0; i<r; i++) row[i] = new Vector<T> (c); } ~Matrix () { for (int i = 0; i<row.size(); i++) delete row[i]; } Vector<T>& operator [ ](unsigned i) const { return *row[i]; } unsigned rows() { return row.size( ) } unsigned columns () { return row[0] -> size( ); } }; main ( ) { Matrix<float> a(2,3); a[0][0] = 0.0; a[0][1] = 0.1; a[0][2] = 0.2; a[1][0] = 1.0; a[1][1] = 1.1; a[1][2] = 1.2; cout<<"Macierz ma "<<a.rows( )<<" wiersze i " <<a.columns( ) <<" kolumny.\n"; for (int i=0; i<2; i++) { for (int j=0; j<3; j++) cout<<a[i][j]<<" "; cout<<endl; } } Macierz ma 2 wiersze i 3 kolumny 0.0 0.1 0.2 1.0 1.1 1.2 Programowanie C++
Szablon klasy dla list jednokierunkowych • Listy - struktury pozwalające na dynamiczną alokację pamięci, tworzone jako połączony ciąg węzłów, z których każdy zawiera dane składowe oraz wskaźnik do następnego węzła. data 12 t template <class T> class ListNode { friend class List<T>; protected: T data; ListNode* next; public: ListNode(T& t, ListNode<T>* p): data(t), next(p) { } }; 12 p next int ListNode< int > template <class T> class List { protected: ListNode<T>* first; ListNode<T>* newNode( T& t, ListNode<T>* p) { ListNode<T>* q = new ListNode<T>(t,p); return q; } ... Programowanie C++
Funkcje składowe szablonu listy ... public : List ( ) : first(0) { } ~List ( ); void insert (T t); int remove (T& t); int isEmpty ( ) { return first == 0;} void print ( ); }; • Konstruktor domyślny ustawia wskaźnikfirstna 0 • Destruktor będzie likwidował całą listę: template <class T> List <T>::~List ( ) { ListNode<T>* temp; for (ListNode<T>* p = first; p; ) { temp = p; p = p->next; delete temp; } } Funkcja insert tworzy nowy węzeł i wstawia go na początek listy: template <class T> void List <T>::insert (T t) { ListNode<T>* p = newNode(t,first); first = p; } Programowanie C++
Listy c.d. #include <iostream.h> #include "List.h" main( ) { List<int> liczby; liczby.insert(0); liczby.insert(1); liczby.insert(2); liczby.insert(3); liczby.print( ); int x; liczby.remove(x); cout<<"Usunięto "<<x<<endl; liczby.print( ); } template <class T> int List <T>::remove ( T& t) { if (isEmpty()) return 0; t = first->data; ListNode<T>* p = first; first = first->next; delete p; return 1; } template <class T> void List <T>::print ( ) { for (ListNode<T>* p = first; p; p = p ->next) cout<<p -> data << "-> ”; cout<<”* \n”; } 3 -> 2 -> 1 -> 0 -> * Usunięto 2 2 -> 1 -> 0 -> * data 2 data next 1 next data 0 next Programowanie C++
Iteratory • Iterator - obiekt mający zdolność poruszania się po elementach pojemników; działający jak wskaźnik pokazujący w danym momencie jeden element należący do pojemnika. • Podstawowe operacje iteratora: • inicjalizacja iteratora na początkowej • pozycji pojemnika, • pobranie wartości danych znajdujących • się we wskazywanej pozycji , • zmiana wartości danych na określonej • pozycji, • określenie czy we wskazywanej przez • iterator pozycji znajduje się jakaś wartość, • przesunięcie do następnej pozycji pojemnika. // Iterator.h template <class T> class Iterator { public: virtual int reset( ) = 0; virtual T operator ( )( ) = 0; virtual void operator = (T t) = 0; virtual int operator ! ( ) = 0; virtual int operator ++( ) =0; }; Programowanie C++
Szablon iteratora dla szablonu klasy List // plik ListIter.h #include ”List.h” #include ”Iterator.h” template <class T> class ListIter: public Iterator<T> { protected: ListNode<T>* current; ListNode<T>* previous; List<T>& list; public: ListIter(List<T>& l):list(l) {reset( );} virtual void reset( ) {previous = NULL; current = list.first;} virtual T operator ( ) ( ) {return current->data;} virtual void operator = (T t) {current->data=t;} virtual int operator ! ( ) ; virtual int operator ++( ) ; void insert (T t); void preInsert(T t); void remove( ); }; template <class T> int ListIter<T>::operator ! ( ) { if (current==NULL) if (previous==NULL) current=list.first; else current=previous->next; return (current!=NULL); } if (!it)... template <class T> int ListIter<T>::operator ++ ( ) { if (current==NULL) if (previous==NULL) current=list.first; else current=previous->next; else { previous=current; current=current->next; } return (current!=NULL); } for (it.reset(); !it; it++)... Programowanie C++
#include "List.h" #include "ListIter.h" #include "Date.h" main( ) { List<Date> Daty; ListIter<Date> it(Daty); Date today; it.insert(today); today.Forth(); it++; it.insert(today); today.Back(); it++; it.insert(today); Daty.print(); Date my(1994,4,19); it.reset(); it++; it=my; it++; it.remove(); for (it.reset(); !it; it++) {Date temp=it(); temp.Forth(); it = temp; } Daty.print(); } template <class T> void ListIter<T>::insert(T t) { ListNode<T>* p=list.newNode(t,0); if (list.isEmpty( ) ) list.first=p; else { p->next= current->next; current->next=p; } } template <class T> void ListIter<T>:remove( ) { if (current==list.first) list.first = current->next; else previous->next= current->next; delete current; current = 0; } 2000 3 28 -> 2000 3 29 -> 2000 3 28 ->* 2000 3 29 -> 1994 4 20 ->* Programowanie C++
Przyjaciel Listy // List.h template <class T> class List { friend class ListIter<T>; //.... }; template <class T> class ListNode { friend class List<T>; friend class ListIter<T>; //.... }; • Lista może posiadać więcej niż jeden iterator: • Iteratory są od siebie niezależne. List<float> list; ListIter<float> it1(list), it2(list),it3(list); it1.insert(11.01); it1++; it1.insert(22.02); it1++; it1.insert(33.03); for (it2.reset(); !it2; it2++) it2=10*it2; it3=it1; Programowanie C++