Friday, May 19, 2017

Programming Challenge 10.19 - Check Writer

Include File: "EvalDate.h"

/* Check Writer - This program display a simulated paycheck. The program asks
   the user to enter the date, the payee's name, and the amount of the check
    (up to $10,000). It then displays a simulated check with the dollar amount
    spelled out, as in the following example:
  
                                                                            * Date: 11/24/2014
        * Pay to the Order of: Mori Yuki                              $1920.85
        * One thousand nine hundred twenty and 85 cents

    The numeric value is formatted in fixed-point notation with two decimal
    places of precision. The decimal place is always displayed, even when the
    number is zero or has no fractional part. String class objects are used in
    this program.

    Input Validation: No negative dollar amounts, or amounts over $10,000 are
    accepted. */

#include "Utility.h"
#include "EvalDate.h"

char     tryAgain();
void   getData(string &, string &, string &);
void   checkRecipient(string &);
void   checkDate(string);
void     checkAmount(string &);
string removePunct(string &);
string toHundred(const string *, const string *, int);
string toThousand(string, const string *, int);
string toTenThousand(string, const string *, int);
string numToWord(string);
string formatCheck(string, string &, string);
void   displayCheck(string, const string, const string, const string);

int main()
{
    string amount;
    string dueDate;
    string recipient;
    string centAmount;
    string wordAmount;
    char   again = ' ';

    do
    {
        amount.clear();
        dueDate.clear();
        recipient.clear();
        wordAmount.clear();
        centAmount.clear();

                         getData(amount, dueDate, recipient);
        wordAmount = formatCheck(amount, wordAmount, centAmount);
                         displayCheck(amount, dueDate, recipient, wordAmount);

        again = tryAgain();

        if (again == 'N')
        {
            cout << "\n\tThe Ishikawa Bank wishes to thank you for doing\n"
                  << "\tbusiness with us! Have a nice day!\n\n";
        }

    } while (again != 'N');

    pauseSystem();
    return 0;
}

/* **********************************************************
   Definition: getData

    This function asks for the recipient's name, the check's
    date, and the amount. Various tests are performed on each
    item, before the contents is passed back.
   ********************************************************** */

void getData(string &amount, string &dueDate, string &recipient)
{
    cout << "\n\n\t\t\tISHIKAWA BANK - CHECK WRITER\n\n"
          << "\n\tPlease enter the recipient's name: ";
    getline(cin, recipient);

        while (recipient.empty())
        {
            cout << "\n\tDear customer, the name field must not be empty!\n\n"
                << "\tPlease enter the recipient's name: ";
            getline(cin, recipient);
        }

    checkRecipient(recipient);

    cout << "\n\tPlease enter today's date, or date you would like\n"
          << "\tthe check cashed (Ex: 05/08/2017): ";
    getline(cin, dueDate);

    checkDate(dueDate);

    cout << "\n\tPlease enter the desired amount: $";
    getline(cin, amount);

    checkAmount(amount);
}

/* **********************************************************
   Definition: checkRecipient

    This function performs various checks on the string object
    containing the recipient's name.
   ********************************************************** */

void checkRecipient(string &recipient)
{
    for (size_t index = 0; index < recipient.length(); index++)
    {
        while (!isalpha(recipient.at(0)) || ispunct(recipient[index]) ||
                isdigit(recipient.at(index)) || isspace(recipient.at(0)))
        {
            cout << "\n\tDear customer, the name field must not be empty, and\n"
                  <<  "\tit must not contain any numbers or punctuation marks!\n\n"
                  << "\n\tPlease enter the recipient's name: ";
            getline(cin, recipient);
        }
    }
}

/* **********************************************************
    Definition: checkDate

    This function checks whether the date and date-format is
    correct. The function performing the checks is contained
    in the header file: "EvalDate".
    ********************************************************** */

void checkDate(string dueDate)
{
    while (evalDate(dueDate) == false)
    {
        cout << "\n\tDear customer, the entered date, and/or\n"
              << "\tdate-format seems to be invalid.\n\n"
              << "\tPlease enter today's date, or date you would like\n\n"
              << "\tthe check cashed (Ex: 05/08/2017): ";
        getline(cin, dueDate);

        evalDate(dueDate);
    }
}

/* **********************************************************
   Definition: checkAmount

    Checks for validity of the entered amount. It must not be
    lower than 0.00 or higher than 9999.99.
   ********************************************************** */

void checkAmount(string &amount)
{
    while (stod(amount) <= 0.00 || stod(amount) > 9999.99)
    {
        cout << "\n\tInput Failure! Dear customer, you entered an amount\n"
              << "\tlower than 1 or greater than 9999.99. The maximum\n"
              << "\tamount is $9999.99.\n\n"
              << "\n\tPlease enter the desired amount:\t\t$";
        getline(cin, amount);
    }
}

/* **********************************************************
   Definition: numToTword

    This function "converts" numbers between 1 and 9999.99 to
    words. This is achieved by accessing two arrays containing
    number words, by their subscript index. The result is
    stored in a string object. This string object is returned.
   ********************************************************** */

string numToWord(string amount)
{
    const string oToTwenty[] = { "", "one ", "two ", "three ", "four ", "five ",
                                          "six ", "seven ", "eight ", "nine ", "ten",
                                          "eleven ", "twelve ", "thirteen ", "fourteen ",
                                          "fifteen ", "sixteen ", "seventeen ", "eighteen ",
                                          "nineteen " };

    const string tenMult[]   = { "", "", "twenty ", "thirty ", "fourty ", "fifty ",
                                          "sixty ", "seventy ", "eighty ", "ninenty " };

    int     numStore = stoi(amount);
    string numWord;
    string words;

    if (amount.length() < 3)
    {
        words = toHundred(oToTwenty, tenMult, numStore);
    }
    else if (amount.length() == 3)
    {
        words = toThousand(amount, oToTwenty, numStore) +
                  toHundred(oToTwenty, tenMult, numStore % 100);
    }
    else if (amount.length() == 4)
    {
        if (numStore % 1000 < 100)
        {
            words = toTenThousand(amount, oToTwenty, numStore) +
                      toHundred(oToTwenty, tenMult, numStore % 100);
        }
        else
        {
            words = toTenThousand(amount, oToTwenty, numStore) +
                      toThousand(amount, oToTwenty, numStore) +
                      toHundred(oToTwenty, tenMult, numStore % 100);
        }
    }
  
    return numWord.append(words);
}

/* **********************************************************
  Definition: toHundred

    This function gets the index positions of the "tens" and
    "ones" place stored in amount. It covers amounts between
    1 and 99. The position is stored, and the result appended
    in a string object. The string object is returned.
    ********************************************************** */

string toHundred(const string *oToTwenty,
                      const string *tenMult, int numSize)
{
    string numStore;
  
    numSize < 20 ? numStore.append(oToTwenty[numSize])   :
                        numStore.append(tenMult[numSize / 10] +
                                             oToTwenty[numSize % 10]);

    return numStore;
}

/* **********************************************************
   Definition: toThousand

    This function gets the index position of the "hundreds"
    place stored in amount. This is achieved by storing the
    subscript positions contained in amount, and erasing the
    contents before it. The result is appended to a string
    object. This string object is returned.
   ********************************************************** */

string toThousand(string amount, const string *oToTwenty, int numSize)
{
    string numStore;
  
    /* This if/else statement covers all sums above and below
        below 1000. Depending on which, the corresponding subscript
        position is extracted and stored in numSize. numSize, after
        performing a calculation on it, points to the appropriate
        position in the string array containing the digit in word-
        form. */
    if (numSize > 999)
    {
        numSize = stoi(amount.erase(2, 3));
        numStore.append(oToTwenty[numSize % 1000 % 10] + "hundred ");
    }
    else
    {
        numSize = stoi(amount.erase(1, 2));
        numStore.append(oToTwenty[numSize] + "hundred ");      
    }

    return numStore;
}

/* **********************************************************
   Definition: toTenThousand

    This function gets the index position of the "thousands"
    place stored in amount. This is achieved by storing the
    first subscript position contained in amountm and erasing
    the remaining contents. The result is appended to a string
    object. This string object is returned.
   ********************************************************** */

string toTenThousand(string amount, const string *oToTwenty, int numSize)
{
    string numStore;

    numSize = stoi(amount.erase(1, 3));

    return numStore.append(oToTwenty[numSize] + "thousand ");
}

/* **********************************************************
   Definition: removePunct

    This function does three things:

        * If the user enters an amount like "256.60", the
          cent amount is stored in a string object, and the
          '.' is erased.
        * If the user enters an amount like "256" without '.',
          '00' is appended to 'centAmount'.
        * If the user enters an amount like "256.2", a '0' is
          appended.

    The cent amount stored in the string object is returned.
   ********************************************************** */

string removePunct(string &amount)
{
    string centAmount;
  
    for (size_t index = 0; index < amount.length(); index++)
    {
        if (ispunct(amount.at(index)))
        {
            centAmount.append(amount, index + 1, 3);  
            amount.erase(index, 3);          
        }  
    }

    if (centAmount.empty())
    {
        centAmount.append("00");
    }
    else if (centAmount.length() == 1)
    {
        centAmount.append("0");
    }

    return centAmount;
}

/* **********************************************************
   Definition: formatCheck

    This function formats the check output, and stores the
    result in a string object. The string object is returned.
   ********************************************************** */

string formatCheck(string amount, string &wordAmount, string centAmount)
{
    centAmount = removePunct(amount);
    wordAmount = numToWord(amount);

    wordAmount.append("dollar(s) and " + centAmount + " cents");
    wordAmount.at(0) = toupper(wordAmount.at(0));

    return wordAmount;
}

/* **********************************************************
   Definition: displayCheck

    This function outputs the formatted check to screen.
   ********************************************************** */

void displayCheck(string amount, const string dueDate,
                        const string recipient, const string wordAmount)
{
    cout << fixed << showpoint << setprecision(2);
    cout << "\n\t" << setw(68) << setfill('-') << "\n\n";
    cout << setfill(' ') << "\n" << setw(64) << right
          << "Date: " << dueDate << "\n"
          << "\tPay to the order of: " << setw(28) << left << recipient
          << setw(2) << right << "$" << stod(amount) << "\n\n\t"
          << wordAmount << "\n\n\t"
          << "Ishikawa Bank\n\t"
          << "2-1-124 Chuo-ku\n\t"
          << "Tokyo, 105-0062\n\n\t"
          << "For: Donation" << setw(24) << "Your Signature: "
          << setw(31) << setfill('_') << "\n"
          << "\n\n\t" << setw(68) << setfill('-') << "\n";
}

/* **********************************************************
   Definition: tryAgain

    This function asks the user if he or she wishes to write
    another check. The decision is returned.
   ********************************************************** */

char tryAgain()
{
    char again = ' ';

    cout << "\n\n\tDo you wish to write another check? (y/N): ";
    cin >> again;
    cin.ignore();

    /* Input validation */
    while (toupper(again) != 'Y' && toupper(again) != 'N')
    {
        cout << "\n\tDo you wish to write another check? (y/N): ";
        cin >> again;
        cin.ignore();
    }

    return toupper(again);
}

Example Output:





No comments:

Post a Comment