3

这是我的自学作业问题之一。

我应该写下这个程序的输出而不实际运行它。我了解这里的所有语法和变量传递,(并且我有答案)但由于某种原因,在纸上追踪它是行不通的。

有什么秘密的图表技术可以让一切井井有条吗?

对于有经验的程序员来说,手工解决这个问题只是儿戏吗?

谢谢

public class Mystery extends ConsoleProgram {
public void run() {
    ghost(13);
}

private void ghost(int x) {
    int y = 0;
    for (int i = 1; i < x; i *= 2) {
        y = witch(y, skeleton(x, i));
    }
    println("ghost: x = " + x + ", y = " + y);
}

private int witch(int x, int y) {
    x = 10 * x + y;
    println("witch: x = " + x + ", y = " + y);
    return x;
}

private int skeleton(int x, int y) {
    return x / y % 2;
}
}
4

5 回答 5

3

尝试用传入的数字写下一堆方法调用,例如:

run()
ghost(13)
skeleton(13,1)

等等

在每次方法调用时,找到一些暂存空间并写出变量并尝试计算代码的作用,直到获得返回值。然后获取该返回值并返回该方法堆栈中的最后一点并刮掉该方法。

例如,上面示例堆栈的顶部(底部)是skeleton(13,1),因此您尝试计算skeleton()当 x 为 13 且 y 为 1 时返回的内容。很简单,它是1。然后回到堆栈,看看返回值应该是什么。在这种情况下它是witch(),所以堆栈是:

run()
ghost(13)
witch(0,1)

并继续直到 run() 完成。

于 2012-08-05T05:12:09.823 回答
3

通常我使用有 2 列(内存和监视器)的表,如下所示:

====================
| Memory | Monitor |
====================
|        |         |
|        |         |
|        |         |
|        |         |
====================

内存就像调试中的手表。监视器是将在监视器中输出的内容

例如:

int x; // Declare X (Memory)
x=10; // fill with 10 (Memory)
System.out.println(x); // print it (Monitor)

如果我跟踪使用该表:

====================
| Memory | Monitor |
====================
| x=10   | 10      |
|        |         |
|        |         |
|        |         |
====================

我希望这能帮到您

更新:我想解释更多细节:

让我们看一下我之前创建的代码

1. int x; // Declare X (Memory)
2. x=10; // fill with 10 (Memory)
3. System.out.println(x); // print it (Monitor)

第 1 步:我声明 X。所以表格如下所示:

====================
| Memory | Monitor |
====================
| x      |         |
|        |         |
|        |         |
|        |         |
====================

第 2 步:我用 10 填充 x,然后看起来像这样:

====================
| Memory | Monitor |
====================
| x=10   |         |
|        |         |
|        |         |
|        |         |
====================

第 3 步:我打印 x

====================
| Memory | Monitor |
====================
| x=10   | 10      |
|        |         |
|        |         |
|        |         |
====================
于 2012-08-05T05:13:46.390 回答
2

您可以做的是在一张纸上实际模拟每个范围(思考方法),并在其中写下所有变量。

如果你调用一个方法,你会拿一张新纸并将它放在现有的纸堆上。如果你从一个方法返回,你会把最上面的一块扔掉。如果您有课程,则需要单独的表格。

那是你能做的。但是没有真正的程序员会这样做。

你要做的是:

  • 通过查看代码了解基本结构。例如:它会在打印“ghost”之前调用“witch”几次。

  • 了解您指导的详细信息,并使用日志记录/系统输出语句和/或调试器仔细检查您的想法并实际执行代码。

那么运动没用吗?不要这么想。虽然你不是自己做的,但它是思考代码的一部分,你总是以一种或另一种方式这样做。

于 2012-08-05T05:10:51.407 回答
0

由于run()它是唯一可见的main()(因此能够被调用)的方法,因此您只需要执行变量到值的替换。将变量的值放在它们出现并生成时。

一旦掌握了替换变量值的窍门,这并不难,这是一种非常宝贵的调试策略。

于 2012-08-05T05:09:59.117 回答
0

您可以展开循环:

for (int i = 1; i < 13; i *= 2) {
    E[i]
}

变成

E[1]; E[2]; E[4]; E[8];

这里没有递归,所以其余的应该很简单。

于 2012-08-05T05:11:11.820 回答