Finding specific days in a specific years and leap years - c++

so, I have this much of the program done I still have to determine what day of the week january 1st is in the current year as well as leap years: A leap year is one whose number is exactly divisible by four. Century years, however, are only leap years if they are exactly divisible by 400. Hence 1900 was not a leap year but 2000 was. Im a bit stuck on where to go from here, I understand it in my head but am having trouble putting my thoughts into code. If anyone can push me in the right direction or if you have a solution id really appreciate the help.
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
tm dateTime;
time_t systemTime = time(0);
localtime_s( &dateTime, &systemTime );
int day = dateTime.tm_mday;//theTime.tm_mday;
int month = dateTime.tm_mon+1;//theTime.tm_mon;
int year = dateTime.tm_year + 1900;//theTime.tm_year + 1900;
int weekDay = dateTime.tm_wday;
cout << "Today is ";
switch (weekDay){
case 0: cout << "Sunday, ";
break;
case 1: cout << "Monday, ";
break;
case 2: cout << "Tuesday, ";
break;
case 3: cout << "Wednesday, ";
break;
case 4: cout << "Thursday, ";
break;
case 5: cout << "Friday, ";
break;
case 6: cout << "Saturday, ";
break;
}
cout << month << "/" << day << "/" << year << endl;
}

Use modulo arithmetic operator (%) to determine if the year is dividable by 4.
If it's not, then it's not leap.
Note that a result of operator% equals 0 if and only if lhs is dividable by rhs.
Then, apply the same operator with logic that stands behind alghoritm that determines if year is leap, as you described in your question. Details are in comments of my answer's code.
[[nodiscard]]
constexpr bool IsLeap(const int & Year) noexcept
{
// If $Year is not dividable by 4, it's not leap, eg 2003.
// Otherwise, apply more logic below (for years like 2004, 2000 or 1900).
if (Year % 4 != 0) [[likely]]
return false;
// If $Year is dividable by 100, eg 2000, check if it's also dividable by 400.
// If it's also dividable by 400, it's leap, eg 2000.
// Otherwise, it's not leap, eg 1900.
if (Year % 100 == 0) [[unlikely]]
{
if (Year % 400 == 0) [[unlikely]]
return true;
return false;
}
// $Year is dividable by 4 and not by 100, so it's leap.
return true;
}
Example:
#include <iostream>
int main()
{
std::cout << std::boolalpha << IsLeap(2003) << std::endl; // false (not dividable by 4)
std::cout << std::boolalpha << IsLeap(2004) << std::endl; // true (dividable by 4 and not dividable by 100)
std::cout << std::boolalpha << IsLeap(2000) << std::endl; // true (dividable by 4, 100 and 400)
std::cout << std::boolalpha << IsLeap(1900) << std::endl; // false (dividable by 4 and 100, but not by 400)
}

To check if a given number is divisible by another number, you use the modulus (%) operator. If a % b == 0, that means that a is divisible by b.
bool is_leap_year(int year) {
if (year % 4 != 0) return false;
// Year is divisible by 4; It is a leap year
if (year % 100 == 0) {
// Unless it is also divisible by 100, in which case it is not a leap year
// Except when it is divisible by 400
if (year % 400 == 0) return true;
return false;
}
return true;
}
// Equivalent to
bool is_leap_year(int year) {
return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
}
And then when finding out what weekday it was on January 1st from the current day, you will have to use the modulus operator again. This time, you will use a % 7, which will give the remainder when something is divided by 7 (So 15 days ago is 15 % 7 == 1 day ago in a different week).

Using the epoch as a reference date (we could really pick any date), we just count up to the current date to get the day of the week.
One optimization is that we can increment the years first and just let the dayOfTheWeek variable increment by 1 or 2 depending if we're currently counting on a leap year or not.
bool isLeapYear(int year)
{
if ((year % 400) == 0)
return true;
if ((year % 100) == 0)
return false;
return ((year % 4) == 0);
}
// return the day of the week for a given month/day/year value
// Sunday is 0. Monday is 1.... Saturday is 6;
int GetDayOfWeek(int month, int day, int year)
{
int dayOfWeek = 5; // January 1, 1970 was a Thursday
int daysOfMonth = [0,31,28,31,30,31,30,31,31,30,31,30,31];
int d = 1;
int m = 1;
int y = 1970;
if (year < 1970)
return -1;
// go "year by year" incrementing dayOfWeek by 1 or 2 based on leap year
while (y < year)
{
dayOfWeek = (isLeapYear(y) ? 2 : 1) % 7;
y++;
}
while (d != day && m != month)
{
// increment the day
d++;
dayOfWeek = (dayOfWeek + 1) % 7;
if (d > daysOfMonth[m]) // new month
{
d = 1;
m++;
}
}
return dayOfWeek;
}

Related

Calendar program for C++ class has a day counting bug

I am making a calendar program in C++ that determines the days of a month in any given year by counting the number of days between January 1st, 1753 all the way to the first day of the given month in the given year. It then divides this number of days by 7 to determine the "offset" that is used to figure out what day the first day of the month begins (example: since January 1st, 1753 is on a Monday, an offset of 2 means that the first day of the month will be on a Wednesday). I completed my code and ran it through several tests when I noticed a very strange bug. For the year 2000, the offset is one higher than it should be (February starts on a Wednesday instead of a Tuesday, etc). This problem doesn't exist in any other leap year, or year ending with "00". It is the only test I am failing, and for the life of me I can't seem to figure out what the problem is.
Here is the code:
//**********************************************************************
#include <iostream>
#include <iomanip>
using namespace std;
int getYear();
int getMonth();
int computeNumDays(int month, int year);
int computeOffset(int month, int year);
bool isLeapYear(int year);
void displayHeading(int month, int year);
void displayTable(int offset, int numDays);
/********************
* MAIN
*********************/
int main()
{
int month = getMonth();
int year = getYear();
int offset = computeOffset(month, year);
int numDays = computeNumDays(month, year);
displayHeading(month, year);
displayTable(offset, numDays);
return 0;
}
/********************
*GETMONTH
*Prompts the user for a month number
*********************/
int getMonth()
{
int month;
//Month number must be between 1 and 12
cout << "Enter a month number: ";
cin >> month;
//Displays an error message if the month is under 1 or over 12
while (month < 1 || month > 12)
{
cout << "Month must be between 1 and 12.\n";
cout << "Enter a month number: ";
cin >> month;
}
return month;
}
/********************
*GETYEAR
* prompts the user for a year
*********************/
int getYear()
{
int year;
cout << "Enter year: ";
cin >> year;
//Displays an error message if the year is less than 1753
while (year < 1753)
{
cout << "Year must be 1753 or later.\n";
cout << "Enter year: ";
cin >> year;
}
cout << "\n";
return year;
}
/********************
*COMPUTENUMDAYS
* For computing the number of days in a month, so we know where to count to when filling in
* the calendar
*********************/
int computeNumDays(int month, int year)
{
int numDays;
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
return numDays = 31;
else if (month == 4 || month == 6 || month == 9 || month == 11)
return numDays = 30;
else if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
return numDays = 29;
else if (month == 2)
return numDays = 28;
}
/*********************
*COMPUTEOFFSET
*********************/
int computeOffset(int month, int year)
{
int totalYearDays = 0;
int totalMonthDays = 0;
//This counts up all the days between the January 1st of 1753 to January 1st of the users input
//year. Leap years are accounted for with the IF statements and the isLeapYear function
for (int yearCount = 1753; yearCount < year; yearCount++)
{
if (isLeapYear(yearCount))
totalYearDays += 366;
else
totalYearDays += 365;
}
//The days of the month of the user input year are added up here. If the user inputs February(2),
//then it counts the days of each month in between and adds them up.
for (int monthCount = 0; monthCount < month; monthCount++)
{
if (monthCount == 1 || monthCount == 3 || monthCount == 5)
totalMonthDays += 31;
else if (monthCount == 7 || monthCount == 8 || monthCount == 10 || monthCount == 12)
totalMonthDays += 31;
else if (monthCount == 4 || monthCount == 6 || monthCount == 9 || monthCount == 11)
totalMonthDays += 30;
//if the user input year is a leap year, then an extra day to February is added
else if (monthCount == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
totalMonthDays += 29;
else if (monthCount == 2)
totalMonthDays += 28;
}
int offset = (totalYearDays + totalMonthDays) % 7;
return offset;
}
/******************************************
* ISLEAPYEAR
******************************************************/
bool isLeapYear(int yearCount)
{
//Equation for determining if a year is a leap year or not
if ((yearCount % 4 == 0 && yearCount % 100 != 0) || (yearCount % 400 == 0))
return true;
else
return false;
}
/*************************************************
*DISPLAYHEADING
* This is where the Month Name and Year are shown
**************************************************/
void displayHeading(int month, int year)
{
if (month == 1)
cout << "January, " << year << endl;
else if (month == 2)
cout << "February, " << year << endl;
else if (month == 3)
cout << "March, " << year << endl;
else if (month == 4)
cout << "April, " << year << endl;
else if (month == 5)
cout << "May, " << year << endl;
else if (month == 6)
cout << "June, " << year << endl;
else if (month == 7)
cout << "July, " << year << endl;
else if (month == 8)
cout << "August, " << year << endl;
else if (month == 9)
cout << "September, " << year << endl;
else if (month == 10)
cout << "October, " << year << endl;
else if (month == 11)
cout << "November, " << year << endl;
else if (month == 12)
cout << "December, " << year << endl;
return;
}
/********************
*DISPLAYTABLE
*********************/
void displayTable(int offset, int numDays)
{
//days of the week are displayed here
cout << setw(4) << "Su" << setw(4) << "Mo" << setw(4) << "Tu"
<< setw(4) << "We" << setw(4) << "Th" << setw(4) << "Fr" << setw(4)
<< "Sa" << setw(2) << endl;
//WeekBreak counter will be used to add new lines for each week
int weekBreak = 1;
//This IF statement determines the number of days before the first of the month occurs,
// as well as sets the weekBreak counter
if (offset != 6 && offset >= 0)
do
{
cout << setw(4) << " ";
offset--;
weekBreak++;
} while (offset != -1);
//The counter loop here begins putting in the dates, all the way from the first to
//the max number of days in the month
for (int date = 1; date <= numDays; date++)
{
cout << " " << setw(2) << date;
weekBreak++; //weekBreak prevents us from putting more than
//7 dates in a single week
if (weekBreak == 8)
{
cout << "\n"; //once a week hits 7 dates(or 8 spaces), it moves on to a new week
weekBreak = 1;
}
}
//this puts an end to the calander, regardless if weekBreak limit is reached
if (weekBreak >= 2 && weekBreak <= 7)
cout << "\n";
}
It bothers me that it only seems to happen for the year 2000. I'm not sure what the cause could be, so I could really use some feedback.
To debug your code I wrote the following main function:
int main()
{
for (int year = 1753; year <= 2021; year++)
{
for (int month = 1; month <= 12; month++)
{
int offset = computeOffset(month, year);
int numDays = computeNumDays(month, year);
std::chrono::year_month_day date(std::chrono::year(year), std::chrono::month(month), std::chrono::day(1));
std::chrono::weekday day{ std::chrono::sys_days(date) };
int expectedOffset = ((day - std::chrono::Monday).count() + 7) % 7;
if (expectedOffset != offset)
{
std::cout << year << "/" << month << " expected " << expectedOffset << " actual " << offset << "\n";
}
}
}
return 0;
}
This confirms it is indeed only the year 2000 which is incorrect. This suggests its the handling of the leap year every 400 years which is incorrect.
As you have a function for calculating leap years the first thing to try is to use that rather than implementing the same code three times (implementing something 3 times triples the chances of creating a bug). Changing computeNumDays to:
else if (month == 2 && isLeapYear(year))
return numDays = 29;
and computeOffset to:
else if (monthCount == 2 && isLeapYear(year))
totalMonthDays += 29;
fixes the bug.
The cause of the bug is actually the combination of 2 bugs:
in computeOffset monthCount starts from 0 not 1.
the expression monthCount == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) will always be true when year % 400 == 0 is true. The intended expression was monthCount == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
This causes the value of totalMonthDays to be 29 more than it should be for years divisible by 400, after %7 this causes the result of computeOffset to be 1 higher than it should be.
By removing repetition your code can be greatly simplified:
int computeNumDays(int month, int year)
{
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return isLeapYear(year) ? 29 : 28;
default:
throw std::invalid_argument("invalid month");
}
}
int computeOffset(int month, int year)
{
int totalYearDays = 0;
int totalMonthDays = 0;
//This counts up all the days between the January 1st of 1753 to January 1st of the users input
//year. Leap years are accounted for with the IF statements and the isLeapYear function
for (int yearCount = 1753; yearCount < year; yearCount++)
{
if (isLeapYear(yearCount))
totalYearDays += 366;
else
totalYearDays += 365;
}
//The days of the month of the user input year are added up here. If the user inputs February(2),
//then it counts the days of each month in between and adds them up.
for (int monthCount = 1; monthCount < month; monthCount++)
{
totalMonthDays += computeNumDays(monthCount, year);
}
int offset = (totalYearDays + totalMonthDays) % 7;
return offset;
}
bool isLeapYear(int yearCount)
{
//Equation for determining if a year is a leap year or not
if ((yearCount % 4 == 0 && yearCount % 100 != 0) || (yearCount % 400 == 0))
return true;
else
return false;
}

are instructions coded wisely in that leap year program in c++?

i just have wondered that i am correct in that code or not for these instructions? Thank youu.
There are 3 criteria that must be taken into account to identify a leap year:
If the year can be evenly divided by 4 then it is a leap year, however…
If that year can be evenly divided by 100, and it is not evenly divided by 400, then it is NOT a leap year.
If that year is evenly divisible by 400, then it is a leap year.
#include <iostream>
int main() {
int year;
std::cout << "Please enter the year:";
std::cin >> year;
if(year % 4 == 0) {
std::cout << "It is leap year.";
} else if ( year % 100 == 0 && year % 400 != 0){
std::cout << "It is not a leap year";
} else if ( year % 400 == 0) {
std::cout << "It is a leap year";
} else {
std::cout << "Sorry! it is not a leap year";
}
}
No, your order is backward. If year % 4 == 0 is true, then you will enter that portion of the if-statement. Consider the year 2100. It is divisible by 4, so it will go into the if, and print that it is a leap year.
Reversing your conditions should solve this:
if ( year % 400 == 0 )
std::cout << "It is a leap year";
else if ( year % 100 == 0 )
std::cout << "It is NOT a leap year";
else if ( year % 4 == 0 )
std::cout << "It is a leap year";
else
std::cout << "Sorry! it is not a leap year";
I think it is the right logic.
if (year % 4 == 0) {
if (year % 100 == 0){
if (year % 400 == 0)
std::cout << "It is a leap year";
else std::cout << "Sorry! it is not a leap year";
}
else std::cout << "It is a leap year";
}
else std::cout << "Sorry! it is not a leap year";
You need to check the exceptions to the general rule first, starting with the exception to the exception.
That is,
The 400 rule
The 100 rule
The 4 rule
Or, you can capture it in a single expression and not worry about the order.
bool is_leap_year = year % 4 == 0
&& (year % 100 != 0 || year % 400 == 0);
std::cout << (is_leap_year ? “Yes!” : “No...”) << std::endl;

Return number of days in a given month of a given year

I wrote a program that, given the month number and the year, returns the number of days in that month:
#include <iostream.h>
#include <conio.h>
void main() {
clrscr();
int month, year, i;
cout << "give the year \n";
cin >> year;
cout << "give the month\n";
cin >> month;
for (i = 1; i <= 12; i++) {
i = month;
switch (month) {
case 1:
cout << "number of day in month is 31\n";
break;
case 2:
if (year % 4 == 0) {
cout << "the number of days is 29 \n";
} else {
cout << "the number of days is 28 \n";
}
break;
case 3, 5, 7, 8, 10, 12:
cout << "the number of days is 31 \n";
break;
default:
cout << "the number of days is 30 \n";
return;
}
}
return;
}
When I give the month number 3, it returns the number of days is 31, so it works fine. But when I give 1 or 2, the output is
number of day in month is 31
number of day in month is 31
number of day in month is 31
.
.
.
.
How can I make it return only number of day in month is 31 or number of day in month is 28 if the case is 2?
Don't repeat the calculation/ don't use the loop. Use the switch case syntax properly.
And your leap year calculation is wrong. It should be like this:
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){
cout << "the number of days is 29 \n";
}
else {
cout << "the number of days is 28 \n";
}
A year is leap year if it is divisible by 4 but not divisible by 100 or it is divisible by 400
You have a loop where i runs from 1 to 12.
Inside that loop you do
switch (month)
But you probably mean
switch (i)
Otherwise you're just repeating the same calculation 12 times.
lazy way:
#include <ctime>
static int GetDaysInMonthOfTheDate(std::tm curDate)
{
std::tm date = curDate;
int i = 0;
for (i = 29; i <= 31; i++)
{
date.tm_mday = i;
mktime(&date);
if (date1->tm_mon != curDate.tm_mon)
{
break;
}
}
return i - 1;
}

Leap year program doesn't seem to run

Question - A year with 366 days is called a leap year. A year is a leap year if it is divisible by four (for example, 1980), except that it is not a leap year if it is divisible by 100 (for example, 1900); however, it is a leap year if it is divisible by 400 (for example, 2000). There were no exceptions before the introduction of the Gregorian calendar on October 15, 1582. Write a program that asks the user for a year and computes whether that year is a leap year.
This is what I have so far, and the program doesn't seem to run for years greater than 1582. Could someone help me out why? Thanks a bunch
using namespace std;
int main()
{
cout<< "Pleas enter a year: " <<endl;
int year = 0;
cin >> year;
if (year <= 1581)
{
if (year % 4 == 0)
{
cout << "It's a leap year, wow! " << endl;
}
else
{
cout << "It's not a leap year " << endl;
}
}
else if (year > 1581)
{
if (year % 4 == 0)
{
if (year % 100 == 0)
{
cout<< "It is not a leap year " << endl;
}
else if (year % 400 == 0)
{
cout<< "It is a leap year, Wow!" << endl;
}
}
}
else
{
cout<< "You entered a wrong year number "<< year<< endl;
}
return 0;
}
You are making it very complex. I don't think you need to care about whether the year is greater than 1582 or not (for a 4 digit number) provided that a leap year is one which is:
• Divisible by 400
OR
• NOT divisible by 100 AND divisible by 4.
Using unnecessary nested ifs can make your code long and error prone. Try this method:
#include<iostream.h>
int main(){
int y=0;
cout << "Enter a year\n";
cin >> y;
cout <<"\n"<<y;
if(y%400==0 || (y%100!=0 && y%4==0))
cout <<" is a leap year";
else
cout <<" is not a leap year";
return 0;
}
Without check if year > 1582
#include<iostream>
using namespace std;
int main()
{
int year;
cout<< "Please enter a year: " <<endl;
cin >> year;
if( year%25 && !(year&3) || !(year&15) )
cout << "It's a leap year!" << endl;
else
cout << "It's not a leap year!" << endl;
return 0;
}
You are missing a number of cases in the handling of years after 1581.
printing "Not leap year" unless (year % 4 == 0)
The third case where a year divisible by 4 is neither divisible by 100 nor 400
It as simple as you have just not written any code that is run when year is 2004, for example.
You are missing 2 else statement
using namespace std;
int main()
{
cout<< "Pleas enter a year: " <<endl;
int year = 0;
cin >> year;
if (year <= 1581)
{
if (year % 4 == 0)
{
cout << "It's a leap year, wow! " << endl;
}
else
{
cout << "It's not a leap year " << endl;
}
}
else if (year > 1581)
{
if (year % 4 == 0)
{
if (year % 100 == 0)
{
cout<< "It is not a leap year " << endl;
}
else if (year % 400 == 0)
{
cout<< "It is a leap year, Wow!" << endl;
}
// <----------- Here you are missing an else
}
// <----------- Here you are missing an else
}
else
{
cout<< "You entered a wrong year number "<< year<< endl;
}
return 0;
}
I suggest
if ( ((year % 400) == 0)
|| ( ((year % 4) == 0) // or (year & 0x3) == 0
&& ( (year <= 1581)
|| ((year % 100) != 0) )))
cout << "It's a leap year, wow! " << endl;
else
cout << "It's not a leap year " << endl;
or
if ( ((year % 4) == 0) // or year & 0x3 == 0
&& ( (year <= 1581)
|| ((year % 100) != 0)
|| ((year % 400) == 0) ) )
cout << "It's a leap year, wow! " << endl;
else
cout << "It's not a leap year " << endl;
It’s a good idea to simplify your conditionals. A general method for this is to convert to a normal form—either conjunctive or disjunctive—and put the tests that are most likely to short-circuit, first. For simple cases such as this, you can just eyeball it.
In this case, conjuctive normal form is extremely simple:
year%4 == 0 &&
( year < 1582 || year%100 != 0 || year%400 == 0 )
That is, the year is divisible by four and any of the three conditions of the Gregorian calendar reform do not hold. Since the first && term that is false, and the first || term that is true, short-circuit the expression, we want to put the clauses that are most likely to short-circuit, first.
Note that you can code-golf year%100 != 0 to year%100 inside a conditional expression, and year%2000 == 0 to !(year%2000), if you find that easier to read.
It makes sense to move this to a helper function. We can mark it constexpr to give the compiler a hint that it can calculate whether constants are leap years or not at compile-time.
I don't like to post complete answers to what look like homework problems, but that ship has sailed.
#include <cstdlib>
#include <iostream>
using std::cin;
using std::cout;
constexpr bool is_leap(const int year)
{
// Conjunctive normal form:
return ( year%4 == 0 &&
( year < 1582 || year%100 != 0 || year%400 == 0 ) );
}
int main()
{
int year = 0; // Used only within the body of the loop that sets it.
while (cin >> year)
cout << year
<< ( is_leap(year) ? " is a leap year.\n"
: " is not a leap year.\n" );
return EXIT_SUCCESS;
}
Even for a trivial program such as this, there’s a design decision worth thinking about: do we declare int year; uninitialized, or initialize it to a bad value such as int year = 0;? In this case, it’s safe either way, because year is only used inside the body of the loop that sets it. If we don’t initialize it, though, we might later refactor the code to use year outside the loop, and then there might be a code path where year is used before it’s initialized (causing undefined behavior!) On the other hand, if we do initialize year, we might prevent the compiler from noticing that there’s a path where it’s used before it was initialized for real. I personally prefer to initialize to an invalid value and assert that it has been updated before use.
Or you can simply write the following program:
#include<iostream>
using namespace std;
int main()
{
int year;
cout << "Enter year: ";
cin >> year;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
cout << "It is a leap year" << endl;
}
else{
cout << "It is not a leap year" << endl;
}
return 0;
}

C++ validating date without using class

Hi I am hoping someone can help me out with what I am doing wrong. This is homework I will point out but was in need of someone to tell me what a moron I am because I am not seeing what it is that I am doing wrong.
I am supposed to let the user enter a month, day, and year to determine if it is a magic date. That part I had already done for another project. I am supposed to go back and validate the date using a function named isDateValid. I'm pretty sure I am missing something obvious and could use anyones help on the subject. Thanks!
The problem is when I run it I am always getting that it is an invalid date!
#include <iostream>
using namespace std;
bool leapYear(int);
bool isDateValid(int, int, int);
int main()
{
int month, day, year;
cout << "Is the date you are thinking of a magic one? Let's see...\n";
cout << "What is the month in numeric form only? "; cin >> month;
cout << "What is the day of the month? "; cin >> day;
cout << "What is the four digit year? "; cin >> year;
if (isDateValid(month, day, year) == false)
{
cout << "The date you entered, "<< month << "/" << day << "/" <<
year << " is NOT a VALID Date.\n";
cout << "If you think I am wrong, please feel free to run me again";
}
else if (month * day == year % 100) // if true then do this
{
cout << "The date you entered, " <<
month << "/" << day << "/" << year << " is a magic date!!\n";
}
else // if false then do this
{
cout << "The date you entered, " << month << "/" << day << "/" <<
year << " is NOT a magic date!!\n";
}
//Program ID
cout <<"\n" << "L5P1LB.cpp\n" << "11-26-12\n" << endl;
system ("pause");
return 0;
}//end main
// isDateValid function to validate date entered
bool isDateValid(int month, int day, int year)
{
bool validation = true;
if(!(year >= 1600 && year <=2100))
validation = false;
if(leapYear(year))
{
if ((month == 2) && (day > 29))
validation = false;
}
else if(!leapYear(year))
{
if ((month == 2) && (day > 28))
validation = false;
}
if((month < 1 && month > 12) || (day < 1))
validation = false;
if((month == 1) || (month ==3) || (month == 5) || (month == 7) ||
(month == 8) || (month == 10) || (month == 12) && (day > 31))
validation = false;
else if (((month == 4) || (month == 6) || (month == 9) || (month == 11)) &&
(day > 30))
validation = false;
else
validation == true;
return validation;
}
// leapYear function to determine if the year is a leap year for validation
bool leapYear(int year)
{
return(year % 100 != 0 && year % 4 == 0) || (year % 400 == 0);
} // end leapYear
EDIT
Okay now my problem is that I am not getting that it is NOT A valid date when it is. Its skipping the validation all together and just running the "magic date" part of it!
Here's the rewrite plus my full code hopefully indented here properly as it is in Bloodshed.
Description: This program determines if when the user enters a month,
day, and four digit year which will then be stripped down to its
two digit year and determined to be a magic date if the day entered
multiplied by the month entered equals the years two digit format.
Design:
begin main
input data
Ask user for a month in number form
Ask user for a day of the month
Ask user for four digit month
Validate
begin isDateValid
if year is between 1600 and 2100, inclusive then return
true
if month is between 1 and 12, inclusive return true
if month is Jan, Mar, May, July, Aug, Oct, Dec
then if day is between 1 and 31 inclusive return true
if month is Apr, June, Sept, Nov
then if day is between 1 and 30 inclusive return true
if month is Feb
then determine if leap year by running function
leapYear provided for us.
if leap year is true
then if day is between 1 and 29, inclusive return true
if not leap year then if day is between 1 and 28,
inclusive then return true
end isDateValid
if isDateValid is true then
Calculate
if the month times the year is equal to the year modulus 100
then output it is a magic date
if it does not equal the year in 2 digit form
then output that it is not a magic date
else output error message
Output Program ID
end main
The output needs to include the books data of 6/10/1960 */
#include <iostream>
using namespace std;
bool leapYear(int);
bool isDateValid(int, int, int);
int main()
{
int month, day, year;
cout << "Is the date you are thinking of a magic one? Let's see...\n";
cout << "What is the month in numeric form only? "; cin >> month;
cout << "What is the day of the month? "; cin >> day;
cout << "What is the four digit year? "; cin >> year;
if (isDateValid(month, day, year) == false)
{
cout << "The date you entered, "<< month << "/" << day << "/" <<
year << " is NOT a VALID Date.\n";
cout << "If you think I am wrong, please feel free to run me again";
}
else if (month * day == year % 100) // if true then do this
{
cout << "The date you entered, " <<
month << "/" << day << "/" << year << " is a magic date!!\n";
}
else // if false then do this
{
cout << "The date you entered, " << month << "/" << day << "/" <<
year << " is NOT a magic date!!\n";
}
//Program ID
cout <<"\n" << "L5P1LB.cpp\n" << "11-26-12\n" << endl;
system ("pause");
return 0;
} //end main
// isDateValid function to validate date entered
bool isDateValid(int month, int day, int year)
{
bool validation = true; // validation set to true
// if it is not between 1600 and 2100 then set to false
if(!(year >= 1600 && year <=2100))
validation = false;
// call leapYear function
if(leapYear(year))
{
// if February and day is greater than 29 then set to false
if ((month == 2) && (day > 29))
validation = false;
}
// else if NOT leapYear
else if(!leapYear(year))
{
// if February and day is greater then 28 then set to false
if ((month == 2) && (day > 28))
validation = false;
}
// if month is less then 1 and over 12 then set to false
if((month < 1 && month > 12))
validation = false;
// if day is less then 1 then set to false
if(day < 1)
validation = false;
// if month is 1 (Jan), 3 (Mar), 5 (May), 7 (July), 8 (Aug), 10 (Oct),
// or 12 (Dec) and day is greater then 31 set to false
if((month == 1) || (month ==3) || (month == 5) || (month == 7) ||
(month == 8) || (month == 10) || (month == 12) && (day > 31))
validation = false;
// if month is 4 (Apr), 6 (June), 9 (Sept), or 11 (Nov) and day is
// greater then 30 set to false
if (((month == 4) || (month == 6) || (month == 9) || (month == 11)) &&
(day > 30))
validation = false;
// else everything that is left set validation to true
else
validation = true;
return validation;
} // End isDateValid
// leapYear function to determine if the year is a leap year for validation
bool leapYear(int year)
{
return(year % 100 != 0 && year % 4 == 0) || (year % 400 == 0);
} // end leapYear
Sorry if I put in the wrong spot or anything!
Thanks for your help also. It is truly appreciated.
You had a few mistakes in your date validation.
The operator precedence noted by Luchian is one, but you had a few others:
You test that month < 1 && month > 12 - this is impossible, a month cannot be smaller than 1 and greater than 12
validation == true doesn't do anything. == is a comparison operator. Luckily this didn't affect your function as validation was already true when reaching this code.
I took the liberty to rewrite it in what I think is a cleaner fashion, but you could probably just fix the month check if you prefer to keep your version
bool isDateValid(int month, int day, int year)
{
bool validation = true;
if(!(year >= 1600 && year <=2100))
validation = false;
if(day < 1)
validation = false;
switch(month)
{
case 2:
if(leapYear(year)) // We only care about leap years in February
if(day > 29)
validation = false;
else
if(day > 28)
validation = false;
break;
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if(day > 31)
validation = false;
break;
case 4: case 6: case 9: case 11:
if(day > 30)
validation = false;
break;
default: // the month is not between 1 and 12
validation = false;
break;
}
return validation;
}
|| is short-circuiting, so (month == 1) || (month ==3) || (month == 5) || (month == 7) ||
(month == 8) || (month == 10) || (month == 12) && (day > 31) evaluates to true if the first conditions are met. You need to add an extra set of parenthesis:
((month == 1) || (month ==3) || (month == 5) || (month == 7) ||
(month == 8) || (month == 10) || (month == 12)) && (day > 31)
Same for the other months.
Also,
validation == true;
is a no-op, you probably meant validation = true.
Personally, I'd suggest something more direct and concise. The ? ternary operator can be a little confusing at first, but is very simple once clearly understood. I think of it as a kind of "if-else" that can be embedded in expressions.
bool isDateValid(int month, int day, int year)
{
return year >= 1600 && year<= 2100 &&
month >= 1 && month <= 12 &&
day >= 1 &&
day <= (month == 2 ? (leapyear(year) ? 29 : 28) :
month == 9 || month == 4 || month == 6 || month == 11 ? 30 : 31);
// "30 days has September, April, June and November..."
}
It may be a little more readable if you use an enum for month constants:
enum Month { Jan = 1, Feb, Mar, Apr ... };
Aim being to actually code:
day <= (month == Feb ? ...