Learning Objectives
- To understand the use of library functions to perform interactive I/O using C++.
- To implement functions given prototypes and use them appropriately.
- To write logical expressions and selection statements in C++.
- To use loops appropriately in C++.
- To declare constants and variables appropriately.
Grading
- 60 points: correctness. Implement functions in cpp and create a birthday calculator. To what extent does your code implement the features required by our specification? To what extent is your code consistent with our specifications and free of bugs? To receive a 5% bonus for this part, submit it no later than Wed 10/04. To receive a 2.5% bonus, submit no later than Thu 10/05.
- 10 points: testing. To what extent is your code tested? Implement the testing functions and submit them via the cpp file. See the Testing section for more details.
- 10 points: style. To what extent is your code written well? To what extent is your code readable? Consult EECS 183 Style Guide and check the Style Checklist at the end of this project’s specification for some tips!
- This project must be completed individually, i.e., no partners.
Distribution Code
Just like for the last project, you’ll first download “distribution code” written by us, and add your own lines of code to it. You can download it either from the Schedule page of the course’s website or by clicking here on project2.zip. After downloading and unzipping it, you’ll find these files:
birthdays.cpp
Starter code for the application you will write in this project. Holds the definitions of required functions and the implementations of a couple functions. We have stubbed all required functions for you.
test.cpp
Testing functions for your birthdays.cpp implementation. Holds the definitions of required testing functions. We have stubbed all required functions for you.
Stubbing functions means adding the minimal necessary code to make a function compile. For example, some of the functions in birthdays.cpp have return types of bool. We have added return false in those functions so that they will compile even if you have not implemented all the functions yet. Be sure to remove our stubs when you write your own implementation of the function. |
Getting Started
- Before diving into the project, take a look through the Warm-Up section and make sure you feel comfortable with the questions provided.
Honor Code
All students in the class are presumed to be decent and honorable, and all students in the class are bound by the College of Engineering Honor Code.
- You may not seek to gain an unfair advantage over your fellow students;
- You may not consult, look at, or possess the unpublished work of another without their permission;
- You are not allowed to look at or in any way derive advantage from the existence of project specifications or solutions either for the current semester or for past semesters; and
- You must appropriately acknowledge your use of another’s work.
Any violation of the honor policies appropriate to each piece of course work will be reported to the Honor Council, and if guilt is established penalties may be imposed by the Honor Council and Faculty Committee on Discipline. Such penalties can include, but are not limited to, letter grade deductions or expulsion from the University.
Also note that on all cases forwarded to the Engineering Honor Council the LSA Dean of Academic Affairs is also notified. Furthermore, the LSA rule is that students involved in honor violations cannot withdraw from nor drop the course.
We run every submission against every other submission and determine similarities. All projects that are “too similar” are forwarded to the Engineering Honor Council. This happened to numerous students last semester. Also know that it takes months to get a resolution from the Honor Council. Discussion of the project will NOT be an issue. Sharing code between students will likely cause the cheating detector to identify both programs as “too similar”. We also search the web for solutions that may be posted online and add these into the mix of those checked for similarities. Searching the web, by the way, is something that we are very good at.
Also note that on all cases forwarded to the Engineering Honor Council the LSA Dean of Academic Affairs is also notified. Furthermore, the LSA rule is students involved in honor violations cannot withdraw from nor drop the course.
birthdays.cpp
In this project, you will develop a command-line application to calculate information regarding specific dates in the past and future.
Problem Statement
An old saying about the birthday of a child goes:
Monday’s child is fair of face,
Tuesday’s child is full of grace,
Wednesday’s child is full of woe,
Thursday’s child has far to go,
Friday’s child is loving and giving,
Saturday’s child works hard for a living,
But the child who is born on a Sunday
Is bonny, blithe, good and happy.
Your program will find out what day any given birthday was on. To enable possible future expansions, you will also include a menu system for your program. It might be interesting to see if any of these traits fit yourself or any other member of your family.
Solution Overview
- Write a program to determine the day of the week a person was born given their birthdate.
- Your program will provide a menu, implemented using a loop, to obtain user input and calculate birthdays.
Even though we are going over what happens in main() early in the specification, this does NOT mean you should begin your implementation with main(). Actually, you should write main() last. Since you need to write main() last, this means you can use it to test all of the individual functions you need to implement. |
- To begin, your program will call printHeading(), which will print this heading:
- *******************************
- Birthday Calculator
*******************************
- Next, your program will call getMenuChoice(), which will not only print the menu (there is a function that does this) but will be also be used to obtain user input for menu selection.
- The menu options are:
- Menu Options
- ————
- 1) Determine day of birth
- 2) Print the next 10 leap years
- 3) Determine birthdays for the next 10 years
- 4) Finished
Choice –>
- Depending upon the value the user enters for “Choice”, the program will either determine the day of your birthday, print 10 leap years, or print your birthdays for the next 10 years.
- Your program shall continue to calculate birthdays and prompt the user for another choice until a user input of ‘Finished’ (user choice 4) is entered.
- When the user input indicates that they’ve had enough and want out of the Birthday Calculator, your program will call printCloser(), which will print this heading:
- ****************************************************
- Thanks for using the Birthday Calculator
****************************************************
and the program naturally finishes.
- There are many functions that assist in making all of this happen. Below are details concerning the functions. The short version is available through the RME’s connected with each of the functions within birthdays.cpp.
printHeading()
- This function has been implemented for you.
- /**
- * Requires: nothing
- * Modifies: cout
- * Effects: prints out the initial heading for the program
- */
void printHeading();
- This function will print the following prompts:
- *******************************
- Birthday Calculator
*******************************
printCloser()
- This function has been implemented for you.
- /**
- * Requires: nothing
- * Modifies: cout
- * Effects: prints out the final greeting for the program
- */
void printCloser();
- This function will print the following prompts:
- ****************************************************
- Thanks for using the Birthday Calculator
****************************************************
printMenu()
- This function has been implemented for you.
- /**
- * Requires: nothing
- * Modifies: cout
- * Effects: prints the menu
- */
void printMenu();
- This function will print the following prompts:
- 1) Determine day of birth
- 2) Print the next 10 leap years
- 3) Determine birthdays for the next 10 years
- 4) Finished
Choice –>
getMenuChoice()
- This function will handle everything for printing the menu and handling input from the user.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /** * Note: write your test cases in main() BEFORE you implement this function * * Requires: nothing * Modifies: cout, cin * Effects: prints the menu * reads the input from the user * checks to make sure the input is within range for the menu * If not, prints “Invalid menu choice” * continues to print the menu and read an input until a valid one is entered * returns the users choice of menu options */ int getMenuChoice(); |
- This function will contain the following prompts, which print depending on program’s execution:
Invalid menu choice
- This function will call the following function(s):
- printMenu()
- Invalid input. You also cannot depend upon users to get the input within range. You also need to handle out of range input. (See Testing section for additional details.) If the user enters a menu option other than 1, 2, 3 or 4 you need to
- print Invalid menu choice
- re-print the menu, and
- get another menu choice
This needs to be repeated until a valid menu choice is entered
isGregorianDate()
- While checking for valid dates, you will find it necessary to ensure that the dates your user enters fall within the limits of the Gregorian calendar, meaning that the date occurs after September 13, 1752.
- The helper function isGregorianDate() will check whether or not a particular date is within the limits of the Gregorian calendar.
- /**
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: month, day, year may represent a date
- * Modifies: nothing
- * Effects: returns ‘true’ if the date is in the limits
- * of the Gregorian calendar otherwise returns ‘false’
- */
bool isGregorianDate(int month, int day, int year);
For example: 9 / 14 / 1752 and 1 / 10 / 1978 are valid Gregorian dates, while 9 / 10 / 1752, 9 / 13 / 1752 and 1 / 10 / 1751 are not.
isLeapYear()
- The function isLeapYear() will check whether or not a particular year is a leap year.
- /**
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: year is a Gregorian year.
- * Modifies: Nothing.
- * Effects: Returns ‘true’ if the year is a leap year,
- * otherwise returns ‘false’.
- */
bool isLeapYear (int year);
- In the Gregorian calendar, every year evenly divisible by 4 is a leap year, with the exception of the following conditions:
- If the year can be evenly divided by 100, it is NOT a leap year, unless:
- The year is also evenly divisible by 400. Then it is a leap year.
For example: 1768 is a leap year. 1800 is not a leap year. 2000 is a leap year.
isValidDate()
- In order to verify valid dates, you will need to implement the function isValidDate(). This function returns true if and only if (IFF) the provided month, day and year is a valid date.
- /**
- ** Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: month, day, year may represent a date.
- * Modifies: Nothing.
- * Effects: Returns ‘true’ if the date is valid,
- * otherwise returns ‘false’.
- */
bool isValidDate(int month, int day, int year);
- To know whether or not a date is valid, you will first need to check: (1) whether the date is within the Gregorian calendar limit and (2) whether the given year is a leap year. Therefore, isGregorianDate() and isLeapYear() both need to have been implemented. Also, this makes isGregorianDate() and isLeapYear() useful helper functions.
A helper function is a function written specifically to perform a task required by another function. In this case, isGregorianDate() and isLeapYear() serve as helper functions to isValidDate(). |
- At this point in your work, you may find the following poetic mnemonic useful:
Thirty days have September,
April, June, and November.
All the rest have 31,
Except for February all alone,
It has 28 each year,
but 29 each leap year.
- Here are some examples of invalid user input to get you started.
- Not a valid month: 13 / 20 / 1980.
- Not a valid day: 1 / 32 / 1980.
- Not a valid day: 4 / 31 / 2015.
- Before 9/14/1752: 5 / 23 / 1300.
- In all of these cases, your program should return false;.
All dates are entered MONTH / DAY / year and not DAY / MONTH / year. 9 / 12 / 2000 is the 12th of September and not the 9th of December. |
determineDay()
Now, you will implement determineDay() to compute the day of the week on which the date occurs. To do this, you will use Zeller’s Rule.
/**
* Note: write your test cases in main() BEFORE you implement this function
*
* Requires: month, day, year to form a valid date.
* i.e., the date passed to this function has already passed isValidDate()
* Modifies: Nothing.
* Effects: Returns the value that Zeller’s formula calculates.
*/
int determineDay(int month, int day, int year);
Zeller’s Rule
- The following formula is named Zeller’s Rule after Christian Zeller, a German mathematician. Using the month, day and year of a date, it computes the day of the week on which that date occurred/will occur.
f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7
MM is the number of the month (adjusted, see below).
- DD is the day.
- YY is the last two digits of the year number (possibly adjusted).
- CC is the century, i.e. the first two digits of the year number (possibly adjusted).
⌊x⌋⌊x⌋ means “the greatest integer that is smaller than or equal to xx ”, where ⌊3.14⌋⌊3.14⌋ becomes 33 and ⌊4⌋⌊4⌋ becomes 44 . This is the floor function in C++ that is defined in the cmath library. |
- For example,
- If the date is 5/3/2015 (May 3, 2015), then MM is 5, DD is 3, YY is 15, and CC is 20.
- If the date is 1/3/2015 (January 3, 2015). then MM is 13, DD is 3, YY will be 14, and CC is 20.
Remember to adjust the date provided by the user accordingly before performing your calculations. Calendar Adjustments |
- Zeller’s rule will return a number ff between 0 and 6. This “zero-indexed” number will correlate to a day of the week in the following manner:
ff | Day of the week |
0 | Saturday |
1 | Sunday |
2 | Monday |
3 | Tuesday |
4 | Wednesday |
5 | Thursday |
6 | Friday |
Calendar Adjustments
- Zeller’s Rule uses a calendar year beginning in March. To account for this, we count March as month 3, and January and February as months 13 and 14 of the previous year. The table below marks conversions.
Our calendar | Zeller’s calendar |
1/1/2015 | 13/1/2014 |
2/1/2015 | 14/1/2014 |
3/1/2015 | 3/1/2015 |
4/1/2015 | 4/1/2015 |
5/1/2015 | 5/1/2015 |
6/1/2015 | 6/1/2015 |
7/1/2015 | 7/1/2015 |
8/1/2015 | 8/1/2015 |
9/1/2015 | 9/1/2015 |
10/1/2015 | 10/1/2015 |
11/1/2015 | 11/1/2015 |
12/1/2015 | 12/1/2015 |
Example Calculations
- A detailed example of Zeller’s Formula is included below.
Date: January 29, 2064 (i.e., 1/29/2064)
M=13M=13 (remember Jan = 13, Feb = 14, March = 3, …)
D=29D=29
Y=63Y=63 (by Zeller’s calendar, the year is actually 2063)
C=20C=20
f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7=(29+⌊13(13+1)5⌋+63+⌊634⌋+⌊204⌋+5×20)mod7=(29+⌊36.4⌋+63+⌊15.75⌋+⌊5⌋+100)mod7=(29+36+63+15+5+100)mod7=248mod7=3f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7=(29+⌊13(13+1)5⌋+63+⌊634⌋+⌊204⌋+5×20)mod7=(29+⌊36.4⌋+63+⌊15.75⌋+⌊5⌋+100)mod7=(29+36+63+15+5+100)mod7=248mod7=3
33 corresponds to a Tuesday, so January 29, 2064 will be a Tuesday.
printDayOfBirth()
Make sure this function is declared and defined as printDayOfBirth and not printBirthday. |
- You will implement printDayOfBirth(), which prints the day of the week using the number you just calculated.
- /**
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: day (0 represents Saturday, 1 Sunday, 2 Monday, 3 Tuesday, etc)
- * Modifies: cout
- * Effects: prints the day you were born on
- * Sunday, Monday, …, Saturday
- */
void printDayOfBirth(int day);
- This function will contain the following prompts, which print depending on program’s execution:
- Saturday
- Sunday
- Monday
- Tuesday
- Wednesday
- Thursday
Friday
- day is the value calculated using Zeller’s rule. Use the table we provided above to determine the day of the week.
- For example, if day is 1, printDayOfBirth() will print
Sunday
determineDayOfBirth()
- This is the function that manages determining the day you were born on.
- /**
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: nothing
- * Modifies: cout, cin
- * Effects: Asks for the Month/day/year of their birth
- * If the date is valid, it will print the day
- * of the week you were born on
- * Otherwise, it will print “Invalid date” prompt
- */
void determineDayOfBirth();
- This function will contain the following prompts, which print depending on program’s execution:
- Enter your date of birth
- format: month / day / year –>
- Invalid date
- You were born on a:
Have a great birthday!!!
Make sure you use the “prompts” exactly as listed in the description for this function. |
- This function will call the following function(s):
- isValidDate()
- determineDay()
- printDayOfBirth()
- This is the function that will:
- Input the date.
- Check to see if it is valid. If the date isn’t valid, it will print the error message Invalid date. If it is, it will
- print the day of the week you were born on.
- tell you to Have a great birthday!!!
Dates should always be entered with spaces between the /. For example, 12 / 20 / 1980 is acceptable while is 12/20/1980 is not. *The absence of such spaces would be considered “bad input,” which you do not have to check for (see Testing for details). | |
For purposes of this project, even if the user enters a birthday that has not yet taken place, your program shall still use the past tense You were born on a: . |
- This function calls several of the other functions you have already written.
print10LeapYears()
- This is the function that asks the user for a Gregorian year and prints the first 10 leap years occurring after (not including) the input year.
- /**
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: nothing
- * Modifies: cin, cout
- * Effects: Asks for a Gregorian year and prints the
- * 10 leap years after (not including) the year entered.
- * If the year is invalid, it prints nothing.
- */
void print10LeapYears();
- This function will contain the following prompts, which print depending on program’s execution:
- Enter year –>
Leap year is
Make sure you use the “prompts” exactly as listed in the description for this function. |
- This function will call the following function(s):
- isLeapYear()
print10Birthdays()
- For the base project the only thing this function needs to do is print
Under Construction
Only the S’more version needs to totally implement this function.
Putting it Together
- Once you have written and tested each of the above functions, it is time to combine everything in main() and do further testing with your new debugging skills. Be sure that your program behaves as illustrated in the Sample Output.
- This function will call the following function(s):
- printHeading()
- getMenuChoice()
- determineDayOfBirth()
- print10Birthdays()
- print10LeapYears()
- printCloser()
Sample Output
Here are a few examples of the way your program output should look, wherein red underlined text represents some user’s input.
The following sample runs do not necessarily correspond to the Sample Run tests of the project autograder. |
Sample run 1
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 1
Enter your date of birth
format: month / day / year –> 9 / 31 / 1980
Invalid date
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 1
Enter your date of birth
format: month / day / year –> 1 / 25 / 1956
You were born on a: Wednesday
Have a great birthday!!!
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
Sample run 2
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 5
Invalid menu choice
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
Sample run 3
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 1
Enter your date of birth
format: month / day / year –> 9 / 13 / 1752
Invalid date
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 1
Enter your date of birth
format: month / day / year –> 19 / 13 / 1982
Invalid date
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 1
Enter your date of birth
format: month / day / year –> 9 / 13 / 1982
You were born on a: Monday
Have a great birthday!!!
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 3
Under Construction
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
Sample run 4
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 2
Enter year –> 1978
Leap year is 1980
Leap year is 1984
Leap year is 1988
Leap year is 1992
Leap year is 1996
Leap year is 2000
Leap year is 2004
Leap year is 2008
Leap year is 2012
Leap year is 2016
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
Sample run 5
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 2
Enter year –> 1980
Leap year is 1984
Leap year is 1988
Leap year is 1992
Leap year is 1996
Leap year is 2000
Leap year is 2004
Leap year is 2008
Leap year is 2012
Leap year is 2016
Leap year is 2020
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
Testing
- As part of this project, you will also submit any code that you write for testing the functions you implement in cpp. It is important to note that you will only be testing your program for invalid input rather than bad input. For the purposes of this document, “bad input” will refer to input whose type (char, int, double, etc.) is different than what is expected by your program. So if your program is expecting that the user will input an integer — you are guaranteed to always receive input of type int and will not receive something like char, which would be considered bad input. On the other hand, you will be testing for “invalid input,” which has the correct type but is considered invalid given the program specification. For example, if you have
int age;
declared in your program, you should probably include a check
if (age < 0) {
// handle invalid input
}
somewhere in your program. The RME’s will be clear about what is considered to be invalid input for a specific function.
- One question you might have is: how do I know that I have enough tests? In practice, the answer to this question is almost always “not enough.” However, for this project, you can take advantage of cpp and the autograder. You will write your test functions in test.cpp and submit it to the autograder. (See How to Submit section.) The autograder will run your test suite against buggy programs in order to see if your tests can expose enough bugs. The nature of the bugs will be hidden from you so you will have to think about how invalid input may affect your program and cause it to produce incorrect behavior given specifications.
Remember, you only have to think about exposing bugs related to invalid input and not bad input. |
Testing Overview
- It is considered good practice to write the test suite BEFORE you implement a function. The idea is to know if you are correct or not without using a submit to the autograder. This is also a very good way to cut coding time by a significant amount.
The basic idea of testing is you start small and build. Start with the obvious inputs needed then expand to the boundary conditions, and then expand further into the what else category. |
- Remember, a computer does not interpret. If you misspell a word, you will fail all autograder test cases. If you omit punctuation, you will fail all autograder test cases. We strongly suggest you test your code. Use diff tools to compare the Sample Output against the output generated by your code using the same input. Some easy-to-use diff websites that we recommend are:
For this project, we will not check differences in whitespace; “hello ” and “hello” are considered to be equivalent. This will not be the case in future projects. |
Testing getMenuChoice()
- To test getMenuChoice(), you do NOT need any of the other functions implemented. You should test it thoroughly now, then if something goes wrong with your code in the future you will know it is NOT this function. This method of testing will save you mega-time.
- To test getMenuChoice(), you need to check it against good input and invalid input. Therefore, to test it, call it within int main() and make sure you get the output and action you expect.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void test_getMenuChoice(); int main() { test_getMenuChoice(); } void test_getMenuChoice() { cout << “testing good input” << endl; cout << getMenuChoice() << endl; // input 1 cout << getMenuChoice() << endl; // input 2 cout << getMenuChoice() << endl; // input 3 cout << “testing bad input” << endl; cout << getMenuChoice() << endl; } |
- For “good input”, you may want to check 1, 2, 3 and 4. Run your code. Make absolutely sure all works as it should.
- Now that we have laid out the testing approach for getMenuChoice(), take the concepts and apply them to all the other functions. You can do this. Just follow the same line of thinking.
Testing isValidDate()
- To test isValidDate(), write your own tests inside the function called test_isValidDate().
- Values for valid and invalid months.
- Values for valid and invalid days.
- Days that are valid for Jan but not for Feb, etc.
- Days that are valid for March but not for April, etc.
- Values for valid and invalid Gregorian years.
- Values for February 29 if it is a leap year and if it isn’t a leap year.
- Then call your test_isValidDate() function within main().
Testing isLeapYear()
- Write your own function test_isLeapYear() and call it within main()
bool isLeapYear(int year) has a “Requires” clause of “year must be a Gregorian year” |
- What this means is you can — and should — test:
- // because 2015 is a Gregorian year
- cout << isLeapYear(2015) << endl;
- However, the year 1750 is not a Gregorian year. The date must strictly after September 13, 1752 to be Gregorian. Therefore, even though it is “legal” within C++ to write
- // invalid test case
- cout << isLeapYear(1750) << endl;
- It violates the Requires clause and the programmer should not do this. It is the responsibility of the coder to not violate the Requires clauses.
- What dates will thoroughly test isLeapYear()?
Hint: you will need four of them.
Preparing your test.cpp
- Once you have written all your tests and have successfully executed them from main(), copy all test-related code into your cpp file. This will include:
- The code that you wrote inside of each of the test functions like: test_isLeapYear(), test_isValidDate(), etc.,
- The code you wrote inside main() to execute the test functions.
- Now submit your cpp to the autograder (How to Submit) to see how many bugs your tests exposed. Once you have successfully submitted your tests, you can remove the testing code from your main() in birthdays.cpp and write the main function for your program.
Bugs To Expose
There are a total of 8 unique bugs to find in our implementations. Your tests do not need to expose all of the bugs to receive full points for the lab. The autograder will tell you the names of the bugs that you have exposed, from the following set:
- CHECK_GREG_MONTH
- CHECK_GREG_DAY
- CHECK_GREG_BASE
- CHECK_GREG_BASE2
- CHECK_LEAP_YEAR
- VALID_LEAP_YEAR
- CONVERT_MONTHS
- CHECK_VALID_DATE
How to Submit
- Write your program using Visual Studio or Xcode as described in lecture and discussion section. Your program must be written and documented to comply with the Style Guidelines provided for EECS 183.
- You must submit both cpp and test.cpp for grading.
- Head to the course Schedule.
- Choose Submit or Submit (test) where you find Project 2 due on the schedule.
- On the new page, click Choose file and navigate to your file. The file you submit to the autograder MUST be called: cpp or test.cpp.
- If confident that you’ve selected the correct file, click Submit to submit your code to the Autograder.
- For each part of the Project (cpp and test.cpp)…
- You have 2 submissions with feedback per day.
- You also have one additional “wildcard” submission with feedback.
- We provide some information regarding the tests that you do not pass. However, it is our intent that you learn to develop code independently. It’s important to have tests to tell you whether or not your code works, but real life does not have an autograder. Providing complete feedback from our own tests will hurt your ability to learn to test.
- You have an infinite number of submits per day, but only the first two submits per day return autograder feedback and a score. Any additional submits are “blind submits,” which do not return autograder feedback — not even a score. Be very cautious with these or you may be surprised by your grade.
- Remember: your last submit is the one we grade, even if an earlier submit would have a higher score. We do not accept submissions via email.
For this project, we will not check differences in whitespace; “hello ” and “hello” are considered to be equivalent. This will not be the case in future projects. |
S’more
- Want more? Try implementing S’more! Calculate the weekday of every birthday you will have for the next ten years and print it, so that you can plan an awesome party every year!
You must first complete and submit to the Autograder the Regular version of the project. |
- You’ll have to update the functionality and RME for one function, print10Birthdays(). Your code should accomplish the printing of the ten years’ birthdays by implementing a loop which will print the birthdays iteratively.
- /**
- * NOTE: for the base project the ONLY thing this function need to do is:
- * “Under Construction”
- *
- * S’more version of this function
- * Note: write your test cases in main() BEFORE you implement this function
- *
- * Requires: nothing
- * Modifies: cout, cin
- * Effects: reads the month and day of birthday
- * loops through 10 years printing the day of the week
- * the birthday falls on
- * if the month/day is not valid, it prints nothing
- * Notes:
- * 1) A loop must be used
- * 2) The only time “Invalid date” will print is when none of the 10 years
- * are valid
- * 3) For a date of Feb 29th, you will have few outputs
- */
void print10Birthdays();
- This function will contain the following prompts, which print depending on program’s execution:
- Enter the month and day of your birth
- format: month / day –>
- Birthday in [YEAR] is on a:
Invalid date
[YEAR] will be a year, such as 2018.
- The S’more version will fully implement the print10Birthdays() years function. This function begins by asking the user for his or her birth month and day, but not year. Then, print the days of the week for every birthday for the next ten years, starting with this calendar year.
- Your function shall prompt the user to enter their birth month and day.
- Enter the month and day of your birth
format: month / day –>
- For every year of the next ten years (starting with this calendar year), this function will print the year and day of the week in this format:
Birthday in 2018 is on a: Monday
- Each birthday should be verified as a valid date by calling the isValidDate() function with the user input month and day, as well as the year.
- If your birthday falls upon the extra day of a leap year (i.e., leap day, February 29th), you will print only the years for which you will have a birthday on the exact day of your birth. If the month/day input has no valid date for all ten years, your function will instead print
Invalid date
and return to the user to the Menu Options display again. Just as in the base version, your program shall continue to calculate birthdays until a user input of finished (user choice 3) is entered. Your program will call printCloser(), and exit just as the Regular version of the project.
Sample Output
Here are a couple examples of the way your program output should look, wherein red underlined text represents some user’s input.
S’more sample run 1
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 3
Enter the month and day of your birth
format: month / day –> 1 / 1
Birthday in 2018 is on a: Monday
Birthday in 2019 is on a: Tuesday
Birthday in 2020 is on a: Wednesday
Birthday in 2021 is on a: Friday
Birthday in 2022 is on a: Saturday
Birthday in 2023 is on a: Sunday
Birthday in 2024 is on a: Monday
Birthday in 2025 is on a: Wednesday
Birthday in 2026 is on a: Thursday
Birthday in 2027 is on a: Friday
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
S’more sample run 2
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 3
Enter the month and day of your birth
format: month / day –> 8 / 16
Birthday in 2018 is on a: Thursday
Birthday in 2019 is on a: Friday
Birthday in 2020 is on a: Sunday
Birthday in 2021 is on a: Monday
Birthday in 2022 is on a: Tuesday
Birthday in 2023 is on a: Wednesday
Birthday in 2024 is on a: Friday
Birthday in 2025 is on a: Saturday
Birthday in 2026 is on a: Sunday
Birthday in 2027 is on a: Monday
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
S’more sample run 3
*******************************
Birthday Calculator
*******************************
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 3
Enter the month and day of your birth
format: month / day –> 27 / 33
Invalid date
Menu Options
————
1) Determine day of birth
2) Print the next 10 leap years
3) Determine birthdays for the next 10 years
4) Finished
Choice –> 4
****************************************************
Thanks for using the Birthday Calculator
****************************************************
How to Submit
- When ready to submit the implementation of S’more to the Autograder, visit Schedule to find the Submit (S’more) link.
- Choose Submit (S’more) where you find Project 2 Due.
- On the new page, click Choose file and navigate to your file. The file you submit to the autograder MUST be called cpp.
- If confident that you’ve selected the correct file, click Submit to submit your code to the Autograder.
- Make sure to first submit the Regular version for project. S’mores are for additional practice and not for the points. However, we do take correct S’mores into consideration when we determine final grades.
Don’t forget to submit your regular version of the project, even if you submit a S’more version. Your project grade comes from your submission for the regular version. |
Appendices
Warm-Up
- What does the ! operator do?
- How can you determine if a number is evenly divisible by another? In other words, how can you check if the remainder is zero?
- How can you get the last digit of a number?
- How can you get the first digit of a number between 100 and 999?
- What’s the purpose of a function, such as sqrt or getline?
- What’s the difference between a function’s declaration (aka prototype) and a definition (aka implementation).
- Suppose you have this code that defines a function called half:
1 2 3 4 | double half(int number) { double answer = (double) number / 2; return answer; } |
- What’s int number on line 1?
- What does (double) (the one inside parentheses) do on line 2?
- How would you use this function in main?
- Write a function that accepts one argument, an int, and checks if it’s even by returning true if it is and false
- Write the line of code that checks if 7 is an even number using the above function.
- Head over to the EECS 183 Style Guide and read the section about Functions, Conditions and Loops.
- What’s the purpose of the Requires clause?
- How are while loops different from for loops? When would you use each?
- What’s a breakpoint?
- What’s the difference between step over and step into commands?
- How do you determine the value a variable has on a specific line of code?
Style Checklist
To maximize your style points, be sure to follow this non-exhaustive checklist:
- Review EECS 183 Style Guide. While all sections are important and relevant for this project, pay particular attention to Functions, Conditions and Loops.
- Review the style grading rubric for Project 2.
- Be sure you’ve included your name, your uniqname and a small description of the program in the header comments
- Be sure that your code is well-commented. It might at first seem that the algorithm is straight-forward and self-explanatory, but would you remember all the details a month from now? And it’s much easier for the staff to help you with your code if you have comments!
- Be sure to use camelCase for names of variables and functions in this project. We used camelCase for the functions we ask you to implement, and it is important that you stay consistent.
- Be sure that your variable names are descriptive. Don’t use names like d, Y or C. Instead, use day, year, century or the like.
- Use functions that we’ve asked you to implement and/or your own helper functions to simplify logic and to minimize repetition of similar code.
- And certainly don’t use global variables. However, global constants are OK.
- When defining and calling functions, make sure not to have spaces around ( and ). For example:
cout << ceil(numberOfCookies);
However, when using if/else statements and loops, be sure to put a space after if, else, for and while, as this example demonstrates:
if (numberOfCookies > numberOfPeople) {
// do something
}
- Remember that all lines must be 80 characters or less.
Zeller’s Formula
f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7
MM is the number of the month (adjusted, see below).
- DD is the day.
- YY is the last two digits of the year number (possibly adjusted).
- CC is the century, i.e. the first two digits of the year number (possibly adjusted).
ff | Day of the week |
0 | Saturday |
1 | Sunday |
2 | Monday |
3 | Tuesday |
4 | Wednesday |
5 | Thursday |
6 | Friday |