16.2 Operatory << i >>
Czym są operatory '<<' i '>>'?
Pamiętamy z
rozdziału o operatorach ,
że na przykład instrukcja '
a + b' interpretowana jest tak
naprawdę jako wywołanie funkcji dodającej, a wartości wyrażeń
a
i
b, po ewentualnej konwersji, są do tej funkcji
przesyłane jako argumenty.
Podobnie jest dla operatorów '<<' i '>>'. Ich użycie
powoduje wywołanie odpowiedniej funkcji dwuargumentowej, przy czym
jako argumenty przesyłana jest do niej referencja do
obiektu-strumienia występującego po lewej stronie i wartość
wyrażenia po prawej stronie operatora. Funkcja ta jest przeciążona;
wybór konkretnej wersji zależy od typu prawego argumentu.
Tak więc dla typów wbudowanych (i wielu bibliotecznych) działanie
operatora jest dobrze określone; dla typów definiowanych przez
programistę można samemu dostarczyć dodatkowe wersje, co
zademonstrujemy w
rozdziale o przeciążeniach .
Bardzo ważne jest to, że funkcja wywoływana przez użycie operatora
'<<' lub '>>' jest funkcją rezultatową: prócz
wykonania samej operacji we/wy, zwraca jako rezultat referencję
do tego samego obiektu-strumienia, który był jej pierwszym (lewym)
argumentem. Zatem w
(cout << x) << y;
wartość wyrażenia w nawiasie jest równoważna
cout,
które w ten sposób staje się ponownie lewym argumentem kolejnego
operatora '<<'. Ponieważ wiązanie operatora '<<'
jest lewe, więc użycie nawiasów w powyższym przykładzie nie
jest konieczne; uzyskujemy dzięki temu możliowość „kaskadowego”
wywołania odpowiednich funkcji:
cout << x << y << z << v << endl;
lub
cin >> x >> y >> z >> v;
gdzie, jak pamiętamy, kierunek „strzałek” można rozumieć jako
kierunek przepływu informacji.
Aby wyprowadzić, na ekran czy do pliku, napis reprezentujący
na przykład wartość zmiennej typu
double, trzeba przyjąć
jakąś umowę co do sposobu formatowania. Sposób ten, jak się
przekonamy, można zmieniać.
Domyślnie zmienne typów wbudowanych są wyprowadzane zgodnie z
następującymi domniemaniami:
Strumienie wyjściowe:
- wartości całościowe (jak
int,
short, itd.):
w systemie dziesiątkowym;
- wartości znakowe: jako pojedyncze znaki;
- wartości zmiennopozycyjne (czyli
float,
double
i
long double): w systemie dziesiątkowym, z
precyzją 6 cyfr. Precyzja oznacza liczbę cyfr znaczących,
a nie liczbę cyfr po kropce dziesiętnej. Na przykład,
wypisanie w formacie domyślnym liczby 200.0/3
daje 66.6667, a nie 66.666667. Końcowe zera po kropce
dziesiętnej nie są pisane. Tak więc wartość 1.129996
zostanie najpierw zaokrąglona do sześciu cyfr znaczących,
dając 1.13000, a następnie wypisana jako 1.13 (ale na
przykład wydruk 1.129994 da 1.12999).
Jeśli po kropce wystąpiłyby same zera,
to opuszczane są i zera, i sama kropka dziesiętna.
Jeśli liczba cyfr przed kropką wynosi lub przekracza
sześć, to wypisane zostaną wszystkie, a część
ułamkowa zostanie pominięta;
- wartości wskaźnikowe (prócz typu
char*):
jako dodatnie liczby całkowite reprezentujące adresy w
pamięci. Adresy wypisywane są w układzie szesnastkowym,
a więc z prefiksem '0x';
- wartości wskaźnikowe typu
char*: jako napisy,
interpretując kolejne bajty w pamięci, poczynając od bajtu
wskazywanego przez wskaźnik, jako zapis kolejnych znaków
napisu; wypisywanie kończy się po napotkaniu bajtu zerowego
(odpowiadającego znakowi końca napisu '
\0');
- wartości logiczne (typu
bool): jako liczby 1 i 0.
Strumienie wejściowe:
- wiodące białe znaki są pomijane;
- każda następna niepusta sekwencja białych znaków
jest interpretowana jako koniec danych. Znaki te pozostają
w buforze i będą pominięte, jako wiodące, przy następnym
czytaniu;
- liczby całkowite wczytywane są w postaci
dziesiętnej; pierwszym niebiałym znakiem może
być znak '+' lub '-', następnie wczytywane są cyfry
aż do napotkania znaku nie
będącego cyfrą — ten znak jest pozostawiany w buforze
i będzie pierwszym znakiem wczytanym przez następną
operację czytania. Na przykład, jeśli program czyta
za pomocą instrukcji 'cin >> x >> y',
to można podać jako dane 128-25; wczytywanie 128 na
x
zakończy się na znaku minus, który pozostanie
w strumieniu. Następnie będzie kontynuowane czytanie
na
y
znaków -25;
- liczby zmiennopozycyjne wczytywane są w
formacie liczb całkowitych bez kropki dziesiętnej,
w formacie z kropką dziesiętną i w notacji
„naukowej” (na przykład 1e-1 to to samo co 0.1,
1.201e+2 to 120.1);
- wartości logiczne mają postać literałów 1 i 0.
T.R. Werner, 21 lutego 2016; 20:17