南昌航空大学软件学院-21207120-第一次博客作业

发布时间 2023-10-02 20:43:17作者: Aiden-WANG

(1)前言:这一次博客是针对该学期第一次到第三次作业所做的总结。关于难度方面,第一次作业的9个题难度平均较低,属于基础知识点的运用考察,第二次则开始提高难度,且幅度略大,第三次在第二次的基础上继续提高了难度以及复杂性,其主要提高的是复杂性和繁琐度,致使总体解题难度上升幅度较大。前三次的题目集题量不大,大概囊括了最基础的输入输出、类的创建;字符串的各种操作(定位某个特点字符在字符串中的下标、提取某段需要的子字符串、对于某个字符或某个子字符串的格式判断等等)、类的交互、函数的创建与使用以及正则表达式的运用等等。除却第一次有9个题以外,第二次有八道题之外,第三次只有4个题;在这三次作业中,其中第一次作业相对比较简单,但我的所有测试点未完全通过,第二次作业也比较相对比较简单,都有几个比较深刻的点都没过,特别是正则表达式这一块。
这几次作业,充分展现了我的自身能力不足,以及我以后应该怎么改进。
通过前三次作业,我对Java的一些基本语法有了一些了解,对于面向对象的过程的思想有了一些掌握,但是还有美中不足的地方,以下是我的反思以及对这三次作业的理解。
(2)设计与分析
 
1、第一次作业
第一题:

此题目主要是教你快速上手java先熟悉基本输入的操作,只要根据相应的数据得出特定的区间范围算出相应的BMI就行了,总体难度简单。

以上是我对第一题的代码,没啥好说的
第一次作业第二题

此题更是简单,甚至还没想多少代码呢,就已经结束了,就是把两个浮点数分隔开而已,只要定义变量然后按空格输出就行了

第一次作业第三题

此题唯一的难点就是让java认出奇数而已,然后相加

无bug
第一次作业第四题

此题看似表面略有难度,实则易题一只,就是吧输入的数据用题目所用的概念秒杀,用公式嵌套就行,逻辑不难,只是计算有点复杂,但是计算是交给机器的,所以基本没有什么难点。

第一次作业第五题

此题是贴近生活,意思是网游里有多种职业,要你输入数字,然后选择相应的职业,如果超出范围,就输出为wrong mat。还算简单吧

上面还有一行import java.util.Scanner;
第一次作业第六题

此题略有难度,就是输入学号然后输出相关信息,类似于人类将复杂空洞的信息转化为自己理解的信息,类似身份证,每几位都有自己相应的意思

2.第二次作业
第二次作业第一题

此题是 成绩计算,就是了解类、数组的基本运用,先输入学生信息,然后输出学生的总分平均分
``import java.util.Scanner;
class Student {
String studentID;
String Name;

int MathScores;
int ChineseScores;
int PhysicsScore;

public Student(String studentID, String Name, int MathScores, int ChineseScores, int PhysicsScore) {
    this.ChineseScores = ChineseScores;
    this.MathScores = MathScores;
    this.PhysicsScore = PhysicsScore;
    this.studentID = studentID;
    this.Name = Name;
}

public int sumScores() {
    return ChineseScores + MathScores + PhysicsScore;
}

public double avgScores() {
    return sumScores() / 3.0;
}

}
public class Main{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Student[] students = new Student[5];
for(int i =0;i < 5;i++)
{
String studentInfo = input.nextLine();
String[] info = studentInfo.split(" ");
String studentID = info[0];
String Name = info[1];
int ChineseScores=Integer.parseInt(info[2]);
int MathScores=Integer.parseInt(info[3]);
int PhysicsScores=Integer.parseInt(info[4]);
students[i]=new Student(studentID,Name,ChineseScores,MathScores,PhysicsScores);

    }
    for(Student student:students){
        System.out.println(String.format("" + student.studentID + " " + student.Name + " " + student.sumScores() + " %.2f",student.avgScores()));
    }
}

}

此题做了删改,前后分两次完成
第二次作业第三题

题目要求编写一个程序,读入一组整数,然后检查是否存在重复的数据。如果存在重复数据,则输出"YES";如果没有重复数据,则输出"NO"。
为了解决这个问题,我们可以使用一个数据结构来存储已经出现过的整数,并在遍历输入的过程中不断检查是否已经存在于数据结构中。
一种常用的数据结构是哈希表(Hash Table),它可以提供快速的插入和查询操作。算法的主要步骤如下:

  1. 读入一个正整数n,表示接下来要读入的整数个数。
  2. 创建一个空的哈希表,用来存储已经出现过的整数。
  3. 循环读入n个整数,并逐个进行以下操作:
    • 检查该整数是否已经存在于哈希表中。如果存在,则输出"YES",表示发现了重复数据,并结束程序。
    • 如果不存在,则将该整数插入哈希表中。
  4. 如果循环结束后仍未输出"YES",则表示没有找到重复数据,输出"NO"。
    通过使用哈希表,我们可以在O(1)的时间复杂度内进行插入和查询操作,因此整个算法的时间复杂度为O(n)。
    一开始我是这么想的但是后面发现把问题过于复杂化了,只要设个flag传参就好了


    前面提交两次有小小的编译错误,分号打错了,导致误码,后修正后已无错误
    第二次作业第七题菜单计价程序


根据题目要求,我们需要设计一个点菜计价程序,可以实现以下功能:

  1. 显示菜单:菜单中包含各个菜品的名称和价格。
  2. 点菜:根据用户输入的菜名和份额,将点菜记录添加到订单中。
  3. 计算总价:根据订单中的点菜记录,计算菜品的总价。

为了实现上述功能,我们可以使用面向对象的思想设计以下几个类:

  1. Dish类:表示菜品信息的类,包含菜品名称和单价。
  2. Menu类:表示菜单的类,包含菜品数组,并提供方法用于查找菜品信息。
  3. Record类:表示点菜记录的类,包含菜品和份额,以及计价的方法。
  4. Order类:表示订单的类,保存了多个点菜记录,提供方法用于添加点菜记录和计算总价。

其中,Dish类和Record类可以具有计算价格的方法,Menu类可以提供查找菜品信息的方法,Order类可以提供添加点菜记录和计算总价的方法。

具体实现时,可以按照以下步骤操作:

  1. 创建菜谱对象并初始化菜品信息数组。
  2. 显示菜谱,即遍历菜谱中的菜品信息,并输出菜名和价格。
  3. 提示用户输入点菜信息,包括菜名和份额。
  4. 根据用户输入的菜名,从菜谱中查找菜品信息,并创建点菜记录对象。
  5. 将点菜记录添加到订单中。
  6. 重复步骤3-5,直到用户不再点菜。
  7. 计算订单的总价,即遍历订单中的点菜记录,调用点菜记录对象的计价方法,并累加每一条记录的价格。
  8. 输出订单的总价。

以上就是一个简单的点菜计价程序的设计思路和步骤,通过合理地设计类和方法,可以实现对菜品信息、菜单、点菜记录和订单的管理,并完成计算点菜总价的功能。
以下是我的代码
import java.util.Scanner;

public class Main{
public static void main(String[] args){
Scanner output=new Scanner(System.in);
String dish;
String []menu =new String[]{"清炒土豆丝","西红柿炒蛋","油淋生菜","麻婆豆腐"};
int price=0,size1;
for(;?{
int count=0;
dish=output.next();
if(dish.equals("end"))break;
size1=output.nextInt();
if(dish.equals(menu[1])){
count=1;
if(size11)price=price+15;
if(size1
2)price=price+23;
if(size13)price=price+30;
}
else if(dish.equals(menu[0])){
count=1;
if(size1
1)price=price+12;
if(size12)price=price+18;
if(size1
3)price=price+24;
}
else if(dish.equals(menu[3])){
count=1;
if(size11)price=price+12;
if(size1
2)price=price+18;
if(size13)price=price+24;
}
else if(dish.equals(menu[2])){
count=1;
if(size1
1)price=price+9;
if(size12)price=price+14;
if(size1
3)price=price+18;
}
if(count==0)System.out.println(dish+" does"+" "+"not"+" "+"exist");
}
System.out.println(price);
}
}
我来对我写的代码进行解释一下
这段代码是一个简单的菜单点餐程序,通过输入菜品名称和菜品大小,计算出总价格。

  1. 首先导入java.util.Scanner类,用于接收用户的输入。
  2. 创建Main类,并在main方法中开始程序的执行。
  3. 创建一个名为outputScanner对象,用于接收用户的输入。
  4. 定义变量dish,用于存储用户输入的菜品名称。
  5. 创建一个菜单数组menu,其中包含四个菜品的名称。
  6. 定义变量price,用于存储订单的总价格,初始值为0。
  7. 使用无限循环for(;;),表示不断接收用户的输入,直到输入end结束程序。
  8. 在循环中,首先定义一个变量count,用于记录菜品是否存在的标记。
  9. 通过output.next()获取用户输入的菜品名称,并将其存储在dish变量中。
  10. 使用output.nextInt()获取用户输入的菜品大小,并将其存储在size1变量中。
  11. 使用条件语句判断用户输入的菜品名称,并根据不同的菜品和大小,更新价格price
  12. 如果输入的菜品名称在菜单数组中不存在,将count设为0,并输出菜品名称加上" does not exist"的提示信息。
  13. 循环结束后,输出最终的总价格price
  14. 代码执行完毕,程序结束。

这段代码的逻辑较为简单,通过判断用户输入的菜品名称和大小,计算出菜品的总价格,并输出最终的总价格。
3.第三次作业
第三次作业第二题
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。

考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重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)成绩平均分只取整数部分,小数部分丢弃

参考类图:


针对这个问题,下面是我的见解,可以按照以下步骤进行处理:

  1. 首先,创建一个存储课程信息的字典,用于记录每门课程的属性(性质和考核方式)。
  2. 创建一个存储学生成绩的字典,其中键为学号,值为一个列表,列表中存储每门课程的成绩信息。
  3. 读取输入数据,并按照指定格式解析。
  4. 检查输入的格式是否正确,包括学号、姓名、课程名称、成绩范围等。
  5. 将解析后的数据按照规则存储到相应的字典中。
  6. 针对每个学生,计算其所有课程总成绩的平均分,并按学号由低到高排序输出。
  7. 针对每门课程,计算平时成绩平均分、期末考试平均分和总成绩平均分,并按课程名称的字符顺序输出。
  8. 针对每个班级,计算该班级所有课程总成绩的平均分,并按班级号由低到高排序输出。

在处理过程中,根据题目要求,需要特别注意以下几点:

  • 检查成绩信息中的课程名称是否存在于课程信息中,如果不存在,则输出相应的错误信息。
  • 检查成绩信息中的成绩数量是否与课程的考核方式匹配,如果不匹配,则输出相应的错误信息。
  • 检查课程信息中的课程性质和考核方式是否匹配,如果不匹配,则输出相应的错误信息。
  • 对于重复的成绩信息,只保留第一个课程信息。

根据具体实现情况,可以使用各种数据结构和算法来实现上述步骤,例如使用字典、列表、排序算法等。最终的输出结果需要按照题目要求进行格式化输出。
以下是我的代码













此题较难,前前后后我大概花了两天的时间去构思,然后又花了两天写代码,由于是在国庆写的,所写代码有点繁琐,所以大家见谅
(3)踩坑心得
1、在第一次大作业中,其实对java各方面的考察还是比较基础的,各题目也不需要涉及很多复杂的思路,直接面向过程便可解决。除却部分边界值考察时会出现bug以外,基本都能通过全部测试点。总体难度也是偏低,属于刚开始的入门题目。大部分题目在经过第一次的报错之后稍加思考便能解决。
2、第二次作业的难度显著提升,尤其是第七题菜单计价,
  这道题目涉及到一个简单的订单系统,其中主要涉及到两个难点:

  1. 如何存储菜谱信息?

在本题中,我们需要表示每个菜品的名称和单价以及针对不同份额的价格。可以考虑设计一个菜品类(Dish),其中包含名称(name)、单价(unitPrice)和不同份额价格的计算方法(getPrice)。另外,我们还可以设计一个菜谱类(Menu)来存储所有菜品信息,并提供查找菜品功能,方便订单添加记录。

  1. 如何保存订单信息?

在本题中,我们需要记录每道菜品的名称和份额,可以考虑设计一个点菜记录类(Record),其中包含菜品(Dish)和份额。此外,我们还需要一个订单类(Order),用于保存用户点的菜品信息并计算总价。在订单类中,我们可以使用列表(List)来存储各个菜品的点餐记录,并提供添加记录、计算总价等功能。

针对以上难点,我们可以采用面向对象设计的方式,把实现细节封装在类的内部,使代码更具可读性和可维护性。同时,我们可以使用合适的数据结构和算法来提高程序的效率。比如,可以使用哈希表来实现菜谱的快速查找,使用动态数组来保存订单记录等。
在题目要求的各个格式判断中例如起始位、结束位以及奇偶校验位,语句较为复杂,容易出现很多bug,且可能出现循环一直不终止的情况而导致运行超时。
3、第三次大作业三个题目的难度均较高,尤其是第二题课程成绩统计
有以下几条难点

  1. 输入数据的格式验证:需要确保输入的数据格式符合要求,例如学号、姓名、课程名称等长度和字符限制,成绩的取值范围等。如果输入的数据格式不正确,需要能够正确地识别并输出相应的错误提示信息。

  2. 数据结构设计:需要设计合适的数据结构来存储课程信息、学生信息和班级信息。同时,需要考虑如何根据学号将学生信息排序,并计算每门课程的平均分和班级的总成绩平均分。

  3. 性质与考核方式的匹配:必修课的考核方式必须为考试,选修课可以选择考试或考察。当解析成绩信息时,需要检查课程的性质和考核方式是否匹配,以防止后续的计算出现错误。

  4. 异常情况处理:在数据输入过程中,可能会出现重复的课程/成绩信息、课程名称不存在、成绩数量和考核方式不匹配等异常情况。对于这些情况,需要能够正确地识别并输出相应的错误提示信息。

解决这些难点的思路是,首先要对输入数据进行严格的验证和解析,确保数据的格式正确。其次,使用适当的数据结构来存储和处理数据,以方便后续计算和排序操作。在处理异常情况时,需要逐步检查可能出现的错误情况,并给出相应的错误提示信息,确保程序能够正确处理各种边界情况。最后,将计算结果按照要求的格式化输出,完成整个问题的求解。
 (4)总结:

1、为更好地遵循面向对象编程的思想,下一次我会将相似功能的部分进行类的封装,以提高代码的复用性和可维护性。相比于冗长的代码,这样的改进可以使代码更加简洁易懂,并且提高代码的可读性和可重用性,使得代码更加符合业务需求。
2、我会承认自己在某些基础知识上存在欠缺和不扎实的问题,并积极努力进行补充和提高。例如,在处理正则表达式和浮点数精度损失等相关问题时,我会积极学习和掌握相关知识和技巧,以确保代码的正确性和可靠性,从而更好地满足业务需求。

3、我会加强对基础函数语法知识的学习和巩固,特别是那些与C语言类似的部分。通过深入理解这些知识,我可以更好地理解和吸收相关概念,并将其应用于实际的编程工作中。自学是一个不断提高的过程,我会不断努力学习和积累,以提高自己的技能水平。

4、学习编程语言就像卖油翁中的“无他!唯手熟尔”,只有通过不断的实践和练习,才能真正掌握技能并提高自己。对于学习Java编程,除了理论知识的学习,强调实践是非常重要的。可以通过解决编程问题、完成小项目、参与开源项目等方式来锻炼自己的编程能力。此外,还可以参加编程竞赛、加入技术社区、阅读优秀的代码等,以拓宽视野和提升技术水平。持续的实践和练习将帮助您更加熟练地运用Java语言,并在实际项目中取得更好的效果。