Overview of Lecture 1 Overloading I/O Operators 2 Overloading << and >> for Fractions 3 Formatted vs Unformatted Input 4 Setting the State of a Stream 5 Questions PIC 10B Streams, Part II April 20, 2016 1 / 10
The Operators << and >> What does the code int n = 10; std :: cout << n; really mean? std::cout is an instance of the class std::ostream. << is a binary operator that has been overloaded to take an int as a parameter. The << operator converts the value of n to the text you see printed on the screen! A declaration for << (for int) looks like std :: ostream & operator < <( std :: ostream & os, const int & val ); Notice << returns a reference to an ostream in fact, it returns a reference to os. The operator >> is declared similarly for the class istream: std :: istream & operator > >( std :: istream & is, const int & val ); PIC 10B Streams, Part II April 20, 2016 2 / 10
Overloading << and >> The symbols << and >> are operators that can be overloaded, just like any other operators. For example, we can declare for our Fraction class std :: ostream & operator < <( std :: ostream & os, Fraction & frac ); and std :: istream & operator > >( std :: istream & is, Fracction & frac ); How should we implement these operators? PIC 10B Streams, Part II April 20, 2016 3 / 10
Implementing << for Fraction Implementing << should not be difficult... we should just implement it in terms of the versions of <<! Desired behavoir: Fraction frac (3, 4); // Make a Fraction with value 3/4 std :: cout << frac ; // Should print 3/4 To make this happen: std :: ostream & operator < <( std :: ostream & os, Fraction & frac ) { os << frac. numerator () << "/" << frac. denominator (); That s all there is to it! The os already knows how to deal with ints and strings! See fraction-io.cpp for examples. PIC 10B Streams, Part II April 20, 2016 4 / 10
Implementing >> for Fraction Dealing with >> and std::istream objects can be messier because we may have to verify the formatting. Should our program ignore white-space characters? For example, should we allow "3 / 4" to be a valid Fraction input? If the pattern int/int is not matched, how do we let the std::istream know? First attempt at a simple Fraction reader: std :: istream & operator > >( std :: istream & is, Fraction & frac ) { int num, den ; char c; istream >> num >> c >> den ; frac. set_value (num, den ); Will this work for all inputs? PIC 10B Streams, Part II April 20, 2016 5 / 10
What We d Like for Fraction Input Ideally all of the following would be admissable inputs 3/4 // This is how a fraction will be printed using << 3 / 4 // This should also be acceptable 3 // Should represent an integer with value 3/1 PIC 10B Streams, Part II April 20, 2016 6 / 10
Formatted vs Unformatted Input Formatted input operators std :: istream is;... // Read something from is and store value to var is >> var ; // must have operator >> defined for var s datatype! getline ( is, str ); // read a line and save to std :: string str Unformatted input is. get (); // Returns value of character read is. get ( ch ); // Stores value of character read to char ch is. peek (); // returns next character in stream is. unget (); // go back to the previous character in the stream Notes: By default >> ignores whitespace characters. get and peek do not ignore whitespace. get increments the position in the stream by one character. peek does not increment the position. unget decrements the position in the stream, allowing you to re-read the previous character. PIC 10B Streams, Part II April 20, 2016 7 / 10
Getting Fraction Input Code std :: istream & operator > >( std :: istream & is, Fraction & frac ) { int num, den = 1; char slash ; is >> num ; slash = is. peek (); while ( slash == ) { // Ignore spaces before / is.get (); slash = is. peek (); if( slash == / ) { is >> slash ; is >> den ; frac = Fraction ( num, den ); return is; PIC 10B Streams, Part II April 20, 2016 8 / 10
Handling Errors with std::istream Stream objects have a state: The state is good() if the object hasn t encountered an error. Otherwise the state is fail, eof (end of file), or bad io.fail() is true if the last operation didn t work as expected because of a logical error (e.g., tried to read an int but encountered the character a ). io.eof() is true if the IO object reached the end of the file. io.bad() is true if the IO object encountered an error reading or writing. If a std::istream is is in a bad state, is.clear() puts it back into a good state if it was in a fail state. The character EOF denotes the end of a file. You can set the state of a stream to fail using is. setstate ( std :: ios_base :: failbit ); PIC 10B Streams, Part II April 20, 2016 9 / 10
Questions 1 What is the difference between getline (is, str ); and is >> str ; When might you prefer one to the other? 2 Consider the following code, which is meant to copy ints input from cin to some output stream os. int val ; while ( std :: cin >> val ) { os << val ; Does the program run as you d expect? When does the while loop terminate? How would you change the code so that the loop terminates after the user hits return/enter? PIC 10B Streams, Part II April 20, 2016 10 / 10