Download this source file (Date.cpp)
Download Date.exe


// Date.cpp - Demo of writting iostream functions (inserters and extractors).
// A simple date class with all member functions removed except
// the inserter and extractor members.  Note the use of the Alternate
// Constructor Syntax to initialize members.
// Written by Wayne Pollock, Tampa FL, 1999

#include <iostream>
#include <iomanip>

//using namespace std;  // This line would be needed for ISO Std C++

class myDate
{
 public:
   myDate ( int m = 1, int d = 1, int y = 1995 ) :
      month( m ), day( d ), year( y ) {}
   friend ostream& operator<< ( ostream& s, const myDate& d );
   friend istream& operator>> ( istream& s, myDate& d );

 private:
   int  month;
   int  day;
   int  year;
   static const int num_days[13];  // The entries 1-12 are used.
};

int main ()
{
   myDate date;

   cout << "Default value of a date is: " << date << endl;
   for ( ; ; )
   {  cout << "Please enter a date (m/d/y): " << flush;
      if ( cin >> date )
         break;                   // Date was read in successfully!
      cerr << "***Error!  Invalid date entered!\a\n" << endl;
      cin.clear();                // This clears all iostate flags.
      cin.ignore( 999, '\n' );    // Skip rest of bad date (to End of Line).
   }
   cout << "The date you entered is: " << date;
   return 0;
}

#ifdef COMMENTED_OUT

Default value of a date is: 1/1/95

Please enter a date (m/d/y): 2-25-95
***Error!  Invalid date entered!

Please enter a date (m/d/y): 2/30/96
***Error!  Invalid date entered!

Please enter a date (m/d/y): 10/31/96
The date you entered is: 10/31/96

#endif

const int myDate::num_days[13] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };


ostream& operator<< ( ostream& out, const myDate& d )  // Inserter.
{
   if ( out )             // Do nothing is output stream is in an error state.
   {  long oldFlags = out.flags();   // Save currnet formatting flags
      out << dec << setfill('0');
      out << setw(2) << d.month << "/" << setw(2) << d.day << "/";
      out << setw(2) << (d.year > 1900 ? d.year-1900 : d.year);
      out << endl;
      out.flags(oldFlags);                  // Restore previous formatting
   }
   return out;
}


istream& operator>> ( istream& in, myDate& d )       // Extractor.
{
   char c = '\0';
   const myDate old_date = d;   // Save current value in case of error.
   if ( in )                    // Only try input if input stream is OK.
      try
      {  if ( !( in >> d.month ) )  throw 1;
         if ( d.month < 1 || d.month > 12 )  throw 2;
         if ( !( in >> c ) )  throw 3;
         if ( c != '/' )  throw 4;
         if ( !( in >> d.day ) )  throw 5;
         if ( d.day < 1 || d.day > myDate::num_days[d.month] )  throw 6;
         if ( !( in >> c ) )  throw 7;
         if ( c != '/' )  throw 8;
         if ( !( in >> d.year ) ) throw 9;
         if ( d.year <=0 )  throw 10;
         if ( d.year < 100 )  d.year += 1900;  // ie, only 2 digits read.
      }  // End of try block
      catch ( int )
      {  in.clear( ios::failbit ); // This sets the iostate flag "failbit".
         d = old_date;             // Restore the original value of the date.
      }

      return in;
}