349 lines
7.9 KiB
C++
349 lines
7.9 KiB
C++
#include "stdio.h"
|
||
#include "stdlib.h"
|
||
|
||
//判断闰年
|
||
int isLeapYear(int year)
|
||
{
|
||
if(year%400==0||(year%100!=0&&year%4==0))
|
||
{
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 计算某年某月的天数
|
||
int daysInMonth(int year, int month)
|
||
{
|
||
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||
if (month == 2 && isLeapYear(year))
|
||
{
|
||
return 29;
|
||
}
|
||
return days[month - 1];
|
||
}
|
||
|
||
// 计算公元1年1月1日到给定日期的总天数
|
||
int totalDays(int year, int month, int day)
|
||
{
|
||
int total = 0;
|
||
for (int i = 1; i < year; i++)
|
||
{
|
||
if ((i % 4 == 0 && i % 100!= 0) || i % 400 == 0)
|
||
{
|
||
total += 366;
|
||
} else {
|
||
|
||
total += 365;
|
||
}
|
||
}
|
||
for (int i = 1; i < month; i++)
|
||
{
|
||
if (year == 1582 && i == 10)
|
||
{
|
||
// 如果是1582年且计算到10月,减去10天
|
||
if (day >= 15)
|
||
{
|
||
day -= 10;
|
||
}
|
||
}
|
||
total += daysInMonth(year, i);
|
||
}
|
||
total += day;
|
||
|
||
return total;
|
||
}
|
||
|
||
// 判断输入是否为合法的数字
|
||
int isNumber(char *input)
|
||
{
|
||
for (int i = 0; input[i]!= '\0'; i++)
|
||
{
|
||
if (input[i] < '0' || input[i] > '9')
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
// 判断日期是否合法
|
||
int isValidDate(int year, int month, int day)
|
||
{
|
||
if (year <= 0)
|
||
{
|
||
return 0;
|
||
}
|
||
if (month < 1 || month > 12)
|
||
{
|
||
return 0;
|
||
}
|
||
if (day < 1 || day > daysInMonth(year, month))
|
||
{
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
//1852
|
||
int a(int year,int month,int day)
|
||
{
|
||
if(year==1582)
|
||
{
|
||
return 0;
|
||
}
|
||
if(month==10)
|
||
{
|
||
return 0;
|
||
}
|
||
if(day>4&&day<15)
|
||
{
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
// 输出一个月的日历
|
||
void printMonth(int year, int month)
|
||
{
|
||
printf(" %d年%d月\n", year, month);
|
||
printf("日 一 二 三 四 五 六\n");
|
||
int startDay = (totalDays(year, month, 1) % 7);
|
||
for (int i = 0; i < startDay; i++)
|
||
{
|
||
printf(" ");
|
||
}
|
||
int days = daysInMonth(year, month);
|
||
for (int i = 1; i <= days; i++)
|
||
{
|
||
printf("%2d ", i);
|
||
if ((totalDays(year, month, i) % 7) == 6)
|
||
{
|
||
printf("\n");
|
||
}
|
||
}
|
||
if ((totalDays(year, month, days) % 7)!= 6)
|
||
{
|
||
printf("\n");
|
||
}
|
||
}
|
||
|
||
// 获取指定日期是周几
|
||
int isWeek(int totalDay) {
|
||
return (totalDay % 7);
|
||
}
|
||
|
||
// 计算某月某天的日期
|
||
int Count_Day(int day[]) {
|
||
return (day[0] * 1000 + day[1] * 100 + day[2] * 10 + day[3]);
|
||
}
|
||
|
||
// 双列输出日历的核心函数
|
||
void printDoubleColumnCalendar(int year) {
|
||
// 对2个月分为6个块进行打印
|
||
for (int block = 0; block < 6; ++block) {
|
||
// 打印表头
|
||
printf("%2d月 %2d月 \n", block + 1, block + 7);
|
||
printf("日 一 二 三 四 五 六 日 一 二 三 四 五 六\n");
|
||
|
||
|
||
int lineEnd_l = 1, lineEnd_r = 1;
|
||
int day_l[] = {year, block + 1, 1};
|
||
int day_r[] = {year, block + 7, 1};
|
||
int totalDay_l = Count_Day(day_l);
|
||
int totalDay_r = Count_Day(day_r);
|
||
|
||
// 每个月有5行需要输出
|
||
for (int line = 0; line < 5; ++line) {
|
||
// flag作标记位,每行有16个输出数字的位置,第9位和16位始终置0,其余位置不为0则输出数字
|
||
int flag[16] = {0};
|
||
// 标记第一行和其它行,用lineEnd_L和R作为整体的日期统计
|
||
if (line == 0) {
|
||
int monthFirstday_l = isWeek(totalDay_l) + 1;
|
||
int monthFirstday_r = isWeek(totalDay_r) + 1;
|
||
for (int stringStation = monthFirstday_l; stringStation < 8; ++stringStation) {
|
||
flag[stringStation] = lineEnd_l++;
|
||
}
|
||
for (int stringStation = monthFirstday_l + 8; stringStation < 16; ++stringStation) {
|
||
flag[stringStation] = lineEnd_r++;
|
||
}
|
||
} else {
|
||
for (int stringStation = 1; stringStation < 8; ++stringStation) {
|
||
flag[stringStation] = lineEnd_l++;
|
||
if (lineEnd_l > (daysInMonth(year, block + 1))) {
|
||
break;
|
||
}
|
||
}
|
||
for (int stringStation = 9; stringStation < 16; ++stringStation) {
|
||
flag[stringStation] = lineEnd_r++;
|
||
if (lineEnd_r > (daysInMonth(year, block + 7) + 1)) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 输出每行的日期
|
||
for (int i = 1; i < 16; ++i) {
|
||
if (i == 9) {
|
||
printf(" ");
|
||
}
|
||
if (flag[i] == 0) {
|
||
printf(" ");
|
||
} else {
|
||
if (flag[i] < 10) {
|
||
printf(" %d", flag[i]);
|
||
} else {
|
||
printf(" %d", flag[i]);
|
||
}
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
}
|
||
}
|
||
// 菜单选项1:判断闰年和星期几
|
||
void option1(void)
|
||
{
|
||
char yearStr[10], monthStr[10], dayStr[10];
|
||
int year, month, day;
|
||
|
||
// 输入年份并验证
|
||
printf("请输入年份:");
|
||
scanf("%s", yearStr);
|
||
if (!isNumber(yearStr))
|
||
{
|
||
printf("输入错误,请输入数字!\n");
|
||
return;
|
||
}
|
||
year = atoi(yearStr);
|
||
|
||
// 输入月份并验证
|
||
printf("请输入月份:");
|
||
scanf("%s", monthStr);
|
||
if (!isNumber(monthStr))
|
||
{
|
||
printf("请输入数字!\n");
|
||
return;
|
||
}
|
||
month = atoi(monthStr);
|
||
|
||
// 输入日期并验证
|
||
printf("请输入日期:");
|
||
scanf("%s", dayStr);
|
||
if (!isNumber(dayStr))
|
||
{
|
||
printf("输入错误,请输入数字!\n");
|
||
return;
|
||
}
|
||
day = atoi(dayStr);
|
||
|
||
// 验证日期整体合法性
|
||
if (!isValidDate(year, month, day))
|
||
{
|
||
printf("日期不合法!\n");
|
||
return;
|
||
}
|
||
|
||
if(!a(year,month,day))
|
||
{
|
||
printf("不存在此日期。\n");
|
||
return;
|
||
}
|
||
|
||
// 判断闰年并输出
|
||
if (isLeapYear(year))
|
||
{
|
||
printf("%d年是闰年。\n", year);
|
||
}
|
||
else
|
||
{
|
||
printf("%d年不是闰年。\n", year);
|
||
}
|
||
|
||
// 计算并输出星期几
|
||
int total = totalDays(year, month, day);
|
||
char *weekdays[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
|
||
printf("%d年%d月%d日是%s\n", year, month, day, weekdays[total % 7]);
|
||
}
|
||
|
||
// 菜单选项2:输出一年的日历(实现较好的双列输出)
|
||
void option2(void)
|
||
{
|
||
char choiceStr[10];
|
||
int choice;
|
||
|
||
// 选择输出方式并验证
|
||
printf("请选择输出方式(1: 单列输出,2: 双列输出): ");
|
||
scanf("%s", choiceStr);
|
||
if (!isNumber(choiceStr))
|
||
{
|
||
printf("输入错误,请输入数字!\n");
|
||
return;
|
||
}
|
||
choice = atoi(choiceStr);
|
||
if (choice!= 1 && choice!= 2)
|
||
{
|
||
printf("选择错误!\n");
|
||
return;
|
||
}
|
||
|
||
char yearStr[10];
|
||
int year;
|
||
|
||
// 输入年份并验证
|
||
printf("请输入年份:");
|
||
scanf("%s", yearStr);
|
||
if (!isNumber(yearStr))
|
||
{
|
||
printf("输入错误,请输入数字!\n");
|
||
return;
|
||
}
|
||
year = atoi(yearStr);
|
||
if (year <= 0)
|
||
{
|
||
printf("年份不合法!\n");
|
||
return;
|
||
}
|
||
|
||
//单列输出
|
||
if (choice == 1)
|
||
{
|
||
for (int month = 1; month <= 12; month++)
|
||
{
|
||
printMonth(year, month);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
printDoubleColumnCalendar(year);
|
||
}
|
||
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
int choice;
|
||
while(choice<=2)
|
||
{
|
||
// 显示菜单并获取用户选择
|
||
printf("1. 判断闰年和星期几\n");
|
||
printf("2. 输出一年的日历\n");
|
||
printf("请选择:");
|
||
scanf("%d", &choice);
|
||
|
||
switch (choice)
|
||
{
|
||
case 1:
|
||
option1();
|
||
break;
|
||
case 2:
|
||
option2();
|
||
break;
|
||
default:
|
||
printf("退出程序\n");
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
return 0;
|
||
} |