C语言 挂历的实现

要求:

实现一个挂历类似于windows系统如图所示的图片:

1,可以显示当前的日期(调用time.h中的函数获取函数的日期);

2,可以显示用户给定的具体日期的挂历显示;

3,跳转当前显示的下一个月,和上一个月。

预备知识:

  1. //获取系统时间

  2. //struct tm * gmtime(const time_t *timer); //将日历时间转化为世界标准时间(即格林尼治时间)

  3. /*struct tm {int tm_sec; /* 秒 – 取值区间为[0,59] */

    int tm_min; /* 分 - 取值区间为[0,59] */

    int tm_hour; /* 时 - 取值区间为[0,23] */

    int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */

    int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */

    int tm_year; /* 年份,其值等于实际年份减去1900 */

    int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */

    int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */

    int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/};*/

  4. #include<time.h>

  5. int main()

  6. {

  7.     time_t timep;

  8.     struct tm *p;

  9.     time (&timep);

  10.     p=gmtime(&timep);

  11.     printf("%d\n",p->tm_sec); /*获取当前秒*/

  12.     printf("%d\n",p->tm_min); /*获取当前分*/

  13.     printf("%d\n",8+p->tm_hour);/*获取当前时,这里获取西方的时间,刚好相差八个小时*/

  14.     printf("%d\n",p->tm_mday);/*获取当前月份日数,范围是1-31*/

  15.     printf("%d\n",1+p->tm_mon);/*获取当前月份,范围是0-11,所以要加1*/

  16.     printf("%d\n",1900+p->tm_year);/*获取当前年份,从1900开始,所以要加1900*/

  17.     printf("%d\n",p->tm_yday); /*从今年1月1日算起至今的天数,范围为0-365*/

  18. }

 getch 获取一个字符不显示到屏幕上,getche获取一个字符显示到屏幕上。

 用函数fflush(stdin)清除全部剩余内容

 

kbhit()函数在头文件#include<conio.h>中,为非阻塞函数。只有键入值得时候返回为真。

 

主要代码实现:

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#define RED "\033[0;32;31m"
#define NONE "\033[m"


/*判断输入的年份是否为闰年
**参数值:year年份
**返回值:闰年返回1,否则返回0
*/
int IsLeap(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
}
/*获取输入年份月份的天数
**参数值:year,month为年,月
**返回值:返回给定年月的天数。
*/
int GetMaxDay(int year, int month)
{
	int Day[13] = { 29,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (IsLeap(year))
	{
		month = 0;
	}
	return Day[month];
}
/*计算某个日期是当年中第几天
**参数值:year年份,month月份
**返回值:返回某个日期是当年的第几天
*/
int GetTotalDays(int year, int month,int day)
{
	int i = 0;
	int total = day;
	for (i = 1; i < month; i++)
	{
		total += GetMaxDay(year, i);
	}
	return total;
}
/*计算某个日期是星期几
**参数值:年月日
**返回值:日期对应的星期
*/
int GetWeekFromData(int year, int month, int day)
{
	//W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 //C计算公式,基姆拉尔森计算公式
	return (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
}
/*显示输入的日期是星期几
**参数值:年月日
**返回值:无
*/
void DisplayWeekFromData(int year, int month, int day)
{
	int W;
	W = GetWeekFromData(year, month, day);
	switch (W)
	{
	case 0:printf("\t%d-%d-%d is Sunday\n", year, month, day); break;
	case 1:printf("\t%d-%d-%d is Monday\n", year, month, day); break;
	case 2:printf("\t%d-%d-%d is Tuesday\n", year, month, day); break;
	case 3:printf("\t%d-%d-%d is Wednesday\n", year, month, day); break;
	case 4:printf("\t%d-%d-%d is Thursday\n", year, month, day); break;
	case 5:printf("\t%d-%d-%d is Friday\n", year, month, day); break;
	case 6:printf("\t%d-%d-%d is Saturday\n", year, month, day); break;
	}
}
/*
**显示挂历
**参数值:年月日
**返回值:无
*/
void DisplayMonth(int year, int month, int day,int flag)
{
	int i, j, W, max_month_day,last_month_days;
	last_month_days = GetMaxDay(year, month - 1);
	W = GetWeekFromData(year, month, 1);
	max_month_day = GetMaxDay(year, month);
	printf("\n\t\t\t%d年%d月", year, month);
	printf("\n\tSUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n");
	last_month_days = last_month_days - W + 1;
	for (i = 0; i < W; i++)
	{
		printf("\t%d", last_month_days);
		last_month_days++;
	}
	for (j = 1; j <= max_month_day; j++)
	{
		if (j == day && flag == 1)
		{
			printf(RED"\t%d"NONE, j);
		}
		else
		{
			printf("\t%d", j);
		}
		if (i % 7 == 6)
		{
			printf("\n");
		}
		i++;
	}

	int NextMonthDays = 1;
	for (i; i % 7 != 0; i++)
	{
		printf("\t%d", NextMonthDays++);
	}
	printf("\n");
}
/*
**一级显示界面(总功能显示)
*/
void MyMenu()
{
	int flag = 0;
	printf("**************************************\n");
	printf("******  your choice             ******\n");
	printf("******  1,show now data(now)    ******\n");
	printf("******  2,show your date        ******\n");
	printf("******  3,exit                  ******\n");
	printf("**************************************\n");
}
/*

*/
void DealSwitch2()
{
	int year;

	char str_month[3] = { 0 };
	char str_day[3] = { 0 };
	printf("please input the date is needed to search\n");
	printf("please input the year:\n");
	scanf("%d", &year);
	printf("please input the month(* is all):\n");
	scanf("%s", &str_month);
	printf("please input the day(* is all)\n");
	scanf("%s", &str_day);
	//
	
	//显示某年的所有日期
	if (strcmp(str_month, "*") == 0)
	{
		time_t today;
		struct tm *p;
		time(&today);
		p = gmtime(&today);
		int month = p->tm_mon + 1;
		int day = p->tm_mday;

		int i = 1;
		while (i != 13)
		{
			if (i == month)
			{
				DisplayMonth(year, month, day, 1);
				i++;
				continue;
			}
			DisplayMonth(year, i++, 1, 0);
		}
		return;
	}
	//显示某个月的所有信息
	else
	{
		DisplayMonth(year, atoi(str_month), 1,0);
		return;
	}
	
}

void UpdateDate(int *year, int *month, int flag/*1为下一月,2为上一月*/)
{
	if (*month == 1 && flag==2)
	{
		*year = *year - 1;
		*month = 12;
	}
	else if (*month == 12 && flag == 1)
	{
		*year = *year + 1;
		*month = 1;
	}
	else if (flag == 1)
	{
		*month = *month + 1;
	}
	else if (flag == 2)
	{
		*month = *month - 1;
	}
	else
	{
		printf("func UpdateDate() error!!!\n");
	}
}

int isNowMonth(int month, int realmonth)
{
	return realmonth == month ? 1 : 0;
}

void DisNowMonth()
{
	time_t today;
	struct tm *p;
	time(&today);
	p = gmtime(&today);
	int year = p->tm_year + 1900;
	int month = p->tm_mon + 1;
	int realmonth = month;//保存今天的month的值
	int day = p->tm_mday;
	DisplayMonth(year, month, day, 1);
	system("pause");
	char flag = 0;
	do 
	{
		//fflush(stdin);
		system("cls");
		printf("your can input 1 to show next month,2 to show last month ,0 to back main menu\n");
		//getchar();
		//flag = getch();
		getchar();
		scanf("%c", &flag);
		switch (flag)
		{
		case '1':UpdateDate(&year, &month, 1); DisplayMonth(year, month, day, isNowMonth(month, realmonth)); system("pause"); break;
		case '2':UpdateDate(&year, &month, 2); DisplayMonth(year, month, day, isNowMonth(month, realmonth)); system("pause"); break;
		case '0':break;
		default: printf("Your Input Error!!!\n"); break;
		}
	} while (flag!='0');
	
}
void main()
{
	
	int flag = INT_MAX;
	do {
		system("cls");//清除屏幕上所有东西
		MyMenu();
		printf("please input your choice:\n");
		scanf("%d", &flag);
		switch (flag)
		{
		case 1:DisNowMonth(); system("pause"); break;
		case 2:DealSwitch2(); system("pause"); break;
		case 0:break;
		default:printf("your input is error!!!\n");
		}
	} while (flag != 0);
	//DisplayMonth(2019, 3, 1);
	printf("hello...\n");
	system("pause");
	return ;
}

 

使用二维数组打印日历:

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

//是否为闰年
bool IsLeapYear(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
}
//获取某年某月的天数
int GetMonthMaxDay(int year, int month)
{
	static int Day[13] = { 29,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (IsLeapYear(year))
		month = 0;
	return Day[month];
}
//计算某个日期是星期几
int GetWeekFromData(int year, int month, int day)
{
	//W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 //C计算公式,基姆拉尔森计算公式
	return (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
}

void ArrtoZero(int **arr)
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 7; j++)
		{
			arr[i][j] = 0;
		}
	}
}
void DataToArr(int year,int month,int **arr)
{
	ArrtoZero(arr);
	int Begin = GetWeekFromData(year, month, 1);
	int Count = 1;
	for (int i = 0; i < 5; i++)
	{
		for (int j = Begin; j < 7 && i==0; j++)
		{
			arr[i][j] = Count++;
		}
		for (int k = 0; i != 0 && k < 7 && Count <= GetMonthMaxDay(year, month); k++)
		{
			arr[i][k] = Count++;
		}
	}
}

void DisplayData(int **Arr)
{
	printf("\n\tSUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 7; j++)
		{
			if (Arr[i][j] != 0)
				printf("\t%d", Arr[i][j]);
			else
				printf("\t ", Arr[i][j]);
		}
		printf("\n");
	}
}
int UpdateData(int *year, int *month, bool flag/*true上一个月,false下一个月*/)
{
	if (flag)
	{
		*month = *month - 1;
		if (*month == 0)
		{
			*year -= 1;
			*month = 12;
		}
	}
	else
	{
		*month = *month + 1;
		if (*month == 13)
		{
			*year += 1;
			*month = 1;
		}
	}
}

void main()
{
	int year = 2019;
	int month = 4;
	int day = 13;
	char flag;
	int **arr = malloc(sizeof(int *) * 5);
	for (int i = 0; i < 7; i++)
	{
		arr[i] = calloc(1, sizeof(int) * 7);
	}
	printf("\n\t\t\t%d年%d月", year, month);
	DataToArr(year, month, arr);

	DisplayData(arr);
	do 
	{
		printf("\t\t\t\t(U上一月,D下一月)\n");
		printf("ShowData:>");
		scanf("%c", &flag);
		getchar();
		system("cls");
		if (flag == 'U' || flag == 'u')
		{
			UpdateData(&year, &month, true);
			printf("\n\t\t\t%d年%d月", year, month);
			DataToArr(year, month, arr);
			DisplayData(arr);

		}
		else if (flag == 'D' || flag == 'd')
		{
			UpdateData(&year, &month, false);
			printf("\n\t\t\t%d年%d月", year, month);
			DataToArr(year, month, arr);
			DisplayData(arr);
		}
		else
		{
			printf("Unkown character!\n");
		}
	} while (flag != '#');
	printf("hello...\n");
	system("pause");
	return ;
}

演示:

功能:输入U和D翻页。



【这里我们增加了新的需求,当前天高亮,前一月和后一月变成不同的颜色】

【代码】:

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <conio.h>

#define RED "\033[0;32;31m"
#define NONE "\033[m"
#define YELLOW "\033[1;33m"


/*判断输入的年份是否为闰年
**参数值:year年份
**返回值:闰年返回1,否则返回0
*/
int IsLeap(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
}
/*获取输入年份月份的天数
**参数值:year,month为年,月
**返回值:返回给定年月的天数。
*/
int GetMaxDay(int year, int month)
{
	int Day[13] = { 29,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (IsLeap(year))
	{
		month = 0;
	}
	return Day[month];
}
/*计算某个日期是当年中第几天
**参数值:year年份,month月份
**返回值:返回某个日期是当年的第几天
*/
int GetTotalDays(int year, int month, int day)
{
	int i = 0;
	int total = day;
	for (i = 1; i < month; i++)
	{
		total += GetMaxDay(year, i);
	}
	return total;
}
/*计算某个日期是星期几
**参数值:年月日
**返回值:日期对应的星期
*/
int GetWeekFromData(int year, int month, int day)
{
	//W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 //C计算公式,基姆拉尔森计算公式
	if (month == 2 || month == 1)
	{
		year -= 1;
		month += 12;
	}
	return (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
}
/*显示输入的日期是星期几
**参数值:年月日
**返回值:无
*/
void DisplayWeekFromData(int year, int month, int day)
{
	int W;
	W = GetWeekFromData(year, month, day);
	switch (W)
	{
	case 0:printf("\t%d-%d-%d is Sunday\n", year, month, day); break;
	case 1:printf("\t%d-%d-%d is Monday\n", year, month, day); break;
	case 2:printf("\t%d-%d-%d is Tuesday\n", year, month, day); break;
	case 3:printf("\t%d-%d-%d is Wednesday\n", year, month, day); break;
	case 4:printf("\t%d-%d-%d is Thursday\n", year, month, day); break;
	case 5:printf("\t%d-%d-%d is Friday\n", year, month, day); break;
	case 6:printf("\t%d-%d-%d is Saturday\n", year, month, day); break;
	}
}
/*
**显示挂历
**参数值:年月日
**返回值:无
*/
void DisplayMonth(int year, int month, int day, int flag)
{
	int i, j, W, max_month_day, last_month_days;
	last_month_days = GetMaxDay(year, month - 1);//获取某年某月的最大的天数
	W = GetWeekFromData(year, month, 1);//获取某月某天的星期
	max_month_day = GetMaxDay(year, month);
	printf("\n\t\t\t%d年%d月", year, month);
	printf("\n\tSUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n");
	last_month_days = last_month_days - W + 1;
	for (i = 0; i < W; i++)
	{
		printf(YELLOW"\t%d"NONE, last_month_days);
		last_month_days++;
	}
	for (j = 1; j <= max_month_day; j++)
	{
		if (j == day && flag == 1)
		{
			printf(RED"\t%d"NONE, j);
		}
		else
		{
			printf("\t%d", j);
		}
		if (i % 7 == 6)
		{
			printf("\n");
		}
		i++;
	}

	int NextMonthDays = 1;
	for (i; i % 7 != 0; i++)
	{
		printf(YELLOW"\t%d"NONE, NextMonthDays++);
	}
	printf("\n");
}
/*
**一级显示界面(总功能显示)
*/
void MyMenu()
{
	int flag = 0;
	printf("**************************************\n");
	printf("******  your choice             ******\n");
	printf("******  1,show now data(now)    ******\n");
	printf("******  2,show your date        ******\n");
	printf("******  3,exit                  ******\n");
	printf("**************************************\n");
}
/*

*/
void DealSwitch2()
{
	int year;

	char str_month[3] = { 0 };
	char str_day[3] = { 0 };
	printf("please input the date is needed to search\n");
	printf("please input the year:\n");
	scanf("%d", &year);
	if (year <= 0) return;

	printf("please input the month(* is all):\n");
	scanf("%s", &str_month);
	if (strcmp(str_month, "*") != 0 && (atoi(str_month) > 12 || atoi(str_month) <= 0)) return;

	/*printf("please input the day(* is all)\n");
	scanf("%s", &str_day);
	if(atoi(str_day)<=0|| atoi(str_day) > GetMaxDay(year,atoi(str_month))) return;*/
	//

	//显示某年的所有日期
	if (strcmp(str_month, "*") == 0)
	{
		time_t today;
		struct tm *p;
		time(&today);
		p = gmtime(&today);
		int month = p->tm_mon + 1;
		int day = p->tm_mday;

		int i = 1;
		while (i != 13)
		{
			if (i == month)
			{
				DisplayMonth(year, month, day, 1);
				i++;
				continue;
			}
			DisplayMonth(year, i++, 1, 0);
		}
		return;
	}
	//显示某个月的所有信息
	else
	{
		DisplayMonth(year, atoi(str_month), 1, 0);
		return;
	}

}

void UpdateDate(int *year, int *month, int flag/*1为下一月,2为上一月*/)
{
	if (*month == 1 && flag == 2)
	{
		*year = *year - 1;
		*month = 12;
	}
	else if (*month == 12 && flag == 1)
	{
		*year = *year + 1;
		*month = 1;
	}
	else if (flag == 1)
	{
		*month = *month + 1;
	}
	else if (flag == 2)
	{
		*month = *month - 1;
	}
	else
	{
		printf("func UpdateDate() error!!!\n");
	}
}

int isNowMonth(int year, int month, int realyear, int realmonth)
{
	return realmonth == month && year == realyear ? 1 : 0;
}

void DisNowMonth()
{
	time_t today;
	struct tm *p;
	time(&today);
	p = gmtime(&today);
	int year = p->tm_year + 1900;
	int realyear = year;
	int month = p->tm_mon + 1;
	int realmonth = month;//保存今天的month的值
	int day = p->tm_mday;
	DisplayMonth(year, month, day, 1);
	system("pause");
	char flag = 0;
	//吃掉回车符
	getchar();
	do
	{
		system("cls");
		printf("your can input 1 to show next month,2 to show last month ,0 to back main menu\n");

		flag = getch();
		switch (flag)
		{
		case '1':UpdateDate(&year, &month, 1); DisplayMonth(year, month, day, isNowMonth(year, month, realyear, realmonth)); getchar(); flag = getch(); break;
		case '2':UpdateDate(&year, &month, 2); DisplayMonth(year, month, day, isNowMonth(year, month, realyear, realmonth)); getchar(); flag = getch(); break;
		case '0':break;
		default: printf("Your Input Error!!!\n"); getchar(); break;
		}
	} while (flag != '0');

}
void main()
{
	int flag = INT_MAX;
	do {
		system("cls");//清除屏幕上所有东西
		MyMenu();
		printf("please input your choice:\n");
		scanf("%d", &flag);
		switch (flag)
		{
		case 1:DisNowMonth(); system("pause"); break;
		case 2:DealSwitch2(); system("pause"); break;
		case 0:break;
		default:printf("your input is error!!!\n");
		}
	} while (flag != 0);
	//DisplayMonth(2019, 3, 1);
	printf("hello...\n");
	system("pause");
	return;
}

【结果】:

【部分代码注意点】:

1,关于输出颜色请参考:https://blog.csdn.net/qq_42418668/article/details/89343771
2,关于//W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 //C计算公式,基姆拉尔森计算公式

需要我们注意,每年的1月和2月如果按照正常的求解会出错,必须把当前年的1月和2月按照上一年的13,14月求解。

例如,求2019,2,1则必须求2018,14,1日就可以返回正常的结果。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值