Why are my If else statements not working? - if-statement

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.

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;
}

rand() and srand() are not declared in this scope

I'm required to write a program that gives a person’s day and month of birth and will then figure out the person’s horoscope sign. The program should prompt the user for a number of persons. When the user responds, the program needs to automatically generate day and month and figure out and display the corresponding horoscope sign.
The program also needs to track number of persons for each sign and display that statistics. After that, the program needs to prompt the user if they want to go again. If the user responds with either a ‘Y’ or a
‘y’ the program needs to repeat the process until the user says that s/he is done.
I have a learning disability and i find it hard to understand sometimes what the questions that are being asked. I do not know how to answer them sometimes. So please be patience with me.
#include <ctime>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
int month, date, i, nOfPeople;
i = 0;
cout << "How many people: " << endl;
cout << "Born on Horoscope Sign" << endl;
cout << "-------------------------" << endl;
cin >> nOfPeople;
while (i < nOfPeople) {
// initialize random seed:
srand(time(NULL))
// generate month and date
month = rand() % 12 + 1;
date = rand() % 28 + 1;
if (month == 3 && date >= 21 || month == 4 && date <= 19) {
cout << "4/19 Aries" << endl;
} else if (month == 4 && date >= 20 || month == 5 && date <= 20) {
cout << "5/7 Taurus" << endl;
} else if (month == 5 && date >= 21 || month == 6 && date <= 21) {
cout << "Gemini" << endl;
} else if (month == 6 && date >= 22 || month == 7 && date <= 22) {
cout << "7/8 Cancer" << endl;
} else if (month == 7 && date >= 23 || month == 8 && date <= 22) {
cout << "8/17 Leo" << endl;
} else if (month == 8 && date >= 23 || month == 9 && date <= 22) {
cout << "Virgo" << endl;
} else if (month == 9 && date >= 23 || month == 10 && date <= 22) {
cout << "Libra" << endl;
} else if (month == 10 && date >= 23 || month == 11 && date <= 21) {
cout << "11/3 Scorpio" << endl;
} else if (month == 11 && date >= 22 || month == 12 && date <= 21) {
cout << "12/11 Saguittarius" << endl;
} else if (month == 12 && date >= 22 || month == 1 && date <= 19) {
cout << "12/22 Capricorn" << endl;
} else if (month == 1 && date >= 20 || month == 2 && date <= 18) {
cout << "Aquarius" << endl;
} else if (month == 2 && date >= 19 || month == 3 && date <= 20) {
cout << "2/21 Pieces" << endl;
}
i++;
}
return 0;
}
std::rand and std::srand are defined in <cstdlib>. Include that header then you should be able to use those functions.

Link the outcome of a formula to user input and validate if they match

So basically I just started to learn c++ and have an assignment which I'm totally stuck on, I googled it for days but just can't find out how to make it work.
The assignment is very simply:
Calculate the age of a person based on the user's input (Birth year, month, day).
The user needs to enter enter the day on which they were born (so for example: thursday)
The Program needs to validate if this is indeed correct
Now I am stuck on point 3;
I made a formula that calculates on which day someone is born. And basically that formula outputs a number 0 - 6 and that references to a day (0 would be sunday, 1 would be monday, etc.)
The problem is that a user would input for example thursday, but the program only recognizes nr 4 as thursday. So the program can't confirm or deny that the user is indeed born on a thursday.
To fix that, I tried the following:
This is the formula that calculates the number 0 to 6 (0 should equal sunday for example)
int fdb = ((jcr + mc + ec + birthday - sjc) % 7); //
This is the full code:
int birthdayfdb;
int sunday;
int monday;
int tuesday;
int wednesday;
int thursday;
int friday;
int saturday;
cout <<"On which day are you born?" << endl;
cin >> birthdayfdb; // Here the users inputs the day where he or she is born on
if ((birthdayfdb == sunday && fdb == 0) || (birthdayfdb == monday && fdb == 1) || (birthdayfdb == tuesday && fdb == 2) || (birthdayfdb == wednesday && fdb == 3) || (birthdayfdb == thursday && fdb == 4) || (birthdayfdb == friday && fdb == 5) || (birthdayfdb == saturday && fdb == 6))
{
cout << "This is Correct" << endl;
}
else
{
cout << "This is incorrect" << endl;
return 0;
}
So this does not work because whatever birthday the user enters, it always says that is is correct.
I looked up all sorts of things on the internet (stackflow, youtube, etc) but I can't find out how to do this.
Complete:
#include <iostream>
using namespace std;
int main ( ) {
int birthyear;
int birthmonth;
int birthday;
cout << “What is your birth year?” << endl;
cin >> birthyear;
if ((birthyear > 2008) || (birthyear < 1928))
{
cout <<“You are too old/young.“<< endl;
return 0;
}
cout << "In which month are you born? (Answer should be in
numbers)“<< endl;
cin >> birthmonth;
if (((birthmonth > 9) && (birthmonth == 2008)) || ((birthmonth < 9)
&& (birthmonth == 1928)))
{
cout <<"You are too old/young.”<< endl;
return 0;
}
cout << “On which day are you born?” << endl;
cin >> birthday;
if (((birthday > 24) && (birthmonth == 9) && (birthyear == 2008)) ||
((birthday < 24) && (birthmonth == 9) && (birthyear == 1928)))
{
cout <<"You are too old/young.”<< endl;
return 0;
}
double ageinyears = (2018 - birthyear);
int agemonths = (9 - birthmonth);
int agedays = (24 - birthday);
int totalmonths = ((ageinyears*12) + agemonths);
cout << “Your age is "<<ageinyears<<" jaar, "<<agemonths<<" months,
and " <<agedays<<" days, or "<<totalmonths<<" months.” << endl;
if ((birthday == 24) && (agemonths != 0))
{
cout <<" "<< endl;
cout << “Congratulations on your month anniversary!“<< endl;
cout <<" "<< endl;
}
else
{
cout << " "<< endl;
}
if ((birthday == 24) && (agemonths == 0))
cout <<" "<< endl;
cout << “Congrationlations with your birthday!”<< endl;
cout <<" "<< endl;
}
int jc = birthyear % 100;
int jcr = ((jc + (jc / 4)) % 7);
int ec;
if ((birthyear >= 1900) && (birthyear <= 1999))
{
ec = 0;
}
if ((birthyear >= 2000) && (birthyear <= 2099))
{
ec = 6;
}
int mc;
if ((birthmonth == 1) || (birthmonth == 10))
{
mc = 0;
}
if (birthmonth == 5)
{
mc = 1;
}
if (birthmonth == 8)
{
mc = 2;
}
if ((birthmonth == 2) || (birthmonth == 3) || (birthmonth == 11))
{
mc = 3;
}
if (birthmonth == 6)
{
mc = 4;
}
if ((birthmonth == 9) || (birthmonth == 12))
{
mc = 5;
}
if ((birthmonth == 4) || (birthmonth == 7))
{
mc = 6;
}
int sjc;
if ((birthmonth == 1 || 2) && (birthyear % 4 == 0 ))
{
sjc = 1;
}
else
{
sjc = 0;
}
int fdb = ((jcr + mc + ec + birthday - sjc) % 7);
cout << fdb << endl;
std::string birthdayfdb;
cout <<"On which day are you born?” << endl;
cin >> birthdayfdb;
bool check = false;
switch(fdb){
case 0:
if(birthdayfdb() == “sunday”) check = true;
case 1:
if(birthdayfdb() == “monday”) check = true;
case 2:
if(birthdayfdb() == “tuesday”) check = true;
case 3:
if(birthdayfdb() == “wednesday”) check = true;
case 4:
if(birthdayfdb() == “thursday”) check = true;
case 5:
if(birthdayfdb() == “friday”) check = true;
case 6:
if(birthdayfdb() == “saturday”) check = true;
}
if(check){
cout << "This is correct" << endl;
}
else{
cout << "This is incorrect" << endl;
}
}
You need to use a Switch Statement in order to achieve what you are looking for.
This is your full code fixed:
#include <iostream>
#include <string>
using namespace std;
int main ( ){
int birthyear;
int birthmonth;
int birthday;
cout << "What is your birth year?" << endl;
try{
cin >> birthyear;
}
catch(...){
cout << "A number is the only accepted input" << endl;
return 0;
}
cout << "In which month are you born? (Answer should be in numbers from 1 to 12)"<< endl;
try{
cin >> birthmonth;
}
catch(...){
cout << "A number is the only accepted input" << endl;
return 0;
}
cout << "On which day are you born?" << endl;
try{
cin >> birthday;
}
catch(...){
cout << "A number is the only accepted input" << endl;
return 0;
}
if ((birthday > 24 || birthday < 1) && (birthmonth > 9 || birthmonth < 1) && (birthyear > 2008 || birthyear < 1918)) {
cout <<"You are too old/young."<< endl;
return 0;
}
double ageinyears = (2018 - birthyear);
int agemonths = (9 - birthmonth);
int agedays;
switch (birthmonth){
case 2:
if((birthyear%100 == 0) && (birthyear%400 == 0)){
agedays = (29 - birthday);
}
else if(birthyear%4 == 0 && birthyear%100 != 0){
agedays = (29 - birthday);
}
else{
agedays = (28 - birthday);
}
break;
case 4:
agedays = (30 - birthday);
break;
case 11:
agedays = (30 - birthday);
break;
case 6:
agedays = (30 - birthday);
break;
case 9:
agedays = (30 - birthday);
break;
default:
agedays = (31 - birthday);
break;
}
int totalmonths = ((ageinyears*12) + agemonths);
cout << "Your age is " <<ageinyears<< " year, "<<agemonths<<" months, and " <<agedays<<" days, or "<<totalmonths<<" total months." << endl;
if ((birthday == 24) && (agemonths == 0)){
cout <<" "<< endl;
cout << "Congrationlations with your birthday!"<< endl;
cout <<" "<< endl;
}
else if ((agedays == 24) && (agemonths != 0)) {
cout <<" "<< endl;
cout << "Congratulations on your month anniversary!"<< endl;
cout <<" "<< endl;
}
int jc = birthyear % 100;
int jcr = ((jc + (jc / 4)) % 7);
int ec;
if ((birthyear >= 1900) && (birthyear <= 1999)){
ec = 0;
}
else if ((birthyear >= 2000) && (birthyear <= 2099)){
ec = 6;
}
int mc;
switch(birthmonth){
case 1:
mc = 0;
break;
case 2:
mc = 3;
break;
case 3:
mc = 3;
break;
case 4:
mc = 6;
break;
case 5:
mc = 1;
break;
case 6:
mc = 4;
break;
case 7:
mc=6;
break;
case 8:
mc = 2;
break;
case 9:
mc = 5;
case 10:
mc = 0;
break;
case 11:
mc = 3;
break;
case 12:
mc = 5;
break;
}
int sjc;
if ((birthmonth == 1 || 2) && (birthyear % 4 == 0 )){
sjc = 1;
}
else{
sjc = 0;
}
int fdb = ((jcr + mc + ec + birthday - sjc) % 7);
std::string birthdayfdb;
cout <<"On which day are you born? E.G. monday" << endl;
try{
cin >> birthdayfdb;
}
catch(...){
cout << "only english days name are accepted!";
return 0;
}
cin >> birthdayfdb;
bool check = false;
switch(fdb){
case 0:
if(birthdayfdb == "sunday") check = true;
break;
case 1:
if(birthdayfdb == "monday") check = true;
break;
case 2:
if(birthdayfdb == "tuesday") check = true;
break;
case 3:
if(birthdayfdb == "wednesday") check = true;
break;
case 4:
if(birthdayfdb == "thursday") check = true;
break;
case 5:
if(birthdayfdb == "friday") check = true;
break;
case 6:
if(birthdayfdb == "saturday") check = true;
break;
}
if(check){
cout << "This is correct" << endl;
}
else{
cout << "This is incorrect" << endl;
}
}
As you can see, we used a boolean variable (bool check;) to save if the user input is validated in order to print (later) the messagge on the screen.
Of course you could just print inside the Switch Case Statement like this:
case 0:
if(birthdayfdb == "sunday"){
cout << "This is correct" << endl;
}
else{
cout << "This is incorrect"<< endl;
}
But this would make it longer and a bit slower. Also, in the above case there are alot of repetition (pretty much the same if statement on every case) while is preferred to just code one single print while saving on a bool variable if the validation of the input is OK.
FIXES:
A little mistake that causes ALOT of problem: you were using ” insted of " to denote strings
You were using alot of If statement instead of using else if
For the birthday calculation is better to use a switch statement
I removed some useless blank output e.g. cout << " " <<endl;
You were declaring some string variable as int e.g. int birthdayfdb
You were checking the user input 3 times while most of the check was a repetition. I change it with only one input validation at the end of the inputs
Another one little mistake that causes alot of problems. You were refering to birthdayfdb as a function and not a string. E.G. if(birthdayfdb() == "sunday") check = true;
A very BIG MISTAKE is the absence of errors handling and a well-done input validation! e.g. If the user type "foo" instead of his birthyear
for further information about String, Data Types, Switch Case statement and Try/Catch statement read the linked documentation!

calling constructor from member function

Here's the question:
Define a class called Month that is an abstract data type for a month. Your class will have one member variable of type int to represent a month (1 for January, 2 for February, and so forth). Include all the following member functions: a constructor to set the month using the first three letters in the name of the month as three arguments, a constructor to set the month using an integer as an argument (1 for January, 2 for February, and so forth), a default constructor, an input function that reads the month as an integer, an input function that reads the month as the first three letters in the name of the month, an output function that outputs the month as an integer, an output function that outputs the month as the first three letters in the name of the month, and a member function that returns the next month as a value of type Month . Embed your class definition in a test program.
#include <iostream>
using namespace std;
class Month
{
public:
Month (char letter1, char letter2, char letter3);
Month (int numOfMonth);
Month ();
void inputAsNum(); // read month as integer
void inputAsCh(); // read first three chars of month
void outputAsCh() const;
void outputAsNum() const;
Month nextMonth();
private:
int month;
};
int main()
{
Month test(5);
//test.inputAsNum();
cout << "Current month is " << endl;
test.outputAsCh();
test.outputAsNum();
cout << endl;
test.nextMonth();
cout << "Next month is " <<endl;
test.outputAsCh();
test.outputAsNum();
cout << endl;
Month test2('a','p','r');
//test2.inputAsCh();
cout << "Current month is " << endl;
test2.outputAsCh();
test2.outputAsNum();
cout << endl;
test2.nextMonth();
cout << "Next month is " <<endl;
test2.outputAsCh();
test2.outputAsNum();
cout << endl;
Month test3;
test3.inputAsNum();
cout << "Current month is " << endl;
test3.outputAsCh();
test3.outputAsNum();
cout << endl;
test3.nextMonth();
cout << "Next month is " <<endl;
test3.outputAsCh();
test3.outputAsNum();
cout << endl;
Month test4;
test4.inputAsCh();
cout << "Current month is " << endl;
test4.outputAsCh();
test4.outputAsNum();
cout << endl;
test4.nextMonth();
cout << "Next month is " <<endl;
test4.outputAsCh();
test4.outputAsNum();
cout << endl;
return 0;
}
Month::Month (char letter1, char letter2, char letter3)
{
if ((letter1 == 'j')&&(letter2 == 'a')&&(letter3 == 'n'))
month= 1;
else if ((letter1 == 'f')&&(letter2 == 'e')&&(letter3 == 'b'))
month= 2;
else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'r'))
month= 3;
else if ((letter1 = 'a')&&(letter2 == 'p')&&(letter3 == 'r'))
month= 4;
else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'y'))
month= 5;
else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'n'))
month= 6;
else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'l'))
month= 7;
else if ((letter1 == 'a')&&(letter2 == 'u')&&(letter3 == 'g'))
month= 8;
else if ((letter1 == 's')&&(letter2 == 'e')&&(letter3 == 'p'))
month= 9;
else if ((letter1 == 'o')&&(letter2 == 'c')&&(letter3 == 't'))
month= 10;
else if ((letter1 == 'n')&&(letter2 == 'o')&&(letter3 == 'v'))
month= 11;
else if ((letter1 == 'd')&&(letter2 == 'e')&&(letter3 == 'c'))
month= 12;
}
Month::Month (int numOfMonth)
:month(numOfMonth)
{ }
Month::Month ()
:month(1)
{ }
void Month::inputAsNum()
{
int num;
cout << "Enter num of month => ";
cin >> num;
month = num;
}
void Month::inputAsCh()
{
char c1,c2,c3;
cout << "Enter three letters of month => ";
cin >> c1 >> c2 >> c3;
Month::Month(c1,c2,c3);
}
void Month::outputAsCh() const
{
if (month == 1)
cout << "Jan ";
else if (month == 2)
cout << "Feb ";
else if (month == 3)
cout << "Mar ";
else if (month == 4)
cout << "Apr ";
else if (month == 5)
cout << "May ";
else if (month == 6)
cout << "Jun ";
else if (month == 7)
cout << "Jul ";
else if (month == 8)
cout << "Aug ";
else if (month == 9)
cout << "Sep ";
else if (month == 10)
cout << "Oct ";
else if (month == 11)
cout << "Nov ";
else if (month == 12)
cout << "Dec ";
}
void Month::outputAsNum() const
{
cout << month;
}
Month Month::nextMonth()
{
if (month < 12)
month++;
else if (month == 12)
month = 1;
return Month(month);
}
The code runs just fine. I try that calling constructor Month::Month (char letter1, char letter2, char letter3) from member function void Month::inputAsCh() . I can solve the problem by changing definition of Month::inputAsCh() and copy paste definitions of the constructor into the function. But, just out of curiosity, can be a constructor called from member function ? If it's okey, Month::inputAsCh() works wrong, I also try on Month test4 variable.
Output Expected Output
------------- -----------------
Current month is Current month is
Nov 11 Nov 11
Next month is Next month is
Dec 12 Dec 12
Current month is Current month is
Apr 4 Apr 4
Next month is Next month is
May 5 May 5
Enter num of month => 2 Enter num of month => 2
Current month is Current month is
Feb 2 Feb 2
Next month is Next month is
Mar 3 Mar 3
Enter three letters of month => apr Enter three letters of month => apr
Current month is Current month is
Jan 1 Apr 4
Next month is Next month is
Feb 2 May 5
Month::Month(c1,c2,c3);
That line doesn't update the current object. It should be an error because Month::Month names the constructor in that context, but some compilers (notably clang) will interpret it as the construction of a temporary object instead (thanks to user657267 for the correction).
You could factor out your month calculation code into a separate function, then call that from both your constructor and your inputAsCh function:
void setMonth(char letter1, char letter2, char letter3)
{
if ((letter1 == 'j')&&(letter2 == 'a')&&(letter3 == 'n'))
month= 1;
else if ((letter1 == 'f')&&(letter2 == 'e')&&(letter3 == 'b'))
month= 2;
else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'r'))
month= 3;
else if ((letter1 = 'a')&&(letter2 == 'p')&&(letter3 == 'r'))
month= 4;
else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'y'))
month= 5;
else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'n'))
month= 6;
else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'l'))
month= 7;
else if ((letter1 == 'a')&&(letter2 == 'u')&&(letter3 == 'g'))
month= 8;
else if ((letter1 == 's')&&(letter2 == 'e')&&(letter3 == 'p'))
month= 9;
else if ((letter1 == 'o')&&(letter2 == 'c')&&(letter3 == 't'))
month= 10;
else if ((letter1 == 'n')&&(letter2 == 'o')&&(letter3 == 'v'))
month= 11;
else if ((letter1 == 'd')&&(letter2 == 'e')&&(letter3 == 'c'))
month= 12;
}
Month::Month (char letter1, char letter2, char letter3)
{
setMonth(letter1, letter2, letter3);
}
void Month::inputAsCh()
{
char c1,c2,c3;
cout << "Enter three letters of month => ";
cin >> c1 >> c2 >> c3;
setMonth(c1,c2,c3);
}
Incidentally, your setMonth function could be greatly simplified by creating a std::string from those chars and comparing with that instead.

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 ? ...