oop三次大作業總結

霜月之陨發表於2024-04-21

前言:題目涉及知識緊湊,環環相扣,涵蓋了當前所學的知識和一定的課外搜尋,難度逐層遞增,一步步加強難度,循序漸進。
分析與設計:
對於題目的分析
首先是第一次大作業的第一題:
需求設計一個風扇類
設計一個名為Fan的類表示一個風扇。這個類包括:

1.三個名為SlOW、MEDIUM和FAST,其值為1、2和3常量表示風扇的速度。

2.一個名為speed的int型別私有資料域表示風扇的速度(預設值為SLOW)。

3.一個名為on的boolean型別私有資料域表示風扇是否開啟(預設值為false)。

4.一個名為radius的double型別私有資料域表示風扇的半徑(預設值為5)。

5.一個名為color的string型別資料域表示風扇的顏色(預設值為white)。

6.這四個成員變數(資料域)的訪問器和修改器。

7.一個無參構造方法;

8.一個有參構造方法 public Fan(int fanSpeed,boolean fanOn,double fanRadius,String fanColor) { ... },

9.一個名為toString()的方法返回描述風扇的字串。如果風扇是開啟的,那麼該方法在一個組合的字串中返回風扇的速度、顏色和半徑。如果風扇沒有開啟,該方法就會返回一個由"fan is off"和風扇顏色以及半徑組合成的字串。
我的程式碼為import java.util.Scanner;
class Fan {
public static final int SLOW = 1;
public static final int MEDIUM = 2;
public static final int FAST = 3;
private int speed;
private boolean on;
private double radius;
private String color;
public Fan() {
speed = SLOW;
on = false;
radius = 5.0;
color = "white";
}

public Fan(int fanSpeed, boolean fanOn, double fanRadius, String fanColor) {
    speed = fanSpeed;
    on = fanOn;
    radius = fanRadius;
    color = fanColor;
}
public int getSpeed() {
    return speed;
}

public void setSpeed(int speed) {
    this.speed = speed;
}

public boolean isOn() {
    return on;
}

public void setOn(boolean on) {
    this.on = on;
}

public double getRadius() {
    return radius;
}

public void setRadius(double radius) {
    this.radius = radius;
}

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public String toString() {
    if (on) {
        return "speed " + speed + "\ncolor " + color + "\nradius " + radius + "\nfan is on";
    } else {
        return "speed " + speed + "\ncolor " + color + "\nradius " + radius+"\nfan is off" ;
    }
}

}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Fan fan1 = new Fan();
System.out.println("-------\nDefault\n-------");
System.out.println(fan1.toString());
System.out.println("-------\nMy Fan\n-------");
int speed = scanner.nextInt();
boolean on = scanner.nextBoolean();
double radius = scanner.nextDouble();
String color = scanner.next();
Fan fan2 = new Fan(speed, on, radius, color);
System.out.println(fan2.toString());
scanner.close();
}
}
先將fan類寫出來,並在其中編寫出預設的風扇狀態,get(),set()方法得到風扇轉速,開關的狀態,顏色,在寫toString()對輸出的格式進行編寫,並在toString()中根據風扇的開關狀態來輸出對應的格式
main中也建立一個預設的fan輸出,在輸入第二的fan,並輸入對應的風扇狀態就可以了。

**第二題為
1.建立一個類Student,具體屬性和方法如下:
屬性:(全部私有,資料型別自己選擇使用)
姓名(name),性別(sex),學號(studentID),年齡(age),專業(major)
方法:
(1)定義一個空引數構造器public Student();
(2)定義一個多引數的構造器,用於為所有屬性賦值public Student(String name,String sex,String studentID,int age,String major)
(3)由於所有屬性私有的,為所有屬性提供getter()和setter()方法;
(4)public String toString()用於返回學生的所有屬性資訊;
(5)public void printInfo()用於列印學生的資訊
2.定義一個測試類Test,在main方法中建立一個Student物件,根據提示輸入學生資訊儲存在物件中,呼叫printInfo()方法輸出學生資訊。
3.輸出結果參考“輸出樣例”
我的程式碼為
import java.util.Scanner;

class Student {
private String name;
private String sex;
private String studentID;
private int age;
private String major;

public Student() {
}

public Student(String name, String sex, String studentID, int age, String major) {
    this.name = name;
    this.sex = sex;
    this.studentID = studentID;
    this.age = age;
    this.major = major;
}
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getSex() {
    return sex;
}

public void setSex(String sex) {
    this.sex = sex;
}

public String getStudentID() {
    return studentID;
}

public void setStudentID(String studentID) {
    this.studentID = studentID;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getMajor() {
    return major;
}

public void setMajor(String major) {
    this.major = major;
}

public String toString() {
    return "姓名:" + name + ",性別:" + sex + ",學號:" + studentID + ",年齡:" + age + ",專業:" + major;
}

public void printInfo() {
    System.out.println(toString());
}

}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Student student = new Student();
String name = scanner.nextLine();
student.setName(name);
String sex = scanner.nextLine();
student.setSex(sex);
int age = scanner.nextInt();
student.setAge(age);
scanner.nextLine();
String major = scanner.nextLine();
student.setMajor(major);

    String studentID = scanner.nextLine();
    student.setStudentID(studentID);
    student.printInfo();
}

}
根據題目所給的提示編寫出student類,用tostring()編寫出輸出格式並使用printInfo()函式列印出學生資訊;

第三題為
建立學生類,包含

屬性:學號(String)、姓名(String)、語文成績(int)、數學成績(int)、物理成績(int)

方法:計算總分、計算平均分

輸入5個學生的資訊,將每個學生的資訊封裝在一個學生物件中。

按輸入順序依次輸出5個學生的總分、平均分(精確到小數點後兩位,捨去部分按四捨五入規則計入最後一位)。

浮點數保留小數的相關知識可參考:
https://blog.csdn.net/huaishuming/article/details/17752365

注意:未用學生類物件封裝資料的,本題計0分
我的程式碼為
import java.util.Scanner;
class Student {
private String studentNumber;
private String name;
private int chineseScore;
private int mathScore;
private int physicsScore;
public Student(String studentNumber, String name, int chineseScore, int mathScore, int physicsScore) {
this.studentNumber = studentNumber;
this.name = name;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
this.physicsScore = physicsScore;
}
public int calculateTotalScore() {
return chineseScore + mathScore + physicsScore;
}
public double calculateAverageScore() {
return Math.round((calculateTotalScore() / 3.0) * 100.0) / 100.0;
}
public String getStudentInfo() {
return studentNumber + " " + name + " " + calculateTotalScore() + " " + String.format("%.2f", calculateAverageScore());
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Student[] students = new Student[5];
for (int i = 0; i < 5; i++) {
String[] input = scanner.nextLine().split(" ");
String studentNumber = input[0];
String name = input[1];
int chineseScore = Integer.parseInt(input[2]);
int mathScore = Integer.parseInt(input[3]);
int physicsScore = Integer.parseInt(input[4]);
students[i] = new Student(studentNumber, name, chineseScore, mathScore, physicsScore);
}
for (Student student : students) {
System.out.println(student.getStudentInfo());
}
scanner.close();
}
}
根據題目意思,輸入五個學生的資訊並列印出他們的總分和平均分
在student類中定義空的student並用多引數結構輸入學生的資料,利用public int calculateTotalScore(),public double calculateAverageScore(),返回學生的總分和平均分;
在main中創造一個student陣列來儲存五個學生的資訊,利用迴圈結構輸入五個學生的資訊,最後使用迴圈輸出五個學生的資訊;
第四題為設計實現答題程式,模擬一個小型的測試,要求輸入題目資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果。

輸入格式:
程式輸入資訊分三部分:

1、題目數量

格式:整數數值,若超過1位最高位不能為0,

樣例:34

2、題目內容

一行為一道題,可以輸入多行資料。

格式:"#N:"+題號+" "+"#Q:"+題目內容+" "#A:"+標準答案

格式約束:題目的輸入順序與題號不相關,不一定按題號順序從小到大輸入。

樣例:#N:1 #Q:1+1= #A:2

     #N:2 #Q:2+2= #A:4

3、答題資訊

答題資訊按行輸入,每一行為一組答案,每組答案包含第2部分所有題目的解題答案,答案的順序號與題目題號相對應。

格式:"#A:"+答案內容

格式約束:答案數量與第2部分題目的數量相同,答案之間以英文空格分隔。

樣例:#A:2 #A:78

  2是題號為1的題目的答案
  78是題號為2的題目的答案

答題資訊以一行"end"標記結束,"end"之後的資訊忽略。

題目類(Question):首先設計題目類,用於表示單個題目的資訊。題目類包括題號、題目內容和標準答案。提供一個方法用於比較學生的答案與標準答案是否一致。

試卷類(ExamPaper):設計試卷類,用於儲存整套題目的資訊。提供方法用於新增題目到試卷中,並能根據題號獲取對應的題目。

答卷類(AnswerSheet):設計答卷類,用於儲存學生的答題資訊。提供方法用於新增學生的答案,以及對答案進行評分。

實現流程:

讀取題目數量,並逐個讀取題目資訊,建立題目物件並加入試卷類中。
讀取學生的答題資訊,根據題號獲取對應的題目,將學生的答案加入答卷類中。
對答卷類中的學生答案進行評分,對比學生答案與標準答案,記錄評分結果。
根據評分結果輸出學生的每道題目的答題資訊,以及整張試卷的判題結果。

第二次大作業的第一題為
編寫手機類(MobilePhone),含有type(型號,String型別)、price(價格,int型別)屬性,要求該類實現Comparable介面,重寫compareTo方法,實現按照price的大小來確定兩個手機物件的大小關係。

在連結串列中新增三個手機物件(從鍵盤輸入),透過Collections類的sort方法對連結串列中的物件按照price升序排序。輸入第四個手機物件的資訊,並查詢它的price是否與連結串列中某個物件的price相同。

輸入格式:
先輸入三部手機的型號、價格資訊
再輸入要查詢的第四部手機的型號、價格資訊
每部手機資訊的格式如:Redmi9A 599
我的程式碼為import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class MobilePhone implements Comparable {
private String type;
private int price;
public MobilePhone(String type, int price) {
this.type = type;
this.price = price;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int compareTo(MobilePhone other) {
return Integer.compare(this.price, other.price);
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList phoneList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
MobilePhone mobilePhone = new MobilePhone(scanner.next(), scanner.nextInt());
phoneList.add(mobilePhone);
}
System.out.println("排序前,連結串列中的資料:");
for (MobilePhone phone : phoneList) {
System.out.printf("型號:%s,價格:%d\n", phone.getType(), phone.getPrice());
}
Collections.sort(phoneList);
System.out.println("排序後,連結串列中的資料:");
for (MobilePhone phone : phoneList) {
System.out.printf("型號:%s,價格:%d\n", phone.getType(), phone.getPrice());
}
MobilePhone newPhone = new MobilePhone(scanner.next(), scanner.nextInt());
boolean h = false;
for (MobilePhone phone : phoneList) {
if (phone.getPrice() == newPhone.getPrice()) {
h = true;
System.out.printf("%s與連結串列中的%s價格相同\n", newPhone.getType(), phone.getType());
break;
}
}
if (!h) {
System.out.printf("連結串列中的物件,沒有一個與%s價格相同的\n", newPhone.getType());
}
}
}
題目要求該類實現Comparable介面,重寫compareTo方法,實現按照price的大小來確定兩個手機物件的大小關係。,
一個新的知識點,Compareable介面可以實現類中成員屬性的排序方法。透過重寫Compareable介面中的CompareTo方法實現自定義規則的排序。
在該題中可以對手機的價格進行排序,在原有的一些基礎資訊上新增了一個comepareTo()的排序功能,
main類中,先利用迴圈輸入三部手機的基本資訊,後輸入第四步手機的資訊,並遍歷手機陣列查詢是否有手機的價格和第四部手機的價格一樣的,如果有就輸出有,沒有就輸出沒有;

第二題為
按要求完成程式的編寫。
1、定義圓類Circle,其中包括:
(1)成員變數:private int radius
(2)無參構造方法 ,給radius賦值為2,並輸出資訊:"This is a constructor with no para.";
(2)有參構造方法 ,接收使用者給的radius賦值,並輸出"This is a constructor with para."(如果給的半徑小於等於0,則賦預設值為2);
(3)為radius新增set方法,接收使用者輸入的半徑,如果使用者輸入半徑為<=0,則讓半徑的值為2;
(4)為radius半徑新增get方法,返回使用者輸入的半徑;
(5)求圓面積方法getArea(), π使用Math.PI代替;
(6)定義toString方法,public String toString( )方法體為:
return "Circle [radius=" + radius + "]";

2、定義Main類,在main方法中,完成下列操作:
(1)定義並建立Circle類物件c1,輸出c1物件,求c1的面積並輸出;
(2)定義並建立Circle類物件c2,輸出c2物件,求c2的面積並輸出;
(3)從鍵盤接收整數半徑,賦值給c2的半徑,輸出c2物件,求c2的面積並輸出;
(4)從鍵盤接收整數半徑,用有參構造方法建立Circle類物件c3,輸出c3物件,求c3的面積後輸出。
我的程式碼為
import java.util.Scanner;
class Circle {
private int radius;
public Circle() {
this.radius = 2;
System.out.println("This is a constructor with no para.");
}
public Circle(int radius) {
if (radius <= 0) {
this.radius = 2;
} else {
this.radius = radius;
}
System.out.println("This is a constructor with para.");
}
public void setRadius(int radius) {
if (radius <= 0) {
this.radius = 2;
} else {
this.radius = radius;
}
}
public int getRadius() {
return radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
public String toString() {
return "Circle [radius=" + radius + "]";
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Circle c1 = new Circle();
System.out.println(c1);
System.out.printf("%.2f\n", c1.getArea());
Circle c2 = new Circle();
System.out.println(c2);
System.out.printf("%.2f\n", c2.getArea());
int radiusC2 = scanner.nextInt();
c2.setRadius(radiusC2);
System.out.println(c2);
System.out.printf("%.2f\n", c2.getArea());
int radiusC3 = scanner.nextInt();
Circle c3 = new Circle(radiusC3);
System.out.println(c3);
System.out.printf("%.2f\n", c3.getArea());
}
}
先編寫出circle類,和main類,先建立兩個預設半徑為2的圓物件c1和c2,然後分別列印出它們的資訊和麵積。接著透過使用者輸入來設定第二個圓物件c2的半徑,並再次列印出其資訊和麵積。接著又建立了第三個圓物件c3,透過使用者輸入設定其半徑,並列印出c3的資訊和麵積。就此完成對⚪資訊的列印
在circle類中定義了無引數建構函式和有引數建構函式,讓使用者可以創造預設⚪和輸入⚪,並定義了相關資訊;

第三題為
設計一個用來描述汽車的類,使用類的非靜態成員變數來表示汽車的車主姓名、當前的速率和當前方向盤的轉向角度,使用類的非靜態成員方法來表示改變汽車的速率和停車兩個操作。在下圖中的【1】【2】【3】處填入正確程式碼使程式可以正確輸出。

/**

  • @author Teacher
  •     主類,用來在pta中執行。
    
  •     其中有一處程式碼需要完善
    

*/
public class Main {
public static void main(String[] args) {

// 此處填寫合適的程式碼【1】
// 生成汽車例項

System.out.printf("車主:%s,速度:%.1f,角度:%.1f\n", car.getOwnerName(), car.getCurSpeed(), car.getCurDirInDegree());

// 設定新速度
car.changeSpeed(10);
System.out.printf("車主:%s,速度:%.1f,角度:%.1f\n", car.getOwnerName(), car.getCurSpeed(), car.getCurDirInDegree());

// 停車
car.stop();
System.out.printf("車主:%s,速度:%.1f,角度:%.1f\n", car.getOwnerName(), car.getCurSpeed(), car.getCurDirInDegree());

}
}

/**

  • @author Teacher
  •     汽車類,其中有兩個內容需要完善。
    

*/
class Car {
// 車主姓名
private String ownerName;
// 當前車速
private float curSpeed;
// 當前方向盤轉向角度
private float curDirInDegree;

public Car(String ownerName) {
this.ownerName = ownerName;
}

public Car(String ownerName, float speed, float dirInDegree) {
this(ownerName);
this.curSpeed = speed;
this.curDirInDegree = dirInDegree;
}

// 提供對車主姓名的訪問
public String getOwnerName() {
return ownerName;
}

// 提供對當前方向盤轉向角度的訪問
public float getCurDirInDegree() {
return curDirInDegree;
}

// 提供對當前車速的訪問
public float getCurSpeed() {
return curSpeed;
}

// 提供改變當前的車速
public void changeSpeed(float curSpeed) {
// 此處填寫合適的程式碼【2】

}

// 提供停車
public void stop() {
// 此處填寫合適的程式碼【3】

}
}
對於三處的程式碼,我們只需填寫一些簡單的程式碼即可;
在第一處中根據題目列印出的資訊新增Car car=new Car("bob");
第二處為一個改變速度的函式出入一個新的速度來取代原來的速度,所以填寫this.curSpeed=curSpeed;即可
第三處為stop函式,讓車速為0就行,所以設定curSpeed=0;

第四題為
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-1基礎上增補或者修改的內容。

要求輸入題目資訊、試卷資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果。

輸入格式:

程式輸入資訊分三種,三種資訊可能會打亂順序混合輸入:

1、題目資訊

一行為一道題,可輸入多行資料(多道題)。

格式:"#N:"+題目編號+" "+"#Q:"+題目內容+" "#A:"+標準答案

格式約束:

1、題目的輸入順序與題號不相關,不一定按題號順序從小到大輸入。
2、允許題目編號有缺失,例如:所有輸入的題號為1、2、5,缺少其中的3號題。此種情況視為正常。

樣例:#N:1 #Q:1+1= #A:2

     #N:2 #Q:2+2= #A:4

2、試卷資訊

一行為一張試卷,可輸入多行資料(多張卷)。

格式:"#T:"+試卷號+" "+題目編號+"-"+題目分值

 題目編號應與題目資訊中的編號對應。

 一行資訊中可有多項題目編號與分值。

樣例:#T:1 3-5 4-8 5-2

3、答卷資訊

答卷資訊按行輸入,每一行為一張答卷的答案,每組答案包含某個試卷資訊中的題目的解題答案,答案的順序與試卷資訊中的題目順序相對應。

格式:"#S:"+試卷號+" "+"#A:"+答案內容

格式約束:答案數量可以不等於試卷資訊中題目的數量,沒有答案的題目計0分,多餘的答案直接忽略,答案之間以英文空格分隔。

樣例:#S:1 #A:5 #A:22

   1是試卷號 

   5是1號試卷的順序第1題的題目答案

   22是1號試卷的順序第2題的題目答案

答題資訊以一行"end"標記結束,"end"之後的資訊忽略。

需要建立一個題目類來表示每道題目,包括題號、題目內容和標準答案。然後建立一個試卷類來表示每張試卷,包括試卷號和題目編號與分值的對映關係。最後建立一個答卷類來表示每份答卷,包括試卷號和題目的答案。

接下來,設計一個方法來解析輸入的資訊。可以考慮使用字串分割和正規表示式來提取題目資訊、試卷資訊和答卷資訊,並用上述建立的類來儲存這些資訊。

然後,編寫一個判題的方法來根據答卷資訊和試卷資訊來判斷答題結果和得分情況。在判題的過程中,需要根據題目的序號和標準答案來逐個判斷答案是否正確,並計算得分情況。

最後,根據判題的結果,設計一個輸出的方法來輸出試卷總分警示、答卷資訊和判分資訊。在輸出的過程中,需要考慮不同的情況,比如試卷總分不為100分、答卷資訊不完整等情況。

第三次大作業的第一題為
Student類具體要求如下:
私有成員變數:學號(sid,String型別),姓名(name,String型別),年齡(age,int型別),專業(major,String型別) 。
提供無參構造和有參構造方法。(注意:有參構造方法中需要對年齡大小進行判定)
普通成員方法:print(),輸出格式為“學號:6020203100,姓名:王寶強,年齡:21,專業:電腦科學與技術”。
普通成員方法:提供setXxx和getXxx方法。(注意:setAge()方法中需要對年齡進行判定)
注意:
年齡age不大於0,則不進行賦值。
print()中的“:”和“,”為均為中文冒號和逗號。

public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//呼叫無參構造方法,並透過setter方法進行設值
String sid1 = sc.next();
String name1 = sc.next();
int age1 = sc.nextInt();
String major1 = sc.next();
Student student1 = new Student();
student1.setSid(sid1);
student1.setName(name1);
student1.setAge(age1);
student1.setMajor(major1);
//呼叫有參構造方法
String sid2 = sc.next();
String name2 = sc.next();
int age2 = sc.nextInt();
String major2 = sc.next();
Student student2 = new Student(sid2, name2, age2, major2);
//對學生student1和學生student2進行輸出
student1.print();
student2.print();
}
}

/* 請在這裡填寫答案 */

我新增的類為import java.util.Scanner;

class Student{
String sid;
String name;
int age;
String major;
public Student(String sid,String name,int age,String major)
{
this.sid=sid;
this.name=name;
this.age=age;
this.major=major;
}
public Student()
{

}
public String getSid()
{
    return sid;
}
public void setSid(String sid)
{
    this.sid=sid;
}
public String getName()
{
    return name;
}
public void setName(String name)
{
    this.name=name;
}
public int getAge()
{
    return age;
}
public void setAge(int age)
{
    if(age<=0)
    {
        ;
    }
    else{
        this.age=age;
    }
}
public String getMajor()
{
    
    return major;
}
public void setMajor(String major)
{
    
    this.major=major;
}
public String toString()
{
    return "學號:"+sid+",姓名:"+name+",年齡:"+age+",專業:"+major;
}
public void print()
{
    System.out.println(toString());
}

}
即將無參構造和有參構造全部寫出來,並寫一個tostring()規範輸出格式即可;
並在main類中用兩種方法構造兩個學生並列印出他們的資訊;

第二題為給定一個日期,判定是否為合法日期。如果合法,判斷該年是否閏年,該日期是當年第幾天、當月第幾天、當週第幾天、。
給定起始日期與結束日期,判定日期是否合法且結束日期是否早於起始日期。如果均合法,輸出結束日期與起始日期之間的相差的天數、月數、唸書。
輸入格式:
第一行輸入一個日期字串,格式為"YYYY-MM-dd"
第二行輸入兩個日期字串,中間使用空格隔開。分別代表開始日期與結束日期。

輸出格式:
如果第一行日期字串非法,輸出自定義的錯誤資訊。
如果第一行日期有效,輸出相關資訊,如果是閏年要輸出是閏年。
如果第二行兩個日期,只要有一個無效。就輸出相關錯誤資訊。
如果第二行兩個日期有效且結束日期不早於開始日期,輸出相關資訊。

我的程式碼為
import java.util.Scanner;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.Period;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String datee = scanner.nextLine();
String[] parts = datee.split("-");
String date1=scanner.nextLine();
String []part1=date1.split(" ");
String []parts1=part1[0].split("-");
String []parts2=part1[1].split("-");
if(isTruedate(parts[0],parts[1],parts[2]))
{
if(isLeapyear(parts[0]))
{
System.out.println(datee+"是閏年.");
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(datee, formatter);
int dayOfYear = date.getDayOfYear();
int dayOfMonth = date.getDayOfMonth();
int dayOfWeek = date.getDayOfWeek().getValue();

    System.out.println(datee+"是當年第" + dayOfYear + "天,"+"當月第" + dayOfMonth + "天,"+"當週第" + dayOfWeek + "天.");
        if((isTruedate(parts1[0],parts1[1],parts1[2]))&&(isTruedate(parts2[0],parts2[1],parts2[2])))
        {
            int a=Integer.parseInt(parts1[0]);
            int b=Integer.parseInt(parts2[0]);
            int c=Integer.parseInt(parts1[1]);
            int d=Integer.parseInt(parts2[1]);
            int e=b-a;
            int f=d-c;
            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date11 = LocalDate.parse(part1[0], formatter1);
            LocalDate date22 = LocalDate.parse(part1[1], formatter1);
            Period period = Period.between(date11, date22);
             if (date22.isAfter(date11)) {
             long days = Math.abs(date22.toEpochDay() - date11.toEpochDay());
            System.out.println(part1[1] + "與" + part1[0] + "之間相差" + days  + "天,所在月份相差" + f + ",所在年份相差" + e +".");
             }
            else{
                System.out.println(part1[1]+"早於"+part1[0]+",不合法!");
            }
        }
        else{
            System.out.println(part1[0]+"或"+part1[1]+"中有不合法的日期.");
        }
    }
    else{
        System.out.println(datee+"無效!");
        if(isTruedate(parts1[0],parts1[1],parts1[2])&&isTruedate(parts2[0],parts2[1],parts2[2]))
        {
           int a=Integer.parseInt(parts1[0]);
            int b=Integer.parseInt(parts2[0]);
            int c=Integer.parseInt(parts1[1]);
            int d=Integer.parseInt(parts2[1]);
            int e=b-a;
            int f=d-c;
            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date11 = LocalDate.parse(part1[0], formatter1);
            LocalDate date22 = LocalDate.parse(part1[1], formatter1);
            Period period = Period.between(date11, date22);
            if (date22.isAfter(date11)) {
             long days = Math.abs(date22.toEpochDay() - date11.toEpochDay());
            System.out.println(part1[1] + "與" + part1[0] + "之間相差" + days  + "天,所在月份相差" + f + ",所在年份相差" + e +".");
             }
            else{
                System.out.println(part1[1]+"早於"+part1[0]+",不合法!");
            }
        }
        
        else{
            System.out.println(part1[0]+"或"+part1[1]+"中有不合法的日期.");
        }
    }
}
  public static boolean isLeapyear(String year){
    int a=Integer.parseInt(year);
    if(a%400==0||a%4==0&&a%100!=0)
    {
        return true;
    }
    else{
        return false;
    }
}
public static boolean isTruedate(String year, String month, String day) {
int a = Integer.parseInt(year);
int b = Integer.parseInt(month);
int c = Integer.parseInt(day);
int maxday;
if ((b == 1) || (b == 3) || (b == 5) || (b == 7) || (b == 8) || (b == 10) || (b == 12)) {
    maxday = 31;
} else if ((b == 4) || (b == 6) || (b == 9) || (b == 11)) {
    maxday = 30;
} else if (b == 2) {
    if (isLeapyear(year)) {
        maxday = 29;
    } else {
        maxday = 28;
    }
} else {
    return false;
}
if (c >= 1 && c <= maxday) {
    return true;
} else {
    return false;
}

}
}
其中用到了import java.time.LocalDate;
import java.time.format.DateTimeFormatter;來直接求出兩個日期相差的時間差,
並編寫isLeapyear()和isTruedate()函式都輸入的日期進行判斷;在main類中輸入日期,然後判斷合法性;
在又輸入兩個日期判斷合法性和日期上起始日期是否早於截至日期,然後算出兩個日期的相差的打day,month,year;
首先,透過LocalDate.parse方法將日期字串解析為LocalDate型別的物件。
然後,使用Period.between方法計算兩個LocalDate物件之間的時間差,得到一個Period物件。
最後,可以從Period物件中獲取年、月、日的差值,從而得到兩個日期之間的差距。
先將字串日期解析為LocalDate物件,然後使用Period.between方法來計算日期的差距,最後獲取時間差中的年、月、日差值。在程式碼中的兩個日期進行對比時,也是類似的操作。透過解析日期字串為LocalDate物件後,判斷日期的先後關係,並計算差距。

第三題為
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-2基礎上增補或者修改的內容,要求輸入題目資訊、試卷資訊、答題資訊、學生資訊、刪除題目資訊,根據輸入題目資訊中的標準答案判斷答題的結果。

輸入格式:

程式輸入資訊分五種,資訊可能會打亂順序混合輸入。

1、題目資訊
題目資訊為獨行輸入,一行為一道題,多道題可分多行輸入。

格式:"#N:"+題目編號+" "+"#Q:"+題目內容+" "#A:"+標準答案

格式約束:
1、題目的輸入順序與題號不相關,不一定按題號順序從小到大輸入。
2、允許題目編號有缺失,例如:所有輸入的題號為1、2、5,缺少其中的3號題。此種情況視為正常。
樣例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4

2、試卷資訊

試卷資訊為獨行輸入,一行為一張試卷,多張卷可分多行輸入資料。
格式:"#T:"+試卷號+" "+題目編號+"-"+題目分值+" "+題目編號+"-"+題目分值+...

格式約束:
題目編號應與題目資訊中的編號對應。
一行資訊中可有多項題目編號與分值。
樣例:#T:1 3-5 4-8 5-2

3、學生資訊

學生資訊只輸入一行,一行中包括所有學生的資訊,每個學生的資訊包括學號和姓名,格式如下。

格式:"#X:"+學號+" "+姓名+"-"+學號+" "+姓名....+"-"+學號+" "+姓名

格式約束:
答案數量可以不等於試卷資訊中題目的數量,沒有答案的題目計0分,多餘的答案直接忽略,答案之間以英文空格分隔。
樣例:
#S:1 #A:5 #A:22
1是試卷號
5是1號試卷的順序第1題的題目答案
4、答卷資訊

答卷資訊按行輸入,每一行為一張答卷的答案,每組答案包含某個試卷資訊中的題目的解題答案,答案的順序號與試 卷資訊中的題目順序相對應。答卷中:

格式:"#S:"+試卷號+" "+學號+" "+"#A:"+試卷題目的順序號+"-"+答案內容+...

格式約束:
答案數量可以不等於試卷資訊中題目的數量,沒有答案的題目計0分,多餘的答案直接忽略,答案之間以英文空格分隔。
答案內容可以為空,即””。
答案內容中如果首尾有多餘的空格,應去除後再進行判斷。
樣例:
#T:1 1-5 3-2 2-5 6-9 4-10 7-3
#S:1 20201103 #A:2-5 #A:6-4
1是試卷號
20201103是學號
2-5中的2是試卷中順序號,5是試卷第2題的答案,即T中3-2的答案
6-4中的6是試卷中順序號,4是試卷第6題的答案,即T中7-3的答案
注意:不要混淆順序號與題號

5、刪除題目資訊

刪除題目資訊為獨行輸入,每一行為一條刪除資訊,多條刪除資訊可分多行輸入。該資訊用於刪除一道題目資訊,題目被刪除之後,引用該題目的試卷依然有效,但被刪除的題目將以0分計,同時在輸出答案時,題目內容與答案改為一條失效提示,例如:”the question 2 invalid~0”

格式:"#D:N-"+題目號

格式約束:

   題目號與第一項”題目資訊”中的題號相對應,不是試卷中的題目順序號。

   本題暫不考慮刪除的題號不存在的情況。      

樣例:

N:1 #Q:1+1= #A:2

N:2 #Q:2+2= #A:4

T:1 1-5 2-8

X:20201103 Tom-20201104 Jack

S:1 20201103 #A:1-5 #A:2-4

D:N-2

end

輸出
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
答題資訊以一行"end"標記結束,"end"之後的資訊忽略。

一開始,我花了一些時間理清了題目的需求,然後按照輸入輸出的要求,設計了相應的資料結構和邏輯流程。在編寫程式碼的過程中,我遵循了物件導向的設計原則,將題目、試卷和答卷分別抽象成了類,並在類中實現了相應的方法來處理題目資訊和答題邏輯。

在實現過程中,我遇到了一些挑戰。比如,處理輸入輸出的格式要求時,需要仔細考慮每一行的格式和內容,確保能夠正確解析題目和答題資訊。另外,在判斷答案是否正確時,我採用了簡單直觀的邏輯,但也要注意考慮邊界情況和異常處理,以保證程式的穩健性。

採坑心得:
在編寫程式碼的過程中遇到的格式問題,有些格式要求輸入","有些要求輸入",",導致有些時候沒有分清楚輸出格式最後到測試錯誤,利用特殊手段得以發現改進,

在輸出 public static boolean isLeapyear(String year){
int a=Integer.parseInt(year);
if(a%4000||a%40&&a%100!=0)
{
return true;
}
else{
return false;
}
}
public static boolean isTruedate(String year, String month, String day) {
int a = Integer.parseInt(year);
int b = Integer.parseInt(month);
int c = Integer.parseInt(day);
int maxday;
if ((b == 1) || (b == 3) || (b == 5) || (b == 7) || (b == 8) || (b == 10) || (b == 12)) {
maxday = 31;
} else if ((b == 4) || (b == 6) || (b == 9) || (b == 11)) {
maxday = 30;
} else if (b == 2) {
if (isLeapyear(year)) {
maxday = 29;
} else {
maxday = 28;
}
} else {
return false;
}
if (c >= 1 && c <= maxday) {
return true;
} else {
return false;
}中,如果我沒有新增public static他就會在提交的時候顯示返回值為0;十分神奇,原因不詳;
並且這段程式碼在後續的提交中即使可以完美勝任他的任務但是依舊顯示答案錯誤,盡力了;

改進建議:在輸入的過程中十分複雜,也不知如何簡化輸入方式,
還有一些判斷資料型別,不知可否用函式來代替,避免重複的程式碼出現

總結:對於這三次的大作業,有些收穫,也對java程式設計有了更深的認知,在大量的實踐過程中對知識的掌握愈加熟練,在完成了題目的編寫和測試後。
這次作業的完成讓我對Java的語言特性和麵向物件程式設計有了更深入的理解,也在解決問題的過程中鍛鍊了自己的邏輯思維和解決技術難題的能力。未來,我期待能夠在Java程式設計領域不斷成長,不斷挑戰更復雜的專案,為自己的技術提升而努力。我相信,透過持續的學習和實踐,我能夠成為一個優秀的Java開發者,併為解決現實問題貢獻自己的一份力量。

相關文章