【C语言项目案例分析】第1章 万年历

【C语言项目案例分析】第1章 万年历


适合新手入门的一本书,还是好多年前买的了,当年买它的时候完全不会编程,看不懂,现在稍微会了点,试着用C++写写练练手。不过说是C++其实还是面向过程的编程了hhh。

万年历

万年历概述

万年历
功能:
若输入是年月日,则输出星期
若输入是年月,则输出当月日历

C++实现

//_____________________________________________________________________
//_____________________________________________________________________
//万年历
//功能:查阅日期
// 若输入是年月日,则输出星期
// 若输入是年月,则输出当月日历
//输入:日期
//输出:星期、日历
#include<vector>
#include<iostream>
#include<string>
#include<regex>
#include<iomanip>
//#include<istream>

using namespace std;

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

const string WEEKEND[] = { "SATURDAY" ,"SUNDAY","MONDAY","TUESDAY" ,"WEDNESDAY" ,"THURSDAY" ,"FIRDAY" };//2020.1.1是星期六
vector<string> SplitString(char* str);//分割字符串
bool IsLeapyear(const structDate&);//是否是闰年
int CountLeapYear(int year);//返回相隔闰年数量,与2020年比,不含当年
int CalDWeek(const structDate& date);//计算星期差
int GetMonDay(const structDate& date);
bool Check(const structDate& date);//检查输入合法

void main(int x, char** date)
{
	if (x == 1)
	{
		cout << "\n ERROR! you forgot to enter the date you want to view" << endl;
		getchar();
		return;
	}

	//获取输入日期             
	vector<structDate> datelst,monlst;
	vector<string> elem;
	for (int i = 1; i < x; i++)
	{
		elem = SplitString(date[i]);
		if (elem.size() == 3)
		{
			structDate tempDate{ stoi(elem[0]), stoi(elem[1]), stoi(elem[2]) };
			if (!Check(tempDate))	cout << date[i] << " is invalid" << endl;
			else datelst.push_back(tempDate);
		}
		else if (elem.size() == 2)
		{
			structDate tempDate{ stoi(elem[0]), stoi(elem[1]), 1 };
			if (!Check(tempDate))	cout << tempDate.year << tempDate.month << tempDate.day << " is invalid" << endl;
			else monlst.push_back(tempDate);
		}
	}
	cout << endl;
	cout << "******************************************************************" << endl;
	for (auto var : datelst)
	{
		//计算天数
		int d = CalDWeek(var);
		if (d >= 0)
		{
			//计算星期
			int week = d % 7;
			cout << var.year << "." << var.month << "." << var.day << " is " << WEEKEND[week] << endl;
		}
		else
		{
			//计算星期
			int week = 7 + d % 7;
			cout << var.year << "." << var.month << "." << var.day << " is " << WEEKEND[week] << endl;
		}
	}
	cout << endl;
	cout <<"******************************************************************"<< endl;
	cout << endl;
	for (auto var : monlst)
	{
		//计算天数
		int d = CalDWeek(var);
		//计算星期
		int week = 0;
		if (d >= 0)
			week = (d % 7 + 6)%7;
		else
			week = ((7 + d % 7) % 7 + 6)%7;

		int monDay = GetMonDay(var);
		//输出日历
		cout << "Calendar of " << var.year << "." << var.month << " is: " << endl;
		cout << "SUN  MON  TUE  WEN  THU  FIR  SAT" << endl;
		for (int i = 1; i <= week+ monDay; i++)
		{
			if (i % 7 != 0)
				if (i <= week)
					cout << setw(5) <<left << " ";
				else
					cout << setw(5) << left << i - week;
			else
				if (i <= week)
					cout << setw(5) << left << " " << endl;
				else
					cout << setw(5) << left << i - week<< endl;
		}
		cout << endl;
		cout << "******************************************************************" << endl;
		cout << endl;
	}

	getchar();
	return;
}

//分割字符串
vector<string> SplitString(char* date)
{
	string dateStr = date;

	//regex reg("(\\.|\\\\)");//正则匹配,\或者.分割年月日
	regex reg("\\D");//正则匹配
	auto test = sregex_token_iterator(dateStr.begin(), dateStr.end(), reg,-1);
	decltype(test) end;
	vector<string> elems(test, end);

	return elems;
}

//是否是闰年
bool IsLeapyear(const structDate& date)
{
	int tempYear = date.year;
	if ((tempYear % 4 == 0 && tempYear % 100 != 0) || (tempYear % 4 == 0 && tempYear % 400 == 0))
		return true;
	return false;
}

//返回相隔闰年数量,与2020年比
int CountLeapYear(int year)
{
	int d;
	if (year == 2000)
		return d = 0;

	if (year > 2000)
	{
		d = (year - 2000 - 1) / 4 - (year - 1 - 2000) / 100 + (year - 1 - 2000) / 400;
	}
	else
	{
		d = (2000 - year - 1) / 4 - (2000 - year - 1) / 100 + (2000 - year - 1) / 400;
	}
	return d;
}

//计算天数差
int CalDWeek(const structDate& date)
{
	//年引起的天数
	int dy = 0, dm = 0, m2 = 0;
	dy = fabs(date.year - 2000) + CountLeapYear(date.year);//一年多一天,闰年再多一天

	//月引起的天数
	m2 = IsLeapyear(date) ? 1 : 0;
	int monDay = 0;
	switch (date.month)
	{
	case 1:
		dm = 0;
		break;
	case 2:
		dm = 31;
		break;
	case 3:
		dm = 31 + 28 + m2;
		break;
	case 4:
		dm = (31 + 28 +31) + m2;
		break;
	case 5:
		dm = (31 + 28 + 31 + 30)+ m2;
		break;
	case 6:
		dm = (31 + 28 + 31 + 30 + 31) + m2;
		break;
	case 7:
		dm = (31 + 28 + 31 + 30 + 31 + 30)+ m2;
		break;
	case 8:
		dm = (31 + 28 + 31 + 30 + 31 + 30 + 31)+ m2;
		break;
	case 9:
		dm = (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31)+ m2;
		break;
	case 10:
		dm = (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) + m2;
		break;
	case 11:
		dm = (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) + m2;
		break;
	case 12:
		dm = (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) % + m2;
		break;
	default:
		break;
	}
	
	//天数
	if (date.year < 2000)
	{
		int m = GetMonDay(date);
		return  -(365 + m2 - dm - date.day) %7 - dy;
	}
	else
		return dy + dm % 7 + date.day % 7;
}

int GetMonDay(const structDate& date)
{
	int month = date.month;
	if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
		return 31;
	if (month == 2 || month == 4 || month == 6 || month == 9 || month == 11)
		return 30;
	return IsLeapyear(date) ? 29: 28;
}

bool Check(const structDate& date)
{
	if (date.year<1900 || date.month < 1 || date.month>12 || date.day < 1 || date.day>31)
		return false;
	return true;
}

原书TC2.0实现

#include <stdio.h>
main(int a,char **date)
{
	int year=0,month=0,day=0,week;
    int d,i,dm,dy,m2;
    char WEEK[9];
    if (a==1)
    {
     printf ("\n ERROR! you forgot to enter the date you want to view\n");
     exit (0);
    }
   i=0; d=-1;
   while (date[1][i])/*遍历传入的参数日期,计算出year,month,day*/
    {
     if ((date[1][i]=='/'||date[1][i]=='.')&&d==-1) { d=0; i++; continue; }
     if ((date[1][i]=='/'||date[1][i]=='.')&&d==0) { d=1; i++; continue; }
     if (d==-1) year=year*10+(date[1][i]-'0');
     if (d==0) month=month*10+(date[1][i]-'0');
     if (d==1) day=day*10+(date[1][i]-'0');
     i++;
    }
   if (month<1||month>12)/*若月份传入错误数字*/
   {
	   printf ("\n ERROR! the entered MONTH is invalid\n"); 
	   exit (0); 
   }
   if (year==2000)
   {
	   dy=0;				/*年引起的星期差为0个*/
	   m2=1;				/*2月引起的星期差为1个*/
	   goto la_100;
   }
   if (year>2000)
	   d=(year-1-2000)/4-(year-1-2000)/100+(year-1-2000)/400+1;
   else 
	   d=(year-2000)/4-(year-2000)/100+(year-2000)/400;
   dy=(year-2000)+d;     /*** 该年 1月1号 到2000年1月1号的 " 星期差 " ***/
   if((year%4==0&&year%100!=0)||(year%100==0&&year%400==0))
    m2=1; 
   else 
	   m2=0;  /*** 该年是否润 ***/
la_100:                    /**** la_100 ****/
          /*** 该月以前的月所引起的 " 星期差 " ***/
   switch (month)
    {
     case 1: dm=0; month=31; break;   /*** month 在此存放该月天数 ***/
     case 2: dm=3; month=d==1? 29:28; break;
     case 3: dm=3+m2; month=31; break;
     case 4: dm=6+m2; month=30; break;
     case 5: dm=1+m2; month=31; break;
     case 6: dm=4+m2; month=30; break;
     case 7: dm=6+m2; month=31; break;
     case 8: dm=2+m2; month=31; break;
     case 9: dm=5+m2; month=30; break;
     case 10: dm=m2; month=31; break;
     case 11: dm=3+m2; month=30; break;
     case 12: dm=5+m2; month=31; break;
    }
   if (day<0||day>month)
    { 
	   printf ("\n ERROR! the entered DAY is invalid\n"); 
	   exit (0);
   }
   week=(dy+dm+day-1+6)%7;
   if(week<0)
	   week+=7;
   if (day>0)       /*** 判定查看类型 ***/
   {
     switch (week)
      {
       case 0: strcpy (WEEK,"SUNDAY"); break;
       case 1: strcpy (WEEK,"MONDAY"); break;
       case 2: strcpy (WEEK,"TUESDAY"); break;
       case 3: strcpy (WEEK,"WEDNESDAY"); break;
       case 4: strcpy (WEEK,"THURSDAY"); break;
       case 5: strcpy (WEEK,"FRIDAY"); break;
       case 6: strcpy (WEEK,"SATURDAY"); break;
      }
     printf ("\n this day is %s  \( %d \)\n\n OK!\n",WEEK,week);
  }
   else
   {
     week=++week%7;
     printf ("\n the calender of this month as following\n");
     printf ("\n *********************************\n");
     printf (" SUN  MON  TUE  WEN  THU  FRI  STA\n");
     for (i=0;i<week;i++) 
		 printf ("     ");
     for (i=1;i<=month;i++)
     {
		 printf (" %2d  ",i);
		 week++;
		 if (week%7==0&&i!=month) 
			 printf ("\n");
	 }
     printf ("\n *********************************\n");
     printf ("\n OK!\n");
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值