Strumienie wejścia i wyjścia¶
Biblioteka strumieni wejścia i wyjścia pozwala na pobieranie i wysyłanie sformatowanych i niesformatowanych zbuforowanych tekstów i wartości liczbowych. Definicje narzędzi związanych ze strumieniami wejścia i wyjścia znajdują się w nagłówkach <istream>
, <ostream>
, itp.
Strumień ostream
konwertuje mające typy obiekty na strumienie znaków (bajtów).
Strumień istream
konwertuje strumienie znaków (bajtów) na obiekty o określonych typach.
Strumień iostream
może służyć zarówno jako istream
, jak i ostream
. Widoczne na schematach bufory to „bufory strumieniowe” (streambuf).
Istnieją trzy standardowe strumienie wejścia i wyjścia:
cout
- standardowy strumień wyjściowy znaków (często domyślnie jest nim ekran),cin
- standardowy strumień wejściowy znaków (często domyślnie jest nim klawiatura),cerr
- standardowy strumień wyjściowy błędów (nie ma bufora).
Hierarchia strumieni wejścia i wyjścia¶
Strumień istream
można połączyć w urządzeniem wejściowym (np. klawiaturą), plikiem lub łańcuchem. Analogicznie strumień ostream
można połączyć z urządzeniem wyjściowym (np. oknem tekstowym), plikiem lub łańcuchem.
Strumień można otworzyć za pomocą konstruktora lub wywołując funkcję open()
:
Typy strumieniowe¶
|
Tworzy pusty strumień z ustawionym trybem m |
---|---|
|
Tworzy strumień łańcuchowy zawierający łańcuch s w trybie m |
|
Tworzy strumień plikowy do otwarcia później |
|
Otwiera plik o nazwie s w trybie m i kieruje na niego strumień plikowy |
|
Otwiera plik o nazwie s w trybie m i ustawia fs, aby się do niego odwoływał |
|
Sprawdza, czy fs jest otwarty |
Dla strumieni plikowych nazwa pliku jest łańcuchem w stylu języka C.
Tryby strumieni¶
Pliki można otwierać w jednym z kilku trybów.
|
Dodawanie na końcu |
---|---|
|
Otwieranie i przechodzenie na koniec |
|
Tryb binarny. Uwaga na zachowanie charakterystyczne dla danego systemu |
|
Do odczytu |
|
Do zapisu |
|
Przycina plik do długości 0. |
Dokładny efekt otwarcia pliku może zależeć od systemu operacyjnego. Jeśli system nie może spełnić żądania otwarcia pliku w określonym trybie, powstanie strumień w trybie innym niż good()
.
Przykład:
void my_code(ostream& os); // Funkcja my_code może używać dowolnego strumienia wyjściowego
ostringstream os; // o oznacza output (wyjście)
ofstream of("my_file");
if (!of) error("Nie można otworzyć pliku 'my_file' w trybie zapisu.");
my_code(os); //Użycie łańcucha
my_code(of);
Obsługa błędów¶
Możliwe są cztery stany strumieni iostream
:
good()
– operacje zakończone sukcesemeof()
– napotkano koniec danych wejściowych (koniec pliku)fail()
– stało się coś nieprzewidzianego (np. szukano cyfry, a znaleziono znak «x»)bad()
– stało się coś nieprzewidzianego i poważnego (np. wystąpił błąd odczytu z dysku)
Za pomocą wywołania s.exceptions()
można zmusić strumienie iostream
do zgłaszania wyjątków, gdy przechodzą w stan inny niż good()
.
Operacje wykonywane na strumieniach w stanie innym niż good()
nie mają żadnego efektu.
Strumienia iostream
można użyć jako warunku . Prawdzie (sukcesowi) odpowiada stan good()
tego strumienia. Jest to podstawa popularnej techniki odczytywania strumieni wartości.
X x; // Bufor wejściowy do przechowywania jednej wartości typu X
while (cin>>x)
{
// Działania na x
}
// Tutaj przekazywane jest sterowanie, gdy operator >> nie może wczytać
// kolejnej wartości typu X ze strumieni cin
Operacje wejściowe¶
Prawie wszystkie operacje wejściowe znajdują się w nagłówku <istream>
. Wyjątkiem są operacje wczytywania danych do łańcuchów, które znajdują się w nagłówku <string>
.
Operacje do formatowanego wstawiania¶
|
Wczytuje do x dane z in zgodnie z typem x |
---|---|
|
Wczytuje wiersz tekstu z in do łańucha s |
Jeśli nie jest napisane inaczej, operacje strumieni wejściowych (istream) zwracają referencje do swoich strumieni, dzięki czemu można budować łańcuchy tych operacji, np. cin>>x>>y;
.
Operacje do nieformatowanego wstawiania¶
|
Wczytuje jeden znak z in i zwraca jego wartość całkowitoliczbową. |
---|---|
|
Wczytuje znak z in do c. |
|
Wczytuje najwyżej n znaków z in do tablicy, zaczynając od p |
|
Wczytuje najwyżej n znaków z in do tablicy, zaczynając od p. Argument t określa znak końcowy. |
|
Wczytuje najwyżej n znaków z in do tablicy, zaczynając od p. Usuwa znak końca z in. |
|
Wczytuje najwyżej n znaków z in do tablicy, zaczynając od p. Argument t określa znak końcowy. Usuwa znak końca z in. |
|
Wczytuje najwyżej n znaków z in do tablicy, zaczynając od p. |
|
x określa liczbę znaków wczytanych przez ostatnią operację bez formatowania na in. |
Funkcje get()
i getline()
wstawiają 0 na końcu ciągu znaków zapisanego w p[0]
.
Funkcja getline()
usuwa znak końca (t) z danych wejściowych, jeśli taki tam jest. Natomiast funkcja get()
tego nie robi. Funkcja read(p,n)
nie wstawia 0 do tablicy za wczytanymi znakami.
Sformatowane operatory wejściowe są łatwiejsze w użyciu i mniej podatne na błędy niż ich niesformatowane odpowiedniki.
Operacje wyjściowe¶
Prawie wszystkie operacje wyjściowe znajdują się w nagłówku <ostream>. Wyjątkiem są operacje wysyłania danych do łańcuchów, które znajdują się w nagłówku <string>
.
|
Zapisuje x w out zgodnie z typem x |
---|---|
|
Zapisuje znak c w out |
|
Zapisuje znaki p[0] ..p[n-1] w out |
Jeśli nie jest napisane inaczej, operacje strumieni wyjściowych (ostream
) zwracają referencje
do swoich strumieni, dzięki czemu można budować łańcuchy tych operacji, np. cin<<x<<y;
.
Formatowanie¶
O formacie strumieni wejścia i wyjścia decydują następujące czynniki:
typ obiektu,
stan strumienia,
informacje dotyczące lokalizacji (zobacz nagłówek
<locale>
)jawnie wykonywane operacje
Standardowe manipulatory¶
W bibliotece standardowej dostępne są manipulatory pozwalające na różne sposoby określać formatowanie. Definicje tych manipulatorów znajdują się w nagłówkach <ios>
, <istream>
, <ostream>
, <iostream>
oraz <iomanip>
(manipulatory pobierające argumenty).
|
Zamienia wartości logiczne true i false na ich reprezentację symboliczną (wejście i wyjście) |
---|---|
|
s.unsetf(ios_base::boolalpha) |
|
Powoduje dodanie przedrostka 0 do danych w formacie ósemkowym i 0x do danych w formacie szesnastkowym |
|
s.unsetf(ios_base:: showbase) |
|
Powoduje wyświetlenie przecinka dziesiętnego |
|
s.unsetf(ios_base:: showpoint) |
|
Dodaje znak + przed liczbami dodatnimi |
|
s.unsetf(ios_base:: showpos) |
|
Pomija białe znaki |
|
s.unsetf(ios_base:: skipws) |
|
Zamienia w numerycznych danych wyjściowych małe litery na wielkie, np. drukuje 1.2E10 i 0X1A2 zamiast 1.2e10 i 0x1a2 |
|
Wyświetli np. x i e, a nie X i E |
|
Dodaje znaki wypełnienia wewnątrz ciągu |
|
Dodaje znaki wypełnienia za wartością |
|
Dodaje znaki wypełnienia przed wartością |
|
Dziesiętna podstawa liczb całkowitych |
|
Szesnastkowa podstawa liczb całkowitych |
|
Ósemkowa podstawa liczb całkowitych |
|
Format dddd.dd liczb zmiennoprzecinkowych |
|
Format naukowy – d.ddddEdd |
|
Wstawia znak «n» i wywołuje flush |
|
Wstawia znak «0» |
|
Opróżnia strumień |
|
Zjada białe znaki |
|
Usuwa znaczniki f |
|
Ustawia znaczniki f |
|
Drukuje na wyjściu liczby całkowite w formacie o podstawie b |
|
Ustawia c jako znak wypełniający |
|
Ustawia precyzję na n cyfr |
|
Ustawia szerokość następnego pola na n znaków |
Wszystkie te operacje zwracają referencje do swojego pierwszego argumentu (strumienia) – s.
Na przykład:
cout << 1234 << ',' << hex << 1234 << ',' << oct << 1234 << endl;
zwróci poniższy wynik:
1234,4d2,2322
Natomiast poniższy kod:
cout << '(' << setw(4) << setfill('#') << 12 << ") (" << 12 << ")\n";
zwróci:
(##12) (12)
Aby bezpośrednio ustawić ogólny format wyjściowy liczb rzeczywistych, należy napisać poniższy kod:
b.setf(ios_base::fmtflags(0), ios_base::floatfield);