【数组】2021年10月18日

这篇博客介绍了C语言中如何使用数组查询特定年份月份的天数,并实现计算日期的功能。通过IS_lead函数判断闰年,Get_YM_day函数获取指定月份天数,Get_YMD_Count函数计算某日是当年的第几天。同时,文章讨论了数组的两个属性:类型和元素个数,以及数组在内存中的连续存储特性。此外,还涉及到了数组下标从0开始的原因和数组声明的相关知识。
#include<stdio.h>
#include<stdlib.h>

//[数组应用最广泛的功能就是查表]
//数组的两个属性:1.数组的类型  2.数组的元素个数
//数组在内存中是连续存储的。


//使用数组实现查询某年某月的天数

//【函数】判断是否是闰年。
bool IS_lead(int year)
{
	return ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));
}

//【函数】输入年份和月份,返回该月天数。
int Get_YM_day(int year, int month)
{
	static const int ar[] = { 29,31,28,31,30,31,30,31,31,30,31,30,31 };
	//                        0  1  2  3  4  5  6  7  8  9  10 11 12

	if (year < 1 || month < 1 || month>12)return -1;//检验参数的合法性

	//if (IS_lead(year)&&month==2)
	if (month == 2 && IS_lead(year))
	{
		month = 0;
	}
	return ar[month];
}

//输入年月日,返回改日是该年的多少天
int Get_YMD_Count(int year, int month, int day)
{
	if (year < 1)return -1;                            //检验参数的合法性
	if (month < 1 || month>12)return -2;               //检验参数的合法性
	if (day<1 || day>Get_YM_day(year, month))return -3;//检验参数的合法性
	int count = 0;

	for (int s_month = 1; s_month < month; s_month++)
	{
		count += Get_YM_day(year, s_month);
	}

	return count + day;
}

int main()
{
	//数组的定义(两种方式)
	int ar[] = { 1,2,3,4,5,6,7,8 };
	int br[8];

	//数组的元素个数必须用常量来声明

	//c语言中的常量
	//10                  字面常量
	//#define LEN 10        宏常量
	//const int len = 10;   常变量
	//enum{ 10 };         枚举常量



	//计算数组的大小
	sizeof(ar) / sizeof(ar[0]);//ar在sizeof里面代表整个数组

	//【问题】数组为什么要从0下标开始?
	//【问题】数组能不能从1下标开始?

	//打印数组
	for (int i = 0; i < (sizeof(ar) / sizeof(ar[0])); i++)
	{
		printf("%d ", ar[i]);
	}

	printf("%d\n", Get_YMD_Count(2021, 10, 18));

	return 0;
}

【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
<think>嗯,用户让我用Java编写一个程序,输入份和该第一天的星期几,然后打印出每月的月历。我需要先理清楚这个问题的步骤,然后逐步解决。首先,我得考虑如何获取用户输入,然后处理每个月的天数,以及每个月的第一天是星期几,接着格式化输出月历。 首先,用户需要输入份和第一天的星期几。例如,20211月1是星期5(用数字5表示)。那程序需要从1月开始,依次打印每个月的历。每个月的历需要正确显示星期排列,并且期要对齐正确的星期位置。 接下来,我需要确定每个月的天数。这里需要注意的是闰的二月有29天,否则是28天。判断闰的条件是:能被4整除但不能被100整除,或者能被400整除。所以,在程序中需要先写一个判断闰的方法,根据输入的份来确定二月的天数。 然后,每个月的第一天的星期几是关键。例如,1月的第一天是用户输入的星期几,那么2月的第一天就是1月的最后一天的星期几加1。例如,1月有31天,假设1月1是星期五(5),那么31天后,1月31是(5 + 31 -1)%7 = (35)%7=0,也就是星期。所以2月1就是0 +1 = 1,星期一。这样,每个月的第一天需要根据前一个月的天数来计算。 所以,我需要一个数组来存储每个月的天数,然后循环处理每个月,同时跟踪当前月份的第一天的星期几。例如,初始时,currentDayOfWeek是用户输入的值。处理完1月后,计算下个月的起始星期几,即(currentDayOfWeek + daysInMonth) %7。例如,1月有31天,起始星期5,那么31天后是星期(5+31)%7=36%7=1(星期一),所以下个月的起始星期是1。但这里可能需要再仔细计算,因为假设1月1是星期5,那么1月31就是(5 + 31-1)%7=(35)%7=0,星期。所以2月1应该是0+1=1?或者是否需要调整? 这里可能需要重新考虑。每个月的第一天是前一个月的最后一天的下一天。例如,如果前一个月有n天,起始星期是s,那么最后一天的星期是(s + n -1)%7,那么下一个月的第一天是(s +n )%7。例如,假设1月1是星期5(s=5),1月有31天,最后一天是(5+31-1)=35,35%7=0,所以下个月的第一天是(5+31)%7=36%7=1,星期一。是的,这样是对的。所以每个月的起始星期是(currentDayOfWeek + daysInPreviousMonth)%7。例如,处理完1月后,currentDayOfWeek更新为(currentDayOfWeek + daysInJanuary)%7,即下个月的第一天的星期几。 因此,在处理每个月的循环中,需要: 1. 获取当前月份的天数,考虑闰。 2. 打印该月的标题,例如“January 2021”。 3. 打印星期标题,例如 一 二 三 四 五 六。 4. 确定该月第一天是星期几,然后打印对应的空格。 5. 逐打印期,每7天换行。 接下来,如何格式化输出呢?例如,每个期占4个字符的宽度,用空格分隔。可以使用printf来格式化输出,比如用%4s来对齐。但需要注意,每个星期从星期开始,还是星期一?根据用户的要求,用户输入的星期用数字表示,0是星期,所以排列应该是、一、二、三、四、五、六。 所以,星期标题应该是“ 一 二 三 四 五 六”,每个占3或4个字符宽度。例如,每个数字用%3d或%4d,或者字符串对齐。 对于每个月的第一天是星期几,比如如果第一天是星期三(3),那么前面需要空出3天的位置。例如,星期三对应的位置是第三列(假设星期是0列),所以在打印期前需要打印3个空位,每个占4个空格?或者具体要看格式怎么安排。 例如,假设每个期占4个字符宽度,那么第一行可能需要打印起始空格,例如,如果第一天是星期三(即第三列,对应索引3,因为星期是0),那么前面有0()、1(一)、2(二)三个空格?或者可能需要重新计算。 假设月份的第一天是星期几的数字是s(0表示星期,1星期一,等等),那么需要在开始打印s*4个空格?或者需要根据位置来安排。例如,对于每一天,确定它在星期中的位置,然后换行。 例如,假设输出如下: January 2021 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 ... 如果第一天是星期三(s=3),那么前三个位置(、一、二)是空的,然后从星期三开始打印1号。每个期占3个字符宽度,右对齐,例如用%3d。 这样,每个星期有7天,所以每打印一个期后,换行到下一周。具体来说,当打印到星期六时,换行。 所以,对于每个月份,首先打印月份名称和份,然后打印星期标题,然后处理期。 步骤总结: 1. 输入份和第一天的星期几。 2. 遍历12个月,对每个月: a. 确定该月的名称和天数。 b. 确定该月第一天是星期几(初始是输入的,后续根据前一个月的天数计算)。 c. 打印月名和份。 d. 打印星期标题。 e. 打印该月的期,根据起始星期调整前面的空格,然后每7天换行。 3. 处理闰的二月天数。 4. 计算每个月的起始星期。 现在,具体到代码实现: 首先,如何存储月份名称和天数?可以用两个数组,一个String数组存储月份名称,另一个int数组存储天数,其中二月先按28天处理,然后根据闰判断调整。 例如: String[] monthNames = {"January", "February", ..., "December"}; int[] daysInMonth = {31,28,31,30,...}; 判断闰: public static boolean isLeapYear(int year) { return (year %4 ==0 && year%100 !=0) || year%400 ==0; } 然后在处理二月时,如果是闰,天数设为29。 接下来,计算每个月的起始星期: 初始时,currentDayOfWeek是用户输入的值(比如,20211月1是5)。 处理完1月后,currentDayOfWeek = (currentDayOfWeek + daysInMonth[0]) %7; 这样,下一个月的起始星期就是这个结果。 然后循环处理每个月。 对于每个月份,打印月名和份: 比如,January 2021。 然后打印星期标题: 一 二 三 四 五 六,每个占3个字符宽度,用空格分隔。 然后,打印该月每一天的位置。例如,假设该月第一天是星期三(s=3),那么前面需要打印3个空格(每个占3字符,所以可能需要打印3个空位,然后开始打印1号)。 具体实现时,可以先打印起始的空格,数量为起始星期几的值乘以每个期占的宽度。或者更准确地说,每个期占3个字符,所以每个位置之间有一个空格?或者每个期用%3d格式,这样每个数字占3位,包括前面的空格。 例如,第一天是星期三(s=3),即该月的第一天是星期三,对应的是星期中的第4位(0是周,1周一,2周二,3周三)。那么,在打印第一行时,前面的三个位置(、一、二)需要留空,然后从第三个位置开始打印1号。 这里可能需要确定如何根据起始星期来放置期。例如,假设起始星期是s,那么需要打印s个空位,每个占3个字符,接着开始打印1号,2号等,每打印7个后换行。 例如,假设起始星期是3(星期三),那么前面有3个空位,每个占3个字符,即总共有3个空位,然后打印1号。 但是,如何实现这个空位?可以用循环打印空格,或者更简单地,在开始打印期之前,先打印s个空格,然后开始期。但期的排列需要考虑每周的位置。 或者,另一种方法是计算每一天在星期中的位置。例如,初始的偏移量是s,然后对于期d,当前的位置是 (s + d -1) %7。当这个值等于6时,换行。 或者,可以用一个计数器,从0开始,每打印一个期,计数器加1,当计数器%7 ==0时换行,但需要考虑起始的空格。 更具体地说: 对于该月的第一天是星期s(例如,3),则: - 打印s个空位(每个占3个空格,比如“ ”)。 - 然后从1开始打印期,每打印一个期,计数器增加,当(计数器 + s)%7 ==0时换行。 或者,另一种方式: 初始化一个变量 dayOfWeek = s; 然后,对于该月的每一天: 打印期,然后dayOfWeek = (dayOfWeek +1) %7; 当dayOfWeek ==0时,换行。 但这样的话,如果某个月的最后一天是星期六(6),则不需要在最后换行,或者是否需要? 例如,假设某个月有30天,起始s=3: 期1在星期三(3),打印后dayOfWeek变成4(周四) 期2:4 ->5 期3:5->6 期4:6->0,此时换行 依此类推。当打印完所有期后,如果最后一天的dayOfWeek不是6,则可能需要补全后面的空格,或者直接结束。 不过,这样处理的话,可能需要每次打印期后检查是否需要换行。比如,每次打印期后,如果dayOfWeek ==0,则换行。 但这样在换行时,可能会有多余的空行,比如当最后一天刚好是周六,那么最后换行一次。 可能需要测试这种情况。 例如,假设某个月有31天,起始星期是5: 1月1是星期五(5),那么该月的星期分布如下: 期1:5 → 打印后dayOfWeek=6 期2:6 → 打印后dayOfWeek=0 →换行 期3:1 →... 依此类推,到31号时,dayOfWeek是(5+31-1)=35 →35%7=0 →所以最后一天是星期,换行。 那在这种情况下,最后换行是正确的。 所以,代码的大致逻辑是: for 每个月份: 打印月份标题 打印星期标题 dayOfWeek = 该月起始的星期几 // 打印前面的空格 for (int i=0; i < dayOfWeek; i++){ System.out.print(" "); // 每个星期几占3个字符 } for (int day=1; day <= daysInMonth; day++){ System.out.printf("%3d", day); // 每个期占3位,右对齐 dayOfWeek++; if (dayOfWeek %7 ==0){ System.out.println(); // 换行 } } // 处理最后可能未换行的情况 if (dayOfWeek %7 !=0){ System.out.println(); } 但这里有问题,比如,当dayOfWeek初始是3(星期三),打印前三个空格,然后开始打印期。每次打印期后,dayOfWeek自增,当达到7的倍数时换行。例如,期1打印后,dayOfWeek是4,不换行;直到期4,dayOfWeek变成7(即0),换行。这可能对吗? 或者,可能需要使用模7: dayOfWeek = (dayOfWeek +1) %7; 例如,初始dayOfWeek=3: 期1打印后,dayOfWeek变为4 →4%7=4 →不换行 期2 →5 →不换行 期3 →6 →不换行 期4 →0 →换行 是的,这样正确。 所以,正确的处理方式应该是: 初始时,打印空格的数量等于起始的星期几的值。例如,起始是星期三(3),则打印3个空格,每个占3字符。然后,每打印一个期,将dayOfWeek加1,模7。如果dayOfWeek等于0(即星期),则换行。 所以,代码应该如下: int dayOfWeek = startingDay; // 该月第一天的星期几 // 打印前面的空格 for (int i=0; i < dayOfWeek; i++){ System.out.print(" "); } for (int day=1; day <= daysInMonth; day++){ System.out.printf("%3d", day); dayOfWeek = (dayOfWeek +1) %7; if (dayOfWeek ==0){ System.out.println(); } } // 如果最后一天打印完后,dayOfWeek不是0,则需要换行 if (dayOfWeek !=0){ System.out.println(); } 这样处理的话,例如: 假设该月有31天,起始是星期三(3): 打印3个空格,然后开始打印1。每打印一个期,更新dayOfWeek: day=1 →dayOfWeek=4 →不换行 day=2 →5 →不换行 day=3 →6 →不换行 day=4 →0 →换行 day=5 →1 →不换行 ... 到day=31,此时dayOfWeek的初始是3,每打印一个期,dayOfWeek会增加: 总共有31天,初始空格3,然后31个期。 每次循环,day从1到31: 计算每次dayOfWeek的变化: 初始dayOfWeek=3 →打印空格3次 然后: day=1 →dayOfWeek=4 →不换行 day=2 →5 →不换行 day=3 →6 →不换行 day=4 →0 →换行 day=5 →1 →不换行 ... 到day=31时,计算: 初始dayOfWeek=3 →循环31次,每次增加1: 总增加次数31次 →dayOfWeek变化为3 +31 =34 →34%7=34-7*4=34-28=6 →最后dayOfWeek=6 →不等于0,所以最后需要换行。 所以,最后一行输出后,是否换行? 例如,假设最后一行只有6号,那么循环结束后的dayOfWeek是6,此时需要换行吗? 假设当循环结束后,无论是否填满一周,都需要换行。例如,在打印完所有期之后,如果最后的dayOfWeek不是0,说明最后一周没填满,需要换行。 例如,在例子中的31天,最后dayOfWeek是6,循环结束后会执行: if (dayOfWeek !=0) →是的,所以换行。 这样,整个月份的历打印完毕,最后有一个换行。 这样看起来是对的。 现在,把这些步骤转换成Java代码。 首先,处理输入: Scanner输入份和起始星期几。 然后,遍历12个月: for (int month=0; month <12; month++){ // 处理每个月的逻辑 } 对于每个月,计算该月的天数: 如果是二月,判断是否闰。 然后,计算该月的起始星期,初始是用户输入的值,之后每个月更新为(currentDayOfWeek + daysInPreviousMonth)%7. 所以,需要维护一个变量currentDayOfWeek,初始为用户输入的值。 例如: int currentDayOfWeek = startDay; // 用户输入的第一天星期几 for (int month=0; month <12; month++){ // 获取月份的天数 int days = daysInMonth[month]; if (month ==1 && isLeapYear(year)){ // 二月且闰 days=29; } // 打印月份名称和份 System.out.println("\n " + monthNames[month] + " " + year); System.out.println(" 一 二 三 四 五 六"); // 打印该月的期 int dayOfWeek = currentDayOfWeek; // 打印前面的空格 for (int i=0; i < dayOfWeek; i++){ System.out.print(" "); } for (int day=1; day <= days; day++){ System.out.printf("%3d", day); dayOfWeek = (dayOfWeek +1) %7; if (dayOfWeek ==0){ System.out.println(); } } if (dayOfWeek !=0){ System.out.println(); } // 更新currentDayOfWeek为下个月的起始星期 currentDayOfWeek = (currentDayOfWeek + days) %7; } 这样,currentDayOfWeek在每个循环后更新为下个月的起始星期。 例如,假设1月有31天,起始星期是5: currentDayOfWeek初始为5 →处理完1月后,currentDayOfWeek = (5+31)%7 =36%7=1 →所以2月的起始星期是1。 这样,每个月的起始星期正确。 现在,测试一下这个逻辑是否正确。 假设输入2021,起始星期5(即1月1是星期五)。 1月的天数是31天,currentDayOfWeek初始是5. 处理完1月后,currentDayOfWeek变为(5+31) mod7=36 mod7=1 →正确。所以2月的第一天是星期一。 二月如果是非闰,天数是28天。处理完二月后,currentDayOfWeek变为(1+28) mod7=29 mod7=1 →所以3月第一天是星期一。 这样,每个月的起始星期正确。 现在,关于月份名称的数组,应该用中文还是英文?用户的问题描述中提到程序要打印每月的月历,可能希望用英文月份名称,例如“January 2021”。但是用户可能需要中文?需要看用户的具体要求。但用户给的例子是“Java编写程序”,通常输出月份可能用英文。或者需要确认。 在用户的问题描述中,示例是“该第一天是星期几(如5)”,而输出可能是中文或英文。但用户的问题没有明确要求,所以假设使用英文月份名称。 所以,月份名称数组可以是: String[] monthNames = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; 这样,打印的标题是“January 2021”等。 接下来,星期标题是“ 一 二 三 四 五 六”,每个字之间用空格分隔,每个占3字符宽度。例如,使用: System.out.println(" 一 二 三 四 五 六"); 这样打印出来的是、一、二、三、四、五、六,每个之间有一个空格,共占3字符宽度? 例如,""后面有一个空格,占两个字符,但可能不够。例如,“”字后面有两个空格,这样每个标题项占3字符,例如: 一 二 三 四 五 六 每个标题项之间有一个空格,所以总共有7*3 -1 =20字符?或者可能使用更紧凑的方式。或者,可能用三个字符的位置,比如每个用%3s,这样每个标题项右对齐,但中文可能占两个字符宽度,所以可能会有问题。但为了简单,直接输出字符串“ 一 二 三 四 五 六”即可。 现在,编写完整的代码: import java.util.Scanner; public class PrintCalendar { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入份:"); int year = scanner.nextInt(); System.out.print("请输入该第一天是星期几(0-6,0代表星期):"); int startDay = scanner.nextInt(); String[] monthNames = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (isLeapYear(year)) { daysInMonth[1] = 29; } int currentDayOfWeek = startDay; for (int month = 0; month < 12; month++) { int days = daysInMonth[month]; System.out.printf("\n %s %d\n", monthNames[month], year); System.out.println(" 一 二 三 四 五 六"); int dayOfWeek = currentDayOfWeek; // 打印前面的空格 for (int i = 0; i < dayOfWeek; i++) { System.out.print(" "); } for (int day = 1; day <= days; day++) { System.out.printf("%3d", day); dayOfWeek = (dayOfWeek + 1) % 7; if (dayOfWeek == 0) { System.out.println(); } } if (dayOfWeek != 0) { System.out.println(); } // 更新下个月的起始星期 currentDayOfWeek = (currentDayOfWeek + days) % 7; } } private static boolean isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } } 现在,测试这个代码是否正确。 例如,输入year=2021,startDay=5(20211月1是星期五)。 程序会处理每个月的currentDayOfWeek: 1月:currentDayOfWeek初始是5,处理完后,currentDayOfWeek = (5+31)=36 mod7=1 →2月起始是星期一。 二月2021不是闰,所以28天。处理完后,currentDayOfWeek = (1+28)=29 mod7=1 →三月起始是星期一。 三月有31天,currentDayOfWeek更新为1+31=32 mod7=4 →四月起始是星期四。 依此类推。 现在,查看1月的输出是否正确: January 2021的起始星期是5(星期五),所以1月1是星期五,对应的是: 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 ... 因为起始空格是5,即打印5个空格,每个占3字符。例如,星期五是5,所以起始空格循环i<5,即打印5次“ ”,即15个空格? 但这样会导致第一行的期1出现在星期六的位置? 或者可能哪里弄反了? 哦,这里可能有个错误。因为currentDayOfWeek初始是startDay,即用户输入的该第一天的星期几。例如,输入5,代表星期五,即该的1月1是星期五。那么在1月的处理中,dayOfWeek初始是5,所以前面会打印5个空格,每个占3字符。这样,期1会被打印在第5个位置,即星期六的位置?这显然不对。 哦,这里发现了问题:星期排列是、一、二、三、四、五、六。每个位置对应0到6。例如,星期是0,星期一是1,依此类推,星期六是6。 所以,如果某个月的1月1是星期五(对应数字5),那么该天应该位于星期五的位置,即第5个位置(从0开始计算)。所以,当打印前面的空格时,应该打印5个空格,每个占3字符,这样期1会被放在星期五的位置。 例如,假设起始星期是5,那么前面有5个空格,期1在星期五的位置,即: 一 二 三 四 五 六 1 2 3 ... 这样,对吗? 比如,假设起始是星期五(5),那么: 空格数目是5 →每个空格占3字符,所以前面的空格总共有5*3=15空格,那么期1出现在星期五的位置。例如: 一 二 三 四 五 六 1 2 这样,1号在星期五的位置,对吗? 是的。因为星期排列是(0)、一(1)、二(2)、三(3)、四(4)、五(5)、六(6)。所以,如果某天是星期五,其对应的位置是5,所以前面有5个空格,每个占3字符,那么期1会被打印在星期五的位置。 这样是正确的。 那在代码中,当用户输入startDay为5时,1月1是星期五,打印正确的位置。 但需要验证代码的输出是否符合预期。 例如,假设用户输入2021,startDay=5: 1月的历应该如下: January 2021 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 因为1月1是星期五(5),所以前面有5个空格,然后打印1,接着2,换行(因为dayOfWeek在打印2后变为(5+2)%7=7%7=0 →换行。然后继续打印3到9,依此类推。 但根据代码的逻辑,初始dayOfWeek是5,所以前面打印5个空格。然后打印1,dayOfWeek变为6 →不换行。打印2,dayOfWeek变为0 →换行。所以第一行是: 1 2 →对吗? 是的,因为5个空格,每个占3字符,所以是15个空格?然后1和2分别占3字符。例如: 空格数:5个,每个3字符 →15空格,接着1(占3字符,右对齐,即“ 1”),然后2(“ 2”),然后换行。 所以第一行显示为“                 1  2”(假设空格用点表示:...............1  2),然后换行。 接着第二天是3,dayOfWeek=1,打印到星期六(6)时换行。 因此,1月的第一周显示为: 1 2 3 4 5 6 7 8 9 这可能与实际20211月的历相符吗? 实际20211月1是星期五,所以该月的历: 1是星期五,位于第5个位置(、一、二、三、四、五的位置是5)。 所以,第一行的星期五位置是1,星期六是2。那么第一行应该只有1和2,对吗? 是的。所以代码的输出是正确的。 综上,代码的逻辑正确。 可能存在的另一个问题是,在打印月份标题时,是否居中?例如,“January 2021”居中显示。当前代码使用System.out.printf("\n %s %d\n", monthNames[month], year);,添加了6个空格,可能不够,导致标题不居中。例如,假设每行的宽度是21字符(7天,每个占3字符),那么月份标题可能需要居中。但这个问题可能不影响功能,用户可能不严格要求。或者可以计算标题的长度,然后添加合适的前导空格,使其居中。例如,月份名称加份的总长度是例如“January 2021”共11字符,每行显示21字符的话,需要左边添加5个空格,使得总空格为5,使得标题居中。例如: int totalWidth = 21; // 7*3 characters String title = monthNames[month] + " " + year; int leadingSpaces = (totalWidth - title.length())/2; 然后打印leadingSpaces个空格。但这样可能更复杂,但用户问题中没有特别要求,所以可能可以忽略,使用固定的空格。 或者,用户可能希望像例子中的那样,使用“ January 2021”这样的格式,即前面有6个空格,让标题左对齐。这可能已经足够。 综上,代码应该可以正确输出每个月的历。</think>以下是分步实现的Java程序,用于打印指定份的月历: ```java import java.util.Scanner; public class CalendarPrinter { public static void main(String[] args) { // 1. 获取用户输入 Scanner scanner = new Scanner(System.in); System.out.print("请输入份:"); int year = scanner.nextInt(); System.out.print("请输入该第一天的星期(0-6):"); int startDay = scanner.nextInt(); // 2. 初始化月份数据 String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 3. 处理闰 if (isLeapYear(year)) { days[1] = 29; } // 4. 遍历12个月 int currentDay = startDay; for (int i = 0; i < 12; i++) { // 打印月份标题 System.out.printf("\n %s %d\n", months[i], year); System.out.println(" 一 二 三 四 五 六"); // 打印首行空格 for (int j = 0; j < currentDay; j++) { System.out.print(" "); } // 打印期 for (int day = 1; day <= days[i]; day++) { System.out.printf("%3d", day); // 换行判断 if ((currentDay + day) % 7 == 0 || day == days[i]) { System.out.println(); } } // 计算下个月起始星期 currentDay = (currentDay + days[i]) % 7; } } // 闰判断方法 private static boolean isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } } ``` ### 实现步骤说明 1. **输入处理** 使用`Scanner`获取用户输入的份和该第一天的星期数,其中: - `0` 表示星期 - `1` 表示星期一 - ... - `6` 表示星期六 2. **月份数据初始化** - `months`数组存储12个月的英文名称 - `days`数组存储每个月的天数(二月默认28天) 3. **闰判断** 根据闰规则调整二月的天数: $$ \text{闰} = (\text{能被4整除且不能被100整除}) \lor (\text{能被400整除}) $$ 4. **循环处理每个月** - **打印标题**:月份名称和份 - **打印星期头**:固定显示" 一 二 三 四 五 六" - **对齐首**:通过空格调整每月第一天的位置 - **期打印**: - 使用`%3d`格式化保证数字对齐 - 每7天换行 - **计算下月起始**:通过取模运算确定下个月第一天的星期 ### 示例输出(20211月) 当输入`2021`和`5`(20211月1是星期五)时: ``` January 2021 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ``` ### 关键逻辑 1. **期对齐** 通过`currentDay`变量跟踪每月首的星期位置,确保期正确对齐。 2. **换行机制** 当累计期数与星期数的和为7的倍数时换行,保证每周显示7天。 3. **闰处理** 独立的闰判断方法使代码更清晰易维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值