文档部分比较详尽的部分就不记录了,只记录一些个人认为值得学习的部分或者自己遇到的问题

Lab 1 - Setup

到CS61B 2024往后的官网找到Auditing CS61B部分,按照文档登录Gradescope,简单来说就是进入后输入课程码MB7ZPY

但是我看Gradescope的SP2021版本好像还有五个月就到期了,不知道以后还能不能用,如果不能用,这部分教程恐怕就没用了

Getting the Starter Files

首先创建一个GitHub仓库
然后在本地clone下来你的仓库

1
git clone https://github.com/YourName/YourRepoName.git

进入YourRepoName这个文件夹,然后添加skeleton远程仓库,这一步是让git记住一个叫skeleton的远程仓库,之后我们通过pull就可以拿到Berkeley官方仓库的作业模板,实际上还能之后随时拉取更新

1
git remote add skeleton https://github.com/Berkeley-CS61B/skeleton-sp21.git

使用下面这个命令来检查目前的远程仓库,会有origin和skeleton

1
git remote -v

接着在当前文件夹(也就是克隆到本地的空仓库)拉取代码

1
git pull skeleton master

Pushing Your Work to GitHub

在原先的文件夹输入下面命令

1
2
3
4
5
6
7
8
9
10
11
❯ git status
On branch main
Your branch is based on 'origin/main', but the upstream is gone.
(use "git branch --unset-upstream" to fixup)

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: lab1/Collatz.java

no changes added to commit (use "git add" and/or "git commit -a")

clone 会复制远程仓库,并自动创建本地分支与远程分支的跟踪关系。但如果远程仓库为空,没有任何分支,Git 无法真正建立对应的 origin/main,虽然本地的main分支基于远程仓库 origin/main ,但是 origin/main 这个分支在远程仓库都不存在,因此会出现 upstream gone

把修改的文件添加到暂存区

1
2
3
4
5
6
❯ git add lab1/*
The following paths are ignored by one of your .gitignore files:
lab1/lab1.iml
lab1/out
hint: Use -f if you really want to add them.
hint: Disable this message with "git config set advice.addIgnoredFile false"

检查是否成功add

1
2
3
4
5
6
7
8
❯ git status
On branch main
Your branch is based on 'origin/main', but the upstream is gone.
(use "git branch --unset-upstream" to fixup)

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: lab1/Collatz.java

提交修改

1
2
3
❯ git commit -m "done with Collatz"
[main 21cb83a] done with Collatz
1 file changed, 5 insertions(+), 7 deletions(-)

When you do this, Git will make a recording of the changes you made to Collatz.java. It will also record the message “done with Collatz” along with the recording. These messages can be helpful if you’re looking to find a specific change at some point in the past.

1
2
3
4
5
6
❯ git status
On branch main
Your branch is based on 'origin/main', but the upstream is gone.
(use "git branch --unset-upstream" to fixup)

nothing to commit, working tree clean

接下来把本地仓库提交到远程仓库

1
git push -u origin main

把本地仓库上传到origin,也就是远程的github仓库,main指的是本地的main分支,这句命令其实是git push -u origin main:main的省略,最后的main指origin远程仓库的main分支

-u表示建立跟踪关系,即让本地main记住上游是origin/main,设置上游的用处有

场景 用处
git status 可以提示本地比上游领先几个提交、落后几个提交
git pull 不写仓库和分支时,知道默认从哪里获取并整合
git push 在你这种同名分支、常见默认配置下,知道默认往哪里推送

以后处于本地main分支时,直接git push就等价于git push origin main,即把本地main推送到origin仓库的远程main

What does add do? Add marks a file (or set of files) as something you want to backup.

What does commit do? Commit creates a backup with the given message.

If commit makes a backup but not to GitHub, where did it back up my files? On your own computer!

What good is a backup on your own computer? If you want to go back to an old version, you can do that using git using other commands. By storing the backup locally, restoring old backups is very fast and doesn’t require an internet connection.

What if my computer dies, isn’t the backup made by commit lost? Yes. That’s why there’s a push command.

Lab 2 - JUnit Tests and Debugging

设置断点后,调试时会停在断点处
step into是执行下一步
step over是跳过函数内部直接得到结果,并跳到下一句
steo out是跳出当前所在的函数,再step into就会到原来调用函数那一句的下一句

Lab 3 - Timing Tests and Randomized Comparison Tests

计时测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package timingtest;
import edu.princeton.cs.algs4.Stopwatch;

/**
* Created by hug.
*/
public class TimeAList {
private static void printTimingTable(AList<Integer> Ns, AList<Double> times, AList<Integer> opCounts) {
System.out.printf("%12s %12s %12s %12s\n", "N", "time (s)", "# ops", "microsec/op");
System.out.printf("------------------------------------------------------------\n");
for (int i = 0; i < Ns.size(); i += 1) {
int N = Ns.get(i);
double time = times.get(i);
int opCount = opCounts.get(i);
double timePerOp = time / opCount * 1e6;
System.out.printf("%12d %12.2f %12d %12.2f\n", N, time, opCount, timePerOp);
}
}

public static void main(String[] args) {
timeAListConstruction();
}

public static void timeAListConstruction() {
// TODO: YOUR CODE HERE
int n = 1000;
AList<Integer> Ns = new AList<>();
AList<Double> times = new AList<>();
AList<Integer> opCounts = Ns;
for (n = 1000; n <= 128000; n *= 2) {
Ns.addLast(n);
AList<Integer> list = new AList<>();

/**
* Record the time.
*/
Stopwatch sw = new Stopwatch();
for (int i = 0; i < n; ++i) {
list.addLast(2);
}
double timeInSeconds = sw.elapsedTime();
times.addLast(timeInSeconds);
}
printTimingTable(Ns, times, opCounts);
}
}

随机测试,每次随机进行一个操作,并且比较正确的数据结构和存在问题的数据结构,看行为是否相符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Test
public void randomizedTest() {
AListNoResizing<Integer> L = new AListNoResizing<>();
BuggyAList<Integer> buggyAList = new BuggyAList<>();
int N = 5000;
for (int i = 0; i < N; i += 1) {
int operationNumber = StdRandom.uniform(0, 4);
if (operationNumber == 0) {
// addLast
int randVal = StdRandom.uniform(0, 100);
L.addLast(randVal);
buggyAList.addLast(randVal);
} else if (operationNumber == 1) {
// size
int size = L.size();
int buggyAListSize = buggyAList.size();
assertEquals(size, buggyAListSize);

} else if (operationNumber == 2 && L.size() > 0) {
// removeLast
int last = L.removeLast();
int buggyAListLast = buggyAList.removeLast();
assertEquals(last, buggyAListLast);
} else if (operationNumber == 3 && L.size() > 0) {
// getLast
int last = L.getLast();
int buggyAListLast = buggyAList.getLast();
assertEquals(last, buggyAListLast);
}
}
}

Resume Program
调试时点这个,程序继续运行直到下一个断点,或者遇到其他暂停事件,或者运行结束

Conditional Breakpoint
右键设置的断点,跳出的弹窗中可以在"Condition: "下那一栏里输入条件,再点击resume后,程序就会运行直到再次遇到下一个断点,如果下一个断点是条件断点,必须满足断点的条件才会停

Exception Breakpoint
异常断点在指定异常抛出时暂停程序,可以直接检查异常现场的变量和调用栈。例如,在数组越界异常发生时暂停。这样,我们就能在程序即将要崩溃时停下来看看发生了什么

在IntelliJ里点击Run,然后点View Breakpoints,在Any exception框里打勾,并打勾Condition:,在框里输入
this instanceof java.lang.ArrayIndexOutOfBoundsException

之后再debug,程序就会停在异常即将发生的时候

NOTE: If you use the debug feature without specifying a condition, your code will stop in some various mysterious places. Make sure you never have “Any Exception” checked without having a specified condition. This is because the process of starting JUnit tests generates a bunch of exceptions that ultimately get ignored. This is well beyond the scope of our class. If you’re done using an execution breakpoint, you should uncheck the “Java Exceptions Breakpoints” box in the top left.