1 / 42

C++ Streams

C++ Streams. Input og Output med C++ Standard Biblioteket. 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.

claral
Download Presentation

C++ Streams

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ Streams Input og Outputmed 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<<, 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 • << og >> er overloaded for alle argumenter vi ønsker å skrive ut • << og >> 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<< og operator>> for å lage lesing og skriving av en klasse.

  12. Eksempel: VARIANT • wostream& operator<<(wostream& os, VARIANT const& arg){ • CComVariant var(arg);// Lager en kopi vi kan endre • os << L"(";// Skriver ut ’(’ på begynnelsen • if ( var.vt & VT_ARRAY ) { // Kaller ny funk. for array • PrintArray(var.vt, var.parray, os); • } else if ( var.vt == VT_RECORD ) { • PrintRecord(var, 0, os);// Kall ny funk for record • } else if (FAILED(var.ChangeType(VT_BSTR))){ • os << L"<nonprintable>";// Ingen behandling • } else if ( var.bstr == NULL ) { • os << _T(”’’”); // Tom streng • } else { // Vi har nå konvertert verdien til en bstring • os << L"'" << var.bstr << L"'"; • } • os << _T(" [") << VarTypeToString(arg.vt) << _T("])"); • return os; • }

  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 <iomanip> • 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 << 2147500037  ”0x80004005” (E_FAIL) • Bools • os << boolalpha << true  ”true” • os << noboolalpha << true  ”1” • Floating points • os << scientific << 1000.0  ”1.00000e3” • 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(0x80041002) << std::endl; //  ”Error 0x80041002”

  17. 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; returnos; } // 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; Eksempel: GetLastError

  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 235 23002.2 Input a number : Input a float : String = 'hello', number = 235, double = 23002. 2 // 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<int>& 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() == ']' ) returnis; // Tom liste // les elementer til vi finner avslutning ']' while ( is.good() && delim != ']' ) { int current = 0; is >> current >> delim; v.push_back(current); } returnis; }

  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 inlineostream& operator<<(ostream& os, struct tm& tm) { typedef time_put<char> ttimeput; ttimeput const& timeput = _USE(os.getloc(), ttimeput); timeput.put(ttimeput::iter_type(os),os,&tm, 'x'); return os; } inlineistream& operator>>(istream& is, struct tm& tm) { typedef time_get<char> 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 char_type> classtee_streambuf : public std::basic_streambuf<char_type> { public: virtualint_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< std::basic_streambuf<char_type> > 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

  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. classtdebugstreambuf : publicstd::basic_streambuf<TCHAR> { 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 virtualint_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 }; Kildekode: tdebugstreambuf

  39. Bruk av tdebufstreambuf • Lag et bufferobjekt • Lag en basic_ostream<TCHAR> • Send output til strømmen tdebugstreambuf debugstreambuf; basic_ostream<TCHAR> 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å http://www.langer.camelot.de/ IOStreams/about.htm • IOStream Examples: http://uw7doc.sco. com/SDK_clib/CTOC-_iostream_Examples.html

More Related