I feel like an idiot asking for help every step of the way. My program is almost complete. I just can't seem to wrap my head around the constructor issue.

Here is the check list of what I have left:
Appropriately use the Dates(int,int,int) & the Dates(string,int,int) constructors;
Appropriately use the displayDates function;
Appropriately use the compareDates function (which I'm sure I can do once I get the other stuff done)

If I need to change the data type of my month data member please let me know...

My main concern with this is getting it to read the string months and display the date. It will read the number values of the months and convert it to the string value. However, I also need it to read in the string value of the month and display the string value of the month. The program will read until it reaches a string value and then it stops without reading the rest of the file. Any suggestions??
Here is the class set up:

#ifndef DATE_H
#define DATE_H

#include <string>
using namespace std;

class Date
{
public:
	//Member Functions
	//Constructors
	Date();
	Date(int,int,int);
	Date(string,int,int);

	//is the date valid
	bool isValidDate(int,int,int);

	//convert int to string
	string convertMonthNumberToString();

	//dsplays entire date using convertMonthNum... if necessary
	void displayDate();

	//compare the dates
	int compareDates(int,int,int);

	//display day number
	int dayNumber();

	//increment
	void increment();

	//is it a leap year
	bool isLeapYear();

	//setter
	void setDate(int,int,int);

	//getter
	int getMonth() const;
	int getDay() const;
	int getYear() const;

private:
	//Data members
	int month;
	int day;
	int year;
};
#endif //DATE_H

Here is the class implementation:

#include "testerResult.h"
#include <iostream>
#include <string>

using namespace std;

Date::Date()
{
	month = 0;
	day = 0;
	year = 0;
}

//Not sure if this is correct...
Date::Date(int m, int d, int y)
{
	m = month;
	d = day;
	y = year;
}

//was previously informed that this is incorrect
Date::Date(string m, int d, int y)
{
	m = convertMonthNumberToString();
	day = d;
	year = y;
}

//I think i need an if statement in here
void Date::displayDate()
{
	cout << convertMonthNumberToString() << " " << day << ", " << year;
}

//can probably figure this out after I get the other things done
int Date::compareDates(int m, int d, int y)
{
	return 0;
}

string Date::convertMonthNumberToString()
{
	switch (month)
	{
	case 1: return "January";
	case 2: return "February";
	case 3: return "March";
	case 4: return "April";
	case 5: return "May";
	case 6: return "June";
	case 7: return "July";  
	case 8: return "August";
	case 9: return "September";
	case 10: return "October";
	case 11: return "November";
	case 12: return "December";
	}
}

int Date::dayNumber()
{
	int numOfDaysInMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31};
	int dayNum = 0;
	for(int i = 1; i < month; i++)
	{
		dayNum += numOfDaysInMonth[i - 1];
	}
	return dayNum += day;
}

void Date::increment()
{
	if(day < 31)
	{
		day++;
	}
	else if(month < 12)
	{
		month++;
		day = 1;
	}
	else
	{
		year++;
		month = 1;
		day = 1;
	}

	if((isLeapYear() == true) && (month == 2 && day == 30))
	{
		month++;
		day = 1;
	}
	else if((isLeapYear() == false) && (month == 2 && day == 29))
	{
		month++;
		day = 1;
	}

}

bool Date::isLeapYear()
{
	bool result;
	if((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
	{
		result = true;
	}
	else
	{
		result = false;
	}
	return result;
}

bool Date::isValidDate(int m, int d, int y)
{
	if(m < 1 || m > 12)
	{
		return false;
	}
	else if(d < 1 || d > 31)
	{
		return false;
	}
	else if(y < 1800 || y > 2100)
	{
		return false;
	}
	else
	{
		return true;
	}
}

void Date::setDate(int m, int d, int y)
{
	if(m < 1 || m >12) return;
	month = m;
	if(d < 1 || d > 31) return;
	day = d;
	if(y < 1800 || y > 2100) return;
	year = y;
}


int Date::getMonth() const
{
	return month;
}
 
int Date::getDay() const
{
	return day;
}
 
int Date::getYear() const
{
	return year;
}

Recommended Answers

All 9 Replies

It will read the number values of the months and convert it to the string value. However, I also need it to read in the string value of the month and display the string value of the month. The program will read until it reaches a string value and then it stops without reading the rest of the file. Any suggestions??

I don't see any file reading at all in this program, so I am confused by the red above, which I'm interpreting as something you've already done. Regardless, please provide the input file and a driver program. Have you written the function prototypes yet or is that what you need help with?

Here is the main program file (the input file is attached):

#include "testerResult.h"
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

void readTextFile(ifstream &rif, int m, int d, int y)
{
	string line;
	string filename;
	cout << "Enter filename : ";
	cin >> filename;
	cout << endl;
	rif.open(filename.c_str(),ios::in,ios::binary);

	Date date1;

	if(rif.fail())
	{
		cout << "Cannot open file.";
		exit(1);
	}
	else
	{
		while(rif >> m >> d >> y)
		{
			
			date1.setDate(m,d,y);

			if(date1.isValidDate(m,d,y) == true)
			{
				cout << endl;
				date1.displayDate();
				cout << " is a valid date." << endl;

				cout << "This date is day number ";
				if((date1.isLeapYear() == true) && (m >= 3 || m <= 12))
				{
					cout << date1.dayNumber() + 1;
				}
				else
				{
					cout << date1.dayNumber();
				}
				cout << " of the year." << endl;

				if(date1.isLeapYear() == true)
				{
					cout << "This is a leap year." << endl;
				}
				else
				{
					cout << "This is not a leap year." << endl;
				}

				date1.increment();
				cout << "The date after incrementing is: ";
				date1.displayDate();

				cout << endl;
			}
			else
			{
				cout << endl;
				cout << m << "/" << d << "/" <<  y << endl;
				cout << "Invalid date." << endl;
			}
			cout << endl;
		}
	}
}

int main()
{
	ifstream rif;
	int m = 0;
	int d = 0;
	int y = 0;

	readTextFile(rif, m, d, y);

	return 0;
}

This line is going to crash the program when month isn't an integer:

while(rif >> m >> d >> y)

m is declared as an integer. You can't read a string in as an integer. You need to read it in as a string. You could do a few things. You could write a static function within your class like:

static int convertMonthToInt(string stringMonth)

If stringMonth is "1" or "January", return 1. If it's "2" or "February", return 2, etc.

Then when you read in from your file:

string stringMonth;
while(rif >> stringMonth >> d >> y)
{
    m = Date::convertMonthToInt (stringMonth);
   // code
}

The third constructor Date(string,int,int) is supposed to handle the string months. I have no clue how to set that up. I've been trying different things. I delcared a new data member 'const char *stringMonth' and have been trying to work with that. I've also thought about trying to use atoi and then use the convertMonthNumberToString() to convert it back to the string. Just not quite sure how to do that. I've also thought about trying to use a switch statement converting the strings to ints and then using the convertMonthNumberToString() to convert it back.

//This thing has been racking my brain for 2 weeks.

The third constructor Date(string,int,int) is supposed to handle the string months. I have no clue how to set that up.

Write the function I am talking about:

static int convertMonthToInt(string stringMonth)

and call it from the constructor, like I did in my example:

Date(string m,int d,int y)
{
    month = convertMonthToInt (m);
    day = d;
    year = y;
}

Regardless, read from the FILE as a string.

I've been trying different things. I delcared a new data member 'const char *stringMonth' and have been trying to work with that.

That's a hack. No new data members. Store month as an int. If you want to have a char* or const char* as a local variable in a function that converts, fine, but not as a data member. Don't store the month as a string, char*, or const char*. If you need to convert for display purposes, you already have a conversion function.

I've also thought about trying to use atoi and then use the convertMonthNumberToString() to convert it back to the string.

If you want to use atoi, fine, but don't convert "back" from an int to a string. When you have an int, it stays and int. Again, you already have a function that converts from an int to a string for display purposes.

convertMonthNumberToString()

I've also thought about trying to use a switch statement converting the strings to ints and then using the convertMonthNumberToString() to convert it back.

Same comment as before regarding converting it "back". There's more than one way to convert from the string to the integer. You can't use a switch statement on a string, so you're stuck with if statements there. Regarding converting "1", "2", "3", etc. to 1, 2, 3, you can convert from a string to char* and use atoi or you can use arrays. I'm an array guy and they're handy for the other months:

string monthInts[12] = {"1", "2", "3", ...};
string months[12] = {"January", "February", ...};

Loop through them and test with an if statment till one matches, then return the appropriate index. Makes for shorter code.

It is 4 in the morning but I finally got it to read in both ways....however....I can't get it to loop until it reads everything...

It will read in the dates that begin with strings (i.e. January 1 1900) until it hits a date that begins with an integer (i.e. 1 1 1900) and will read those until it hits another date that beings with a string, then it will display the last date in the file as an invalid date, whether it is a string or an int and then it will end.

I have attached the files so as to use less space....
the test file ---
--- datesFile.txt

the header file ---
--- testerResult.h

the implementation file ---
--- testerResult.cpp

the main file ---
--- resultTester.cpp


Any knowledge as to why it won't loop to read everything like it should?

oops....guess I was up too late. It only reads the string versions now....well...gotta keep workin...

int Date::convertMonthStringToInt(string stringMonth)
{
	if(stringMonth == "January")
		return 1;
	else if(stringMonth == "February")
		return 2;
	else if(stringMonth == "March")
		return 3;
	else if(stringMonth == "April")
		return 4;
	else if(stringMonth == "May")
		return 5;
	else if(stringMonth == "June")
		return 6;
	else if(stringMonth == "July")
		return 7;
	else if(stringMonth == "August")
		return 8;
	else if(stringMonth == "September")
		return 9;
	else if(stringMonth == "October")
		return 10;
	else if(stringMonth == "November")
		return 11;
	else if(stringMonth == "December")
		return 12;
}

What if stringMonth is "1", "2", "3", ... You need to be able to handle these. Add them to your function using if statements or atoi. Also add something for invalid data (strings that aren't "1" through "12" or "January" through "December". Have something like "ERROR" and have it display and end the program so you know exactly where the problem is.

Date::Date(string m, int d, int y)
{
	month = convertMonthStringToInt(m);
	day = d;
	year = y;
}

Put a cout statement or breakpoint in to see if this constructor is ever called. Looks like you convert your string to an int before you ever call a constructor here in your driver program:

string stringMonth;
		while(rif >> stringMonth >> d >> y)
		{
			m = Date::convertMonthStringToInt(stringMonth);

			date1.setDate(m,d,y);

Then you have a whole bunch of mostly the same code way below, starting with this:

while(rif >> m >> d >> y)

m is an int. Don't read in the month as an int directly from the file. Plus you've already exhausted the entire file in the previous while loop. You need to delete this entire while loop starting with the line above. It looks like a leftover from the last attempt.

Put a cout statement in all of your constructors. My guess is that they aren't being called more than once since you only have one Date object, declared well before the while loop and no new commands that might possibly call the constructor dynamically. That's fine, as far as I am concerned. You don't necessarily NEED more than one Date object, but stick some cout statements in those constructors so you know when they are called. You might be surprised.

commented: This has helped a ton.... Thanks!! +1

2 weeks of late nights and tons of assistance and its almost complete!!! The read in part is at least done. I also made it to read in months that were typed with a lower case beginning to be valid. Now I just have to compare dates and call it good. I will rack my brain until I hit a snag. Thanks a ton VernonDozier!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.