_C Programming Column_ by Al Stevens Example 1: (a) using namespace Sysutils; (b) #include using namespace std; Listing One // ---- date.h #ifndef DATE_H #define DATE_H #include class BadDate { }; class CalendarDate { int m_nMonth, m_nDay, m_nYear; int ExtractDateComponent(const char** pText, int min, int max); void AppendDateComponent(string& rstrDate, int nComponent, bool bAddSlash = true) const; public: CalendarDate(const char* pText = 0) throw(BadDate); void BuildDateDisplay(string& rString) const; bool IsEmpty() { return m_nMonth == 0 && m_nDay == 0 && m_nYear == 0; } void NextMonth(); bool IsDecember() const { return m_nMonth == 12; } bool operator==(const CalendarDate& rDate) const { return rDate.m_nMonth == m_nMonth && rDate.m_nDay == m_nDay && rDate.m_nYear == m_nYear; } bool operator!=(const CalendarDate& rDate) const { return !(*this == rDate); } }; #endif Listing Two // --- Date.cpp #include #include #include "Date.h" // --- extract a Date component (mm/dd/yy) from a Date string int CalendarDate::ExtractDateComponent(const char** pText, int min, int max) { while (isspace(**pText)) (*pText)++; int nComponent = atoi(*pText); if (nComponent < min || nComponent > max) throw BadDate(); while (isdigit(**pText)) (*pText)++; while (isspace(**pText)) (*pText)++; return nComponent; } // --- construct a Date object from a Date string (mm/dd/yy) CalendarDate::CalendarDate(const char* pText) throw(BadDate) { m_nMonth = 0; m_nDay = 0; m_nYear = 0; if (pText == 0) return; m_nMonth = ExtractDateComponent(&pText, 0, 12); if (m_nMonth == 0 && *pText == '\0') return; if (*pText != '/' ) throw BadDate(); pText++; m_nDay = ExtractDateComponent(&pText, 1, 31); if (*pText != '/' ) throw BadDate(); pText++; m_nYear = ExtractDateComponent(&pText, 0, 99); if (*pText != '\0' ) throw BadDate(); // --- validate day based on month, year if (m_nMonth == 2) { if (m_nDay > 29 || (m_nDay == 29 && ((m_nYear % 4) || m_nYear == 0))) throw BadDate(); } else if (m_nDay == 31) if (m_nMonth == 4 || m_nMonth == 6 || m_nMonth == 9 || m_nMonth == 11) throw BadDate(); } // --- append to a display string a component of a Date object void CalendarDate::AppendDateComponent(string& rstrDate, int nComponent, bool bAddSlash) const { if (nComponent < 10) rstrDate += "0"; char str[5]; itoa(nComponent, str, 10); rstrDate += str; if (bAddSlash) rstrDate += "/"; } // --- build a display string from a Date object void CalendarDate::BuildDateDisplay(string& rstrDate) const { rstrDate = ""; AppendDateComponent(rstrDate, m_nMonth); AppendDateComponent(rstrDate, m_nDay); AppendDateComponent(rstrDate, m_nYear, false); } // --- increment date by one month void CalendarDate::NextMonth() { if (++m_nMonth == 13) { m_nMonth = 1; if (++m_nYear == 100) m_nYear = 0; } } Listing Three // ---- mortgage.h #ifndef MORTGAGE_H #define MORTGAGE_H #include "Date.h" struct Mortgage { double m_nPrincipal; // loan amount in $ double m_nInterest; // monthly interest rate int m_nTerm; // loan term in months CalendarDate m_PaymentDate; // date of first payment CalendarDate m_BalloonDate; // date of balloon payment double Payment(); // compute and return monthly payment }; #endif Listing Four // --- mortgage.cpp #include #include "mortgage.h" double Mortgage::Payment() { double nPayment = ((double)((long)(((m_nPrincipal*m_nInterest)/ (1-pow((1/(1+m_nInterest)),m_nTerm))+.005)*100)))/100; return nPayment; } Listing Five //--------------------------------------------------------------------------- #include #pragma hdrstop //--------------------------------------------------------------------------- USEFORM("mortdata.cpp", Form1); USERES("Amort.res"); USEFORM("Schedule.cpp", Schedule); USEUNIT("Date.cpp"); USEUNIT("mortgage.cpp"); //--------------------------------------------------------------------------- WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->CreateForm(__classid(TSchedule), &Schedule); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } return 0; } //--------------------------------------------------------------------------- Listing Six //--------------------------------------------------------------------------- #ifndef AmortH #define AmortH //--------------------------------------------------------------------------- #include #include #include #include #include #include "mortgage.h" //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TLabel *Label1; TLabel *Label2; TLabel *Label3; TLabel *Label4; TLabel *Label5; TLabel *Label6; TEdit *Principal; TEdit *Interest; TEdit *Term; TEdit *PaymentDate; TEdit *BalloonDate; TButton *Compute; TLabel *Payment; TButton *DisplaySchedule; void __fastcall ComputeClick(TObject *Sender); void __fastcall DisplayScheduleClick(TObject *Sender); private: // User declarations Mortgage m_Mortgage; bool m_bScheduleOK; public: // User declarations virtual __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern TForm1 *Form1; //--------------------------------------------------------------------------- #endif Listing Seven //--------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include "mortdata.h" #include "schedule.h" #include "Date.h" //--------------------------------------------------------------------------- #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::ComputeClick(TObject *Sender) { m_bScheduleOK = false; bool bPrincipalOK = false; if (Principal->Text != "") { m_Mortgage.m_nPrincipal = Principal->Text.ToDouble(); bPrincipalOK = m_Mortgage.m_nPrincipal > 0; } if (!bPrincipalOK) { MessageBox(0, "Invalid principal amount", "Error", MB_ICONERROR); return; } bool bInterestOK = false; if (Interest->Text != "") { double nInterest = Interest->Text.ToDouble(); m_Mortgage.m_nInterest = nInterest / 100 / 12; bInterestOK = nInterest > 0; } if (!bInterestOK) { MessageBox(0, "Invalid interest amount", "Error", MB_ICONERROR); return; } bool bTermOK = false; if (Term->Text != "") { m_Mortgage.m_nTerm = Term->Text.ToInt() * 12; bTermOK = m_Mortgage.m_nTerm > 0; } if (!bTermOK) { MessageBox(0, "Invalid term", "Error", MB_ICONERROR); return; } m_bScheduleOK = true; double nPayment = m_Mortgage.Payment(); strstream strPmt; strPmt << setprecision(2) << setiosflags(ios::fixed | ios::right) << nPayment; Payment->Caption = strPmt.str(); } //--------------------------------------------------------------------------- void __fastcall TForm1::DisplayScheduleClick(TObject *Sender) { ComputeClick(Sender); if (m_bScheduleOK) { try { m_Mortgage.m_PaymentDate = CalendarDate(PaymentDate->Text.c_str()); if (m_Mortgage.m_PaymentDate.IsEmpty()) throw BadDate(); m_Mortgage.m_BalloonDate = CalendarDate(BalloonDate->Text.c_str()); Schedule->DisplaySchedule(m_Mortgage); } catch (BadDate) { MessageBox(0, "Invalid date", "Error", MB_ICONERROR); return; } } } //--------------------------------------------------------------------------- 1