_C Programming Column_
by Al Stevens

Example 1:

(a)
using namespace Sysutils;

(b)
#include <string>
using namespace std;

Listing One
// ---- date.h
#ifndef DATE_H
#define DATE_H

#include <cstring.h>

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 <stdlib.h>
#include <ctype.h>
#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 <math.h>
#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 <vcl\vcl.h>
#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 <vcl\Classes.hpp>
#include <vcl\Controls.hpp>
#include <vcl\StdCtrls.hpp>
#include <vcl\Forms.hpp>
#include <vcl\Menus.hpp>
#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 <vcl\vcl.h>
#pragma hdrstop

#include <strstream>
#include <iomanip>
#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



