I have a c++ assignment that asks to enter one date and second date and find the number of days between the two, including leap years. My code displays the correct values for two dates, however when tested for 1/2/3 to 3/21/12345, it displays 4507994, which is 93 more days than the correct value of 4507901. Why is this happening? I am including cstdlib and iostream
using namespace std;
bool isLeapYear (int year)
{
bool tf;
if (year%4 !=0)
{
tf = true;
}
else if (year%4 == 0)
{
if (year%1000 == 0)
{
if (year %400 == 0)
{
tf = false;
}
else
{
tf = true;
}
}
tf = false;
}
return tf;
}
int last_day(int month, int year)
{
int lday;
if (month == 2)
{
if (isLeapYear (year) == false)
{
lday = 29;
}
else
{
lday = 28;
}
}
else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8|| month == 10 || month ==12)
{
lday = 31;
}
else if (month == 4 || month == 6 || month == 9 || month == 11)
{
lday = 30;
}
return lday;
}
void howlongwait (int &month, int &day, int &year)
{
if (day == last_day(month, year))
{
if (month == 12 && day == 31)
{
month = 1;
day = 1;
year = year+1;
}
else
{
month = month+1;
day = 1;
year = year;
}
}
else
{
month = month;
day = day+1;
year = year;
}
}
int main()
{
int month, month2, day2, day, year, year2;
int days = 0;
char trash, garb, garb2, trash2;
cout << "Enter start date (no spaces): " << endl;
cin >> month >> trash >> day >> garb >> year;
cout << "Enter end date (no spaces): " << endl;
cin >> month2 >> trash2 >> day2 >> garb2 >> year2;
if (year2 < year)
{
cout << "Never..." << endl;
return 0;
}
else
{
while ((month != month2) || (day != day2) || (year != year2))
{
howlongwait (month, day, year);
days=days+1;
}
}
cout << "You have to wait " << days << " days" << endl;
}
`
isLeapYear should be fixed like this:
bool isLeapYear (int y)
{
return y%4 == 0 && (y%400 == 0 || y%100 != 0);
}
and please replace isLeapYear (year) == false to isLeapYear (year) == true.
Your version of isLeapYear is:
year%1000 == 0 should be year%100 == 0
corresponding else is missing
flip true and false, or change the function name if you need
Related
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;
}
This program asks for a number from 1 to 12 and prints out the month and season correspondent to the input number, if the user types anything else than numbers from 1 to 12 an error message is displayed. It looks like the first if statement runs perfectly with its correspondent nested statements but the next else if statements wont work, try with 1, 2, and 12 and the program will work perfectly, but it doesn't with any other value, does anyone knows why this is happening?
Here's the program...
#include <iostream>
#include <string>
using namespace std;
int main() {
int number;
string season, month;
cout << "Welcome! This program will provide the season of the year based on the month you enter, 1 corresponding to January, 2 for February and so on until 12 for December" << endl << endl;
cout << "Enter a number between 1 and 12: ";
cin >> number;
if (number == 1 || 2 || 12)
{
if (number == 1)
{
month = "January";
season = "winter";
}
else if (number == 2)
{
month = "February";
season = "winter";
}
else if (number == 12)
{
month = "December";
season = "winter";
}
}
else if (number == 3 || 4 || 5)
{
if (number == 3)
{
month = "March";
season = "spring";
}
else if (number == 4)
{
month = "April";
season = "spring";
}
else if (number == 5)
{
month = "May";
season = "spring";
}
}
else if (number == 6 || 7 || 8 )
{
if (number == 6)
{
month = "June";
season = "summer";
}
else if (number == 7)
{
month = "July";
season = "summer";
}
else if (number == 8)
{
month = "August";
season = "summer";
}
}
else if (number == 9 || 10 || 11)
{
if (number == 9)
{
month = "September";
season = "fall";
}
else if (number == 10)
{
month = "October";
season = "fall";
}
else if (number == 11)
{
month = "November";
season = "fall";
}
}
else
{
cout << "You entered an ivalid value";
return 0;
}
cout << "-------------------------------------------------------------" << endl;
cout << "You entered " << number << ". " << month << " is the " << season << " season.";
return 0;
}
I believe that the || operator does not work how you are using it. That is, the statement if (number == 1 || 2 || 12) is likely being converted into boolean values:
number == 1
2
12
So imaging you are forcing each of those values into a boolean representation. There's probably a more exact way of explaining this though.
The fix is likely to do this:
if (number == 1 || number == 2 || number == 12)
etc.
#include <iostream>
using namespace std;
int daysMonth (int month) // the part to clarify
{
if (month >= 1 && month <= 12){
if (month == 2)
return 28;
if (month == 4 || month == 6 || month == 9 || month == 11)
return 30;
return 31;
}
return 0;
}
void nextDay (int day, int month, int year) // nextday conditions
{
int daysOfMonth = daysMonth(month);
if ((year % 4 == 0) && (year % 100 != 0) || year % 400 == 0)
{
if (day == 28){
day = 29;
month = month;
year = year;
}
}
if (day != daysOfMonth)
{
day = day + 1;
month = month;
year = year;
}
if (day == daysOfMonth)
{
day = 1;
month = month + 1;
year = year;
}
if ((month == 12) && (day == 31))
{
day = 1;
month = 1;
year = year + 1;
}
cout << "Next day is : " << day << "/" << month << "/" << year << endl;
}
int main(){
int day;
int month;
int year;
cout << "Enter a date : " << endl;
cin >> day;
cin >> month;
cin >> year;
cout << "Your chosen date is : " << day << "/" << month << "/" << year << endl;
if (day >= 1 && day <= 31 && month >= 1 && month <= 12)
{
nextDay(day, month, year);
}
else
cout << "Invalid date" << endl;
}
Now my question is the following :
If I'm entering 28/02/2016 I'm getting 30/02/2016.
The other question is :
Is there a way to get the date in the DD/MM/YYYY format and then get the DD MM YYYY with a coommand like stoi - I mention that the command is not working for me.
I was trying to get the results like usual if I input 28/02/2016 I should get 29/02/2016 - I know there's another condition to increase the day + 1 but why isn't that skipped ?
I'm trying to assign bool leapyear to true/false if the requirements of if statement are met
#include <iostream>
using namespace std;
int main()
{
int month;
int year;
bool leapyear;
cout << "Enter a month (1-12): ";
cin >> month;
cout << "Enter a year: ";
cin >> year;
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
cout << "31 days\n";
}
else if (month == 4 || month == 6 || month == 9 || month == 11) {
cout << "30 day\n";
}
if ((year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
bool leapyear = true;
cout << "This year is a leap year!\n";
}
else {
bool leapyear = false;
cout << "This year is not a leap year!\n";
}
if (leapyear == true && month == 2) {
cout << "29 days\n";
}
else if (leapyear == false && month == 2) {
cout << "28 days\n";
}
}
but when I run the code visual showed me an error
Uninitialized local variable 'leapyear' used
Just remove the two bool in your if and else blocks and give an initial value to your leapyear variable. You are trying to define a variable with the same name several times instead of just changing its value, which is probably what you want to do here.
Initialization:
int month;
int year;
bool leapyear = false; // You have to initialize the value of your variable here.
If and else statements:
if ((year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
leapyear = true;
cout << "This year is a leap year!\n";
}
else {
leapyear = false;
cout << "This year is not a leap year!\n";
}
You have to understand the difference between creating a variable and setting its value.
bool leapyear = false; // Create a leapyear variable with the initial value false
leapyear = true; // Modify the value of the leapyear variable with the value true
Your code has three different variables, all called leapyear, and each that exists for a different part of the code.
At the top of your program, you declared leapyear:
int month;
int year;
bool leapyear; // This variable is not initialized.
Down later, you declare more variable2, also called leapyear:
if ((year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
// New Variable declared here!
// It has the same name, but is a different variable
bool leapyear = true;
cout << "This year is a leap year!\n";
// The local variable ends here
// It goes "out-of-scope", and no longer exists.
}
else {
// New Variable declared here!
bool leapyear = false;
cout << "This year is not a leap year!\n";
// The Variable goes "out-of-scope" here, and no longer exists.
}
Later on, when your code does this:
// Using the original variable, which is STILL not initialized
if (leapyear == true && month == 2) {
cout << "29 days\n";
}
else if (leapyear == false && month == 2) {
cout << "28 days\n";
}
I am working on a homework assignment for my C++ class, but I'm have difficulty with my overloading constructor.The default constructor works fine but the overloading constructor will not work properly.Any guidance would be appericated.
/*
Name:Isis Curiel
Date:04/05/2017
Assignment 10
Instructions:
Redo assignment 5 by
1. Defining a class Date that has
(1) Three member variables:
date,
month,
year
(2) member functions
constructor: Initializes the Date to the given month, day and
year or to the default value. you can overload the constructor,
or use default arguments.
example use:
Date today(3,31, 2017); // 03/31/2017
Date firstDay; // will be 01/01/2017
reset: reset the month, day and year based on the parameters. So today.reset(4,1,2017); will change today to 04/01/2017.
get_day_of_week: return the day of the week as int 0-6
get_day_of_week_name: return the day of the week as a string
print: print out the date information include the date, month, year, day of the week.
(3) helper funcions:
bool is_leap_year();
// Returns true if the given year is a leap year
int get_century_value();
// Returns a value computed from the century of the year
int get_year_value();
// Returns a value computed based on the years since the beginning of the century.
int get_month_value();
// Returns a value (from a table) for the Date's month
2. write a main function to test the class.
*/
#include "stdafx.h"
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
class Date {
private:
int date, month, year, newDate, newMonth, newYear;
/*
reset: reset the month, day and year based on the parameters. So today.reset(4,1,2017); will change today to 04/01/2017.
get_day_of_week: return the day of the week as int 0-6
get_day_of_week_name: return the day of the week as a string
print: print out the date information include the date, month, year, day of the week.
*/
public:
Date() {
month = 01;
date = 01;
year = 2017;
}
Date(int fmonth, int fdate, int fyear) {
fmonth = month;
fdate = date;
fyear = year;
}
bool is_leap_year(int year) {
if (((year % 4 == 0) && (!(year % 100 == 0))) || ((year % 400 == 0)))
{
////isLeapYear = true;
return true;
}
else
return false;
}
int get_century_value(int year) {
int centValue;
year = year / 100;
year = year % 4;
year = 3 - year;
year = year * 2;
centValue = year;
return centValue;
}
int get_year_value(int year) {
int y1;
int yearVal;
year = year % 100;
y1 = year / 4;
yearVal = y1 + year;
return yearVal;
}
int get_month_value(int month, int year) {
if (month == 1 && is_leap_year(year) == false)
return 0; ///but doesnt returning 0 cause issues ?
else if (month == 1 && is_leap_year(year))
return 6;
else if (month == 2 && is_leap_year(year) == false)
return 3;
else if (month == 2 && is_leap_year(year))
return 2;
else if (month == 3)
return 3;
else if (month == 4)
return 6;
else if (month == 5)
return 1;
else if (month == 6)
return 4;
else if (month == 7)
return 6;
else if (month == 8)
return 2;
else if (month == 9)
return 5;
else if (month == 10)
return 0;
else if (month == 11)
return 3;
else if (month == 12)
return 5;
else
return 6;
}
int get_day_of_week(int month, int date, int year) {
int x;
x = ((date + get_month_value(month, year) + get_year_value(year) + get_century_value(year)) % 7);
///((getMonthValue + getYearValue + getCenturyValue)%7)
return x;
}
void get_day_of_week_name(int month, int date, int year) {
if (month > 12 || month < 1) {
cout << "Try again Please enter a month, day, and year, separated by " <<
"spaces(e.g., '7 4 2008') : ";
get_day_of_week(month, date, year);
cin >> month;
cin >> date;
cin >> year;
}
else if (month == 2 && date == 29 && is_leap_year(year) == false)
{
cout << "Try again Please enter a month, day, and year, separated by " <<
"spaces(e.g., '7 4 2008') : ";
get_day_of_week(month, date, year);
cin >> month;
cin >> date;
cin >> year;
}
else if (date > 31 || date < 1) {
cout << "Try again Please enter a month, day, and year, separated by " <<
"spaces(e.g., '7 4 2008') : ";
get_day_of_week(month, date, year);
cin >> month;
cin >> date;
cin >> year;
}
else if (month == 4 || month == 7 || month == 9 || month == 11 && date > 30) {
cout << "Try again Please enter a month, day, and year, separated by " <<
"spaces(e.g., '7 4 2008') : ";
get_day_of_week(month, date, year);
cin >> month;
cin >> date;
cin >> year;
}
else {
string dayW;
if (get_day_of_week(month, date, year) == 0)
dayW = "Sunday";
else if (get_day_of_week(month, date, year) == 1)
dayW = "Monday";
else if (get_day_of_week(month, date, year) == 2)
dayW = "Tuesday";
else if (get_day_of_week(month, date, year) == 3)
dayW = "Wednesday";
else if (get_day_of_week(month, date, year) == 4)
dayW = "Thursday";
else if (get_day_of_week(month, date, year) == 5)
dayW = "Friday";
else if (get_day_of_week(month, date, year) == 6)
dayW = "Saturday";
else
dayW = "INVALID";
cout << dayW;
}
}
void print() {
string dayW;
if (get_day_of_week(month, date, year) == 0)
dayW = "Sunday";
else if (get_day_of_week(month, date, year) == 1)
dayW = "Monday";
else if (get_day_of_week(month, date, year) == 2)
dayW = "Tuesday";
else if (get_day_of_week(month, date, year) == 3)
dayW = "Wednesday";
else if (get_day_of_week(month, date, year) == 4)
dayW = "Thursday";
else if (get_day_of_week(month, date, year) == 5)
dayW = "Friday";
else if (get_day_of_week(month, date, year) == 6)
dayW = "Saturday";
else
dayW = "INVALID";
cout << "Today is " << dayW << " " << month <<
" " << date << " " << year << endl; //prints out day and full date
}
void reset(int newDate,int newMonth, int newYear) {
newDate = date;
newMonth = month;
newYear = year;
}
};
int main()
{
int i = 3;
int z = 31;
int f = 2017;
Date today(i,z,f); // 03/31/2017
today.print();
Date firstDay; // will be 01/01/2017
firstDay.print();
Sleep(50000);
return 0;
}
You have the assignments backwards.
Date(int fmonth, int fdate, int fyear) {
fmonth = month;
fdate = date;
fyear = year;
}
should be
Date(int fmonth, int fdate, int fyear) {
month = fmonth;
date = fdate;
year = fyear;
}