Biblioteka obiektowa C++ klasa string

Transkrypt

Biblioteka obiektowa C++ klasa string
programowanie w C++ dla OWK
Biblioteka obiektowa C++ klasa string - 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
biblioteki obiektowej string w C++. Często programiści C++, którzy wcześniej przez długie lata programowali w języku C z przyzwyczajenia ograniczają się do klasy string.h rodem z
języka C (w programach C++ włącza się ją poprzez polecenie #include <cstring>) unikając biblioteki obiektowej. Niepotrzebnie. W poniższych przykładach skorzystamy dodatkowo
z klasy kontenerowej vector.
Wybrane przykłady
Na wstępie rozważmy program string1.cc który nie wymaga dłuższego tłumaczenia. Komentarze w źródle kodu powinny wystarczyć. Z kodu można zrozumieć w jaki sposób obiektom z klasy
string przypisać łańcuchy znakowe, jak dodawać do siebie obiekty klasy string. Przede wszystkim uderzająca jest prostota tych poleceń, są bardziej proste niż przy korzystaniu z pomocy
biblioteki cstring wymagającej dodatkowej wiedzy nt tablic typu znakowego.
1 #include <i o s t r e a m >
2 #include <s t r i n g > // b i b l o t e k a j e z y k a C++ n i e m y l i c z
3
// z b i b l i o t e k a lancuchow znakowych j e z y k a C
4 using namespace s t d ;
5
6 int main ( ) {
7
8
s t r i n g imie , nazwisko ; // d e k l a r a c j a o b i e k t o w z k l a s y s t r i n g
9
// sa p u s t e i c h d l u g o s c =0;
10
s t r i n g s ; // t e z p u s t a d e k l a r a c j a . Zeby z o b a c z y c d l u g o s c
11
// t a k i e g o l a n c u c h a k o r z y s t a m y z metody l e n g t h ( )
12
13
cout<<endl <<" uruchamiamy metode length (), tj. podaj dlugosc " ;
14
15
cout<<i m i e . l e n g t h ()<< e n d l ; // wydrukowana z o s t a n i e d l u g o s c l a n c u c h=0
16
// bo j e s t p u s t y
17
18
cout<<" Podaj swoje imie"<<e n d l ;
19
c i n >>i m i e ; // t u t a j z o s t a n i e o b i e k t o w i i m i e p r z y p i s a n a w a r t o s c
20
cout<<" Wpisales imie: "<<imie <<e n d l ;
21
22
cout<<" dlugosc lancucha imie="<<i m i e . l e n g t h ()<< e n d l ;
23
24
cout<<" Podaj swoje nazwisko "<<e n d l ;
25
26
27
28
29
c i n >>nazwisko ; // t u t a j z o s t a n i e o b i e k t o w i i m i e p r z y p i s a n a w a r t o s c
30
31
s=i m i e+nazwisko ; // o b i e k t y t y p u s t r i n g mozna dodawac
32
33 cout<<" ---------------------------------------------"<<e n d l ;
34
cout<<" Dzien dobry "<<s<<e n d l ;
35 cout<<" ---------------------------------------------"<<e n d l ;
36
37 // Nie w y g l a d a t o j e s z c z e d o b r z e d l a t e g o
38 // t e r a z wstawimy s p a c j e pomiedzy i m i e i n a z w i s k o i a na koncu dodamy b u z k e
39
2
40
41
42
43
44
45
46
s=i m i e + " " + nazwisko + " :)" ;
cout<<" Dzien dobry "<<s<<e n d l ;
return 0 ;
}
Łańcuchy możemy prównywać ze sobą analogicznie jak zmienne numeryczne. Świadczy o tym
poniższy przykład string2.cc.
1 #include <i o s t r e a m >
2 #include <s t r i n g >
3
4 using namespace s t d ;
5
6 int main ( ) {
7
8 cout<<" Porownujemy obiekty typu string "<<e n d l ;
9
10 s t r i n g wyraz1 , wyraz2 ;
11
12 cout<<" Wpisz dwa wyrazy : " ;
13
14 c i n >>wyraz1>>wyraz2 ;
15
16 i f ( wyraz1 != wyraz2 ) {
17
cout<<" Wyrazy nie sa te same"<<e n d l ;
18
i f ( wyraz1>wyraz2 ) cout<<wyraz1<<" jest wiekszy niz "<<wyraz2<<e n d l ;
19
e l s e cout<<wyraz1<<" jest mniejszy "<<wyraz2<<e n d l ;
20 }
21 e l s e cout<<wyraz1<<" = "<<wyraz2<<e n d l ;
22 return 0 ;
23 }
Rozważymy teraz trochę trudniejszy przykład, w którym pokażemy jak z wprowadzonego
łańcucha znakowego można wydrukować każdy znak niezależnie i jak podmienić grupę znaków
innymi znakami. W tym celu rozważmy program string3.cc.
1 #include <i o s t r e a m >
2 #include <s t r i n g >
3
4 using namespace s t d ;
5
6 int main ( ) {
7
8
s t r i n g Wyraz ; // d e k l a r a c j a o b i e k t o w , k o r e sa lancuchami
9
// sa p u s t e i c h d l u g o s c =0;
10
11
12
cout<<" Teraz wpisz jakis wyraz "<<e n d l ;
13
c i n >>Wyraz ; // t u t a j z o s t a n i e o b i e k t o w i Wyraz p r z y p i s a n a w a r t o s c
14
15 int d l u g o s c=Wyraz . l e n g t h ( ) ;
16
17
cout<<" Dlugosc wpisanego tekstu wynosi "<<d l u g o s c <<e n d l ;
18
19
3
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
char znak=Wyraz [ 0 ] ; // p i e r w s z y znak w p i s a n e g o t e k s t u
cout<<" Pierwszy wpisany znak Twojego tekstu to: "<<znak<<e n d l ;
znak=Wyraz [ d l u g o s c − 1 ] ;
cout<<" Ostatni znak Twojego teksu to: "<<znak<<e n d l ;
cout<<endl <<endl <<"A teraz wypiszemy wszystkie znaki w Twoim tekscie "<<e n d l ;
f o r ( int i =0; i <d l u g o s c ; i ++){
cout<<i <<"\t"<<Wyraz [ i ]<< e n d l ;
}
cout<<" ******************** "<<e n d l ;
cout<<" Wpisz dlugi wyraz zawierajacy slowo aku"<<e n d l ;
s t r i n g inny ;
c i n >>inny ;
// t e r a z zapytamy o numer znaku w ktorym z n a j d u j e s i e p o s z u k i w a n y
// l a n c u c h znakowy np . s l o w o aku
//W tym c e l u uruchamiamy metode f i n d ( )
int numer=inny . f i n d ( "aku" ) ;
cout<<" lancuch znakow aku znajduje sie na "<<numer<<" miejscu "<<e n d l ;
cout<<"w wyrazie :"<<e n d l ;
cout<<inny<<e n d l ;
return 0 ;
}
Zauważmy że nasz wyraz (łańcuch znakowy) musi być “politycznie poprawny“ tzn. nie może
zawierać spacji. Wszystko psuje się. W kolejnym przykładzie zobaczymy że jednak możemy
włączyć spacje w przypadku gdzy obiektowi z klasy string przypisujemy literał znakowy.
1 #include <i o s t r e a m >
2 #include <s t r i n g >
3
4 using namespace s t d ;
5
6 int main ( ) {
7
8
9 s t r i n g z d a n i e ; // p r z y p i s z e m y mu l i t e r a l znakowy
10
//w p r z y p a d k u podania w a r t o s c i p o p r z e z l i t e r a l l a n c u c h znakowy
11
// moze z a w i e r a c s p a c j e
12
13 z d a n i e="Ma powstac tekst byle dlugi lub krotki " ;
14 cout<<z d a n i e <<e n d l ;
15 cout<<" --------------------------------------------------"<<e n d l ;
16 cout<<" Znajdziemy w tym zdaniu slowo dlugi i zamienimy slowem jaki"<<e n d l ;
17
18 s t r i n g Z n a l e z i o n e Z n a k i ( " dlugi " ) ;
19 s t r i n g NoweZnaki ( "jaki " ) ; // dajemy j e d n a s p a c j e w i e c e j aby
20
// i c h b y l o t y l e i l e z a s t e p o w a n y c h znakow s l o w a d l u g i
4
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// bedziemy p r z e g l a d a c l a n c u c h z d a n i e od p o z y c j i 0
// i s z u k a c s l o w a ” d l u g i ”
int n = z d a n i e . f i n d ( Z n a l e z i o n e Z n a k i , 0 ) ; // zmienna n p o d a j e p o l o z e n i e
// p o j a w i s i e pewna l i c z b a c a l k o w i t a
cout<<s t r i n g : : npos<<e n d l ;
// Sprawdzamy c z y s l o w o d l u g i z o s t a l o z n a l e z i o n e
// i j e s l i t a k t o z s t e p u j e m y nowymi znakami
i f ( n != s t r i n g : : npos ) {
z d a n i e . r e p l a c e ( n , NoweZnaki . s i z e ( ) , NoweZnaki ) ;
}
// wydruk z d a n i a
cout<<z d a n i e <<e n d l ;
return 0 ;
}
Poniżej jest źródło string5.cc w którym wykorzystujemy kontenerową klasę vector do której
będziemy wrzucać obiekty klasy string. Komentarze w źródle tego programu pozwolą korzystać
ze składni klasy kontenerowej bez wstępnego jej omówienia.
1 #include <i o s t r e a m >
2 #include <s t r i n g >
3 #include <v e c t o r > // k l a s a kontenerowa
4
// do k o n t e n e r a mozna w k l a d a c o b i e k t y dowolnych k l a s
5
// a l e w tym p r z y k l a d z i e bedziemy w k o n t e r n e r z e u m i e s z c z a c
6
// t y l k o o b i e k t y k l a s y s t r i n g
7
8 using namespace s t d ;
9
10 int main ( ) {
11
12 // bedziemy s k l a d a c wyrazy z d a n i a w k o n t e n e r z e z d a n i e
13
14 v e c t o r <s t r i n g > z d a n i e ; // a l o k a c j a k o n t e n e r a z d a n i e
15
// do k o n t e n e r a wrzucamy wyrazy o d d z i e l o n e s p a c j a
16 s t r i n g wyraz ;
17 cout<<" Wpisz zdanie zakonczone przez nacisniecie klawisza ENTER "<<e n d l ;
18
while ( c i n >>wyraz ) { // s p a c j e o d d z i e l a j a p o s z c z e g o l n e wyrazy
19
z d a n i e . push back ( wyraz ) ; // metoda p u s h b a c k ( ) s l u z y do w k l a d a n i a
20
i f ( c i n . peek()==’\n’ ) break ; // o b i e k t o w do k o n t e n e r a
21
}
22
23 cout<<" Napisane zostalo zdanie : " ;
24
25 f o r ( int i =0; i <z d a n i e . s i z e ( ) ; i ++){
26
cout<<z d a n i e [ i ]<<" " ;
27 }
28 cout<<e n d l ;
29
30
31 return 0 ;
32 }
5
Dla części młodego pokolenia programistów kontenery będą wygodniejsze niż stosowanie
tablic. To że nie jest to trudne widać z kolejnego przykładu kontener1.cc.
1 // z d e f i n i u j e m y wlasna k l a s e
2 // k t o r e j o b i e k t y umiescimy w k o n t e n e r z e
3
4 #include <i o s t r e a m >
5 #include <v e c t o r > // k o n t e n e r v e c t o r
6 #include <c s t d l i b >
7
8 using namespace s t d ;
9
10 c l a s s Czlowiek { // d e f i n i u j e m y k l a s e C z l o w i e k
11 private :
12
int wiek ;
13
double waga ;
14 public :
15
Czlowiek ( ) { } // k o n s t r u k t o r bezparametrowy
16
Czlowiek ( int w) { wiek=w; } // k o n s t r u k t o r z parametrem
17
18
void WpiszWiek ( int a ) { wiek=a ; }
19
int PodajWiek ( ) { return wiek ; }
20
21
void WpiszWage ( double w) { waga=w; }
22
double PodajWage ( ) { return waga ; }
23 } ;
24
25
26 int main ( ) {
27
28
typedef s t d : : v e c t o r <Czlowiek∗> Rodzina ; // s k l a d n i a d l a d e f i n i c j i
29
// k o n t e n e r a Rodzina
30
Rodzina Kowalscy ;
// p u s t y k o n t e n e r Kowalscy
31
Rodzina Wojewodzki ; // p u s t y k o n t e n e r Wojewodzki
32
33 // r o d z i n a K o w a l s k i c h − 3 o s o b y
34
35
f o r ( int n=0;n<3;n++){
36
Kowalscy . push back (new Czlowiek ) ; // w k l a d a n i e o b i e k t o w do k o n t e n e r a
37
}
38
39 // r o d z i n a Wojewodzki − 2 o s o b y
40
41
Wojewodzki . push back (new Czlowiek ( 3 5 ) ) ;
42
Wojewodzki . push back (new Czlowiek ( 7 0 ) ) ;
43
44
double waga ;
45
46
f o r ( int n=0;n<Kowalscy . s i z e ( ) ; n++){ // l o s o w e p r z y p i s a n i e wagi
47
waga=random ( ) / ( 1 . 0 +RAND MAX) ∗ 1 0 0 . 0 ;
48
Kowalscy [ n]−>WpiszWage ( waga ) ;
49
}
50
51
f o r ( int n=0;n<Wojewodzki . s i z e ( ) ; n++){
52
waga=random ( ) / ( 1 . 0 +RAND MAX) ∗ 1 0 0 . 0 ;
53
Wojewodzki [ n]−>WpiszWage ( waga ) ;
54
}
6
55
56
57
58
59
60
61
62
63
cout<<" Rodzina Kowalscy :"<<e n d l ;
f o r ( int n=0;n<Kowalscy . s i z e ( ) ; n++){
cout<<Kowalscy [ n]−>PodajWage()<<" kg"<<e n d l ;
}
return 0 ;
}
Biblioteke string można też wykorzystać do kopiowania łańcuchów znakowych z pliku do
innego pliku. Mozliwości te widać z kolejnego przykładu gdzie nie martwimy sie już wielkością
strumienia wejściowego bo o wszystko dba biblioteka string.
1 // Inny p r z y k l a d k o p i o w a n i a b i n a r n e g o p l i k u na inny p l i k b i n a r n y
2
3 #include <i o s t r e a m >
4 #include <f s t r e a m >
5
6 using namespace s t d ;
7
8 main ( int argc , char ∗∗ argv )
9 {
10 i f ( a r g c !=3){
11
cout<<" Poprawny format polecenia : "<<e n d l ;
12
cout<<argv [0]<<" nazwa_pliku_do_skopiowania nazwa_nowego_pliku "<<e n d l ;
13
return 1 ;
14 }
15
16 s t r i n g l i n i a ;
17 f s t r e a m WE,WY;
18
19 // k o p i o w a n i e b i n a r n e ma dodatkowo i o s : : b i n a r y
20 //Do k o p i o w a n i a t e k s t u w y s t a r c z y l o b y WE. open ( a r g v [ 1 ] , i o s : : i n ) d l a c z y t a n i a z p l i k u
21 // i WY. open ( a r g v [ 2 ] , i o s : : o u t ) do z a p i s u do p l i k u
22
23
WE. open ( argv [ 1 ] , i o s : : i n | i o s : : b i n a r y ) ;
24
WY. open ( argv [ 2 ] , i o s : : out | i o s : : b i n a r y ) ;
25
26
i f (WE. good ( ) == f a l s e | | WY. good ( ) == f a l s e ) {
27
c o u t << "Nie moge otworzyc jednego z plikow " << e n d l ;
28
return ( 1 ) ;
29
}
30
31
32
33
while ( 1 ) {
34
35
g e t l i n e (WE, l i n i a ) ;
36
i f (WE. e o f ( ) ) break ;
37
38
WY<<l i n i a <<e n d l ;
39
40
}
41
42
43 return 0 ;
7
44
}
8