Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

Input og Output med C++ Standard Biblioteket

Liknende presentasjoner


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

1 Input og Output med C++ Standard Biblioteket
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 operator<<, operator>> Manipulatorer Locales
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: Bools Floating points
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 Med 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 Bruk av operator>>
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 = 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; 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() == ']' ) return is; // Tom liste // les elementer til vi finner avslutning ']' while ( is.good() && delim != ']' ) { int current = 0; is >> current >> delim; v.push_back(current);

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<char> 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<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(),

27 Streambuffer Oversikt Class tee_streambuf
Om overstyring av buffere Class tdebugstreambuf

28 Streambuffer Oppgaver Kan overstyres etter brukers behov
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> class tee_streambuf : public std::basic_streambuf<char_type> { 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< 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
Get Area (input) Put Area (output) Unbuffered uflow overflow Buffered underflow sync Buffer eback, 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<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 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)); // This method is called when user requests flushing of the buffer virtual int sync() { ::OutputDebugString(m_buffer); return 0; TCHAR m_buffer[BUFFER_SIZE]; // The buffer };

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å IOStreams/about.htm IOStream Examples: com/SDK_clib/CTOC-_iostream_Examples.html


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

Liknende presentasjoner


Annonser fra Google