Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

C++ Streams Input og Output med C++ Standard Biblioteket.

Liknende presentasjoner


Presentasjon om: "C++ Streams Input og Output med C++ Standard Biblioteket."— Utskrift av presentasjonen:

1 C++ Streams Input og Output med C++ Standard Biblioteket

2 Sammenheng •Hva gjør Streams? –Input/output –Formattering av tall, datoer, etc. –Utskrift av objekter –Transparent håntering av forskjellige kilder •Hvilken annen funksjonalitet finnes for dette? –printf, wfprintfn, tsprintf, etc. –strftime –scanf

3 Hva gir Streams? •Uniform håntering av argumenter •Typesikkerhet •Transparent håntering av kilde og destinasjon –Konsol I/O –Streng –Fil –Egendefinerte (f.eks. Nettverk, eller DebugStream) •Automatisk minnehåntering/bufferhåntering •Intergrasjon med Locales

4 Uniform håntering av argumenter { MyClass obj; struct tm timeNow; char const* myString; int myNumber; std::cout << obj << ” litt tekst ” << timeNow << ”mer tekst ” << myString << myNumber << std::endl; }

5 Typesikkerhet printf("%d\n", int_variable); // correct printf("%f\n", double_variable); // correct printf("%d\n", double_variable); // outputting an int, but a double value is supplied printf("%f\n", int_variable); // outputting a double, but an int value is supplied printf(”%s\n”, string(”Hello world”)); // outputting a string, but an object is supplied scanf("%d", &int_variable); // correct scanf("%d", int_variable); // oops! left out the ampersand! scanf("%lf", &int_variable); // oops! reading a floating-point value into an integer! scanf(”%s”, &string_variable); // oops! reading into object

6 Kildeuavhengighet •Gjøres ved hjelp av stream-buffer klasser •En istream/ostream kan assosieres med en vilkårlig stream-buffer klasse •Dersom ingen buffer-klasse passer, kan man lage sin egen •fstream- og stringstream-klassene bruker kun constructor til å angi en fil-buffer •En streambuffer hånterer minne selv •En stream brukes på samme måte uavhengig av buffer

7 Eksempel { std::ofstream logFile(”LogFile.txt”); streambuf oldBuf = cout.rdbuf(logFile.rdbuf()); // Bruk cout som normal. Output vil komme // til LogFile.txt fila // Reset buffer cout.rdbuf(oldBuf); }

8 Formattering operator > Manipulatorer Locales

9 operator<< og operator<< •Operator<< brukes til å skrive ut verdier •Operator>> brukes til å lese verdier ofstream os(”outfile.txt”); ifstream is(”infile.txt”); int a = 14, b = 20; string str(”Hello world”); os << a << ” + ” << b << ” = ” << a+b << endl; os << str << endl; is >> a >> b >> b;

10 Operator overloading • > er overloaded for alle argumenter vi ønsker å skrive ut • > har presendens mellom +/- og <, <=, etc –os << a + b  os << (a + b), men –os << a < b  (os << a) < b, som er feil •<< er venstre-assosiativ –os << a << b << c  ((os << a) << b) << c  op<<(op<<(op<<(os, a), b), c) –Dette fungerer fordi op<<(os, a) returnere en referanse til os

11 Definere egne operatorer •Man kan overloaded operator > for å lage lesing og skriving av en klasse.

12 Eksempel: VARIANT 1.wostream& operator<<(wostream& os, VARIANT const& arg) { 2.CComVariant var(arg);// Lager en kopi vi kan endre 3.os << L"(";// Skriver ut ’(’ på begynnelsen 4. 5.if ( var.vt & VT_ARRAY ) {// Kaller ny funk. for array 6.PrintArray(var.vt, var.parray, os); 7.} else if ( var.vt == VT_RECORD ) { 8.PrintRecord(var, 0, os); // Kall ny funk for record 9.} else if ( FAILED(var.ChangeType(VT_BSTR)) ){ 10.os "; // Ingen behandling 11.} else if ( var.bstr == NULL ) { 12.os << _T(”’’”); // Tom streng 13.} else { // Vi har nå konvertert verdien til en bstring 14.os << L"'" << var.bstr << L"'"; 15.} 16.os << _T(" [") << VarTypeToString(arg.vt) << _T("])"); 17.return os; 18.}

13 Manipulatorer •I tillegg til tekst, kan man sende manipulatorer til en strøm •Manipulatorer endrer ofte oppførsel til strømmen, eller har andre sideeffekter •Eksempler på manipulatorer fra –endl – skriver ut en newline og flusher buffer –Setw, setfill – setter bredden og fill for numre –Boolalpha – skriver ”true” og ”false” for bool –Setprecision – setter presisjon for flyttall –Fixed, scientific – setter notasjon for flyttall

14 Output formattering •Integers: –os << setw(4) << setfill(’0’) << 8  ”0008” –os << setbase(16) << showbase <<  ”0x ” (E_FAIL) •Bools –os << boolalpha << true  ”true” –os << noboolalpha << true  ”1” •Floating points –os << scientific <<  ” e3” –os << fixed << setprecision(2) << PI  ”3.14”

15 Manipulatorer •Uten argumenter –En funksjon med profil ostream& f(ostream&) er automatisk en manipulator –Eks: tostream& GetLastError(tostream& os); •Med argumenter –Må være en klasse med args som constructor- argumenter og operator << definert

16 Eksempel: Format struct Format // Uses FormatMessage API to decode error code { Format(HRESULT hr) : m_hr(hr) {} friend ostream& operator<<(ostream& os, Format const& self) { LPSTR lpBuf = 0; DWORD nRetval = FormatMessage(..., NULL, self.m_hr, 0, (LPSTR)&lpBuf, 0, NULL); if ( nRetval != 0 ) { // FormatMessage var vellykket os << lpBuf; LocalFree(lpBuf); } else { // FormatMessage feilet os << "Error " << showbase << setbase(0x10) << self.m_hr << endl; } return os; } private: HRESULT m_hr; }; cout << Format(E_NOTIMPL) << std::endl; //  ”Not implemented” cout << Format(0x ) << std::endl; //  ”Error 0x ”

17 Eksempel: GetLastError ostream& GetLastError(ostream& os) { DWORD nStatus = ::GetLastError(); if ( nStatus == 0 ) return os; // no error occured os << "Error code : " << nStatus << ". "; os << "Error text : " << Format(nStatus) << std::endl; return os; } // Bruk os << GetLastError << std::endl; // Mangler med Format (finnes i WinStream.cpp i f.eks. AccountingSrv): // Må fjerne \n\r fra slutten av feiltekster // Må kunne finne feil i andre moduler: string const oleDbModule("c:\\program files\\common files\\system” ”\\ole db\\msdaerr.dll”); os << Format(hr, oleDbModule) << endl;

18 Input Bruk av operator>>

19 Input: Eksempel string str; cout << "Input a string : "; cin >> str; int I = 0; cout << "Input a number : "; cin >> i; double d = 0.0; cout << "Input a float : "; cin >> d; os << "String = '" << str << "', number = " << i << ", double = " << d << std::endl; // Kjøring Input a string : hello Input a number : 234 Input a float : 200 String = 'hello', number = 234, double = 200 // Glemte å vente på tur Input a string : hello Input a number : Input a float : String = 'hello', number = 235, double = // Ting går feil: Input a string : hello there Input a number : Input a float : String = 'hello', number = 0, double = 0

20 Input •Å lese på cin flusher cout. Dette er fordi strømmene er ”tied”: –cin.tie(cout); •Input er white-space separert, selv fra konsol –Whitespace er definert i forhold til locale. •Dersom man skriver noe uventet, leses ikke verdien –Man kan bruke funksjonen basic_istream::good() for å se om det gikk galt

21 Input streams 2 string str; cout << "Input a string : "; cin >> str; int i = 0; cout << "Input a number : "; cin >> i; if ( !cin.good() ) { cout << "Invalid number!" << std::endl; } double d = 0.0; cout << "Input a float : "; cin >> d; if ( !cin.good() ) { cout << "Invalid number!" << std::endl; } cout << "String = '" << str << "', number = " << i << ", double = " << d << std::endl; // Kjøring Input a string : hello there Input a number : Invalid number! Input a float : Invalid number! String = 'hello', number = 0, double = 0

22 Input: andre funksjoner •istream& getline(char *s, streamsize n, char delim) •peek, ignore, putback •istream_iterator •Mer finkornete feilhånteringsfunksjonalitet –fail (kunne ikke lese) vs. bad (buffer i en ”farlig tilstand”) vs. eof (slutt på input) •Mer fleksibel whitespace håntering

23 Egne operatorer istream& operator>>(iostream& is, vector & v) { // Leser en vector som ser slik ut: ”[0, 2, 5,... ]” char delim; v.clear(); // skjekk åpningstegn is >> delim; if ( delim != '[' ) { // Dette er ikke en liste is.putback(delim); is.clear(ios::badbit|is.rdstate()); return is; } if ( is.flags() & ios::skipws ) is >> ws; if ( is.peek() == ']' ) return is; // Tom liste // les elementer til vi finner avslutning ']' while ( is.good() && delim != ']' ) { int current = 0; is >> current >> delim; v.push_back(current); } return is; }

24 Locales •Et locale er beskrivelse av settings for brukerens plassering i verden •Et locale inneholder flere facets. En facet angir settings for ett aspekt med localet •Følgende standard facet eksisterer –ctype (character egenskaper) –collate (sortering), codecvt (tegnsett konvertering) –Penger: moneypunct, money_get, money_put –Numre: numpunct, num_get, num_put –Dato: time_get, time_put –messages

25 Locales og strømmer •Ios_base, som er superklasse til ostream og istream definerer funksjonene: –getloc() returner locale objektet til strømmen –imbue() setter nytt locale objekt for strømmen •Locale-objektet brukes til å formattere tall, men kan også brukes i egendefinerte operator<<

26 Eksempel med struct tm inline ostream& operator<<(ostream& os, struct tm& tm) { typedef time_put ttimeput; ttimeput const& timeput = _USE(os.getloc(), ttimeput); timeput.put(ttimeput::iter_type(os),os,&tm, 'x'); return os; } inline istream& operator>>(istream& is, struct tm& tm) { typedef time_get ttimeget; ttimeget const& timeget = _USE(os.getloc(), ttimeget); timeget.get_date(ttimeput::iter_type(is.rdbuf()),timeput::iter_type(), is, is, &tm); if ( !is ) return is; timeget.get_time(ttimeput::iter_type(is.rdbuf()), timeput::iter_type(), is, is, &tm); return os; }

27 Streambuffer Oversikt Class tee_streambuf Om overstyring av buffere Class tdebugstreambuf

28 Streambuffer •Oppgaver –Hånterer kilde/destinasjon for lesing å skriving –Bufring/minnehåntering –Unicode/ANSI konverteringer •Kan overstyres etter brukers behov •Gjør ingen formattering av output •Ganske stor og forvirrende klasse, så jeg vil kun gi en grunnleggende oversikt

29 Streambuffer interface •Input –in_avail() – input: chars som kan leses før sync –snextc() – returnerer neste character –sbumpc() – hopper en character fram –sgetc() – returnere nåværende character –sgetn(E *s, streamsize n) – leser neste n –sputbackc(E c) – angrer lesing av c –sungetc() – angrer forrige lesning •Output –pubsync() – flusher bufferet –sputc(E c) – skriver neste char –sputn(const E *s, streamsize n)

30 std::basic_streambuf •Baseklassen til alle strømbuffere •Gir en implementasjon av alle funksjonen, både for bufret og ubufret I/O •Har to ”lag” med ”template method” patternet –xgetn, xget, xputn – kan overstyres, men fungerer bra for de fleste formål, de kaller: –uflow, underflow, sync og overflow, som bør overstyres

31 Ubufferet I/O •En ubufferet streambuf sender I/O direkte til sin eksterne kilde •Input: Må overstyre uflow til å returnere neste character •Output: Må overstyre overflow til å sende characters

32 Eksempel: tee_streambuf •Sender output til alle registrerte buffere •Er ubufret (dvs. mellomlagrer ikke data) •Overrider kun følgende metode: –Overflow •Jeg har ikke laget kode for å manipulere bufferene som det videresendes til

33 tee_streambuf source: template class tee_streambuf : public std::basic_streambuf { public: virtual int_type overflow(int_type c) { for (Buffers::iterator pBuffer=m_listeners.begin(); pBuffer!=m_listeners.end(); ++pBuffer ) { if ( pBuffers->sputc(c) == traits_type::eof() ) return traits_type::eof(); } return traits_type::not_eof(c); } private: typedef std::vector > Buffers; Buffers m_listeners; };

34 Buffer-basert Input •Input buffer –eback(), gptr(), og egptr() angir start, current og slutt, respektive –setg() kan brukes til å sette disse pekerene –gbump() brukes til å inkrementere current •Basic_streambuf::xsgetn hånterer input til det ikke er mer igjen i bufferet, kalles underflow. •underflow må hente mer til bufferet, eller returnere eof.

35 Buffer-basert output •Output buffer: –pbase(), pptr(), epptr() angir buffer –setp() setter buffer –pbump() inkrementere current •basic_streambuf::xsputn hånterer output til det ikke er mer plass i bufferet, så kalles overflow. •overflow må skaffe mer plass, eller returnere eof •I tillegg må sync sørge for at bufferet flushes

36 Streambuffer implementasjon Get Area (input)Put Area (output) Unbuffereduflowoverflow Bufferedunderflowoverflow sync Buffereback, gptr, egptr, gbump pbase, pptr, epptr, pbump

37 Eksempel 2: tdebugstreambuf •Bufret output streambuffer •Sender output til Win32 API’et OutputDebugStream •Fungerer kun som output •Binder cout til seg selv, slik at cout går til debug-strømmen

38 Kildekode: tdebugstreambuf class tdebugstreambuf : public std::basic_streambuf { tdebugstream() { setp(m_buffer, m_buffer, m_buffer+nBufSize-1); cin.rdbuf(this); } // This method is called when the buffer is filled up and must be flushed virtual int_type overflow(int_type c) { if (traits_type::eq_int_type(traits_type::eof(), c)) return traits_type::not_eof(c); synch(); sputc(traits_type::to_char_type(c)); return traits_type::not_eof(c); } // This method is called when user requests flushing of the buffer virtual int sync() { ::OutputDebugString(m_buffer); setp(m_buffer, m_buffer, m_buffer+nBufSize-1); return 0; } TCHAR m_buffer[BUFFER_SIZE]; // The buffer };

39 Bruk av tdebufstreambuf •Lag et bufferobjekt •Lag en basic_ostream •Send output til strømmen tdebugstreambuf debugstreambuf; basic_ostream traceStream(&debugstreambuf); traceStream << _T(”Hello world”) << std::endl;

40 Bonus: Videre muligheter •Jeg bruker i DataLayerSrv og AccountingSrv noen hjelpeklasser •Stream-manager –Velger mellom flere strømmer avh. av oppsett –Eks. TraceMgr[TraceProgress] << ”Det går fremover”

41 Stack-objekt som følger fremgang •TraceBlock trace(”FunctionName”); –Gjør trace[TraceProgress] << functionName << ”entered” •trace.Progress(”Doing something”); –Gjør trace[TraceProgress] << functionName << ”Doing something” •trace[TraceWarn] << ”Something went wrong”; •trace.NormalExit(); –Gjør trace[TraceProgress] << ”Function exited” –Dersom det ikke gjøres, vil destructor gjøre trace[TraceWarn] << ”Abnormal termination. Last progress was ” << lastProgress;

42 Ressurser •Angelica Langer & Klaus Kreft, ”Standard C++ IOStreams and Locales”, 2000, utdrag på IOStreams/about.htmhttp://www.langer.camelot.de/ IOStreams/about.htm •IOStream Examples: com/SDK_clib/CTOC- _iostream_Examples.htmlhttp://uw7doc.sco. com/SDK_clib/CTOC- _iostream_Examples.html


Laste ned ppt "C++ Streams Input og Output med C++ Standard Biblioteket."

Liknende presentasjoner


Annonser fra Google