Last active
December 21, 2021 16:51
-
-
Save DragonOsman/c372f99863d52db4b3dabf427ded6b8c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Osman Zakir | |
| // 12 / 21 / 2021 | |
| // Beginning C++20: From Novice to Professional by Ivor Horton and Peter Van Weert | |
| // Chapter 8 Exercise 1 | |
| // Exercise Specs: | |
| /** | |
| * Write a function, validate_input(), that accepts two integer arguments that | |
| * represent the upper and lower limits for an integer that is to be entered. | |
| * It should accept a third argument that is a string describing the input, | |
| * with the string being used in the prompt for input to be entered. The | |
| * function should prompt for input of the value within the range specified by | |
| * the first two arguments and include the string identifying the type of value to | |
| * be entered. The function should check the input and continue to prompt for input | |
| * until the value entered by the user is valid. Use the validate_input() function | |
| * in a program that obtains a user’s date of birth and outputs it in the form of | |
| * this example: | |
| * | |
| * > You were born on the 21st of November, 2012 | |
| * | |
| * The program should be implemented so that separate functions, month(), year(), and day(), | |
| * manage the input of the corresponding numerical values. Don’t forget leap | |
| * years—February 29, 2017, is not allowed! | |
| */ | |
| import <iostream>; | |
| import <format>; | |
| import <chrono>; | |
| import <string>; | |
| unsigned validate_input(unsigned lower_limit, unsigned upper_limit, | |
| const std::string& description); | |
| unsigned year(unsigned lower_limit, unsigned upper_limit); | |
| unsigned month(unsigned lower_limit, unsigned upper_limit); | |
| unsigned day(unsigned lower_limit, unsigned upper_limit); | |
| unsigned get_upper_day_limit(unsigned birth_month, int birth_year); | |
| std::string get_output_day_str(unsigned day); | |
| int main() | |
| { | |
| const auto now{ std::chrono::system_clock::now() }; | |
| const std::chrono::year_month_day ymd{ std::chrono::floor<std::chrono::days>(now) }; | |
| const int current_year{ static_cast<int>(ymd.year()) }; | |
| const unsigned lower_year_limit = current_year - 160; // lower birth year | |
| // limit is 160 years ago | |
| const unsigned lower_month_limit{ 1 }; | |
| const unsigned upper_month_limit{ 12 }; | |
| const unsigned birth_year{ year(lower_year_limit, current_year) }; | |
| const unsigned birth_month{ month(lower_month_limit, upper_month_limit) }; | |
| const unsigned lower_day_limit{ 1 }; | |
| const unsigned upper_day_limit{ get_upper_day_limit(birth_month, birth_year) }; | |
| const unsigned birth_day{ day(lower_day_limit, upper_day_limit) }; | |
| const std::string output_day_str{ get_output_day_str(birth_day) }; | |
| std::cout << std::format("You were born on the {} of {:B}, {}\n", | |
| output_day_str, std::chrono::month{ birth_month }, birth_year); | |
| } | |
| std::string get_output_day_str(const unsigned day) | |
| { | |
| std::string output_day_str; | |
| std::string day_str{ std::to_string(day) }; | |
| if (day_str.ends_with("1")) | |
| { | |
| output_day_str = day_str += "st"; | |
| } | |
| else if (day_str.ends_with("2")) | |
| { | |
| output_day_str = day_str += "nd"; | |
| } | |
| else if (day_str.ends_with("3")) | |
| { | |
| output_day_str = day_str += "rd"; | |
| } | |
| else | |
| { | |
| output_day_str = day_str += "th"; | |
| } | |
| return output_day_str; | |
| } | |
| unsigned get_upper_day_limit(const unsigned birth_month, const int birth_year) | |
| { | |
| unsigned upper_day_limit{}; | |
| switch (birth_month) | |
| { | |
| case 1: case 3: case 5: case 7: case 8: case 10: case 12: | |
| upper_day_limit = 31; | |
| case 4: case 6: case 9: case 11: | |
| upper_day_limit = 30; | |
| case 2: | |
| std::chrono::year year{ birth_year }; | |
| if (year.is_leap()) | |
| { | |
| upper_day_limit = 29; | |
| } | |
| else | |
| { | |
| upper_day_limit = 28; | |
| } | |
| } | |
| return upper_day_limit; | |
| } | |
| unsigned validate_input(const unsigned lower_limit, const unsigned upper_limit, | |
| const std::string& description) | |
| { | |
| unsigned value{}; | |
| std::cout << "Please enter your " << description << " now: "; | |
| std::cin >> value; | |
| if (value < lower_limit || value > upper_limit) | |
| { | |
| while (value < lower_limit || value > upper_limit) | |
| { | |
| std::cout << "invalid " << description << "! Try again: "; | |
| std::cin >> value; | |
| } | |
| std::cin.ignore(32767, '\n'); | |
| } | |
| return value; | |
| } | |
| unsigned day(const unsigned lower_limit, const unsigned upper_limit) | |
| { | |
| return validate_input(lower_limit, upper_limit, "day of birth"); | |
| } | |
| unsigned month(const unsigned lower_limit, const unsigned upper_limit) | |
| { | |
| return validate_input(lower_limit, upper_limit, "month of birth"); | |
| } | |
| unsigned year(const unsigned lower_limit, const unsigned upper_limit) | |
| { | |
| return validate_input(lower_limit, upper_limit, "year of birth"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment