Chapter 10 - Chapter 10 Chapter Input/Output Streams Bjarne...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: Chapter 10 Chapter Input/Output Streams Bjarne Stroustrup www.stroustrup.com/Programming Abstract Abstract We get data from files, sensors, web We connections, etc., which we want to analyze, print, graph, etc. Sometimes, we want to produce such data. In this lecture, we look at C++’s basic mechanisms for reading and writing streams of data. We also discuss an interesting – apparently trivial – problem: how to read an integer. trivial Stroustrup/Programming 2 Overview Overview Fundamental I/O concepts Files Opening Reading and writing streams Reading I/O errors Reading a single integer Stroustrup/Programming 3 Input and Output Input data source: input device device driver input library our program our program data destination: output library device driver Stroustrup/Programming output device 4 The stream model The c “somewhere” (1,234) ostream 123 buffer An ostream An ostream turns values of various types into character sequences sends those characters somewhere E.g., console, file, main memory, another computer Stroustrup/Programming 5 The stream model The c “somewhere” (1,234) istream 123 buffer An istream An istream turns character sequences into values of various types turns gets those characters from somewhere E.g., console, file, main memory, another computer Stroustrup/Programming 6 The stream model The Reading and writing Of typed entities Typically stored (entered, printed, etc.) as text But not necessarily (see binary streams in chapter 11) Extensible << (output) and >> (input) plus other operations Type safe Formatted You can define your own I/O operations for your own types A stream can be attached to any I/O or storage device Stroustrup/Programming 7 Files Files We turn our computers on and off We like to keep our data So we keep what we want to preserve on disks and similar So permanent storage permanent A file is a sequence of bytes stored in permanent storage The contents of our main memory is transient A file has a name The data on a file has a format We can read/write a file if we know its name and format Stroustrup/Programming 8 A file file 0: 1: 2: At the fundamental level, a file is a sequence of bytes At numbered from 0 upwards numbered Other notions can be supplied by programs that interpret a Other “file format” “file For example, the 6 bytes "123.45" might be interpreted as the For floating-point number 123.45 Stroustrup/Programming 9 Files Files General model disk Files (sequences of bytes) I/O system iostreams Stroustrup/Programming Main memory Objects (of various types) 10 Files Files To read a file We must know its name We must open it (for reading) Then we can read Then we must close it That is typically done implicitly To write a file We must name it We must open it (for writing) Or create a new file of that name Then we can write it We must close it We That is typically done implicitly Stroustrup/Programming 11 Opening a file for reading Opening // … // int main() { cout << "Please enter input file name: "; string name; cin >> name; ifstream ist(name.c_str()); // ifstream is an“input stream from a file” // is // c_str() gives a low-level (“system” // c_str() // or C-style) string from a C++ string or // defining an ifstream with a name string ifstream // opens the file of that name for reading opens if (!ist) error("can’t open input file ", name); // … // Stroustrup/Programming 12 Opening a file for writing Opening // … // cout << "Please enter name of output file: "; cin >> name; ofstream ofs(name.c_str()); // ofstream is an “output stream from a file” ofstream is // defining an ofstream with a name string // ofstream // opens the file with that name for writing // opens if (!ofs) error("can’t open output file ", name); // … // } Stroustrup/Programming 13 Remember Remember Sometimes students want to read to a file or Sometimes to write from a file – this causes errors from We read in from an input stream (ist >>) We from We write out to an output stream (ost <<) We to It’s like a piece of paper: Reading is getting information from the paper Writing is putting information on the paper Stroustrup/Programming 14 Reading from a file Reading Suppose a file contains a sequence of pairs Suppose representing hours and temperature readings representing 0 60.7 1 60.6 2 60.3 3 59.22 The hours are numbered 0..23 0..23 The No further format is assumed Maybe we can do better than that (but not just now) Termination Reaching the end of file terminates the read Anything unexpected in the file terminates the read E.g., q Stroustrup/Programming 15 Reading a file Reading // … // struct Reading { // a temperature reading // temperature int hour; // hour after midnight [0:23] // hour double temperature; // in Fahrenheit // in // (How would you define a Reading that could handle both Fahrenheit and Celsius?) (How Reading(int h, double t) :hour(h), temperature(t) { } }; vector<Reading> temps; // create a vector to store the readings // create int hour; double temperature; while (ist >> hour >> temperature) { // read // read if (hour < 0 || 23 <hour) error("hour out of range"); // check // check temps.push_back( Reading(hour,temperature) ); // store store } // … // Stroustrup/Programming 16 I/O error handling Sources of errors Human mistakes Human Files that fail to meet specifications Specifications that fail to match reality Programmer errors Etc. iostream reduces all errors to one of four states good() eof() fail() bad() // the operation succeeded // the // we hit the end of input (“end of file”) // we // something unexpected happened // something // something unexpected and serious happened // something Stroustrup/Programming 17 Sample integer read “failure” Sample Ended by “terminator character” Ended by format error 1 2 3 4 5.6 State is fail() State fail() Ended by “end of file” 12345* State is fail() State fail() 1 2 3 4 5 end of file 1 2 3 4 5 Control-Z (Windows) 1 2 3 4 5 Control-D (Unix) Control-D State is eof() State eof() Something really bad Disk format error State is bad() State bad() Stroustrup/Programming 18 I/O error handling I/O void fill_vector(istream& ist, vector<int>& v, char terminator) { // read integers from ist into v until we reach eof() or terminator read until or int i = 0; while (ist >> i) v.push_back(i); // read and store in v until “some failure” while if (ist.eof()) return; // fine: we found the end of file fine: we if (ist.bad()) error("ist is bad"); // stream corrupted; let’s get out of here! if stream get if (ist.fail()) { // clean up the mess as best we can and report the problem if clean ist.clear(); // clear stream state, so that we can look for terminator ist.clear(); so char c; ist>>c; // read a character, hopefully terminator terminator if (c != terminator) { // unexpected character // unexpected ist.unget(); // put that character back // put ist.clear(ios_base::failbit); // set the state back to fail() // set } } } Stroustrup/Programming 19 Throw an exception for bad() Throw // How to make ist throw if it goes bad: // How make bad ist.exceptions(ist.exceptions()|ios_base::badbit); // can be read as // can // “set ist’s exception mask to whatever it was plus badbit” // ist // or as “throw an exception if the stream goes bad” // or Given that, we can simplify our input loops by no longer checking for Given bad bad Stroustrup/Programming 20 Simplified input loop Simplified void fill_vector(istream& ist, vector<int>& v, char terminator) { // read integers from ist into v until we reach eof() or terminator read until or int i = 0; while (ist >> i) v.push_back(i); if (ist.eof()) return; // fine: we found the end of file // fine: we // not good() and not bad() and not eof(), ist must be fail() // good() bad() eof() ist fail() ist.clear(); // clear stream state // clear char c; ist>>c; // read a character, hopefully terminator // terminator if (c != terminator) { // ouch: not the terminator, so we must fail // ouch: ist.unget(); // maybe my caller can use that character // maybe ist.clear(ios_base::failbit); // set the state back to fail() // set } } Stroustrup/Programming 21 Reading a single value Reading // first simple and flawed attempt: // first cout << "Please enter an integer in the range 1 to 10 (inclusive):\n"; int n = 0; while (cin>>n) { // read // read if (1<=n && n<=10) break; // check range check cout << "Sorry, " << n << << " is not in the [1:10] range; please try again\n"; << } Three kinds of problems are possible the user types an out-of-range value getting no value (end of file) the user types something of the wrong type (here, not an integer) Stroustrup/Programming 22 Reading a single value Reading What do we want to do in those three cases? What handle the problem in the code doing the read? throw an exception to let someone else handle the throw problem (potentially terminating the program)? problem ignore the problem? Reading a single value Is something we often do many times We want a solution that’s very simple to use Stroustrup/Programming 23 Handle everything: What a mess! Handle cout << "Please enter an integer in the range 1 to 10 (inclusive):\n"; int n = 0; while (n==0) { // Spot the bug! // Spot cin >> n; if (cin) { // we got an integer; now check it: // we if (1<=n && n<=10) break; cout << "Sorry, " << n << " is not in the [1:10] range; please try again\n"; } else if (cin.fail()) { // we found something that wasn’t an integer // we cin.clear(); // we’d like to look at the characters // we’d cout << "Sorry, that was not a number; please try again\n"; char ch; while (cin>>ch && !isdigit(ch)) ; // throw away non-digits // throw if (!cin) error("no input"); // we didn’t find a digit: give up if we cin.unget(); // put the digit back, so that we can read the number // put } else else error("no input"); // eof or bad: give up error("no // eof } // if we get here n is in [1:10] if Stroustrup/Programming 24 The mess: The trying to do everything at once Problem: We have all mixed together reading values prompting the user for input writing error messages skipping past “bad” input characters testing the input against a range Solution: Split it up into logically separate parts Stroustrup/Programming 25 What do we want? What What logical parts do we what? int get_int(); // read an int from cin // cin // so that we can check the range int int get_int(int low, int high); // read an int in [low..high] from cin int read from cin void skip_to_int(); // we found some “garbage” character we // so skip until we find an int so Separate functions that do the logically separate actions Stroustrup/Programming 26 Skip “garbage” Skip void skip_to_int() { if (cin.fail()) { // we found something that wasn’t an integer // we cin.clear(); // we’d like to look at the characters // we’d char ch; while (cin>>ch) { // throw away non-digits // throw if (isdigit(ch)) { cin.unget(); // put the digit back, // put // so that we can read the number // so return; } } } error("no input"); // eof or bad: give up // eof } Stroustrup/Programming 27 Get (any) integer Get int get_int() { int n = 0; while (true) { if (cin >> n) return n; if cout << "Sorry, that was not a number; please try again\n"; cout skip_to_int(); } } Stroustrup/Programming 28 Get integer in range Get int get_int(int low, int high) { cout << "Please enter an integer in the range " << low << " to " << high << " (inclusive):\n"; while (true) { int n = get_int(); if (low<=n && n<=high) return n; cout << "Sorry, " << n << " is not in the [" << low << ':' << high << "] range; please try again\n"; } } Stroustrup/Programming 29 Use Use int n = get_int(1,10); cout << "n: " << n << endl; int m = get_int(2,300); cout << "m: " << m << endl; Problem: The “dialog” is built into the read operations Stroustrup/Programming 30 What do we really want? really // parameterize by integer range and “dialog” // parameterize int strength = get_int(1, 10, "enter strength", "Not in range, try again"); cout << "strength: " << strength << endl; int altitude = get_int(0, 50000, "please enter altitude in feet", "Not in range, please try again"); cout << "altitude: " << altitude << "ft. above sea level\n"; That’s often the really important question Ask it repeatedly during software development As you learn more about a problem and its solution, your answers improve Stroustrup/Programming 31 Parameterize Parameterize int get_int(int low, int high, const string& greeting, const string& sorry) { cout << greeting << ": [" << low << ':' << high << "]\n"; while (true) { int n = get_int(); if (low<=n && n<=high) return n; cout << sorry << ": [" << low << ':' << high << "]\n"; } } Incomplete parameterization: get_int() still “blabbers” Incomplete get_int() “utility functions” should not produce their own error messages Serious library functions do not produce error messages at all They throw exceptions (possibly containing an error message) Stroustrup/Programming 32 User-defined output: operator<<() User-defined Usually trivial ostream& Date::operator<<(ostream& os, const Date& d) { return os << '(' << d.year() << ',' << d.month() << ',' << d.day() << ')'; } We often use several different ways of outputting a value Tastes for output layout and detail vary Tastes Stroustrup/Programming 33 33 Use Use void do_some_printing(Date d1, Date d2) { cout << d1; // means Date::operator<<(cout,d1) ; // Date::operator<<(cout,d1) cout << d1 << d2; // means (cout << d1) << d2; (cout // means (Date::operator<<(cout,d1)) << d2; // (Date::operator<<(cout,d1)) // means Date::operator<<((Date::operator<<(cout,d1)), d2) ; // means } Stroustrup/Programming 34 User-defined input: operator>>() User-defined istream& Date::operator>>(istream& is, Date& dd) // Read date in format: ( year , month , day ) // Read { int y, d, m; char ch1, ch2, ch3, ch4; is >> ch1 >> y >> ch2 >> m >> ch3 >> d >> ch4; if (!is) return is; // we didn’t get our values, so just leave // we if (ch1!='(' || ch2!=',' || ch3!=',' || ch4!=')') { // oops: format error // oops: is.clear(ios_base::failbit); // something wrong: set state to fail() fail() return is; // and leave and } dd = Date(y,Month(m),d); // update dd // update return is; // and leave with is in the good() state // is } Stroustrup/Programming 35 Next Lecture Next Customizing input and output (chapter 11) Stroustrup/Programming 36 ...
View Full Document

Ask a homework question - tutors are online