1.前言:

本次是第三次对面向对象程序设计题目集的总结分析博客。第一次的Java的作业比较简单,后面两次有些题目开始有点复杂,主要开始涉及到多个类。

2.设计与分析

1.第一次作业:第一次作业主要用到输入输出已经String类型的运用,和if-else或者switch判断的用法。

题目:7-7 判断三角形类型

输入三角形三条边,判断该三角形为什么类型的三角形。

输入格式:

在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。

输出格式:

(1)如果输入数据非法,则输出“Wrong Format”;
(2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”;
(3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”;
(3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”;
(5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”;
(6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”;
(7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。

代码:

import java.util.Scanner;
public class Main
{
    public static void main(String[] args)
    {
        Scanner input=new Scanner(System.in);
        float sideA,sideB,sideC;
        sideA=input.nextFloat();
        sideB=input.nextFloat();
        sideC=input.nextFloat();
        if(sideA<1||sideA>200||sideB<1||sideB>200||sideC<1||sideC>200)
        {
        	System.out.print("Wrong Format");
        }
        else
        {
        	if((sideA+sideB>sideC)&&(sideA+sideC>sideB)&&(sideB+sideC>sideA))
        	{
        		if(sideA==sideB||sideA==sideC||sideB==sideC)
        		{
        			if((sideA==sideB)&&(sideB==sideC))
            			System.out.print("Equilateral triangle");
        			else if(((Math.abs(sideA*sideA+sideB*sideB-sideC*sideC)<0.00001)||Math.abs(sideA*sideA+sideC*sideC
        			    -sideB*sideB)<0.00001)||Math.abs(sideB*sideB+sideC*sideC-sideA*sideA)<0.00001)
        				System.out.print("Isosceles right-angled triangle");
        			else
                		System.out.print("Isosceles triangle");
        		}
        		else
        		{
        			if((sideA*sideA+sideB*sideB==sideC*sideC)||(sideA*sideA+sideC*sideC
            			 ==sideB*sideB)||(sideB*sideB+sideC*sideC==sideA*sideA))
        				System.out.print("Right-angled triangle");
        			else
        				System.out.print("General triangle");
        		}     	    		
        	}
        	else
        		System.out.print("Not a triangle");
        }
    }


}

这里我主要用if-else语句去判断,判断的也比较简单粗暴,所以判断很多,应该还可以在优化下

 

2.第二次作业:第二次作业的难度比第一次要大一点,逐渐开始对类的运用比较多,特别是菜单的那道题,对于习惯用c语言面向过程编程,对于面向对象还是有些不熟悉

7-7 菜单计价程序-1

某饭店提供4种菜,每种菜品的基础价格如下:
西红柿炒蛋 15
清炒土豆丝 12
麻婆豆腐 12
油淋生菜 9

设计点菜计价程序,根据输入的订单,计算并输出总价格。
订单由一条或多条点菜记录组成,每条记录一行,最后以"end"结束
每条点菜记录包含:菜名、份额两个信息。
份额可选项包括:1、2、3,分别代表小、中、大份)

不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格
2。
如果计算出现小数,按四舍五入的规则进行处理。

参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
}

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
}

点菜记录类:保存订单上的一道菜品记录
Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()//计价,计算本条记录的价格
}

订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(String dishName,int portion)
//添加一条菜品信息到订单中。
}

类图:

类的代码:

//菜品类:对应菜谱上一道菜的信息。
class Dish {
	String name;//菜品名称
	int unit_price; //单价
	int getPrice(int portion){//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
		if(portion==1)
			return unit_price;
		else if(portion==2)
			return (int)(unit_price*1.5);
		else 
			return unit_price*2;
	}
}

//菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
class Menu {
	Dish[] dishs;//菜品数组,保存所有菜品信息
	Menu(){
		dishs=new Dish[4];
		for(int i=0;i<4;i++)
			dishs[i]=new Dish();
		dishs[0].name="西红柿炒蛋";
		dishs[0].unit_price=15;
		dishs[1].name="清炒土豆丝";
		dishs[1].unit_price=12;
		dishs[2].name="麻婆豆腐";
		dishs[2].unit_price=12;
		dishs[3].name="油淋生菜";
		dishs[3].unit_price=9;
	}

	Dish searthDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。
		for(Dish dish:dishs) {
			if(dish.name.equals(dishName))
				return dish;
		}
		return null;
	}
}

//点菜记录类:保存订单上的一道菜品记录
class Record {
	Dish d;//菜品
	int portion;//份额(1/2/3代表小/中/大份)
	int getPrice(){//计价,计算本条记录的价格
		return d.getPrice(portion);
	}
}

//订单类:保存用户点的所有菜的信息。
class Order {
	Record[] records;//保存订单上每一道的记录
	
	Order() {
		records=new Record[10];
	}
	int getTotalPrice(){//计算订单的总价
		int sum=0;
		for(Record record:records) {
			// 在for循环中,可以利用“变量类型 变量名称 : 数组名称”的形式,直接把数组元素赋值给该变量
			if (record != null) { // 添加判空条件,避免空指针异常
				sum+=record.getPrice();
			}
		}
		return sum;
	}
	
	Record addARecord(String dishName,int portion) {//添加一条菜品信息到订单中。
		Record record=new Record();
		record.d.name=dishName;
		record.portion=portion;
		return record;
	}
}

  

7-8 jmu-java-日期类的基本使用
  1. 给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当周第几天、。
  2. 给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。

输入格式:

第一行输入一个日期字符串,格式为"YYYY-MM-dd"
第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。

输出格式:

如果第一行日期字符串非法,输出自定义的错误信息。
如果第一行日期有效,输出相关信息,如果是闰年要输出是闰年。
如果第二行两个日期,只要有一个无效。就输出相关错误信息。
如果第二行两个日期有效且结束日期不早于开始日期,输出相关信息。

分析:

对于java时间的处理,可以用java的时间类,比如这道题就算,用的类如下

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;

代码:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
        String dateStr = input.nextLine();
        String rangeStr = input.nextLine();
        //2021-02-28
        if(!dateStr.matches("[0-9]{4}-[0-9]{2}-[0-9]{2}"))
        	 System.out.println(dateStr + "无效!");
        else {
            int year=Integer.parseInt(dateStr.substring(0, 4));
            int month=Integer.parseInt(dateStr.substring(5, 7));
            int day=Integer.parseInt(dateStr.substring(8));
            if (!isValid(year,month,day)) 
                System.out.println(dateStr + "无效!");
            else {

                // 解析日期字符串为LocalDate对象,并获取年、月、日
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); 
                if(isLeapYear(year))
                    System.out.println(dateStr+"是闰年.");
                System.out.println(dateStr+"是当年第"+ date.getDayOfYear()+"天,当月第"+day+"天,当周第"
                    +date.getDayOfWeek().getValue()+"天.");
                }
        }
        String[] dates=rangeStr.split(" ");
        if(!dates[0].matches("[0-9]{4}-[0-9]{2}-[0-9]{2}")||!dates[1].matches("[0-9]{4}-[0-9]{2}-[0-9]{2}"))
        	System.out.println(dates[0] + "或" + dates[1] + "中有不合法的日期.");
        else {
            int year_1 = Integer.parseInt(dates[0].substring(0, 4));
            int month_1 = Integer.parseInt(dates[0].substring(5, 7));
            int day_1 = Integer.parseInt(dates[0].substring(8));
            int year_2 = Integer.parseInt(dates[1].substring(0, 4));
            int month_2 = Integer.parseInt(dates[1].substring(5, 7));
            int day_2 = Integer.parseInt(dates[1].substring(8));
            if(!isValid(year_1,month_1,day_1)||!isValid(year_2,month_2,day_2))
            	System.out.println(dates[0] + "或" + dates[1] + "中有不合法的日期.");
            else {
                LocalDate startDate = LocalDate.parse(dates[0], DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                LocalDate endDate = LocalDate.parse(dates[1], DateTimeFormatter.ofPattern("yyyy-MM-dd"));

                // 判断结束日期是否早于开始日期
                if (endDate.isBefore(startDate)) {
                	System.out.println(dates[1]+"早于"+dates[0]+",不合法!");
                    return;
                }

                long daysDiff = ChronoUnit.DAYS.between(startDate, endDate);
                // 输出日期差
                System.out.println(dates[1]+"与"+dates[0]+"之间相差"+daysDiff+"天,所在月份相差"+
                                   (month_2-month_1)+",所在年份相差"+(year_2-year_1)+".");
        }

      }
       
	}
    public static boolean isValid(int year, int month, int day) {
        // 检查月份是否在有效范围内
        if (month < 1 || month > 12) {
            return false;
        }

        // 检查日期是否在有效范围内
        if (day < 1 || day > 31) {
            return false;
        }

        // 对不同的月份进行特殊处理
        if (month == 2) { // 2月
            // 检查是否为闰年
            boolean isLeapYear = isLeapYear(year);
            if (isLeapYear && day > 29) {
                return false;
            } else if (!isLeapYear && day > 28) {
                return false;
            }
        } else if (month == 4 || month == 6 || month == 9 || month == 11) { // 小月
            if (day > 30) {
                return false;
            }
        }

        return true;
    }
    // 判断年份是否为闰年
    public static boolean isLeapYear(int year) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }
}

 

第三次作业:

7-2 课程成绩统计程序-1

某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。

考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。

考察的总成绩直接等于期末成绩

必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。

1、输入:

包括课程、课程成绩两类信息。

课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。

课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式

课程性质输入项:必修、选修

考核方式输入选项:考试、考察

课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩

课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩

以上信息的相关约束:

1)平时成绩和期末成绩的权重默认为0.3、0.7

2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】

3)学号由8位数字组成

4)姓名不超过10个字符

5)课程名称不超过10个字符

6)不特别输入班级信息,班级号是学号的前6位。

2、输出:

输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。

为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。

1)学生课程总成绩平均分按学号由低到高排序输出

格式:学号+英文空格+姓名+英文空格+总成绩平均分

如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"

2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出

格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分

如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"

3)班级所有课程总成绩平均分按班级由低到高排序输出

格式:班级号+英文空格+总成绩平均分

如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"

异常情况:

1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"

2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"

以上两种情况如果同时出现,按第一种情况输出结果。

3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"

4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"

5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。

信息约束:

1)成绩平均分只取整数部分,小数部分丢弃

参考类图:

这道题情况比较多,有点复杂,我没写出来,这里只能给一些我的思路和设计的类

我用到的类主要有以下这些

class Course{//课程
    String courseName;
    String courseNature;//课程性质,必修或选修 
    String courseAssess;//考核方式
    public Course(String courseName,String courseNature,String courseAssess) {
    	this.courseName=courseName;
    	this.courseNature=courseNature;
    	this.courseAssess=courseAssess;
    }
    
    public boolean isCourse() {
    	if(courseNature.equals("必修")&&!courseAssess.equals("考试")) {
    		System.out.println(courseName+" : course type & access mode mismatch");
    		return false;
    	}
    	else
    		return true;		
    }

}
class Grade{
	//课程成绩
    String num;
    String StudentName;
    String courseName;
    int usualGrades;
    int finalGrades;
    Grade(){
    }
    public Grade(String num,String StudentName,String courseName,int usualGrades, int finalGrades) {
    	this.num=num;
    	this.StudentName=StudentName;
    	this.courseName=courseName;
    	this.usualGrades=usualGrades;
    	this.finalGrades=finalGrades;
    }
    public int getUsualGrade() {
    	return usualGrades;
	}
    public int getFinalGrades() {
    	return finalGrades;
    }
    public int getTotalGrade() {
    	return (int)(usualGrades*0.3+finalGrades*0.7);
	}
}

class ExamGrade extends Grade {//考核成绩
	int examGrade;
	public ExamGrade(){
		examGrade=(int)(usualGrades*0.3+finalGrades*0.7);
	}

}
class ExamineGrades extends Grade{//考察成绩
	int examineGrades;
	ExamineGrades(){
		examineGrades=finalGrades;
	}
}

 

三.心得体会

踩坑心得:一开始写日期的题目,没有了解到java中一些自带的时间类,可以直接用自带的时间类,在计算时间上会方便很多。还有比如判断输入之类。还是日期那道题,就因为判断输入格式不正确,所以有两个测试点没有过,后来用了正则表达式来判断就方便的多。

总结:通过这几次的作业,我开始会用面向对象的思想去解决问题,当然还有些不熟练,这些要通过练习来进步


 posted on 2023-10-07 21:30  djx7022  阅读(44)  评论(0编辑  收藏  举报