第一次博客作业

发布时间 2023-03-25 19:58:11作者: 椛huahua

第一次博客作业

 

题目集1~3总结性Blog

(1)前言:

题目集1难度一般,题量较大,主要考察选择语句,循环语句以及对运算符的合理使用。同时考察了处理字符串问题可使用的StringBuilder,StringBuffer,append(),contains(),indexOf()语句。另外,由于部分题目要求量较大,对我们的信息理解与处理能力做出了要求。

题目集2难度较高,题量较大,考察了选择语句以及循环语句的使用,与题目集1不同的是,这次还对方法做了要求。同时考察了数组的声明与使用,处理字符串可用到的charAt(),subString(),逻辑运算符|| &&的使用以及闰年的判断。

题目集3难度较高,题量较少,但每道题的工作量都很大,重点考察了定义类和创建对象以及静态变量,私有属性的使用,构造方法构造对象的使用,以及我们对对象和类的总的理解。

(2)设计与分析

pta题目集一7-2

题目名:身体质量指数(BMI)测算

条件:

BMI(身体质量指数)计算方法:体重(以千克为单位)除以身高(以米为单位)的平方

输入格式:

两个数值:体重(以千克为单位),身高(以米为单位),数值间以空格分隔。例如:65.5 1.75。
注意:体重的世界纪录是727公斤,身高的世界纪录是2.72米。输入数据上限不得超过纪录,下限不得小于等于0;

输出格式:

输入数值超出范围 :输出“input out of range”。例如:-2 3或者125 5。
BMI小于18.5 :输出“thin”。
BMI大于等于18.5小于24 :输出“fit”。
BMI大于等于24小于28 :输出“overweight”。
BMII大于等于28 :输出“fat”。

源码

 

分析:该题其实考察的就是if-else判断语句的使用,对BMI可能存在的五种情况进行判断,并对应相应的结果即可。

心得:看清题目要求,不要急于下手,先想好程序的框架,再去动手效率会高很多。

pta题目集一7-5

题目名:去掉重复的字符

条件:

输入一个字符串,输出将其中重复出现的字符去掉后的字符串

输入格式:

一行字符串

输出格式:

去掉重复字符后的字符串

源码:

 

分析:本题要求我输出去掉重复字符的字符串,可String类是不可变的,因此想到采用StringBuffer类或者说StringBuilder类

心得:对于这种处理字符串或者说改变原字符串的问题,一般可采用StringBuffer类或者StringBuilder类。

可改进的地方:源码中我采用了StringBuffer,但其实改成StringBuilder会更好,因为这题并没有涉及到多任务并发访问,在这种情况下,使用StringBuilder会更好,因为StringBuilder比StringBuffer更高效。

pta题目集三7-3

题目名:定义日期类()

条件:

定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。
注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。

要求:Date类结构如下图所示:

类图.jpg

输入格式:

在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。

输出格式:

  • 当输入数据非法及输入日期不存在时,输出“Date Format is Wrong”;
  • 当输入日期合法,输出下一天,格式如下:Next day is:年-月-日

源码:

 

分析:

 

这道题用于输出输入日期的下一天,就要考虑输入日期的几种情况。如果输入日期是每个月的最后一天,那么他的下一天就是month+1,day=1。而如果是12月的最后一天,也就是12月31日,那么他的下一天就为year+1,month=1,day=1;如果不是每个月的最后一天的话,就只需day+1。

基本结构如类图所示,

设计一个名为Date的类,该类中有三个私有属性year,month,day,然后在该类中设计9个方法,其中方法isLeapYear()用于判断是否是闰年(如果某年是闰年的话,那么这个月的2月有29天,这在判断某天的下一天是很重要的,因为正常来讲二月份只有28天,而如果是闰年,就有29天。也就是说,如果不是闰年,那么2月28日的下一天就是3月1日,而如果是闰年,那么2月28日的下一天就是2月29日)。方法checkInputValidity(int,int,int)用于判断输入日期是否合理,而判断输入日期是否合理前,需判断该年是否是闰年。然后就是方法getNextDate(int,int,int),用于得到并输出某天的下一天即可。

pta题目集三7-4

题目名:日期类设计

条件:

参考题目3和日期相关的程序,设计一个类DateUtil,该类有三个私有属性year、month、day(均为整型数),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了创建该类的构造方法、属性的getter及setter方法外,需要编写如下方法:

public boolean checkInputValidity();//检测输入的年、月、日是否合法
public boolean isLeapYear(int year);//判断year是否为闰年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)
public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等
public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数
public String showDate();//以“year-month-day”格式返回日期值
 

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

源码:

import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;

int choice = input.nextInt();

if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

DateUtil date = new DateUtil(year, month, day);

if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}

m = input.nextInt();

if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}

System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

DateUtil date = new DateUtil(year, month, day);

if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}

n = input.nextInt();

if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}

System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());

DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}

class DateUtil{
private int year;
private int month;
private int day;
public DateUtil(int year , int month , int day) {
this.year = year;
this.month = month;
this.day = day;
}
int getYear(){
return year;
}
void setYear(int year){
this.year = year;
}
int getMonth(){
return month;
}
void setMonth(int month){
this.month = month;
}
int getDay(){
return day;
}
void setDay(int day){
this.day = day;
}
public boolean isLeapYear(int year){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)){
return true;
}
else{
return false;
}
}
public boolean checkInputValidity(){
int[] months = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(getYear())){
months[2] = 29;
}
if(getYear() >= 1820 && getYear() <= 2020 && getMonth() >= 1 && getMonth() <= 12 && getDay() >= 1 && getDay() <= months[month]){
return true;
}
else{
return false;
}

}
public DateUtil getNextNDays(int m){
int[] months = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};

for(int i = 0;i < m;i++){
if(isLeapYear(year)){
months[2] = 29;
}
else{
months[2] = 28;
}
if(day == months[month]){
if(month == 12){
year++;
month = 1;
day = 1;
}
else{
month++;
day = 1;
}
}
else{
day++;
}
}
return new DateUtil(year,month,day);
}
public DateUtil getPreviousNDays(int n){
int[] months = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year)){
months[2] = 29;
}
else{
months[2] = 28;
}
for(int j = 0;j < n;j++){
if(day != 1){
day--;
}
else{
if(month == 1){
year--;
if(isLeapYear(year)){
months[2] = 29;
}
else{
months[2] = 28;
}
month = 12;
day = 31;
}
else{
month--;
day = months[month];
}
}
}
return this;

}
public boolean compareDates(DateUtil date){
if(this.year > date.getYear()){
return true;
}
else if(this.year == date.getYear() && month > date.getMonth()){
return true;
}
else if(this.year == date.getYear() && month == date.getMonth() && this.day > date.getDay()){
return true;
}
else{
return false;
}

}
public boolean equalTwoDates(DateUtil date){
if(this.year == date.getYear() && this.month == date.getMonth() && this.day == date.getDay()){
return true;
}
else{
return false;
}
}
public int getDaysofDates(DateUtil date){
int result = 0;
if(equalTwoDates(date)){
result = 0;
}
else{
int[] months = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
if(compareDates(date)){
while(!equalTwoDates(date)){
if(isLeapYear(year)){
months[2] = 29;
}
else{
months[2] = 28;
}
if(day == 1){
if(month == 1){
year--;
month = 12;
day = 31;
}
else{
month--;
day=months[month];
}
}
else{
day--;
}
result++;
}

}
else{
while(!equalTwoDates(date)){
if(isLeapYear(year)){
months[2] = 29;
}
else{
months[2] = 28;
}
if(day == months[month]){
if(month == 12){
year++;
month = 1;
day = 1;
}
else{
month++;
day = 1;
}
}
else{
day++;
}
result++;

}

}
}
return result;
}
public String showDate(){
return year + "-" + month + "-" + day;
}

}

分析:

该题在上一题的要求上要求更深了一步,上一题让我们求某天的下一天,而这道题让我们求某天的下n天和前n天,以及某两天之间相差的天数,但其实是换汤不换药的。求下n天就是在上一题的基础上多一个迭代的情况,就是求下一天的n个迭代,然后求前n天就是求下n天的相反情况。而求两天之间相差的天数,其实就是求下n天或者求前n天的一个逆的过程,两天之间相差的天数想当于前面求前n天或者后n天的n。在这个思路下,其实这道题就比较容易攻克了。

先设计名为DateUtil的类,包括3个私有属性year,month,day。一样的,需要有个判断是否是闰年的方法(isLeapYear(int))以及判断输入日期是否合理的方法(checkInputValidity(int,int,int)),方法getPreviousNDays(int)用于求前n天,方法compareDates(DateUtil)用于比较两天的先后,equalTwoDates(DateUtil)比较两天是否相同。(这在后面可帮助求两天直接相差的天数),getDaysofDates(Dateutil)用于求两天相差的天数。该题的难点就是如何将求后一天的思路升级成求后n天,前n天的思路,以及将求前n天与求后n天的思路应用在求两天相差的天数。这就是在求两天相差天数getDaysofDates(Dateutil)这个方法中的代码类似于getPreviousNDays(int)与getNextNDays(int)中代码相结合的原因。如图

求下n天

-----------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

求前n天

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

求两天相差的天数

 

 

(3)踩坑心得

1.求商运算符/的使用。

/操作符可进行两个整数的运算也可进行两个浮点数的运算,
当两个操作数为整数时其结果必为整数,例如0/2==0,
只要其一个操作数为浮点数,其运算结果必为浮点数。

而在题目集三7-2中,有个求月利率的操作,如图:

正确代码应该是:MonthlyInterestRate= balance * (annualInterestRate / 1200);

而我一开始写的错误代码为:MonthlyInterestRate= balance * annualInterestRate / 1200;  我漏写了这个括号导致无法通过测试点,就是因为/这个运算符的机制。

2.误以为闰年的2月有28天,非闰年的二月有29天,事实是闰年的2月有29天,非闰年的二月为28天。

(4)改进建议

自己的代码书写并不规范,部分代码可读性并不是很强,不够简洁且题目的思路其实可以更加简单一点,这样对代码的要求量也可以随之减少些。可以在代码可读性上在改进一些。例如一些可以用switch case的条件语句就尽量少用if-else语句,一些功能可以以方法的形式进行封装,用的时候直接调用即可,不用一段代码写多次,增强代码的可读性。

另外就是类的设计,要遵守内聚性,不可一个类里面出现不属于自己的属性或方法。

同时,要增加代码的效率,减少代码运行所需的空间与时间,例如跳出循环与否都不影响结果时,尽量跳出循环,提高效率。

(5)总结:

关于StringBuilder与StringBuffer:

二者在用法上区别不大,二者的不同之处在于StringBuilder的效率高于StringBuffer,而当出现多任务并发访问的情况是,使用StringBuffer更为安全。

关于String类:

学到了indexOf(ch),charAt(index),contains(s1),equals(s1),substring(beginIndex)等处理String类的方法

关于类的构建:

应遵守内聚性、一致性、封装性等原则。

类中的方法可以同名但参数必须不同,以实现“一个方法,多个功能”的效果。

若类中存在非一般类数据类型的数组,需要为其申请空间,否则将会出现非法访问的情况。