R17-06.DOC

42
 Rozdział 17. Strumienie Do tej pory używaliśmy cout do wypisywania tekstu na ekranie, zaś cin do odczytywania klawiatury , wykorzystywaliśmy je bez pełnego zrozumienia ich działania. Z tego rozdziału dowiesz się czym s! strumienie i jak się ich używa,  jak zarz!dza" we jściem i wyjście m, wykorzystuj!c strum ienie,  jak odczytywa" i zapisy wa" pliki za pomoc! strumieni. Przegląd strumieni #$$ nie określa, w jaki spos%b dane s! wypisywa ne na ekranie lub zapisywane do pliku, ani w  jaki spos%b s! one odczy tywane przez program. &peracje te stanowi! jednak podstawow! częś"  pracy z #$$, więc bib lioteka standardowa #$ $ zawiera bibliotekęiostream, kt%ra obsługuje wejście i wyjście '()&, input*output+. Zalet! oddzielenia unkcji wejścia*wy jścia od języka i obsługiwania ich w bibliotekach jest możliwoś" łatwiejszego przenoszenia program%w pomiędzy r%żnymi platormami. Dzięki temu można napisa" program na komputerze -#, a następnie przekompilowa" go i uruchomi" na stacji roboczej un. -roducent kompilatora dostarcza odpowiedni! bibliotekę i wszystko działa. -rzynajmniej w teorii. UWA GA Biblio teka jest zbiorem lik!" .obj # kt!re mogą b$% ołą&zone z rogramem " &elu za e"nieni a dodatko"ej 'unk&jonalno(&i. )est to najbardziej odsta"o "a 'orma ono"nego"ielokrotnego  "$korz$st $"an ia ko du # i u* $"an a od &z as !" i er "sz$&+ rogramist!" # r$ją&$&+ zera i jed$nki na (&iana&+ jaski,.

Transcript of R17-06.DOC

Page 1: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 1/42

Rozdział 17.Strumienie

Do tej pory używaliśmy cout do wypisywania tekstu na ekranie, zaś cin do odczytywania

klawiatury, wykorzystywaliśmy je bez pełnego zrozumienia ich działania.

Z tego rozdziału dowiesz się

• czym s! strumienie i jak się ich używa,

•  jak zarz!dza" wejściem i wyjściem, wykorzystuj!c strumienie,

•  jak odczytywa" i zapisywa" pliki za pomoc! strumieni.

Przegląd strumieni#$$ nie określa, w jaki spos%b dane s! wypisywane na ekranie lub zapisywane do pliku, ani w jaki spos%b s! one odczytywane przez program. &peracje te stanowi! jednak podstawow! częś" pracy z #$$, więc biblioteka standardowa #$$ zawiera bibliotekę iostream, kt%ra obsługuje

wejście i wyjście '()&, input*output+.

Zalet! oddzielenia unkcji wejścia*wyjścia od języka i obsługiwania ich w bibliotekach jestmożliwoś" łatwiejszego przenoszenia program%w pomiędzy r%żnymi platormami. Dzięki temumożna napisa" program na komputerze -#, a następnie przekompilowa" go i uruchomi" na stacjiroboczej un. -roducent kompilatora dostarcza odpowiedni! bibliotekę i wszystko działa.-rzynajmniej w teorii.

UWAGA Biblioteka jest zbiorem lik!" .obj # kt!re mogą b$% ołą&zone z rogramem " &elu

zae"nienia dodatko"ej 'unk&jonalno(&i. )est to najbardziej odsta"o"a 'ormaono"nego"ielokrotnego  "$korz$st$"ania kodu# i u*$"ana od &zas!" ier"sz$&+rogramist!"# r$ją&$&+ zera i jed$nki na (&iana&+ jaski,.

Page 2: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 2/42

Kapsułkowanie/lasy biblioteki iostream postrzegaj! przepływ danych z programu na ekran jako strumie0,

 płyn!cy bajt po bajcie. 1eśli punktem docelowym strumienia jest plik lub ekran, wtedy jego

2r%dłem jest zwykle jakaś częś" programu. 3dy strumie0 jest odwr%cony, dane mog! pochodzi" zklawiatury lub z dysku i mog! 4wypełnia"5 zmienne w programie.

1ednym z podstawowych zada0 strumieni jest kapsułkowanie problemu pobierania danych zwejścia 'na przykład dysku+ i wysyłania ich do wyjścia 'na przykład na ekran+. -o stworzeniustrumienia program działa z tym strumieniem, kt%ryprzy czym strumie0 zajmuje się wszystkimi

szczeg%łami. 6ę podstawow! ideę ilustruje rysunek 78.7.

9ys. 78.7. /apsułkowanie poprzez strumienie

BuforowanieZapis na dysk 'i w mniejszym stopniu także na ekran+ jest bardzo 4kosztowny.5 Zapis danych nadysk lub odczyt ich z dysku zajmuje 'stosunkowo+ dużo czasu, a podczas operacji zapisu i odczytudziałanie programu zwykle jest zablokowane. :by rozwi!za" ten problem, strumienie oeruj!

4buorowanie5. Dane s! zapisywane do strumienia, ale nie s! natychmiast zapisywane na dysk.Zamiast tego buor strumienia wypełnia się danymi; gdy się całkowicie wypełni, dane s!zapisywane na dysk w ramach pojedynczej operacji.

<yobra2my sobie wodę wpływaj!c! do zbiornika przez g%rny zaw%r i wypełniaj!c! go, lecz niewypływaj!c! z niego poprzez dolny zaw%r. (lustruje to rysunek 78.=.

9ys. 78.=. <ypełnianie buora

Page 3: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 3/42

3dy woda 'dane+ całkowicie wypełni zbiornik, zaw%r się otwiera i cała zawartoś" gwałtowniewypływa. -okazuje to rysunek 78.>.

9ys. 78.>. &pr%żnianie buora

3dy buor się opr%żni, dolny zaw%r zostaje zamknięty, otwiera się g%rny zaw%r i do zbiornika* buora zaczyna napływa" woda. -rzedstawia to rysunek 78.?.

9ys. 78.?. -onowne napełnianie buora

Page 4: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 4/42

#zęsto zdarza się, że chcemy wypuści" wodę ze zbiornika jeszcze zanim całkowicie się wypełni. @azywa się to 4zrzucaniem buora5. (lustruje to rysunek 78.A.

9ys. 78.A. Zrzucanie buora

Page 5: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 5/42

Strumienie i bu'or$1ak można było oczekiwa", #$$ implementuje strumienie i buory w spos%b obiektowy.

/lasa streambuf zarz!dza buorem, zaś jej unkcje składowe oeruj! możliwoś"wypełniania, opr%żniania, zrzucania i innych sposob%w manipulowania buorem.

• /lasa ios jest bazow! klas! dla klas wejścia*wyjścia z użyciem strumieni. 1edn! ze

zmiennych składowych tej klasy jest obiekt klasy streambuf.

• /lasy istream i ostream s! wyprowadzone z klasy ios i specjalizuj! działanie strumieni

wejściowych i wyjściowych.

• /lasa iostream jest wyprowadzona zar%wno z klasy istream, jak i ostream i dostarcza

metod wejścia*wyjścia do wypisywania danych na ekranie i odczytywania ich z klawiatury.

• /lasa fstream zapewnia wejście i wyjście z oraz do plik%w.

Standardo"e obiekt$ "ej(&ia-"$j(&ia3dy program #$$, zawieraj!cy klasę iostream, rozpoczyna działanie, tworzy i inicjalizuje

cztery obiekty

UWAGABiblioteka klas$ iostream  jest doda"ana rzez komilator do rogramu

automat$&znie. Ab$ u*$% jej 'unk&ji# musisz dołą&z$% do o&zątku kodu s"ojego rogramuodo"iednią instruk&j #include.

• cin 'wymawiane jako 4si*in5+ obsługuje wprowadzanie danych ze standardowego wejścia,

czyli klawiatury.

• cout 'wymawiane jako 4si*aut5+ obsługuje wyprowadzanie danych na standardowe wyjście,

czyli ekran.

• cerr 'wymawiane jako 4si*err5+ obsługuje nie  buorowane wyprowadzanie danych na

standardowe urz!dzenie wyjściae dla wydruku błęd%w, czyli ekran. -onieważ wyjście błęd%w

nie jest buorowane, wszystko co zostanie wysłane do cerr, jest wypisywane na

standardowym urz!dzeniu błęd%w natychmiast, bez oczekiwania na wypełnienie buora lub

nadejście polecenia zrzutu.

• clog 'wymawiane jako 4si*log5+ obsługuje buorowane wyprowadzanie danych na

standardowe wyjście błęd%w, czyli ekran. Doś" często to wyjście jest przekierowywane do pliku log dziennika, co zostanie opisane w następnym podrozdziale.

Page 6: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 6/42

Przekiero"$"anie/ażde ze standardowych urz!dze0, wejścia, wyjścia oraz błęd%w, może zosta" przekierowane nainne urz!dzenie. tandardowe wyjście błęd%w często jest przekierowywane do pliku, zaśstandardowe wejście i wyjście mog! zosta" poł!czone potokowo z plikami danych wejściowych iwyjściowych. Bożna uzyska" ten eekt za pomoc! polece0 systemu operacyjnego.

-rzekierowanie oznacza powi!zanie wyjścia 'lub wejścia+ z miejscem innym niż domyślne.&peratory przekierowania dla D&*a i C@(/*a to < dla przekierowania wejścia oraz > dla

 przekierowania wyjścia.

-otok oznacza wykorzystanie danych wyjściowych jednego programu jako danych wejściowychdrugiego.

D& zapewnia jedynie podstawowe polecenia przekierowywania, takie jak przekierowane wyjście

'>+ i przekierowane wejście '<+. C@( posiada bardziej zaawansowane możliwości przekierowywania, ale rz!dz!ca nimi zasada jest ta sama zapisz wyniki skierowane na ekran do

 pliku lub przekaż je potokiem do innego programu. -odobnie, dane wejściowe dla programu mog!  by" pobierane z pliku, a nie z domyślnej klawiatury.

-rzekierowywanie jest raczej unkcj! systemu operacyjnego niż bibliotek iostream. #$$

zapewnia jedynie dostęp do czterech urz!dze0 standardowych; przekierowanie tych urz!dze0 w

odpowiednie miejsca należy do użytkownika.

Wej(&ie z u*$&iem &in3lobalny obiekt cin odpowiada za wejście i jest dostępny dla programu po doł!czeniu biblioteki

iostream. <e wcześniejszych przykładach, w celu umieszczania danych w zmiennych programu,

używaliśmy przeci!żonego operatora ekstrakcji '>>+. 1ak to działaE kładnia, jak by" może

 pamiętasz, jest następuj!ca

int someVariable;cout << "Wpisz liczbe: ";cin >> someVariable;

3lobalny obiekt cout zostanie opisany w dalszej części rozdziału; na razie skupmy się na trzeciej

linii, cin >> someVariable;. #zego możemy dowiedzie" się na temat cinE&czywiście, musi to by" obiekt globalny, gdyż nie zdeiniowaliśmy go w naszym kodzie. Zdoświadczenia wiemy, że cin posiada przeci!żony operator ekstrakcji '>>+ i że eektem tego jest

wypełnienie naszej lokalnej zmiennej someVariable danymi z buora cin.

Page 7: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 7/42

 @ie od razu możemy domyśli" się, że cin przeci!ża operator ekstrakcji dla bardzo r%żnych typ%w

 parametr%w, między innymi int&, short&, long&, double&, float&, char* i tak dalej. 3dy

 piszemy cin >> someVariable;, analizowany jest typ zmiennej someVariable. <

 poprzednim przykładzie zmienna ta była typu int, więc została wywołana następuj!ca unkcja

istream & operator>> (int &

Zauważ, że ponieważ parametr jest przekazywany poprzez reerencję, operator ekstrakcji możedziała" na pierwotnej zmiennej. Fisting 78.7 ilustruje użycie obiektu cin.

Fisting 78.7. &biekt cin obsługuje r%żne typy danych  !: isting $%$ ' u)cie obietu cin  $:+: #include <iostream>

  ,: using namespace std;  -:

.: int main(  /: 0  %: int m)1nt;  2: long m)ong;  3: double m)4ouble; $!: float m)5loat; $$: unsigned int m)6nsigned; $+:$,: cout << "int: "; $-: cin >> m)1nt; $.: cout << "long: "; $/: cin >> m)ong; $%: cout << "double: "; $2: cin >> m)4ouble; $3: cout << "float: "; +!: cin >> m)5loat;

 +$: cout << "unsigned: "; ++: cin >> m)6nsigned; +,:+-: cout << "7n7nint:7t" << m)1nt << endl; +.: cout << "long:7t" << m)ong << endl; +/: cout << "double:7t" << m)4ouble << endl; +%: cout << "float:7t" << m)5loat << endl; +2: cout << "unsigned:7t" << m)6nsigned << endl; +3: return !; ,!: 8

Wynik int: +long: %!!!!double: 32%/.-,+$float: ,,,unsigned: +.

int: +

Page 8: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 8/42

long: %!!!!double: 32%/.-e9!!2float: ,,,unsigned: +.

Analiza

< liniach od 8. do 77. s! deklarowane zmienne r%żnych typ%w. < liniach od 7>. do ==.użytkownik jest proszony o wprowadzenie wartości dla tych zmiennych, po czym w liniach od =?.do =G. wypisywane s! 'z użyciem cout+ wyniki.

<ynik odzwierciedla akt, że dane zostały umieszczone w zmiennych odpowiedniego 4rodzaju5 i

że program działa tak, jak mogliśmy tego oczekiwa".

Łańcuchy

&biekt cin może także obsługiwa" argumenty w postaci ła0cuch%w do znak%w 'char*+; tak więc

możemy stworzy" buor znak%w i uży" cin do jego wypełnienia. @a przykład, możemy napisa"

char ourame.!=;cout << "Wpisz so?e imie: ";cin >> ourame;

3dy wpiszesz @esse, zmienna ourame zostanie wypełniona znakami 1, e, s, s, HI. &statni znak

to null; cin automatycznie ko0czy nim ła0cuch, dlatego w buorze musi by" wystarczaj!ca iloś"

miejsca na pomieszczenie całego ła0cucha oraz ko0cz!cego go znaku null. Dla unkcji bibliotekistandardowej znak null oznacza koniec ła0cucha. Junkcje biblioteki standardowej zostan!

om%wione w rozdziale =7., 4#o dalej5.

Problemy z łańcuchami

-amiętaj!c o wszystkich zaletach obiektu cin, możesz by" zaskoczony, pr%buj!c wpisa" do

ła0cucha swoje pełne imię i nazwisko. &biekt cin traktuje białe spacje jako separatory. 3dy

natraia na spację lub znak nowej linii, zakłada, że dane wejściowe dla parametru s! kompletne i,w przypadku ła0cuch%w, dodaje na ich ko0cu znak null. -roblem ten ilustruje listing 78.=.

Fisting 78.=. -r%ba wpisania do cin więcej niż jednego słowa!: isting $%+ ' cin i AaBcuch) znaC

  $:

+: #include <iostream>  ,:-: int main(

  .: 0  /: char ourame.!=;  %: std::cout << "Doda? imie: ";

Page 9: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 9/42

  2: std::cin >> ourame;  3: std::cout << "Easz na imie: " << ourame << std::endl; $!: std::cout << "Doda? imie i naziso: "; $$: std::cin >> ourame; $+: std::cout << "az)asz sie: " << ourame << std::endl; $,: return !;

 $-: 8

Wynik Doda? imie: @esseEasz na imie: @esseDoda? imie i naziso: @esse ibert)az)asz sie: @esse

Analiza

< linii K. została stworzona tablica znak%w 'w celu przechowania danych wprowadzanych przez

użytkownika+. < linii 8. użytkownik jest proszony o wpisanie jedynie imienia; imię to jest

 przechowywane prawidłowo, co odzwierciedla wynik.

< linii 7I. użytkownik jest proszony o podanie całego nazwiska. &biekt cin odczytuje dane

wejściowe i gdy natraia na spację pomiędzy wyrazami, umieszcza po pierwszym słowie znak nulli ko0czy odczytywanie danych. @ie tego oczekiwaliśmy.

:by zrozumie", dlaczego działa to w ten spos%b, przeanalizuj listing 78.>. <yświetla on danewprowadzone do kilku p%l.

Fisting 78.> <ejście wielokrotne!: isting $%, ' dziaAanie cin

  $:+: #include <iostream>

  ,: using namespace std;  -:.: int main(

  /: 0  %: int m)1nt;  2: long m)ong;  3: double m)4ouble; $!: float m)5loat; $$: unsigned int m)6nsigned; $+: char m)Word.!=; $,:$-: cout << "int: "; $.: cin >> m)1nt; $/: cout << "long: "; $%: cin >> m)ong; $2: cout << "double: "; $3: cin >> m)4ouble;

 +!: cout << "float: "; +$: cin >> m)5loat; ++: cout << "sloo: "; +,: cin >> m)Word; +-: cout << "unsigned: "; +.: cin >> m)6nsigned;

Page 10: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 10/42

 +/:+%: cout << "7n7nint:7t" << m)1nt << endl; +2: cout << "long:7t" << m)ong << endl; +3: cout << "double:7t" << m)4ouble << endl; ,!: cout << "float:7t" << m)5loat << endl; ,$: cout << "sloo: 7t" << m)Word << endl;

 ,+: cout << "unsigned:7t" << m)6nsigned << endl; ,,:,-: cout << "7n7nintF longF doubleF floatF slooF unsigned: "; ,.: cin >> m)1nt >> m)ong >> m)4ouble; ,/: cin >> m)5loat >> m)Word >> m)6nsigned; ,%: cout << "7n7nint:7t" << m)1nt << endl; ,2: cout << "long:7t" << m)ong << endl; ,3: cout << "double:7t" << m)4ouble << endl; -!: cout << "float:7t" << m)5loat << endl; -$: cout << "sloo: 7t" << m)Word << endl; -+: cout << "unsigned:7t" << m)6nsigned << endl; -,:--:-.: return !; -/: 8

Wynik int: +long: ,!,!,double: ,3,3,3,3%2,-float: ,,,sloo: Gellounsigned: 2.

int: +long: ,!,!,double: ,3,3,3e9!$$float: ,,,

sloo: Gellounsigned: 2.

intF longF doubleF floatF ordF unsigned: , ,!-3,2 ,3,2-%-%,/// b)e '+

int: ,long: ,!-3,2double: ,3,2-%e9!!2float: ///sloo: b)eunsigned: -+3-3/%+3-

Analiza

6akże w tym przykładzie zostało stworzonych kilka zmiennych, tym razem obejmuj!cych takżetablicę znak%w. Cżytkownik jest proszony o wprowadzenie danych, kt%re następnie zostaj!wypisane.

Page 11: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 11/42

< linii >?. użytkownik jest proszony i wpisanie wszystkich danych jednocześnie, po czym każde4słowo5 danych wejściowych jest przypisywane odpowiedniej zmiennej. < przypadku takiego

wielokrotnego przypisania, obiekt cin musi potraktowa" każde słowo jako pełne dane dla każdej

ze zmiennych. 3dyby obiekt cin potraktował wszystkie dane jako skierowane do jednej zmiennej,

wtedy takie poł!czone wprowadzanie danych nie byłoby możliwe.

Zwr%" uwagę, że w linii ?=. ostatnim zaż!danym obiektem była liczba całkowita bez znaku, leczużytkownik wpisał wartoś" H+. -onieważ cin wierzy, że odczytuje liczbę całkowit! bez znaku,

wzorzec bitowy wartości H+ został odczytany jako liczba bez znaku. <artoś" ta, wypisana przez

cout, to -+3-3/%+3-. <artoś" całkowita bez znaku -+3-3/%+3- ma dokładnie ten sam wz%r

 bit%w, co wartoś" całkowita ze znakiem r%wna H+.

< dalszej części rozdziału zobaczymy, jak wpisa" do buora cały ła0cuch z wieloma słowami. @arazie jednak pojawia się pytanie w jaki spos%b operator ekstrakcji daje sobie radę z ł!czeniemwartościE

operator>> zwraca referencję do obiektu istream<artości! zwracan! przez cin jest reerencja do obiektu istream. -onieważ samo cin jest

obiektem klasy istream, więc zwracana wartoś" jednej ekstrakcji może by" wejściem dla

następnej.

int IarJneF IarKoF IarKhree;cout << "Wpisz trz) liczb): ";cin >> IarJne >> IarKo >> IarKhree;

3dy piszemy cin >> IarJne >> IarKo >> IarKhree;, wtedy pierwsza ekstrakcja jest

obliczana jako 'cin >> IarJne+. &trzymana wartoś" jest kolejnym obiektem istream i

operator ekstrakcji tego obiektu otrzymuje zmienn! IarKo. <ygl!da to tak, jakbyśmy napisali

((cin >> IarJne >> IarKo >> IarKhree;

Do techniki tej wr%cimy p%2niej, przy omawianiu działania obiektu cout.

/nne 'unk&je składo"e klas$" d$soz$&ji &in&pr%cz przeci!żonego operatora>>, obiekt cin posiada< dyspozycji obiektu cin pozostaje nie

tylko operator >>, ale także inne unkcje składowe. ! one używane wtedy, gdy jest wymagana

 bardziej precyzyjna kontrola wprowadzania danych.

Page 12: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 12/42

prowadzanie pojedynczych znak!woperator>> przyjmuj!cy reerencję do znaku może by" użyty do pobierania pojedynczego znaku

ze standardowego wejścia. Do pobrania pojedynczego znaku można także uży" unkcji składowej

get(, i to na dwa sposoby unkcja get( może zosta" wywołana bez parametr%w'wtedywykorzystywana jest wartoś" zwracana+ lub z reerencj! do znaku.

"#ycie $et%& bez parametr!w

-ierwsza orma unkcji get( nie przyjmuje żadnych parametr%w. Zwraca ona odczytany znak

lub znak L&J 'znak ko0ca pliku, end o ile+ w chwili dojścia do ko0ca pliku. Junkcja get( bez

 parametr%w nie jest używana zbyt często. @ie ma możliwości ł!czenia tej unkcji z wielokrotnymwprowadzaniem, gdyż zwracan! wartości! nie jest obiekt klasy iostream. Dlatego nie zadziała

 poniższa linia kodu

cinget( >> m)VarJne >> m)VarKo; niedozolone

<artości! zwracan! przez cinget( >> m)VarJne jest wartoś" całkowita, a nie obiekt klasy

iostream.

 @ajczęstsze zastosowanie unkcji get( bez parametr%w przedstawia listing 78.?.

Fisting 78.?. Cżycie unkcji get( bez parametr%w  !: isting $%- ' 6sing get( ith no parameters  $:+: #include <iostream>

  ,:-: int main(

  .: 0  /: char ch;  %: hile ( (ch L std::cinget( ML NJ5  2: 0  3: std::cout << "ch: " << ch << std::endl; $!: 8 $$: std::cout << "7nOotoeM7n"; $+: return !; $,: 8

Wynik Gelloch: Gch: e

ch: lch: lch: och:

World

Page 13: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 13/42

ch: Wch: och: rch: lch: d

ch: (ctrl9z

OotoeM

Analiza

< linii K. została zadeklarowana lokalna zmienna znakowa ch. -ętla hile przypisuje dane

otrzymane od unkcji getcin( do ch, i gdy nie jest to znak ko0ca pliku, wypisywany jest

ła0cuch.

<ypisywane dane s! buorowane aż do chwili osi!gnięcia ko0ca linii. 3dy zostanie napotkanyznak L&J 'wprowadzony w wyniku naciśnięcia kombinacji klawiszy Ctrl+Z  w D&*ie lub

Ctrl+D w C@(/*ie+, następuje wyjście z pętli.

-amiętaj, że nie każda implementacja klasy istream obsługuje tę wersję unkcji get(, mimo iż

obecnie stanowi ona częś" standardu :@()(&.

"#ycie funkcji $et%& z parametrem w postaci referencji do znaku

3dy jako parametr unkcji get( zostanie użyty znak, jest on wypełniany następnym znakiem ze

strumienia wejściowego. Zwracan! wartości! jest obiekt iostream, więc wywołanie tej unkcji

get( może by" ł!czone, co ilustruje listing 78.A.

Fisting 78.A. Cżycie unkcji get( z parametrem  !: isting $%. ' 6)cie func?i get( z parametrem  $:+: #include <iostream>

  ,:-: int main(

  .: 0  /: char aF bF c;  %:2: std::cout << "Wpisz trz) liter): ";

  3:$!: std::cinget(aget(bget(c; $$:$+: std::cout << "a: " << a << "7nb: "; $,: std::cout << b << "7nc: " << c << std::endl; $-: return !; $.: 8

Wynik Wpisz trz) liter): raz

Page 14: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 14/42

a: rb: ac: z

Analiza

< linii K. zostały zadeklarowane trzy zmienne znakowe. < linii 7I. zostaje trzykrotnie wywołana,w spos%b poł!czony, unkcja cinget(. @ajpierw jest wywoływana cinget(a. 6o powoduje

umieszczenie pierwszej litery w zmiennej a i zwr%cenie obiektu cin. < rezultacie, po powrocie z

wywołania, zostaje wywołane cinget(b, a w zmiennej b jest umieszczana następna litera.

&statecznie wywołane zostaje cinget(c, a w zmiennej c zostaje umieszczona trzecia litera.

-onieważ cinget(a zwraca obiekt cin, moglibyśmy napisa"

cingat(a >> b;

< tej ormie cinget(a zwraca obiekt cin, więc drug! raz! jest cin >> b;.

6:/ @(L

Cżywaj operatora ekstrakcji '>>+wtedy, gdy

chcesz pomin!" białe spacje.

Cżywaj unkcji get( z parametrem wtedy,

gdy chcesz sprawdzi" każdy znak, wł!cznie z białymi spacjami.

'dczytywanie łańcuch!w z wej(cia standardowe$o&perator ekstrakcji '>>+ może by" używany do wypełniania tablicy znak%w, podobnie jak unkcje

get( i getline(.

&statnia orma unkcji get( przyjmuje trzy parametry. -ierwszym z nich jest wska2nik do

tablicy znak%w, drugim parametrem jest maksymalna iloś" znak%w do odczytania plus jeden, zaś

trzecim parametrem jest znak ko0cz!cy.

3dy jako drugi parametr podasz wartoś" +!, unkcja get( odczyta dziewiętnaście znak%w, doda

znak null, po czym umieści całoś" w buorze wskazywanym przez pierwszy parametr. 6rzeci parametr, znak ko0cz!cy, jest domyślnie znakiem nowej linii 'P7nP+. 3dy znak ko0cz!cy zostanie

napotkany przed odczytaniem maksymalnej ilości znak%w, do ła0cucha zostaje dodany znak null,

a znak ko0cz!cy pozostaje w buorze wejściowym.pos%b użycia tej ormy unkcji get( przedstawia listing 78.K.

Fisting 78.K. Cżycie unkcji get( z tablic! znak%w

Page 15: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 15/42

  !: isting $%/ ' 6)cie func?i get( z tablicQ znaC  $:+: #include <iostream>

  ,: using namespace std;  -:.: int main(

  /: 0  %: char stringJne+./=;  2: char stringKo+./=;  3:$!: cout << "Wpisz piersz) lancuch: "; $$: cinget(stringJneF+./; $+: cout << "Diersz) lancuch: " << stringJne << endl; $,:$-: cout << "Wpisz drugi lancuch: "; $.: cin >> stringKo; $/: cout << "4rugi lancuch: " << stringKo << endl; $%: return !; $2: 8

Wynik Wpisz piersz) lancuch: 4obr) zartDiersz) lancuch: 4obr) zartWpisz drugi lancuch: t)nfa art4rugi lancuch: t)nfa

Analiza

< liniach 8. i G. zostały zadeklarowane dwie tablice znak%w. < linii 7I. użytkownik jest proszonyo wprowadzeanie ła0cucha, po czym w linii 77. zostaje wywołana unkcja cinget(.

-ierwszym parametrem jest buor do wypełnienia, zaś drugim jest zwiększona o jedenmaksymalna iloś" znak%w, jak! unkcja get( może przyj!" 'dodatkowa pozycja jest

zarezerwowana dla znaku null , P7!P+. Domyślnym, trzecim parametrem jest znak nowej linii.

Cżytkownik wpisuje 44obr) art5. -onieważ raza ta ko0czy się znakiem nowej linii, jest ona

umieszczana wraz z ko0cz!cym znakiem null w buorze stringJne.

< linii 7?. użytkownik jest proszony o wpisanie kolejnego ła0cucha; tym razem do odczytania gozostał użyty operator ekstrakcji. -onieważ operator ekstrakcji odczytuje znaki tylko do chwili

napotkania białej spacji, w drugim buorze zostaje umieszczony wyraz 4tyna5, wraz z ko0cowymznakiem null. &czywiście, nie tego chcieliśmy.

(nnym sposobem rozwi!zania tego problemu jest użycie unkcji getline(, co ilustruje listing

78.8.

Fisting 78.8. Cżycie unkcji getline(  !: isting $%% ' 6)cie func?i getline(  $:+: #include <iostream>

  ,: using namespace std;  -:.: int main(

  /: 0

Page 16: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 16/42

  %: char stringJne+./=;  2: char stringKo+./=;  3: char stringKhree+./=; $!:$$: cout << "Wpisz piersz) lancuch: "; $+: cingetline(stringJneF+./;

 $,: cout << "Diersz) lancuch: " << stringJne << endl; $-:$.: cout << "Wpisz drugi lancuch: "; $/: cin >> stringKo; $%: cout << "4rugi lancuch: " << stringKo << endl; $2:$3: cout << "Wpisz trzeci lancuch: "; +!: cingetline(stringKhreeF+./; +$: cout << "Krzeci lancuch: " << stringKhree << endl; ++: return !; +,: 8

Wynik Wpisz piersz) lancuch: raz da trz)

Diersz) lancuch: raz da trz)Wpisz drugi lancuch: czter) piec szesc4rugi lancuch: czter)Wpisz trzeci lancuch: Krzeci lancuch: piec szesc

Analiza

6en przykład wymaga dokładnego przeanalizowania, gdyż może sprawi" kilka niespodzianek. <liniach od 8. do M. zostały zadeklarowane trzy tablice znak%w.

< linii 77. użytkownik jest proszony o wprowadzenie ła0cucha; ten ła0cuch jest odczytywany za pomoc! unkcji getline(. -odobnie jak unkcja get(, unkcja getline( przyjmuje buor i

maksymaln! liczbę znak%w. 1ednak w odr%żnieniu od unkcji get(, ko0cowy znak nowej linii

 jest odczytywany i odrzucany. Junkcja get( nie odrzuca ko0cowego znaku nowej linii, ale

 pozostawia go w buorze wejściowym.

< linii 7A. użytkownik jest ponownie proszony o wpisanie ła0cucha; tym razem do jegoodczytania zostaje użyty operator ekstrakcji. Cżytkownik wpisuje czter) piRS szeTS, a w

tablicy buorze stringKo umieszczane jest pierwsze słowo czter). @astępnie wyświetlany jest

komunikat Wpisz trzeci AaBcuch: i ponownie zostaje wywołana unkcja getline(.

-onieważ w buorze wejściowym nadal znajduj! się słowa piRS szeTS, zostaj! one natychmiast

odczytane, aż do znaku nowej linii; dopiero wtedy unkcja getline( ko0czy działanie i ła0cuch

z buora stringKhree zostaje wypisany na ekranie 'w =7. linii kodu+.

Cżytkownik nie ma możliwości wpisania trzeciego ła0cucha, gdyż drugie wywołanie unkcjigetline( zostaje spełnionezaspokojone przez dane pozostaj!ce jeszcze w buorze wejściowym

 po wywołaniu operatora ekstrakcji w linii 7K.

&perator ekstrakcji '>>+ odczytuje znaki aż do chwili napotkania pierwszego białego znaku, wtedy

umieszcza odczytane słowo w tablicy znak%w.

Junkcja składowa get( jest przeci!żona. < pierwszej wersji nie przyjmuje żadnych parametr%w

i zwraca znak pobrany z buora wejściowego. < drugiej wersji przyjmuje reerencję do pojedynczego znaku i poprzez reerencję zwraca obiekt klasy istream.

Page 17: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 17/42

< trzeciej i ostatniej wersji unkcja get( przyjmuje tablicę znak%w, iloś" znak%w do pobrania

oraz znak ko0cz!cy 'kt%rym domyślnie jest znak nowej linii+. 6a wersja unkcji get( odczytuje

znaki do tablicy aż do chwili odczytania maksymalnej ich ilości 'mniejszej o jeden od wartości podanej jako jej parametr+ lub do natraienia na znak ko0cowyy. 3dy unkcja get( natrai na

znak ko0cowyy, przestaje odczytywa" dalsze znaki, a znak ko0cowy pozostawia w buorze.

Junkcja składowa getline( także przyjmuje trzy parametry buor do wypełnienia, zwiększon!

o jeden maksymaln! iloś" znak%w, jak! może odczyta", oraz znak ko0cowyy. Junkcja getline(działa tak samo, jak unkcja get( z takimi samymi parametrami, z wyj!tkiem tego, że unkcja

getline( odrzuca znak ko0cowy.

"#ycie cin)i$nore%&

#zasem zdarza się, że chcemy pomin!" znaki, kt%re pozostały na ko0cu linii 'do znaku EOL, end

of line+ lub do ko0ca pliku ' EOF , end of file+. łuży do tego unkcja składowa ignore(. Junkcja

ta przyjmuje dwa parametry maksymaln! iloś" znak%w do pominięcia oraz znak ko0cowy.3dybyśmy napisali ignore(2!FP7nP, zostałoby odrzuconych do osiemdziesięciu znak%w.

Znaleziony znak nowej linii zostałby odrzucony i unkcja zako0czyłaby działanie. Cżycie unkcjiignore( ilustruje listing 78.G.

Fisting 78.G. Cżycie unkcji ignore(  !: isting $%2 ' 6)cie func?i ignore(  $: #include <iostream>  +: using namespace std;  ,:-: int main(

  .: 0  /: char stringJne+..=;  %: char stringKo+..=;

  2:3: cout << "Wpisz piersz) lancuch: "; $!: cinget(stringJneF+..; $$: cout << "Diersz) lancuch: " << stringJne << endl; $+:$,: cout << "Wpisz drugi lancuch: "; $-: cingetline(stringKoF+..; $.: cout << "4rugi lancuch: " << stringKo << endl; $/:$%: cout << "7n7nU teraz sprobu? pononie7n"; $2:$3: cout << "Wpisz piersz) lancuch: "; +!: cinget(stringJneF+..; +$: cout << "Diersz) lancuch: " << stringJne<< endl; ++:+,: cinignore(+..FP7nP;

 +-:+.: cout << "Wpisz drugi lancuch: "; +/: cingetline(stringKoF+..; +%: cout << "4rugi lancuch: " << stringKo<< endl; +2: return !; +3: 8

Page 18: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 18/42

Wynik Wpisz piersz) lancuch: dano temuDiersz) lancuch: dano temu

Wpisz drugi lancuch: 4rugi lancuch:

U teraz sprobu? pononieWpisz piersz) lancuch: dano temuDiersz) lancuch: dano temuWpisz drugi lancuch: b)l sobie4rugi lancuch: b)l sobie

Analiza

< liniach K. i 8. zostały stworzone dwie tablice znak%w. < linii M. użytkownik jest proszony owprowadzenie ła0cucha, więc wpisuje słowa dano temu, po kt%rych naciska klawisz Enter . Do

odczytania ła0cucha zostaje w linii 7I. wywołana unkcja get(. Junkcja get( wypełnia tablicę 

stringJne i ko0czy działanie na znaku nowej linii, ale nie odrzuca go, lecz pozostawia w

 buorze wejściowym.

< linii 7>. użytkownik jest ponownie proszony o wpisanie ła0cucha znak%w, ale unkcjagetline( w linii 7?. odczytuje pozostały w buorze znak nowej linii i natychmiast po tym

ko0czy działanie 'zanim użytkownik może wpisa" jakikolwiek znak+.

< linii 7M. użytkownik jest jeszcze raz proszony o dokonanie wpisu i wpisuje te same słowa, co na pocz!tku. 1ednak tym razem, w linii =>., zostaje użyta unkcja ignore(, kt%ra 4zjada5

 pozostaj!cy znak nowej linii. < zwi!zku z tym, gdy w linii =K. zostaje wywołana unkcjagetline(, buor wejściowy jest już pusty i użytkownik może wprowadzi" następn! linię

historyjki.

peek%& oraz putback%&&biekt strumienia wejściowego cin posiada dwie dodatkowe metody, kt%re mog! okaza" się

całkiem przydatne unkcję pee(, kt%ra sprawdza, czy w buorze jest dostępny znak, lecz nie

 pobiera go, oraz unkcję putbac(, kt%ra wstawia znak do strumienia wejściowego. Fisting 78.M

 pokazuje, w jaki spos%b mogłyby zosta" użyte te unkcje.

Fisting 78.M. Cżycie unkcji pee( i putbac(  !: isting $%3 ' 6)cie func?i pee( i putbac(  $: #include <iostream>  +: using namespace std;  ,:-: int main(

  .: 0  /: char ch;  %: cout << "Wpisz fraze: ";  2: hile ( cinget(ch

Page 19: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 19/42

  3: 0 $!: if (ch LL PMP $$: cinputbac(PP; $+: else $,: cout << ch; $-: hile (cinpee( LL P#P

 $.: cinignore($FP#P; $/: 8 $%: return !; $2: 8

Wynik Wpisz fraze: adszedlMczas#naMdobra#zabaeMadszedlczasnadobrazabae

Analiza

< linii K. została zadeklarowana zmienna znakowa ch, a w linii 8. użytkownik jest proszony o

wpisanie razy. Zadaniem tego programu jest zamiana każdego wykrzyknika 'M+ na znak dolara '+oraz usunięcie każdego znaku hash '#+.

-rogram działa w pętli aż do napotkania znaku ko0ca pliku 'Ctrl+C  w <indows, Ctrl+ ZC  lubCtrl+D w innych systemach operacyjnych+. -amiętajmy, że dla ko0ca pliku unkcja cinget( 

zwraca wartoś" ! dla zasygnalizowania ko0ca pliku. 1eśli bież!cy znak jest wykrzyknikiem,

zostaje odrzucony i do buora wejściowego jest wstawiany znak dolara; zostanie on odczytany jako następny znak ła0cucha. 1eśli bież!cy znak nie jest wykrzyknikiem, zostaje wydrukowany./ażdy znak w buorze jest sprawdzany za pomoc! unkcji pee( i jeśli jest to znak #, zostaje

usunięty.

 @ie jest to najbardziej eektywny spos%b wykonania tego zadania 'nie usunie znaku #, gdy będzie

on pierwszym znakiem wprowadzonego ła0cucha+, ale ilustruje spos%b działania tych metod. @ies! one wykorzystywane zbyt często i nie łam sobie głowy, pr%buj!c na siłę wymyśli" jakieś ich

zastosowanie. -otraktuj je jako swego rodzaju sztuczk ię ; by" może kiedyś do czegoś się przydadz!.

RA0A unk&je pee(  i putbac(  są z"$kle u*$"ane do rzet"arzania ła,&u&+!" i

inn$&+ dan$&+# na rz$kład "ted$# gd$ &+&em$ st"orz$% komilator.

W$j(&ie orzez &out&biektu cout, wraz z przeci!żonym operatorem wstawiania '<<+, używaliśmy do wypisywania na

ekranie ła0cuch%w, liczb całkowitych i innych danych. (stnieje także możliwoś" ormatowania

Page 20: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 20/42

wypisywanych danych, wyr%wnywania kolumn i wypisywania danych numerycznych w postacidziesiętnej i szesnastkowej. <szystkie te zagadnienia opiszemy w tym podrozdziale.

*rzucanie zawarto(ci bufora

-rzekonaliśmy się, że użycie endl powoduje zrzucenie zawartości buora. endl wywołuje

unkcję składow! flush( obiektu cout, kt%ra wypisuje wszystkie dane znajduj!ce się w

 buorze. Junkcję flush( można wywoływa" bezpośrednio, albo poprzez wywołanie metody

obiektu, albo poprzez napisanie

cout << flush

-rzydaje się to wtedy, gdy chcemy mie" pewnoś", że buor wyjściowy jest pusty i że jego

zawartoś" została wypisana na ekranie.

Po"iązane 'unk&jeDziałanie operatora ekstrakcji może by" rozszerzone unkcjami get( i getline(; operator

wstawiania także może by" uzupełniony unkcjami put( oraz rite(.

Junkcja put( służy do wysyłania pojedynczego znaku do urz!dzenia wyjściowego. -onieważ

unkcja ta zwraca reerencję do obiektu klasy ostream i ponieważ cout jest obiektem tej klasy,

możemy ł!czy" wywołanie unkcji put( z wywołaniami operatora wstawiania. (lustruje to

listing 78.7I.

Fisting 78.7I. Cżycie unkcji put(  !: isting $%$! ' 6)cie func?i put(  $:+: #include <iostream>

  ,:-: int main(

  .: 0  /:std::coutput(PGPput(PePput(PlPput(PlPput(PoPput(P7nP;  %: return !;  2: 8

Wynik Gello

Page 21: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 21/42

UWAGA2iekt!re komilator$ mają roblem z "$is$"aniema znak!" za omo&ą o"$*szegokodu. )e(li t"!j komilator nie "$isze sło"a Gello# mo*esz ominą% ten listing.

Analiza

Finia K. jest przetwarzana w następuj!cy spos%b std::coutput(PGP wypisuje na ekranie

literę G i zwraca obiekt cout. 6o pozostawia nam

coutput(PePput(PlPput(PlPput(PoPput(P7nP;

<ypisana zostaje litera e, pozostawiaj!c coutput(PlP. -roces się powtarza wypisane zostaj!

litery i zwracany jest obiekt cout, aż do chwili wypisania ko0cowego znaku 'P7nP+, po czym

unkcja ko0czy działanie.

Junkcja rite( działa podobnie jak operator wstawiania '<<+, ale przyjmuje parametr

określaj!cy maksymaln! iloś" znak%w, jaka może zosta" wypisana. 1ej użycie pokazuje listing78.77.

Fisting 78.77. Cżycie unkcji rite(  !: isting $%$$ ' 6)cie func?i rite(  $: #include <iostream>  +: #include <stringh>  ,: using namespace std;  -:.: int main(

  /: 0  %: char Jne= L "J ?eden most za daleo";  2:3: int fullength L strlen(Jne;

 $!: int toohort L fullength '-; $$: int tooong L fullength 9 /; $+:$,: coutrite(JneFfullength << "7n"; $-: coutrite(JneFtoohort << "7n"; $.: coutrite(JneFtooong << "7n"; $/: return !; $%: 8

Wynik J ?eden most za daleoJ ?eden most za daJ ?eden most za daleo XY Z

UWAGAW t"oim komuterze "$nik mo*e "$gląda% nie&o ina&zej.

Analiza

Page 22: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 22/42

< linii 8. jest tworzona pojedyncza raza. < linii M. zmienna fullength 'pełna długoś"+ zostaje

ustawiona na długoś" razy, zmienna toohort 'zbyt kr%tka+ zostaje ustawiona na długoś"

 pomniejszon! o cztery, zaś zmienna tooong 'zbyt długa+ zostaje ustawiona na wartoś"

fullength plus sześ".

< linii 7>., za pomoc! unkcji rite(, zostaje wypisana cała raza. Długoś" została ustawionazgodnie z aktyczn! długości! razy, więc wydruk jest poprawny.

< linii 7?. raza jest wypisywana ponownie, lecz tym razem jest o cztery znaki kr%tsza niż pełnawersja, co odzwierciedla kolejna linia wyniku.

< linii 7A. raza jest wypisywana jeszcze raz, ale tym razem unkcja rite( ma wypisa" o sześ"

znak%w za dużo. -o wypisaniu razy wypisane zostaj! znaki odpowiadaj!ce wartościom sześciu bajt%w z pamięci położonej bezpośrednio za raz!.

3aniulator$# zna&zniki oraz instruk&je'ormato"ania

trumie0 wyjściowy posiada kilka znacznik%w stanu, określaj!cych aktualnie używany system

liczbowy 'dziesiętny lub szesnastkowy+, szerokoś" wypisywanych p%l oraz znak używany dowypełniania p%l. Znacznik stanu jest bajtem, kt%rego poszczeg%lne bity posiadaj! określoneznaczenia. pos%b operowania bitami zostanie opisany w rozdziale =7. /ażdy ze znacznik%wklasy ostream może by" ustawiany za pomoc! unkcji składowych i manipulator%w.

"#ycie cout)width%&Domyślna szerokoś" wydruku niku umożliwia zmieszczenie w jej obrębie wypisywanej liczby,znaku lub ła0cucha znajduj!cego się w buorze wyjściowym. Bożna j! zmieni", używaj!c unkcjiidth(. -onieważ idth( jest unkcj! składow!, musi by" wywoływana z użyciem obiektu

cout. Zmienia ona szerokoś" jedynie następnego wypisywanego pola, po czym natychmiast

 przywraca ustawienia domyślne. 1ej użycie ilustruje listing 78.7=.

Fisting 78.7=. Dostosowywanie szerokości wydruku niku  !: isting $%$+ ' 4ostoso)anie szerooTci )druu  $: #include <iostream>  +: using namespace std;  ,:-: int main(

  .: 0  /: cout << "tart >";  %: coutidth(+.;  2: cout << $+, << "< [oniec7n";  3:$!: cout << "tart >";

Page 23: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 23/42

 $$: coutidth(+.; $+: cout << $+,<< "< astepn) >"; $,: cout << -./ << "< [oniec7n"; $-:$.: cout << "tart >"; $/: coutidth(-;

 $%: cout << $+,-./ << "< [oniec7n"; $2:$3: return !; +!: 8

Wynik tart > $+,< [oniectart > $+,< astepn) >-./< [oniectart >$+,-./< [oniec

Analiza

-ierwsze wyjście 'linie od K. do G. kodu+ wypisuje liczbę $+, w polu, kt%rego szerokoś" zostałaustawiona na =A w linii 8.. &dzwierciedla to pierwsza linia wyniku.

Drugie wyjście najpierw wypisuje liczbę $+, w polu o szerokości ustawionej na =A znak%w, po

czym wypisuje wartoś" -./. Zauważ, że wartoś" -./ jest wypisywana w polu o szerokości

umożliwiaj!cej precyzyjne zmieszczenie tej liczby; jak wspomniano, unkcja idth( odnosi się

wył!cznie do następnego wypisywanego pola.

&statnia linia wyniku pokazuje, iż ustawienie szerokości mniejszej niż wymagana oznaczaustawienie szerokości wystarczaj!cej na zmieszczenie wypisywanego ła0cucha.

"stawianie znak!wu wypełnieaniaZwykle obiekt cout wypełnia puste pola 'powstałe w wyniku wywołania unkcji idth(+

spacjami, tak jak widzieliśmy w poprzednim przykładzie. #zasem zdarza się jednak, że chcemy

wypełni" ten obszar innymi znakami, na przykład gwiazdkami. < tym celu możemy wywoła"unkcję fill(, jako argument przekazuj!c jej znak, kt%rego chcemy uży" jako znaku

wypełnieania. -okazuje to listing 78.7>.

Fisting 78.7>. Cżycie unkcji fill(  !: isting $%$, ' 6)cie func?i fill(  $:+: #include <iostream>

  ,: using namespace std;  -:.: int main(

  /: 0  %: cout << "tart >";  2: coutidth(+.;  3: cout << $+, << "< [oniec7n"; $!:

Page 24: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 24/42

 $$:$+: cout << "tart >"; $,: coutidth(+.; $-: coutfill(P*P; $.: cout << $+, << "< [oniec7n"; $/: return !;

 $%: 8

Wynik tart > $+,< [oniectart >**********************$+,< [oniec

Analiza

Finie od 8. do M. stanowi! powt%rzenie poprzedniego przykładu. Finie od 7=. do 7A. takżestanowi! powt%rzenie, ale tym razem, w linii 7?., jako znak wypełniania zostaje wybranagwiazdka, co odzwierciedla druga linia wyniku.

+unkcja setf%&

&biekt iostream pamięta sw%j stan dzięki przechowywanym znacznikom. Bożemy je ustawia",

wywołuj!c unkcję setf( i przekazuj!c jej jedn! z predeiniowanych stałych wyliczeniowych.

&biekty posiadaj! stan wtedy, gdy kt%raś lub wszystkie z ich danych reprezentuj! warunki, kt%remog! ulega" zmianom podczas działania programu.

 @a przykład, możemy określi", czy maj! by" wyświetlane zera ko0cowee 'tak by =I.II nie zostałoobcięte do =I+. :by wył!czy" zera ko0cowe, wywołaj setf(ios::shopoint.

tałe wyliczeniowe należ! do zakresu klasy iostream 'ios+ i w zwi!zku z tym s! stosowane z

 pełn! kwaliikowan! nazw! w postaci ios::naza\znacznia, na przykład ios::shopoint.

Cżywaj!c ios::shopos można wł!czy" wyświetlanie znaku plus '9+ przed liczbami dodatnimi.

Z kolei do wyr%wnywania wyniku służ! stałe ios::left 'do lewej strony+, ios::right 'do

 prawej+ lub ios::internal 'znak wypełnieania jest wstawiany między prze znakiem

 przedrostkiem oznaczaj!cym system a liczb!+.

Cstawiaj!c znaczniki, możemy także wybra"ustawi" system dla wypisywanych liczb jako

dziesiętny 'stała ios::dec+, %semkowy 'o podstawie osiem, stała ios::oct+ lub szesnastkowy

'o podstawie szesnaście, stała ios::he]+. 6e znaczniki mog! by" także ł!czone z operatorem

wstawiania. Cstawienia te ilustruje listing 78.7?. Dodatkowo, listing ten pokazuje także

zastosowanie manipulatora set, kt%ry ustawia szerokoś" pola, ale może by" przy tym ł!czony z

operatorem wstawiania.

Fisting 78.7?. Cżycie unkcji setf(  !: isting $%$- ' 6)cie func?i setf(  $: #include <iostream>  +: #include <iomanip>  ,: using namespace std;  -:

Page 25: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 25/42

  .: int main(  /: 0  %: const int number L $2.;  2: cout << "iczba to " << number << endl;  3:$!: cout << "iczba to " << he] << number << endl;

 $$:$+: coutsetf(ios::shobase; $,: cout << "iczba to " << he] << number << endl; $-:$.: cout << "iczba to " ; $/: coutidth($!; $%: cout << he] << number << endl; $2:$3: cout << "iczba to " ; +!: coutidth($!; +$: coutsetf(ios::left; ++: cout << he] << number << endl; +,:+-: cout << "iczba to " ; +.: coutidth($!; +/: coutsetf(ios::internal;

 +%: cout << he] << number << endl; +2:+3: cout << "iczba to:" << set($! << he] << number << endl; ,!: return !; ,$: 8

Wynik iczba to $2.iczba to b3iczba to !]b3iczba to !]b3iczba to !]b3iczba to !] b3iczba to:!] b3

Analiza

< linii 8. stała typu int zostaje zainicjalizowana wartości! $2.. 6a wartoś" zostaje wypisana w

linii G.

<artoś" jest wyświetlana ponownie w linii 7I., ale tym razem w poł!czeniu z manipulatorem he],

kt%ry powoduje, że wartoś" ta jest wypisywana w systemie szesnastkowym 'jako b3+.

'zesnastkowa cyra b odpowiada dziesiętnej liczbie $$. 1edenaście razy szesnaście r%wna się

$%/; po dodaniu 3 otrzymujemy wartoś" $2..+

< linii 7=. zostaje ustawiony znacznik shobase. -owoduje on, że do wszystkich liczb

szesnastkowych zostaje dodany przedrostek !] 'co wida" w kolejnych liniach wyniku+.

< linii 7K. szerokoś" pola zostaje ustawiona na dziesię" znak%w, a wypisywana wartoś" jestwyr%wnywana do prawej strony pola. < linii =I. szerokoś" także zostaje ustawiona na dziesię"znak%w, ale tym razem wypisywana liczba zostaje wyr%wnana do lewej strony.

Page 26: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 26/42

< linii =A. szerokoś" także zostaje ustawiona na dziesię" znak%w, ale tym razem zostajezastosowany znacznik internal. < zwi!zku z tym przedrostek '!]+ jest wypisywany po lewej

stronie, a sama wartoś" 'b3+ po prawej.

 @a koniec, w linii =M. do ustawienia szerokości dziesięciu znak%w zostaje użyty poł!czony

operator ł!czenia 'konkatenacji+ set(, po czym wartoś" jest wypisywana ponownie.

Strumienie kontra 'unk&ja rint'45<iększoś" implementacji #$$ posiada standardowe biblioteki wejścia*wyjścia z języka #,zawieraj!ce między innymi unkcję printf(. #ho" unkcja ta może by" łatwiejsza w użyciu niż

obiekt cout, jednak jej użycie nie jest zalecane.

Junkcja printf( nie zapewnia bezpiecze0stwa typ%w, więc łatwo jest przypadkowo nakaza" jej

wypisanie wartości całkowitej jako znaku, i odwrotnie. Junkcja ta nie obsługuje klas, więc nie mamożliwości poinormowania jej jak ma wypisywa" dane klasy; trzeba jej przekazywa" kolejno

wszystkie wartości, kt%re maj! zosta" wypisane.

-onieważ korzysta z tej unkcji duża iloś" starszego kodu, w tym podrozdziale pokr%tce om%wimy jej działanie. :by m%c skorzysta" z tej unkcji, musisz pamięta" o doł!czeniu do kodu pliku

nagł%wkowego stdio.h. < swojej najprostszej ormie unkcja printf( przyjmuje jako pierwszy

 parametr ła0cuch ormatuj!cy, zaś jako następne parametry serię wartości.

Na0cuch ormatuj!cy jest ujętym w cudzysłowy ła0cuchem znak%w, zawieraj!cym specyikatorykonwersji. <szystkie specyikatory konwersji musz! zaczyna" się od symbolu procent%w '^+.

 @ajczęściej stosowane specyikatory zostały zebrane w tabeli 78.7.

6abela 78.7. -owszechnie stosowane specyikatory konwersjipecyikator Zastosowanie

^s <ypisywanie ła0cuch%w.

^d <ypisywanie liczb całkowitych.

^ld <ypisywanie długich liczb całkowitych.

^lgd <ypisywanie wartości typu double.

^f <ypisywanie wartości typu float.

/ażdy ze specyikator%w konwersji może zawiera" pole szerokości oraz pole precyzji,

 przedstawiane jako wartoś" zmiennoprzecinkowa, w kt%rej cyry po lewej stronie kropkidziesiętnej oznaczaj! całkowit! szerokoś" pola, a cyry po prawej stronie punktu dziesiętnegooznaczaj! dokładnoś" zapisu liczb zmiennopozycyjnych. 6ak więc specyikator ^.d określa

szerok! na pię" cyr liczbę całkowit!, a ^$..f jest specyikatorem dla szerokiej na piętnaście

Page 27: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 27/42

cyr wartości typu float, w kt%rej na części dziesiętn! ma zosta" przeznaczone pię" ostatnich

cyr. 9%żne zastosowania unkcji printf( przedstawia listing 78.7A.

Fisting 78.7A. Drukowanie z użyciem unkcjiprintf(  !: $%$. 4ruoanie z u)ciem func?i printf(

  $: #include <stdioh>  +:,: int main(

  -: 0  .: printf("^s"F"Wita? siecie7n";  /:%: char *phrase L "Wita? pononieM7n";

  2: printf("^s"Fphrase;  3:$!: int ] L .; $$: printf("^d7n"F]; $+:$,: char *phraseKo L "Jto ila artosci: "; $-: char *phraseKhree L " i ?eszcze te: "; $.: int ) L %F z L ,.;

 $/: long longVar L 32-./; $%: float floatVar L 22f; $2:$3: printf("^s ^d ^d"FphraseKoF)Fz; +!: printf("^s ^ld ^f7n"FphraseKhreeFlongVarFfloatVar; +$:++: char *phrase5our L "formatoane: "; +,: printf("^s ^.d ^$!d ^$!.f7n"Fphrase5ourF)FzFfloatVar; +-:+.: return !; +/: 8

Wynik Wita? siecie

Wita? pononieM.Jto ila artosci: % ,. i ?eszcze te: 32-./ 22!!!!!formatoane: % ,. 22!!!!

Analiza

-ierwsza instrukcja printf(, zawarta w linii A., używa ormy standardowej nazwy printf, po

kt%rej następuje ujęty w cudzysłowy ła0cuch ze specyikatorem konwersji 'w tym przypadku ^s+,

a po nim wartoś", kt%ra ma zosta" wstawiona w miejsce specyikatora konwersji.

pecyikator ^s wskazuje, że jest to ła0cuch, a wartości! ła0cucha w tym przypadku jest ujęte w

cudzysłowy "Wita? siecie".

Druga instrukcja printf( jest podobna do pierwszej, ale tym razem jako drugi parametr unkcji

został użyty wska2nik do typu char, a nie stała ła0cuchowa.

6rzecia instrukcja printf(, w linii 77., używa specyikatora konwersji dla liczb całkowitych,

zaś wstawian! wartości! jest zmienna całkowita ]. #zwarta instrukcja printf(, w linii 7M., jest

Page 28: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 28/42

 już bardziej skomplikowana. ! w niej ł!czone trzy wartości. Dla każdej z nich istniejespecyikator konwersji, a odpowiednie wartości s! przekazywane jako rozdzielone przecinkami

kolejne parametry unkcji.

 @a koniec, w linii =>. specyikatory konwersji zostaj! użyte do określenia szerokości i

dokładności. 1ak wida", jest to nieco łatwiejsze niż używanie manipulator%w.

<spomnieliśmy wcześniej o ograniczenie unkcji printf(, kt%re polega na braku kontroli

typ%w. &pr%cz tego, unkcji printf( nie można zadeklarowa" jako unkcji zaprzyja2nionej lub

unkcji składowej klasy. < zwi!zku z tym, gdy chcemy wypisywa" r%żne dane składowe klasy,musimy jawnie przekazywa" każdy z akcesor%w klasy do unkcji printf(.

6zsto zada"ane $tanie

6z$ mo*esz odsumo"a% sosob$ maniulo"ania "$j(&iem

8do"ied9 4se&jalne odziko"ania dla Roberta ran&isa5 Ab$ s'ormato"a% "$j(&ie " 6::#nale*$ u*$% kombina&ji znak!" se&jaln$&+# maniulator!" "$j(&ia oraz zna&znik!".

Poni*sze znaki se&jalne są dołą&zane do "$j(&io"ego ła,&u&+a "$s$łanego do cout  za

omo&ą oeratora "sta"iania;

7n < no"a linia

7r < o"r!t karetki

7t < tabulator 

77 < le"$ uko(nik

7oddd 4li&zba !semko"a5 < znak AS6//

7a < alarm 4s$gnał d9"iko"$5.

2a rz$kład;

Page 29: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 29/42

cout << "7aW)stQpiA bAQdM7t"

o"oduje o"stanie s$gnału d9"iko"ego# "$isanie komunikatu błdu oraz rzej(&ie donastnego tabulatora. 3aniulator$ są u*$"ane z obiektem cout. 3aniulator$ rz$jmują&e

argument$ "$magają dołą&zenia liku nagł!"ko"ego iomani n p do liku standardo"ego.

8to lista maniulator!"# kt!re nie wymagają  liku iomanip;

flush < zrzu&a bu'or "$j(&io"$

endl < "sta"ia znak no"ej linii i zrzu&a bu'or "$j(&io"$

oct < usta"ia s$stem "$is$"an$&+ li&zb na !semko"$

dec < usta"ia s$stem "$is$"an$&+ li&zb na dziesitn$

he] < usta"ia s$stem "$is$"an$&+ li&zb na szesnastko"$.

8to lista maniulator!" wymagających liku iomanip;

setbase(base  < usta"ia s$stem li&zbo"$ 4= > dzies(ietn$# ? > !semko"$# 1= > dziesitn$#

1@ > szesnastko"$5

set(idth < usta"ia minimalną szeroko(% ola

setfill(ch < usta"ia znak "$ełniania ust$&+ obszar!" ola

setprecision(p < usta"ia dokładno(% "$is$"ania li&zb zmiennooz$&$jn$&+

setiosflags(f < usta"ia jeden lub "i&ej zna&znik!" ios

resetiosflags(f < rz$"ra&a stan jednego lub "i&ej zna&znik!" ios.

Page 30: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 30/42

2a rz$kład;

cout << set($+ << setfill(P#P << he] << ] << endl;

usta"ia szeroko(% ola na d"ana(&ie znak!"# usta"ia znak "$ełniania na P#P# nakazuje

"$is$"anie li&zb " s$stemie szesnastko"$m# "$isuje "arto(% zmiennej ]# umiesz&za "bu'orze znak no"ej l inii i zrzu&a za"arto(% bu'ora. Wsz$stkie maniulator$# z "$jątkiem flush#

endl  oraz set# obo"iązują a* do "ro"adzenia ja"nej zmian$ lub ko,&a rogramu.

0om$(lna "arto(% maniulatora set jest rz$"ra&ana o "$konaniu bie*ą&ego cout.

Wraz z maniulatorami setiosflags  oraz resetiosflags mogą b$% u*$"ane oni*sze

zna&zniki ios;

ios::left < "$r!"nuje "$nik do le"ej stron$ ola

ios::right < "$r!"nuje "$nik do ra"ej stron$ ola

ios::internal < znak lub rzedrostek zostaje "$r!"nan$ do le"ej# a li&zba do ra"ej

ios::dec < dziesitn$ s$stem li&zbo"$

ios::oct < !semko"$ s$stem li&zbo"$

ios::he] < szesnastko"$ s$stem li&zbo"$

ios::shobase < dodaje rzedrostek !]  do li&zb szesnastko"$&+ i rzedrostek ! do li&zb

!semko"$&+

ios::shopoint < dodaje zera ko,&o"e# zgodnie z "$maganą dokładno(&ią 

ios::uppercase < l iter$ " li&zba&+ szesnastko"$&+ i " "arto(&ia&+ "$("ietlan$&+ " zaisie

in*$nierskim "$kładni&z$m są "$("ietlane jako "ielkie

ios::shopos < rzed "arto(&iami dodatnimi jest "$("ietlan$ znak lus

Page 31: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 31/42

ios::scientific  < li&zb$ zmiennorze&inko"eoz$&$jne  są "$("ietlane " zaisie

in*$nierskim "$kładni&z$m

ios::fi]ed < li&zb$ zmiennorze&inko"eoz$&$jne są "$("ietlane " zaisie dziesitn$m.

0odatko"e in'orma&je na ten temat mo*na znale9% " liku ios  oraz " dokumenta&jikomilatora.

Wej(&ie i "$j(&ie z u*$&iem lik!"trumienie zapewniaj! jednolity spos%b obsługi danych przychodz!cych z klawiatury lub ztwardego dysku oraz wychodz!cych na ekran lub do twardegoy dysk u. < każdym z powyższych przypadk%w możemy korzysta" z operator%w wstawiania i ekstrakcji lub innych, powi!zanych znimi unkcji i manipulator%w. Do otwarcia i zamknięcia pliku należy uży" obiekt%w typuifstream i ofstream, kt%rych działanie om%wimy w kilku następnych podrozdziałach.

o'stream-oszczeg%lne obiekty używane do odczytu z pliku lub zapisu do pliku s! nazywane obiektamiofstream. ! one wyprowadzone z używanych przez nas dot!d obiekt%w iostream.

:by rozpocz!" zapis do pliku, musimy najpierw stworzy" obiekt typu ofstream, a następnie

 powi!za" go z konkretnym plikiem na dysku. :by m%c używa" obiekt%w typu ofstream, do

kodu należy doł!czy" plik nagł%wkowy fstream.h.

UWAGA Ponie"a* lik fstream.h dołą&za lik iostream.h# nie ma otrzeb$ ja"nego dołą&zaniatego drugiego liku.

Page 32: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 32/42

,tany strumieni&biekty typu iostream przechowuj! znaczniki określaj!ce stan wejścia i wyjścia. Bożemy je

sprawdza" za pomoc! logicznych unkcji eof(, bad(, fail( oraz good(. Junkcja eof( 

zwraca wartoś" true, gdy obiekt typu iostream napotkał koniec pliku. Junkcja bad( zwracawartoś" true, gdy pr%bujemy wykona" niedozwolon! operację. Junkcja fail(zwraca wartoś"

true, gdy unkcja bad( zwraca wartoś" true lub operacja się nie powiodła. @a koniec, unkcja

good( zwraca wartoś" true, gdy wszystkie trzy pozostałe unkcje zwracaj! wartoś" false.

'twieranie plik!w dla wej(cia i wyj(cia:by otworzy" plik myfile.cpp z obiektem typu ofstream, deklarujemy egzemplarz obiektu typu

ofstream i jako parametr przekazujemy mu nazwę pliku

ofstream fout("m)filecpp";

&twarcie tego pliku do odczytu wygl!da podobnie, ale wykorzystujemy w tym celu obiektifstream

ifstream fin("m)filecpp";

Zwr%" uwagę na użyte nazwy, fout oraz fin; nazwa fout została użyta w celu zwr%cenia uwagi

na podobie0stwo z cout, a nazwa fin w celu wykazania podobie0stwa do nazwy cin.

1edn! z ważnych unkcji strumieni zwi!zanych z plikami, jest unkcja close(. /ażdy tworzony

obiekt strumienia otwiera plik albo do zapisu, albo do odczytu, albo do obu tych operacji. -ozako0czeniu zapisywania lub odczytywania danych należy zamkn!" plik unkcj! close(; to

zapewnia, że plik nie zostanie uszkodzonye i że zawarte w buorze dane zostan! zrzucone na dysk.

3dy obiekty strumieni plik%w zostan! już powi!zane z plikami na dysku, mog! zosta" użyte taksamo jak wszystkie inne obiekty strumieni. (lustruje to listing 78.7K.

Fisting 78.7K. &twieranie plik%w do odczytu i zapisu  !: isting $%$/ Jtieranie pliC do odcz)tu i zapisu  $: #include <fstream>  +: #include <iostream>  ,: using namespace std;  -:.: int main(

  /: 0  %: char fileame2!=;  2: char buffer+..=; dla dan)ch u)tonia  3: cout << "aza pliu: "; $!: cin >> fileame; $$:

Page 33: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 33/42

 $+: ofstream fout(fileame; otieram) do zapisu $,: fout << "Ka linia ?est zapisana bezposrednio do pliu7n"; $-: cout << "Wpisz test dla pliu: "; $.: cinignore($FP7nP; odrzucam) zna noe? linii po naziepliu $/: cingetline(bufferF+..; odcz)tu?em) dane proadzone

przez u)tonia $%: fout << buffer << "7n"; i zapisu?em) ?e do pliu $2: foutclose(; zam)am) pli; bRdzie gotC dopononego otarcia $3:+!: ifstream fin(fileame; pononie otieram) pli doodcz)tu +$: cout << "Jto zaartosc pliu:7n"; ++: char ch; +,: hile (finget(ch +-: cout << ch; +.:+/: cout << "7n***[oniec zaartosci pliu***7n"; +%:+2: finclose(; dbaAoTS zasze popAaca +3: return !;

 ,!: 8

Wynik aza pliu: test$Wpisz test dla pliu: Ken test zostal zapisan) do pliuMJto zaartosc pliu:Ka linia ?est zapisana bezposrednio do pliuKen test zostal zapisan) do pliuM

***[oniec zaartosci pliu***

Analiza

< linii 8. zostaje przygotowany buor przeznaczony na nazwę pliku, zaś w linii G. został przygotowany buor przeznaczony na dane wprowadzane przez użytkownika. < linii M.użytkownik jest proszony o podanie nazwy pliku, a wprowadzona przez niego nazwa jestumieszczana w buorze fileame. < linii 7=. zostaje stworzony obiekt typu ofstream o nazwie

fout, kt%ry jest wi!zany z now! nazw! pliku. 6o powoduje otwarcie pliku; jeśli plik istniał już

wcześniej, jego zawartoś" zostaje usunięta.

< linii 7>. do pliku zostaje bezpośrednio zapisany ła0cuch znak%w. < linii 7?. użytkownik jest proszony o wpisanie danych. Znak ko0ca linii pozostały po wpisaniu przez użytkownika nazwy pliku jest odrzucany w linii 7A., po czym w linii 7K. następne dane wpisane przez użytkownika s!umieszczane w buorze. Dane te s! w linii 78. zapisywane do pliku wraz ze znakiem nowej linii, po czym w linii 7G. następuje zamknięcie pliku.

< linii =I. plik jest otwierany ponownie, tym razem w trybie do odczytu danych, po czym wliniach =>. i =?. jego zwartoś" jest odczytywana i wypisywana na ekranie 'każdy znakwypisywany jest osobno+.

Page 34: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 34/42

*miana domy(lne$o zachowania obiektu ofstreamw trakcie otwierania pliku

Domyślnym działaniem wykonywanym przy otwieraniu pliku jest stworzenie pliku, gdy jeszczenie istnieje, lub obcięcie pliku 'tj. usunięcie całej jego zawartości+, gdy już istnieje. 3dy takie

zachowanie domyślne nie jest poż!dane, możemy jawnie przekaza" drugi argument dokonstruktora obiektu typu ofstream.

Dostępne argumenty to

• ios::app O powoduje doł!czenie danych do ko0ca istniej!cego pliku, bez usuwania

istniej!cych w pliku danych.

• ios::ate O umieszcza nas na ko0cu pliku, ale możemy zapisywa" dane w dowolnym

miejscu pliku.

• ios::trunc O argument domyślny. -owoduje usunięcie zawartości istniej!cego pliku.

• ios::nocreate O jeśli plik nie istnieje, otwarcie się nie powiedzie.

• ios::noreplace O jeśli plik już istnieje, otwarcie się nie powiedzie.

Dla ciekawych nazwa app pochodzi od słowa append  'dołącz +, ate od at end  'na kocu+ oraz

trunc od truncate 'o!etni"+. Fisting 78.78 ilustruje użycie doł!czania 'append+ przez otwarcie

 pliku stworzonego w listingu 78.7K i dopisanie do niego dalszej treści.

Fisting 78.78. Dopisywanie do ko0ca pliku  !: isting $%$% 4opis)anie do oBca pliu  $: #include <fstream>  +: #include <iostream>  ,: using namespace std;  -:.: int main( zraca $ prz)padu bARdu

  /: 0  %: char fileame2!=;  2: char buffer+..=;  3: cout << "Drosze pononie pisac naze pliu: "; $!: cin >> fileame; $$:$+: ifstream fin(fileame; $,: if (fin cz) ?u istnie?e_ $-: 0 $.: cout << "`iezaca zaartosc pliu:7n"; $/: char ch; $%: hile (finget(ch

 $2: cout << ch; $3: cout << "7n***[oniec zaartosci pliu***7n"; +!: 8 +$: finclose(; ++:

Page 35: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 35/42

 +,: cout << "7nJtieranie " << fileame << " tr)biedopis)ania7n"; +-:+.: ofstream fout(fileameFios::app; +/: if (Mfout +%: 0

 +2: cout << "ie mozna otorz)c " << fileame << " dodopis)ania7n"; +3: return($; ,!: 8 ,$:,+: cout << "7nWpisz test dla pliu: "; ,,: cinignore($FP7nP; ,-: cingetline(bufferF+..; ,.: fout << buffer << "7n"; ,/: foutclose(; ,%:,2: finopen(fileame; pononie prz)pisu?em) istnie?ac)obiet finM ,3: if (Mfin -!: 0 -$: cout << "ie mozna otorz)c " << fileame << " do

odcz)tu7n"; -+: return($; -,: 8 --: cout << "7nJto zaartosc pliu:7n"; -.: char ch; -/: hile (finget(ch -%: cout << ch; -2: cout << "7n***[oniec zaartosci pliu***7n"; -3: finclose(; .!: return !; .$: 8

Wynik Drosze pononie pisac naze pliu: test$`iezaca zaartosc pliu:Ka linia ?est zapisana bezposrednio do pliuKen test zostal zapisan) do pliuM

***[oniec zaartosci pliu***

Jtieranie test$ tr)bie dopis)ania

Wpisz test dla pliu: Wiece? testu dla pliuM

Jto zaartosc pliu:Ka linia ?est zapisana bezposrednio do pliuKen test zostal zapisan) do pliuMWiece? testu dla pliuM***[oniec zaartosci pliu***

Analiza

Cżytkownik jest proszony o ponowne wpisanie nazwy pliku. 6ym razem w linii 7=. jest tworzonyobiekt strumienia wejściowego z pliku. <ynik otwierania jest sprawdzany w linii 7>. i jeśli plik

Page 36: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 36/42

istnieje, jego zawartoś" jest wypisywana w liniach od 7A. do 7M. Zwr%" uwagę, że if(fin jest

synonimem if(fingood(.

 @astępnie zamykany jest plik wejściowy; ten sam plik zostaje otwarty ponownie w linii =A., tymrazem w trybie dopisywania. -o tym otwarciu 'i wszystkich innych+ sprawdzamy, czy plik został

otwarty poprawnie. Zwr%" uwagę, że if(Mfout jest tym samym, co if(foutfail(.Cżytkownik jest proszony o wpisanie tekstu, kt%ry jest dopisywany do pliku. < linii >K. plikzostaje ponownie zamknięty.

 @a koniec, tak jak w listingu 78.7K, plik zostaje ponownie otwarty w trybie do odczytu. 1ednaktym razem obiekt fin nie musi by" deklarowany ponownie, jest mu po prostu przypisywana ta

sama nazwa pliku. < linii >M. ponownie następuje sprawdzenie poprawności otwarcia i gdywszystko jest w porz!dku, zawartoś" pliku zostaje wypisana na ekranie, a sam plik jest ostateczniezamykany.

6:/ @(L

prawdzaj każde otwarcie pliku, aby mie" pewnoś" że został on poprawnie otwarty.

-onownie wykorzystuj istniej!ce obiektyifstream lubo ofstream.

-o wykorzystaniu obiekt%w ofstream zamykaj

 je

 @ie pr%buj zamyka" lub ponownie przypisywa"

cin i cout.

Pliki binarne a liki teksto"e @iekt%re systemy operacyjne, takie jak D&, dokonuj! rozr%żnienia pomiędzy plikamitekstowymi a plikami binarnymi. -liki tekstowe 'jak można się domyśla"+ przechowuj! wszystko jako tekst, więc duże liczby, takie jak A? >=A s! przechowywane jako ła0cuchy cyr 'PAQ, P?Q, P>Q,P=Q, PAQ+. 6o może by" nieeektywne, ale ma tę zaletę, że tekst może zosta" odczytany przez proste

 programy, takie jak D&*owy program t)pe.

:by dopom%c systemowi plik%w w odr%żnieniu pliku tekstowego od binarnego, #$$ udostępniaznacznik ios::binar). < wielu systemach ten znacznik jest ignorowany, gdyż wszystkie dane

s! przechowywane w postaci binarnej. < jeszcze innych systemach znacznik ten jestniedozwolony i uniemożliwia skompilowanie programuR

-liki binarne mog! przechowywa" nie tylko liczby i ła0cuchy, ale także całe struktury danych.Bożna do nich zapisywa" wszystkie dane jednocześnie, używaj!c metody rite( klasy

fstream.

3dy użyjemy metody rite(,do odczytania zapisanych danych możemy uży" unkcji read(.

/ażda z tych unkcji oczekuje wska2nika do znaku, więc adres obiektu trzeba rzutowa" na do 

wska2nik a do znaku.

Page 37: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 37/42

Drugim argumentem obu unkcji jest iloś" znak%w do zapisu lub odczytu, kt%r! można wyznaczy"za pomoc! unkcji sizeof(. -amiętaj, że zapisywane s! tylko dane klasy, a nie jej metody.

&dczytywane s! także tylko dane. Zapis zawartości klasy do pliku ilustruje listing 78.7G.

Fisting 78.7G. Zapis zawartości klasy do pliku  !: isting $%$2 apis zaartoTci las) do pliu  $: #include <fstream>  +: #include <iostreamh>  ,: using namespace std;  -:.: class Unimal

  /: 0  %: public:  2: Unimal(int eightFlongda)s:itsWeight(eightF4a)sUliIe(da)s08  3: Unimal(08 $!:$$: int OetWeight(const 0 return itsWeight; 8 $+: Ioid etWeight(int eight 0 itsWeight L eight; 8 $,:$-: long Oet4a)sUliIe(const 0 return 4a)sUliIe; 8 $.: Ioid et4a)sUliIe(long da)s 0 4a)sUliIe L da)s; 8 $/:$%: priIate: $2: int itsWeight; $3: long 4a)sUliIe; +!: 8; +$:++: int main( zraca $ prz)padu bARdu +,: 0 +-: char fileame2!=; +.:+/:+%: cout << "Drosze pisac naze pliu: "; +2: cin >> fileame; +3: ofstream fout(fileameFios::binar);

 ,!: if (Mfout ,$: 0 ,+: cout << "ie mozna otorz)c " << fileame << " dozapisu7n"; ,,: return($; ,-: 8 ,.:,/: Unimal `ear(.!F$!!; ,%: foutrite((char* &`earFsizeof `ear; ,2:,3: foutclose(; -!:-$: ifstream fin(fileameFios::binar); -+: if (Mfin -,: 0 --: cout << "ie mozna otorz)c " << fileame << " do

odcz)tu7n"; -.: return($; -/: 8 -%:-2: Unimal `earKo($F$; -3:

Page 38: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 38/42

 .!: cout << "`earKoOetWeight(: " << `earKoOetWeight( <<endl; .$: cout << "`earKoOet4a)sUliIe(: " << `earKoOet4a)sUliIe(<< endl; .+:.,: finread((char* &`earKoF sizeof `earKo;

 .-:..: cout << "`earKoOetWeight(: " << `earKoOetWeight( <<endl; ./: cout << "`earKoOet4a)sUliIe(: " << `earKoOet4a)sUliIe(<< endl; .%: finclose(; .2: return !; .3: 8

Wynik Drosze pisac naze pliu: Unimals`earKoOetWeight(: $`earKoOet4a)sUliIe(: $`earKoOetWeight(: .!

`earKoOet4a)sUliIe(: $!!

Analiza

< liniach od A. do =I. została zadeklarowana okrojona klasa Unimals. < liniach od =?. do >?.

zostaje stworzony plik otwarty do zapisu w trybie binarnym. < linii >K. zostaje stworzony obiekt,

kt%rego waga zostaje ustawiona na AI, a wiek na 7II dni. Dane zawarte w tym obiekcie zostaj! wlinii >8. zapisane do pliku.

< linii >M. plik jest zamykany, a w linii ?7. ponownie otwierany do odczytu w trybie binarnym. <

linii ?G. tworzony jest drugi obiekt klasy Unimal, o wadze 7 i wieku wynosz!cym tylko jeden

dzie0. < linii A>. do nowego obiektu odczytywane s! dane z pliku, zastępuj!c istniej!ce daneobiektu danymi odczytanymi z pliku.

Przet"arzanie linii ole&enia<iele system%w operacyjnych, takich jak D& czy C@(, umożliwia użytkownikowi przekazywanie parametr%w do programu podczas jego uruchamiania. -arametry te s! nazywaneopcjami linii polecenia i zwykle s! oddzielone od siebie spacjami. @a przykład

omeDrogram Daram$ Daram+ Daram,

6e parametry nie s! przekazywane bezpośrednio do unkcji main(, zamiast tego unkcja main(każdego programu otrzymuje dwa parametry. -ierwszym jest iloś" parametr%w w linii polecenia'parametr typu int+. @azwa pliku także jest wliczana do ilości parametr%w, więc każdy program

Page 39: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 39/42

 posiada co najmniej jeden parametr. -rzedstawiona powyżej przykładowa linia polece0 zawieracztery parametry 'nazwa programu, omeDrogram, plus trzy parametry daje cztery argumenty

wywołania programu+.

Drugim parametrem przekazywanym do unkcji main( jest tablica wska2nik%w do ła0cuch%w

znak%w. -onieważ nazwa tablicy jest stałym wska2nikiem do pierwszego elementu tablicy,możemy zadeklarowa" ten wska2nik jako wska2nik do wska2nika do typu char, jako wska2nik do

tablicy element%w char lub jako wska2nik do tablicy tablic element%w char.

Zwykle pierwszy argument ma nazwę argc 'ar#ument count , iloś" argument%w+, ale możesz

nazwa" go tak, jak chcesz. Drugi argument często nosi nazwę argI 'ar#ument $ector , wektor

argument%w+, ale to także tylko konwencja.

Zwykle sprawdza się wartoś" parametru argc, aby upewni" się, czy program otrzymał

oczekiwan! iloś" argument%w, a następnie poprzez argI odwołuje się do samych ła0cuch%w

 parametr%w. -amiętaj, że argI!= jest nazw! programu, a argI$= jest jego pierwszym

 parametrem, reprezentowanym przez ła0cuch. 1eśli argumentami programu maj! by" liczby,należy je zamieni" z ła0cuch%w na wartości numeryczne. < rozdziale =7. zobaczymy, jak możnawykorzysta" w tym celu standardowe unkcje biblioteczne konwersji. pos%b korzystania zargument%w linii polecenia przedstawia listing 78.7M.

Fisting 78.7M. Cżywanie argument%w linii polecenia  !: isting $%$3 6)anie argumentC linii polecenia  $: #include <iostream>  +: int main(int argcF char **argI  ,: 0  -: std::cout << "Jtrz)mano " << argc << " argumento7n";  .: for (int iL!; i<argc; i99  /: std::cout << "argument " << i << ": " << argIi= <<std::endl;  %: return !;  2: 8

Wynik KestDrogram Keach ourself 99 1n +$ 4a)sJtrz)mano % argumentoargument !: KestDrograme]eargument $: Keachargument +: ourselfargument ,: 99argument -: 1nargument .: +$argument /: 4a)s

UWAGA3usisz uru&+omi% ten kod albo z linii ole&e, 4tj. z okna 08S-a5 lub usta"i% arametr$linii ole&enia " komilatorze 4zajrz$j do dokumenta&ji s"ojego komilatora5.

Page 40: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 40/42

Analiza

Junkcja main( deklaruje dwa argumenty argc jest zmienn! całkowit! zawieraj!c! iloś"

argument%w linii polecenia, a argI jest wska2nikiem do tablicy ła0cuch%w. /ażdy ła0cuch w

tablicy wskazywanej przez argI jest jednym argumentem linii polecenia. Zauważ, że argI 

mogłoby r%wnie łatwo zosta" zadeklarowane jako char *argI= lub char argI==. 1est tozależne wył!cznie od stylu programowania. nawet mimo iż w< tym programie, mimo iż argI 

zostało zadeklarowane jako wska2nik do wska2nika, to jednak do dostępu do poszczeg%lnychkolejnych ła0cuch%w 'będ!cych argumentami z linii polece0+ odwołujemy się jakdo nadal s! wykorzystywane element%wy tablicy.

< linii ?. argument argc zostaje wykorzystany przy wypisywaniu ilości argument%w linii

 polecenia siedem, wliczaj!c w to nazwę programu.

< liniach A. i K. zostaje wypisany każdy z argument%w linii polecenia; do cout przekazywane s!zako0czone zerem ła0cuchy znak%w pobierane z tablicy ła0cuch%w.

Sardziej popularne zastosowanie argument%w linii polecenia zostało przedstawione na listingu78.=I, powstałym w wyniku zmodyikowania listingu 78.7G tak, by program odczytywał nazwę

 pliku z linii polecenia.

Fisting 78.=I. Cżycie argument%w linii polecenia  !: isting $%+! 6)cie argumentC linii polecenia  $: #include <fstream>  +: #include <iostream>  ,: using namespace std;  -:.: class Unimal

  /: 0  %: public:  2: Unimal(int eightFlongda)s:itsWeight(eightF4a)sUliIe(da)s08  3: Unimal(08 $!:$$: int OetWeight(const 0 return itsWeight; 8 $+: Ioid etWeight(int eight 0 itsWeight L eight; 8 $,:$-: long Oet4a)sUliIe(const 0 return 4a)sUliIe; 8 $.: Ioid et4a)sUliIe(long da)s 0 4a)sUliIe L da)s; 8 $/:$%: priIate: $2: int itsWeight; $3: long 4a)sUliIe; +!: 8; +$:++: int main(int argcF char *argI= zraca $ prz)padu bARdu +,: 0 +-: if (argc ML + +.: 0 +/: cout << "6z)cie: " << argI!= << " <naza\pliu>" << endl;

 +%: return($; +2: 8 +3:,!: ofstream fout(argI$=Fios::binar); ,$: if (Mfout ,+: 0

Page 41: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 41/42

 ,,: cout << "ie mozna otorz)c " << argI$= << " dozapisu7n"; ,-: return($; ,.: 8 ,/:,%: Unimal `ear(.!F$!!;

 ,2: foutrite((char* &`earFsizeof `ear; ,3:-!: foutclose(; -$:-+: ifstream fin(argI$=Fios::binar); -,: if (Mfin --: 0 -.: cout << "ie mozna otorz)c " << argI$= << " doodcz)tu7n"; -/: return($; -%: 8 -2:-3: Unimal `earKo($F$; .!:.$: cout << "`earKoOetWeight(: " << `earKoOetWeight( <<endl;

 .+: cout << "`earKoOet4a)sUliIe(: " << `earKoOet4a)sUliIe(<< endl; .,:.-: finread((char* &`earKoF sizeof `earKo; ..:./: cout << "`earKoOetWeight(: " << `earKoOetWeight( <<endl; .%: cout << "`earKoOet4a)sUliIe(: " << `earKoOet4a)sUliIe(<< endl; .2: finclose(; .3: return !; /!: 8

Wynik `earKoOetWeight(: $`earKoOet4a)sUliIe(: $`earKoOetWeight(: .!`earKoOet4a)sUliIe(: $!!

Analiza

Deklaracja klasy Unimal jest taka sama jak na listingu 78.7G. 6ym razem jednak zamiast prosi"

użytkownika o nazwę pliku, wykorzystujemy argument linii polecenia. < linii ==. unkcja main(została zadeklarowana jako przyjmuj!ca dwa parametry iloś" argument%w linii polecenia orazwska2nik do tablicy ła0cuch%w tych argument%w.

< liniach od =?. do =G. program sprawdza, czy otrzymał wymagan! iloś" argument%w 'dokładnie

dwa+. 1eśli użytkownik nie poda pojedynczej nazwy pliku, zostanie wypisany komunikat błędu

6z)cie KestDrogram <naza\pliu>

Page 42: R17-06.DOC

7/18/2019 R17-06.DOC

http://slidepdf.com/reader/full/r17-06doc 42/42

 @astępnie program ko0czy działanie. Zwr%" uwagę, że używaj!c argI!= zamiast sztywno

określonej nazwy programu, możemy skompilowa" ten program tak, aby przyjmował dowoln!nazwę i by była ona automatycznie wyświetlana w tym komunikacie.

< linii >I. program pr%buje otworzy" wskazany plik do zapisu binarnego. @ie ma powodu, by

kopiowa" nazwę pliku do tymczasowego buora lokalnego, gdyż można bezpośredniowykorzysta" argument argI$=.

6a technika zostaje powt%rzona w linii ?=., gdzie ten sam plik zostaje otwarty do odczytu; a takżew liniach >>. i ?A., w kt%rych wypisywane s! komunikaty błęd%w otwarcia pliku.