您的位置:首页 > 其它

输入日期显示星期几

2013-08-02 16:25 232 查看
输入日期显示星期几

比如今天是2013年8月2日,星期五。我们现在就是要实现这样一个功能,给定一个日期,得到该日期是星期几。

比如:

日期

星期

2013年8月2日

星期五

20130803

星期六

2013-08-04

星期天

2013-6-18

星期二

2014/1/16

星期四

2000/8/15

星期二

我们需要解决的问题有如下几点:

1.对输入格式进行归一化处理;

2.计算将来或以前某一天是星期几;

一、对输入格式的归一化处理

我们首先实现对输入格式的归一化处理,程序如下:

// 输入日期的归一化处理
#include <iostream>
#include <string>
using namespace std;

struct date
{
int year;
int month;
int day;
};

int m_d[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };

int is_leap(int year)
{
// 注意 year % 100 != 0
//      year % 4   == 0
//      year % 400 == 0
// 这三者的顺序
// 总共4中顺序组合,不同的顺序影响不同的计算效率
if (year % 100 != 0 && year % 4 == 0 || year % 400 == 0)
{
return 1;
}
else
{
return 0;
}
}

bool get_date(const string& str, date& dt)
{
dt.year = 0;
dt.month = 0;
dt.day = 0;

int y(0), m(0), d(0);
string sy, sm, sd;
int f = 1;
bool full = false, pass_d = false;
for (string::size_type i = 0; i != str.size(); ++i)
{
// if (isdigit(static_cast<int>(str[i])))
// 该语句导致isctype.c中断言错误:unsigned(c + 1) <= 256
// 故改为:
if (str[i] >= '0' && str[i] <= '9')
{
pass_d = false;
if (f == 1)
{
sy += str[i];
if (sy.size() == 4)
{
++f;
full = true;
}
}
else if (f == 2)
{
sm += str[i];
if (sm.size() == 2)
{
++f;
full = true;
}
}
else if (f == 3)
{
sd += str[i];
if (sd.size() == 2)
{
++f;
full = true;
}
}
else if (f > 3)
{
return false;
}
}
else
{
if (pass_d == false)
{
pass_d = true;
if (full == true)
{
full = false;
}
else
{
++f;
/*if (f > 4)
{
return false;
}*/
}
}
else
{
continue;
}
}
}

y = atoi(sy.c_str());
m = atoi(sm.c_str());
d = atoi(sd.c_str());

if (m < 1 || m > 12)
{
return false;
}
else
{
if (d < 1 || d > m_d[is_leap(y)][m])
{
return false;
}
}
dt.year = y;
dt.month = m;
dt.day = d;
return true;
}

string uni_date(const date& dt)
{
string ret;
char tmp[1000];

itoa(dt.year, tmp, 10);
ret += tmp;

ret += '-';
if (dt.month < 10)
{
ret += '0';
}
itoa(dt.month, tmp, 10);
ret += tmp;

ret += '-';
if (dt.day < 10)
{
ret += '0';
}
itoa(dt.day, tmp, 10);
ret += tmp;

return ret;
}

int main()
{
string str;
while (1)
{
cout << "输入:";
cin >> str;
date dt;
cout << "输出:";
if (get_date(str, dt))
{
cout << uni_date(dt) << endl;
}
else
{
cout << "输入日期非法!" << endl;
}
cout << endl;
}
}




二、计算将来或以前某一天是星期几

这里我们需要有个参照点,就以今天为参照点:20130802——星期五,我们首先计算将来某一天或以前某一天相对于今天相差几天,然后根据相差天数推算出具体是星期几。

具体程序如下:

// 计算将来或以前某一天是星期几
#include <iostream>
#include <string>
using namespace std;

struct date
{
int year;
int month;
int day;

int weekday;

static int m_d[2][13];

static int y_d[2];

static string d_w[8];
};

int date::m_d[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };

int date::y_d[2] = {365, 366};

string date::d_w[8] = {"", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"};

int is_leap(int year)
{
// 注意 year % 100 != 0
//      year % 4   == 0
//      year % 400 == 0
// 这三者的顺序
// 总共4中顺序组合,不同的顺序影响不同的计算效率
if (year % 100 != 0 && year % 4 == 0 || year % 400 == 0)
{
return 1;
}
else
{
return 0;
}
}

bool get_date(const string& str, date& dt)
{
dt.year = 0;
dt.month = 0;
dt.day = 0;

int y(0), m(0), d(0);
string sy, sm, sd;
int f = 1;
bool full = false, pass_d = false;
for (string::size_type i = 0; i != str.size(); ++i)
{
// if (isdigit(static_cast<int>(str[i])))
// 该语句导致isctype.c中断言错误:unsigned(c + 1) <= 256
// 故改为:
if (str[i] >= '0' && str[i] <= '9')
{
pass_d = false;
if (f == 1)
{
sy += str[i];
if (sy.size() == 4)
{
++f;
full = true;
}
}
else if (f == 2)
{
sm += str[i];
if (sm.size() == 2)
{
++f;
full = true;
}
}
else if (f == 3)
{
sd += str[i];
if (sd.size() == 2)
{
++f;
full = true;
}
}
else if (f > 3)
{
return false;
}
}
else
{
if (pass_d == false)
{
pass_d = true;
if (full == true)
{
full = false;
}
else
{
++f;
/*if (f > 4)
{
return false;
}*/
}
}
else
{
continue;
}
}
}

y = atoi(sy.c_str());
m = atoi(sm.c_str());
d = atoi(sd.c_str());

if (m < 1 || m > 12)
{
return false;
}
else
{
if (d < 1 || d > date::m_d[is_leap(y)][m])
{
return false;
}
}
dt.year = y;
dt.month = m;
dt.day = d;
return true;
}

string uni_date(const date& dt)
{
string ret;
char tmp[1000];

itoa(dt.year, tmp, 10);
ret += tmp;

ret += '-';
if (dt.month < 10)
{
ret += '0';
}
itoa(dt.month, tmp, 10);
ret += tmp;

ret += '-';
if (dt.day < 10)
{
ret += '0';
}
itoa(dt.day, tmp, 10);
ret += tmp;

return ret;
}

string cal_weekday(date& dt)
{
string dt_str = uni_date(dt);
string ref_str = "20130802";
date ref_dt;
ref_dt.year = 2013;
ref_dt.month = 8;
ref_dt.day = 2;
ref_dt.weekday = 5;

bool fut;
date bigger, smaller;
if (dt_str >= ref_str)
{
fut = true;
bigger = dt;
smaller = ref_dt;
}
else
{
fut = false;
bigger = ref_dt;
smaller = dt;
}
int smaller_days = 0, bigger_days = 0;
for (int m = 1; m < smaller.month; ++m)
{
smaller_days += date::m_d[is_leap(smaller.year)][m];
}
smaller_days += smaller.day;

for (int y = smaller.year; y < bigger.year; ++y)
{
bigger_days += date::y_d[is_leap(y)];
}
for (int m = 1; m < bigger.month; ++m)
{
bigger_days += date::m_d[is_leap(bigger.year)][m];
}
bigger_days += bigger.day;

int diff = bigger_days - smaller_days;
if (fut)
{
dt.weekday = (ref_dt.weekday + diff) % 7;
}
else
{
dt.weekday = ((ref_dt.weekday + 7) - (diff % 7)) % 7;
}
// 当为星期天时,dt.weekday为0,所以根据date::d_w[]需要做一下特殊处理
if (dt.weekday == 0)
{
dt.weekday = 7;
}
return date::d_w[dt.weekday];
}

int main()
{
string str;
while (1)
{
cout << "输入:";
cin >> str;
date dt;
cout << "输出:";
if (get_date(str, dt))
{
cout << uni_date(dt) << endl;
}
else
{
cout << "输入日期非法!" << endl << endl;
continue;
}
cout << cal_weekday(dt) << endl;
cout << endl;
}
}




三、总结

本文的初衷是想根据给定的日期得到其对应的星期。首先,我们对于输入的日期做了一个归一化处理,一是为了方便用户输入方便,二是为了我们后续处理的便捷。然后,我们对归一化处理后的日期进行计算,根据一个参照点(20130802——星期五)得到早于或晚于该天的星期。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: