programowanie w C++ dla OWK Programowanie w C++ z użyciem kontenerów - parę przykładów programów Opracowanie: dr hab. Mirosław R. Dudek, prof. UZ 1
Streszczenie W tym rozdziale podamy kilka najprostszych przykładów programów korzystających z kontenerów w C++. Przedsmak możliwości pakowania obiektów do kontenerów poznaliśmy w poprzednim rozdziale w przypadku zastosowania klasy string. Zawsze tam, gdzie chemy utworzyć tablicę obiektów a nie za bardzo wiemy ile tych obiektów będzie można skorzystać z pomocy klas kontenerowych, list, deque i vector. Kontenery realizowane są liniowo (obiekt układany jest za obiektem) i wybór rodzaju kontenera do którego chcemy wrzucać obiekty zależy od rodzaju problemu który implementujemy w naszym programie. Jeśli wykonywanie programu oznacza częste wkładanie nowego obiektu do wnętrza konteneru lub usuwanie go to najlepiej wybrać list ale jeśli najczęstszymi operacjami w naszym programie będzie tylko dostęp do któregoś obiektu wewnątrz kontenera (uruchomienie metod, zmiana wartości pól dla danego obiektu itp.) to najlepiej użyć kontener typu vector lub deque. We wszystkich przypadkach wkładanie obiektu do kontenera odbywa się w taki sam sposób poprzez funkcję push back(). Wybrane przykłady Na wstępie rozważmy program mrowki.cc który nie wymaga dłuższego tłumaczenia. Komentarze w źródle kodu powinny wystarczyć. W programie zadajemy liczbę mrówek N z klawiatury i pozwalamy im starzeć się. Wynik programu to dwie kolumny liczb kolejna jednostka czasu i liczba żywych mrówek w tej jednostce czasu. Ta wersja programu jest okrutna bo nie pozwalamy mrówkom reprodukować się. Czytelnik ma szansę uratować mrowisko i wprowadzić samodzielnie reguły przeżycia :) My natomiast będziemy koncentrować się wyłącznie na korzystaniu z kontenera vector. 1 #include <iostream> 2 #include <vector > // k l a s a kontenerowa 3 #include <c s t d l i b > 4 5 6 using namespace std ; 7 8 9 class mrowka{ 10 private : 11 int wiek ; // wiek mrowki 12 int DlugZycia ; // d l u g o s c z y c i a mrowki 13 14 public : 15 mrowka (){} 16 17 mrowka ( ) ; 18 19 void WpiszDlugoscZycia ( int a ){ DlugZycia=a ; } 20 void WpiszWiek ( int a ){ i f ( a>dlugzycia ) wiek=dlugzycia ; 21 else wiek=a ; } 22 void S t a r z e n i e ( ) { wiek+=1;} 23 int PodajWiek ( ) { return wiek ; } 24 25 26 } ; 27 28 typedef std : : vector <mrowka > armia ; // d e k l a r a c j a kontenera armia 29 30 2
31 int main ( ) { 32 33 armia mrowy ; // deklarujemy o b i e k t mrowy do k t o r e g o bedziemy 34 // dokladac o b i e k t y mrowka. 35 36 int N; 37 cout<<" Podaj liczbe mrowek"<<e n d l ; 38 cin>>n; 39 cout<<endl ; 40 int wiek,w; // b e d z i e losowy 41 int MaxDlugZycia =20; 42 // a l o k a c j a N mrowek w kontenerze mrowy 43 44 for ( int k=0; k<n; k++){ 45 mrowy. push back (new mrowka ) ; 46 } 47 48 // p o n i z e j mrowki otrzymuja wiek w sposob losowy 49 for ( int k=0; k<n; k++){ 50 mrowy [ k] >WpiszDlugoscZycia ( MaxDlugZycia ) ; 51 w=(int ) ( rand ()/(1.0+RAND MAX) 1 0. 0 + 0. 5 ) ; 52 mrowy [ k] >WpiszWiek (w) ; 53 } 54 55 int czas ; 56 cout<<" Podaj liczbe jednostek czsu ewolucji mrowek"<<e n d l ; 57 cout<<"t=" ; cin>>czas ; 58 cout<<endl ; 59 60 int Ntotal ; // c a l k o w i t a l i c z b a mrowek 61 62 for ( int t =0; t<czas ; t++){ 63 64 Ntotal =0; 65 for ( int k=0; k<n; k++){ 66 i f (mrowy [ k] >PodajWiek()<MaxDlugZycia ) Ntotal++; 67 } 68 i f ( Ntotal==0){ 69 cout<<" Wszystkie mrowy nie zyja"<<e n d l ; 70 e x i t ( 1 ) ; 71 } 72 73 cout<<t<<"\t"<<ntotal <<e n d l ; 74 75 for ( int k=0; k<n; k++){ 76 i f (mrowy [ k] >PodajWiek()<MaxDlugZycia ) mrowy [ k] > S t a r z e n i e ( ) ; 77 } 78 79 } 80 81 return 0 ; 82 } Napiszemy ta samą wersję programu trochę ładniej z użyciem funkcji. Kod programu stanie się czytelniejszy. 1 #include <iostream> 3
2 #include <vector > // k l a s a kontenerowa 3 #include <c s t d l i b > 4 5 6 using namespace std ; 7 8 9 class mrowka{ 10 private : 11 int wiek ; // wiek mrowki 12 int DlugZycia ; // d l u g o s c z y c i a mrowki 13 14 public : 15 mrowka (){} 16 17 mrowka ( ) ; 18 19 void WpiszDlugoscZycia ( int a ){ DlugZycia=a ; } 20 void WpiszWiek ( int a ){ i f ( a>dlugzycia ) wiek=dlugzycia ; 21 else wiek=a ; } 22 void S t a r z e n i e ( ) { wiek+=1;} 23 int PodajWiek ( ) { return wiek ; } 24 25 26 } ; 27 28 typedef std : : vector <mrowka > armia ; // d e k l a r a c j a kontenera armia 29 armia mrowy ; // deklarujemy o b i e k t mrowy do k t o r e g o bedziemy 30 // dokladac o b i e k t y mrowka. 31 32 33 void AlokujKontenery ( armia &Mrowy, int N, int MaxDlugZycia ){ 34 // a l o k a c j a N mrowek w kontenerze mrowy 35 36 37 for ( int k=0; k<n; k++){ 38 mrowy. push back (new mrowka ) ; 39 } 40 41 //mrowki otrzymuja wiek w sposob losowy 42 int wiek,w; // b e d z i e losowy 43 for ( int k=0; k<n; k++){ 44 mrowy [ k] >WpiszDlugoscZycia ( MaxDlugZycia ) ; 45 w=(int ) ( rand ()/(1.0+RAND MAX) MaxDlugZycia + 0.5); 46 mrowy [ k] >WpiszWiek (w) ; 47 } 48 49 } 50 51 int PoliczZyweMrowki ( armia &Mrowy, int N, int MaxDlugZycia ){ 52 int Ntotal =0; 53 for ( int k=0; k<n; k++){ 54 i f (mrowy [ k] >PodajWiek()<MaxDlugZycia ) Ntotal++; 55 } 56 return Ntotal ; 57 } 4
58 59 void DodajRokZycia ( armia &Mrowy, int N, int MaxDlugZycia ){ 60 for ( int k=0; k<n; k++){ 61 i f (mrowy [ k] >PodajWiek()<MaxDlugZycia ) mrowy [ k] > S t a r z e n i e ( ) ; 62 } 63 } 64 65 66 int main ( ) { 67 68 int N; 69 cout<<" Podaj liczbe mrowek"<<e n d l ; 70 cin>>n; 71 cout<<endl ; 72 73 int MaxDlugZycia =20; 74 75 76 AlokujKontenery (mrowy,n, MaxDlugZycia ) ; // zaalokowane z o s t a n i e N o b i e k t o t o w 77 //mrowka w kontenerze mrowy 78 79 80 81 int czas ; 82 cout<<" Podaj liczbe jednostek czsu ewolucji mrowek"<<e n d l ; 83 cout<<"t=" ; cin>>czas ; 84 cout<<endl ; 85 86 int Ntotal ; // c a l k o w i t a l i c z b a mrowek 87 88 for ( int t =0; t<czas ; t++){ 89 90 Ntotal=PoliczZyweMrowki (mrowy,n, MaxDlugZycia ) ; 91 92 i f ( Ntotal==0){ 93 cout<<" Wszystkie mrowy nie zyja"<<e n d l ; 94 e x i t ( 1 ) ; 95 } 96 97 cout<<t<<"\t"<<ntotal <<e n d l ; // wydruk na ekran 98 99 DodajRokZycia ( mrowy, N, MaxDlugZycia ) ; 100 } 101 102 return 0 ; 103 } W obu programach pojawiły sie pętle for które indeksowały obiekty w kontenerze. Jako indeksu można użyć również tzw. iteratora. Jest to narzędzie które pozwala iterować zawartość kontenera w trochę inny sposób. Zobaczmy to na działającym przykładzie. 1 #include <iostream> 2 #include <vector > // k l a s a kontenerowa 3 #include <c s t d l i b > 4 5 6 using namespace std ; 5
7 8 9 class mrowka{ 10 private : 11 int wiek ; // wiek mrowki 12 int DlugZycia ; // d l u g o s c z y c i a mrowki 13 14 public : 15 mrowka (){} 16 17 mrowka ( ) ; 18 19 void WpiszDlugoscZycia ( int a ){ DlugZycia=a ; } 20 void WpiszWiek ( int a ){ i f ( a>dlugzycia ) wiek=dlugzycia ; 21 else wiek=a ; } 22 void S t a r z e n i e ( ) { wiek+=1;} 23 int PodajWiek ( ) { return wiek ; } 24 25 26 } ; 27 28 29 30 typedef std : : vector <mrowka > armia ; // d e k l a r a c j a kontenera armia 31 armia mrowy ; // deklarujemy o b i e k t mrowy do k t o r e g o bedziemy 32 // dokladac o b i e k t y mrowka. 33 34 typedef armia : : i t e r a t o r Kolejny ; // d e k l a r a c j a o b i e k t u i t e r a t o r a 35 36 37 38 void AlokujKontenery ( armia &mrowy, int N, int MaxDlugZycia ){ 39 // a l o k a c j a N mrowek w kontenerze mrowy 40 41 42 for ( int k=0; k<n; k++){ 43 mrowy. push back (new mrowka ) ; 44 } 45 46 //mrowki otrzymuja wiek w sposob losowy 47 int wiek,w; // b e d z i e losowy 48 for ( int k=0; k<n; k++){ 49 mrowy [ k] >WpiszDlugoscZycia ( MaxDlugZycia ) ; 50 w=(int ) ( rand ()/(1.0+RAND MAX) MaxDlugZycia + 0.5); 51 mrowy [ k] >WpiszWiek (w) ; 52 } 53 54 } 55 56 int PoliczZyweMrowki ( armia &mrowy, int MaxDlugZycia ){ 57 int Ntotal =0; 58 // p o n i z e j mamy dostep do obiektow poprzez i t e r a t o r k 59 for ( Kolejny k=mrowy. begin ( ) ; k!=mrowy. end ( ) ; k++){ 60 i f ( ( k) >PodajWiek()<MaxDlugZycia ) Ntotal++; 61 } 62 return Ntotal ; 6
63 } 64 65 void DodajRokZycia ( armia &mrowy, int MaxDlugZycia ){ 66 for ( Kolejny k=mrowy. begin ( ) ; k!=mrowy. end ( ) ; k++){ 67 i f ( ( k) >PodajWiek()<MaxDlugZycia ) ( k) >S t a r z e n i e ( ) ; 68 } 69 } 70 71 72 int main ( ) { 73 74 int N; 75 cout<<" Podaj liczbe mrowek"<<e n d l ; 76 cin>>n; 77 cout<<endl ; 78 79 int MaxDlugZycia =20; 80 81 82 AlokujKontenery (mrowy,n, MaxDlugZycia ) ; // zaalokowane z o s t a n i e N o b i e k t o t o w 83 //mrowka w kontenerze mrowy 84 85 86 87 int czas ; 88 cout<<" Podaj liczbe jednostek czsu ewolucji mrowek"<<e n d l ; 89 cout<<"t=" ; cin>>czas ; 90 cout<<endl ; 91 92 int Ntotal ; // c a l k o w i t a l i c z b a mrowek 93 94 for ( int t =0; t<czas ; t++){ 95 96 Ntotal=PoliczZyweMrowki (mrowy, MaxDlugZycia ) ; 97 98 i f ( Ntotal==0){ 99 cout<<" Wszystkie mrowy nie zyja"<<e n d l ; 100 e x i t ( 1 ) ; 101 } 102 103 cout<<t<<"\t"<<ntotal <<e n d l ; // wydruk na ekran 104 105 DodajRokZycia ( mrowy, MaxDlugZycia ) ; 106 } 107 108 return 0 ; 109 } Miejsce w programie, gdzie użyty został iterator do przeglądania obiektów w kontenerze to dwie następujące funkcje. 1 2 3 int PoliczZyweMrowki ( armia &mrowy, int MaxDlugZycia ){ 4 int Ntotal =0; 5 // p o n i z e j mamy dostep do obiektow poprzez i t e r a t o r k 6 for ( Kolejny k=mrowy. begin ( ) ; k!=mrowy. end ( ) ; k++){ 7
7 i f ( ( k) >PodajWiek()<MaxDlugZycia ) Ntotal++; 8 } 9 return Ntotal ; 10 } 11 12 void DodajRokZycia ( armia &mrowy, int MaxDlugZycia ){ 13 for ( Kolejny k=mrowy. begin ( ) ; k!=mrowy. end ( ) ; k++){ 14 i f ( ( k) >PodajWiek()<MaxDlugZycia ) ( k) >S t a r z e n i e ( ) ; 15 } 16 } Tutaj ( k) oznacza wartość pod adresem k. Tutaj wartością jest obiekt mrowka. 8