Introduction to C Programming Module 5 C Stream

  • Slides: 32
Download presentation
Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling Yaodong Bi,

Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling Yaodong Bi, Ph. D. Department of Computing Sciences University of Scranton (717)941 -6108 bi@cs. uofs. edu August 20, 1998 bi@cs. uofs. edu

Outline z Module 1 - An Overview of C++ and OO Programming z Module

Outline z Module 1 - An Overview of C++ and OO Programming z Module 2 - Classes and Operator Overloading z Module 3 - Inheritance and Dynamic Binding z Module 4 - Function and Class Templates z Module 5 - C++ Stream I/O and Exception Handling August 20, 1998 bi@cs. uofs. edu 2

Review of Module 4 z Function Templates y. Function Template Definition y. Function Template

Review of Module 4 z Function Templates y. Function Template Definition y. Function Template Instantiation y. Template Explicit Specialization y. Overloading Function Templates y. Template Compilation Models z Class Templates y. Class Template Definition y. Class Template Instantiation y. Members of Class Templates y. Friend Declarations in Class Templates y. Class Template Compilation Model August 20, 1998 bi@cs. uofs. edu 3

Outline of Module 5 z Exception Handling y. Throwing an Exception and the Try

Outline of Module 5 z Exception Handling y. Throwing an Exception and the Try Block y. Catching an Exception y. Exception Specifications y. Advanced Topics z C++ Stream I/O y. Input/Output of Built-in Types y. Formats y. Overloading the I/O Operators << and >> y. File Input and Output y. Condition States August 20, 1998 bi@cs. uofs. edu 4

Example 1: Stack with Exceptions // except. h #include <iostream. h> class CPop. On.

Example 1: Stack with Exceptions // except. h #include <iostream. h> class CPop. On. Empty { public: CPop. On. Empty(int sz = 0); void Print() const; private: int m_n. Stack. Size; }; class CPush. On. Full { public: CPush. On. Full(int sz = 0); void Print() const; private: int m_n. Stack. Size; }; August 20, 1998 // except. cpp #include "except. h" CPop. On. Empty: : CPop. On. Empty(int sz) : m_n. Stack. Size(sz) { } void CPop. On. Empty: : Print() const { cout << "Exception: Pop on empty stack!n"; cout << "Stack Size = " << m_n. Stack. Size << endl; } CPush. On. Full: : CPush. On. Full(int sz) : m_n. Stack. Size(sz) { } void CPush. On. Full: : Print() const { cout << "Exception: Push on Full stack!n"; cout << "Stack Size = " << m_n. Stack. Size << endl; } bi@cs. uofs. edu 5

Ex 1: Stack with Exceptions - cont’d // Stack. h const int max. Size

Ex 1: Stack with Exceptions - cont’d // Stack. h const int max. Size = 10; class CStack { public: CStack(int sz = max. Size); CStack(const CStack&); CStack& operator= (const CStack&); void Push (int item); int Pop(); bool Is. Empty() const; bool Is. Full() const; ~CStack(); private: int* m_Array; int m_n. Top; int m_n. Size; }; August 20, 1998 // stack. cpp #include <iostream. h> #include "Stack. h" #include "except. h" void CStack: : Push(int item) { if (Is. Full()) throw CPush. On. Full(m_n. Size); m_Array[++m_n. Top] = item; } int CStack: : Pop() { if (Is. Empty()) throw CPop. On. Empty(m_n. Size); return m_Array[m_n. Top--]; } bool CStack: : Is. Empty() const { return (m_n. Top < 0); } bool CStack: : Is. Full() const { return (m_n. Top == m_n. Size - 1); } CStack: : ~CStack() { delete [] m_Array; } bi@cs. uofs. edu 6

Ex 1: Stack with Exceptions - cont’d // stack. cpp -- cont’d CStack: :

Ex 1: Stack with Exceptions - cont’d // stack. cpp -- cont’d CStack: : CStack(int sz) { m_Array = new int[sz]; m_n. Size = sz; m_n. Top = -1; } CStack: : CStack(const CStack& stack) { m_n. Size = stack. m_n. Size; m_n. Top = stack. m_n. Top; m_Array = new int[m_n. Size]; for (int i=0; i<=m_n. Top; i++) m_Array[i] = stack. m_Array[i]; } CStack& CStack: : operator=(const CStack& stack) { if (&stack != this) { delete [] m_Array; m_n. Size = stack. m_n. Size; m_n. Top = stack. m_n. Top; m_Array = new int[m_n. Size]; for (int i=0; i<=m_n. Top; i++) m_Array[i] = stack. m_Array[i]; } return *this; } August 20, 1998 // class. cpp #include <iostream. h> #include "Stack. h" #include "except. h" void main() { CStack stack; try { for ( int i = 1; i < max. Size+3; i++) stack. Push(i*100); } catch (CPush. On. Full push. Except) { push. Except. Print(); } // continued on next page bi@cs. uofs. edu 7

Ex 1: Stack with Exceptions - cont’d // class. cpp -- cont’d try {

Ex 1: Stack with Exceptions - cont’d // class. cpp -- cont’d try { } z Exception objects for (; ; ) cout << stack. Pop() << endl; } catch (CPop. On. Empty pop. Except) { pop. Except. Print(); } z The first for-loop tries to push three more items than the capacity of the stack. z The second infinite for-loop pops until the stack is empty August 20, 1998 class CPop. On. Empty; class CPush. On. Full; z The throw expression void CStack: : Push(int item) { if (Is. Full()) throw CPush. On. Full(m_n. Size); …. } z The try - catch block try { for (; ; ) cout << stack. Pop() << endl; } catch (CPop. On. Empty pop. Except) { pop. Except. Print(); } bi@cs. uofs. edu 8

Exception Handling z Problem Statement y The designer of a library can detect run-time

Exception Handling z Problem Statement y The designer of a library can detect run-time errors, but does not in general know what to do with them. The user of the library may know how to cope with such errors but cannot detect them. x. Ex. : The user of a math library may not know when a expression may have a divide-by-zero operation. The math library can detect it and the user program may know how to handle it. z A Solution -- Exception handling y Exceptions provide a way for code that detects a problem from which it cannot recover to pass the problem on to some part of the system that might be able to recover. z C++ implementation on Exception handing y A function that finds a problem it cannot handle throws an exception, and its (direct or indirect) caller that can handle the problem catches the exception. x. Ex. : The math library throws a divide-by-zero exception, the user program catches the exception and handles it. August 20, 1998 bi@cs. uofs. edu 9

Throwing an Exception and the Try Block z Throwing an Exception -- by the

Throwing an Exception and the Try Block z Throwing an Exception -- by the detector y Syntax: throw An_Exception; ex: throw 2; throw CPop. On. Empty(m_n. Size); // call a constructor y An exception must be an object; it cannot be a class type. throw CPop. On. Empty; // illegal - not an object z The Try Block -- by the caller y The caller that can handle the exception executes the try block. try { // statements that can cause exceptions } catch (Exception_1) { // handle exception 1 } …. catch (Exception_n) { // handler exception_n; } August 20, 1998 bi@cs. uofs. edu 10

Throwing an Exception and the Try Block y Control flow of the try block

Throwing an Exception and the Try Block y Control flow of the try block x If no exception occurs, the code in the try-block is executed and its handlers are ignored. The next statement after the last catch clause is executed. x If an exception is thrown, • the statements following the throw statement are ignored and the try-block exits (the stack is unwound. ). • The catch clauses are checked in order. The first matched catch is executed. After a catch clause is completed, the program continues at the statement following the last catch in the list. • If no catch clause can catch the exception, the exception is passed to the next caller along the calling chain. x. Once an exception is thrown, the program does not resume where the exception was originally thrown even after the exception is handled. y A try block introduces a local scope -- a variable declared within the block cannot be referred to outside the block, including the catch clauses. try { … int x; …} catch (exception) { … cout << x; // error: x is undefined …} y It is possible to include the entire body of a function in the try block. int main() try { // the body of main() … } catch (exception) { … } August 20, 1998 bi@cs. uofs. edu 11

Catching an Exception z Exception objects y The exception declaration of a catch clause

Catching an Exception z Exception objects y The exception declaration of a catch clause can be either a type declaration or an object declaration. try { … } catch (int) {…} // type delcaration. try { … } catch (int x) {… cout << x; . . . } // object delcaration. try { … } catch (CPop. On. Empty x) {… x. Print(); . . . } // object delcaration. y An exception object is always created at the throw point. Type X; // a global variable int main () { try {. . . throw X; } // an exception object is created and initialized with X catch (Type EX) { EX = Y; } // EX is copied from the exception object. The assignment // changes the local EX, not the exception object, not the global X catch (Type& EX) { EX = Y; } // EX is a reference to the exception object, not the global X // the assignment changes the exception object } August 20, 1998 bi@cs. uofs. edu 12

Catching an Exception z Stack Unwinding y When an exception cannot be handled, the

Catching an Exception z Stack Unwinding y When an exception cannot be handled, the search is continued to the calling function. This is continued until the exception can be handled or the program terminates. Ex: try {… foo(x); } catch (Type 1) { //handler Type 1; …. } void foo(x) { try { … foobar() } catch (Type 2) {…} } void foobar() { …. throw Type 1(); …} y As the stack being unwound, the local objects at each unwound level end and their destructors are called. In the above example, when throw Type() is completed, 1. all local variables in foobar() are destroyed with their destructors. 2. All local variables in foo() are destroyed with their destructors. z The Catch-all handler -- ellipsis. Ex: try {… } // should be used as the last catch clause. catch (…) { // enter for any type of exception } August 20, 1998 bi@cs. uofs. edu 13

Catching an Exception z Rethrow y A catch clause can pass the exception further

Catching an Exception z Rethrow y A catch clause can pass the exception further up the list of function calls by re-throwing the exception. Ex: try {… foo(x); } catch (Type 1 EX) { if (cannothandle(EX)) { throw; } …. } // re-throw the exception y The exception that is re-thrown is the original exception object. Type X; // a global variable int foo () { try {. . . throw X; } catch (Type EX) { … EX = y; throw; } } int main () { try { …foo(); } catch (Type &EX 1) { … EX 1 = z; } } // EX 1 references to the original except. object copied from the global X // it doesn’t reference to EX in foo(), not to the global X either. August 20, 1998 bi@cs. uofs. edu 14

Exception Specifications z An exception specification follows the function parameter list. class CStack {.

Exception Specifications z An exception specification follows the function parameter list. class CStack {. . . void Push (int item) throw (CPush. On. Full); }; int Pop() throw (CPush. On. Full); z An empty exception specification guarantees that the function doesn’t throw any exception. void foo(int item) throw (); // foo() will not throw any exception z If a function declaration does not specify an exception specification, it may throw exceptions of any type. void foo(int item) ; // foo() can throw an exception of any type z If a function throws an exception that is not in the specification list, the function unexpected() in the standard library is invoked, which in turn, by default, terminates the program. z MS VC++ 6. 0 doesn’t seem to support exception specifications. August 20, 1998 bi@cs. uofs. edu 15

Advanced Topics: Grouping of Exceptions y. Grouping of Exceptions: Put exceptions into families class

Advanced Topics: Grouping of Exceptions y. Grouping of Exceptions: Put exceptions into families class Matherr { //… virtual void debug_print(); }; class Overflow: public Matherr { //… virtual void debug_print(); }; class Zero. Divide: public Matherr { //… virtual void debug_print(); }; class Int. Overflow: public Overflow { //… virtual void debug_print(); }; August 20, 1998 int add(int x, int y) { // …. . if (overflow()) throw Int. Overflow(); } void foo() { } try { int i = add(INT_MAX, 2); } catch (Matherr& m) { m. debug_print(); // Int. Overflow’s debug_print() } bi@cs. uofs. edu 16

Advanced Topics: Resource Management y. Resource Acquisition is initialization class File_ptr { FILE* p;

Advanced Topics: Resource Management y. Resource Acquisition is initialization class File_ptr { FILE* p; public: File_ptr(const char* n, const char* a) { p =fopen(n, a); } ~File_ptr() { fclose(p); } }; void use_file(const char* fn) { File_ptr f_ptr(fn, “r”); // use file }; f_ptr is a local object of use_file(). If an exception occurs in use_file(), the file pointed by f_ptr would be closed when use_file exits and File_ptr’s destructor is called automatically. August 20, 1998 class Acquire { File_ptr ff; Lock_ptr ll; public: Acquire(const char* n, const char* m) : ff(n, “r”), // acquire ff ll(m) //acquire ll { // constructor body } }; If an exception occurs in ll(m), the destructor of ff will be invoked. If the Acquire constructor’s body has an exception, the destructors of ff and ll will be invoked. ==> resources are released. bi@cs. uofs. edu 17

Input/Output of Built-in Types y Input/Output classes xistream: input stream class xostream: output stream

Input/Output of Built-in Types y Input/Output classes xistream: input stream class xostream: output stream class xiostream: bidirectional input/output class y Standard Input/Output objects xcin: an istream class object for standard input xcout: an ostream class object for standard output xcerr: an ostream class object for standard error output y The output operator <<. x. It accepts argument of any of the built-in data types. cout << int_var << double_var; cout << “this is a string!n” << char_ptr; cout << &int_var; // print the address of int_var in hexadecimal. cout << true << false; // print 1 and 0 respectively, by default. x. Operator << associates left to right cout << x << y; // is equivalent to ( cout << x ) << y; August 20, 1998 bi@cs. uofs. edu 18

Input/Output of Built-in Types y The input operator >>. x. It accepts argument of

Input/Output of Built-in Types y The input operator >>. x. It accepts argument of any of the built-in data types. cin >> int_var >> double_var; cin << char_var; // all white spaces are skipped x. Operator >> associates left to right cin >> x >> y; // is equivalent to ( cin >> x ) >> y; y By default, the operator >> discards any intervening white space ( blank, tab, newline, formfeed, and carriage return). Input sequence: 123 1 b cd cin >> int_var >> ch 1 >>ch 2 >> ch 3 >>ch 4; cout << int_var<<ch 1<<ch 2<<ch 3<<ch 4; // prints 1231 bcd y To process every input character including white spaces: while (cin. get(char_var)) cout. put(char_var); // read every char in input and print char by char August 20, 1998 bi@cs. uofs. edu 19

Formats y Integer outputs cout. setf(ios_base: : oct, ios_base: : basefield); cout << 1234;

Formats y Integer outputs cout. setf(ios_base: : oct, ios_base: : basefield); cout << 1234; //print octal 2322 cout. setf(ios_base: : dec, ios_base: : basefield); cout << 1234; //print decimal 1234 -- decimal is the default y Floating-point output cout << 1234. 56789; // default output: 1234. 57 cout. setf(ios_base: : scientific, ios_base: : floatfield); cout << 1234. 56789; // scientific format: 1. 2345678 e+003 cout. setf(ios_base: : fixed, ios_base: : floatfield); cout << 1234. 56789; // fixed point format: 1234. 567890 cout. setf(0, ios_base: : floatfield); // reset default cout. precision(8); // set precision to 8 cout << 1234. 56789; // print: 1234. 5679 y Above print results were generated with MS VC++ 6. 0 and its standard iostream. August 20, 1998 bi@cs. uofs. edu 20

Formats y Output fields cout. width(4); // only affect the immediate << operation cout

Formats y Output fields cout. width(4); // only affect the immediate << operation cout << 12; //print with two space in front of 12 cout. width(4); cout. fill(‘#’); cout << 12; //print ##12 cout. width(0); // print as many as needed y Field adjustment cout. width(4); cout. fill(‘#’); cout. setf(ios_base: : left, ios_base: : adjustfield); // left cout. width(4); cout << -12; // print -12# cout. setf(ios_base: : right, ios_base: : adjustfield); // right -- default cout. width(4); cout << 12; // print ##12 cout. setf(ios_base: : internal, ios_base: : adjustfield); // between sign and # cout. width(4); cout << -12; // print -#12 y Above print results were generated with MS VC++ 6. 0 and its standard iostream. August 20, 1998 bi@cs. uofs. edu 21

Formats y Manipulators -- must #include <iomanip> cout << x << flush << y

Formats y Manipulators -- must #include <iomanip> cout << x << flush << y << flush; // explicitly request that the buffer be flushed. cin >> noskipws >> x; // don’t skip white spaces. cout << 1234 << “, “ <<hex<< 1234 <<“, “ << oct << 1234; // prints 1234, 4 d 2, 2322. cout << setw(6) << setfill(‘$’) << 12; // prints $$$$12. y When using manipulators that don’t take arguments, don’t add (). cout << hex() << 12; // error: hex doesn’t take arguments y make sure #include <iomanip> in your program y Users may define their own manipulators y The manipulators shown here are only some examples. For more comprehensive descriptions, read Lippman’s and Strousptrup’s books. y Above print results were generated with MS VC++ 6. 0 and its standard iostream. August 20, 1998 bi@cs. uofs. edu 22

Overloading the I/O operators << and >> y General skeleton of an overloaded output

Overloading the I/O operators << and >> y General skeleton of an overloaded output operator ostream& operator<<(ostream& os, const Class. Type &obj) { // actual output of the members. os << // … … // return ostream object return os; } y General skeleton of an overloaded input operator istream& operator>>(istream& is, Class. Type &obj) { // actual input to the members. os >> // … … // return istream object return is; } August 20, 1998 bi@cs. uofs. edu 23

Overloading the I/O operators << and >> y An Example class complex { friend

Overloading the I/O operators << and >> y An Example class complex { friend ostream& operator<<(ostream& os, const complex &obj); friend istream& operator>>(istream& is, complex &obj); Private: int real, image; }; ostream& operator<<(ostream& os, const complex &obj) { os << “< “ <<obj. real <<“, “ <<obj. image<<“ >n” ; return os; } istream& operator>>(istream& is, complex &obj) { is >> obj. real >> obj. image; return is; } int main() { complex cmplx; cin >> cmplx; cout << cmplx; return 0; } August 20, 1998 bi@cs. uofs. edu 24

Overloading the I/O operators << and >> z Virtual output functions #include "stdafx. h"

Overloading the I/O operators << and >> z Virtual output functions #include "stdafx. h" #include <iostream. h> class base { public: virtual ostream& put(ostream& s) {return s <<"Basen"; } }; class derived: public base { public: virtual ostream& put(ostream& s) {return s <<"Derivedn"; } }; z Implementation ostream& operator<<(ostream& s, base& b) { return b. put(s); } int main(int argc, char* argv[]) { } base bs; derived dr; cout << bs << dr; return 0; August 20, 1998 y The ostream members are not virtual. y Since the exact type of a subclass may not be known yet, correct output cannot be achieved simply by defining a << for each new type. y Design a virtual put function in the base and subclasses. virtual ostream& put(ostream& s); y Call the virtual function in << from a reference to the base ostream& operator<< (ostream& s, base& b) { return b. put(s); } y << doesn’t need to be a friend of the classes in this example. bi@cs. uofs. edu 25

File Input and Output y To use file input and output, include #include <fstream>

File Input and Output y To use file input and output, include #include <fstream> using namespace std; y To open a file for output only. ofstream outfile(“filename”, ios_base: : out); ofstream outfile(“filename”); // output is default // when the file does not exist, it would be created. // if an file is opened for output, all data in the file is discarded. if (!outfile) //open failed. { cerr << “file cannot be opened!n” exit(-1); } y ofstream is derived from ostream. All the ostream operations can be applied to ofstream objects. char ch = ‘ ‘; outfile. put(‘ 1’). put(‘)’). put(ch); outfile<<“ 1+1=“ << 1+1 << endl; // insert 1) 1+1 = 2 to outfile. y To open a file for append. ofstream outfile(“filename”, ios_base: : app); August 20, 1998 bi@cs. uofs. edu 26

File Input and Output y To open a file for input only. ifstream infile(“filename”);

File Input and Output y To open a file for input only. ifstream infile(“filename”); if (!infile) { cerr <<“input file open failedn”; exit(-1); } infile >> int_var; while (infile. get(ch)) cout. put(ch); y An fstream object can open a file for either input and output. fstream file; file. open(“filename”, ios_base: : in); // open the file for input file >> wd; file. close(); file. open(“filename”, ios_base: : app); // open the same file for output file << endl << wd << endl; file. close(); y An fstream object can open a file for both input and output. fstream file; file. open(“filename”, ios_base: : in | ios_base: : app); August 20, 1998 bi@cs. uofs. edu 27

Condition States y Condition flags. xeof(): return true if end-of-file has been encountered. if

Condition States y Condition flags. xeof(): return true if end-of-file has been encountered. if (cin. eof() ) { // ok, input complete. } xbad(): return true if an invalid op. has been attemped -- file corrupted. if (cin. bad() ) { // file corrupted in some undefined way. } xfail(): return true if an o. p has been unsuccessful. Ex. Invalid input format ifstream infile(“filename”); if (infile. fail() ) { // file open failed. } xgood(): return true if previous operation was successful - file in good cond. If (infile. good() ) { // continuing processing the file. } y Two methods for modifying the condition states. xclear() resets the condition state to an explicit value cin. clear(ios_base: : goodbit); // reset cin to good condition xsetstate(): add a condition tot he existing condition of the object. if ((ch = is. get()) != ‘<‘) cin. setstate(ios_base: : failbit); // if the current char is not ‘<‘, mark the fail state. x. To set multiple states, cin. setstate(ios_base: : badbit | ios_base: : failbit); // set both bad state and fail state. August 20, 1998 bi@cs. uofs. edu 28

Summary of Module 5 z Exception Handling y. Throwing an Exception and the Try

Summary of Module 5 z Exception Handling y. Throwing an Exception and the Try Block y. Catching an Exception y. Exception Specifications y. Advanced Topics z C++ Stream I/O y. Input/Output of Built-in Types y. Formats y. Overloading the I/O Operators << and >> y. File Input and Output y. Condition States August 20, 1998 bi@cs. uofs. edu 29

Advice z z z z Don’t use exceptions where more local control structures will

Advice z z z z Don’t use exceptions where more local control structures will suffice. Use the “resource acquisition is initialization” to manager resources. Not every program needs to be exception safe. Avoid throwing exceptions from copy constructors. Avoid throwing exceptions from destructors. Throw an exception to indicate failure in a constructor. Develop an error-handling strategy early in the design. z Overload << and >> for user-defined types with values that have meaningful textual representations. z Remember that by default >> skips white spaces z Remember to #include <iomanip> when using standard manipulators. z Remember that the width manipulator applies to the following I/O operation only. z Define virtual input/output functions. August 20, 1998 bi@cs. uofs. edu 30

Programming Assignments z Exception -- CDate y Modify the CDate example so that it

Programming Assignments z Exception -- CDate y Modify the CDate example so that it throws exceptions when a value is out of valid range. y Group the exceptions in CDate into a class hierarchy. Use virtual functions to print offensive values (year, month, or day). y Write a main() to test those exceptions. z Exception -- An array class y Design an array class that throws Out. Of. Range when the subscript is of range. Out. Of. Range can print the size of the array and the offensive subscript. z Overload Operators << and >> y Design virtual input and output functions for the CPerson-CManager. CEngineer inheritance example. z File Input/output y Design a program that counts the number of words and the number of white spaces in the input file. August 20, 1998 bi@cs. uofs. edu 31

August 20, 1998 bi@cs. uofs. edu 32

August 20, 1998 bi@cs. uofs. edu 32