Advertisement
Guest User

help

a guest
Oct 9th, 2015
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.84 KB | None | 0 0
  1. rthdays.cpp
  2. In this project, you will develop a command-line application to calculate information regarding specific dates in the past and future.
  3.  
  4. Problem Statement
  5. An old saying about the birthday of a child goes:

  6.  
  7. Monday’s child is fair of face,
  8. Tuesday’s child is full of grace,
  9. Wednesday’s child is full of woe,
  10. Thursday’s child has far to go,
  11. Friday’s child is loving and giving,
  12. Saturday’s child works hard for a living,
  13. But the child who is born on a Sunday
  14. Is bonny, blithe, good and happy.
  15. 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.
  16.  
  17. Solution Overview
  18. Write a program to determine the day of the week a person was born given their birthdate.
  19.  
  20. Your program will provide a menu, implemented using a loop, to obtain user input and calculate birthdays.
  21.  
  22. Even though we are going over what happens in int main() early in the specification, this does NOT mean you should begin your implementation with int main(). Actually, you should write main() last.
  23. Since you need to write 'main()' last, this means you can use it to test all of the individual functions you need to implement.
  24. To begin, your program will call printHeading(), which will print this heading:
  25.  
  26. *******************************
  27. Birthday Calculator
  28. *******************************
  29. 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.
  30.  
  31. The menu options are:
  32.  
  33. Menu Options
  34. ------------
  35. 1) Determine day of birth
  36. 2) Determine birthdays for the next 10 years
  37. 3) Finished
  38.  
  39. Choice -->
  40. Depending upon the value the user enters for "Choice", the program will either determine the day of your birthday or print your birthdays for the next 10 years.
  41.  
  42. Your program shall continue to calculate birthdays and prompt the user for another choice until a user input of 'Finished' (user choice 3) is entered.
  43.  
  44. 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:
  45.  
  46. ****************************************************
  47. Thanks for using the Birthday Calculator
  48. ****************************************************
  49. and the program naturally finishes.
  50.  
  51. 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.
  52.  
  53. One of the first rules of programming is to make no assumptions about your program’s user. Often users provide incorrect input, either accidentally (through unfamiliarity with the program, or perhaps a typo) or maliciously (with the intent of causing your program to fail).
  54. Your program must therefore check the user’s input to make sure it is within the correct range and to make sure it did not make cin fail before using it for your calculations.
  55. printHeading()
  56. This function has been implemented for you.
  57.  
  58. /**
  59. * Requires: nothing
  60. * Modifies: cout
  61. * Effects: prints out the initial heading for the program
  62. */
  63. void printHeading();
  64. This function will print the following prompts:
  65.  
  66. *******************************
  67. Birthday Calculator
  68. *******************************
  69. printCloser()
  70. This function has been implemented for you.
  71.  
  72. /**
  73. * Requires: nothing
  74. * Modifies: cout
  75. * Effects: prints out the final greeting for the program
  76. */
  77. void printCloser();
  78. This function will print the following prompts:
  79.  
  80. ****************************************************
  81. Thanks for using the Birthday Calculator
  82. ****************************************************
  83. printMenu()
  84. This function has been implemented for you.
  85.  
  86. /**
  87. * Requires: nothing
  88. * Modifies: cout
  89. * Effects: prints the menu
  90. */
  91. void printMenu();
  92. This function will print the following prompts:
  93.  
  94. 1) Determine day of birth
  95. 2) Determine birthdays for the next 10 years
  96. 3) Finished
  97. Choice -->
  98. getMenuChoice()
  99. This function will handle everything for printing the menu and handling input from the user.
  100.  
  101. 1
  102. 2
  103. 3
  104. 4
  105. 5
  106. 6
  107. 7
  108. 8
  109. 9
  110. 10
  111. 11
  112. /**
  113. * Requires: nothing
  114. * Modifies: cout, cin
  115. * Effects: prints the menu
  116. * reads the input from the user
  117. * checks to make sure the input is within range for the menu
  118. * If not prints "Invalid menu choice"
  119. * continues to print the menu and read an input until a valid one is entered
  120. * returns the users choice of menu options
  121. */
  122. int getMenuChoice();
  123. This function will contain the following prompts, which print depending on program’s execution:
  124.  
  125. Invalid menu choice
  126. This function will call the following function(s):
  127.  
  128. printMenu()
  129.  
  130. Remember, cleaning up for incorrect input is critical in getting a program to really run correctly.
  131.  
  132. Wrong input. You also cannot depend upon users to get the input correct and within range. You also need to handle out of range input. If the user enters a menu option other than 1, 2, or 3, you need to
  133.  
  134. print Invalid menu choice
  135.  
  136. re-print the menu, and
  137.  
  138. get another menu choice
  139.  
  140. If the user enters something like 1 3, then read getMenuChoice should read 1 as the menu choice and leave 3 in the input stream. You shouldn’t have to do anything special for this if you read input the usual way.
  141.  
  142. This needs to be repeated until a valid menu choice is entered
  143.  
  144. Testing
  145.  
  146. Testing is an art and not a science. It is absolutely a skill and can be developed.
  147. 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.
  148. To test getMenuChoice(), you do NOT need any of the other functions implemented. And when you 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.
  149.  
  150. To test getMenuChoice(), you need to check it against good input and bad input. Therefore, to test it, call it within int main() and make sure you get the output and action you expect.
  151.  
  152. 1
  153. 2
  154. 3
  155. 4
  156. 5
  157. 6
  158. 7
  159. 8
  160. 9
  161. 10
  162. 11
  163. 12
  164. 13
  165. 14
  166. void test_getMenuChoice();
  167.  
  168. int main() {
  169. test_getMenuChoice();
  170. }
  171.  
  172. void test_getMenuChoice() {
  173. cout << "testing good input" << endl;
  174. cout << getMenuChoice() << endl; // input 1
  175. cout << getMenuChoice() << endl; // input 2
  176. cout << getMenuChoice() << endl; // input 3
  177. cout << "testing bad input" << endl;
  178. cout << getMenuChoice() << endl;
  179. }
  180. For "good input", you may want to check 1, 2, and 3. Run your code. Make absolutely sure all works as it should.
  181.  
  182. Now it is time to check for "bad input". You may want to check: 0, 5, -3. And if you want to be really sure it works, you will also want to check a non-numeric such as a, z, #, abc — the autograder will be checking .
  183.  
  184. If a non-integer is entered, cin will go into a fail state. To handle, you will need to clear cin and then get rid of "the offending characters" by reading all left on that line of input into a string.
  185. You should only remove the rest of an input line when cin enters a fail state. If cin is not in a fail state, you should always leave any unread characters in the input stream.
  186. 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.
  187.  
  188. isLeapYear()
  189. The helper function isLeapYear() will check whether or not a particular year is a leap year.
  190.  
  191. /**
  192. * Requires: year is a Gregorian year.
  193. * Modifies: Nothing.
  194. * Effects: Returns true if the year is a leap year,
  195. * otherwise returns false.
  196. */
  197. bool isLeapYear (int year);
  198. In the Gregorian calendar, every year evenly divisible by 4 is a leap year, with the exception of the following conditions:
  199.  
  200. If the year can be evenly divided by 100, it is NOT a leap year, unless:
  201.  
  202. The year is also evenly divisible by 400. Then it is a leap year.
  203.  
  204. For example: 1768 is a leap year. 1800 is not a leap year. 2000 is a leap year.
  205.  
  206. Testing
  207.  
  208. Write your own function test_isLeapYear() and call it within int main()
  209.  
  210. bool isLeapYear(int year) has a "Requires" clause of "year must be a Gregorian year"
  211. What this means is you can — and should — test:
  212.  
  213. // because 2015 is a Gregorian year
  214. cout << isLeapYear(2015) << endl;
  215. 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
  216.  
  217. // invalid test case
  218. cout << isLeapYear(1750) << endl;
  219. 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.
  220.  
  221. What dates will thoroughly test isLeapYear()?
  222.  
  223. Hint: you will need four of them.
  224.  
  225. isValidDate()
  226. 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.
  227.  
  228. /**
  229. * Requires: month, day, year may represent a date.
  230. * Modifies: Nothing.
  231. * Effects: Returns true if the date is valid,
  232. * otherwise returns false.
  233. */
  234. bool isValidDate(int month, int day, int year);
  235. To know whether or not a date is valid, you will first need to check whether the given year is a leap year. Therefore, isLeapYear() needs to have been implemented. Also, this makes isLeapYear() a useful helper function.
  236.  
  237. A helper function is a function written specifically to perform a task required by another function. In this case, isLeapYear() serves as a helper function to isValidDate().
  238. While checking for valid dates, you will also 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.
  239.  
  240. At this point in your work, you may find the following poetic mnemonic useful:
  241.  
  242. Thirty days have September,
  243. April, June, and November.
  244. All the rest have 31,
  245. Except for February all alone,
  246. It has 28 each year,
  247. but 29 each leap year.
  248. Here are some examples of invalid user input to get you started.
  249.  
  250. Not a valid month: 13/20/1980.
  251.  
  252. Not a valid day: 1 / 32 / 1980.
  253.  
  254. Not a valid day: 4 / 31 / 2015.
  255.  
  256. Before 9/14/1752: 5 / 23 / 1300.
  257.  
  258. In all of these cases, your program should return false;.
  259.  
  260. All dates are entered MONTH / DAY / year and not DAY / MONTH / year.
  261. 9 / 12 / 2000 is the 12th of September and not the 9th of December.
  262. Testing
  263.  
  264. To test isValidDate(), create your own function called test_isValidDate() you will need multiple different test sets.
  265.  
  266. Values for valid and invalid months.
  267.  
  268. Values for valid and invalid days.
  269.  
  270. Days that are valid for Jan but not for Feb, etc.
  271.  
  272. Days that are valid for March but not for April, etc.
  273.  
  274. Values for valid and invalid Gregorian years.
  275.  
  276. Values for February 29 if it is a leap year and if it isn’t a leap year.
  277.  
  278. Then call your test_isValidDate() function within int main().
  279.  
  280. determineDay()
  281. 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.
  282.  
  283. /**
  284. * Requires: month, day, year to form a valid date.
  285. * i.e., the date passed to this function has already passed isValidDate()
  286. * Modifies: Nothing.
  287. * Effects: Returns the value that Zeller's formula calculates.
  288. */
  289. int determineDay(int month, int day, int year);
  290. Zeller’s Rule
  291.  
  292. 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.
  293.  
  294. f=(D+⌊13(M+1)5⌋+Y+⌊Y4⌋+⌊C4⌋+5×C)mod7
  295. M is the number of the month (adjusted, see below).
  296.  
  297. D is the day.
  298.  
  299. Y is the last two digits of the year number (possibly adjusted).
  300.  
  301. C is the century, i.e. the first two digits of the year number (possibly adjusted).
  302.  
  303. ⌊x⌋ means “the greatest integer that is smaller than or equal to x”, where ⌊3.14⌋ becomes 3 and ⌊4⌋ becomes 4. This is the floor function in C++ that is defined in the cmath library.
  304. For example,
  305.  
  306. If the date is 5/3/2015 (May 3, 2015), then M is 5, D is 3, Y is 15, and C is 20.
  307.  
  308. If the date is 1/3/2015 (January 3, 2015). then M is 13, D is 3, Y will be 14, and C is 20.
  309.  
  310. Remember to adjust the date provided by the user accordingly before performing your calculations. Calendar Adjustments
  311. Zeller’s rule will return a number f between 0 and 6. This “zero-indexed” number will correlate to a day of the week in the following manner:
  312.  
  313. f Day of the week
  314. 0
  315. Saturday
  316. 1
  317. Sunday
  318. 2
  319. Monday
  320. 3
  321. Tuesday
  322. 4
  323. Wednesday
  324. 5
  325. Thursday
  326. 6
  327. Friday
  328. Calendar Adjustments
  329.  
  330. 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.
  331.  
  332. Our calendar Zeller’s calendar
  333. 1/1/2015
  334. 13/1/2014
  335. 2/1/2015
  336. 14/1/2014
  337. 3/1/2015
  338. 3/1/2015
  339. 4/1/2015
  340. 4/1/2015
  341. 5/1/2015
  342. 5/1/2015
  343. 6/1/2015
  344. 6/1/2015
  345. 7/1/2015
  346. 7/1/2015
  347. 8/1/2015
  348. 8/1/2015
  349. 9/1/2015
  350. 9/1/2015
  351. 10/1/2015
  352. 10/1/2015
  353. 11/1/2015
  354. 11/1/2015
  355. 12/1/2015
  356. 12/1/2015
  357. Example Calculations
  358.  
  359. A detailed example of Zeller’s Formula is included below.
  360.  
  361. Date: January 29, 2064 (i.e., 1/29/2064)
  362.  
  363. M=13 (remember Jan = 13, Feb = 14, March = 3, …​)
  364. D=29
  365. Y=63 (by Zeller’s calendar, the year is actually 2063)
  366. C=20
  367. 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=3
  368. 3 corresponds to a Tuesday, so January 29, 2064 will be a Tuesday.
  369.  
  370. printDayOfBirth()
  371. Make sure this function is declared and defined as printDayOfBirth and not printBirthday.
  372. You will implement printDayOfBirth(), which prints the day of the week using the number you just calculated.
  373.  
  374. /**
  375. * Requires: day (0 represents Saturday, 1 Sunday, 2 Monday, 3 Tuesday, etc)
  376. * Modifies: cout
  377. * Effects: prints the day you were born on
  378. * Sunday, Monday, ..., Saturday
  379. */
  380. void printDayOfBirth(int day);
  381. This function will contain the following prompts, which print depending on program’s execution:
  382.  
  383. Saturday
  384. Sunday
  385. Monday
  386. Tuesday
  387. Wednesday
  388. Thursday
  389. Friday
  390. day is the value calculated using Zeller’s rule. Use the table we provided above to determine the day of the week.
  391.  
  392. For example, if day is 1, printDayOfBirth() will print
  393.  
  394. Sunday
  395. determineDayOfBirth()
  396. This is the function that manages determining the day you were born on.
  397.  
  398. /**
  399. * Requires: nothing
  400. * Modifies: cout, cin
  401. * Effects: Asks for the Month/day/year of their birth
  402. * If the date is valid, it will print the day
  403. * of the week you were born on
  404. * Otherwise, it will print "Invalid date" prompt
  405. */
  406. void determineDayOfBirth();
  407. This function will contain the following prompts, which print depending on program’s execution:
  408.  
  409. Enter your date of birth
  410. format: month / day / year -->
  411. Invalid date
  412. You were born on a:
  413. Have a great birthday!!!
  414. This function will call the following function(s):
  415.  
  416. isValidDate()
  417.  
  418. determineDay()
  419.  
  420. printDayOfBirth()
  421.  
  422. This is the function that will:
  423.  
  424. Input the date.
  425.  
  426. 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
  427.  
  428. print the day of the week you were born on.
  429.  
  430. tell you to Have a great birthday!!!
  431.  
  432. Dates may be entered with our without spaces around the /.
  433. 12/20/1980 is acceptable. 12 / 20 / 1980 is also acceptable.
  434. 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: .
  435. This function calls several of the other functions you have already written.
  436.  
  437. Make sure you use the "prompts" exactly as listed in the description for this function.
  438. print10Years()
  439. For the base project the only thing this function needs to do is print
  440.  
  441. Under Construction
  442. Only the S’more version needs to totally implement this function.
  443.  
  444. Putting it Together
  445. 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. Also know that we’ve made our own implementation of the project available, see Staff’s Implementation for details.
  446.  
  447. This function will call the following function(s):
  448.  
  449. printHeading()
  450.  
  451. getMenuChoice()
  452.  
  453. determineDayOfBirth()
  454.  
  455. print10Years()
  456.  
  457. printCloser()
  458.  
  459. Testing (diff)
  460. 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:
  461.  
  462. diffchecker.com
  463.  
  464. quickdiff.com
  465.  
  466. diffnow.com
  467.  
  468. 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.
  469. Sample Output
  470. Here are a few examples of the way your program output should look, wherein red underlined text represents some user’s input.
  471.  
  472. Sample run 1
  473. *******************************
  474. Birthday Calculator
  475. *******************************
  476.  
  477.  
  478.  
  479. Menu Options
  480. ------------
  481. 1) Determine day of birth
  482. 2) Determine birthdays for the next 10 years
  483. 3) Finished
  484.  
  485. Choice --> 1
  486.  
  487. Enter your date of birth
  488. format: month / day / year --> 9/31/1980
  489.  
  490. Invalid date
  491.  
  492.  
  493. Menu Options
  494. ------------
  495. 1) Determine day of birth
  496. 2) Determine birthdays for the next 10 years
  497. 3) Finished
  498.  
  499. Choice --> 1
  500.  
  501. Enter your date of birth
  502. format: month / day / year --> 1/25/1956
  503.  
  504. You were born on a: Wednesday
  505.  
  506. Have a great birthday!!!
  507.  
  508.  
  509. Menu Options
  510. ------------
  511. 1) Determine day of birth
  512. 2) Determine birthdays for the next 10 years
  513. 3) Finished
  514.  
  515. Choice --> 3
  516.  
  517. ****************************************************
  518. Thanks for using the Birthday Calculator
  519. ****************************************************
  520. Sample run 2
  521. *******************************
  522. Birthday Calculator
  523. *******************************
  524.  
  525.  
  526.  
  527. Menu Options
  528. ------------
  529. 1) Determine day of birth
  530. 2) Determine birthdays for the next 10 years
  531. 3) Finished
  532.  
  533. Choice --> 4
  534.  
  535. Invalid menu choice
  536.  
  537.  
  538. Menu Options
  539. ------------
  540. 1) Determine day of birth
  541. 2) Determine birthdays for the next 10 years
  542. 3) Finished
  543.  
  544. Choice --> 3
  545.  
  546. ****************************************************
  547. Thanks for using the Birthday Calculator
  548. ****************************************************
  549. Sample run 3
  550. *******************************
  551. Birthday Calculator
  552. *******************************
  553.  
  554.  
  555.  
  556. Menu Options
  557. ------------
  558. 1) Determine day of birth
  559. 2) Determine birthdays for the next 10 years
  560. 3) Finished
  561.  
  562. Choice --> 1
  563.  
  564. Enter your date of birth
  565. format: month / day / year --> 9/13/1752
  566.  
  567. Invalid date
  568.  
  569.  
  570. Menu Options
  571. ------------
  572. 1) Determine day of birth
  573. 2) Determine birthdays for the next 10 years
  574. 3) Finished
  575.  
  576. Choice --> 1
  577.  
  578. Enter your date of birth
  579. format: month / day / year --> 19/13/1982
  580.  
  581. Invalid date
  582.  
  583.  
  584. Menu Options
  585. ------------
  586. 1) Determine day of birth
  587. 2) Determine birthdays for the next 10 years
  588. 3) Finished
  589.  
  590. Choice --> 1
  591.  
  592. Enter your date of birth
  593. format: month / day / year --> 9/13/1982
  594.  
  595. You were born on a: Monday
  596.  
  597. Have a great birthday!!!
  598.  
  599.  
  600. Menu Options
  601. ------------
  602. 1) Determine day of birth
  603. 2) Determine birthdays for the next 10 years
  604. 3) Finished
  605.  
  606. Choice --> 3
  607.  
  608. ****************************************************
  609. Thanks for using the Birthday Calculator
  610. ****************************************************
  611. Staff’s Implementation
  612. If you’d like to play with the staff’s implementation of birthdays (to see the end result, to test your own solution, or just to procrastinate), know that you can download Mac and Windows versions from the Projects page of the course’s website.
  613.  
  614. If you’d like to run the staff’s solution on a Windows PC, download the Windows executable from the course’s website and just double-click on it. If prompted, click Run to allow Windows to run the program.
  615.  
  616. If you’d like to run the staff’s solution on a Mac, first download the Mac executable from the course’s website.
  617.  
  618. Next, move it from your Downloads folder to your Desktop (or anywhere else you’d like).
  619.  
  620. Open Terminal. This app allows you to interact with your computer via keyboard commands. If you’re not sure where to find Terminal, press Command-Space to open Spotlight and search for Terminal, or head to Applications > Utilities folder in Finder and you’ll find Terminal there.
  621.  
  622. Once you’ve opened a Terminal window, type the following and hit Enter:
  623.  
  624. cd ~/Desktop
  625. This will change your current directory to Desktop. Because the Desktop folder is in your home directory and because ~ is a way to reference the home directory, you can reference your Desktop with ~/Desktop. If you placed the executable file in a different directory, you’ll have to instead provide a path to that directory.
  626.  
  627. Now you have to change permissions for birthdays in order allow your computer to run the executable. In Terminal, type the following and hit Enter:
  628.  
  629. chmod u+x birthdays
  630. Now you can run our solution by simply executing
  631.  
  632. ./birthdays
  633. If you’d like to run it again, just retype the above command.
  634.  
  635. If you’d like to run our solution after you close the Terminal, you’ll have to first re-open it and again execute cd command from above. No need to execute chmod the second time.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement