BLOG_OOP_PTA与菜单计价程序分析

发布时间 2023-05-25 14:02:45作者: Ω∅rMī3

前言

涉及知识点

  • 1.关于C语言中的printf和JAVA中sout之类的区别的初步认识;
    在第一次作业中便有sout出现

  • 2.对于创建对象和类的初步实践;
    同上,有class Dish和class Menu,Menu menu=new Menu()等出现

  • 3.对于调用类的初步理解;
    同上

题量

  • 量偏多,主要原因是大一课程量较多,很少有空余时间去仔细琢磨;对于独立题型,可以在零碎时间内完成,而对于系列题目则需要不少功夫。

难度

  • 同上,对于系列题目需要花些功夫。

设计与分析

独立题目分析如下


  • 7-1 身体质量指数(BMI)测算(源码)
import java.util.Scanner;

public class Main
{
    public static void main(String[] args)
    {
        double h,w,bmi;
        Scanner in=new Scanner(System.in);
        w=in.nextDouble();
        h=in.nextDouble();
        bmi=w/(h*h);
        if(h<=0||h>2.72 || w>727)
        {
        System.out.print("input out of range");
            return;
        }
         if(bmi<18.5)
        {
        System.out.print("thin");
             return;
        }
        if(bmi>=18.5 && bmi<24)
        {
        System.out.print("fit");
            return;
        }
         if(bmi>=24 && bmi<28)
        {
        System.out.print("overweight");
             return;
        }
        
        System.out.print("fat");

    }

}
  • 7-1 身体质量指数(BMI)测算(分析)
    此题在我看来主要是Scanner和sout的认识,即在于“输入输出”问题:Scanner in=new Scanner(System.in);在第一次做的时候总是纠结于为什么要这么写,囹圄于in是什么,(System.in)是什么,但其实没必要,学到后面自然会明白了。
    对于此题其他部分,我认为和c语言极为相似,故不需特别分析。

  • 7-2 长度质量计量单位换算(源码)
import java.util.Scanner;

public class Main
{
    public static void main(String args[])
    {
        double kg,met,pound,inch;
        Scanner in = new Scanner(System.in);
        kg=in.nextDouble();
        met=in.nextDouble();
        pound=kg/0.45359237;
        inch=met/0.0254;
        System.out.print((float)pound+" "+(float)inch);
        
    }
    
    
}
  • 7-2 长度质量计量单位换算(分析)
    此题在我看来主要考察强制类型转换,对于结果的输出(sout),需要通过(float)将其转换为正确的格式。

  • 7-4 小明走格子(源码)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int m = scanner.nextInt();
        for (int i = 0; i < m; i++) {
            int n = scanner.nextInt();
            System.out.println(numOfWays(n));
        }
    }

    private static int numOfWays(int n) {
    if (n < 1) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    int[][] matrix = {
            {1, 1, 1, 1},
            {1, 0, 0, 0},
            {0, 1, 0, 0},
            {0, 0, 1, 0}
    };
    int[][] init = {{1}, {1}, {0}, {0}};
    int[][] res = matrixPower(matrix, n - 1);
    int[][] ans = matrixMultiply(res, init);
    return ans[0][0];
}

private static int[][] matrixPower(int[][] matrix, int p) {
    int[][] res = new int[matrix.length][matrix[0].length];
    for (int i = 0; i < res.length; i++) {
        res[i][i] = 1;
    }
    int[][] tmp = matrix;
    while (p != 0) {
        if ((p & 1) == 1) {
            res = matrixMultiply(res, tmp);
        }
        tmp = matrixMultiply(tmp, tmp);
        p >>= 1;
    }
    return res;
}

private static int[][] matrixMultiply(int[][] matrix1, int[][] matrix2) {
    int[][] res = new int[matrix1.length][matrix2[0].length];
    for (int i = 0; i < res.length; i++) {
        for (int j = 0; j < res[0].length; j++) {
            for (int k = 0; k < matrix1[0].length; k++) {
                res[i][j] = (res[i][j] + matrix1[i][k] * matrix2[k][j]) % 1000000007;
            }
        }
    }
    return res;
}

}
  • 7-4 小明走格子(分析)
    这道题其实类似c语言会出的那种题目,即仅存在单个复杂问题,需要较强大的逻辑能力。个人认为这道题算是让我们从c语言的题目中过渡一下,习惯用java也完成这类问题。当然,虽然大体上代码能通过samples,但是仍有一个测试点无法通过,运行超时。想着想着就错过了提交时间了。

  • 7-2 有重复的数据(源码)
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < n; i++) {
            int num = sc.nextInt();
            if (set.contains(num)) {
                System.out.println("YES");
                return;
            } else {
                set.add(num);
            }
        }
        System.out.println("NO");
    }
}
  • 7-2 有重复的数据(分析)
    在我看来是初次接触集合(set)的产物,里面调用了set库中的contain和add方法。如果知道并掌握了set语句就比较容易,但是如果压根不知道这玩意的话写这道题会绕不少弯路。当然,后题(7-3 去掉重复的数据)同理。故不做分析。

  • 7-4 单词统计与排序(源码)
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        String[] words = input.split("[ ,.]");

        // 定义一个Set集合,用于去重并排序
        Set<String> wordSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                if (s1.length() != s2.length()) {
                    return s2.length() - s1.length();
                } else {
                    return s1.compareToIgnoreCase(s2);
                }
            }
        });

        for (String word : words) {
            if (!word.isEmpty()) {  // 判断单词是否为空
                wordSet.add(word);
            }
        }

        // 遍历集合,输出结果
        for (String word : wordSet) {
            System.out.println(word);
        }
    }
}
  • 7-4 单词统计与排序(分析)
    这道题对于方法库的了解要求更深了:String[] words = input.split("[ ,.]");和s1.compareToIgnoreCase(s2);和if (!word.isEmpty())等处都可以体现。

  • 对于其他题
    大部分都是一些测试点无法通过,在此就不过多分析。

第一次源码如下

import java.util.*;


public class Main
{

    public static void main(String args[])
    {
        Menu menu=new Menu();
        //set 保存错误的菜名用于打印。set保证元素不能重复
        Set<String> noDishs = new HashSet<String>();
        menu.dishs.add(new Dish("西红柿炒蛋",15));
        menu.dishs.add(new Dish("清炒土豆丝",12));
        menu.dishs.add(new Dish("麻婆豆腐",12));
        menu.dishs.add(new Dish("油淋生菜",9));
        Order order=new Order();
        Scanner sc = new Scanner(System.in);
        while(sc.hasNextLine()){
            String str=sc.nextLine();
            if(str.equals("end")){
                sc.close();
                break;
            }
            String[] strs=str.split(" ");
            //System.out.println(strs.length);
            if(menu.searthDish(strs[0])==null){
                noDishs.add(strs[0]);
                continue;
            }
            order.addARecord(strs[0],Integer.valueOf(strs[1]),menu);
        }
        Iterator it = noDishs.iterator();
            while (it.hasNext()) {
            String noDish = it.next().toString();
            System.out.println(noDish+" does not exist");
}
        //round函数四舍五入
        System.out.println(Math.round(order.getTotalPrice()));
    }
}
class Dish{
    String  name;
    int unit_price;

    public Dish(String name,int unit_price){
        this.name=name;
        this.unit_price=unit_price;
    };
    double getPrice(int portion){
        switch(portion){
            case 1:
                return unit_price;
            case 2:
                return unit_price*1.5;
            case 3:
                return unit_price*2;
        }
        return 0;
    }
}
class Menu{
    ArrayList<Dish> dishs=new ArrayList<Dish>();

    Dish searthDish(String dishName){

        for(Dish dish:dishs){
            if(dish.name.equals(dishName)){
                return  dish;
            }
        }

    return null;
}
    }
class Record{
    Dish d;
    int portion;

    public Record(Dish d,int portion){
        this.d=d;
        this.portion=portion;
    }
    double getPrice(){
        return d.getPrice(portion);
    }
}
class Order{
    List<Record> records=new ArrayList<Record>();
    double getTotalPrice(){
        double sum=0;
        for(int i=0;i<records.size();i++){
            sum=sum+records.get(i).getPrice();
        }
        return sum;
    }
    void addARecord(String dishName,int portion,Menu menu){
        if(menu.searthDish(dishName)==null)return;
        Record newOrder=new Record(menu.searthDish(dishName),portion);
        records.add(newOrder );
    }
}
  • 对于第一次题目来说,对于学习完大致内容的现在来说并不算难,但是对于刚刚起步学习的时候可以说是摸不着头脑,俗话说“万事开头难”,可能也说的是此。

分析

  • 其实结构很简单明了,就是类似于看图说话:题目要求了什么就完成什么就行。要求项并不繁多复杂,一步步写下去就可以写出来。
    • 对于创建的类
      • class Dish
        String name:定义菜品名字name
        int unit_price:定义菜品价格unit_price
      • class Menu
        ArrayList<Dish> dishs=new ArrayList<Dish>():通过ArrayList存储菜单;
        Dish searthDish(String dishName):根据菜名在菜谱中查找菜品信息,返回Dish对象;
        等等

第二次源码如下

import java.util.*;

public class Main {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    Order od = new Order();
    Menu mn = new Menu();
    String b = "";
    b = in.nextLine();
    String[] a = new String[10];
    int t = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    int s = 0;
    int s1 = 0;
    int s2 = 0;
    int s3 = 0;
    while (!b.equals("end")) {
      a = b.split(" ");
      if (a.length == 2 && !a[1].equals("delete")) {
        s = Integer.parseInt(a[1]);
        mn.dishs[i] = new Dish();
        mn.dishs[i] = mn.addDish(a[0], s);
        i++;
      }
      if (a.length == 4) {
        s1 = Integer.parseInt(a[0]);
        s2 = Integer.parseInt(a[2]);
        s3 = Integer.parseInt(a[3]);
        od.records[k] = new Record();
        od.records[k] = od.addARecord(s1, a[1], s2, s3);
        od.records[k].d = mn.searchDish(a[1]);
        if (od.records[k].d == null)
          System.out.println(a[1] + " does not exist");
        else
          System.out.println(od.records[k].orderNum + " " + od.records[k].d.name + " " + od.records[k].getPrice());
        k++;
      }
      if (a[1].equals("delete")) {
        s1 = Integer.parseInt(a[0]);
        od.delTheDishByOrderNum(s1);
      }
      b = in.nextLine();
    }
    System.out.println(od.getTotalPrice());
  }
}

class Dish {
  String name;
  int unit_price;

  int getPrice(int portion) {
    switch (portion) {
      case 1:
        return unit_price;
      case 2:
        if (unit_price == 15 || unit_price == 9)
          return ((int) (unit_price * 1.5)) + 1;
        else
          return unit_price * 3 / 2;
      case 3:
        return unit_price * 2;
    }
    return 0;
  }
}

class Menu {
  Dish[] dishs = new Dish[10];
  int t = 0;

  Dish searchDish(String dishName) {
    int flag = 0;
    int i;
    for (i = t - 1; i >= 0; i--) {
      if (dishName.equals(dishs[i].name) == true) {
        flag = 1;
        break;
      }
    }
    if (flag == 1)
      return dishs[i];
    else {
      return null;
    }
  }

  Dish addDish(String dishName, int unit_price) {
    Dish dish1 = new Dish();
    dish1.name = dishName;
    dish1.unit_price = unit_price;
    t++;
    return dish1;
  }
}

class Record {
  int orderNum;
  Dish d = new Dish();
  int portion;
  int num;

  int getPrice() {
    return num * d.getPrice(portion);
  }
}

class Order {
  Record[] records = new Record[10];
  int count = 0;
  int sum = 0;
  int i = 0;

  double getTotalPrice() {
    for (i = 0; i < count; i++) {
      if (records[i].d != null)
        sum += records[i].getPrice();
    }
    return sum;
  }

  Record addARecord(int orderNum, String dishName, int portion, int num) {
    Record a = new Record();
    a.orderNum = orderNum;
    a.d.name = dishName;
    a.portion = portion;
    a.num = num;
    count++;
    return a;
  }

  void delTheDishByOrderNum(int orderNum) {
    if (orderNum <= count) {
      records[orderNum - 1].num = 0;
    } else
      System.out.println("delete error;");
  }
}

分析

  • 第二次题目增加了顾客删除所选菜品的功能,而且对于点菜方式也进行了升级,表现为可自定义菜单,而不是固定式菜单,更加人性化
    • 对于新创建的方法等
      • Order {
        Record[] records
        //保存订单上每一道的记录
        int getTotalPrice()
        //计算订单的总价
        Record addARecord(int orderNum,String dishName,int portion,int num)
        //添加一条菜品信息到订单中。
        delARecordByOrderNum(int orderNum)
        //根据序号删除一条记录
        findRecordByNum(int orderNum)
        //根据序号查找一条记录
        }:
      • while (!b.equals("end")) 作为循环的判断,体现了调用方法的便捷性:若读取到的不是"end",则继续循环,否则结束循环。
      • 对于判断菜单和订单的输入问题,可通过split方法分割输入的字符串,观察输入示例不难发现,当输入菜单时,形如麻婆豆腐 12 \n油淋生菜 9,则每行只有2个字符串,对于输入订单,则有形如1 麻婆豆腐 2 2\n2 油淋生菜 1 3
        ,每行4个字符串。有了区别便好判断了:通过新建数组b存储每行的字符串数目,就很方便判断出来输入的到底是菜单还是订单。
      • 对于删除菜品,那更简单了,一旦读取到了"delete",便执行删除菜品的方法即可。

第三次源码如下

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

public class Main {

    static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        Menu mn = new Menu();
        Order[] od = new Order[100];
        int orderIdx = 0;
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
            if (line.equals("end")) {
                break;
            }
            String[] parts = line.split(" ");
            if (parts[0].equals("table")) {
                String[] time = parts[3].split("/");
                int year = Integer.parseInt(time[0]);
                int month = Integer.parseInt(time[1]);
                int day = Integer.parseInt(time[2]);
                time = parts[4].split(":");
                int hour = Integer.parseInt(time[0]);
                int minute = Integer.parseInt(time[1]);
                int second = Integer.parseInt(time[2]);
                od[orderIdx] = new Order(Integer.parseInt(parts[1]), year, month, day, hour, minute, second);
                orderIdx++;
            } else if (parts[1].equals("delete")) {
                int orderNum = Integer.parseInt(parts[0]);
                Record record = od[orderIdx - 1].findRecordByNum(orderNum);
                if (record == null) {
                    System.out.println("delete error");
                } else {
                    od[orderIdx - 1].delARecordByOrderNum(orderNum);
                }
            } else {
                String dishName = parts[1];
                Dish dish = mn.searthDish(dishName);
                if (dish == null) {
                    dish = mn.addDish(dishName, Integer.parseInt(parts[2]));
                }
                int orderNum = Integer.parseInt(parts[0]);
                int portion = Integer.parseInt(parts[2]);
                int num = Integer.parseInt(parts[3]);
                od[orderIdx -1].addARecord(orderNum, dish, portion, num);
            }
        }
        for (int i = 0; i < orderIdx; i++) {
            System.out.println(od[i].toString());
        }
    }

    public static class Menu {
        private List<Dish> dishes;

        public Menu() {
            dishes = new ArrayList<>();
        }

        public Dish searthDish(String name) {
            for (Dish dish : dishes) {
                if (dish.getName().equals(name)) {
                    return dish;
                }
            }
            return null;
        }

        public Dish addDish(String name, int price) {
            Dish dish = new Dish(name, price);
            dishes.add(dish);
            return dish;
        }
    }

    public static class Dish {
        private String name;
        private int price;

        public Dish(String name, int price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public int getPrice() {
            return price;
        }
    }

    public static class Order {
        private int tableNum;
        private List<Record> records;
        private Date date;

        public Order(int tableNum, int year, int month, int day, int hour, int minute, int second) {
            this.tableNum = tableNum;
            records = new ArrayList<>();
            Calendar calendar = Calendar.getInstance();
            calendar.set(year, month - 1, day, hour, minute, second);
        }

        public void addARecord(int orderNum, Dish dish, int portion, int num) {
            Record record = new Record(orderNum, dish, portion, num);
            records.add(record);
        }

        public Record findRecordByNum(int orderNum) {
            for (Record record : records) {
                if (record.getOrderNum() == orderNum) {
                    return record;
                }
            }
            return null;
        }

        public void delARecordByOrderNum(int orderNum) {
            Record record = findRecordByNum(orderNum);
            if (record != null) {
                records.remove(record);
            }
        }

        public int getTableNum() {
            return tableNum;
        }

        public Date getDate() {
            return date;
        }
    }
}

分析

  • 此次题目较之前的题目进一步升级,引入了桌号和日期功能,更加贴近生活,同时难度也进一步提升。
    • 对于新创建的方法及知识点等
      • 当用户输入的命令为"table"时,代码会创建一个新的订单对象,并将其存储在订单数组中。
if (parts[0].equals("table")) {
    String[] time = parts[3].split("/");
    int year = Integer.parseInt(time[0]);
    int month = Integer.parseInt(time[1]);
    int day = Integer.parseInt(time[2]);
    time = parts[4].split(":");
    int hour = Integer.parseInt(time[0]);
    int minute = Integer.parseInt(time[1]);
    int second = Integer.parseInt(time[2]);
    orders[orderIdx] = new Order(Integer.parseInt(parts[1]), year, month, day, hour, minute, second);
    orderIdx++;
}
  • 这段代码首先通过split方法将输入的日期和时间字符串拆分成年、月、日、小时、分钟和秒的数组。然后使用Integer.parseInt将这些字符串转换为整数类型,用于创建Order对象的构造函数参数。最后,将创建的订单对象存储在订单数组中,并更新订单索引,
    其涉及到字符串处理、数组操作、类型转换和对象创建等知识点。通过拆分输入字符串、解析日期和时间、使用整数类型存储时间信息,以及创建订单对象并将其存储在数组中,实现了订单的创建和存储。

采坑心得

在做独立题的过程中,除了个别较为复杂的题目,大多数是可以应付的。当然,例如走格子问题,也可以通过大多测试点。而对于系列题目即菜单,我在第二次时便将其转入了idea中进行分类作业。然而由于水平不足,总是会有一些编译上的错误,而自己甚至一时不知道如何解决。
在询问高人后又总是无法通过测试点,其中较为典型的一个例子便是最后sout总价格部分,不知为何总是输出不了--这个问题至今都没有靠我自身解决。

主要困难以及改进建议

主要困难大多归于浮躁。在现在的大学生活中总是很难沉下心来做一件事,导致如编程这种需要冷静头脑的工作受到了很大的约束。然而风气问题,源于根本,绝非一夕而成,要彻除此问题也绝非一朝可矣,它需要全校甚至全社会的努力。
然而关于自身,又能如何做呢?但愿在这炙热的淤泥中,自己也能冷静自濯吧。

总结

本阶段三次题目集算是对于java的入门,我学习到了java库基本方法,以及java较c语言来说特殊的类的机制及其调用关系。然而学的东西多浮虚表,难以深究,对于一些边角知识或者细节问题等等都未曾细细了解。往后的生涯需要更多的练习,以求掌握甚至于精通此课程。
对于课程等等,我希望老师能够允许学生在课上打开笔记本,跟着老师的节奏,同步地完成该章节所学的内容,通过真正的实践例子,来对于java有一个真实的感受,而不是一直听课--直至睡着。同时,examsys的作业提交也总是有问题,由于对电脑知识的了解并不深入,所以这个问题直到今天也未解决。希望以后能够用回pta等
专业的作业提交网站,即算是对于作业的提交更醒目更方便,也算是为我这种小白减轻一点没有必要的负担。