一、题目名称:“三天打鱼两天晒网”
二、题目内容:中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。用C或C++语言/java/python实现程序解决问题。
三、算法设计:
1.输入当前日期的年、月、日。
2.检验当前日期是否合法。
3.从2010年开始遍历
3.1若当前年份小于输入年份
3.1.1若当前年份为闰年,则总天数累加366
3.1.2若当前年份不是闰年,则总天数累加365
3.2遍历年份+1
4.计算输入的月份之前每个月的天数,并累加到总天数中
5.将输入的日期累加到总天数中
6.将总天数对5取模,得到余数
7.若余数为1、2、3时,则当天打鱼,否则为晒网。
四、调试截图:
1.调试输入部分,确保程序能由接收到输入。
2.调试计算天数的部分,验证间隔天数是否正确。
五、测试结果:
1.结果测试
2.日期合法性测试
六、遇到的困难及解决方案:
1.第一次测试时,程序运行完的总天数不正确,调试后发现,通过观察变量的取值发现,输入的月和日取值始终相同,查找代码才发现是将两个变量名字写成了一个。
2.验证日期合法性时,开始采用的方法是直接暴力if-else选择判断,遇到的问题是所需要考虑的情况太多,导致判断十分繁琐、层次不清晰。例如:年份是否为闰年、月份是否包含二月、每个月月份的天数等等,都需要一个个判断。通过查阅,发现Java中有判断日期合理性的方法。
// 检验日期的合法性,合法返回true,不合法返回false
public static boolean isValidDate(String strDate) {
boolean isValid = true;// 指定日期格式为四位年/两位月份/两位日期,注意yyyy/MM/dd区分大小写;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
// 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01
dateFormat.setLenient(false);
dateFormat.parse(strDate);
} catch (ParseException e) {
// 如果throw java.text.ParseException或者NullPointerException,就说明格式不对
isValid = false;
}
return isValid;
}
3.在测试文件读入部分时,遇到的困难是无法将年、月、日分开读入。解决的办法也很简单,在in.dat文件中存储日期时,将年月日用特殊符号分隔开,直接利用String类型中的split()方法读取,并将年月日分别放String数组中,再进行后续操作。
// 从in.dat文件中读取日期
public static void inputDate() throws Exception {
File file = new File("src/in.dat");
BufferedReader br = new BufferedReader(new FileReader(file));// 输入流
String str;
while ((str = br.readLine()) != null) {// 按行读取
String[] ss = str.trim().split("-");// 日期格式为yyyy-MM-dd
// for test
// System.out.println(ss[0].trim() + "-" + ss[1].trim() + "-" + ss[2].trim());
}
br.close();// 关闭流
}
七、源代码
package chapterOne;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
/**
* @ClassName: FitsAndStarts
* @Description:TODO judge someday is Fit or Start
* @author: YanCX
* @date: 2019年2月28日 上午8:44:24
*/
public class FitsAndStarts {
private static Scanner scanner;
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
int curYear = 0, curMonth = 0, curDay = 0;
scanner = new Scanner(System.in);
System.out.println("依次输入年、月、日,并用空格分隔:");
curYear = scanner.nextInt();
curMonth = scanner.nextInt();
curDay = scanner.nextInt();
String strDate = curYear+"-"+curMonth+"-"+curDay;
// inputDate();
if (isValidDate(strDate)) {
String strResult = "";
strResult = judge(curYear, curMonth, curDay);
// outputResult(strResult);
System.out.println(strResult);
}else {
System.out.println("Date Error!");
}
}
// 判断打鱼or晒网,并返回字符串
public static String judge(int curYear, int curMonth, int curDay) {
String strResult = "";
int totalDays = getTotalDays(curYear, curMonth, curDay);
int x = totalDays % 5;
if (x <= 3 && x > 0) {
strResult = "Starts";
} else {
strResult = "Fits";
}
return strResult;
}
// 判断当前年份是否为闰年,是返回true,不是返回false
public static boolean isLeapYear(int curYear) {
if (curYear % 400 == 0 || (curYear % 4 == 0 && curYear % 100 != 0)) {
return true;
}
return false;
}
// 计算从当前日期距离2010年1月1日的总天数,返回总天数
public static int getTotalDays(int curYear, int curMonth, int curDay) {
int totalDays = 0;// 总天数
// 统计年
for (int i = 2010; i < curYear; i++) {
if (isLeapYear(i)) {
totalDays += 366;
} else {
totalDays += 365;
}
}
// 统计月,利用switch开关特点,倒序累加
switch (curMonth - 1) {
case 11:
totalDays += 30;
case 10:
totalDays += 31;
case 9:
totalDays += 30;
case 8:
totalDays += 31;
case 7:
totalDays += 31;
case 6:
totalDays += 30;
case 5:
totalDays += 31;
case 4:
totalDays += 30;
case 3:
totalDays += 31;
case 2:
if (isLeapYear(curYear)) {
totalDays += 29;
} else {
totalDays += 28;
}
case 1:
totalDays += 31;
case 0:
totalDays += 0;
break;
default:
System.out.println("month error!");
}
// 统计日
totalDays += curDay;
return totalDays;
}
// 检验日期的合法性,合法返回true,不合法返回false
public static boolean isValidDate(String strDate) {
boolean isValid = true;// 指定日期格式为四位年/两位月份/两位日期,注意yyyy/MM/dd区分大小写;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
// 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01
dateFormat.setLenient(false);
dateFormat.parse(strDate);
} catch (ParseException e) {
// 如果throw java.text.ParseException或者NullPointerException,就说明格式不对
isValid = false;
}
return isValid;
}
// 从in.dat文件中读取日期
public static void inputDate() throws Exception {
File file = new File("src/in.dat");
BufferedReader br = new BufferedReader(new FileReader(file));// 输入流
String str;
while ((str = br.readLine()) != null) {// 按行读取
String[] ss = str.trim().split("-");// 日期格式为yyyy-MM-dd
// for test
// System.out.println(ss[0].trim() + "-" + ss[1].trim() + "-" + ss[2].trim());
}
br.close();// 关闭流
}
// 将结果输出到output.txt中
public static void outputResult(String strResult) {
try {
File file = new File("src/output.txt");
// 文件不存在时,主动创建文件。
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file, false);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(strResult);
bw.close();
fw.close();
// for test
// System.out.println("test done!");
} catch (Exception e) {
// TODO: handle exception
}
}
}