前言
涉及知识点
- 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对象;
等等
- 如class 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等
专业的作业提交网站,即算是对于作业的提交更醒目更方便,也算是为我这种小白减轻一点没有必要的负担。