Lekcja 9: Strumienie i operacje wejścia/wyjścia
Strumienie - czym są i jakie są ich rodzaje
Strumienie można sobie wyobrazić jako dane płynące od źródła do celu. Zarówno cele, jak i źródła strumienia mogą być różne - może to być ekran, klawiatura, plik lub jakieś inne zewnętrzne urządzenie.
W języku C++ wyróżniamy trzy typy strumieni: strumienie wejściowe (wczytują dane), strumienie wyjściowe (wypisują dane) oraz strumienie uniwersalne, umożliwiające zarówno wczytywanie, jak i wypisywanie danych.
Strumieniami posługujemy się wówczas, gdy chcemy przeprowadzić jakiekolwiek operacje wejścia/wyjścia. W przedstawionych programach takie operacje przeprowadzaliśmy wielokrotnie - wiele razy pobieraliśmy dane z klawiatury i wiele razy wypisywaliśmy dane na ekran. W tym celu posługiwaliśmy się właśnie strumieniami.
Musisz sobie zdawać sprawę, że strumienie w języku C++ są ogromnym ułatwieniem. Nie raz wypisywaliśmy już zmienne na ekran i zmienna została wypisywana zawsze poprawnie. Tak naprawdę wszystkie dane, które strumień wypisuje na ekran muszą zostać sformatowane . Jeśli wypisujemy liczbę float, to liczba zostaje wypisana jako liczba float. Taka sama sytuacja jest przy pobieraniu danych.
Jeśli wydaje Ci się to czymś oczywistym, to musisz wiedzieć, że wypisywanie i pobieranie danych w języku C, czyli poprzedniku języka C++ nie było wcale takie łatwe. Tam musieliśmy za każdym razem określić, w jaki sposób ma zostać wypisana dana zmienna - czy mamy wypisać zmienną jako liczbę całkowitą, znak czy może napis. Sprawiało to, że to programista musiał dbać o to, czy dane zostaną wypisane poprawnie - w języku C++ na szczęście przy zwykłym wypisywaniu nie musimy się tym martwić.
Dla przykładu, aby wypisać liczbę typu float, w C++ piszemy:
cout << zmienna;
Z kolei w języku C musieliśmy dołączyć bibliotekę stdio.h i zrobić to w następujący sposób:
printf("%f",zmienna);
Strumienie predefiniowane
Strumienie predefiniowane to strumienie stworzone dla Ciebie i gotowe do korzystania. Gdyby nie istniały, trzeba by je było stworzyć samemu, co niewątpliwie nie było by zbyt łatwym zadaniem. Aby skorzystać ze strumieni predefiniowanych należy dołączyć bibliotekę iostream - jak widzisz w każdym programie do tej pory właśnie dołączaliśmy tę bibliotekę.
W języku C++ istnieją cztery strumienie predefiniowane:
cout - powiązany ze standardowym urządzeniem wyjścia
cin - powiązany ze standardowym urządzeniem wejścia
cerr - strumień błędów - połączony ze standardowym urządzeniem wyjścia
clog - podobnie jak cerr, ale wydajniejszy przy wielu danych
Jak więc widzisz każdy ze strumieni ma jakieś przeznaczenie. To, że strumień jest powiązany ze standardowym urządzeniem wyjścia, oznacza w większości wypadków, że jest połączony z ekranem. Z kolei to, że strumień jest powiązany ze standardowym urządzeniem wejścia, oznacza, że jest on powiązany z klawiaturą.
Na szczęście język C++ jest na tyle elastyczny, że możemy zmieniać powiązanie każdego z predefiniowanych strumieni. Zazwyczaj wiąże się strumień cerr lub clog z plikiem na dysku. Pozostałych powiązań raczej się nie zmienia, chociaż jest to możliwe i niekiedy wygodne.
Nas oczywiście najbardziej interesują dwa pierwsze strumienie: strumień wyjściowy cout oraz strumień wejściowy cin. Z tych strumieni korzystaliśmy już nie raz.
Operatory << i >>
Wiesz już czym są strumienie. Same strumienie jednak nam nie wystarczą. Aby móc przeprowadzić jakąkolwiek operację na strumieniach korzystamy z następujących operatorów:
<< - operator wysyłania do strumienia
>> - operator pobierania ze strumienia
W praktyce będzie to oznaczało, że jeśli chcemy coś wypisać, używamy operatora <<. Natomiast gdy chcemy pobrać dane, użyjemy operatora >>. Można zatem sobie zapamiętać, że piszemy cout << oraz cin >>.
Dodatkowe informacje dotyczące strumieni
Jak już udało Ci się zaobserwować w programach, za jednym razem możemy wypisać tylko jedną daną lub ich kilka. Na przykład fragment:
cout <<zmienna1;
cout <<' ';
cout <<zmienna2;
cout <<'\n';
możemy bez problemu zastąpić takim krótszym zapisem:
cout <<zmienna1<<' '<<zmienna2<<'\n';
Na tej samej zasadzie możemy łączyć kilka danych podczas pracy z każdym innym strumieniem, zarówno wejściowym, jak i wyjściowym.
Oprócz tego warto zwrócić uwagę na pewne domyślne ustawienia strumieni. Jest ich bardzo wiele i na tym etapie kursu chcę Ci jedynie zasygnalizować istnienie takich ustawień.
Otóż strumienie mają zdefiniowanych bardzo wiele standardowych parametrów. Na przykład liczby zmiennopozycyjne zostają wypisane z dokładnością 6 miejsc po przecinku. Jeśli chcemy wypisać liczbę z większą liczbą miejsc po przecinku, będziemy musieli to strumieniowi zasygnalizować.
Podobnie rzecz się ma w przypadku pobierania danych z urządzenia. Na przykład wszystkie białe znaki znajdujące się przed pobieranymi danymi są ignorowane. Ponadto za koniec danych uznawany jest pierwszy biały znak. Dlatego też nie uda nam się tak łatwo wczytać zdania: "Ala ma kota.". Zostanie wczytane tylko pierwsze słowo. Natomiast drugie słowo zostanie uznane za zupełnie nową daną, co może mieć katastrofalne skutki.
Takich domniemań w pracy strumieni jest naprawdę bardzo wiele. Na razie założymy, że jesteśmy zadowoleni ze standardowych ustawień i przejdziemy do ważniejszych kwestii w języku C++.
Podsumowanie
Dzięki tej lekcji udało Ci się zrozumieć, w jaki sposób można pobierać dane i je wypisywać. Teraz wiesz już czym są strumienie i zdajesz sobie sprawę, że istnieje bardzo wiele opcji umożliwiających zmianę domyślnych ustawień w pracy strumieni, które postaram Ci się przedstawić w odpowiednim momencie.