第A练——日期与时间

**

第A练——日期与时间

**

  1. 日期与时间——必做题

1.1. 判断天数:TheDay.cpp(本题50分) 【题目描述】 输入某“年”某“月”某“日”,判断这一天是这一年的第几天?

【程序分析】
以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天,特殊情况,闰年且输入月份大于3时需考虑多加一天。建议使用switch分支语句。
【输入】
输入文件TheDay.in有1行,包含3个int类型的整数,各整数之间由一个英文状态下的空格隔开,即输入的年月日变量year, month, day。
【输出】
输出文件TheDay.out有1行,包含1个int类型的整数(整型变量sum),即这一天是这一年的第几天?
【输入输出样例1】
TheDay.in TheDay.out
2016 4 5 96
【输入输出样例2】
TheDay.in TheDay.out
1997 2 18 49
【数据限制】
year≥1,1≤month≤12,1≤day≤31。

#include<stdio.h>
int main(){ 
	int year, month, day, sum, leap; //sum-第几天;leap-是否为闰年(1-是; 0-否)
	printf("\n请输入年(year), 月(month), 日(day)[空格隔开]:\n"); 

	FILE *fp;
	if((fp=fopen("TheDay.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("TheDay.in", "r", stdin);
		freopen("TheDay.out", "w", stdout);
	}

	scanf("%d%d%d", &year, &month, &day); 
	//***************************************************
	//(1)先计算'某月以前' 月份的‘总天数’(不考虑是否闰年) 
	switch(month){ 
	case 1:  sum=0;   break; 
	case 2:  sum=31;  break; //31 =0 +31
	case 3:  sum=59;  break; //59 =31+28
	case 4:  sum=90;  break; //90 =59+31
	case 5:  sum=120; break; //120=90+30
	case 6:  sum=151; break; //151=120+31
	case 7:  sum=181; break; //181=151+30
	case 8:  sum=212; break; //212=181+31
	case 9:  sum=243; break; //243=212+31
	case 10: sum=273; break; //273=243+30
	case 11: sum=304; break; //304=273+31
	case 12: sum=334; break; //334=304+30
	default:
		printf("data error!");
		break;
	} 
	
	//(2)计算到该月该天的‘天数’
	sum = sum + day; /*再加上某天的天数*/ 
	
	//(3.1)根据年份判断是否闰年, 进行处理....
	if( year%400 == 0 || (year%4 == 0 && year%100 != 0) ){ /*判断是不是闰年*/ 
		leap = 1; 
	}else{ 
		leap = 0; 
	}
	//(3.2)根据【是否闰年?】 + 【是否2月份之后?】确定总天数是否+1
	if(leap==1 && month>2){/*如果是闰年且月份大于2,总天数应该加一天*/ 
		sum++;
	}
	//===================================================
	printf("%d\n", sum);//这一天是这一年的第%d天!
	
	return 0;
}

1.2. 年龄计算:ComputeAge.cpp(本题20分) 【题目描述】 有n个人(n为整数)坐在一起,问第n个人多少岁?他说比第n-1个人大diff岁(diff为整数)。问第n-1个人岁数,他说比第n-2个人大diff岁。问第n-2个人,又说比第n-3人大diff岁。依次类推,最后问第一个人,他说是8岁。请问第n个人的年龄是多大?

【程序分析】
利用递归的方法,递归分为回推和递推两个阶段。要想知道第n个人岁数,需知道第n-1人的岁数,依次类推,推到第一人(8岁),再往回推。
【输入】
输入文件ComputeAge.in有1行,包含2个int类型的整数,两个整数之间由一个英文状态下的空格隔开,即输入的变量n和diff。
【输出】
输出文件ComputeAge.out有1行,包含1个int类型的整数(变量age的值),即第n个人的年龄。
【输入输出样例1】
ComputeAge.in ComputeAge.out
5 2 16
【输入输出样例2】
ComputeAge.in ComputeAge.out
100 32 3176
【数据限制】
n≥3,diff≥1。

#include<stdio.h>

int computeAge(int n, int diff) {
	//********************************************
	int c; 

	if(n == 1){
		c = 8;
	}else{
		c = computeAge(n-1, diff) + diff; 
	}

	return c; 
	//============================================
} 

int main(){
	int n, diff, age; //n-人的总数目; diff-人i和人(i-1)之间的年龄差; age-第n个人的年龄
	printf("\n请输入总人数(n), 年龄差(diff)[空格隔开]:\n"); 

	FILE *fp;
	if((fp=fopen("ComputeAge.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("ComputeAge.in", "r", stdin);
		freopen("ComputeAge.out", "w", stdout);
	}
	
	scanf("%d%d", &n, &diff); //输入总人数、年龄差
	//********************************************

	age = computeAge(n, diff); //调用函数computeAge(n, diff)获得第n人的年龄
	
	//============================================
	printf("%d\n", age); //输出第n人的年龄

	return 0;
}

1.3. 判断星期几:Week.cpp(本题30分) 【题目描述】 请输入星期几的第一个字母来判断一下是星期几;如果第一个字母一样,则继续输入第二个字母以判断是星期几。输入错误时,请输出字符串信息“data error”;输入正确时,请输出星期几对应的英文单词(monday, tuesday, wednesday, thursday, friday, saturday, Sunday。注意:全小写格式)。

【程序分析】
第1个字母用switch语句进行判断。若第一个字母一样,则用if语句判断第2个字母。
【输入】
输入文件Week.in有1行,包含若干个字符,即输入的若干个描述星期的字符。
【输出】
输出文件Week.out有1行,包含判断结果的输出。输入错误时,输出字符串信息“data error”;输入正确时,输出星期几对应的英文单词(monday, tuesday, wednesday, thursday, friday, saturday, sunday),全小写格式。
【输入输出样例1】
Week.in Week.out
fRiDay friday
【输入输出样例2】
Week.in Week.out
tuDDD tuesday
【输入输出样例3】
Week.in Week.out
988uhk data error
【数据限制】
必须输入至少1个字符。

#include <stdio.h>
#include <ctype.h> /*字符大小写转换函数: char toupper(char)和char tolower(char)*/

int main(){
	char letter; //letter-输入的某个字符
	printf("请输入星期字母字符:\n"); //请输入星期的第1-2个字母
	
	FILE *fp;
	if((fp=fopen("Week.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("Week.in", "r", stdin);
		freopen("Week.out", "w", stdout);
	}
	//************************************************	
	switch (toupper(letter=getchar())){
	case 'S':
		//printf("请输入星期的第2个字母:\n"); 
		if(tolower(letter=getchar()) == 'a'){
			printf("saturday\n"); 
		}else if (tolower(letter=getchar()) == 'u'){
			printf("sunday\n"); 
		}else{
			printf("data error\n");
		}
		break;
	case 'F':
		printf("friday\n");
		break; 
	case 'M':
		printf("monday\n");
		break; 
	case 'T':
		//printf("请输入星期的第2个字母:\n"); 
		if(tolower(letter=getchar()) == 'u'){
			printf("tuesday\n"); 
		}else if (tolower(letter=getchar()) == 'h'){
			printf("thursday\n"); 
		}else{
			printf("data error\n"); 
		}
		break;
	case 'W':
		printf("wednesday\n");
		break; 
	default:
		printf("data error\n"); 
	}
	//================================================
	return 0;
}
  1. 日期与时间——提高题

2.1. 编制万年历:Calendar.cpp(本题100分) 【题目描述】 根据输入的年份,输出该年份的年历(1至12月的月历)。

【题目分析】
目标是学习和掌握三维数组的用法。
 函数f(…)和g(…)用于求出该年1月1日的星期。
 月份month在程序中的数值为011,分别表示112月。月份值0表示1月。
 由闰年的判断条件(四年且不是100年一闰, 400年一闰),确定该年是否为闰年。
 为了便于按星期输出各月的月历,引入三维数组的日期表int date[12][6][7]。其中,12表示12各月,6表示一个月最多有6个星期,7表示每星期7天。程序首先将日期表中各元素的值置为0,然后顺序将各月的日期填写到日期表中,各月的天数按月取自数组day_tbl[][](该数组是二维数组,第一行存储平年各月的天数,第二行存储闰年各月的天数)。
【输入】
输入文件Calendar.in有1行,包含1个int类型的正整数,即输入的年份year。
【输出】
程序的输出分两栏。左边一栏自上到下依次是16月的月历,右边一栏自上到下依次是712月的月历。输出时,若日期数为0,就用4个空白符代替,否则输出日期。具体输出格式请查看【输入输出样例】。
程序对应的输出文件Calendar.out为上述输出(有若干行)。
【输入输出样例】
Calendar.in Calendar.out
2016
【数据限制】
year≥1。

/* 输入年份,输出该年的年历. */
#include "stdio.h"

/**使用德国数学家克里斯蒂安·蔡勒公式(Zeller’s Formula)计算给定年份year的第一天是星期几。具体方法:自己上网查询与学习!*/

/*功能: 如果月份<3(三月之前), 则年份回退1年; 否则, 视为当年. */
int YEAR(int year, int month){ /* 如果'月'<3, 则f(年, 月)='年-1';  否则, f(年, 月)='年' */
	if (month < 3){
		return year-1;
	}else{
		return year;
	}
}

/*功能: 因为月份<3(三月之前)年份回退1年, 因此月份相应调整. */
int MONTH(int month){ /* 如果'月'<3, g(月)='月+13';  否则, g(月)='月+1' */
	if (month < 3){
		return month + 12;
	}else{
		return month;
	}
}

/*功能: 判断某年(year)某月(month)某日(day)是星期几?返回整型int:0~6, 0表示星期天, 1~6表示星期一~六. 
方法:使用德国数学家克里斯蒂安·蔡勒(Christian Zeller, 1822-1899)在1886年推导出的,因此通称为蔡勒公式(Zeller’s Formula)

W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1.

其中,公式由世纪数减一(C)、年份末两位(y)、月份(M)和日数(d)即可算出W,再除以7,得到的余数是几就表示这一天是星期几。
唯一需要变通的是要把1月和2月当成上一年的13月和14月,C和y都按上一年的年份取值。
因此,人们普遍认为这是计算任意一天是星期几的最好的公式。

注意:
(1)公式都是基于公历(格里高利历)的置闰规则来考虑的! 
(2)负数不能按习惯的余数的概念求余数,只能按数论中的余数的定义求余。为了方便计算,我们可以给它加上一个7的整数倍,使它变为一个正数,比如加上70,得到55。再除以7,余6,说明这一天是星期六。这和实际是一致的!
现在仍然让我们来算2004年5月1日的星期,显然C=20,y=4,M=5,d=1,代入蔡勒公式,有:
W = [20/4] - 40 + 4 + 1 + [13 * (5+1) / 5] + 1 - 1
  = -15.
*/
int WeekDay(int year, int month, int day){
	long trYEAE = YEAR(year, month);
	int C = trYEAE/100; //世纪数减一
	int y = trYEAE%100; //年份末两位
	int M = MONTH(month);
	int d = day;
	
	int W = (C/4) - 2*C + y + (y/4) + (13*(M+1)/5) + d -1;
	//printf("YEAR=%d, C=%d, y=%d, M=%d, d=%d, W=%d \n", YEAR, C, y, M, d, W);
	
	//根据W的值,判定星期几?
	if( W < 0){ //如果W为负,不好求余数, 则加上若干个7, 使之非负 
		while( W < 0){
			 W += 7;
		}				
	}
	
	int weekday = W%7; //对7求余数,得到year/month/day这一天是星期几 
		
	return weekday;
}


/*功能: 判断给定的年份year是否为闰年? 四年一闰, 100年不闰, 400年一闰。1-是; 0-否。*/
int IsLeap(int year){
	return (year%4==0 && year%100) || (year%400 == 0);
}

int date[12][6][7]; //日期表

int day_tbl[][12] = {//365*3 + 366 = 1095 + 366 = 1461
	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, //'平'年每月天数(30*4 + 31*7 + 28 = 120+217+28 = 365)
	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}  //'闰'年每月天数(30*4 + 31*7 + 29 = 120+217+28 = 366)
};

int main(){
	int sw, leap, i, j, k, wd, day; //sw-星期几?  leap-是否闰年;  wd-周;  day-一个月的哪一天?
	int year; //年
	char title[] = " SUN MON TUE WED THU FRI SAT"; //'星期'标题(每个日期占4个字符, 右对齐)
	printf("请输入年份(year):"); //年

	FILE *fp;
	if((fp=fopen("Calendar.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("Calendar.in", "r", stdin);
		freopen("Calendar.out", "w", stdout);
	}

	scanf("%d", &year); //输入年份值及回车
	//**************************************************************************************
	/*(1)该年(year) 1月1日是星期几? */
	sw = WeekDay(year, 1, 1); //返回整型int:0~6, 0表示星期天, 1~6表示星期一~六.
	
	/*(2)判断该年(year)是否是闰年? */
	leap =  IsLeap(year); //是否闰年(1-是; 0-否)
	
	/*(3)初始化日期表,将日期表中各元素的值置为0 */
	for(i=0; i<12; i++){ //0~11 一至十二月
		for(j=0; j<6; j++){ //0~5 本月一至五周
			for(k=0; k<7; k++){ //0~6 本周 周日至周六
				date[i][j][k] = 0; //日期表置0
			}
		}
	}
	
	/*(4)根据给定的年份(year), 赋值日期数据*/
	for(i=0; i<12; i++){//一年12个月
		/**将第i月(共day_tbl[leap][i]天)的日期(1~day_tbl[leap][i])填入日期表 */
		for(wd=0, day=1; day<=day_tbl[leap][i]; day++) {
			//A.将第i月第'day'天的信息填写在日期表date[][][]的对应地方
			date[i][wd][sw] = day; //第i月, 第wd周,星期sw

			//B.星期'几'往后移动
			sw = (++sw)%7; //每星期7天, 以0~6计数
			
			//C.碰到0(星期天), 新的一周开始
			if(sw == 0){
				wd++; //每7天一周, 星期天开始新的一周
			}
		}
	}
	
	//printf("|===========================%d年的日历===========================|\n|", year); //日历头
	/*(5)分两栏输出year年的12各月的日历信息(左栏1-6月, 右栏7-12月) */
	for(i=0; i<6; i++){
		//A.先测算第i月和第i+6月的最大星期数(日期表的第6行是否有日期?)
		for(wd=0, k=0; k<7; k++){ //日期表的第6行有日期,则wd != 0
			wd += date[i][5][k] + date[i+6][5][k];
		}
		
		//B.第i月和第i+6月有几个星期(要显示几行?)
		wd = wd?6:5;
		
		//C.输出第i月和第i+6月(月历)的行头信息(注意:右栏第i+6月的"月份标识%2d"之前有3个空格[前后共6个字符位], 其它控制字符之间一个字符' ')
		//printf("%2d %s   %2d %s |\n|", i+1, title, i+7, title);
		printf("%2d %s   %2d %s\n", i+1, title, i+7, title);

		//D. 从第0周 至 第wd周, 输出日历信息
		for(j=0; j<wd; j++){
			//(D.1)空过: 月份标识的3[2+1]个字符位 
			printf("   "); //输出3个空白符
			
			//(D.2)【左栏为第i月】, 右栏为第i+6月
			for(k=0; k<7; k++){ //左侧栏,...
				if(date[i][j][k]){  //若有日期(非0), 则'按4个字符宽度的格式'输出(i月)该日期
					printf("%4d", date[i][j][k]);
				}else{ //无日期, 则'按4个字符宽度的格式'输出4个空格
					printf("%4c", ' ');
				}
			}
			
			//(D.3)第i月和第i+6月(月历) 之间,6个空格隔开
			printf("%6c", ' '); //输出6个空白符
			
			//(D.4)左栏为第i月,【右栏为第i+6月】
			for(k=0; k<7; k++){ //右侧栏,...
				if(date[i+6][j][k]){ //若有日期(非0), 则'按4个字符宽度的格式'输出(i+6月)该日期
					printf("%4d", date[i+6][j][k]);
				}else{ //无日期, 则'按4个字符宽度的格式'输出4个空格
					printf("%4c", ' ');
				}
			}

			//(D.5)一行之后,输入换行符
			//printf(" |\n|");
			printf("\n");
		}
	}
	
	//puts("==================================================================|");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python计算思维训中,循环和列表是非常重要的概念。循环可以让我们重复执行某些操作,而列表则是一种非常方便的数据结构,可以存储多个元素。在Python中,我们可以使用for循环来遍历列表中的元素,也可以使用while循环来重复执行某些操作,直到满足某个条件为止。同时,我们还可以使用列表推导式来快速生成列表,这对于处理大量数据非常有用。总之,循环和列表是Python编程中必不可少的基础知识,掌握它们可以让我们更加高效地处理数据和解决问题。 ### 回答2: Python是一门流行的编程语言,使用它可以进行各种类型的编程。计算思维是一种重要的编程思维方式,它非常适合用Python语言来进行训。在这方面,循环和列表是Python编程中重要的概念之一。 循环是Python编程中非常常用的结构,它允许程序在代码块中重复执行相同的操作。 Python提供了两种类型的循环:for循环和while循环。 for循环适用于在已知对象(如字符串、列表或元组)上循环,而while循环适用于在条件为真时循环。在循环中,我们经常使用控制流语句如break和continue,来控制循环结束或跳过某些迭代。 列表是Python中非常重要的数据类型之一,可以存储一系列有序的元素。因为列表是可变的数据类型,所以它可以通过添加、删除元素来修改。 Python中的列表提供了一系列有用的方法,如append(添加元素)、pop(删除元素)、sort(排序元素)等。通过使用列表,我们可以很方便地存储和处理大量数据。同时,利用嵌套列表,我们可以存储复杂结构的数据,如矩阵和树等。 循环和列表是Python编程的两个重要构成部分。它们可以提高我们的编程效率,减少代码行数,同时也可以让我们更好地理解和应用计算思维的概念。因此,在Python编程训中,我们应该注重循环和列表的学习。例如,我们可以通过编写简单的程序来打印斐波那契数列或找到列表中的最大值,来习循环和列表的概念。 通过不断训和实践,我们可以更深入地理解Python编程的精髓,提高我们的编程思维和手段。 ### 回答3: Python是一门非常强大的编程语言,它具有着多种数据类型和结构,其中列表是Python语言中最为常用的一种数据结构,循环则是Python语言中最为重要的控制语句之一。在Python的计算思维训中,循环和列表是两个非常重要的主题。 在Python中,循环一般分为两种,分别是for循环和while循环。这两种循环语句可以帮助开发者重复执行一段代码,从而避免代码重复。for循环一般用于对一组数据的遍历,可以对列表、元组、字符串等序列类型进行遍历操作。while循环则是在条件满足的情况下一直执行一段代码,直到条件不满足为止。通过掌握循环语句,开发者能够编写出更加高效的代码,提高代码开发和维护的效率。 除了循环语句,列表也是Python语言中非常重要的数据结构之一。列表是一个有序的数据序列,可以存储任意类型的数据,包括数字、字符串、元组及其他列表等等。Python中的列表还具有嵌套的特性,即可以将一个列表当作另一个列表的元素。通过使用列表,开发者能够更加方便地处理大量数据,并进行各种复杂的操作。 循环和列表是Python计算思维中非常重要的两个主题。学会了循环和列表的使用方法,开发者能够更加高效地处理各种数据,编写出更加优雅的程序。同时,循环和列表也是Python语言中的基础,掌握好这两个主题,能够为后续的计算思维训打下很好的基础,进一步提高开发者的编程能力和水平。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值