PARADYGMATY PROGRAMOWANIA Wykład 6 Wejście wyjście strumieniowe stdin standardowy strumień wejściowy stdout standardowy strumień wyjściowy stderr standardowy strumień komunikatów o błędach pliki - inne źródła wejścia / wyjścia programu plik jest uporządkowanym strumieniem bajtów Trybu zapisu / odczytu ze strumieni binarny strumień jest nieinterpretowanym przez procedury zapisu/odczytu ciągiem bajtów tekstowy zakłada się, że strumień jest zapisem ciągu znaków pisarskich (znak może składać się z więcej niż jednego bajtu zależnie od systemu kodowania), procedury wejścia / wyjścia mogą dokonywać konwersji pomiędzy postacią binarną a ustaloną postacią tekstową Ogólne zasady wykorzystywania strumieni w programach Strumienie, z których chce korzystać program są dla programisty reprezentowane przez obiekty specjalnie do tego celu zaprojektowanych klas. stdin jest reprezentowany za pomocą predefiniowanego obiektu o nazwie cin stdout jest reprezentowany za pomocą predefiniowanego obiektu o nazwie cout Strumienie (z wyjątkiem standardowych) muszą być przed użyciem otwarte Przyjęto konwencję, że dla klas reprezentujących strumienie definiuje się operatory wejścia ( >> ) i wyjścia ( >> ) o następujących cechach: lewym operandem jest referencja do strumienia, prawym operandem jest obiekt lub l-wyrażenie typu prostego, który jest żródłem danych dla operacji,
wartością operatora jest referencja do strumienia przekazanego jako lewostronny operand wówczas można wielokrotnie używać operatorów << lub >> w jednym wyrażeniu. Przeciążone operatory << i >> są zdefiniowane dla typów wbudowanych (int, char, char*, double float ) oraz dla niektórych typów definiowanych w bibliotekach standardowych (np. dla typu string). Dla klas definiowanych przez programistę może on zdefiniować operator << i >> w sposób specyficzny dla swojego typu danych. Hierarchia klas do obsługi wejścia wyjścia strumieniowego cin obiekt klasy istream cout obiekt klasy ostream Operacje na plikach: ifstream (input file stream) klasa pozwalająca na odczyt z pliku ofstream (output file stream) klasa pozwalająca na zapis do pliku fstream - klasa pozwalająca na odczyt i zapis w pliku Operacje na ciągach znaków pozwalają traktować bufory znakowe jak strumienie, w szczególności można w ten sposób dokonywać konwersji danych pomiędzy postacią znakową i binarną. Strumienie są buforowane nie ma pewności, że wykonanie operatora wyjścia << spowoduje natychmiastowe pojawienie się danych na urządzeniu fizycznym.
metoda flush() - wymusza opróżnienie bufora i zapis danych do urządzenie: cout.flush(); Działanie operatora odczytu >> w odniesieniu do danych typu char * (łańcuchy znaków) operator odczytuje dane z pominięciem poprzedzających białych znaków (spacja, tabulacja, nowa linia) i kończy odczytywanie po napotkaniu pierwszego białego znaku po "nie-białym" wniosek nie można odczytywać napisów zawierających białe znaki metoda get pozwala odczytać łańcuch z białymi znakami istream & get( char &c); odczyt pojedynczego znaku istream & get( char *buf, int n, char term = '\n' ); odczytuje nie więcej niż n-1 znaków do bufora buf, kończy po napotkaniu znaku term, znak kończący nie jest odczytywany i pozostaje w strumieniu, znak '\0' jest zapisywany w buforze istream & getline(); podobnie jak get ale znak nowej linii jest usuwany ze strumienia lecz nie trafia do bufora W przypadku osiągnięcia końca strumienia ( Ctrl-Z ) funkcje zwracają referencję pustą (NULL) char c; while (cin.get( c )!= NULL) printf("%d\n", c ); while (cin.get( buf, 50 )!= NULL) printf("%s\n", buf ); // BŁĄD zapetlenie programu Przeciążanie operatorów << i >> dla typów zdefiniowanych przez programistę class compl friend ostream & operator << ( ostream & out_strm, compl nmb ); friend istream & operator >> ( istream & out_strm,
compl & nmb ); private: double re, im; ; public: compl( double re = 0.0, double im = 0.0 ); void set_re ( double re ); void set_im( double im ); ostream & operator << ( ostream & out_strm, compl nmb ) out_strm << nmb.re << " " << nmb.im ; return out_strm; istream & operator >> ( istream & in_strm, compl & nmb ) in_strm >> nmb.re >> nmb.im ; return in_strm; Sprawdzanie statusu strumienia: class ios public: enum is_state( goodbit, eofbit, failbit, badbit ); int bad() const; // wystąpił błąd int eof() const; // osiągnięto koniec pliku int fail() const; // wystąpił błąd nie utracono danych int good() const; // następna operacja może się powiesc //... ; Badanie stanu za pomoca metod bad(), eof(), fail(), good() za pomoca metody io_state rdstate(); Formatowanie i manipulatory manipulator obiekt modyfikujący sposób działania operatorów strumieniowych manipulatory z parametrami zdefiniowane w pliku nagłówkowym iomanip.h określanie formatu liczby całkowitej
oct ósemkowy, hex szesnastkowy dec dziesiętny UWAGA: konwersji poddawana jest wartość kodu U2 liczby, np hex dla 1 -> ffffffff oct dla 1 -> 37777777777 określanie szerokości pola setw( int width ) określa szerokośc pola na wyświetlenie następnej danej setfill( char filler = ' ' ) określa znak wypełniający pole obowiązuje aż do odwołania setprecision ( int precision = 6 ) określenie ilości miejsc po przecinku dla liczb zmiennoprzecinkowych Operacje na plikach wymagają włączenia pliku fstream (bez.h konwencja nazywania plików nagłówkowych w C++) oraz uaktywnienia przestrzeni nazw std #include <fstream> using namewspace std; Deklaracja zmiennej plikowej: fstream file; otwarcie pliku metoda open void open( const char *s, ios_base::openmode mode = ios_base::in ios_base::out ); np. file.open( "c:\\test.txt", ios::out ios::app )... file.close(); Tryby otwarcia: in, out, app, trunc nocreate, noreplace, binary, ate Operacje binarne: write( char *buffer, int size ); read( char *buffer, int size );
Pozycjonowanie w pliku class ios enum seek_dir (beg, curr, end ); istream seekg( int rel_pos, seek_dir d = ios::beg ); int tellg(); ostream seekp( int rel_pos, seek_dir d = ios::beg ); int tellp(); Operacje wejscia-wyjscia w pamięci: strumień może być symulowany w pamięci w tablicy znakowej (lub za pomocę typu string) wszystkie operacje które moga byc wykonywane na ostream moga być też wykonane na ostrstream, Podobnie dla istream i istrstream istrstream::istrstream( char * buf, int size ); ostrstream::istrstream( char * buf, int size ); #include <iostream> using namespace std ; #include <iomanip> #include <strstream> // <--- bo uzywamy ostrstream #include <sstream> // <-- bo uzywamy ostringstream /*******************************************************/ int main() int nr_silnika = 4 ; float temperat = 156.7123 ; char komunikat[80] ; ostrstream strumyk(komunikat, sizeof(komunikat) ); // strumyk << "Awaria silnika "<< setw(2) << nr_silnika << ", temperatura oleju " << setprecision(2) << temperat << " stopni C \n" ; // cout << komunitat; strumyk.seekp(8, ios_base::beg); // strumyk << "XYZ" ; cout << "Po zabawie z pozycjonowaniem :\n" << komunikat ;
// ##################### NOWY STYL ######################" ostringstream strumyk2; // strumyk2 << "Awaria silnika "<< setw(2) << nr_silnika << ", temperatura oleju " << setprecision(2) << temperat << " stopni C \n" ; // if(!strumyk2) cout << "jakis blad "<< endl; strumyk2 << "Musisz cos zrobic!!!\n" << ends ; // cout << strumyk2.str() <, endl; strumyk2.seekp(8, ios_base::beg); // strumyk2 << "XYZ" ; cout << "Po zabawie z pozycjonowaniem :\n" << strumyk2.str() ;