Wejście – wyjście strumieniowe

Transkrypt

Wejście – wyjście strumieniowe
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,
ostrstream::istrstream( char * buf,
int size );
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() ;
}
//
//

Podobne dokumenty