introduction to c++ programming module 5 c++ stream i/o and exception handling

32
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 [email protected]

Upload: rafal

Post on 06-Jan-2016

29 views

Category:

Documents


4 download

DESCRIPTION

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 [email protected]. Outline. Module 1 - An Overview of C++ and OO Programming Module 2 - Classes and Operator Overloading - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Introduction to C++ ProgrammingModule 5

C++ Stream I/O and Exception Handling

Yaodong Bi, Ph.D.Department of Computing Sciences

University of Scranton(717)[email protected]

Page 2: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Outline

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

Module 2 - Classes and Operator Overloading

Module 3 - Inheritance and Dynamic Binding

Module 4 - Function and Class Templates

Module 5 - C++ Stream I/O and Exception Handling

Page 3: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Review of Module 4Function Templates

Function Template Definition Function Template Instantiation Template Explicit Specialization Overloading Function Templates Template Compilation Models

Class Templates Class Template Definition Class Template Instantiation Members of Class Templates Friend Declarations in Class Templates Class Template Compilation Model

Page 4: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Outline of Module 5

Exception Handling Throwing an Exception and the Try Block Catching an Exception Exception Specifications Advanced Topics

C++ Stream I/O Input/Output of Built-in Types Formats Overloading the I/O Operators << and >> File Input and Output Condition States

Page 5: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Example 1: Stack with Exceptions// except.h

#include <iostream.h>

class CPopOnEmpty{public:

CPopOnEmpty(int sz = 0);void Print() const;

private:int m_nStackSize;

};

class CPushOnFull{public:

CPushOnFull(int sz = 0);void Print() const;

private:int m_nStackSize;

};

// except.cpp

#include "except.h"

CPopOnEmpty::CPopOnEmpty(int sz):m_nStackSize(sz) { }

void CPopOnEmpty::Print() const{

cout << "Exception: Pop on empty stack!\n";cout << "Stack Size = " << m_nStackSize << endl;

}

CPushOnFull::CPushOnFull(int sz):m_nStackSize(sz) { }

void CPushOnFull::Print() const{

cout << "Exception: Push on Full stack!\n";cout << "Stack Size = " << m_nStackSize << endl;

}

Page 6: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Ex 1: Stack with Exceptions - cont’d// Stack.h

const int maxSize = 10;

class CStack {public:

CStack(int sz = maxSize);CStack(const CStack&); CStack& operator=

(const CStack&);void Push (int item);int Pop();bool IsEmpty() const;bool IsFull() const;~CStack();

private:int* m_Array;int m_nTop;int m_nSize;

};

// stack.cpp#include <iostream.h>#include "Stack.h"#include "except.h"

void CStack::Push(int item) {

if (IsFull()) throw CPushOnFull(m_nSize);m_Array[++m_nTop] = item;

}int CStack::Pop() {

if (IsEmpty()) throw CPopOnEmpty(m_nSize);return m_Array[m_nTop--];

}bool CStack::IsEmpty() const

{ return (m_nTop < 0); }bool CStack::IsFull() const

{ return (m_nTop == m_nSize - 1); }CStack::~CStack()

{ delete [] m_Array; }

Page 7: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Ex 1: Stack with Exceptions - cont’d// stack.cpp -- cont’dCStack::CStack(int sz) { m_Array = new int[sz];

m_nSize = sz;m_nTop = -1; }

CStack::CStack(const CStack& stack){ m_nSize = stack.m_nSize;

m_nTop = stack.m_nTop;m_Array = new int[m_nSize];for (int i=0; i<=m_nTop; i++)

m_Array[i] = stack.m_Array[i]; }CStack& CStack::operator=(const CStack& stack) { if (&stack != this)

{ delete [] m_Array; m_nSize = stack.m_nSize;

m_nTop = stack.m_nTop; m_Array = new int[m_nSize];

for (int i=0; i<=m_nTop; i++) m_Array[i] =

stack.m_Array[i]; }return *this; }

// class.cpp

#include <iostream.h>#include "Stack.h"#include "except.h"

void main(){

CStack stack;

try { for ( int i = 1; i < maxSize+3; i++)

stack.Push(i*100);}catch (CPushOnFull pushExcept){

pushExcept.Print();}

// continued on next page

Page 8: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

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

try{ for (;;)

cout << stack.Pop() << endl;}catch (CPopOnEmpty popExcept){

popExcept.Print();}

}

The first for-loop tries to push three more items than the capacity of the stack.

The second infinite for-loop pops until the stack is empty

Exception objectsclass CPopOnEmpty;class CPushOnFull;

The throw expressionvoid CStack::Push(int item) { if (IsFull()) throw

CPushOnFull(m_nSize);…. }

The try - catch blocktry{ for (;;)

cout << stack.Pop() << endl;}catch (CPopOnEmpty popExcept){

popExcept.Print();}

Page 9: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Exception Handling Problem Statement

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.

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.

A Solution -- Exception handling 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.

C++ implementation on Exception handing 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.

Ex.: The math library throws a divide-by-zero exception, the user program catches the exception and handles it.

Page 10: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

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

Syntax: throw An_Exception;

ex: throw 2; throw CPopOnEmpty(m_nSize); // call a constructor

An exception must be an object; it cannot be a class type.

throw CPopOnEmpty; // illegal - not an object

The Try Block -- by the caller The caller that can handle the exception executes the try

block.try {

// statements that can cause exceptions }catch (Exception_1){

// handle exception1}….catch (Exception_n){ // handler exception_n;}

Page 11: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

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

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.

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.

Once an exception is thrown, the program does not resume where the exception was originally thrown even after the exception is handled.

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 …}

It is possible to include the entire body of a function in the try block.

int main()try { // the body of main() … } catch (exception) { … }

Page 12: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Catching an Exception Exception objects

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 (CPopOnEmpty x) {… x.Print(); ...} // object delcaration.

An exception object is always created at the throw point.Type X; // a global variableint 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

}

Page 13: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Catching an Exception Stack Unwinding

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); } void foo(x) void foobar()

catch (Type1) { try { … foobar() } { …. { //handler Type1; catch (Type2) throw

Type1(); ….} {…} } … }

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.

The Catch-all handler -- ellipsis.Ex: try {… } // should be used as the last catch clause.

catch (…) { // enter for any type of exception }

Page 14: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Catching an Exception Rethrow

A catch clause can pass the exception further up the list of function calls by re-throwing the exception.Ex: try {… foo(x); }

catch (Type1 EX) { if (cannothandle(EX)) { throw; } // re-throw the

exception ….}

The exception that is re-thrown is the original exception object.Type X; // a global variableint foo ()

{ try { ...throw X; } catch (Type EX) { … EX = y; throw; } }int main ()

{ try { …foo(); } catch (Type &EX1) { … EX1 = z; }

}// EX1 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.

Page 15: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Exception Specifications An exception specification follows the function parameter list.

class CStack { ...

void Push (int item) throw (CPushOnFull);int Pop() throw (CPushOnFull);

};

An empty exception specification guarantees that the function doesn’t throw any exception.

void foo(int item) throw (); // foo() will not throw any exception

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

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.

MS VC++ 6.0 doesn’t seem to support exception specifications.

Page 16: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Advanced Topics: Grouping of Exceptions Grouping of Exceptions: Put exceptions into families

class Matherr {//…virtual void debug_print();

};class Overflow: public Matherr {

//…virtual void debug_print();

};class ZeroDivide: public Matherr {

//…virtual void debug_print();

};class IntOverflow: public Overflow {

//…virtual void debug_print();

};

int add(int x, int y){ // …..

if (overflow()) throw IntOverflow();

}void foo(){

try { int i = add(INT_MAX, 2);}catch (Matherr& m){

m.debug_print();// IntOverflow’s

debug_print()}

}

Page 17: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Advanced Topics: Resource Management 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(),

thefile pointed by f_ptr would be closedwhen use_file exits and File_ptr’s destructor is called automatically.

class Acquire {File_ptr ff;Lock_ptr ll;

public:Acquire(const char* n, const char* m)

: ff(n, “r”), // acquire ffll(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.

Page 18: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Input/Output of Built-in Types Input/Output classes

istream: input stream class ostream: output stream class iostream: bidirectional input/output class

Standard Input/Output objects cin: an istream class object for standard input cout: an ostream class object for standard output cerr: an ostream class object for standard error output

The output operator <<. 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.

Operator << associates left to right cout << x << y; // is equivalent to

( cout << x ) << y;

Page 19: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Input/Output of Built-in Types The input operator >>.

It accepts argument of any of the built-in data types.cin >> int_var >> double_var; cin << char_var; // all white spaces are skipped

Operator >> associates left to right cin >> x >> y; // is equivalent to

( cin >> x ) >> y; By default, the operator >> discards any intervening white

space ( blank, tab, newline, formfeed, and carriage return).Input sequence: 123 1

b c d cin >> int_var >> ch1 >>ch2 >> ch3 >>ch4;cout << int_var<<ch1<<ch2<<ch3<<ch4;

// prints 1231bcd 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

Page 20: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Formats Integer outputs

cout.setf(ios_base::oct, ios_base::basefield);cout << 1234; //print octal 2322cout.setf(ios_base::dec, ios_base::basefield);cout << 1234; //print decimal 1234 -- decimal is the default

Floating-point output cout << 1234.56789; // default output: 1234.57cout.setf(ios_base::scientific, ios_base::floatfield);cout << 1234.56789; // scientific format:

1.2345678e+003cout.setf(ios_base::fixed, ios_base::floatfield);cout << 1234.56789; // fixed point format: 1234.567890cout.setf(0, ios_base::floatfield); // reset default

cout.precision(8); // set precision to 8cout << 1234.56789; // print: 1234.5679

Above print results were generated with MS VC++ 6.0 and its standard iostream.

Page 21: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Formats Output fields

cout.width(4); // only affect the immediate << operationcout << 12; //print with two space in front of 12cout.width(4); cout.fill(‘#’);cout << 12; //print ##12cout.width(0); // print as many as needed

Field adjustment cout.width(4); cout.fill(‘#’);cout.setf(ios_base::left, ios_base::adjustfield); // leftcout.width(4); cout << -12; // print -12#cout.setf(ios_base::right, ios_base::adjustfield); // right -- defaultcout.width(4); cout << 12; // print ##12cout.setf(ios_base::internal, ios_base::adjustfield); // between sign

and #cout.width(4); cout << -12; // print -#12

Above print results were generated with MS VC++ 6.0 and its standard iostream.

Page 22: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Formats 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, 4d2, 2322.

cout << setw(6) << setfill(‘$’) << 12;// prints $$$$12.

When using manipulators that don’t take arguments, don’t add ().cout << hex() << 12; // error: hex doesn’t take arguments

make sure #include <iomanip> in your program Users may define their own manipulators The manipulators shown here are only some examples. For more

comprehensive descriptions, read Lippman’s and Strousptrup’s books. Above print results were generated with MS VC++ 6.0 and its

standard iostream.

Page 23: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

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

ostream& operator<<(ostream& os, const ClassType &obj){

// actual output of the members.os << // …

…// return ostream objectreturn os;

} General skeleton of an overloaded input operator

istream& operator>>(istream& is, ClassType &obj){

// actual input to the members.os >> // …

…// return istream objectreturn is;

}

Page 24: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Overloading the I/O operators << and >> 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;

}

Page 25: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Overloading the I/O operators << and >>

#include "stdafx.h"#include <iostream.h>

class base {public:

virtual ostream& put(ostream& s) {return s <<"Base\n";}

};

class derived: public base {public:

virtual ostream& put(ostream& s) {return s <<"Derived\n";}

};

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;

}

Virtual output functions The ostream members are not

virtual. 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.

Implementation Design a virtual put function

in the base and subclasses. virtual ostream& put(ostream& s); Call the virtual function in <<

from a reference to the base ostream& operator<<

(ostream& s, base& b){ return b.put(s);}

<< doesn’t need to be a friend of the classes in this example.

Page 26: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

File Input and Output To use file input and output, include

#include <fstream>using namespace std;

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);}

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. To open a file for append.

ofstream outfile(“filename”, ios_base::app);

Page 27: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

File Input and Output To open a file for input only.

ifstream infile(“filename”); if (!infile) { cerr <<“input file open failed\n”;

exit(-1); }

infile >> int_var;while (infile.get(ch)) cout.put(ch);

An fstream object can open a file for either input and output.fstream file; file.open(“filename”, ios_base::in); // open the file for inputfile >> wd;file.close();

file.open(“filename”, ios_base::app); // open the same file for output

file << endl << wd << endl;file.close();

An fstream object can open a file for both input and output.fstream file; file.open(“filename”, ios_base::in | ios_base::app);

Page 28: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Condition States Condition flags.

eof(): return true if end-of-file has been encountered.if (cin.eof() ) { // ok, input complete.}

bad(): return true if an invalid op. has been attemped -- file corrupted.if (cin.bad() ) { // file corrupted in some undefined way.}

fail(): return true if an o.p has been unsuccessful. Ex. Invalid input format

ifstream infile(“filename”);if (infile.fail() ) { // file open failed.}

good(): return true if previous operation was successful - file in good cond.

If (infile.good() ) { // continuing processing the file.} Two methods for modifying the condition states.

clear() resets the condition state to an explicit valuecin.clear(ios_base::goodbit); // reset cin to good condition

setstate(): 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.

To set multiple states,cin.setstate(ios_base::badbit | ios_base::failbit);

// set both bad state and fail state.

Page 29: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Summary of Module 5

Exception Handling Throwing an Exception and the Try Block Catching an Exception Exception Specifications Advanced Topics

C++ Stream I/O Input/Output of Built-in Types Formats Overloading the I/O Operators << and >> File Input and Output Condition States

Page 30: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Advice 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.

Overload << and >> for user-defined types with values that have meaningful textual representations.

Remember that by default >> skips white spaces Remember to #include <iomanip> when using standard

manipulators. Remember that the width manipulator applies to the following I/O

operation only. Define virtual input/output functions.

Page 31: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling

Programming Assignments Exception -- CDate

Modify the CDate example so that it throws exceptions when a value is out of valid range.

Group the exceptions in CDate into a class hierarchy. Use virtual functions to print offensive values (year, month, or day).

Write a main() to test those exceptions.

Exception -- An array class Design an array class that throws OutOfRange when the

subscript is of range. OutOfRange can print the size of the array and the offensive subscript.

Overload Operators << and >> Design virtual input and output functions for the CPerson-

CManager-CEngineer inheritance example. File Input/output

Design a program that counts the number of words and the number of white spaces in the input file.

Page 32: Introduction to C++ Programming Module 5 C++ Stream I/O and Exception Handling