第一次博客作业
前言:
第一次大作业:本次大作业有9道题,虽然题目的数量很多,但是可能因为是第一次大作业,题目比较简单,就是最基础的语法之类的简单运用,但是要了解代码的格式和输入输出的区别,其他基本上和C的语法差不多。输入和输出的语句需要自己学习一下。学号的识别考查到了字符串的截取substring的用法,以及单个字符的chatAt的用法,浮点类型如何判断直角。数据的类型需要进行转换,在定义double类型的时候,结果float需要进行强制转换。 还有用到了Math中的pow求一个数的幂次方
第二次大作业:题量一共四题,虽然题量减少,但是代码的复杂度却在增加,对于熟练了写面向过程C的我们,开始写前两题面向对象的题目总是摸不着头脑没有很清楚的思路。这考察了我们如何对类进行设计,并进行类之间的调用,如何将输入的东西存在类的对象里面,怎么将各个类分配自己的功能,将菜单功能设计出来。而第三题考察了我们对java已经写好的类进行调用,对时间的格式限定,对字符串进行切割的spilt的用法。第四题则是考察了调用IO包对程序进行快读的操作。
第三次大作业:这次作业题量也有所增加,7道题目,但我认为就第一题比较难,其他都是考我们对java写好的类进行一下调用就可以了,比如Set,Calendar等等一些类。这些与面向对象没有太大的关系,而第一题则需要设计不同的类,以及对输入的东西进行处理。
第一次大作业设计与分析:
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”。
输入样例1:
在这里给出一组输入。例如:
50 50 50.0
输出样例1:
在这里给出相应的输出。例如:
Equilateral triangle
输入样例2:
在这里给出一组输入。例如:
60.2 60.2 80.56
输出样例2:
在这里给出相应的输出。例如:
Isosceles triangle
输入样例3:
在这里给出一组输入。例如:
0.5 20.5 80
输出样例3:
在这里给出相应的输出。例如:
Wrong Format
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
float triangle_long = input.nextFloat();
float triangle_middle = input.nextFloat();
float triangle_short = input.nextFloat();
float temp ;
if(triangle_long < triangle_middle){
temp = triangle_long;
triangle_long = triangle_middle ;
triangle_middle = temp;
}
if(triangle_long < triangle_short){
temp = triangle_long;
triangle_long = triangle_short;
triangle_short = temp;
}
if(triangle_middle < triangle_short){
temp = triangle_middle;
triangle_middle = triangle_short;
triangle_short = temp;
}
boolean b = (triangle_middle*triangle_middle + triangle_short*triangle_short) - triangle_long*triangle_long < 0.1;
if(triangle_short < 1 || triangle_long > 200 ){
System.out.println("Wrong Format");
} else if ((triangle_short + triangle_middle ) <= triangle_long || (triangle_long - triangle_short) >= triangle_middle) {
System.out.println("Not a triangle");
} else if ( triangle_long == triangle_middle && triangle_middle == triangle_short) {
System.out.println("Equilateral triangle");
} else if (triangle_short == triangle_middle && b ) {
System.out.println("Isosceles right-angled triangle");
} else if (triangle_short == triangle_middle || triangle_long == triangle_middle) {
System.out.println("Isosceles triangle");
} else if (b) {
System.out.println("Right-angled triangle");
}else {
System.out.println("General triangle");
}
}
}
分析:首先对输入三个数据的值,进行大小的判断排序,将第一个triangle_long变成三边中最长的那个数,依次有中间的,最小的数。在判断数据是否合法,让最大的边不超过数据的最大值,最小边不小于数据的最小值。在判断数据是否能够构成等边三角形的时候只需要判断两边之长是否小于最长的边,最长的边减最短的边是否大于中间值。等边三角形三边相等,等腰三角形则是中间的是否等于最大或最小的。
我认为这题最值得重要的是,当判断数据为浮点数类型的时候,对等腰直角三角形的判断那个测试点,因为是计算机语言不能和正常数学计算那样精确判断平方和相等,而是应该判断两者的差距大小小于一个范围从而来判断两者相等,以后在对浮点数的计算结果进行判断的时候应要多考虑到这一点。
但我将判断的条件修改后
boolean b = (triangle_middle*triangle_middle + triangle_short*triangle_short) - triangle_long*triangle_long < 0.1;开始的时候我是将这个直接判断放在if语句中,但是后面觉得代码有些复杂,因此我将这个的结果的正确与否放在了变量b中,当进行判断是否为直接写
7-6 学号识别
学校的学号由8位数字组成,前两位是入学年份(省略了20);第3、4位是学院编号,01代表材料学院,02代表机械学院,03代表外语学院,20代表软件学院;第5、6位是学院内部班级编号,最后两位是班级内部学号。如:18011103,入学年份是2018年,材料学院,11班,03号
输入格式:
8位数字组成的学号。例如:18011103
注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入
输出格式:
学号每一项的完整说明。例如:
入学年份:2018年
学院:材料学院
班级:11
学号:03
注意:如非法输入,输出“Wrong Format"
输入样例:
在这里给出一组输入。例如:
18011103
输出样例:
在这里给出相应的输出。例如:
入学年份:2018年
学院:材料学院
班级:11
学号:03
输入样例1:
在这里给出一组输入。例如:
18013
输出样例1:
在这里给出相应的输出。例如:
Wrong Format
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String str = input.next();
char [] arr = new char[8] ;
if(str.length() != 8){
System.out.println("Wrong Format");
}else{
for (int i = 0; i < str.length(); i++) {
arr[i] = str.charAt(i);
}
if(arr[2] == '0' && arr[3] == '1'){
System.out.println("入学年份:" + 20 + arr[0] + arr[1] + "年");
System.out.println("学院:" + "材料学院");
System.out.println("班级:" + arr[4] + arr[5]);
System.out.println("学号:" + arr[6] + arr[7]);
} else if (arr[2] == '0' && arr[3] == '2') {
System.out.println("入学年份:" + 20 + arr[0] + arr[1] + "年");
System.out.println("学院:" + "机械学院");
System.out.println("班级:" + arr[4] + arr[5]);
System.out.println("学号:" + arr[6] + arr[7]);
} else if (arr[2] == '0' && arr[3] == '3') {
System.out.println("入学年份:" + 20 + arr[0] + arr[1] + "年");
System.out.println("学院:" + "外语学院");
System.out.println("班级:" + arr[4] + arr[5]);
System.out.println("学号:" + arr[6] + arr[7]);
} else if (arr[2] == '2' && arr[3] == '0') {
System.out.println("入学年份:" + 20 + arr[0] + arr[1] + "年");
System.out.println("学院:" + "软件学院");
System.out.println("班级:" + arr[4] + arr[5]);
System.out.println("学号:" + arr[6] + arr[7]);
} else{
System.out.println("Wrong Format");
}
}
}
}
这道题考察了一个新的知识点就是一个字符串可以通过chatAt进行提取不同位置上的一个字符,但是现在我认为这题可以用substring进行相应的截取更加的好。substring是一位置包含前面不包含后面的一个截取方式。同时在相应的数字上对应输出的东西。
在一个字符串中提取出其中的二进制数值序列,。
输入格式:
一个由0、1构成的序列,以-1为结束符,非0、1字符视为正常输入,但忽略不计,未包含结束符的序列视为非法输入。例如:abc00aj014421-1
输出格式:
将输入的序列去掉非0、1字符以及结尾符的数据内容,
注:结束符-1之后的0\1字符忽略不计。
例如:00011。
输入样例:
在这里给出一组输入。例如:
abc00aj014421-1
输出样例:
在这里给出相应的输出。例如:
00011
输入样例1:
在这里给出一组输入。例如:
a0571-1k001y
输出样例1:
在这里给出相应的输出。例如:
01
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String str1 = input.nextLine();
String str2 = "";
int count = 0;
for (int i = 0; i < str1.length(); i++) {
if(str1.charAt(i) == '-' && str1.charAt(i+1) == '1'){
count = 1;
break;
}else{
if(str1.charAt(i) == '1' || str1.charAt(i) == '0'){
str2 += str1.charAt(i);
}
}
}
if (count == 0){
System.out.println("Wrong Format");
}else {
System.out.println(str2);
}
}
}
分析:将输入的一串字符串进行分割成一个字符,并且判断是否符合要求,如果符合要求的话就将字符加在字符串中。
这道题主要是字符串的拼接问题,刚开始我不知道如何将符合要求的字符连接起来,而是直接加上,那样就不是符合要求的东西了。因此需要定义一个像str2一样的空字符串。然后进行字符之间的加法。
开始没有把字符的输入方式改成nextline导致无法接受空格和转义字符。
长度、质量的计量有多重不同的计算体系,有标准的国际单位制:千克与米,也有各个国家自己的计量方法如:磅、英寸;1磅等于0.45359237千克,1英寸等于0.0254米,请编写程序实现国际单位制与英制之间的换算。
输入格式:
两个浮点数,以空格分隔,第一个是质量(以千克为单位)、第二个是长度(以米为单位)。例如:0.45359237 0.0254。
输出格式:
两个浮点数,以空格分隔,第一个是质量(以磅为单位)、第二个是长度(以英寸为单位)。例如:1.0 1.0。
输入样例:
在这里给出一组输入。例如:
0.45359237 0.0254
输出样例:
在这里给出相应的输出。例如:
1.0 1.0
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
float quality = input.nextFloat();
float length = input.nextFloat();
quality /= 0.45359237;
length /= 0.0254;
System.out.println(quality + " " + length);
}
}
分析:输入两个浮点型的数据,除以相应的数字变成新的数字。
但是开始的时候我将变量类型定义为double,需要强制转换,否则无法过测试点。
长度、质量的计量有多重不同的计算体系,有标准的国际单位制:千克与米,也有各个国家自己的计量方法如:磅、英寸;1磅等于0.45359237千克,1英寸等于0.0254米,请编写程序实现国际单位制与英制之间的换算。
输入格式:
两个浮点数,以空格分隔,第一个是质量(以千克为单位)、第二个是长度(以米为单位)。例如:0.45359237 0.0254。
输出格式:
两个浮点数,以空格分隔,第一个是质量(以磅为单位)、第二个是长度(以英寸为单位)。例如:1.0 1.0。
输入样例:
在这里给出一组输入。例如:
0.45359237 0.0254
输出样例:
在这里给出相应的输出。例如:
1.0 1.0
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
float quality = input.nextFloat();
float length = input.nextFloat();
quality /= 0.45359237;
length /= 0.0254;
System.out.println(quality + " " + length);
}
}
这题最主要的是数据的强制转换,数据的输入,也比较常规
计算一个数列中所有奇数的和。
输入格式:
十个整数,以空格分隔。例如:1 2 3 4 5 6 7 8 9 0。
输出格式:
输入数列中所有奇数之和。例如:25。
输入样例:
在这里给出一组输入。例如:
1 2 3 4 5 6 7 8 9 0
输出样例:
在这里给出相应的输出。例如:
25
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int [] arr = new int[10];
Scanner input = new Scanner(System.in);
int sum = 0;
for (int i = 0 ; i < arr.length ; i++ ){
arr[i] = input.nextInt();
}
for (int j = 0 ; j < arr.length ; j++ ) {
if (arr[j] % 2 != 0) sum += arr[j];
}
System.out.println(sum);
}
}
手动输入数据需要调用Scanner类。
房屋交易在日常生活中非常常见的事情,房屋交易时要额外支付各种税费,按2022年房产交易新政策的规定买房人应缴纳税费包括:
1、契税:首次购房评估额90平(含)内1%、90平-144平(含)内1.5%,超过144平或非首 次3%,买方缴纳。
2、印花税:房款的0.05%。
3、交易费:3元/平方米。
4、测绘费:1.36元/平方米。
5、权属登记费及取证费:一般情况是在200元内。
输入格式:
四个数据,以空格分隔:
1、第几次购房(整数)
2、房款(整数/单位万元)
3、评估价(整数/单位万元)
4、房屋面积(浮点数/单位平方米)。
例如:1 100 100 90。
输出格式:
契税、印花税、交易费、测绘费(以元为单位),以空格分隔。例如:10000.0 500.0 270.0 122.4
输入样例:
在这里给出一组输入。例如:
1 100 100 90
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int count = input.nextInt();
int house_payment = input.nextInt();
int evaluation_price = input.nextInt();
double area = input.nextDouble();
double deed = 0;
if(count == 1){
if( area <= 90){
deed = evaluation_price * 10000 * 0.01 ;
} else if (area > 90 && area <= 144) {
deed = evaluation_price * 10000 * 0.015;
} else if (area > 144) {
deed = evaluation_price * 10000 * 0.03;
}
}else if (count > 1){
deed = evaluation_price * 10000 * 0.03 ;
}
double stamp_duty = house_payment * 0.05 * 100 ;
double transaction_fees = 3 * area ;
double t = 1.36 * area ;
System.out.println((float)deed + " " + (float)stamp_duty + " " + (float)transaction_fees + " " + (float)t);
}
}
数据的初始化,if-else 进行不同条件的判断。 接收入第几次购房(整数),房款(整数/单位万元),评估价(整数/单位万元),房屋面积(浮点数/单位平方米),然后分别计算契税、印花税、交易费、测绘费然后输出。注意精度转化,输入为int型,输出为double型即可。
第一次大作业踩坑心得:
1. 有些题目需要进行强制转换,而老师题目中没表面清楚,导致卡了很久
2.这是因为开始输入的代码中的next遇到空格后就输入结束了。而nextline可以接受空格和转义字符。
3. 因为输入的数据为double类型会发生计算精度丢失,当我算计是否是直角三角形的时候两边的平方和等于第三边的平方,计算值可能会有很小的误差,导致正确无法判断是否是直角三角形,导致有一个测试点一直过不了。以后只有整形才用等号判断直接三角形。浮点类型用差值小于一个数进行比较。
4. 开始在判断是否为三角形的时候,我写成两短边相加大于等于第三边,则三角形就是成立的。后面发现等于是不能构成三角形的。
5. 注意输出的时候格式记得与题目所给的格式一致。
6. 在定义if-else语句的时候一定要完整,包含每个情况,不遗漏对边界值测试的考虑。
7. 字符串是否相等的比较用equals而不是==号。
第二次大作业设计与分析:
某饭店提供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)
//添加一条菜品信息到订单中。
}
输入格式:
每条点菜记录的格式:
菜名+空格(英文)+份额
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
最后一条记录以“end”结束。
输出格式:
订单上所有菜品的总价(整数数值),每份菜
如果订单中包含不能识别的菜名,则在总价之前输出“** does not exist”,**是不能识别的菜名
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 2
西红柿炒蛋 3
end
输出样例:
在这里给出相应的输出。例如:
48
输入样例1:
订单中包含不存在的菜品记录。例如:
麻婆豆腐 2
炒脆肚 2
西红柿炒蛋 3
end
输出样例1:
在这里给出相应的输出。例如:
炒脆肚 does not exist
48
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Dish dish1 = new Dish("西红柿炒蛋",15);
Dish dish2 = new Dish("清炒土豆丝",12);
Dish dish3 = new Dish("麻婆豆腐",12);
Dish dish4 = new Dish("油淋生菜",9);
Dish[] dishes = {dish1,dish2,dish3,dish4};
Menu menu = new Menu();
menu.dish = dishes;
Scanner input = new Scanner(System.in);
Order order = new Order();
Record[] records_1 = new Record[10];
int index = 0;
while (true){
String name = input.next();
if(name.equals("end")){
break;
}else {
int portion = input.nextInt();
records_1[index] = order.addARecord(name,portion);
if(menu.searthDish(name) == null){
System.out.println(name + " does not exist");
}else{
records_1[index].d = menu.searthDish(name);
}
}
index++;
}
order.records = records_1;
int sum = 0;
sum += order.getTotalPrice();
System.out.println(sum);
}
}
class Dish {
String name ;
int unit_price;
int getUnit_price;
public Dish(String name,int unit_price) {
this.name = name;
this.unit_price =unit_price;
}
public Dish() {
}
}
class Menu {
Dish[] dish ;
public Dish searthDish(String dishName){
for (int i = 0; i < dish.length; i++) {
if (dish[i].name.equals(dishName)){
return dish[i];
}
}
return null;
}
}
class Order {
Record[] records;
public int getTotalPrice(){
Record a ;
int sum = 0;
for (int i = 0;records[i]!=null; i++) {
a = records[i];
sum += a.getPrice(records[i].portion);
}
return sum;
}
public Record addARecord(String dishName,int portion){
Record record = new Record();
record.d.name = dishName;
record.portion = portion;
return record;
}
}
class Record {
Dish d = new Dish();
int portion;
public int getPrice(int portion){
int getUnit_price = 0;
if(portion == 1){
getUnit_price = d.unit_price;
}else if(portion == 2){
double x = d.unit_price*1.5;
getUnit_price =(int) Math.round (x);
} else if (portion == 3) {
getUnit_price = d.unit_price*2;
}
return getUnit_price;
}
}
分析:定义了五个类,Dish类用来记录菜品的名字,基础价,根据份数,获取点菜菜品的价格,类里有俩个构造函数,一个是含有带参数的,一个是不带参数的。在主函数手动输入菜品。Menu类中有一个Dish类中的数组对象,调用Dish类,可以进行菜单中的菜品添加。Menu类中有一个searthDish的方法,方法里传入需要查找的菜品名字,在类中的dish数组中进行查找,如果查找到了,返回菜品对应的dish对象,如果数组中没有找到该菜品,则返回null的对象。Record类中,开辟一个Dish的对象,然后份额求价钱,Order类中有Record类的对象数组,有计算总价,添加记录的方法。Main类中开辟了Menu,Order类的对象,并将该对象类中东西进行赋值。
开始没有考察对异常菜名的考虑,没有将Main函数中的record数组存入一个数据就赋值给Order中的record的数组。
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:点菜记录和删除信息。每一类信息都可包含一条或多条记录,每条记录一行。
点菜记录包含:序号、菜名、份额、份数。
份额可选项包括:1、2、3,分别代表小、中、大份。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格2。
如果计算出现小数,按四舍五入的规则进行处理。
参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号\
Dish d;//菜品\
int portion;//份额(1/2/3代表小/中/大份)\
int getPrice()//计价,计算本条记录的价格\
}
订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
输入格式:
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:
序号+英文空格+菜名+英文空格+份额+英文空格+份数
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
最后一条记录以“end”结束。
输出格式:
按顺序输出每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。
如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后输出订单上所有菜品的总价(整数数值),
本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的下一次作业中会做要求。
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
63
输入样例1:
订单中包含删除记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
27
输入样例2:
订单中包含不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
end
输出样例2:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
63
输入样例3:
订单中包含删除信息以及不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 delete
7 delete
end
输出样例3:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
27
输入样例4:
订单中包含删除信息以及不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
end
输出样例4:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
63
import java.util.Scanner;
/*
输入:输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
处理:判断订单上的菜品,菜单上是否含有,有的话存入records类中
输出:输出不合适的信息,删除错误的信息,菜单,菜品的价格,总花费
*/
public class Main {
public static void main(String[] args) {
Menu menu = new Menu();
Dish[] dishes = new Dish[10];
Scanner input = new Scanner(System.in);
int index = 0;
String sc = input.nextLine();
String[] arr = sc.split(" ");
String name1 = arr[0];
int price = Integer.parseInt(arr[1]);
while (true){
menu.dish = dishes;
dishes[index] = menu.addDish(name1,price );
sc = input.nextLine();
arr = sc.split(" ");
name1 = arr[0];
if (arr[0].equals("end")) {
System.out.println(0);
return;
}
if(arr[1].equals("delete")) break;
if (arr.length == 4 ) break;
price = Integer.parseInt(arr[1]);
index++;
}
Order order = new Order();
Record[] records_1 = new Record[10];
int order_num = Integer.parseInt(arr[0]);
String name2= arr[1];
int portion = Integer.parseInt(arr[2]);
int num = Integer.parseInt(arr[3]);
int index_1 = 0;
int flag = 0;
if (menu.searthDish(name2) != null ){
records_1[index_1] = order.addARecord(order_num, name2, portion, num);
records_1[index_1].d = menu.searthDish(name2);
System.out.println(records_1[index_1].orderNum + " " + records_1[index_1].d.name + " " + records_1[index_1].getPrice(records_1[index_1].portion,records_1[index_1].num));
index_1++;
flag = 1 ;
}
Record[] records = new Record[10];
int t = 0;
while (!arr[0].equals("end")){
order.records = records_1;
if(arr.length == 4){
order_num = Integer.parseInt(arr[0]);
name2 = arr[1];
portion = Integer.parseInt(arr[2]);
num = Integer.parseInt(arr[3]);
if (menu.searthDish(name2) == null ) System.out.println(name2 + " does not exist");
else if(flag == 0){
records_1[index_1] = order.addARecord(order_num, name2, portion, num);
records_1[index_1].d = menu.searthDish(name2);
System.out.println(order.records[index_1].orderNum + " " + order.records[index_1].d.name + " " + order.records[index_1].getPrice(order.records[index_1].portion,order.records[index_1].num));
index_1++;
}
}
else{
order_num = Integer.parseInt(arr[0]);
if(!order.delARecordByOrderNum(order_num)) System.out.println("delete error;");
else{
records[t++] = order.findRecordByNum(order_num);
}
}
sc = input.nextLine();
arr = sc.split(" ");
flag = 0;
}
int sum1 = 0;
for (int i = 0; i < t; i++) {
sum1 += records[i].getPrice(records[i].portion,records[i].num);
}
int sum = 0;
sum += order.getTotalPrice();
System.out.println(sum - sum1);
}
}
class Menu {
Dish[] dish;//菜品数组,保存所有菜品信息
public Dish searthDish(String dishName){
for (int i = 0; dish[i] != null; i++) {
if (dish[i].name.equals(dishName)){
return dish[i];
}
}
return null;
}//根据菜名在菜谱中查找菜品信息,返回Dish对象。
public Dish addDish(String dishName,int unit_price){
for (int i = 0; dish[i]!=null; i++) {
if(dish[i].name.equals(dishName)){
dish[i].unit_price = unit_price;
}
}
Dish dish = new Dish();
dish.name = dishName;
dish.unit_price = unit_price;
return dish;
}//添加一道菜品信息
}
class Dish {
String name ;
int unit_price;
}
class Record {
Dish d = new Dish();//菜品\
int orderNum;//序号\
int portion;//份额(1/2/3代表小/中/大份)
int num ; //份数(1,2,3)
public int getPrice(int portion,int num){
int getUnit_price = 0;
if(portion == 1){
getUnit_price = d.unit_price;
}else if(portion == 2){
double x = d.unit_price*1.5;
getUnit_price =(int) Math.round (x);
} else if (portion == 3) {
getUnit_price = d.unit_price*2;
}
getUnit_price = getUnit_price * num;
return getUnit_price;
}
}
class Order {
Record[] records;//保存订单上每一道的记录
public int getTotalPrice() {
Record a;
int sum = 0;
for (int i = 0; records[i] != null; i++) {
a = records[i];
sum += a.getPrice(records[i].portion,records[i].num);
}
return sum;
}
public Record addARecord(int orderNum,String dishName,int portion,int num){
Record record = new Record();
record.orderNum = orderNum;
record.num = num;
record.d.name = dishName;
record.portion = portion;
return record;
}//添加一条菜品信息到订单中。
public boolean delARecordByOrderNum(int orderNum){
for (int i = 0; records[i] != null; i++) {
if (records[i].orderNum == orderNum){
return true;
}
}
return false;
}
public Record findRecordByNum(int orderNum){
for (int i = 0; records[i]!=null; i++) {
if (records[i].orderNum == orderNum){
return records[i];
}
}
return null;
}//根据序号查找一条记录
}
由于两题都是菜单,都是关于类的设计,因此大概思路还是差不多的。但是这题我们需要对输入信息进行一定的处理,根据输入的字符串的长度大小。判断是对菜单里的菜品进行输入,还是用户进行点菜记录的输入。以及什么是对输入进行结束的标志。Menu中比上面那题多了一个对菜品记录的添加。因为题目中还增加了一个需求,还要对点菜菜品的删除,删除这个点菜菜品的记录,在Order类中添加了,查找菜品的记录,以及对菜品记录进行删除。查找的功能,如果找到记录,则返回菜品的Record,如果没有找到则返回null,在删除的方法中,返回Boolean类型的值,判断是否删除。最后总价的计算,用记录中的值减去删除记录里的值。
这道题卡了好久这个对异常菜名的删除,该过好多的代码,但是依然无法通过。最好经过室友的点拨和提醒,我明白这道题需要在键盘中输入一个数据的时候,我们需要立马对这个进行一个反馈,而不是将要输入的东西,全部存储起来留在最后一起输出。刚开始的时候我觉得自己的测试点和题目几乎都一样,但是得了0分。这主要是自己输入格式的错误。
- 给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当周第几天、。
- 给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。
输入格式:
第一行输入一个日期字符串,格式为"YYYY-MM-dd"
第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。
输出格式:
如果第一行日期字符串非法,输出自定义的错误信息。
如果第一行日期有效,输出相关信息,如果是闰年要输出是闰年。
如果第二行两个日期,只要有一个无效。就输出相关错误信息。
如果第二行两个日期有效且结束日期不早于开始日期,输出相关信息。
输入样例1:
第一行日期非法、第二行有日期非法
2020-02-30
2020-02-30 2020-01-02
输出样例1:
2020-02-30无效!
2020-02-30或2020-01-02中有不合法的日期.
输入样例2:
均有效且合法
2021-02-28
2019-08-01 2020-01-02
输出样例2:
2021-02-28是当年第59天,当月第28天,当周第7天.
2020-01-02与2019-08-01之间相差154天,所在月份相差-7,所在年份相差1.
输入样例3:
日期均有效,但结束日期早于开始日期
2020-02-28
2020-02-02 2020-02-01
输出样例3:
2020-02-28是闰年.
2020-02-28是当年第59天,当月第28天,当周第5天.
2020-02-01早于2020-02-02,不合法!
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class Main {
/*
输入:输入三个日期,年份,月份,日。
处理:将字符串日期去格式化,得到对应的整数。给定一个日期,判定是否为合法日期
给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。
如果第二行两个日期,只要有一个无效。就输出相关错误信息。
如果第二行两个日期有效且结束日期不早于开始日期,输出相
输出:输出第一个年是否闰年,该日期是当年第几天、当月第几天、当周第几天,如果均合法,输出结束日期与起始日期之间的相差的天数、月数。
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String s1 = input.next(); //输入日期 格式为2020-3/-1
String[] arr1 = s1.split("-"); // 以-为分隔符,提取年月日
int y1 = Integer.parseInt(arr1[0]); //转换为int型
int m1 = Integer.parseInt(arr1[1]);
int d1 = Integer.parseInt(arr1[2]);
dataJudge rq1 = new dataJudge(y1, m1, d1);
if (rq1.Judge(y1, m1, d1) && s1.length() == 10) {
boolean t = isLeapYear(rq1.year);
if (t) System.out.println(s1 + "是闰年.");
if (fun(y1, m1, d1) != -1) {
System.out.println(s1 + "是当年第" + fun(y1, m1, d1) + "天,当月第" + d1 + "天," + getWeekOfDate(s1));
}
} else
System.out.println(s1 + "无效!");
String s2 = input.next();
String s3 = input.next();
String[] arr2 = s2.split("-");
String[] arr3 = s3.split("-");
int y2 = Integer.parseInt(arr2[0]);
int m2 = Integer.parseInt(arr2[1]);
int d2 = Integer.parseInt(arr2[2]);
int y3 = Integer.parseInt(arr3[0]);
int m3 = Integer.parseInt(arr3[1]);
int d3 = Integer.parseInt(arr3[2]);
dataJudge rq2 = new dataJudge(y2, m2, d2);
dataJudge rq3 = new dataJudge(y3, m3, d3);
// 判断后面俩个日期的有效性
if (rq2.Judge(y2, m2, d2) && rq3.Judge(y3, m3, d3)&& s2.length() == 10 && s3.length()== 10) {
if (y2 > y3 ) {
System.out.println(s3+ "早于" + s2 + ",不合法!");
} else if (y2 == y3 && m2 > m3) {
System.out.println(s3 + "早于" + s2 + ",不合法!");
} else if (y2 == y3 && m2 == m3 && d2 > d3) {
System.out.println(s3 + "早于" + s2 + ",不合法!");
} else {
int diffMonth = diffMonth(m2, m3);
int diffYear = diffYear(y2, y3);
int diffDays = diffDays(y2, m2, d2, y3, m3, d3);
System.out.println(s3 + "与" + s2 + "之间相差" + diffDays + "天,所在月份相差" + diffMonth + ",所在年份相差" + diffYear + ".");
}
} else System.out.println(s2 + "或" + s3 + "中有不合法的日期.");
}
// 是否为闰年的判定
public static boolean isLeapYear(int year) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
return true;
}
return false;
}
//计算日期是当年的第几天
public static int fun(int year, int month, int day) {
int res = 0;
int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (isLeapYear(year))
days[2] = 29;
if (days[month] < day)
return -1;
for (int i = 0; i < month; i++) {
res += days[i];
}
return res + day;
}
public static String getWeekOfDate(String s1) {
String[] weekDays = {"当周第7天.", "当周第1天.", "当周第2天.", "当周第3天.", "当周第4天.", "当周第5天.", "当周第6天."};
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance(); // 获得一个日历
Date datet;
try {
datet = f.parse(s1);
cal.setTime(datet);
} catch (ParseException e) {
e.printStackTrace();
}
int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
if (w < 0)
w = 0;
return weekDays[w];
}
public static int diffMonth(int month1, int month2) {
return month2 - month1;
}
public static int diffYear(int year1, int year2) {
return year2 - year1;
}
public static int diffDays(int year2, int month2, int day2, int year3, int month3, int day3) {
int d_Days = 0;
for (int i = year2; i < year3; i++) {
if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0) {
d_Days += 366;
} else d_Days += 365;
}
d_Days += fun(year3,month3,day3) - fun(year2,month2,day2);
return d_Days;
}
}
class dataJudge {
int year ; //初始化日期
int month1 ;
int day ;
int[] monthBig = new int[] {1, 3, 5, 7,8, 10, 12}; //大月
int k = 0; //判断大小月
// public String print() {
// if(month1 < 10){
// if (day < 10) return year + "-0" + month1 + "-0" + day;
// else return year + "-0" + month1 + "-" + day;
// }
// else {
// if(day < 10) return year + "-" + month1 + "-0" + day;
// else return year + "-" + month1 + "-" + day;
// }
// }
//判断日期转换前后是否一致
public boolean Judge(int year, int month, int day) {
if (this.year == year && this.month1 == month && this.day == day && year !=0 && month!= 0 && day !=0)
return true;
else{
this.year = year;
this.day = day;
return false;
}
}
//将日期转为合法日期
public dataJudge(int year, int month, int day) {
if(year > 0 && year < 3000) { //年份在1-2999
this.year = year;
if(month > 0 && month < 13) //月份在1-12
this.month1 = month;
for(int i = 0; i < monthBig.length; i++) //判断是否为大月
if(month == monthBig[i]) {
k = 1;
break;
}
if(k == 1 && day > 0 && day < 32) //大月
this.day = day;
else if(k == 0 && month != 2 && day > 0 && day < 31) //小月
this.day = day;
else if(year % 400 == 0 || year % 4 == 0 && year % 100 != 0) {
if(day > 0 && day < 30) //闰年2月
this.day = day;
}
else if(day > 0 && day < 29) //平年2月
this.day = day;
}
}
}
这道题就用了两个大类,Judge中定义了俩个方法,Judge判断了数据的合理性,然后dataJudge将合理的数据进行分割,在进行大月和小月天数的计算。Main类中定义了判断是否为闰年的isLeapYear方法,fun计算日期是当年的第几天,getWeekofDate 计算是星期几,后面三个方法分别计算两个时间相差的年,月,日。而getWeekOfdate中调用了时间的类,对特殊格式的处理,并且定义了星期几的数组,可以返回。而里面的一个异常方法可以通过try catch进行解决。
本题定义了两个大类,类中有许多的方法,dataJudge类中的Judge的方法主要是对输入数据是否合理进行一个判断,dataJudge合理的话分割出年月日等信息。Main类中有判断闰年和计算相差天数,月份,年数。这题中最重要的是getWeekOfDate,这里面调用了时间类来进行时间的判断。并且在处理异常的时候用try和catch进行解决异常。但是在后面一次的时候,发现这个很浪费时间。可以用LOcalDate解决。
从A点到B点有n个格子,小明现在要从A点到B点,小明吃了些东西,补充了一下体力,他可以一步迈一个格子,也可以一步迈两个格子,也可以一步迈3个格子,也可以一步迈4个格子。请编写程序计算小明从A点到B点一共有多少种走法。
输入格式:
输入包含多组数据,第一行为一个整数m,m不超过10000,表示输入数据组数。接下来m行,每行为一个整数n(保证对应的输出结果小于231),表示从A点到B点的格子数。
输出格式:
输出为m个整数,表示对于每组数据小明从A点到B点的走法数。
输入样例:
2
5
3
输出样例:
15
4
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) throws IOException {//使用IO包中的类需要throws IOException
/*输入:第一行输入一个整数count,接下来count行,每行为一个整数n,表示从A点到B点的格子数
处理:前几个进行列举法,知道0,1,2,3,4各自的走法数分别为1,1,2,4,8.第5个走法为:15,第6个的走法为29。可以发现第i个数据,为i前面4个走法之和。
导入一个人IO包进行快速输入。StreamTokenizer 类中 有个方法 nval 这个方法就是我们读取数据的方法,他默认是double类型的,(int)进行强制转换
输出:依次输出输入格子数对应的走法
*/
StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
input.nextToken();
int count = (int)input.nval;
int[] a = new int[10000];
long[] b = new long[10000];
// b[0] = 1; // 为了后面可以找到规律假设的一个数据
b[1] = 1;
b[2] = 2;
b[3] = 4;
b[4] = 8;
int max = 0;
for (int i = 0; i < count; i++) {
input.nextToken();
a[i] = (int) input.nval;
if(a[i] > max) max= a[i];
}
for (int i = 5; i <= max; i++) b[i] = b[i - 1] + b[i - 2] + b[i - 3] + b[i - 4];
for (int i = 0; i < count; i++) {
System.out.println(b[a[i]]);
}
}
}
这个题目并不像前面三道题一样考虑类的设计,直接用面向过程的语言就可以解决了,但这题的难点就是要善于发现规律,后面的数字和前面的数字有什么关系。并且需要导入IO包进行快速的读取输入,不然就会超时。
第二次大作业踩坑心得:
1. 考虑问题需要全面,对一些边界值进行测试。
2. 在使用一个类的对象的时候,需要声明一下这个类的对象,否则会报错。
3. 在进行菜单类问题中,要在输入一个数据,输出一个和它匹配的输出,而不是在输入完所有数据退出程序的时候再进行全部数据的一起输出。
在上面所说的那种情况下,这几个测试点一直无法通过。
而更改完边输入输出就直接通过了。
4.
在日期类的那题,我一直卡在了,当第一个数据无效的时候一直无法通过,而题目中那些不合理的数据输入,都能输出符合自己满意的答案。因此一直无法找出哪里出错了,后面有满分的同学,询问一下他关于这的测试点。才明白是自己没有考虑这个时间如果长度不符合题意,也是要输出无效的结果。
5. 当运行超时的时候记得导入IO包让数据输入的更快。
6. 价格的四舍五入没有使用Math.round,而是直接将数据(int)化,这样无法起到四舍五入的效果。
第三次大作业设计与分析:
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。
不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
如果序号不对,输出"delete error"
代点菜信息包含:桌号 序号 菜品名称 份额 分数
代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。
程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。
每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。
折扣的计算方法(注:以下时间段均按闭区间计算):
周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。
周末全价,营业时间:9:30-21:30
如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"
参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish\[\] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号\\
Dish d;//菜品\\
int portion;//份额(1/2/3代表小/中/大份)\\
int getPrice()//计价,计算本条记录的价格\\
}
订单类:保存用户点的所有菜的信息。
Order {
Record\[\] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
### 输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+”:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+“:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 12/2/3
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 38
输入样例1:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 17/0/0
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 22
输入样例2:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 16/59/59
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例2:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours
输入样例3:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/5 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
7 delete
end
输出样例3:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
table 1 out of opening hours
table 2: 63
输入样例4:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/3 19/5/12
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 4 麻婆豆腐 1 1
7 delete
end
输出样例4:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
4 table 2 pay for table 1 12
delete error;
table 1: 63
table 2: 75
此题就不进行源代码的粘贴了
分析:这道题也是一个菜单题,相比与第二次的代码的题目难度也增加了不少,这题增加了桌号的标识功能,以及这周几点钟点的菜,并且一桌可以帮另外的桌进行点菜。而在不同的时间需要判断该店在营业,不同的营业时间进行不同的折扣。因为加入了时间,所以需要有对时间的格式的处理。还要Table类的功能。而Order函数中需要加入代点的功能。相比于之前的代码,我将原来的数组变成了动态数组,这样不用考虑数组越界的情况。而且为了保证数据的私有性,用了private。以及对时间处理的优化,LocaDate可以大大的节省时间。圈复杂进行分析的话,我认为我这题,有些功能没有分的很明确,比如print中的功能有些多,可以在拆成不同的小功能。
在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,去掉所有重复的数字。最后按照输入顺序输出没有重复数字的数据。所有重复的数字只保留第一次出现的那份。
输入格式:
你的程序首先会读到一个正整数 n,1≤n≤100000。
然后是 n 个整数,这些整数的范围是 [1, 100000]。
输出格式:
在一行中按照输入顺序输出去除重复之后的数据。每两个数据之间有一个空格,行首尾不得有多余空格。
输入样例:
5
1 2 2 1 4
输出样例:
1 2 4
import java.util.LinkedHashSet; import java.util.Scanner; import java.util.Set; public class Main { /* 输入:输入一个整数值count,为输入元素的个数 处理:输入完整数值,用nextLine将末尾换行符吸收,并输入一个字符串,根据空格进行分割,分割出前count 个元素,根据set类将重复元素删除 输出:输出set中的元素,先调用一个toArray转化为数组。 */ public static void main(String[] args) { Scanner input = new Scanner(System.in); int count = input.nextInt(); input.nextLine(); //调用set类对元素加入数组限定 Set<Integer> set = new LinkedHashSet<>(); // LinkedHashset正常顺序 for (int i = 0; i < count; i++) { int t = input.nextInt(); set.add(t); //如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。 // 如果此 set 已经包含该元素,则该调用不改变此 set 并返回 false } Object[] toArray = set.toArray(); for (int i = 0 ; i < toArray.length ; i++) { if(i == toArray.length -1) System.out.println(toArray[i]); else System.out.print(toArray[i] + " "); } } }
分析:这题没有什么太大的难度,考了一个对于set类的使用。
但是整数不能打Int而是Interger。
从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。
预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。
输入格式:
输入两行,每行输入一个日期,日期格式如:2022-06-18
输出格式:
第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周
输入样例1:
2000-02-18
2000-03-15
输出样例1:
第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周
输入样例2:
2022-6-18
2022-6-1
输出样例2:
第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class Main { public static void main(String[] args) throws ParseException { Scanner sc = new Scanner(System.in); String str1 = sc.nextLine(); String str2 = sc.nextLine(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); Date date1 = sdf1.parse(str1); Date date2 = sdf1.parse(str2); long time1 = date1.getTime(); long time2 = date2.getTime(); if(time1 > time2){ System.out.println("第一个日期比第二个日期更晚"); System.out.println("两个日期间隔" + (time1 - time2)/24/3600/1000 + "天"); System.out.println("两个日期间隔" + (time1 - time2)/24/3600/1000/7 + "周" ); }else{ System.out.println("第一个日期比第二个日期更早"); System.out.println("两个日期间隔" + (time2 - time1)/24/3600/1000 + "天"); System.out.println("两个日期间隔" + (time2 - time1)/24/3600/1000/7 + "周" ); } } }
这道题,因为在第一题中已经涉及到了对时间的处理,查询了一些关于时间的类,没有太大的难度。SimpleDataFormat 可将格式化的日期变成自己想要的类型。Date类中的getTime可以获取该时间离1970相差多少毫秒,因此在计算天数的时候需要进行一系列的乘除。
第三次大作业踩坑心得:
1. 格式的输入问题,在输入桌号标识后要在他:后面加一个空格。
2.
这是因为对时间的判断,提取错误导致当时间输入格式与题目不一样的时候,提取不到信息,导致无法正确获取桌的信息。正是如此导致程序异常终止。程序就非零返回了。
table 1 2023/3/22 12/2/3 当如果是table 1 2023/11/22 12/20/3 这样用substring的话就没法截取了,后面更改为了用spilt对/进行分割获取数据。这个足足卡了两天(哭)!
3.
第一次虽然运气好,通过了第一题,但是在后面提交总是出现几个超时的。这是因为自己刚开始调用的那个时间类太耗费时间。导致运行时间很长,后面更改为Locatdate就很好解决了这一时间的问题
4.
每次输入完之后就进行了index的自加操作,但是这个index中的tables中是没有数据的,因此需要用index-1;否则会进行
报错
5. 踩过的最大坑莫过于,那个周末的时间测试点了。一直寻找那三个测试点的原因,反复对代码进行更改,但它竟然是因为老师说给的那个周末的测试点出现了错误。
6. 去掉重复数据的那一题,虽然用了Set对重复数据知输入一遍,但是在输出最终结果的时候,顺序与题目中的不同。
而用Hashset会按照一种特定的方法进行排序。
7. 面向过程的封装性的在有参函数的构造,如果调用空参函数的构造时候,需要声明。
8.
next 和 nextLine 要区分清楚,next不可以接受空格,nextline 可以接受空格。在输入完next数据后,要输入一个nextLIne类型的话,需要先用nextLIne接受空格和换行符。
主要困难以及改进建议:
做了三次大作业,开始的主要困难点在于自己怎么合理的设计好一个类,类的定义和用法,类里面应该拥有一个怎么样的功能。还有不知道怎么很好运用java自身已经写好的类。在接下来,希望自己可以打好一些语法的基础。让逻辑更加清晰在这些基础上,我认为大作业最困难的一个点在于寻找测试点,当你已经写好一个代码,就错了一两个测试点,但是那个测试点的描述比较含糊(相当于没有),这时候只有自己盲目的去寻找,这是最耗时间但是成效很低的一件事情。有时候甚至会想着把代码重新写过。我认为自己自身的基础知识不是很扎实,一些基础的语法和知识不能灵活的运用。这三次大作业都有一个菜单的功能,我觉得自己在每次写新的题目都有一些自己的领悟和改进。刚开始的我是使用数组的,因为不知道订单和桌的多少,无法确定数组的大小。很有可能太小造成数组的越界,而当数组的大小定义太大容易浪费内存空间。
建议: 希望老师能够将测试点错误写的详细一点,好难找啊!
而这样添加元素进行也比较麻烦。因此学习之后更改为了ArrayList的动态数组的写法。添加一个开辟一个。
由scanner的读取方法改进成快读。
总结:
1. 函数与变量的调用上,代码耦合度高,调用关系太乱,特别是第三次菜单,那个一个类中的圈复杂度达到了29,希望下次可以对类的设计也更加合理。
2. 字符串输入尽量用next() 代替 nextLine() ,因为next()会过滤掉无用的换行符,减少输入类型的不匹配的问题
3. 代码注释少,隔段时间就会看不懂代码,增加工作难度,习惯不好。
4. 通过这几次的大作业,我认为自己相比从前编程的逻辑也更加清晰,类的使用更加顺手,处理类间关系时更加完善,明白了如何处理输入时间的格式处理化,怎么样很好调用时间类。掌握了java与C两者语言的不同点,也学会了java的一些基本语法,例如变量的定义,怎么手动输入,数组,运算符,集合等。学会了用用idea进行调试,可以不用肉眼进行一个一个分析,让自己更加清晰的知道自己哪里出错了。还有希望自己下次能在一些必要的东西多打一点注释,否则下次自己也不是很能看懂,没法进行代码的重复利用。下个阶段需要对正则表达,把类与类之间的关系梳理一下,尽量做到MVC的模式。把方法功能细化,各司其职这些让逻辑清晰的东西上下点功夫。这几次大作业我觉得让我收获最大的一点就是学会了一种坚持,一点要将题目写对。正因为这一点,自己每天都在为了这个方向坚持努力。
希望老师可以将测试点错误给清晰点,真的很难找。