UCB CS61B fa23 lab2(Debugging) 解析与答案

写在前面的废话

lab2 的难度不是很高,其主要设计思路就是帮助学生熟悉 Intellj IEDAdebugger 工具的使用。但是其中涉及了一些 Java 的语法,对 Java 小白不是很友好。再就是上一篇blog里我说要持续更新 CS61Blabproj ,所以这部分虽然不难,但还是写了这篇blog。

lab2 预计用时 1 ~ 3 小时(比 proj0 少多了 😦 )

如果以前接触过别的 debugger ,这里大部分内容对你来说都会比较简单。

one more times : 本人小白,希望路过的大佬手下留情

前言

这次的 lab2 要求我们找到三个密码来解除一个 “炸弹”💣 ,密码会在程序运行的时候产生,所以我们要用 debugger 来监视程序运行时变量的 value


三段代码一次呈现

先看代码,解释在后面

public class BombMain {
    public static void main(String[] args) {
        int phase = 2;
        if (args.length > 0) {
            phase = Integer.parseInt(args[0]);
        }
        // TODO: Find the correct inputs (passwords) to each phase using debugging techniques
        //原文的部分注释给删掉了
        Bomb b = new Bomb();
        if (phase >= 0) {
            b.phase0("39291226");
        }
        if (phase >= 1) {
            b.phase1(IntList.of(0,9,3,0,8));
        }
        if (phase >= 2) {
            int i = 0;
            String a  = "A ";
            while (i < 1336){
                a =a + "A ";
                i++;
            } //这里的奇怪循环后面会解释
            a = a + "-81201430";
            b.phase2(a);
        }
    }
}

Bomb Introduction (Phase 0)

这是 Bomb.java 文件中关于 Phase 0 的代码

    public void phase0(String password) {
        String correctPassword = shufflePassword("hello");
        if (!password.equals(correctPassword)) {
            System.out.println("Phase 0 went BOOM!");
            System.exit(1);
        }
        System.err.println("You passed phase 0 with the password \"" + password + "\"");
    }

这里出现了一个 password.equals() 的函数,这不是我们自己写的函数,而是一个库函数。需要强调,我们要学会自己查找库函数或者 Java 的标准语法,这里提供一个官方网址Java SE 21

上文函数的具体内容public boolean equals(Object anObject)

实际上,获取这个密码并不需要详细了解这个函数的功能,按如下方式设置断点,然后 “步过” 一次,可以看到我们的 passwors 和正确密码 correctPassword 都显示了出来。
断点位置
灰色波浪线的部分表示 这部分程序不会执行 (因为 if 条件为 false )

其实正常是在这里查看相关的变量的值,但是 Intellj IDEA 贴心的在相应的行上显示的相关值。
debugger
所以 password 就是 "39291226" 啦,填入到 BombMain.java 文件中就好啦


Visualizer (Phase 1)

这里强调让我们学习使用 Visualizer
就是这个
Java Visualizer
上图是 password 正确的时候 Java Visualizer 的显示

如果不改动开始时的代码

		if (phase >= 1) {
			b.phase1(null); // Figure this out too
        }

Java Visualizer 的显示是这样(在 Bomb.java 文件的46行处打断点)
Phase2
注意到 corrrectIntListPassword 指向了一个链表,我们需要让我们的 password 和这个链表相同,根据课程文档的提示,我们使用 IntList.of() 函数

/**
     * Method to create an IntList from an argument list.
     * You don't have to understand this code. We have it here
     * because it's convenient with testing. It's used like this:
     * <p>
     * IntList myList = IntList.of(1, 2, 3, 4, 5);
     * will create an IntList 1 -> 2 -> 3 -> 4 -> 5 -> null. 
     * <p>
     * You can pass in any number of arguments to IntList.of and it will work:
     * IntList mySmallerList = IntList.of(1, 4, 9);
     */
    public static IntList of(int... argList) {
        if (argList.length == 0)
            return null;
        int[] restList = new int[argList.length - 1];
        System.arraycopy(argList, 1, restList, 0, argList.length - 1);
        return new IntList(argList[0], IntList.of(restList));
    }

我们不需要完全明白这个函数的原理,只需要知道它可以创建一个链表即可。所以我们的 password

		if (phase >= 1) {
            b.phase1(IntList.of(0,9,3,0,8));
        }

Conditional Breakpoints (Phase 2)

这部分希望我们学会对断点进一步设置以便于 debug。其难点在于需要自己弄明白一点课外的 Java 语法

首先是public String[] split(String regex)
然后是public static int parseInt(String s)
还有 for (int item : array){}
(这三个是连接,可以直接跳转)

	public void phase2(String password) {
        String[] passwordPieces = password.split(" ");  //对应这里

        Random r = new Random(1337);
        Set<Integer> numbers = new HashSet<>();
        while (numbers.size() < 100000) {
            numbers.add(r.nextInt());
        }

        boolean correct = false;
        int i = 0;
        for (int number : numbers) {  //这里
            if (i == 1337 && Integer.parseInt(passwordPieces[i]) == number) {  //和这里
                correct = true;
            }
            i++;
        }
        if (!correct) {
            System.out.println("Phase 2 went BOOM!");
            System.exit(3);
        }
        System.err.println("You passed phase 2 with the password \"" + password + "\"");
    }

我们在检测密码的地方打断点( Bomb.java 文件的67行)结果如图
哈哈
如果你操作正常,你的运行结果和上图应该是不一样的 😃
有两个原因

  1. 没有对断点进一步设置
  2. password 不一样

断点可以这样设置
在这里插入图片描述
因为 if() 的第一个条件是 i == 1337 所以我们可以直接去到 i == 1337 的时候

**此时如果你已经明白上面提到的 三个函数 (这个连接不是很好用 😐 )你应该会意识到字符串数组 passwordPieces 的第1338个元素应该是 -81201430 我们的密码要有1337个空格,前1337项不重要,让第1338项为 -81201430 即可。

所以有如下代码

	if (phase >= 2) {
           int i = 0;
           String a  = "A ";
           while (i < 1336){
               a =a + "A ";
               i++;
           }
           a = a + "-81201430";
           b.phase2(a);
    }
    //这里 a = "A A A A A ... A A A -81201430" 'A'共1337个,没有实际含义,仅用于占位

课程文档给了这样一个提示
在这里插入图片描述
因此我认为我的思路是正确的 😃 离谱


结尾

到这里 lab2 就完成了,看一眼运行结果吧
运行结果
(”A ……“ 很长,不截了)

以后还会继续更新,欢迎同在自学 CS61B 小伙伴一起交流,也欢迎路过的大佬指点。

先前 oracle 的官方文档看不懂的可以看菜鸟教程 ,但还是推荐多看英文文档联系英语,所以之前没提菜鸟教程 😃

彻底结尾了,感谢阅读!!

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值