날짜 처리를 위한 Date 클래스 (Dates Manipulation)
cpp
#include <iostream>
#include <cstring>
#include <sstream> // new header including - using stringstream (Date::toString())
#include <cassert> // using assert function
using namespace std;
class Date {
// Put your private data fields here.
private:
// friend member
friend ostream& operator<<(ostream& output, Date* p)
{
output << p->toString(); // This mean output(Date* p's address) changes string p->toString().
return output;
};
// operator'<<' overloading ..
// if Date* d1 = new Date(12/31/2009); , cout << d1;'s output is d1's address..
// To solve this problem, I choose operator << overloading.
// I don't add This line (friend ostream& op...) to class Date public.
// It is private , not public. So, it is legal! (from Notes on grading)
// operator << overloading - reference : http://www.fredosaurus.com/notes-cpp/oop-friends/overload-io.html
int m_month;
int m_day;
int m_year;
// Constructs a date with the given month, day and year. If the date is
// not valid, the entire program will halt with an error message.
// @param month is a month, numbered in the range 1...12.
// @param day is between 1 and the number of days in the given month.
// @param year is the year in question, with no digits omitted.
public:
Date(int month, int day, int year)
{
// error message - for Invalid Date
assert(isValidDate(month, day, year)); // print error message & line number & program halts
m_month = month;
m_day = day;
m_year = year;
}
// Constructs a Date object corresponding to the given string.
// @param s should be a string of the form "month/day/year" where month must
// be one or two digits, day must be one or two digits, and year must be
// between 1 and 4 digits. If s does not match these requirements or is not
// a valid date, the program halts with an error message.
Date(string s)
{
// Convert string to int using C++ - reference : http://www.techbytes.ca/techbyte99.html (lang:english)
const char* ds = s.c_str(); // convert string to const char*
int k=0,t=0;
unsigned i=0;
int month,day,year;
string t_s;
const char* t_c;
// string
for(i=0;i<s.length();i++)
{
if(ds[i] == '/') k++;
}
if(k>2)
{
cout << "\nError: Invalid String.\n";
} else {
k=0;
// string::length - reference : http://www.cplusplus.com/reference/string/string/length/
for(i=0;i<s.length();i++) // s.length() means string s's length.
{
if(ds[i] == '/')
{
k++;
t_s = s.substr(t, i-1); // substr from string s
// string::substr - reference : http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
if(t==0&&i==1) t_s=s[0];
t_c = t_s.c_str(); // string member - c_str() .. convert string to const char*
if(k==1) { // first-order - t_c is 'const char*' & it means month
month = atoi(t_c);t=i+1; // function atoi(const char*) - convert const char* to integer
}
if(k==2) { // second-order - t_c is 'const char*' & it means day
day = atoi(t_c);t=i+1;
}
}
if(i==s.length()-1) { // t_c means year
t_s = s.substr(t, i-1);
t_c = t_s.c_str();
year = atoi(t_c); //break;
}
}
// error message - for Invalid Date
assert(isValidDate(month, day, year)); // print error message & line number & program halts
m_month = month;
m_day = day;
m_year = year;
}
}
// Checks whether the given year is a leap year.
// @return true if and only if the input year is a leap year.
static bool isLeapYear(int year)
{
// leapyear reference : http://blog.naver.com/makesome/140002664401 (lang:korean)
if(year%4==0)
{
if(year>=1582)
{
if(year%100==0)
{
if(year%400 ==0)
{
return true;
} else {
return false;
}
} else {
return true;
}
} else {
return true;
}
} else {
return false;
} // replace this line with your solution
}
// Returns the number of days in a given month.
// @param month is a month, numbered in the range 1...12.
// @param year is the year in question, with no digits omitted.
// @return the number of days in the given month.
static int daysInMonth(int month, int year)
{
if(month==1 ||month==3 ||month==5 ||month==7 ||month==8 ||month==10 ||month==12)
{
return 31;
} else if(month==2) {
if(isLeapYear(year))
{
return 29;
} else {
return 28;
}
} else {
return 30;
}
}
// Checks whether the given date is valid.
// @return true if and only if month/day/year constitute a valid date.
// Years prior to A.D. 1 are NOT valid.
static bool isValidDate(int month, int day, int year)
{
if(year < 1 || year>9999) return false; // Years prior to A.D. 1 are NOT valid.
if(month < 1 || month >12) return false;
if(day<1 || day>daysInMonth(month,year)) return false;
return true;
}
// Returns a string representation of this date in the form month/day/year.
// The month, day, and year are printed in full as integers; for example,
// 12/7/2006 or 3/21/407.
// @return a string representation of this date.
string toString()
{
// old C style (failed) - using non-standard function: itoa, _itoa, _itoa_s (only for microsoft visual studio)
/*
char buffer[4];
_itoa_s(m_month, buffer, 10);
string month = buffer;
_itoa_s(m_day, buffer, 10);
string day = buffer;
_itoa_s(m_year, buffer, 10);
string year = buffer;
*/
// New C++ Style - using stringstream
//
// standard string class - reference : http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html (lang:english)
//
// C++ string class - reference : http://www.synch3d.com/wiki/moin/moin.cgi/C_2b_2b_20string_20_c5_ac_b7_a1_bd_ba (lang:korean)
//
// How do I convert a value (a number, for example) to a std::string?
// - reference : http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.1
//
// C++ — Convert int to string
// - reference : http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/
string is;
stringstream s_month,s_day,s_year;
s_month << m_month;
is += s_month.str();
is += '/';
s_day << m_day;
is += s_day.str();
is += '/';
s_year << m_year;
is += s_year.str();
return is;
}
// Determines whether this Date is before the Date d.
// @return true if and only if this Date is before d.
bool isBefore(Date* d)
{
if(m_year < d->m_year)
{
return true;
} else if(m_year > d->m_year)
{
return false;
} else {
if(m_month < d->m_month)
{
return true;
} else if(m_month > d->m_month)
{
return false;
} else {
if(m_day < d->m_day)
{
return true;
} else {
return false;
}
}
}
}
// Determines whether this Date is after the Date d.
// @return true if and only if this Date is after d.
bool isAfter(Date* d)
{
if(m_year > d->m_year)
{
return true;
} else if(m_year < d->m_year)
{
return false;
} else {
if(m_month > d->m_month)
{
return true;
} else if(m_month < d->m_month)
{
return false;
} else {
if(m_day > d->m_day)
{
return true;
} else {
return false;
}
}
}
}
// Returns the number of this Date in the year.
// @return a number n in the range 1...366, inclusive, such that this Date
// is the nth day of its year. (366 is only used for December 31 in a leap
// year.)
int dayInYear()
{
int tmp, sum=0, t_month;
for (t_month=1;t_month<m_month;t_month++)
{
tmp = daysInMonth(t_month,m_year);
sum += tmp;
}
sum += m_day;
return sum;
}
// Determines the difference in days between d and this Date. For example,
// if this Date is 12/15/1997 and d is 12/14/1997, the difference is 1.
// If this Date occurs before d, the result is negative.
// @return the difference in days between d and this date.
int difference(Date* d)
{
int i, sum=0, c_year;
if(isAfter(d))
{
c_year = m_year - d->m_year;
if(c_year==0)
{
return (dayInYear()-d->dayInYear());
} else {
for(i=d->m_year;i<m_year;i++)
{
if(isLeapYear(i)) sum+=366;
else sum+=365;
}
sum += dayInYear() - d->dayInYear();
return sum;
}
} else if(isBefore(d)) {
c_year = d->m_year - m_year;
if(c_year==0)
{
return (dayInYear()-d->dayInYear());
} else {
for(i=m_year;i<d->m_year;i++)
{
if(isLeapYear(i)) sum+=366;
else sum+=365;
}
sum += d->dayInYear() - dayInYear();
return (-sum);
}
} else {
return 0;
}
}
};
int main()
{
cout << "\nTesting constructors." << endl;
Date* d1 = new Date(1, 1, 1);
/*
// Test Temp value
string temp_string;unsigned int i;
// Testing Date.toString()
temp_string = d1->toString();
cout << "\nTesting Date class by three integer- \nDate should be 1/1/1: ";
for(i=0;i<temp_string.length();i++) cout << temp_string[i];
cout << "\n\n";
// end
*/
cout << "Date should be 1/1/1: " << d1 << endl;
d1 = new Date("2/4/2");
cout << "Date should be 2/4/2: " << d1 << endl;
d1 = new Date("2/29/2000");
cout << "Date should be 2/29/2000: " << d1 << endl;
d1 = new Date("2/29/1904");
cout << "Date should be 2/29/1904: " << d1 << endl;
/*
// Testing Date.toString()
temp_string = d1->toString();
cout << "\nTesting Date class by string- \nDate should be 2/29/1904: ";
for(i=0;i<temp_string.length();i++) cout << temp_string[i];
cout << "\n\n";
// end
*/
d1 = new Date(12, 31, 1975);
cout << "Date should be 12/31/1975: " << d1 << endl;
Date* d2 = new Date("1/1/1976");
cout << "Date should be 1/1/1976: " << d2 << endl;
Date* d3 = new Date("1/2/1976");
cout << "Date should be 1/2/1976: " << d3 << endl;
Date* d4 = new Date("2/27/1977");
Date* d5 = new Date("8/31/2110");
// I recommend you write code to test the isLeapYear function!
cout << "\nTesting isLeapYear(int year)- \noutput should be 1-0-1-1: ";
cout<< d1->isLeapYear(1996) << "-" << d1->isLeapYear(1900) << "-" << d1->isLeapYear(2000) << "-" << d1->isLeapYear(1000) << endl;
// output : 1-0-1-1
//cout << d1->toString();
// end
cout << "\nTesting before and after." << endl;
cout << d2 << " after " << d1 << " should be true: " << d2->isAfter(d1) << endl;
cout << d3 << " after " << d2 << " should be true: " << d3->isAfter(d2) << endl;
cout << d1 << " after " << d1 << " should be false: " << d1->isAfter(d1) << endl;
cout << d1 << " after " << d2 << " should be false: " << d1->isAfter(d2) << endl;
cout << d2 << " after " << d3 << " should be false: " << d2->isAfter(d3) << endl;
cout << d1 << " before " << d2 << " should be true: " << d1->isBefore(d2) << endl;
cout << d2 << " before " << d3 << " should be true: " << d2->isBefore(d3) << endl;
cout << d1 << " before " << d1 << " should be false: " << d1->isBefore(d1) << endl;
cout << d2 << " before " << d1 << " should be false: " << d2->isBefore(d1) << endl;
cout << d3 << " before " << d2 << " should be false: " << d3->isBefore(d2) << endl;
cout << "\nTesting difference." << endl;
cout << d1 << " - " << d1 << " should be 0: " << d1->difference(d1) << endl;
cout << d2 << " - " << d1 << " should be 1: " << d2->difference(d1) << endl;
cout << d3 << " - " << d1 << " should be 2: " << d3->difference(d1) << endl;
cout << d3 << " - " << d4 << " should be -422: " << d3->difference(d4) << endl;
cout << d5 << " - " << d4 << " should be 48762: " << d5->difference(d4) << endl;
}