// A simple exception handling example. Checking for a divide-by-zero exception.
#include 
// Class DivideByZeroException to be used in exception 
// handling for throwing an exception on a division by zero.
class DivideByZeroException {
public:
   DivideByZeroException() 
      : message( "attempted to divide by zero" ) { }
   const char *what() const { return message; }
private:
   const char *message;
};

// Definition of function quotient. Demonstrates throwing 
// an exception when a divide-by-zero exception is encountered.
double quotient( int numerator, int denominator )
{
   if ( denominator == 0 )
      throw DivideByZeroException();
   return (double) numerator / denominator;
}

// Driver program
void main(void)
{
   int number1, number2;
   double result;

   cout << "Enter two integers (end-of-file to end): ";

   while ( cin >> number1 >> number2 ) {
      // the try block wraps the code that may throw an 
      // exception and the code that should not execute if an exception occurs
      try {   
         result = quotient( number1, number2 );
         cout << "The quotient is: " << result << endl;
      }
      catch ( DivideByZeroException ex ) { // exception handler
         cout << "Exception occurred: " << ex.what() << endl;
      }

      cout << "\nEnter two integers (end-of-file to end): ";
   }
   cout << endl;
   return 0;      // terminate normally
}


// resize1d.h
// change the size of a 1D array
template
void ChangeSize1D(T * &a, int n, int ToSize)
{// Change the size of the one-dimensional
 // array a to ToSize.  n is the number of elements in the array at present.
	
	// allocate a new array of desired size
	T *temp = new T [ToSize];
	if ( temp == NULL)
		throw NoMem();

	// copy from old space to new space
	if ( ToSize < n )
	   throw OutBoundary();
	
	for (int i = 0; i < ToSize; i++)
		temp[i] = a[i];

   // free old space
   delete [] a;
   // make a point to new space
   a = temp;
}

// exception classes for various error types
#ifndef XCEPT_H
#define XCEPT_H

// insufficient memory
class NoMem {
public:
	NoMem():message("there is no enough memory for allocation")
	{}
	const char *what() const {return message;}
private:
	const char *message;
};
// use when n > size
class OutBoundary {
public:
	OutBoundary():message("the array is not large enough")
	{}
	const char *what() const {return message;}
private:
	const char *message;
};
#endif
// driver.cpp for ArrayResize Project
#include 
#include 
#include "resize1d.h"
#include "xcept.h"
void main(void)
{	const int ArraySize = 20;
	int ActualSize, NewSize;
	int *x, i;
	try {	x = new int [ArraySize];
		if ( x == NULL )
			throw NoMem();
		cout << "Enter the actual size of the array: ";
		cin >> ActualSize;
		if ( ActualSize > ArraySize )
			throw OutBoundary();	
		for (i = 0; i < ActualSize; i++)
			x[i] = i;
		// print out the orinial array
		cout << "The original array is shown as: " << endl;
		for (i = 0; i < ActualSize; i++)
			cout << x[i] << " ";
		cout << endl;
		// change the array size 
		cout << "Enter a new size for the array: ";
		cin >> NewSize;
		ChangeSize1D(x, ActualSize, NewSize);
	}
   	catch (NoMem ex)	{
		cout << "Exception occurred: " << ex.what() << endl;
		exit(1);
	}
	catch (OutBoundary ex)	{
		cout << "Exception occurred: " << ex.what() << endl;
		exit(1);
	}
	catch(...) {
		cerr << "Uncaught system exception" << endl;
		exit(1);
	}	
	for (i = ActualSize; i < NewSize; i++)
		x[i] = i;
	// output
	cout << "The new array is shown as: " << endl;
	for (i = 0; i < NewSize; i++)
		cout << x[i] << " ";
	cout << endl;
}
// Demonstration of rethrowing an exception.
#include 
#include 

using namespace std;

void throwException() throw ( exception )
{
   // Throw an exception and immediately catch it.
   try {
      cout << "Function throwException\n";
      throw exception();  // generate exception
   }
   catch( exception e )
   {
      cout << "Exception handled in function throwException\n";
      throw;  // rethrow exception for further processing
   }

   cout << "This also should not print\n";
}   

void main(void)
{
   try {
      throwException();
      cout << "This should not print\n";
   }
   catch ( exception e )
   {
      cout << "Exception handled in main\n";
   }

   cout << "Program control continues after catch in main" 
        << endl;
   
}












// StackUnwinding.cpp
// Demonstrating stack unwinding.
#include 
#include 

using namespace std;

void function3() throw ( runtime_error )
{
   throw runtime_error( "runtime_error in function3" );
}

void function2() throw ( runtime_error )
{
   function3();
}

void function1() throw ( runtime_error )
{
   function2();
}

void main(void)
{
   try {
      function1();
   }
   catch ( runtime_error e )
   {
      cout << "Exception occurred: " << e.what() << endl;
   }
}