Java程序设计实验2 | Java语言基础

*本文是博主对Java各种实验的再整理与详解,除了代码部分和解析部分,一些题目还增加了拓展部分(⭐)。拓展部分不是实验报告中原有的内容,而是博主本人自己的补充,以方便大家额外学习、参考。

目录

一、实验目的

二、实验内容

1、实验题目:基本语法

(1)求任意输入的10个数的和。

(2)实验题目:获取三个整数中的最大值(用三元运算符)

        ⭐拓展-通过泛型类获取任意类型的三个数的最大值

2、实验题目:选择结构的应用 

(1)键盘录入月份的值,输出对应的季节

(2)输入年份和月份,输出该年月的天数

        ⭐拓展-输入年、月、日,输出这天是该年的第几天

(3)出租车计费问题

3、实验题目:循环结构的应用

(1)分别用do-while和for循环计算1+1/2!-1/3!+1/4!-1/5!…的前20项之和。 

(2)求1000以内的完全数(一个数等于它的因子之和称为完全数) 

(3)微信中的一个拿鸡蛋问题

5、实验题目:课后作业题

(1)求六边形面积,六边形面积可以通过下面公式计算(s是边长)

(2)实现会员注册,要求用户名长度不小于3,密码长度不小于6,若不满足需有提示信息,提示输入有误;注册时两次输入密码必须相同(字符串)

(3)找出两个分教最高的学生:编写程序,提示输入学生的个数、每个学生的名字及其分数,最后显示获得最高分的学生和第二高分的学生

(4)定义一维数组并初始化,通过键盘任意输入一个数,查找该数是否存在(结果返回下标值)

(5)编写一个程序,将二维数组a转置后存入数组b(所谓转置就是行列互换)

三、实验总结


一、实验目的

1、掌握变量的命名是否符合Java关于标识符的命名规则。

2、掌握8种基本数据类型和3种类型转换的方法。

3、熟悉各种运算符的优先级和结合方向。

4、掌握控制结构的3种语句。

5、掌握Java输入数据的基本方法;Scanner。

6、掌握方法的定义、调用格式,理解方法调用和参数传递的原理,掌握方法的重载,理解方法的递归调用。

7、掌握数组的定义、动态和静态初始化格式,数组的遍历和应用,Array工具类的使用。


二、实验内容

1、实验题目:基本语法

(1)求任意输入的10个数的和。

源代码:

常规方式for循环输入并求和。该题逻辑非常基础,不作过多说明。对于Scanner不了解的同学可以查看该文档Scanner

import java.util.Scanner;

public class S2_1_1 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);    //创建Scanner对象
        int sum = 0;
        for(int i = 1; i <= 10; i++) {    //连续输入10个数
            System.out.println("请输入第"+i+"个数:");
            int n = reader.nextInt();
            sum += n;    //累加求和
        }
        reader.close();    //记得关闭
        System.out.println(sum);
    }
}

列出测试数据和实验结果截图:


(2)实验题目:获取三个整数中的最大值(用三元运算符)

源代码:

代码1:直接使用三目运算符。

import java.util.Scanner;

public class S2_1_2 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int a = reader.nextInt();
        int b = reader.nextInt();
        int c = reader.nextInt();

        int temp = (a > b) ? a : b;
        //若a大于b,则三目运算符表达式值为a,否则为b
        int max = (temp > c) ? temp : c;
        //若temp大于c,则三目运算符表达式值为temp,否则为c
        System.out.println("max = " + max);
    }
}

代码2:将求最大值的程序封装成方法,通过调用方法获取最大值。 

import java.util.Scanner;

public class S2_1_2 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int a = reader.nextInt();
        int b = reader.nextInt();
        int c = reader.nextInt();

        int temp = max(a,b);    //调用方法
        int max = max(temp,c);
        System.out.println("max = " + max);
    }

    public static int max(int x, int y){
        return x > y ? x : y;
    }
}

列出测试数据和实验结果截图:


⭐拓展-通过泛型类获取任意类型的三个数的最大值

提问:如果想要比较的对象不仅是整数,而是任意的基本数据类型,那该怎么办呢?

当然,我们可以采用方法重载,枚举多种情况、写多个方法。但这样依旧有些费劲,毕竟光是可以比较的数值类型就有7种,更何况可能还需要比较自定义类型。这时,我们可以借助泛型来实现。详解部分可以查阅下面这篇文章:

🔗Java初识泛型 | 如何通过泛型类/泛型方法获取任意类型的三个数的最大值?


2、实验题目:选择结构的应用 

(1)键盘录入月份的值,输出对应的季节

源代码:

用switch或if来进行分支判断都是简便且可行的,这里给出用if实现的代码。 

import java.util.Scanner ;

public class S2_2_1 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in) ;

        System.out.println("请输入一个月份的值:") ;
        int month = sc.nextInt() ;

        if(month > 12 || month < 1){
            System.out.println("您输入的月份不合法") ;
        }else if(month >= 3 && month <= 5){
            System.out.println("春季") ;
        }else if(month >= 6 && month <= 8){
            System.out.println("夏季") ;
        }else if(month >= 9 && month <= 11){
            System.out.println("秋季") ;
        }else{
            System.out.println("冬季") ;
        }
    }
}

列出测试数据和实验结果截图:

(2)输入年份和月份,输出该年月的天数

import  java.util.Scanner;

public class S2_2_2 {
    public static void main(String[] args){
        Scanner s =new Scanner (System.in);
        System.out.println("请输入年份:");
        int year= s.nextInt();

        System.out.println("请输入月份:");
        int month= s.nextInt();

        int day = 0;
        switch (month){
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                day = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                day = 30;
                break;
            case 2:
                if(year%4 == 0 && year%100 != 0 || year%400==0){
                    day=29;
                }else{
                    day=28;
                }
                break;
        }

        System.out.println(year+"年"+month+"月有"+day+"天");
    }
}

⭐拓展-输入年、月、日,输出这天是该年的第几天

我们写分支结构时,当发现既可以使用switch-case(同时switch中表达式的取值情况不太多),又可以使用if-else时,我们可以优先选择使用switch-case,因为switch-case的执行效率稍高。 

import java.util.Scanner;

public class YearDayTest {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入year:");
        int year = reader.nextInt();
        System.out.println("请输入month:");
        int month = reader.nextInt();
        System.out.println("请输入day:");
        int day = reader.nextInt();

        //定义一个变量来保存天数
        int sumDays = 0;
        //不加break,达到逐月累加的效果
        switch(month) {
            case 12:
                sumDays += 30;  //加的是上个月也就是11月的天数
            case 11:
                sumDays += 31;
            case 10:
                sumDays += 30;
            case 9:
                sumDays += 31;
            case 8:
                sumDays += 31;
            case 7:
                sumDays += 30;
            case 6:
                sumDays += 31;
            case 5:
                sumDays += 30;
            case 4:
                sumDays += 31;
            case 3:
                if(year%4 == 0 && year%100 != 0 || year%400==0){
                    sumDays += 29;
                }else{
                    sumDays += 28;
                }
            case 2:
                sumDays += 31;
            case 1:
                sumDays += day; //最后加上当月的天数
        }
        System.out.println(year + "年" + month + "月" + day + "日是当年的第" + sumDays + "天" );
    }
}

(3)出租车计费问题

• KF市的出租车计费方式为:起步2公里内5元,2公里以上每公里收费1.3元,9公里以上每公里收费2元,燃油附加费1元。

• 编写程序,输入公里数,计算出所需的出租车费用。

源代码:

import java.util.Scanner;

public class S2_2_3 {
    public static void main(String[] args) {
      Scanner reader = new Scanner(System.in);
      double price = 0.0;

      System.out.println("请输入里程数:");

      double mile = reader.nextDouble();

      if(mile <= 2 && mile > 0){
          price = 5;
      } else if (mile > 2 && mile <= 9) {
          price = (mile-2) * 1.3 + 5;
      } else if (mile > 9) {
          price = 5 + 7 * 1.3 + (mile-9) * 2 + 1;
      }

      System.out.println("价格为:" + price + "元。");
    }
}

列出测试数据和实验结果截图:


3、实验题目:循环结构的应用

(1)分别用do-while和for循环计算1+1/2!-1/3!+1/4!-1/5!…的前20项之和。 

本题是基础的累加、阶乘的运用。较为基础,故不多作说明。

源代码:

for循环实现

public class S2_3_1 {
    public static void main(String[] args) {
        double sum = 0;
        double fact = 1;
        for(int i = 1; i <= 20; i++){
            fact *= i;    //求每项中的阶乘
            sum += 1/fact;    //将各项累加
        }
        System.out.println(sum);
    }
}

do-while循环实现

public class S2_3_1 {
    public static void main(String[] args) {
        double sum = 0;
        double fact = 1;
        int i = 1;
        do {
            fact *= i++;
            sum += 1/fact;
        }while(i <= 20);

        System.out.println(sum);
    }
}

列出测试数据和实验结果截图:

(2)求1000以内的完全数(一个数等于它的因子之和称为完全数) 

通过试除法,找到数n所有的因子并相加,最后作判断即可。 

源代码:

public class S2_3_2 {
    //判断是否是完全数的方法
    public static boolean isPerfectNumber(int n){
        //一个数等于它的因子之和称为完全数
        int sum = 0;    //用于记录因子之和
        for(int i = 1; i <= n/2; i++){    //试除法寻找因子
            if(n%i == 0){    
                sum += i;    //此处i即n的因子
            }
        }
        //比较因子之和与这个数本身是否相等
        if(sum == n){
            return true;
        }else{
            return false;
        }
    }

    public static void main(String[] args) {
        for(int n = 6; n <= 1000; n++){
            if(isPerfectNumber(n)){
                System.out.println(n);
            }
        }
    }
}

(3)微信中的一个拿鸡蛋问题

一筐鸡蛋,1个1个拿,正好拿完。

     2个2个拿,还剩1个。

     3个3个拿,正好拿完。

     4个4个拿,还剩1个。

     5个5个拿,还差1个。

     6个6个拿,还剩3个。

     7个7个拿,正好拿完。

     8个8个拿,还剩1个。

     9个9个拿,正好拿完。

问:筐里最少有多少鸡蛋?

这个问题非常简单,但必须注意细节:5个5个拿时,是还“差”一个,而不是还“剩”一个。假设有4个鸡蛋,那么此时5个5个拿,就是还差一个的情景。因此,此时的鸡蛋数加上差的1个,恰好是5的倍数。

源代码:

public class S2_3_3 {
    public static void main(String[] args) {
        int i = 0;
        while(true) {
            i++;
            if(i%2==1 && i%3==0 && i%4==1 && (i+1)%5==0 && i%6==3 && i%7==0 && i%8==1 && i%9==0){
                System.out.println(i);
                break;
            }
        }
    }
}

列出测试数据和实验结果截图:


5、实验题目:课后作业题

(1)求六边形面积,六边形面积可以通过下面公式计算(s是边长)

注:使用Math类中的方法计算tan值。 

源代码: 

public class Test {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        double s = reader.nextDouble();
        System.out.println(getArea(s));
    }
    public static double getArea(double s){
        double x1 = 6*Math.pow(s,2);
        double x2 = 4*Math.tan(Math.PI/6);
        return x1/x2;
    }
}

列出测试数据和实验结果截图: 

(2)实现会员注册,要求用户名长度不小于3,密码长度不小于6,若不满足需有提示信息,提示输入有误;注册时两次输入密码必须相同(字符串)

本题的关键是字符串的输入与两个字符串之间的比较方法equals的运用。注意,若要求忽略大小写比较,则用到equalsIgnoreCase()方法。

源代码:

import java.util.Scanner;
public class S2_5_2 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String userName = reader.next();
        while(userName.length() < 3) {
            System.out.println("用户名长度不可小于3!请重新输入:");
            userName = reader.next();
        }
        System.out.println("请输入密码:");
        String password = reader.next();
        while(password.length() < 6) {
            System.out.println("密码长度不可小于6!请重新输入:");
            password = reader.next();
        }
        System.out.println("请确认密码:");
        String confirmPassword = reader.next();
        if(confirmPassword.equals(password)) {
            System.out.println("注册成功!");
        }else {
            System.out.println("两次密码不一致!");
        }
    }
}

 列出测试数据和实验结果截图:

(3)找出两个分教最高的学生:编写程序,提示输入学生的个数、每个学生的名字及其分数,最后显示获得最高分的学生和第二高分的学生

方法一:直接求解

该代码没有用到面向对象的思想,编程思路是分别创建两个数组:分数数组与姓名数组进行分开存储。通过排序代码,以分数为标准对姓名数组进行排序,最后输出前两项的姓名。 

源代码:

import  java.util.Scanner;

public class S2_5_3 {
    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);

        System.out.println("请输入学生个数");
        int num = reader.nextInt();

        //创建分数数组和姓名数组进行分开存储
        int[] score = new int[num];
        String[] name = new String[num];

        for(int i=0;i<num;i++)
        {
            System.out.println("请输入第"+(i+1)+"个学生的名字");
            name[i]= reader.next();
            System.out.println("请输入第"+(i+1)+"个学生的成绩");
            score[i]=reader.nextInt();
        }

        //直接选择排序
        for(int i=0;i<num;i++)
        {
            for(int j=i+1;j<num;j++)
            {
                if(score[i]<score[j])
                {
                    String tmp = name[i];
                    name[i] = name[j];
                    name[j] = tmp;
                }
            }
        }

        System.out.println("第一名为:"+name[0]+"。第二名为:"+name[1]);
    }
}

列出测试数据和实验结果截图:

  

方法二:面向对象

该方法是上一种方式的优化,核心思路是实现Student类,创建Student数组,并通过直接对Student数组排序的方式最高分的Student对象与第二高分的Student对象。

注意:由于数组排序的过程中设计对象的比较,因此需要重写compareTo()方法才能进行Student数组的排序。

源代码:

import java.util.Arrays;
import java.util.Scanner;

public class S2_5_3 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入学生的个数:");
        int num = reader.nextInt();
        Student[] students = new Student[num];
        System.out.println("请依次输入学生的姓名与分数:");
        for (int i = 0; i < students.length; i++){
            System.out.println("学生"+(i+1));

            String namei = reader.next();   //① 注意:写成.next()和.nextLine()在此有区别!
            int scorei = reader.nextInt();    //②
            students[i] = new Student(namei,scorei);    //③
        }
        Arrays.sort(students);    //④

        System.out.println("获得最高分的学生是:" + students[0]);
        System.out.println("获得第二高分的学生是:" + students[1]);
    }
}

class Student implements Comparable<Student>{    //⑤
    String name;
    int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    //重写compareTo方法以数组排序
    @Override
    public int compareTo(Student o) {
        return o.score-this.score;
    }

    //重写toString方法以打印对象
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

代码详解: 

  1. 注释①处写成.next()和.nextLine()在此是有区别的。正确的方式应当是写成reader.next(); 一方面,.next()不会因为获取到上一个输入遗留下来的换行空白符而停止读取;另一方面,在用户实际输入的时候既可以将“姓名”和“分数”用换行隔开,也可以用空格等非换行符隔开。若写成.nextLine()。则会有上面的两个问题,会抛出InputMismatchException
    通过调试可以知道,此时的字符串“小明”并没有被①代码接收,而是被②代码接收,①代码似乎被直接“跳过”了,类型不匹配因此异常
  2.  ③处代码是创建新的Student对象。注意,在创建Student数组的时候,并没有实例化Student对象。数组没有初始化,因此Student数组内均为null。通过构造方法给Student对象的name和score赋值,并实例化数组中的元素。
  3. ④直接调用Arrays中的方法sort给数组中的元素进行排序。注意:该数组是引用类型,要实现排序必须重写Comparable或Comparator接口,并重写相应的比较方法,也就是指定比较的规则。
  4. ⑤处实现了Comparable接口。

列出测试数据和实验结果截图: 

(4)定义一维数组并初始化,通过键盘任意输入一个数,查找该数是否存在(结果返回下标值)

方法一:数组中查找比对

源代码:

import java.util.Arrays;
import java.util.Scanner;

public class S2_5_44 {
    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);
        int[] array={0,1,2,3,4,5,6,7,8,9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));

        System.out.println("请输入一个数:");
        int num = reader.nextInt();

        int i = 0;
        for(; i < array.length; i++)
        {
            if(num == array[i])
            {
                break;
            }
        }
        if(i < array.length){
            System.out.println("该数存在,下标为" + i);
        }else{
            System.out.println("没有找到");
        }
    }
}

 列出测试数据和实验结果截图: 

 

方法二:将数组转变为字符串后,调用indexOf()方法

注意,将int数组转换为String,不能直接调用Arrays.toString()方法。因为该方法输出的内容并不完全是原数组中的,而是还有分隔符逗号、前后中括号[] 等。通过调试可以看到:

我们希望0下标的位置是"0",但这里却是"["。Java中没有库函数可以实现int数组直接转换成String的方法,因此我们需要自己实现一个myToString()来完成,逻辑也并不难。 

源代码:

import java.util.Arrays;
import java.util.Scanner;

public class S2_5_4 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));

        System.out.println("请输入一个数:");
        int num = reader.nextInt();
        //将待查找的数转变成String类型,再查找
        String strNum = String.valueOf(num);
        //调用自己实现的方法,将int数组转变成String数组
        String strArray = myToString(array);
        
        //获取查找下标值
        int ret = strArray.indexOf(strNum);
        if(ret != -1){
            System.out.println("找到了,下标是:" + ret);
        } else {
            System.out.println("没有找到");
        }
    }

    //自己实现将int数组转换为String的方法
    public static String myToString(int[] array) {
        String str = "";
        for (int x : array) {
            str += x+"";
        }
        return str;
    }
}

列出测试数据和实验结果截图:

 

方法三:调用Arrays工具类中的binarySearch()方法

如图,这是binarySearch()一个方法的api文档。通过文档可知,配合sort()方法,可以直接调用二分查找方法实现查找。 

源代码:

import java.util.Arrays;
import java.util.Scanner;

public class S2_5_4 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("数组为:");
        System.out.println(Arrays.toString(array));

        System.out.println("请输入一个数:");
        int num = reader.nextInt();
        Arrays.sort(array);    //必须先进行排序
        int ret = Arrays.binarySearch(array,num);    //调用二分查找方法

        if(ret < 0) {
            System.out.println("没有找到!");
        }else{
            System.out.println("找到了,下标为" + ret);
        }
    }
}

(5)编写一个程序,将二维数组a转置后存入数组b(所谓转置就是行列互换)

例如: 

 源代码:

import java.util.Arrays;
import java.util.Scanner;
public class S2_5_5 {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);

        System.out.println("请输入数组的行数n与列数m:");
        int n = reader.nextInt();
        int m = reader.nextInt();
        int[][] src = new int[n][m];
        int[][] dst = new int[m][n];

        System.out.printf("请输入一个%d*%d的数组:\n",n,m);
        for(int i = 0; i < src.length;i++)
        {
            for(int j = 0; j < src[i].length; j++)
            {
                src[i][j] = reader.nextInt();
            }
        }

        for(int i = 0; i < dst.length; i++)
        {
            for(int j = 0; j < dst[i].length; j++)
            {
                dst[i][j] = src[j][i];
            }
        }

        System.out.println("转制后的二位数组为:");
        //System.out.println(Arrays.deepToString(dst));
        for(int i = 0; i < dst.length; i++)
        {
            for(int j = 0; j < dst[i].length; j++)
            {
                System.out.print(dst[i][j] + " ");
            }
            System.out.println();
        }
    }
}

列出测试数据和实验结果截图:


实验总结

  1. 完成上述实验,我更熟地掌握了Java的基础语法,包括:
    1. Java关于标识符的命名规则,Java标识符可以字母、数字、下划线和美元符构成,且数字不能开头。类名用大驼峰,变量名、方法名用小驼峰。
    2. 掌握了8种基本数据类型int,byte,short,char,long,float,double,Boolean的使用情况和相应的类型转换方法。
    3. 我熟悉了各种运算符包括自增、自减、三目运算符等的优先级和结合方向。
    4. 我掌握了控制结构的3种语句,包括if、switch选择语句、while、do-while、for、for-each循环语句。
    5. 我掌握了Java输入数据的基本方法:Scanner。我可以熟练地通过调用Scanner对象输入各种数据类型的数据进行编程。
    6. 我掌握了方法的定义和调用格式,能正确写出Java定义方法的语法。也理解了方法调用和参数传递的原理,包括值传递和址传递。
    7. 我掌握了方法的重载,重载的条件是方法的名称必须相同,参数列表必须不同,返回值类型不做要求。
    8. 我也理解了方法的递归调用,递归就是方法自己调用自己,会在虚拟机栈中建立栈帧。
    9. 在与数组相关的实验中,我掌握了数组的定义、动态和静态初始化格式。我能通过for循环对一维数组和二维数组进行遍历,能完成数组的转置、数组的排序,构建引用类型的数组。也可以熟练通过Array工具类,直接调用Arrays中的方法进行数组排序和逆序。

  2. 在编程中我没有遇到难以解决的问题。遇到唯一的问题是在求完数时,本来需要对一个数进行试除,然后计算该数的所有因子之和。我在for循环判断试除因子范围时,将i的界限写成了i <=Math.sqrt(n),但输出结果有误(什么也没输出)。通过调试,后来我将i 改为 i <= n/2,就能正确输出结果了。这是因为我一开始没有意识到因子有对称性这个特点。
  3. 最后,通过实验,我对基础算法进行了很好的复习。
  • 19
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值