This is the first program that I have written in my C++ saga that I actually think is useful. The description for this assignment is kinda long and mundane though:
Write a program that inputs a date (for example: July 4, 2008) and outputs the day of the week that corresponds to that date. The following algorithm is from Wikipedia. The implementation will require several functions.
bool isLeapYear(int year);
This function should return
true
ifyear
is a leap year andfalse
if it is not. Here is the pseudo code to determine a leap year:leap_year = (year divisible by 400) or (year divisible by 4 and not divisible by 100)
int getCenturyValue(int year);
This function should take the first two digits of the year (that is, the century), divide by \$ 4 \$, and save the remainder. Subtract the remainder from \$ 3 \$ and return this value multiplied by \$ 2 \$. For example, the year \$ 2008 \$ becomes \$ \dfrac{20}{4} = 5 \$ with a remainder of \$ 0 \$. \$ 3 - 0 = 3 \$. Return \$ 3 \cdot 2 = 6 \$.
int getYearValue(int year);
This functions computes a value based on the years since the beginning of the century. First, extract the last two digits of the year. For example, \$ 08 \$ is extracted for \$ 2008 \$. Next, factor in leap years. Divide the value from the previous step by \$ 4 \$ and discard the remainder. Add the two results together and return this value. For example, from \$ 2008 \$ we extract \$ 08 \$. Then \$ \dfrac{8}{4} = 2 \$ with a remainder of \$ 0 \$. Return \$ 2 + 8 = 10 \$.
int getMonthValue(int month, int year);
This function should return a value based on the table below and will require invoking the
isLeapYear()
function.$$ \newcommand\T{\Rule{0pt}{1em}{.5em}} \begin{array}{|c|c|} \hline \textbf{Month} & \textbf{Return Value} \\\hline \text{January} \T & 0 \left(6 \text{ if year is a leap year} \right) \\\hline \text{February} \T & 3 \left(2 \text{ if year is a leap year} \right) \\\hline \text{March} \T & 3 \\\hline \text{April} \T & 6 \\\hline \text{May} \T & 1 \\\hline \text{June} \T & 4 \\\hline \text{July} \T & 6 \\\hline \text{August} \T & 2 \\\hline \text{September} \T & 5 \\\hline \text{October} \T & 0 \\\hline \text{November} \T & 3 \\\hline \text{December} \T & 5 \\\hline \end{array} $$
Finally, to compute the day of the week, compute the sum of the date's day plus the values returned by
getMonthValue
,getYearValue
, andgetCenturyValue
. Divide the sum by \$ 7 \$ and compute the remainder. A remainder of \$ 0 \$ corresponds to Sunday, \$ 1 \$ corresponds to Monday, etc., up to \$ 6 \$, which corresponds to Saturday. For example, the date July 4, 2008 should be computed as (day of month) + (getMonthValue) + (getYearValue) + (getCenturyValue) = \$ 4 + 6 + 10 + 6 = 26 \$. \$ \dfrac{26}{7} = 3 \$ with a remainder of \$ 5 \$. The fifth day of the week corresponds to Friday.Your program should allow the user to enter any date and output the corresponding day of the week in English.
This program should include a
void
function namedgetInput
that prompts the user for the date and returns the month, day, and year using pass-by-reference parameters. You may choose to have the user enter the date's month as either a number (1-12) or a month name.
dayOfWeek.cpp
:
/**
* @file dayOfWeek.cpp
* @brief Computes the day of the week given a certain date
* @author syb0rg
* @date 10/23/14
*/
#include <cctype>
#include <iostream>
#include <limits>
enum Months {None, January, February, March, April, May, June, July, August, September, October, November, December};
std::string *weekDays = new std::string[7] {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
/**
* Makes sure data isn't malicious, and signals user to re-enter proper data if invalid
*/
size_t getSanitizedNum()
{
size_t input = 0;
while(!(std::cin >> input))
{
// clear the error flag that was set so that future I/O operations will work correctly
std::cin.clear();
// skips to the next newline
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid input. Please enter a positive number: ";
}
return input;
}
/**
* Safetly grabs and returns a lowercase version of the character (if the lowercase exists)
*/
char32_t getSanitizedChar()
{
// absorb newline character (if existant) from previous input
if('\n' == std::cin.peek()) std::cin.ignore();
return std::tolower(std::cin.get());
}
bool isLeapYear(const int year)
{
if (0 == (year % 400) || (0 == (year % 4) && (year % 100))) return true;
else return false;
}
int getCenturyValue(const size_t year)
{
return (2 * (3 - div(year / 100, 4).rem));
}
int getYearValue(const size_t year)
{
int mod = year % 100;
return (mod + div(mod, 4).quot);
}
int getMonthValue(const size_t month, const size_t year)
{
switch (month) {
case January:
if (isLeapYear(year)) return 6;
case October:
return 0;
case May:
return 1;
case August:
return 2;
case February:
if (isLeapYear(year)) return 2;
case March:
case November:
return 3;
case June:
return 4;
case September:
case December:
return 5;
case April:
case July:
return 6;
default:
return -1;
}
}
int dayOfWeek(const size_t month, const size_t day, const size_t year)
{
return div(day + getMonthValue(month, year) + getYearValue(year) + getCenturyValue(year), 7).rem;
}
void getInput(size_t &month, size_t &day, size_t &year)
{
std::cout << "Enter the month (1-12): ";
month = getSanitizedNum();
std::cout << "Enter the day (1-31): ";
day = getSanitizedNum();
std::cout << "Enter the year: ";
year = getSanitizedNum();
}
int main()
{
size_t month = 0;
size_t day = 0;
size_t year = 0;
do
{
getInput(month, day, year);
std::cout << "The day of the week is " << weekDays[dayOfWeek(month, day, year)] << std::endl;
std::cout << "Run the program again (y/N): "; // signify n as default with capital letter
} while ('y' == getSanitizedChar());
}