练习9.51是一个很好的对类的封装练手的题目,我们观察都是按照月、日、年的形式输入字符串,并且它们之间有逗号、点号或者空格隔开,于是我们可以根据这个特征设计类。设计的过程中要明确哪些是公有的(可以外部访问的)、哪些是私有的。对月份的处理比较麻烦,可以以字母输入,也可以以数字输入,所以封装成了一个函数。另外输出查看也封装成了一个函数。
C++代码:
#include <iostream>
#include <string>
#include <vector>
#include <array>
using namespace std;
class Date
{
public:
Date(const string &s = "");
void Print();
private:
unsigned year = 1970;
unsigned month = 1;
unsigned day = 1;
array<string, 12> month_enum = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
unsigned monthParse(const string &s);
};
Date::Date(const string &s)
{
if (s.empty())
return;
string sep = " ./";
if (s.find_first_of(sep) == string::npos)
throw std::invalid_argument("This format is not supported now.");
else
{
auto pos1 = s.find_first_of(sep);
month = monthParse(s.substr(0, pos1 - 1));
auto pos2 = s.find_first_of(sep, pos1 + 1);
int day_len = pos2 - pos1 - 1;
day = stoi(s.substr(pos1 + 1, day_len));
year = stoi(s.substr(pos2 + 1));
}
}
unsigned Date::monthParse(const string &s)
{
if (s.empty())
return month;
if (s.find_first_of("123456789") != string::npos)
return stoi(s);
for (int i = 0; i < 12; ++i)
{
if (s.find(month_enum[i]) != string::npos)
return i + 1;
}
return month;
}
void Date::Print()
{
cout << year << "-" << month << "-" << day << endl;
}
int main()
{
{ // default case
auto date = Date();
date.Print();
}
{ // January 1, 1900
auto date = Date("January 1, 1900");
date.Print();
}
{ // 1/1/1900
auto date = Date("1/1/1900");
date.Print();
}
{ // Jan 1, 1900
auto date = Date("Jan 1, 1900");
date.Print();
}
}
输出:
参考:
- 《C++ Primer》