万年历(C语言)-程序设计/作业

Mzyh 2024-06-28 10:35:04 阅读 98

··········目录··········

一,预备知识

1.  关于 struct tm 结构体

2.  计算 星期几 的方式

3.  输出不同颜色的字体

二,代码分段解析

1.  头文件和定义的全局变量

2.  头文件head.h

3.  主函数main

三,代码中使用到的函数

1,展示选择菜单

2,判断给定年份是否为闰年

3,计算返回给定月份的天数

4,计算给定日期是星期几

5,显示当前指定日期的月历

6,显示指定年份的全年日历

7,验证给定的日期是否有效

8,查询指定日期的月历并突出显示

9,重置时间为当前系统时间

10,将当前日期调整为新输入的日期,无效则重置时间

四,全部代码


前言: 文章不足之处请麻烦评论指正!

总体设计:

1,显示菜单提示用户进行输入并执行对应函数

2,获取当前日期:获取系统时间作为默认值,显示所在年月的月历并突出当天日期

3,显示全年年历:显示所在年份的全年日历,并突出当天日期

4,查询日期:输入指定日期并突出显示,用户可选择显示全年日历或月历

5,调整日期:用户输入可修改时间的默认值,且检查到无效日期时可以重置为系统时间

一,预备知识

1.  关于 struct tm 结构体

struct tm 是C语言中的一个结构体,定义在头文件 <time.h> 中。它用于存储时间和日期的信息,我们只需要在程序中包含<time.h>头文件,就可以使用此结构体中的信息,能够更方便地操作和处理时间。结构体的定义如下:

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 到 11

int tm_year; // 年份,从 1900 开始

int tm_wday; // 一周中的日,范围从 0 (周日) 到 6 (周六)

int tm_yday; // 一年中的日,范围从 0 到 365

int tm_isdst; // 夏令时标识

};


2.  计算 星期几 的方式

公式:int w = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;        

(其中d表示日,m表示月,y表示年;其中w+1表示星期几)

w 的值将是 0 到 6 之间的一个整数,分别代表一周的不同天,再加 1 准确表示周几。


3.  输出不同颜色的字体

·演示效果:

`其中 \33[0m 为关闭所有属性.

·根据上面的演示,我们可以直接得出结论:在输出时候加上 \033[ 参数 …… \033[0m 即可使得在一句打印语句中输出的字体是有颜色的。(使用ANSI转义码控制文本属性)

---

·格式解析:   \033[ 参数1;参数2  是样式的开始 \33[参数  是样式的结束,如果不结束则代表着后续的输出字符也套用其中的格式。(更多关于c语言字体颜色的内容可自行搜索)


二,代码分段解析

1.  头文件和定义的全局变量

#include"head.h" //包含头文件head.h

time_t t; //定义time_t类型的变量t

struct tm* today; //创建结构体指针变量today

int choice = 0; //用于键盘输入选择菜单选项

int year, month, day; //全局变量用于记录当前的时间信息

int year1, month1, day1; //全局变量用于记录输入要查询的时间

全局变量可以为本文件中其它函数所共用,它的作用域为从定义变量的位置开始到本源文件结束。定义为全局变量可方便函数直接调用,而不需要再进行传参.

2.  头文件head.h

#pragma once

#include<stdio.h>

#include<time.h>

//菜单

void menu();

//判断给定年份是否是闰年

int isLeapYear(int y);

//这个函数用于计算返回该月的天数

int daysInMonth(int y, int m);

//这个函数用于计算给定日期是星期几

int dayOfWeek(int y, int m, int d);

//可突出显示当前指定年月的月历

void displayCalendar(int y, int m, int currentDay);

//这个函数用于显示指定年份 year 的全年日历

void displayYearCalendar(int y);

//这个函数用于验证给定的日期是否有效

int isValidDate(int y, int m, int day);

//查询指定日期的月历并突出显示

void queryDate(int y, int m, int day);

//允许用户通过键盘输入来调整日期

void adjustDate(int y, int m, int d);

//重置时间为当前系统时间

void resetTime();

如果使用的是Microsoft Visual Studio进行编写代码,请在代码开头添加:

#define _CRT_SECURE_NO_WARNINGS

3.  主函数main

int main()

{

int year2, month2, day2;

t = time(NULL);//time(&t),获取当前时间戳(秒数)

//将时间戳(秒数)转换为 struct tm 结构体,对应本地时区

today = localtime(&t);

year = today->tm_year + 1900;//年份从1900开始

month = today->tm_mon + 1; //月份从1开始

day = today->tm_mday; //一个月中的日,0-31

do

{

//获取对应日期为星期几

int week = dayOfWeek(year, month, day);

//打印菜单,并进行输入选择

printf(">>>\033[36;5mNOW: %d-%d-%d · 周%d\033[0m\n", year, month, day, week);

menu();

printf("\033[1m请输入选择的操作: \033[0m");

scanf("%d", &choice);

switch (choice)

{

case 1:

//显示当前的月历,并突出显示今天的日期

displayCalendar(year, month, day);

break;

case 2:

system("cls");//清空已有内容

displayYearCalendar(year);

break;

case 3:

printf("请输入要查询的日期(YYYY MM DD): ");

scanf("%4d %2d %2d", &year1, &month1, &day1);

queryDate(year1, month1, day1);

break;

case 4:

printf("请输入修改后的日期(YYYY MM DD): ");

scanf("%4d %2d %2d", &year2, &month2, &day2);

adjustDate(year2, month2, day2);

break;

case 0:

printf("已退出万年历系统!\n");

break;

default:

printf("输入错误,请重试!\n");

break;

}

} while (choice);

return 0;

}

主要根据用户使用键盘进行输入选择,然后通过switch语句执行对应的函数。


三,代码中使用到的函数

1,展示选择菜单

void menu()

{

printf("\033[36m| 1, 获取当前日期 |\033[0m\n");

printf("\033[36m| 2, 显示全年日历 |\033[0m\n");

printf("\033[36m| 3, 查询日期 |\033[0m\n");

printf("\033[36m| 4, 调整日期 |\033[0m\n");

printf("\033[36m| 0, 退出 |\033[0m\n");

printf("\n");

}


2,判断给定年份是否为闰年

int isLeapYear(int y)

{

    if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)

        return 1;//返回1,代表闰年

    else

        return 0;//返回0,代表平年

}

 计算闰年的方式:   :年份可以被4整除但是不能被100整除;  :年份能被400整除。


3,计算返回给定月份的天数

int daysInMonth(int y, int m)

{

int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

if (m == 2 && isLeapYear(y))

{

days[2] = 29;

}

return days[m];

}

定义一个长度为13的整型数组存放月份的天数(为了提高代码的可读性,在0索引处置0,则后续的每个索引都可以代表其对应月份的天数),判断给定的年份是否为闰年,是闰年则将2月的天数置为29天,最后返回对应月份的天数。


4,计算给定日期是星期几

int dayOfWeek(int y, int m, int d)

{

if (m < 3)

{

m += 12;

y--;

}

int h = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;

//h+1表示某时间是星期几

return h + 1;

}

 在“预备知识”部分已介绍了根据给定的日期计算星期的方法!


5,显示当前指定日期的月历

void displayCalendar(int y, int m, int currentDay)

{

printf("\033[33m================== %4d 年 %2d 月 =================\033[0m\n", y,m);

printf("日\t一\t二\t三\t四\t五\t六\n");

printf("--------------------------------------------------\n");//6*6+2*7

int first_day = dayOfWeek(y, m, 1); //获取每月1号是周几

int ofday = daysInMonth(y, m); //获取一个月有多少天

int count = first_day;

for (int i = 0; i <= ofday; i++)

{

//使日期能对齐对应的星期

if (i == 0)

{

for (int j = 0; j < count % 7; j++)

{

printf("\t");

}

}

else if (i == currentDay)

{

//突出显示日期(当m等于要查询的时间或等于当前的时间)

if (m == month || m == month1)

{

printf("\033[31m%2d\033[0m\t", i);

count++;

}

else

{

printf("%2d\t", i);

count++;

}

}

else

{

printf("%2d\t", i);

count++;

}

//循环打印一周后换行

if (count % 7 == 0)

{

printf("\n");

}

}

printf("\n");

}

参数中的currentDay表示需要进行突出显示的日期。 


月历打印格式的逻辑:

获取到每个月的一号是星期几和每个月共有多少天,一号是周几则在前面打印对应数量的制表符或空格; 

使用一个变量记录一号是周几,每当打印一天的时候这个变量则进行自增++,当到周日(7)时则进行换行后再打印日期,直到一个月中所有天数都打印完成。

在打印所有的天数中可进行判断当前要打印的天数是否等于currentDay,如果等于则进行突出显示,不等于则进行普通打印。


6,显示指定年份的全年日历

void displayYearCalendar(int y)

{

int i = 0;

for (i = 1; i <= 12; i++)

{

displayCalendar(y, i, day);

printf("\n");

}

}

 在循环中调用打印月历的函数即可打印出对应日期的年历


7,验证给定的日期是否有效

int isValidDate(int y, int m, int d)

{

if (y < 1900 || (m < 1 || m >12) || (d < 1 || d > daysInMonth(y, m)))

return 0;//返回0,代表格式错误

else

return 1;//返回1,代表格式正确

}

 


8,查询指定日期的月历并突出显示

void queryDate(int y, int m, int d)

{

int choice = 0;

int flag = isValidDate(y, m, d);

if (flag)

{

printf("请选择: \033[36m| 1.月历 - 2.年历 |\033[0m\n");

scanf("%d", &choice);

if (choice == 1)

{

displayCalendar(y, m, d);

}

else if(choice == 2)

{

//将关于日期的全局变量修改为指定的日期,在突出显示后再修改回系统值.

day = d;

month = m;

displayYearCalendar(y);

day = today->tm_mday;

month = today->tm_mon + 1;

}

else

printf("请重新选择!\n");

}

else

printf("无效的日期!\n");

}

 


9,重置时间为当前系统时间

void resetTime()

{

year = today->tm_year+1900;

month = today->tm_mon+1;

day = today->tm_mday;

printf("\033[31m已重置为系统时间!\033[0m\n");

}

 当输入无效的日期时,将时间信息重置为初始时间(此程序为当前系统时间)。


10,将当前日期调整为新输入的日期,无效则重置时间

void adjustDate(int y, int m, int d)

{

int flag = isValidDate(y, m, d);

if (flag)

{

year = y;

month = m;

day = d;

printf("当前的时间已修改为:%d年%d月%d日\n", y, m, d);

}

else

{

printf("无效的日期!\n");

//输入日期无效则进行重置时间

resetTime();

}

}

修改默认时间展图


四,全部代码

希望文章对你有所帮助。有问题和建议可评论区一起讨论!

以下代码可直接粘贴进编辑器运行。2个文件( .h 和 .c )的代码在 “全部代码” 中已经整合为一个文件。

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<time.h>

#include<windows.h>

//菜单

void menu();

//判断给定年份是否是闰年

int isLeapYear(int y);

//这个函数用于计算返回该月的天数

int daysInMonth(int y, int m);

//这个函数用于计算给定日期是星期几

int dayOfWeek(int y, int m, int d);

//可突出显示当前指定年月的月历

void displayCalendar(int y, int m, int currentDay);

//这个函数用于显示指定年份 year 的全年日历

void displayYearCalendar(int y);

//这个函数用于验证给定的日期是否有效

int isValidDate(int y, int m, int day);

//查询指定日期的月历并突出显示

void queryDate(int y, int m, int day);

//允许用户通过键盘输入来调整日期

void adjustDate(int y, int m, int d);

//重置时间为当前系统时间

void resetTime();

//定义全局变量

time_t t;

struct tm* today;

int choice = 0;

int year, month, day;

int year1, month1, day1;

int main()

{

int year2, month2, day2;

t = time(NULL);//time(&t),获取当前时间戳(秒数)

//将时间戳(秒数)转换为 struct tm 结构体,对应本地时区

today = localtime(&t);

year = today->tm_year + 1900;//年份从1900开始

month = today->tm_mon + 1;//月份从1开始

day = today->tm_mday;

do

{

int week = dayOfWeek(year, month, day);

printf(">>>\033[36;5mNOW: %d-%d-%d · 周%d\033[0m\n", year, month, day, week);

menu();

printf("\033[1m请输入选择的操作: \033[0m");

scanf("%d", &choice);

switch (choice)

{

case 1:

//显示当前的月历,并突出显示今天的日期

displayCalendar(year, month, day);

break;

case 2:

system("cls");//清空已有内容

displayYearCalendar(year);

break;

case 3:

printf("请输入要查询的日期(YYYY MM DD): ");

scanf("%4d %2d %2d", &year1, &month1, &day1);

queryDate(year1, month1, day1);

break;

case 4:

printf("请输入修改后的日期(YYYY MM DD): ");

scanf("%4d %2d %2d", &year2, &month2, &day2);

adjustDate(year2, month2, day2);

break;

case 0:

printf("已退出万年历系统!\n");

break;

default:

printf("输入错误,请重试!\n");

break;

}

} while (choice);

return 0;

}

//菜单

void menu()

{

printf("\033[36m| 1, 获取当前日期 |\033[0m\n");

printf("\033[36m| 2, 显示全年日历 |\033[0m\n");

printf("\033[36m| 3, 查询日期 |\033[0m\n");

printf("\033[36m| 4, 调整日期 |\033[0m\n");

printf("\033[36m| 0, 退出 |\033[0m\n");

printf("\n");

}

//判断给定年份 year 是否是闰年

int isLeapYear(int y)

{

if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)

return 1;//闰年

else

return 0;//平年

}

//用于计算返回该月的天数

int daysInMonth(int y, int m)

{

int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

if (m == 2 && isLeapYear(y))

{

days[2] = 29;

}

return days[m];

}

//计算给定日期的星期几

int dayOfWeek(int y, int m, int d)

{

if (m < 3)

{

m += 12;

y--;

}

int h = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;

/*余数的值将是0(星期日)到6(星期六)之间的一个整数,

分别代表一周的不同天,再加1准确表示周几)*/

//h+1表示某时间是星期几

return h + 1;

}

//显示当前指定年月的月历

void displayCalendar(int y, int m, int currentDay)

{

printf("\033[33m================== %4d 年 %2d 月 =================\033[0m\n", y,m);

printf("日\t一\t二\t三\t四\t五\t六\n");

printf("--------------------------------------------------\n");//6*6+2*7

int first_day = dayOfWeek(y, m, 1);//获取每月1号的周数

int ofday = daysInMonth(y, m);//获取一个月有多少天

int count = first_day;

for (int i = 0; i <= ofday; i++)

{

//使日期能对齐对应的星期

if (i == 0)

{

for (int j = 0; j < count % 7; j++)

{

printf("\t");

}

}

else if (i == currentDay)

{

//突出显示日期

if (m == month || m == month1)

{

printf("\033[31m%2d\033[0m\t", i);

count++;

}

else

{

printf("%2d\t", i);

count++;

}

}

else

{

printf("%2d\t", i);

count++;

}

//循环打印一周后换行

if (count % 7 == 0)

{

printf("\n");

}

}

printf("\n");

}

//这个函数用于显示指定年份的全年日历

void displayYearCalendar(int y)

{

int i = 0;

for (i = 1; i <= 12; i++)

{

displayCalendar(y, i, day);

printf("\n");

}

}

//验证给定的日期是否有效

int isValidDate(int y, int m, int d)

{

if (y < 1900 || (m < 1 || m >12) || (d < 1 || d > daysInMonth(y, m)))

return 0;//格式错误

else

return 1;//格式正确

}

//查询指定日期的月历并突出显示

void queryDate(int y, int m, int d)

{

int choice = 0;

int flag = isValidDate(y, m, d);

if (flag)

{

printf("请选择: \033[36m| 1.月历 - 2.年历 |\033[0m\n");

scanf("%d", &choice);

if (choice == 1)

{

displayCalendar(y, m, d);

}

else if(choice == 2)

{

//将关于日期的全局变量修改为指定的日期,在突出显示后再修改回系统值.

day = d;

month = m;

displayYearCalendar(y);

day = today->tm_mday;

month = today->tm_mon + 1;

}

else

printf("请重新选择!\n");

}

else

printf("无效的日期!\n");

}

//将当前日期调整为新输入的日期,无效则重置时间

void adjustDate(int y, int m, int d)

{

int flag = isValidDate(y, m, d);

if (flag)

{

year = y;

month = m;

day = d;

printf("当前的时间已修改为:%d年%d月%d日\n", y, m, d);

}

else

{

printf("无效的日期!\n");

//输入日期无效则进行重置时间

resetTime();

}

}

//重置时间为当前系统时间

void resetTime()

{

year = today->tm_year+1900;

month = today->tm_mon+1;

day = today->tm_mday;

printf("\033[31m已重置为系统时间!\033[0m\n");

getchar();

Sleep(1300);

system("cls");

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。