为了账号安全,请及时绑定邮箱和手机立即绑定

C++ win32控制台显示月历

标签:
C++

事情的起因是前端同事一时性起想自己写一个日历控件

然后研究了一下逻辑思路


我们参考一下win10系统的显示格式

https://img1.sycdn.imooc.com//5b4f0ba20001e72a02680368.jpg



从日期数据来说,这是一个6X7的矩阵

除了当月的天数以外,头尾还要补齐上月末与下月初的日期。



首先,需要确定本月显示的天数,那么第一件事,得判断当前月共有多少天,包括闰年的处理



int getdays(int year,int month){	switch(month){	case 12:  return 31;case 11:  return 30;case 10:  return 31;case  9:  return 30;case  8:  return 31;case  7:  return 31;case  6:  return 30;case  5:  return 31;case  4:  return 30;case  3:  return 31;case  2: if((year%400==0)||(year%4==0)&&(year%100!=0))return 29;else   return 28;case  1:  return 31;case  0:  return 31;}		}




注意,这里加了一个case 0,因为下文中会引用到求上月份天数,如果是1月份的上个月,即传入0,那么实际返回的应是去年的12月所以是31天。


确定好本月以后,我们推一下上个月需要的天数,首先就要确定本月的一号在矩阵的位置,也就是周几。拿上图为例,其排列是周一至周日。

那么如果是周日(7),则需要补上6天,即,需要补的天数为当前月1号的星期-1

那么求当前月1号的星期也可以通过本日的日期信息获取(week-(day-1)%7)这个应该不难理解,即计算日期的差值,如果求出的值小于1那么就再加上7


这样我们就能求出开始需要补充的天数了。


后面追加的天数更为简单,直接初始成1号往后加就好了


大体思路确定了以后,我们开始过一遍这个6*7矩阵


首先是头部分,我用一个自减变量来标记他,这样做的好处是,我可以直接用上个月的天数减去这个变量求得应该显示的日期,比如说我本月的1号是在周日

那么就需要补充上月的6天,我第一个显示的就是31(上个月天数)-(6-1)即26号,最后显示31-0=31号


if(needday-->0)
{
time_table[i][j]=Pdays-needday;
printf("%02d%c",time_table[i][j],j==6?'\n':' ');
}



然后是本月的正常日期,也可以加上后面追加的一起算,只要把超过当前天数时,天数清空就好了。即:

time_table[i][j]=day_count++;  
if(day_count>days)
   {
   day_count=1;   
        }
   printf("%02d%c",time_table[i][j],j==6?'\n':' ');



下面贴出完整代码:


#include<stdio.h>#include<time.h>#include<stdlib.h>#include<windows.h>#include<string.h>using namespace std;int i,j;int time_table[6][7];int getdays(int year,int month){			switch(month){	case 12:  return 31;case 11:  return 30;case 10:  return 31;case  9:  return 30;case  8:  return 31;case  7:  return 31;case  6:  return 30;case  5:  return 31;case  4:  return 30;case  3:  return 31;case  2: if((year%400==0)||(year%4==0)&&(year%100!=0))return 29;else   return 28;case  1:  return 31;case  0:  return 31;}		}int main(){SYSTEMTIME sys;GetLocalTime( &sys );	HANDLE consolehwnd;consolehwnd=GetStdHandle(STD_OUTPUT_HANDLE);	/*	printf("%d\n",sys.wYear);	printf("%d\n",sys.wMonth);	printf("%d\n",sys.wDay);	printf("%d\n",sys.wDayOfWeek);		printf("%d\n",sys.wHour);	printf("%d\n",sys.wMinute);	printf("%d\n",sys.wSecond);    printf("%d\n",sys.wMilliseconds);    */int days=getdays(sys.wYear,sys.wMonth);int Pdays=getdays(sys.wYear,sys.wMonth-1);// printf("%d\n",days);int day_count=1;int FirstDayWeekAsMonth=sys.wDayOfWeek-(sys.wDay-1)%7;if(FirstDayWeekAsMonth<1)	FirstDayWeekAsMonth+=7;// printf("%d\n",	FirstDayWeekAsMonth);int needday=FirstDayWeekAsMonth-1;printf("%s\n",	"一 二 三 四 五 六 日");SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY|FOREGROUND_GREEN);for(i=0;i<6;i++)	for(j=0;j<7;j++)	{		if(needday-->0)		{			time_table[i][j]=Pdays-needday;			SetConsoleTextAttribute(consolehwnd,FOREGROUND_RED);			printf("%02d%c",time_table[i][j],j==6?'\n':' ');SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY|FOREGROUND_GREEN);		}		else		{		time_table[i][j]=day_count++;		printf("%02d%c",time_table[i][j],j==6?'\n':' ');		 		if(day_count>days)		{			day_count=1;	    SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY|FOREGROUND_BLUE);	    	}		}	}SetConsoleTextAttribute(consolehwnd, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//	for(i=0;i<6;i++)//	for(j=0;j<7;j++)//	printf("%02d%c",time_table[i][j],j==6?'\n':' ');		return 0;}




运行截图



注:GetLocalTime实现获取当前日期信息,SetConsoleTextAttribute实现改变控制台输出颜色,为了区别月份

https://img1.sycdn.imooc.com//5b4f0bae0001cdbf04990324.jpg


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消