要求:
实现一个挂历类似于windows系统如图所示的图片:
1,可以显示当前的日期(调用time.h中的函数获取函数的日期);
2,可以显示用户给定的具体日期的挂历显示;
3,跳转当前显示的下一个月,和上一个月。
预备知识:
//获取系统时间
//struct tm * gmtime(const time_t *timer); //将日历时间转化为世界标准时间(即格林尼治时间)
/*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()为负。*/};*/
#include<time.h>
int main()
{
time_t timep;
struct tm *p;
time (&timep);
p=gmtime(&timep);
printf("%d\n",p->tm_sec); /*获取当前秒*/
printf("%d\n",p->tm_min); /*获取当前分*/
printf("%d\n",8+p->tm_hour);/*获取当前时,这里获取西方的时间,刚好相差八个小时*/
printf("%d\n",p->tm_mday);/*获取当前月份日数,范围是1-31*/
printf("%d\n",1+p->tm_mon);/*获取当前月份,范围是0-11,所以要加1*/
printf("%d\n",1900+p->tm_year);/*获取当前年份,从1900开始,所以要加1900*/
printf("%d\n",p->tm_yday); /*从今年1月1日算起至今的天数,范围为0-365*/
}
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日就可以返回正常的结果。