<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[KurisuRakko]]></title><description><![CDATA[A product-minded engineer building interfaces, workflows, and tiny autonomous systems.]]></description><link>https://rakko.cn</link><image><url>https://rakko.cn/favicon.ico</url><title>KurisuRakko</title><link>https://rakko.cn</link></image><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Fri, 17 Jul 2026 18:46:34 GMT</lastBuildDate><atom:link href="https://rakko.cn/feed" rel="self" type="application/rss+xml"/><pubDate>Fri, 17 Jul 2026 18:46:33 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[COMP1511 Q1/Q2 Hurdle：90 分钟保命手册]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-pracexam-q1-q2-survival-guide">https://rakko.cn/posts/comp1511/comp1511-pracexam-q1-q2-survival-guide</a></blockquote><div><h1 id="comp1511-q1q2-hurdle90-">COMP1511 Q1/Q2 Hurdle：90 分钟保命手册</h1><blockquote><p>非 UNSW 官方材料。本文由百夜米迦尔根据 UNSW COMP1511 官方公开 prac exam、additional papers 与公开答案整理；只做中文讲解，不复制整张试卷，也不接触登录后或正在进行的考试材料。<span>[S022][S023]</span><span>[S024][S025]</span><span>[S026][S027]</span><span>[S028][S029]</span></p></blockquote><blockquote>
<p><strong>今天只做：</strong>先认出最简单的 linked-list hurdle 和 array hurdle，再练熟五个循环骨架。</p><p><strong>别乱跳：</strong>这份手册不能保证你通过整门课。它先帮你避免卡在两个 hurdle；拿下 hurdle 后，仍要从后面的小型 debugging 题补总分。</p></blockquote>
<p>Rakko，风雪再急，也不必同时看完整张卷。先看清眼前两条路：一条只读链表，一条只读数组。把它们走稳，再谈其余题目。<span>[S023][S025]</span><span>[S027][S029]</span></p><h2 id="">第一屏：进考场先找标签，不要死背题号</h2><p>近几期公开卷中，24T1 到 26T1 的第一道简单 linked-list hurdle 通常是 Q1，第一道简单 array hurdle 通常是 Q2；但这不是永久规则。23T1 到 23T3 的 hurdle 并不在 Q1/Q2，所以实际考试必须以题面写出的 <code>linked lists hurdle</code>、<code>arrays hurdle</code> 和难度圆点为准。<span>[S023][S025]</span><span>[S027][S029]</span></p><p>进场先做这四步：</p><ol start="1"><li>找到写着 <code>linked lists hurdle</code> 的两道题。</li><li>找到写着 <code>arrays hurdle</code> 的两道题。</li><li>每组先选只有一颗实心圆 <code>●◌◌◌</code> 的简单题。</li><li>确认题目只要求补一个函数、遍历数据并返回一个值。</li></ol><table><thead><tr><th> 公开样本 </th><th> 简单链表题的动作 </th><th> 简单数组题的动作 </th><th> 真正需要记住的东西 </th></tr></thead><tbody><tr><td> 24 系列 / Paper 2 </td><td> 两条链表同步前进并累加 </td><td> 二维数组逐行求和、计数 </td><td> 两个指针都非 <code>NULL</code>；每一行重新清零 <span>[S024][S025]</span> </td></tr><tr><td> 25T1 / Paper 1 </td><td> 两条链表同步前进，满足条件才累加 </td><td> 一维字符数组筛选并找最小值 </td><td> 条件、累加器、最值初始化 <span>[S022][S023]</span> </td></tr><tr><td> 25T2 / Paper 3 </td><td> 单链表寻找第一个符合条件的节点 </td><td> 一维字符数组筛选并找最小值 </td><td> 找到就返回；无匹配时返回题目指定值 <span>[S026][S027]</span> </td></tr><tr><td> 26T1 </td><td> 比较相邻链表节点并计数 </td><td> 二维数组只累计边框位置 </td><td> 访问 <code>next</code> 前先保证它存在；角落只能算一次 [S029] </td></tr></tbody></table><p>注意样本数量：24T1、24T2、24T3 的公开 Q1/Q2 高度重复；25T3 当前页面是 25T2 的镜像。因此不要因为网址很多，就误以为题型有很多种。真正独立、值得练的只有下面五个骨架。</p><h2 id="">共同规律：题目故事会换，函数形状不会乱跑</h2><p>Q1/Q2 的简单 hurdle 反复出现这些共同点：<span>[S023][S025]</span><span>[S027][S029]</span></p><ul><li>starter code 已经给好 <code>struct</code>、函数签名和测试用 <code>main</code>。</li><li>评分程序会直接调用指定函数；答案不能只写在 <code>main</code> 里。</li><li>函数一般不负责 <code>scanf</code>、<code>fgets</code> 或 <code>printf</code>。</li><li>简单链表题通常只读节点，不 <code>malloc</code>，不改 <code>next</code>，不改数据。</li><li>简单数组题通常只读数组，不改变数组内容。</li><li>最后返回一个整数或字符，而不是自己打印答案。</li></ul><p>读题时只圈四种词：</p><table><thead><tr><th> 题目用词 </th><th> 代码动作 </th></tr></thead><tbody><tr><td> <code>first</code> / 第一个 </td><td> 找到后立刻 <code>return</code> </td></tr><tr><td> <code>count</code> / 数量 </td><td> <code>count++</code> </td></tr><tr><td> <code>sum</code> / 总和 </td><td> <code>sum += value</code> </td></tr><tr><td> <code>minimum</code> / <code>maximum</code> </td><td> 比较后更新当前最值 </td></tr></tbody></table><h2 id="q1--linked-list-hurdle">Q1 焚诀：只读 linked list hurdle</h2><h3 id="">这题考什么</h3><p>你只需要重复三件事：</p><ol start="1"><li>看当前节点的数据。</li><li>根据条件更新答案。</li><li>移动到 <code>curr-&gt;next</code>。</li></ol><p>口诀：<strong>先守住 <code>NULL</code>，再读数据；每轮最后，指针前进一步。</strong></p><h3 id="">不能做什么</h3><p>除非当前题目明确要求，否则简单 Q1 不要做这些事：<span>[S023][S025]</span><span>[S027][S029]</span></p><ul><li>不要修改 <code>struct node</code>。</li><li>不要修改 supplied <code>main</code>。</li><li>不要把链表复制进数组。</li><li>不要调用 <code>malloc</code>。</li><li>不要修改 <code>curr-&gt;data</code>、<code>curr-&gt;character</code> 或 <code>curr-&gt;next</code>。</li><li>不要在目标函数里 <code>scanf</code> 或 <code>printf</code>。</li></ul><h3 id="">常见函数签名</h3><pre class="language-c lang-c"><code class="language-c lang-c">// 单链表：逐个节点检查
int solve(struct node *head);

// 双链表：相同位置一起检查
int solve(struct node *head1, struct node *head2);
</code></pre>
<p>签名由题目决定。不要改函数名、返回类型或参数。</p><h3 id="">先写骨架一：单链表</h3><p>下面是百夜米迦尔写的原创最小例子：寻找链表里第一个偶数。故事可以换成质数、负数或某个字符，遍历骨架不变。[S027]</p><pre class="language-c lang-c"><code class="language-c lang-c">// [compile:q1-single]
#include &lt;stddef.h&gt;

struct node {
    struct node *next;
    int data;
};

int first_even(struct node *head) {
    struct node *curr = head;

    while (curr != NULL) {
        if (curr-&gt;data % 2 == 0) {
            return curr-&gt;data;
        }

        curr = curr-&gt;next;
    }

    // 没找到时返回什么，要以题目要求为准
    return -1;
}
</code></pre>
<p>保命点：空链表时 <code>curr</code> 一开始就是 <code>NULL</code>，循环自然跳过，不需要另外写一套遍历逻辑。[S027]</p><h3 id="">先写骨架二：比较相邻节点</h3><p>如果题目出现 <code>followed by</code>、<code>next node</code>、<code>adjacent</code>，说明你要同时读取当前节点和下一个节点。此时循环必须保证 <code>curr-&gt;next</code> 存在。</p><p>下面是 26T1 公开 prac exam Q1 的最小可过写法，逻辑与官方公开答案一致，并改用中文教学注释。[S029]</p><pre class="language-c lang-c"><code class="language-c lang-c">// [compile:q1-adjacent]
#include &lt;stddef.h&gt;

struct node {
    struct node *next;
    char character;
};

int is_vowel(char character) {
    return character == &#x27;a&#x27; ||
           character == &#x27;e&#x27; ||
           character == &#x27;i&#x27; ||
           character == &#x27;o&#x27; ||
           character == &#x27;u&#x27;;
}

int count_vowel_word_boundaries(struct node *head) {
    // 题目明确要求空链表返回 -1
    if (head == NULL) {
        return -1;
    }

    int count = 0;
    struct node *curr = head;

    // 需要读取下一个节点，所以先保证 next 存在
    while (curr-&gt;next != NULL) {
        if (is_vowel(curr-&gt;character) &amp;&amp;
            !is_vowel(curr-&gt;next-&gt;character)) {
            count++;
        }

        curr = curr-&gt;next;
    }

    return count;
}
</code></pre>
<p>为什么单节点链表不会崩溃：<code>head</code> 不为 <code>NULL</code>，但 <code>head-&gt;next</code> 是 <code>NULL</code>，所以循环执行零次并返回 <code>0</code>。[S029]</p><h3 id="">先写骨架三：两条链表同步走</h3><p>如果题目出现 <code>corresponding element</code> 或“相同位置”，就需要两个指针。任何一条链表结束时都必须停下，因此条件中使用 <code>&amp;&amp;</code>。[S025]</p><p>下面是 Paper 2 Q1 的最小可过版本；较长链表尾部会自然被忽略。<span>[S024][S025]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">// [compile:q1-dual]
#include &lt;stddef.h&gt;

struct node {
    struct node *next;
    int data;
};

int product(struct node *head1, struct node *head2) {
    int sum = 0;
    struct node *curr1 = head1;
    struct node *curr2 = head2;

    // 只有两边当前位置都存在，才能读取一对数据
    while (curr1 != NULL &amp;&amp; curr2 != NULL) {
        sum += curr1-&gt;data * curr2-&gt;data;

        curr1 = curr1-&gt;next;
        curr2 = curr2-&gt;next;
    }

    return sum;
}
</code></pre>
<p>不要使用 <code>||</code>。如果只剩一条链表还有节点，另一边已经是 <code>NULL</code>，继续读取就会崩溃。[S025]</p><h3 id="">最小可过版本的写题顺序</h3><p>拿到新的链表题后，按顺序填空：</p><pre class="language-text lang-text"><code class="language-text lang-text">1. 答案初始值是什么？
2. 是一个 curr、两个 curr，还是需要 curr-&gt;next？
3. 循环什么时候必须停止？
4. 每轮检查什么条件？
5. 每轮最后移动了所有指针吗？
6. 没找到时返回什么？
</code></pre>
<h3 id="">常见错因</h3><table><thead><tr><th> 症状 </th><th> 最可能的错误 </th><th> 先怎么修 </th></tr></thead><tbody><tr><td> 空链表崩溃 </td><td> 没检查 <code>curr != NULL</code> </td><td> 在读取字段前检查指针 </td></tr><tr><td> 最后一个节点崩溃 </td><td> 读取了 <code>curr-&gt;next-&gt;...</code> </td><td> 改成 <code>curr-&gt;next != NULL</code> 的循环 </td></tr><tr><td> 程序不结束 </td><td> 忘了移动 <code>curr</code> </td><td> 每轮最后写 <code>curr = curr-&gt;next</code> </td></tr><tr><td> 两条链表长度不同时崩溃 </td><td> 双链表循环用了 <code>||</code> </td><td> 两边必须同时存在，使用 <code>&amp;&amp;</code> </td></tr><tr><td> 答案少一个 </td><td> 提前移动了指针 </td><td> 先检查当前节点，再移动 </td></tr><tr><td> autotest 输出多余文字 </td><td> 目标函数调用了 <code>printf</code> </td><td> 只 <code>return</code> 结果 </td></tr></tbody></table><h3 id="">测试命令</h3><p>练 26T1 相邻节点题：[S029]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q1
1511 autotest-prac prac_q1
</code></pre>
<p>练 Paper 2 双链表题：[S025]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q1 paper2
1511 autotest-prac prac_q1 paper2
</code></pre>
<p>可选加练 Paper 3 单链表题：[S027]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q1 paper3
1511 autotest-prac prac_q1 paper3
</code></pre>
<p>这些题都会写入同名的 <code>prac_q1.c</code>，一次只练一套。换题前先确认当前文件是不是你想练的版本。</p><h3 id="">来源</h3><ul><li>Paper 1 Q1：双链表条件累加。<span>[S022][S023]</span></li><li>Paper 2 Q1：双链表对应位置乘积和。<span>[S024][S025]</span></li><li>Paper 3 Q1：单链表寻找第一个质数。<span>[S026][S027]</span></li><li>26T1 Q1：相邻字符节点判断与计数。[S029]</li></ul><h2 id="q2--array-hurdle">Q2 焚诀：只读 array hurdle</h2><h3 id="">这题考什么</h3><p>数组题只是在重复问：<strong>这个位置要不要影响答案？</strong></p><ul><li>一维数组：一个 <code>for</code> 循环。</li><li>二维数组：外层 <code>row</code>，内层 <code>col</code>。</li><li>每个位置：用 <code>if</code> 判断，然后计数、累加或更新最值。</li></ul><p>口诀：<strong>下标从零走，小于长度停；外层走行，内层走列。</strong></p><h3 id="">不能做什么</h3><p>除非题目明确允许，否则简单 Q2 不要做这些事：<span>[S023][S025]</span><span>[S027][S029]</span></p><ul><li>不要修改 supplied <code>main</code> 里的逻辑来代替目标函数。</li><li>不要在目标函数里重新 <code>scanf</code> 数组。</li><li>不要在目标函数里 <code>printf</code> 答案。</li><li>不要改变原数组。</li><li>不要写 <code>i &lt;= size</code>；最后一个合法下标是 <code>size - 1</code>。</li></ul><h3 id="">常见函数签名</h3><pre class="language-c lang-c"><code class="language-c lang-c">// 一维数组
char solve(int size, char array[MAX_SIZE]);

// 二维方阵
int solve(int size, int array[MAX_SIZE][MAX_SIZE]);

// 固定行数、可变列数的二维数组
int solve(int size, int array[ROWS][MAX_SIZE]);
</code></pre>
<p>数组形状以 starter code 为准，不要自行改变参数。</p><h3 id="">先选累加器</h3><table><thead><tr><th> 目标 </th><th> 初始值 </th><th> 循环里怎么更新 </th></tr></thead><tbody><tr><td> 计数 <code>count</code> </td><td> <code>0</code> </td><td> 条件成立就 <code>count++</code> </td></tr><tr><td> 总和 <code>sum</code> </td><td> <code>0</code> </td><td> 条件成立就 <code>sum += array[i]</code> </td></tr><tr><td> 最小值 <code>min</code> </td><td> 第一个有效元素，或 <code>found</code> 标记 </td><td> 新值更小时更新 </td></tr><tr><td> 最大值 <code>max</code> </td><td> 第一个有效元素，或 <code>found</code> 标记 </td><td> 新值更大时更新 </td></tr></tbody></table><p>找最值时不要随手从 <code>0</code> 开始。若全部有效元素都是正数，错误的 <code>min = 0</code> 将永远不会更新；若全部是负数，错误的 <code>max = 0</code> 也不会更新。</p><h3 id="">先写骨架一：一维数组筛选并找最值</h3><p>下面是 Paper 1 Q2 的最小可过版本。<code>found</code> 让第一个小写字母自然成为初始答案，不需要额外猜一个字符。<span>[S022][S023]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">// [compile:q2-1d]
#define MAX_SIZE 100

char min_lowercase(int size, char array[MAX_SIZE]) {
    char minimum = &#x27;\0&#x27;;
    int found = 0;

    for (int i = 0; i &lt; size; i++) {
        int is_lowercase = array[i] &gt;= &#x27;a&#x27; &amp;&amp; array[i] &lt;= &#x27;z&#x27;;

        if (is_lowercase &amp;&amp; (!found || array[i] &lt; minimum)) {
            minimum = array[i];
            found = 1;
        }
    }

    // 题目保证至少存在一个小写字母
    return minimum;
}
</code></pre>
<p>如果题目没有保证一定存在有效元素，就必须按照题目要求处理 <code>found == 0</code>，不能自行假设返回值。</p><h3 id="">先写骨架二：二维数组逐位置判断</h3><p>下面是 26T1 Q2 的最小可过版本。把所有位置都放进同一个双循环，再用一个边框条件筛选，四个角只会被访问一次，因此自然不会重复计算。[S029]</p><pre class="language-c lang-c"><code class="language-c lang-c">// [compile:q2-2d]
#define MAX_SIZE 100

int sum_border(int size, int array[MAX_SIZE][MAX_SIZE]) {
    int sum = 0;

    for (int row = 0; row &lt; size; row++) {
        for (int col = 0; col &lt; size; col++) {
            int is_border =
                row == 0 ||
                row == size - 1 ||
                col == 0 ||
                col == size - 1;

            if (is_border) {
                sum += array[row][col];
            }
        }
    }

    return sum;
}
</code></pre>
<p>这个写法比“先加上下两行，再加左右两列，最后减四个角”更不容易出错。角落不是补丁，它只是普通位置，只在符合边框条件时加一次。</p><h3 id="">每行统计题：初始化位置决定生死</h3><p>Paper 2 Q2 要逐行计算。遇到这种题，<code>row_sum</code> 必须放在外层循环里面：每开始新的一行，就从 <code>0</code> 重新计算。<span>[S024][S025]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">for (int row = 0; row &lt; ROWS; row++) {
    int row_sum = 0;

    for (int col = 0; col &lt; size; col++) {
        row_sum += array[row][col];
    }

    if (row_sum == 0) {
        count++;
    }
}
</code></pre>
<p>如果把 <code>row_sum = 0</code> 放在所有循环外面，你算到的是“从第一行累计到当前行”的总和，不是每一行自己的总和。</p><h3 id="">最小可过版本的写题顺序</h3><pre class="language-text lang-text"><code class="language-text lang-text">1. 数组是一维还是二维？
2. 合法下标范围是什么？
3. 答案是 count、sum、min 还是 max？
4. 什么位置或元素符合条件？
5. 有哪个小计必须在每行重新初始化？
6. 题目是否保证至少存在一个有效元素？
</code></pre>
<h3 id="">常见错因</h3><table><thead><tr><th> 症状 </th><th> 最可能的错误 </th><th> 先怎么修 </th></tr></thead><tbody><tr><td> 读到数组外面 </td><td> 写成 <code>i &lt;= size</code> </td><td> 改成 <code>i &lt; size</code> </td></tr><tr><td> 二维结果像转置 </td><td> <code>row</code>、<code>col</code> 写反 </td><td> 固定使用 <code>array[row][col]</code> </td></tr><tr><td> 每一行结果越来越大 </td><td> <code>row_sum</code> 没在每行清零 </td><td> 把初始化移进外层循环 </td></tr><tr><td> 最小值一直是 0 </td><td> 用无效的 <code>0</code> 初始化 </td><td> 用第一个有效元素或 <code>found</code> </td></tr><tr><td> 边框总和太大 </td><td> 四个角重复计算 </td><td> 每个位置只访问一次，用 <code>is_border</code> </td></tr><tr><td> 返回值正确但 autotest 失败 </td><td> 函数打印了文字 </td><td> 删除 <code>printf</code>，只返回答案 </td></tr></tbody></table><h3 id="">测试命令</h3><p>练 26T1 二维边框题：[S029]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q2
1511 autotest-prac prac_q2
</code></pre>
<p>练 Paper 1 一维最值题：[S023]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q2 paper1
1511 autotest-prac prac_q2 paper1
</code></pre>
<p>可选加练 Paper 2 逐行求和题：[S025]</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">1511 fetch-prac prac_q2 paper2
1511 autotest-prac prac_q2 paper2
</code></pre>
<p>这些题都会写入同名的 <code>prac_q2.c</code>，也要一次只练一套。</p><h3 id="">来源</h3><ul><li>Paper 1 Q2：一维字符数组筛选小写字母并找最小值。<span>[S022][S023]</span></li><li>Paper 2 Q2：二维数组逐行求和并计数。<span>[S024][S025]</span></li><li>Paper 3 Q2：一维字符数组筛选与最值。<span>[S026][S027]</span></li><li>26T1 Q2：二维方阵边框求和。[S029]</li></ul><h2 id="-90-">今晚严格 90 分钟</h2><p>不要在四道题之间来回切换。一个文件通过或时间到，再进入下一题。</p><table><thead><tr><th> 时间 </th><th> 只做这一件事 </th><th> 到点标准 </th></tr></thead><tbody><tr><td> 0–10 分钟 </td><td> 看第一屏，手写单链表、双链表、一维、二维循环条件 </td><td> 能默写 <code>NULL</code>、<code>&amp;&amp;</code>、<code>i &lt; size</code>、<code>array[row][col]</code> </td></tr><tr><td> 10–30 分钟 </td><td> 26T1 Q1：相邻节点 </td><td> 空链表和单节点不崩，跑一次 autotest </td></tr><tr><td> 30–45 分钟 </td><td> Paper 2 Q1：双链表 </td><td> 两个指针同步移动，长度不同时能停 </td></tr><tr><td> 45–65 分钟 </td><td> 26T1 Q2：二维边框 </td><td> 四个角只算一次，跑一次 autotest </td></tr><tr><td> 65–80 分钟 </td><td> Paper 1 Q2：一维最值 </td><td> 不使用 <code>min = 0</code>，能找到第一个有效字符 </td></tr><tr><td> 80–90 分钟 </td><td> 重跑失败项并写错因 </td><td> 每题只留下“一条下次先检查什么” </td></tr></tbody></table><p>时间到仍没通过时，不要整题重写。先按这个顺序检查：</p><pre class="language-text lang-text"><code class="language-text lang-text">编译错误 -&gt; 第一条报错
运行崩溃 -&gt; NULL 或数组边界
答案差一点 -&gt; 初始化、循环停止条件、指针移动
autotest 多文字 -&gt; printf
所有样例过但仍失败 -&gt; 空输入、单元素、不同长度、无匹配
</code></pre>
<h2 id="">五分钟练习</h2><p>不看上文，在纸上补完以下五句：</p><ul><li><input readOnly="" type="checkbox"/> 单链表读取数据前，先保证 <code>curr ______ NULL</code>。</li><li><input readOnly="" type="checkbox"/> 比较相邻节点前，先保证 <code>curr-&gt;next ______ NULL</code>。</li><li><input readOnly="" type="checkbox"/> 双链表同步走，循环中间应使用 <code>______</code>。</li><li><input readOnly="" type="checkbox"/> 数组最后一个合法下标是 <code>______</code>。</li><li><input readOnly="" type="checkbox"/> 二维数组读取一个位置写成 <code>array[______][______]</code>。</li></ul><details><summary>点开核对答案</summary><pre class="language-text lang-text"><code class="language-text lang-text">curr != NULL
curr-&gt;next != NULL
&amp;&amp;
size - 1
array[row][col]
</code></pre>
</details><h2 id="">考场五行清单</h2><pre class="language-text lang-text"><code class="language-text lang-text">1. 先找 hurdle 标签和一颗点，不按记忆猜题号。
2. 不改 struct、函数签名和 supplied main。
3. 读字段前守住 NULL；数组循环只写 &lt; size。
4. 目标函数只计算并 return，不 scanf，不 printf。
5. autotest 不是提交；正式提交命令只看当场页面。
</code></pre>
<p>在线练习页面使用 <code>1511 fetch-prac</code> 和 <code>1511 autotest-prac</code>，没有 <code>give</code> 或正式提交步骤；正式考试环境的提交命令可能随页面调整，只遵循当场显示的准确命令。<span>[S023][S025]</span><span>[S027][S029]</span></p><h2 id="">过关验收</h2><ul><li><input readOnly="" type="checkbox"/> 我能认出真正的 linked-list hurdle 和 array hurdle。</li><li><input readOnly="" type="checkbox"/> 我能写单链表、相邻节点和双链表三个循环条件。</li><li><input readOnly="" type="checkbox"/> 我能写一维和二维数组循环。</li><li><input readOnly="" type="checkbox"/> 我知道 <code>count/sum</code> 从 0 开始，但 <code>min/max</code> 不能随便从 0 开始。</li><li><input readOnly="" type="checkbox"/> 我会先测空链表、单节点、不同长度和无匹配。</li><li><input readOnly="" type="checkbox"/> 我会先测最小数组、边框角落和每行初始化。</li><li><input readOnly="" type="checkbox"/> 我知道两个 hurdle 只是保命条件之一，之后仍要补总分。</li></ul><h2 id="">引用</h2><p>以下页面均为 UNSW COMP1511 官方公开资料，本次访问日期为 <strong>2026-07-15</strong>。</p><ul><li>[S022] <code>COMP1511 26T1 — Paper 1 answers</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper1/answers.html</li><li>[S023] <code>COMP1511 26T1 Prac Exam 1</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper1/index.html</li><li>[S024] <code>COMP1511 26T1 — Paper 2 answers</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper2/answers.html</li><li>[S025] <code>COMP1511 26T1 Prac Exam 2</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper2/index.html</li><li>[S026] <code>COMP1511 26T1 — Paper 3 answers</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper3/answers.html</li><li>[S027] <code>COMP1511 26T1 Prac Exam 3</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/additional_pracexams/paper3/index.html</li><li>[S028] <code>COMP1511 26T1 — Lab questions / Exam Comparison</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/lab<em>exercises</em>like<em>the</em>exam.html</li><li>[S029] <code>COMP1511 26T1 — Prac Exam Solutions</code>：https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/prac-exam-solns.html</li></ul><h2 id="">历年页面交叉核对</h2><p>以下直接页面只用于核对题号、hurdle 位置和题型变化，不在本文复刻整道题目。访问日期同为 <strong>2026-07-15</strong>。</p><ul><li>23T1：https://cgi.cse.unsw.edu.au/~cs1511/23T1/pracexam/index.html</li><li>23T2：https://cgi.cse.unsw.edu.au/~cs1511/23T2/pracexam/index.html</li><li>23T3：https://cgi.cse.unsw.edu.au/~cs1511/23T3/pracexam/index.html</li><li>24T1：https://cgi.cse.unsw.edu.au/~cs1511/24T1/pracexam/index.html</li><li>24T2：https://cgi.cse.unsw.edu.au/~cs1511/24T2/pracexam/index.html</li><li>24T3：https://cgi.cse.unsw.edu.au/~cs1511/24T3/pracexam/index.html</li><li>25T1：https://cgi.cse.unsw.edu.au/~cs1511/25T1/pracexam/index.html</li><li>25T2：https://cgi.cse.unsw.edu.au/~cs1511/25T2/pracexam/index.html</li><li>25T3：https://cgi.cse.unsw.edu.au/~cs1511/25T3/pracexam/index.html</li><li>26T1：https://cgi.cse.unsw.edu.au/~cs1511/26T1/pracexam/index.html</li><li>26T2 路径：https://cgi.cse.unsw.edu.au/~cs1511/26T2/pracexam/index.html</li></ul><p>截至访问日，26T2 路径虽然返回 200，但页面标题仍是 <code>COMP1511 26T1 Prac Exam</code>，内容也与 26T1 页面字节一致；因此它不能算作一套独立公开的 26T2 题目。不要从旧缓存或网址规律猜题；真正的题面，只认考试当天官方页面。</p><p>先拿下 hurdle，再去捡总分。铃声会替稳稳走过每一个节点的人响起，喵。</p>
<script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-pracexam-q1-q2-survival-guide#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-pracexam-q1-q2-survival-guide</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-pracexam-q1-q2-survival-guide</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Wed, 15 Jul 2026 05:01:20 GMT</pubDate></item><item><title><![CDATA[一条线段为什么不是向量子空间：MATH1231 子空间反例速通]]></title><description><![CDATA[<link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-subspace-cover.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-scalar-stretch.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-parameter-check.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-vs-line.svg"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/mathematics/line-segment-not-vector-subspace-math1231">https://rakko.cn/posts/mathematics/line-segment-not-vector-subspace-math1231</a></blockquote><div><blockquote><p>这篇只解决一个问题：为什么</p><p>$$
S={t\mathbf v:0\le t\le 10}
$$</p><p>这种“从原点出发的一段线段”不是 vector subspace。</p><p>你不用背一整页公理。考试里只要抓住一个失败点：<strong>scalar multiplication 不封闭</strong>。</p></blockquote>
<p><img alt="封面：有限线段被数乘拉出范围" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-subspace-cover.svg"/></p><h2 id="0-">0. 题目在说什么？</h2><p>题目：</p><p>$$
\mathbf v=\begin{pmatrix}1\2\3\end{pmatrix}\in\mathbb R^3.
$$</p><p>Show that the line segment</p><p>$$
S={t\mathbf v:0\le t\le 10}
$$</p><p>is not a vector subspace.</p><p>先翻译成人话：</p><ul><li>$\mathbf v$ 是一个固定方向；</li><li>$t\mathbf v$ 表示沿着这个方向走；</li><li>$0\le t\le 10$ 表示只能从 $0\mathbf v$ 走到 $10\mathbf v$；</li><li>所以 $S$ 不是整条无限长直线，而是一条<strong>有限线段</strong>。</li></ul><p>如果把它想象成数轴上的一段，就是：</p><p>$$
0\mathbf v,\ 1\mathbf v,\ 2\mathbf v,\ \ldots,\ 10\mathbf v
$$</p><p>以及中间所有小数倍的位置。</p><h2 id="1-">1. 子空间最怕什么？</h2><p>如果 $S$ 是 $\mathbb R^3$ 的 vector subspace，它至少必须满足：</p><table><thead><tr><th> 必须满足的条件 </th><th> 意思 </th></tr></thead><tbody><tr><td> zero vector in $S$ </td><td> 零向量要在集合里 </td></tr><tr><td> closed under vector addition </td><td> 两个集合里的向量相加，还要在集合里 </td></tr><tr><td> closed under scalar multiplication </td><td> 集合里的向量乘任何实数，还要在集合里 </td></tr></tbody></table><p>这题里面，零向量其实在：</p><p>$$
0\mathbf v=\begin{pmatrix}0\0\0\end{pmatrix}\in S,
$$</p><p>因为 $0\le 0\le 10$。</p><p>所以不能用“零向量不在”秒杀。</p><p>老师用的是第二种思路：</p><blockquote><p>找一个 $x\in S$，但让某个 scalar multiple $kx\notin S$。</p></blockquote>
<p>这就叫：</p><p>$$
S\text{ is not closed under scalar multiplication.}
$$</p><p><img alt="数乘封闭检查：从集合内拉到集合外" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-scalar-stretch.svg"/></p><h2 id="2-">2. 先别被符号绕晕：集合参数和外部倍数不一样</h2><p>这题最容易混的是同一个希腊字母到处飞。</p><p>我建议你考试时心里分清楚两层：</p><table><thead><tr><th> 符号 </th><th> 作用 </th></tr></thead><tbody><tr><td> $t$ </td><td> 用来描述集合里的点：$t\mathbf v$，其中 $0\le t\le 10$ </td></tr><tr><td> $k$ </td><td> 你拿来做 scalar multiplication 的外部倍数，可以是任何实数 </td></tr></tbody></table><p>也就是说：</p><ol start="1"><li>先找一个集合里的向量 $x=t\mathbf v$。</li><li>再用一个外部 scalar $k$ 去乘它。</li><li>检查 $kx$ 还能不能写成 $s\mathbf v$，并且满足 $0\le s\le 10$。</li></ol><p>如果不能，它就跑出 $S$ 了。</p><h2 id="3-">3. 老师的反例：先选一个在集合里的向量</h2><p>取：</p><p>$$
x=\mathbf v=1\mathbf v.
$$</p><p>因为 $1$ 在 $0$ 和 $10$ 之间：</p><p>$$
0\le 1\le 10,
$$</p><p>所以：</p><p>$$
x=\mathbf v\in S.
$$</p><p>这一步非常重要：你要先证明自己选的东西真的在集合里。</p><h2 id="4--11">4. 现在把它乘以 11</h2><p>如果 $S$ 真的是 vector subspace，那么 $x\in S$ 以后，任何实数倍都应该还在 $S$。</p><p>老师取：</p><p>$$
k=11.
$$</p><p>于是：</p><p>$$
kx=11x=11\mathbf v.
$$</p><p>但 $11\mathbf v$ 要在 $S$ 里，就必须能写成 $t\mathbf v$，并且满足：</p><p>$$
0\le t\le 10.
$$</p><p>这里的系数已经是 $11$：</p><p>$$
11&gt;10.
$$</p><p>所以：</p><p>$$
11\mathbf v\notin S.
$$</p><p><img alt="代入检查：1 在范围内，11 超出范围" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-parameter-check.svg"/></p><h2 id="5-">5. 结论怎么写？</h2><p>我们已经找到：</p><p>$$
x\in S,
$$</p><p>但：</p><p>$$
11x\notin S.
$$</p><p>所以：</p><p>$$
S\text{ is not closed under scalar multiplication.}
$$</p><p>因此：</p><p>$$
S\text{ is not a vector subspace of }\mathbb R^3.
$$</p><p>这题到这里就结束了。</p><h2 id="6--11">6. 为什么能想到乘 11？</h2><p>不是玄学。</p><p>集合 $S$ 只允许：</p><p>$$
0\le t\le 10.
$$</p><p>这句话等价于：</p><blockquote><p>系数最多只能到 $10$。</p></blockquote>
<p>所以你只要把一个在里面的向量放大到系数超过 $10$，它就会掉出去。</p><p>最舒服的选择就是：</p><p>$$
x=1\mathbf v\in S.
$$</p><p>然后乘：</p><p>$$
11.
$$</p><p>得到：</p><p>$$
11x=11\mathbf v\notin S.
$$</p><p>如果你想更快，其实也可以乘 $-1$：</p><p>$$
-x=-\mathbf v,
$$</p><p>因为系数 $-1&lt;0$，也不在 $0\le t\le 10$ 里面。</p><p>但视频里用 $11$，我们就按老师的版本写。</p><h2 id="7-">7. 这题的本质：线段不是整条直线</h2><p>一个真正的一维子空间应该长这样：</p><p>$$
L={t\mathbf v:t\in\mathbb R}.
$$</p><p>这里的 $t$ 可以是任何实数：</p><p>$$
\ldots,\ -2,\ -1,\ 0,\ 1,\ 2,\ 11,\ 100,\ \ldots
$$</p><p>所以整条直线可以被随便放大、缩小、反向。</p><p>但题目里的：</p><p>$$
S={t\mathbf v:0\le t\le 10}
$$</p><p>只是一段有限线段。</p><p>它有两个端点：$0\mathbf v$ 和 $10\mathbf v$。</p><p>一旦你把里面的点继续往外拉，例如 $11\mathbf v$，它就不在这段线段上了。</p><p><img alt="整条直线 vs 有限线段" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/line-segment-vs-line.svg"/></p><h2 id="8-">8. 考试可直接抄的版本</h2><pre class="language-text lang-text"><code class="language-text lang-text">Take x = v = 1v. Since 0 &lt;= 1 &lt;= 10, we have x in S.

However, 11x = 11v. This is not in S, since the coefficient 11 does not satisfy 0 &lt;= 11 &lt;= 10.

Therefore S is not closed under scalar multiplication. Hence S is not a vector subspace of R^3.
</code></pre>
<p>如果要写得更数学一点：</p><p>$$
x=\mathbf v=1\mathbf v\in S
$$</p><p>since $0\le 1\le 10$. But</p><p>$$
11x=11\mathbf v\notin S
$$</p><p>since $11&gt;10$. Hence $S$ is not closed under scalar multiplication, so $S$ is not a vector subspace of $\mathbb R^3$.</p><h2 id="9-">9. 初学者检查清单</h2><p>遇到</p><p>$$
S={t\mathbf v:a\le t\le b}
$$</p><p>这种题，按三步走：</p><ol start="1"><li>看它是不是只给了一个有限区间。</li><li>先取一个在区间里的简单数，例如 $t=1$ 或 $t=0$。</li><li>用一个 scalar 把它乘到区间外，例如超过上界，或者变成负数。</li></ol><p>只要你写出：</p><p>$$
x\in S,\qquad kx\notin S,
$$</p><p>就能证明它不是 subspace。</p><h2 id="10-">10. 自测题</h2><h3 id="-1">自测 1</h3><p>设：</p><p>$$
S={t\mathbf v:-2\le t\le 2}.
$$</p><p>证明 $S$ 不是 vector subspace。</p><p>答案：</p><p>取 $x=\mathbf v=1\mathbf v$。因为 $-2\le 1\le 2$，所以 $x\in S$。</p><p>但：</p><p>$$
3x=3\mathbf v.
$$</p><p>系数 $3$ 不满足 $-2\le 3\le 2$，所以 $3x\notin S$。</p><p>因此 $S$ is not closed under scalar multiplication，不是 vector subspace。</p><h3 id="-2">自测 2</h3><p>设：</p><p>$$
S={t\mathbf v:t\ge 0}.
$$</p><p>证明 $S$ 不是 vector subspace。</p><p>答案：</p><p>取 $x=\mathbf v=1\mathbf v$。因为 $1\ge 0$，所以 $x\in S$。</p><p>但：</p><p>$$
-x=-\mathbf v.
$$</p><p>这对应的系数是 $-1$，不满足 $t\ge 0$，所以 $-x\notin S$。</p><p>因此 $S$ is not closed under scalar multiplication，不是 vector subspace。</p><h2 id="11-">11. 最后一口气版总结</h2><p>这节课的核心只有一句：</p><blockquote><p>有限线段不是 vector subspace，因为 subspace 不能有“只能从 0 到 10”这种边界。</p></blockquote>
<p>本题标准反例：</p><p>$$
x=\mathbf v=1\mathbf v\in S,
$$</p><p>但：</p><p>$$
11x=11\mathbf v\notin S.
$$</p><p>所以 $S$ is not closed under scalar multiplication。</p><p>一旦 scalar multiplication 不封闭，它就不是 vector subspace。</p></div><p style="text-align:right"><a href="https://rakko.cn/posts/mathematics/line-segment-not-vector-subspace-math1231#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/mathematics/line-segment-not-vector-subspace-math1231</link><guid isPermaLink="true">https://rakko.cn/posts/mathematics/line-segment-not-vector-subspace-math1231</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 08 Jun 2026 11:23:17 GMT</pubDate></item><item><title><![CDATA[一眼判断集合不是向量空间：MATH1231 反例速通]]></title><description><![CDATA[<link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-cover.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-flow.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-example-1.svg"/><link rel="preload" as="image" href="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-example-2.svg"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/mathematics/sets-that-are-not-vector-spaces-math1231">https://rakko.cn/posts/mathematics/sets-that-are-not-vector-spaces-math1231</a></blockquote><div><blockquote><p>这篇只解决一个问题：题目给你一个集合 $S$，怎么快速证明它 <strong>不是</strong> vector space。</p><p>重点不是把十条公理背一遍，而是学会找一个反例。一个反例就够了。</p></blockquote>
<p><img alt="封面：closure 被反例打破" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-cover.svg"/></p><h2 id="0-">0. 先把结论说人话</h2><p>Vector space 最重要的感觉是：</p><blockquote><p>你在集合里做正常向量操作，结果还应该留在集合里。</p></blockquote>
<p>这里的“正常向量操作”主要是两件事：</p><ol start="1"><li>scalar multiplication：把向量乘一个数，例如 $2v$、<code>-v</code>、<code>0v</code>。</li><li>vector addition：两个向量相加，例如 $u+v$。</li></ol><p>所以要证明一个集合 <strong>不是</strong> vector space，最爽的方法就是找一个操作让它“跑出去”：</p><table><thead><tr><th> 想破坏什么 </th><th> 你要找什么 </th><th> 写法 </th></tr></thead><tbody><tr><td> 零向量条件 </td><td> $\mathbf{0}\notin S$ </td><td> zero vector is not in $S$ </td></tr><tr><td> 数乘封闭 </td><td> $v\in S$，但 $kv\notin S$ </td><td> not closed under scalar multiplication </td></tr><tr><td> 加法封闭 </td><td> $u,v\in S$，但 $u+v\notin S$ </td><td> not closed under vector addition </td></tr></tbody></table><p><img alt="三步判断流程图" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-flow.svg"/></p><p>记住这句话：</p><blockquote><p>证明“是”要检查很多东西；证明“不是”只要抓到一个失败点。</p></blockquote>
<h2 id="1--vin-s">1. 什么叫 $v\in S$？</h2><p>很多人卡在符号，其实非常机械。</p><p>如果题目写：</p><p>$$
S={x\in\mathbb{R}^3: 2x<em>1+3x</em>2^3-4x_3^2=0},
$$</p><p>那 $v\in S$ 的意思就是：</p><blockquote><p>把 $v$ 的三个坐标代进 $2x<em>1+3x</em>2^3-4x_3^2$，结果等于 $0$。</p></blockquote>
<p>如果结果不是 $0$，那就是 $v\notin S$。</p><p>所以这种题不用想得太玄。它就是“代入检查”。</p><h2 id="2--1">2. 例题 1：用数乘把它踢出去</h2><p>题目：</p><p>$$
S={x\in\mathbb{R}^3: 2x<em>1+3x</em>2^3-4x_3^2=0}.
$$</p><p>Show that $S$ is not a vector space.</p><h3 id="-s-">第一步：找一个在 $S$ 里的向量</h3><p>老师取：</p><p>$$
v=\begin{pmatrix}2\0\1\end{pmatrix}.
$$</p><p>我们先验证它真的在 $S$ 里。把 $x<em>1=2,\ x</em>2=0,\ x_3=1$ 代进去：</p><p>$$
2(2)+3(0)^3-4(1)^2
=4+0-4
=0.
$$</p><p>所以：</p><p>$$
v\in S.
$$</p><h3 id="-2">第二步：把它乘以 2</h3><p>$$
2v=2\begin{pmatrix}2\0\1\end{pmatrix}
=\begin{pmatrix}4\0\2\end{pmatrix}.
$$</p><p>现在检查 $2v$ 还在不在 $S$：</p><p>$$
2(4)+3(0)^3-4(2)^2
=8+0-16
=-8.
$$</p><p>这不是 $0$，所以：</p><p>$$
2v\notin S.
$$</p><p><img alt="例题 1：v 在 S 中，但 2v 不在 S 中" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-example-1.svg"/></p><h3 id="">结论怎么写？</h3><p>因为 $v\in S$，但 $2v\notin S$，所以 $S$ is not closed under scalar multiplication。</p><p>于是：</p><p>$$
S\text{ is not a vector space.}
$$</p><h3 id="-201">为什么老师会想到 $(2,0,1)$？</h3><p>不是玄学，是在凑数。</p><p>原条件是：</p><p>$$
2x<em>1+3x</em>2^3-4x_3^2=0.
$$</p><p>想找一个简单向量，就先让中间那项消失：</p><p>$$
x_2=0.
$$</p><p>再取一个简单的：</p><p>$$
x_3=1.
$$</p><p>条件就变成：</p><p>$$
2x_1-4=0.
$$</p><p>所以：</p><p>$$
x_1=2.
$$</p><p>于是自然得到：</p><p>$$
(2,0,1).
$$</p><p>这就是找反例的常见套路：把变量设成 $0$ 或 $1$，让式子尽量简单。</p><h2 id="3--2">3. 例题 2：用加法把它踢出去</h2><p>题目：</p><p>$$
S=\left{\begin{pmatrix}a\b\c\end{pmatrix}\in\mathbb{R}^3:(a-b)c=0\right}.
$$</p><p>Find two non-zero elements of $S$ and show $S$ is not closed under vector addition.</p><h3 id="">先看条件到底在说什么</h3><p>$$
(a-b)c=0
$$</p><p>两个东西相乘等于 $0$，所以至少有一个是 $0$：</p><p>$$
a-b=0
$$</p><p>或者：</p><p>$$
c=0.
$$</p><p>也就是：</p><p>$$
a=b
$$</p><p>或者：</p><p>$$
c=0.
$$</p><p>所以 $S$ 不是一个单纯的平面，而像是两块条件拼在一起：</p><ul><li>一块是所有满足 $a=b$ 的向量；</li><li>另一块是所有满足 $c=0$ 的向量。</li></ul><h3 id="">第一步：从两块里各拿一个向量</h3><p>取：</p><p>$$
u=\begin{pmatrix}1\1\1\end{pmatrix},
\qquad
w=\begin{pmatrix}1\2\0\end{pmatrix}.
$$</p><p>验证 $u\in S$：</p><p>$$
(1-1)(1)=0.
$$</p><p>验证 $w\in S$：</p><p>$$
(1-2)(0)=0.
$$</p><p>所以 $u,w\in S$。</p><h3 id="">第二步：把它们相加</h3><p>$$
u+w
=\begin{pmatrix}1\1\1\end{pmatrix}
+\begin{pmatrix}1\2\0\end{pmatrix}
=\begin{pmatrix}2\3\1\end{pmatrix}.
$$</p><p>现在检查这个和还在不在 $S$：</p><p>$$
(2-3)(1)=-1.
$$</p><p>不是 $0$，所以：</p><p>$$
u+w\notin S.
$$</p><p><img alt="例题 2：两块条件各取一个，和掉出 S" src="https://gist.githubusercontent.com/KurisuRakko/2f70f3b848671ed61aa3a50e8b29f479/raw/vector-space-example-2.svg"/></p><h3 id="">结论怎么写？</h3><p>因为 $u,w\in S$，但 $u+w\notin S$，所以 $S$ is not closed under vector addition。</p><p>于是：</p><p>$$
S\text{ is not a vector space.}
$$</p><h2 id="4--vector-space">4. 一眼识别：什么时候优先怀疑它不是 vector space？</h2><p>看到下面这些东西，要立刻警觉：</p><table><thead><tr><th> 条件里出现 </th><th> 为什么危险 </th></tr></thead><tbody><tr><td> 平方、立方，例如 $x<em>3^2$、$x</em>2^3$ </td><td> 数乘后指数会变，例如 $(2x)^2=4x^2$，比例乱掉 </td></tr><tr><td> 两个变量相乘，例如 $xy$、$(a-b)c$ </td><td> 加法通常会破坏乘积为零的结构 </td></tr><tr><td> 常数项，例如 $x+y=1$ </td><td> 零向量通常不满足 </td></tr><tr><td> 绝对值、不等式、圆、球面 </td><td> 一般不容易对加法/数乘封闭 </td></tr></tbody></table><p>但注意：这只是“怀疑”。考试证明还是要写出具体反例。</p><h2 id="5-">5. 考试可直接抄的模板</h2><h3 id="-a">模板 A：数乘不封闭</h3><pre class="language-text lang-text"><code class="language-text lang-text">Take v = (...) in S, since ...

However, kv = (...), and substituting this into the defining condition gives ...
Thus kv is not in S.

Hence S is not closed under scalar multiplication, so S is not a vector space.
</code></pre>
<h3 id="-b">模板 B：加法不封闭</h3><pre class="language-text lang-text"><code class="language-text lang-text">Take u = (...) and v = (...) in S, since ...

However, u + v = (...), and substituting this into the defining condition gives ...
Thus u + v is not in S.

Hence S is not closed under vector addition, so S is not a vector space.
</code></pre>
<h3 id="-c">模板 C：零向量不在集合里</h3><pre class="language-text lang-text"><code class="language-text lang-text">The zero vector is not in S, since substituting 0 into the defining condition gives ...

Therefore S is not a vector space.
</code></pre>
<h2 id="6-">6. 怎么自己找反例？</h2><p>按这个顺序试：</p><ol start="1"><li>先代零向量。零向量不在，直接结束。</li><li>如果有平方/立方，试找一个 $v\in S$，再试 $2v$。</li><li>如果有乘积等于 $0$，试从两个分支各拿一个向量，再相加。</li><li>如果题目条件很复杂，就先把一些变量设成 $0$ 或 $1$，让式子变简单。</li></ol><p>这就是这节课真正想训练的东西：不是背答案，而是会制造一个会跑出集合的向量。</p><h2 id="7-">7. 自测题</h2><h3 id="-1">自测 1</h3><p>$$
S={(x,y)\in\mathbb{R}^2:x^2+y=0}.
$$</p><p>证明 $S$ 不是 vector space。</p><p>答案：</p><p>取：</p><p>$$
v=(1,-1).
$$</p><p>因为：</p><p>$$
1^2+(-1)=0,
$$</p><p>所以 $v\in S$。</p><p>但：</p><p>$$
2v=(2,-2),
$$</p><p>而：</p><p>$$
2^2+(-2)=2\ne0.
$$</p><p>所以 $2v\notin S$。因此 $S$ is not closed under scalar multiplication，不是 vector space。</p><h3 id="-2">自测 2</h3><p>$$
S={(x,y,z)\in\mathbb{R}^3:xy=0}.
$$</p><p>证明 $S$ 不是 vector space。</p><p>答案：</p><p>取：</p><p>$$
u=(1,0,0),\qquad v=(0,1,0).
$$</p><p>因为两个向量都满足 $xy=0$，所以 $u,v\in S$。</p><p>但：</p><p>$$
u+v=(1,1,0),
$$</p><p>此时：</p><p>$$
xy=1\ne0.
$$</p><p>所以 $u+v\notin S$。因此 $S$ is not closed under vector addition，不是 vector space。</p><h2 id="8-">8. 最后一口气版总结</h2><p>证明集合不是 vector space，不要硬查全部公理。</p><p>你只需要找一个失败点：</p><ul><li>$\mathbf{0}\notin S$；</li><li>或者 $v\in S$ 但 $kv\notin S$；</li><li>或者 $u,v\in S$ 但 $u+v\notin S$。</li></ul><p>例题 1 用的是数乘不封闭：$(2,0,1)\in S$，但 $2(2,0,1)\notin S$。</p><p>例题 2 用的是加法不封闭：$(1,1,1),(1,2,0)\in S$，但它们的和 $(2,3,1)\notin S$。</p><p>一句话：</p><blockquote><p>找到一个会跑出去的向量，题就结束了。</p></blockquote></div><p style="text-align:right"><a href="https://rakko.cn/posts/mathematics/sets-that-are-not-vector-spaces-math1231#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/mathematics/sets-that-are-not-vector-spaces-math1231</link><guid isPermaLink="true">https://rakko.cn/posts/mathematics/sets-that-are-not-vector-spaces-math1231</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Sun, 07 Jun 2026 07:07:15 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 5 课：strings、2D arrays 与 structs]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-05-2d-arrays-strings-structs">https://rakko.cn/posts/comp1511/comp1511-05-2d-arrays-strings-structs</a></blockquote><div><h1 id="-5-strings2d-arrays--structs">第 5 课：strings、2D arrays 与 structs</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 Week 04/05 的 strings、2D arrays、array of structs 与 command-line 相关 lecture slides 做中文转述；练习模板为本站原创。<span>[S013][S014]</span>[S015]</p></blockquote><blockquote>
<p>今天只做：string、2D array、struct array 各读一个最小模板。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-04-debugging-strings-exam-drill">上一课</a> · <a href="/posts/comp1511/comp1511-06-cli-multifile-pointers">下一课：命令行参数、多文件与指针入门</a>
别乱跳：2D array 永远先写 row，再写 col。</p></blockquote>
<h2 id="">本课目标</h2><p>今天只抓 3 件事：string 当 <code>char</code> array 读，2D array 先 row 再 col，struct array 先取出一个元素再看字段。<span>[S013][S014]</span>[S015]</p><table><thead><tr><th> 焚诀 </th><th> 先做什么 </th></tr></thead><tbody><tr><td> string </td><td> 一格一格看字符 </td></tr><tr><td> 2D array </td><td> 外层 <code>row</code>，内层 <code>col</code> </td></tr><tr><td> array of structs </td><td> <code>students[i].field</code> </td></tr></tbody></table><h2 id="">最小模板</h2><p>2D array 题不要先想图形，先写两层循环；这个写法对应官方 2D arrays 主题，但代码是原创练习模板。<span>[S014][S015]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">int count_target(int grid[][NUM_COLS], int rows, int target) {
    int count = 0;

    for (int row = 0; row &lt; rows; row++) {
        for (int col = 0; col &lt; NUM_COLS; col++) {
            if (grid[row][col] == target) {
                count++;
            }
        }
    }

    return count;
}
</code></pre>
<h2 id="struct-array-">struct array 读法</h2><p>Lecture 7 提到 array of structs 的视觉理解；保命读法是：先定位 <code>i</code>，再读字段，不要同时脑补太多层。[S013]</p><pre class="language-c lang-c"><code class="language-c lang-c">struct student {
    int zid;
    int mark;
};

int count_passes(struct student students[], int size) {
    int passes = 0;

    for (int i = 0; i &lt; size; i++) {
        if (students[i].mark &gt;= 50) {
            passes++;
        }
    }

    return passes;
}
</code></pre>
<h2 id="5-">5 分钟练习</h2><ul><li><input readOnly="" type="checkbox"/> 写一个循环数出 string 里有几个 <code>&#x27;a&#x27;</code>。</li><li><input readOnly="" type="checkbox"/> 写一个 2D array 循环，把每一行的总和打印出来。</li><li><input readOnly="" type="checkbox"/> 写一个 struct array 循环，找最高 <code>mark</code>。</li></ul><details><summary>点开：最常见错因</summary><p>2D array 最常见错因是临时变量放错层级；每一行要重新计算的值，应该放在外层 <code>row</code> 循环里面。<span>[S014][S015]</span></p></details><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我知道 string 本质上可以按 <code>word[i]</code> 逐字符处理。</li><li><input readOnly="" type="checkbox"/> 我能写 <code>grid[row][col]</code>。</li><li><input readOnly="" type="checkbox"/> 我知道每一行的 <code>sum</code> 要在 row 循环里重置。</li><li><input readOnly="" type="checkbox"/> 我能读懂 <code>students[i].mark</code>。</li></ul><h2 id="">引用</h2><ul><li>[S013] Lecture 7 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf</a></li><li>[S014] Lecture 8 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf</a></li><li>[S015] Lecture 9 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-05-2d-arrays-strings-structs#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-05-2d-arrays-strings-structs</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-05-2d-arrays-strings-structs</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:16:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 6 课：命令行参数、多文件与指针入门]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-06-cli-multifile-pointers">https://rakko.cn/posts/comp1511/comp1511-06-cli-multifile-pointers</a></blockquote><div><h1 id="-6-">第 6 课：命令行参数、多文件与指针入门</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 Week 05 的 command line arguments、multi-file projects、pointers 和 memory lecture 做中文转述；代码模板为本站原创。<span>[S015][S016]</span></p></blockquote><blockquote>
<p>今天只做：分清 <code>argc</code>、<code>argv</code>、<code>&amp;</code>、<code>*</code> 四个符号。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-05-2d-arrays-strings-structs">上一课</a> · <a href="/posts/comp1511/comp1511-07-malloc-free-linked-list-start">下一课：malloc/free 与 linked list 起步</a>
别乱跳：指针先翻译成“地址”，不要马上想很深。</p></blockquote>
<h2 id="">本课目标</h2><p>第 6 课不追求“懂完内存”，只要先会读 3 个符号：<code>argc</code> 是数量，<code>argv</code> 是文字列表，<code>&amp;</code> 是地址。<span>[S015][S016]</span></p><table><thead><tr><th> 看见 </th><th> 先翻译成 </th></tr></thead><tbody><tr><td> <code>argc</code> </td><td> 参数个数 </td></tr><tr><td> <code>argv[1]</code> </td><td> 第一个额外参数 </td></tr><tr><td> <code>&amp;x</code> </td><td> <code>x</code> 的地址 </td></tr><tr><td> <code>*p</code> </td><td> 地址 <code>p</code> 指向的值 </td></tr></tbody></table><h2 id="command-line-arguments">command line arguments</h2><p>Lecture 9 进入 command line arguments；保命做法是先检查 <code>argc</code>，再读 <code>argv</code>，不要假设用户一定给了参数。[S015]</p><pre class="language-c lang-c"><code class="language-c lang-c">int main(int argc, char *argv[]) {
    if (argc &lt; 2) {
        printf(&quot;Usage: ./program word\n&quot;);
        return 1;
    }

    printf(&quot;first word: %s\n&quot;, argv[1]);
    return 0;
}
</code></pre>
<h2 id="">指针先别怕</h2><p>Lecture 10 把 pointers、memory 和 dynamic memory 放在一起；第一天只要记住“指针变量存的是地址”。[S016]</p><pre class="language-c lang-c"><code class="language-c lang-c">int value = 7;
int *pointer = &amp;value;

printf(&quot;%d\n&quot;, *pointer);
</code></pre>
<details><summary>点开：<code>*</code> 为什么有两个意思？</summary><p>在声明里，<code>int *pointer</code> 表示 <code>pointer</code> 是一个指向 <code>int</code> 的指针；在表达式里，<code>*pointer</code> 表示去这个地址里拿值。这个区分来自 C 指针语法，复习时要分场景看。<span>[S006][S016]</span></p></details><h2 id="5-">5 分钟练习</h2><ul><li><input readOnly="" type="checkbox"/> 写一个程序，没有参数时打印 usage。</li><li><input readOnly="" type="checkbox"/> 画出 <code>value -&gt; address -&gt; pointer</code>。</li><li><input readOnly="" type="checkbox"/> 解释 <code>&amp;value</code> 和 <code>*pointer</code> 的区别。</li></ul><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我会先检查 <code>argc</code>。</li><li><input readOnly="" type="checkbox"/> 我知道 <code>argv[0]</code> 通常是程序名。</li><li><input readOnly="" type="checkbox"/> 我知道指针保存地址。</li><li><input readOnly="" type="checkbox"/> 我不会在没检查的情况下直接读 <code>argv[1]</code>。</li></ul><h2 id="">引用</h2><ul><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S015] Lecture 9 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf</a></li><li>[S016] Lecture 10 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-06-cli-multifile-pointers#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-06-cli-multifile-pointers</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-06-cli-multifile-pointers</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:15:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 7 课：malloc/free 与 linked list 起步]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-07-malloc-free-linked-list-start">https://rakko.cn/posts/comp1511/comp1511-07-malloc-free-linked-list-start</a></blockquote><div><h1 id="-7-mallocfree--linked-list-">第 7 课：malloc/free 与 linked list 起步</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 Lecture 10/11 的 dynamic memory、malloc/free、multi-file projects 和 linked list 起步内容做中文转述；模板为本站原创。<span>[S016][S017]</span></p></blockquote><blockquote>
<p>今天只做：创建一个 node，再用 <code>curr</code> 走到 <code>NULL</code>。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-06-cli-multifile-pointers">上一课</a> · <a href="/posts/comp1511/comp1511-08-linked-list-delete">下一课：linked list 删除节点</a>
别乱跳：遍历时不要改 <code>head</code>，只移动 <code>curr</code>。</p></blockquote>
<h2 id="">本课目标</h2><p>今天只练一件事：一个 node 里面有数据和 <code>next</code>，很多 node 串起来就是 linked list。[S017]</p><table><thead><tr><th> 焚诀 </th><th> 意思 </th></tr></thead><tbody><tr><td> <code>malloc</code> </td><td> 申请一块空间 </td></tr><tr><td> <code>free</code> </td><td> 用完还回去 </td></tr><tr><td> <code>head</code> </td><td> 链表第一个节点 </td></tr><tr><td> <code>curr</code> </td><td> 正在看的节点 </td></tr></tbody></table><h2 id="">创建一个节点</h2><p>Lecture 11 把 malloc/free 和 linked list 放在一起讲；创建节点时先申请、再检查、再填字段。[S017]</p><pre class="language-c lang-c"><code class="language-c lang-c">struct node {
    int data;
    struct node *next;
};

struct node *create_node(int value) {
    struct node *new_node = malloc(sizeof(struct node));
    if (new_node == NULL) {
        return NULL;
    }

    new_node-&gt;data = value;
    new_node-&gt;next = NULL;
    return new_node;
}
</code></pre>
<h2 id="">遍历模板</h2><p>链表遍历对应 Lecture 11 的 traversal 主题；保命写法是 <code>curr != NULL</code>，每轮最后走到 <code>curr-&gt;next</code>。[S017]</p><pre class="language-c lang-c"><code class="language-c lang-c">void print_list(struct node *head) {
    struct node *curr = head;
    while (curr != NULL) {
        printf(&quot;%d\n&quot;, curr-&gt;data);
        curr = curr-&gt;next;
    }
}
</code></pre>
<details><summary>点开：为什么不要动 head？</summary><p><code>head</code> 是入口。如果你直接把 <code>head = head-&gt;next</code> 一路改下去，最后可能找不到原来的链表开头；用 <code>curr</code> 走路更稳。[S017]</p></details><h2 id="5-">5 分钟练习</h2><ul><li><input readOnly="" type="checkbox"/> 画 <code>head -&gt; [3] -&gt; [5] -&gt; NULL</code>。</li><li><input readOnly="" type="checkbox"/> 写 <code>print_list</code>。</li><li><input readOnly="" type="checkbox"/> 写一句话解释 <code>new_node-&gt;next = NULL</code>。</li></ul><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我知道 <code>malloc</code> 后要检查 <code>NULL</code>。</li><li><input readOnly="" type="checkbox"/> 我知道 linked list 的终点是 <code>NULL</code>。</li><li><input readOnly="" type="checkbox"/> 我能用 <code>curr</code> 遍历，不乱改 <code>head</code>。</li><li><input readOnly="" type="checkbox"/> 我知道用完动态内存要 <code>free</code>。</li></ul><h2 id="">引用</h2><ul><li>[S016] Lecture 10 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf</a></li><li>[S017] Lecture 11 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_7/COMP1511_26T1_Lecture11.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_7/COMP1511_26T1_Lecture11.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-07-malloc-free-linked-list-start#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-07-malloc-free-linked-list-start</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-07-malloc-free-linked-list-start</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:14:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 8 课：linked list 删除节点]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-08-linked-list-delete">https://rakko.cn/posts/comp1511/comp1511-08-linked-list-delete</a></blockquote><div><h1 id="-8-linked-list-">第 8 课：linked list 删除节点</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 Lecture 13/14 的 linked list 删除节点内容做中文转述；不复刻考试题，代码模板为本站原创。<span>[S018][S019]</span></p></blockquote><blockquote>
<p>今天只做：画出删 head 和删 middle 的箭头变化。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-07-malloc-free-linked-list-start">上一课</a> · <a href="/posts/comp1511/comp1511-09-linked-list-exam-debugging">下一课：linked list 综合查错</a>
别乱跳：删除题先保 <code>prev</code> 和 <code>curr</code>，再考虑 <code>free</code>。</p></blockquote>
<h2 id="">本课目标</h2><p>删除节点不要分裂成一堆补丁；先统一想成“找到前一个节点，让它跳过要删的节点”。<span>[S018][S019]</span></p><table><thead><tr><th> 情况 </th><th> 先做什么 </th></tr></thead><tbody><tr><td> 空链表 </td><td> 直接返回 <code>head</code> </td></tr><tr><td> 删头 </td><td> 新 head 是旧 head 的 next </td></tr><tr><td> 删中间 </td><td> <code>prev-&gt;next = curr-&gt;next</code> </td></tr><tr><td> 删尾 </td><td> 同样是让 prev 指向 NULL </td></tr></tbody></table><h2 id="">删除第一个匹配值</h2><p>Lecture 13/14 的删除主题覆盖 head、tail、middle 和单节点；下面模板把这些情况放进同一条逻辑里。<span>[S018][S019]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">struct node *delete_first(struct node *head, int value) {
    struct node *curr = head;
    struct node *prev = NULL;

    while (curr != NULL &amp;&amp; curr-&gt;data != value) {
        prev = curr;
        curr = curr-&gt;next;
    }

    if (curr == NULL) {
        return head;
    }

    if (prev == NULL) {
        head = curr-&gt;next;
    } else {
        prev-&gt;next = curr-&gt;next;
    }

    free(curr);
    return head;
}
</code></pre>
<h2 id="">口诀</h2><p>链表删除题先问 3 个问题：要删的是不是 <code>NULL</code>，要删的是不是 <code>head</code>，删完有没有把节点 <code>free</code>。<span>[S018][S019]</span></p><details><summary>点开：为什么函数要 return head？</summary><p>如果删的是第一个节点，<code>head</code> 会变；所以让函数返回新的 <code>head</code>，调用者才能接住变化。这是 linked list 删除题的保命接口习惯。<span>[S018][S019]</span></p></details><h2 id="5-">5 分钟练习</h2><ul><li><input readOnly="" type="checkbox"/> 画删除 head 的前后箭头。</li><li><input readOnly="" type="checkbox"/> 画删除 middle 的前后箭头。</li><li><input readOnly="" type="checkbox"/> 解释为什么 <code>free(curr)</code> 要在改好链接之后。</li></ul><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我知道空链表直接返回。</li><li><input readOnly="" type="checkbox"/> 我知道删头会改变 <code>head</code>。</li><li><input readOnly="" type="checkbox"/> 我知道删中间要保留 <code>prev</code>。</li><li><input readOnly="" type="checkbox"/> 我知道找不到目标时不应该乱 free。</li></ul><h2 id="">引用</h2><ul><li>[S018] Lecture 13 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_8/COMP1511_26T1_Lecture13.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_8/COMP1511_26T1_Lecture13.pdf</a></li><li>[S019] Lecture 13/14 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-08-linked-list-delete#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-08-linked-list-delete</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-08-linked-list-delete</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:13:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 9 课：linked list 综合与 exam-style debugging]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-09-linked-list-exam-debugging">https://rakko.cn/posts/comp1511/comp1511-09-linked-list-exam-debugging</a></blockquote><div><h1 id="-9-linked-list--exam-style-debugging">第 9 课：linked list 综合与 exam-style debugging</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 linked list 后续 lecture、Exam information lecture、Debugging Guide 和公开复习入口做中文转述；不复制真实考试题正文。<span>[S019][S020]</span><span>[S004][S001]</span></p></blockquote><blockquote>
<p>今天只做：写一个 linked list 长度函数，并测空链表。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-08-linked-list-delete">上一课</a> · <a href="/posts/comp1511/comp1511-10-final-revision">下一课：期末复习焚诀</a>
别乱跳：查错先测空、一个节点、三个节点。</p></blockquote>
<h2 id="">本课目标</h2><p>第 9 课把 linked list 题从“会写模板”推进到“能查错”；先保 traversal，再保 insert/delete，再看输出差异。<span>[S019][S020]</span>[S004]</p><table><thead><tr><th> 症状 </th><th> 先查 </th></tr></thead><tbody><tr><td> 崩溃 </td><td> <code>curr != NULL</code> 有没有守住 </td></tr><tr><td> 输出少一个 </td><td> 循环有没有提前停 </td></tr><tr><td> 删除后乱了 </td><td> <code>prev-&gt;next</code> 有没有接对 </td></tr><tr><td> 内存问题 </td><td> <code>malloc</code> / <code>free</code> 是否成对 </td></tr></tbody></table><h2 id="exam-style-">exam-style 查错顺序</h2><p>官方 Debugging Guide 把错误分成 compile、autotest、run time、logic；链表题也按这个顺序查，不要一上来重写整题。[S004]</p><ol start="1"><li>先让它编译。</li><li>再跑一个最小手动测试。</li><li>再跑公开允许的 autotest。</li><li>最后看边界：空链表、一个节点、删头、删尾、找不到。</li></ol><h2 id="">综合模板：数节点</h2><p>这题型常用来确认 traversal 是否安全；下面是原创模板，用来练 <code>curr != NULL</code> 的手感。[S019]</p><pre class="language-c lang-c"><code class="language-c lang-c">int list_length(struct node *head) {
    int length = 0;
    struct node *curr = head;

    while (curr != NULL) {
        length++;
        curr = curr-&gt;next;
    }

    return length;
}
</code></pre>
<details><summary>点开：最小测试怎么写？</summary><p>先测空链表长度是不是 0，再测一个节点是不是 1，最后测三个节点是不是 3；小测试能帮你定位 traversal 是不是提前断掉。<span>[S004][S019]</span></p></details><h2 id="5-">5 分钟练习</h2><ul><li><input readOnly="" type="checkbox"/> 写 <code>list_length</code>。</li><li><input readOnly="" type="checkbox"/> 给空链表、一个节点、三个节点各写一个预期。</li><li><input readOnly="" type="checkbox"/> 写一条错因：我这次错在 <code>curr</code>、<code>prev</code>、还是 <code>head</code>？</li></ul><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我能说出链表题先测哪三个边界。</li><li><input readOnly="" type="checkbox"/> 我能按 Debugging Guide 分类错误。</li><li><input readOnly="" type="checkbox"/> 我知道 autotest 失败时要看输出差异。</li><li><input readOnly="" type="checkbox"/> 我不会因为一题失败就整题重写。</li></ul><h2 id="">引用</h2><ul><li>[S001] COMP1511 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S019] Lecture 13/14 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf</a></li><li>[S020] Lecture 15 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-09-linked-list-exam-debugging#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-09-linked-list-exam-debugging</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-09-linked-list-exam-debugging</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:12:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 10 课：期末复习焚诀]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-10-final-revision">https://rakko.cn/posts/comp1511/comp1511-10-final-revision</a></blockquote><div><h1 id="-10-">第 10 课：期末复习焚诀</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 Week 10、Exam revision 入口、Lecture 15/16 和 C reference sheet 做中文转述；prac exam 只给训练方向和链接，不复制题目正文。<span>[S001][S020]</span><span>[S021][S006]</span></p></blockquote><blockquote>
<p>今天只做：按 array、linked list、mixed 的顺序复习，不反过来。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-09-linked-list-exam-debugging">上一课</a> · <a href="/posts/comp1511/comp1511-final-start-here">Final 路线图</a>
别乱跳：先保 hurdle，再捡小题。</p></blockquote>
<h2 id="">本课目标</h2><p>期末不要贪全；先保 array hurdle，再保 linked list hurdle，最后用 mixed questions 捡分。<span>[S001][S020]</span>[S021]</p><table><thead><tr><th> 顺序 </th><th> 做什么 </th></tr></thead><tbody><tr><td> 1 </td><td> 数组和字符串基础 </td></tr><tr><td> 2 </td><td> linked list 遍历/插入/删除 </td></tr><tr><td> 3 </td><td> 指针和 malloc/free 错因 </td></tr><tr><td> 4 </td><td> mixed small questions </td></tr></tbody></table><h2 id="-10-">考前 10 分钟速查</h2><p>Lecture 15/16 进入 exam information、revision 和 exam-style questions；你的考前速查只保留会救命的模板。<span>[S020][S021]</span></p><ul><li><input readOnly="" type="checkbox"/> 数组：下标从 0 到 <code>size - 1</code>。</li><li><input readOnly="" type="checkbox"/> 2D array：外层 row，内层 col。</li><li><input readOnly="" type="checkbox"/> string：停在 <code>&#x27;\0&#x27;</code>。</li><li><input readOnly="" type="checkbox"/> pointer：<code>&amp;</code> 取地址，<code>*</code> 取地址里的值。</li><li><input readOnly="" type="checkbox"/> linked list：<code>curr != NULL</code> 才能读 <code>curr-&gt;data</code>。</li></ul><h2 id="">最小复习循环</h2><p>官方主页列出 Week 10 lab、prac exam solutions 和 exam revision 资源；本站只转成复习流程，不复制 prac exam 题目正文。[S001]</p><ol start="1"><li>15 分钟：做 1 道 array/string。</li><li>15 分钟：做 1 道 linked list traversal。</li><li>15 分钟：修 1 个错因。</li><li>5 分钟：写“下次先看什么”。</li></ol><details><summary>点开：今天只剩 30 分钟怎么办？</summary><p>只做 array hurdle 和 linked list traversal。期末复习最怕翻很多页但没有动手；先保能写出来的模板。<span>[S001][S020]</span></p></details><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我知道期末先保数组和链表。</li><li><input readOnly="" type="checkbox"/> 我能写一个安全的 linked list traversal。</li><li><input readOnly="" type="checkbox"/> 我能解释 <code>malloc</code> 后为什么要检查 <code>NULL</code>。</li><li><input readOnly="" type="checkbox"/> 我不会把 prac exam 内容复制到公开页面。</li></ul><h2 id="">引用</h2><ul><li>[S001] COMP1511 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S020] Lecture 15 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf</a></li><li>[S021] Lecture 16 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_10/COMP1511_26T1_Lecture16.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_10/COMP1511_26T1_Lecture16.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-10-final-revision#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-10-final-revision</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-10-final-revision</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:11:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 Exam 2 急救路线图]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-exam2-start-here">https://rakko.cn/posts/comp1511/comp1511-exam2-start-here</a></blockquote><div><h1 id="comp1511-exam-2-">COMP1511 Exam 2 急救路线图</h1><blockquote><p>非 UNSW 官方材料。本文基于官方课程主页、strings/2D arrays 相关 lecture、Debugging Guide 和 Style Guide 做中文转述；不复制真实考试题正文。<span>[S001][S013]</span><span>[S014][S015]</span><span>[S004][S005]</span></p></blockquote><blockquote>
<p>今天只做：string、2D array、struct array 各过一遍。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-05-2d-arrays-strings-structs">第 5 课</a> · <a href="/posts/comp1511/comp1511-practice-menu">练习菜单</a>
别乱跳：第二次先保逐字符和 row/col。</p></blockquote>
<h2 id="">先把目标缩小</h2><p>Exam 2 先按 strings、2D arrays、structs、functions、assignment-style debugging 来准备；这和本站 AGENTS 规则一致，也贴合官方 Week 04/05 内容走向。<span>[S013][S014]</span>[S015]</p><table><thead><tr><th> 优先级 </th><th> 练什么 </th><th> 过关线 </th></tr></thead><tbody><tr><td> 1 </td><td> string 逐字符 </td><td> 能停在 <code>&#x27;\0&#x27;</code> </td></tr><tr><td> 2 </td><td> 2D array </td><td> 能 row/col 双循环 </td></tr><tr><td> 3 </td><td> struct array </td><td> 能读 <code>items[i].field</code> </td></tr><tr><td> 4 </td><td> debugging </td><td> 能分清错误类型 </td></tr></tbody></table><h2 id="-3-">今日 3 轮</h2><p>每轮 25 分钟，只做一件事。不要同时开 lecture、lab、答案和聊天窗口。[S001]</p><ol start="1"><li>看第 5 课。</li><li>做 1 道 string 或 2D array 题。</li><li>写 1 条错因。</li></ol><h2 id="">考前速查</h2><p>官方 Debugging Guide 建议先分类错误；Exam 2 也按 compile、autotest、run time、logic 的顺序查。[S004]</p><ul><li><input readOnly="" type="checkbox"/> 编译不过：看第一条错误。</li><li><input readOnly="" type="checkbox"/> 输出不对：看空格、换行、大小写。</li><li><input readOnly="" type="checkbox"/> 2D array 错：检查 row/col 有没有写反。</li><li><input readOnly="" type="checkbox"/> string 错：检查有没有越过 <code>&#x27;\0&#x27;</code>。</li></ul><details><summary>点开：我很慌时只做什么？</summary><p>只做 2D array 模板和 string 模板。先拿会循环的分，再慢慢补 struct 和函数限制。<span>[S014][S015]</span></p></details><h2 id="">引用</h2><ul><li>[S001] COMP1511 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S005] COMP1511 Style Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html</a></li><li>[S013] Lecture 7 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf</a></li><li>[S014] Lecture 8 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf</a></li><li>[S015] Lecture 9 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-exam2-start-here#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-exam2-start-here</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-exam2-start-here</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:10:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 Exam 3 急救路线图]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-exam3-start-here">https://rakko.cn/posts/comp1511/comp1511-exam3-start-here</a></blockquote><div><h1 id="comp1511-exam-3-">COMP1511 Exam 3 急救路线图</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 pointers、malloc/free、linked list 和 debugging 相关公开资料做中文转述；不复制真实考试题正文。<span>[S016][S017]</span><span>[S018][S019]</span>[S004]</p></blockquote><blockquote>
<p>今天只做：画链表，写 traversal，再写一条 <code>head/curr/prev/free</code> 错因。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-07-malloc-free-linked-list-start">第 7 课</a> · <a href="/posts/comp1511/comp1511-practice-menu">练习菜单</a>
别乱跳：第三次先保 traversal，再保删除。</p></blockquote>
<h2 id="">先把目标缩小</h2><p>Exam 3 先保 pointers、malloc/free、linked list 遍历、插入和删除；这些主题集中出现在 Lecture 10 到 Lecture 13/14。<span>[S016][S017]</span><span>[S018][S019]</span></p><table><thead><tr><th> 优先级 </th><th> 练什么 </th><th> 过关线 </th></tr></thead><tbody><tr><td> 1 </td><td> 指针读法 </td><td> 分清 <code>&amp;</code> 和 <code>*</code> </td></tr><tr><td> 2 </td><td> malloc/free </td><td> 申请、检查、释放 </td></tr><tr><td> 3 </td><td> traversal </td><td> <code>curr != NULL</code> </td></tr><tr><td> 4 </td><td> delete </td><td> 能处理删头 </td></tr></tbody></table><h2 id="-3-">今日 3 轮</h2><ul><li><input readOnly="" type="checkbox"/> 画 1 条链表。</li><li><input readOnly="" type="checkbox"/> 写 1 个 traversal。</li><li><input readOnly="" type="checkbox"/> 写 1 条错因：我错在 <code>head</code>、<code>curr</code>、<code>prev</code>、还是 <code>free</code>？</li></ul><h2 id="">最小模板</h2><p>linked list 题先写 traversal；插入删除都是在这个安全移动基础上加逻辑。<span>[S017][S018]</span>[S019]</p><pre class="language-c lang-c"><code class="language-c lang-c">struct node *curr = head;
while (curr != NULL) {
    curr = curr-&gt;next;
}
</code></pre>
<details><summary>点开：先别做什么？</summary><p>先别背大段答案。链表题真正保命的是画图、保护 <code>head</code>、检查 <code>NULL</code>、最后再 <code>free</code>。<span>[S017][S018]</span>[S019]</p></details><h2 id="">引用</h2><ul><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S016] Lecture 10 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture10.pdf</a></li><li>[S017] Lecture 11 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_7/COMP1511_26T1_Lecture11.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_7/COMP1511_26T1_Lecture11.pdf</a></li><li>[S018] Lecture 13 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_8/COMP1511_26T1_Lecture13.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_8/COMP1511_26T1_Lecture13.pdf</a></li><li>[S019] Lecture 13/14 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture1314.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-exam3-start-here#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-exam3-start-here</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-exam3-start-here</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:09:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 Final 急救路线图]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-final-start-here">https://rakko.cn/posts/comp1511/comp1511-final-start-here</a></blockquote><div><h1 id="comp1511-final-">COMP1511 Final 急救路线图</h1><blockquote><p>非 UNSW 官方材料。本文基于官方课程主页、Exam information/revision lectures、C reference sheet 和公开 revision 入口做中文转述；不复制 prac exam 题目正文。<span>[S001][S020]</span><span>[S021][S006]</span></p></blockquote><blockquote>
<p>今天只做：先 array hurdle，再 linked list hurdle，最后 mixed。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-10-final-revision">第 10 课</a> · <a href="/posts/comp1511/comp1511-practice-menu">练习菜单</a>
别乱跳：期末不要从最难大题开始。</p></blockquote>
<h2 id="">先把目标缩小</h2><p>Final 先保 array hurdle，再保 linked list hurdle，最后做 mixed small questions；官网 Week 10 和 Important Resources 区域提供 revision/prac exam 入口。<span>[S001][S020]</span>[S021]</p><table><thead><tr><th> 顺序 </th><th> 今天做 </th><th> 做到什么算过 </th></tr></thead><tbody><tr><td> 1 </td><td> array/string </td><td> 能安全循环 </td></tr><tr><td> 2 </td><td> linked list </td><td> 能 traversal + delete head </td></tr><tr><td> 3 </td><td> pointer/malloc </td><td> 能解释地址和释放 </td></tr><tr><td> 4 </td><td> mixed </td><td> 限时做，不恋战 </td></tr></tbody></table><h2 id="50-">50 分钟急救版</h2><ol start="1"><li>10 分钟：看第 10 课速查。</li><li>15 分钟：做 1 道 array/string。</li><li>15 分钟：做 1 道 linked list。</li><li>10 分钟：写错因和下一题入口。</li></ol><h2 id="">不要踩的坑</h2><ul><li><input readOnly="" type="checkbox"/> 不要把 <code>autotest</code> 当作 <code>submit</code>。</li><li><input readOnly="" type="checkbox"/> 不要在公开页面复制真实考试题正文。</li><li><input readOnly="" type="checkbox"/> 不要用题目禁止的库函数或语言特性。</li><li><input readOnly="" type="checkbox"/> 不要在链表题里乱改 <code>head</code>。</li></ul><details><summary>点开：只剩一天怎么办？</summary><p>只跑 array/string + linked list 两条线。Final 复习不是把所有内容看一遍，而是让手能写出保命模板。<span>[S001][S020]</span>[S021]</p></details><h2 id="">引用</h2><ul><li>[S001] COMP1511 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S020] Lecture 15 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_9/COMP1511_26T1_Lecture15.pdf</a></li><li>[S021] Lecture 16 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_10/COMP1511_26T1_Lecture16.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_10/COMP1511_26T1_Lecture16.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-final-start-here#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-final-start-here</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-final-start-here</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:08:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 练习菜单]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-practice-menu">https://rakko.cn/posts/comp1511/comp1511-practice-menu</a></blockquote><div><h1 id="comp1511-">COMP1511 练习菜单</h1><blockquote><p>非 UNSW 官方材料。本文只整理训练方向和官方公开入口，不复制 revision/prac exam 题目正文。<span>[S001][S031]</span><span>[S032][S033]</span><span>[S034][S035]</span>[S036]</p></blockquote><blockquote>
<p>今天只做：只挑 1 个练习方向，不挑一整套。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-mistake-log-template">错题本模板</a>
别乱跳：选完题就离开菜单，别继续逛。</p></blockquote>
<h2 id="">今天只挑一题</h2><p>COMP1511 官网按 week、revision、resources 组织了大量公开练习入口；这里把它压成“每天只挑一题”的菜单，防止你在页面之间乱跳。[S001]</p><table><thead><tr><th> 状态 </th><th> 今天只做 </th></tr></thead><tbody><tr><td> 第二次 </td><td> string / 2D array / struct array </td></tr><tr><td> 第三次 </td><td> pointer / malloc / linked list traversal </td></tr><tr><td> 期末 </td><td> array hurdle / linked list hurdle </td></tr></tbody></table><h2 id="exam-2-">Exam 2 菜单</h2><p>Exam 2 先练 strings、2D arrays、structs 和 debugging；Week 04/05 extra revision 可作为公开练习入口。<span>[S031][S032]</span></p><ul><li><input readOnly="" type="checkbox"/> 逐字符扫描一个 string。</li><li><input readOnly="" type="checkbox"/> 用 row/col 走完一个 2D array。</li><li><input readOnly="" type="checkbox"/> 从 struct array 里找最大值。</li><li><input readOnly="" type="checkbox"/> 按 Debugging Guide 写出错误类型。[S004]</li></ul><h2 id="exam-3-">Exam 3 菜单</h2><p>Exam 3 先练 pointers、malloc/free 和 linked list；Week 06/07/08 extra revision 可作为公开练习入口。<span>[S033][S034]</span>[S035]</p><ul><li><input readOnly="" type="checkbox"/> 画出 <code>int *p = &amp;x</code>。</li><li><input readOnly="" type="checkbox"/> 写一个 <code>create_node</code>。</li><li><input readOnly="" type="checkbox"/> 写一个 linked list traversal。</li><li><input readOnly="" type="checkbox"/> 写一个 delete-head 分支。</li></ul><h2 id="final-">Final 菜单</h2><p>Final 先从 Week 10 revision、exam-style resources 和 C reference sheet 回到保命模板；这里只留训练方向，不复制 prac exam 内容。<span>[S006][S028]</span><span>[S029][S036]</span></p><ul><li><input readOnly="" type="checkbox"/> 15 分钟 array/string。</li><li><input readOnly="" type="checkbox"/> 15 分钟 linked list。</li><li><input readOnly="" type="checkbox"/> 10 分钟 pointer/malloc 错因。</li><li><input readOnly="" type="checkbox"/> 10 分钟 mixed question。</li></ul><details><summary>点开：不会选题怎么办？</summary><p>选你最怕但最短的那一类。不要选“大综合”，先选 string 计数、2D array 求和、linked list 长度这种能 25 分钟结束的题。<span>[S001][S004]</span></p></details><h2 id="">做完写这三行</h2><pre class="language-text lang-text"><code class="language-text lang-text">我错在：
下次先看：
同类题口诀：
</code></pre>
<h2 id="">引用</h2><ul><li>[S001] COMP1511 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S028] Additional exam-like questions: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/lab_exercises_like_the_exam.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/lab_exercises_like_the_exam.html</a></li><li>[S029] Prac Exam Solutions: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/prac-exam-solns.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/prac-exam-solns.html</a></li><li>[S031] Week 04 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/04/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/04/questions</a></li><li>[S032] Week 05 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/05/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/05/questions</a></li><li>[S033] Week 06 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/06/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/06/questions</a></li><li>[S034] Week 07 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/07/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/07/questions</a></li><li>[S035] Week 08 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/08/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/08/questions</a></li><li>[S036] Week 10 extra revision: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/10/questions">https://cgi.cse.unsw.edu.au/~cs1511/26T1/revision/10/questions</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-practice-menu#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-practice-menu</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-practice-menu</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Tue, 19 May 2026 13:06:40 GMT</pubDate></item><item><title><![CDATA[COMP1511 Exam 1 急救路线图]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-exam1-start-here">https://rakko.cn/posts/comp1511/comp1511-exam1-start-here</a></blockquote><div><h1 id="comp1511-exam-1-">COMP1511 Exam 1 急救路线图</h1><blockquote><p>非 UNSW 官方材料。这是百夜米迦尔基于 COMP1511 26T1 官方公开页面、Lab Exam 信息页和 lecture slides 写的中文转述学习笔记，不复制题目正文、不托管 PDF/PPT、不替代官方说明。<span>[S001][S002]</span>[S003]</p></blockquote><blockquote>
<p>今天只做：基础虚就按第 1-4 课顺序补，不开其他路线。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-01-terminal-hello-c">第 1 课</a> · <a href="/posts/comp1511/comp1511-practice-menu">练习菜单</a>
别乱跳：Exam 1 只保编译、循环、数组、debugging。</p></blockquote>
<h2 id="">先把目标缩小</h2><p>课程首页把内容按 week、lecture、tutorial、lab、revision 和 resources 组织；Lab Exam 信息页公开说明了示例考试的时间、题量、分值结构和保密要求，所以今晚的目标不是“把整门课完整补完”，而是按 Exam 1 最高收益主题补齐输入输出、条件、循环、函数、数组、字符串和 debugging。<span>[S001][S003]</span></p><table><thead><tr><th> 优先级 </th><th> 今晚主题 </th><th> 你要做到 </th></tr></thead><tbody><tr><td> 1 </td><td> 1D / 2D array </td><td> 能用下标循环、计数、找位置、返回结果 </td></tr><tr><td> 2 </td><td> 输入输出 </td><td> 能写 <code>printf</code> / <code>scanf</code>，并让格式完全匹配 </td></tr><tr><td> 3 </td><td> 条件和循环 </td><td> 能把题目条件翻译成 <code>if/else</code>、<code>while</code>、<code>for</code> </td></tr><tr><td> 4 </td><td> debugging / string </td><td> 能定位编译错误、autotest 差异和字符串结束条件 </td></tr></tbody></table><h2 id="">官方来源告诉我们的复习顺序</h2><p>Lecture 1/2 覆盖 C 程序、终端、变量和基础输入输出；Lecture 3/4 进入条件与循环；Lecture 5/6 开始强调函数、style 和数组；Lecture 7/8/9 继续展开字符串与二维数组。这个顺序很适合做“从第一节课开始，但只抓 Exam 1 相关动作”的急救路径。<span>[S007][S008]</span><span>[S009][S010]</span><span>[S011][S012]</span><span>[S013][S014]</span>[S015]</p><p>Debugging Guide 把错误分成编译错误、autotest 错误、运行时错误和逻辑错误；这正好对应考前最后一轮检查：先让代码能编译，再看输出差异，最后处理边界和逻辑。[S004]</p><details><summary>点开：如果只剩 90 分钟，怎么救？</summary><ol start="1"><li>25 分钟：写 3 个最小程序，分别练 <code>printf</code>、<code>scanf</code>、<code>if/else</code>。<span>[S006][S008]</span>[S009]</li><li>35 分钟：只练数组模板，先 1D，再 2D；数组是 lecture 中从 Week 3/4 开始反复出现的核心材料。<span>[S012][S013]</span><span>[S014][S015]</span></li><li>20 分钟：按 Debugging Guide 的分类查错，不要在一条报错里硬猜。[S004]</li><li>10 分钟：读 Lab Exam 信息页的时间、autotest、fetch 和保密要求，只看规则，不复制题目内容。[S003]</li></ol></details><h2 id="">今天别做这些</h2><ul><li>不要把 UNSW PDF 或 PPT 复制到自己站上；这里所有学习页只链接官方来源并做中文转述。[S002]</li><li>不要复刻 Lab Exam 题目、样例数组、样例输出或题目提供的初始文件；只引用公开规则和高层结构。[S003]</li><li>不要用没讲过的花哨 C 特性救场；Style Guide 建议初学者优先使用 lecture 中已经覆盖的语言特性。[S005]</li></ul><h2 id="">过关勾选</h2><ul><li><input readOnly="" type="checkbox"/> 我能编译并运行一个最小 C 程序。</li><li><input readOnly="" type="checkbox"/> 我能写 <code>if/else</code> 和至少一种循环。</li><li><input readOnly="" type="checkbox"/> 我能用下标访问 1D / 2D array。</li><li><input readOnly="" type="checkbox"/> 我能按 Debugging Guide 先分清错误类型。[S004]</li></ul><h2 id="">本系列链接</h2><ul><li>当前：路线图</li><li><a href="/posts/comp1511/comp1511-01-terminal-hello-c">第 1 课：终端、main 与第一段 C 程序</a></li><li><a href="/posts/comp1511/comp1511-02-variables-input-branching">第 2 课：变量、scanf 与 if/else</a></li><li><a href="/posts/comp1511/comp1511-03-loops-functions-arrays">第 3 课：循环、函数与数组</a></li><li><a href="/posts/comp1511/comp1511-04-debugging-strings-exam-drill">第 4 课：debugging、字符串与模拟考试</a></li></ul><h2 id="">引用</h2><ul><li>[S001] COMP1511 26T1 course homepage: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/">https://cgi.cse.unsw.edu.au/~cs1511/current/</a></li><li>[S002] COMP1511 lecture slides index: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/</a></li><li>[S003] COMP1511 Lab Exam public information page: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html">https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S005] COMP1511 Style Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S007] Lecture 1 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture01.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture01.pdf</a></li><li>[S008] Lecture 2 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture02.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture02.pdf</a></li><li>[S009] Lecture 3 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf</a></li><li>[S010] Lecture 4 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf</a></li><li>[S011] Lecture 5 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture05.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture05.pdf</a></li><li>[S012] Lecture 6 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture06.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture06.pdf</a></li><li>[S013] Lecture 7 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf</a></li><li>[S014] Lecture 8 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf</a></li><li>[S015] Lecture 9 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-exam1-start-here#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-exam1-start-here</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-exam1-start-here</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 18 May 2026 15:29:00 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 2 课：变量、scanf 与 if/else]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-02-variables-input-branching">https://rakko.cn/posts/comp1511/comp1511-02-variables-input-branching</a></blockquote><div><h1 id="-2-scanf--ifelse">第 2 课：变量、scanf 与 if/else</h1><blockquote><p>非 UNSW 官方材料。本文按官方 Lecture 2/3/4 和 C reference sheet 转述变量、输入输出和条件控制；练习题为原创。<span>[S008][S009]</span><span>[S010][S006]</span></p></blockquote><blockquote>
<p>今天只做：把 <code>int</code>、<code>double</code>、<code>char</code> 和 <code>scanf</code> 占位符配对。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-01-terminal-hello-c">上一课</a> · <a href="/posts/comp1511/comp1511-03-loops-functions-arrays">下一课：循环、函数与数组</a>
别乱跳：输入题先把格式读对，再写漂亮分支。</p></blockquote>
<h2 id="">变量：先说类型，再放值</h2><p>Lecture 2 明确把 variables、constants 和 C 里的 maths 放在早期主题；你现在要先能识别 <code>int</code>、<code>double</code>、<code>char</code>，再配对 <code>printf</code> / <code>scanf</code> 的格式占位符。<span>[S008][S006]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">int age = 18;
double mark = 72.5;
char grade = &#x27;C&#x27;;
</code></pre>
<table><thead><tr><th> 类型 </th><th> 常见用途 </th><th> 输出占位符 </th></tr></thead><tbody><tr><td> <code>int</code> </td><td> 整数 </td><td> <code>%d</code> </td></tr><tr><td> <code>double</code> </td><td> 小数 </td><td> <code>%lf</code> </td></tr><tr><td> <code>char</code> </td><td> 单个字符 </td><td> <code>%c</code> </td></tr></tbody></table><h2 id="scanf">scanf：先练对普通变量</h2><p>Lecture 3 回顾了 <code>printf()</code> / <code>scanf()</code>，Lecture 4 继续把 <code>scanf</code> 错误和控制流放在一起；考前先记住普通变量读入时要把地址传给 <code>scanf</code>。<span>[S009][S010]</span></p><pre class="language-c lang-c"><code class="language-c lang-c">int x;
scanf(&quot;%d&quot;, &amp;x);

char ch;
scanf(&quot; %c&quot;, &amp;ch);
</code></pre>
<p><code>%c</code> 前面的空格是为了跳过前面残留的空白字符；这条是考前很实用的经验解释，来源背景是官方 debugging 和 lecture 对输入错误的反复强调。<span>[S004][S010]</span></p><details><summary>点开：为什么 int 要写 &amp;x？</summary><p><code>scanf</code> 要把读到的值写回变量，所以它需要变量的位置；对普通 <code>int</code>、<code>double</code>、<code>char</code> 变量，先按 <code>&amp;变量名</code> 的模式写。后面学数组和字符串时会有例外。[S006]</p></details><h2 id="ifelse">if/else：把条件翻译成分支</h2><p>Lecture 3 把 <code>if</code> statements、logical operators、<code>else</code> 和循环放在 control flow 主题里；写分支时先按中文题意拆成互斥区间，再写代码。[S009]</p><pre class="language-c lang-c"><code class="language-c lang-c">if (mark &lt; 50) {
    printf(&quot;fail\n&quot;);
} else if (mark &lt; 65) {
    printf(&quot;pass\n&quot;);
} else {
    printf(&quot;higher\n&quot;);
}
</code></pre>
<p>这里第二个分支不用再写 <code>mark &gt;= 50</code>，因为第一段已经排除了更小的情况。这是原创讲法，用来训练“前面的条件会影响后面的条件”。[S009]</p><h2 id="">立刻练</h2><p>写一个程序读入整数 <code>temperature</code>：小于 18 输出 <code>cold</code>，18 到 27 输出 <code>ok</code>，大于 27 输出 <code>hot</code>。这道题是原创，不使用官方 Lab Exam 题目或样例。[S003]</p><details><summary>参考答案</summary><pre class="language-c lang-c"><code class="language-c lang-c">#include &lt;stdio.h&gt;

int main(void) {
    int temperature;
    scanf(&quot;%d&quot;, &amp;temperature);

    if (temperature &lt; 18) {
        printf(&quot;cold\n&quot;);
    } else if (temperature &lt;= 27) {
        printf(&quot;ok\n&quot;);
    } else {
        printf(&quot;hot\n&quot;);
    }

    return 0;
}
</code></pre></details><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我能把 <code>int</code>、<code>double</code>、<code>char</code> 和格式占位符配上。</li><li><input readOnly="" type="checkbox"/> 我知道普通变量读入常见写法是 <code>scanf(&quot;%d&quot;, &amp;x)</code>。</li><li><input readOnly="" type="checkbox"/> 我知道读字符时常用 <code>scanf(&quot; %c&quot;, &amp;ch)</code>。</li><li><input readOnly="" type="checkbox"/> 我能用 <code>if/else if/else</code> 写互斥区间。</li></ul><h2 id="">引用</h2><ul><li>[S003] COMP1511 Lab Exam public information page: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html">https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S008] Lecture 2 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture02.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_1/COMP1511_26T1_Lecture02.pdf</a></li><li>[S009] Lecture 3 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf</a></li><li>[S010] Lecture 4 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-02-variables-input-branching#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-02-variables-input-branching</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-02-variables-input-branching</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 18 May 2026 15:27:00 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 3 课：循环、函数与数组]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-03-loops-functions-arrays">https://rakko.cn/posts/comp1511/comp1511-03-loops-functions-arrays</a></blockquote><div><h1 id="-3-">第 3 课：循环、函数与数组</h1><blockquote><p>非 UNSW 官方材料。本文基于官方 functions、style、1D array、2D array 和 strings 相关 lecture PDF 做中文转述；所有练习模板为原创。<span>[S011][S012]</span><span>[S013][S014]</span>[S015]</p></blockquote><blockquote>
<p>今天只做：写一个 <code>for</code> 循环，能安全访问 <code>array[i]</code>。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-02-variables-input-branching">上一课</a> · <a href="/posts/comp1511/comp1511-04-debugging-strings-exam-drill">下一课：debugging、字符串与模拟考试</a>
别乱跳：数组题先找下标，不先背一整章。</p></blockquote>
<h2 id="">循环：重复做同一件事</h2><p>Lecture 3/4 把 loop 放进 control flow，Lecture 6 进入 arrays；数组题其实就是“用循环访问很多格子”，所以你先把 <code>for</code> 读顺。<span>[S009][S010]</span>[S012]</p><pre class="language-c lang-c"><code class="language-c lang-c">for (int i = 0; i &lt; size; i++) {
    printf(&quot;%d\n&quot;, i);
}
</code></pre>
<p>这段的读法是：<code>i</code> 从 0 开始；只要 <code>i &lt; size</code> 就继续；每轮后 <code>i++</code>。这个解释是本站原创，但结构来自 C 的基础控制流和数组访问。<span>[S006][S012]</span></p><h2 id="">函数题：先看题目让不让输出</h2><p>Lecture 5 把 functions 和 style 放在同一课，Style Guide 也强调代码布局、函数和限制；Exam 练习里常见坑是题目要 <code>return</code>，你却写了 <code>printf</code>。<span>[S011][S005]</span></p><table><thead><tr><th> 题目说法 </th><th> 你该怎么做 </th></tr></thead><tbody><tr><td> should return </td><td> 用 <code>return 值;</code> </td></tr><tr><td> should not print </td><td> 不要写 <code>printf</code> </td></tr><tr><td> should not scan </td><td> 不要写 <code>scanf</code> </td></tr></tbody></table><h2 id="1d-array-">1D array 模板：找位置，再处理附近</h2><p>Lecture 6 开始看 arrays，并把函数和数组放在一起复习；下面的模板不是官方题目，是用于练“找目标下标”的原创模式。[S012]</p><pre class="language-c lang-c"><code class="language-c lang-c">int index_of_first(int values[], int size, int target) {
    for (int i = 0; i &lt; size; i++) {
        if (values[i] == target) {
            return i;
        }
    }

    return -1;
}
</code></pre>
<details><summary>点开：为什么找不到时返回 -1？</summary><p>数组合法下标从 0 开始，<code>-1</code> 不是合法下标，所以常被用来表示“没找到”。这是原创约定讲解；真正考试里要以题目要求为准。[S012]</p></details><h2 id="2d-array-">2D array 模板：外层行，内层列</h2><p>Lecture 7/8/9 都围绕 strings、array of arrays 和 2D arrays 继续展开；二维数组先按“行 row + 列 col”读，不要一上来想复杂图形。<span>[S013][S014]</span>[S015]</p><pre class="language-c lang-c"><code class="language-c lang-c">#define NUM_COLS 6

int count_rows_with_even_sum(int array[][NUM_COLS], int num_rows) {
    int rows = 0;

    for (int row = 0; row &lt; num_rows; row++) {
        int sum = 0;

        for (int col = 0; col &lt; NUM_COLS; col++) {
            sum += array[row][col];
        }

        if (sum % 2 == 0) {
            rows++;
        }
    }

    return rows;
}
</code></pre>
<p>最容易错的是把 <code>sum</code> 放到外层循环外面；每一行都要重新计数，这个模式对应 2D array 题的基本循环结构。<span>[S014][S015]</span></p><h2 id="">本课过关标准</h2><ul><li><input readOnly="" type="checkbox"/> 我能写 <code>for</code> 循环访问 <code>array[i]</code>。</li><li><input readOnly="" type="checkbox"/> 我会先看函数题能不能 <code>printf</code> / <code>scanf</code>。</li><li><input readOnly="" type="checkbox"/> 我知道 2D array 常写 <code>array[row][col]</code>。</li><li><input readOnly="" type="checkbox"/> 我知道每一行的临时计数要在外层循环里重置。</li></ul><h2 id="">引用</h2><ul><li>[S005] COMP1511 Style Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S009] Lecture 3 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture03.pdf</a></li><li>[S010] Lecture 4 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_2/COMP1511_26T1_Lecture04.pdf</a></li><li>[S011] Lecture 5 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture05.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture05.pdf</a></li><li>[S012] Lecture 6 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture06.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_3/COMP1511_26T1_Lecture06.pdf</a></li><li>[S013] Lecture 7 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf</a></li><li>[S014] Lecture 8 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf</a></li><li>[S015] Lecture 9 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_5/COMP1511_26T1_Lecture09.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-03-loops-functions-arrays#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-03-loops-functions-arrays</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-03-loops-functions-arrays</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 18 May 2026 15:26:00 GMT</pubDate></item><item><title><![CDATA[COMP1511 第 4 课：debugging、字符串与模拟考试]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/comp1511/comp1511-04-debugging-strings-exam-drill">https://rakko.cn/posts/comp1511/comp1511-04-debugging-strings-exam-drill</a></blockquote><div><h1 id="-4-debugging">第 4 课：debugging、字符串与模拟考试</h1><blockquote><p>非 UNSW 官方材料。本文基于 Debugging Guide、Lab Exam 信息页、strings/2D array lecture 和 C reference sheet 做中文转述；不复制官方 exam 题目或样例。<span>[S004][S003]</span><span>[S014][S006]</span></p></blockquote><blockquote>
<p>今天只做：把错误分成 compile、autotest、runtime、logic 其中一类。
下一步：<a href="/posts/comp1511/comp1511-start-here">主控台</a> · <a href="/posts/comp1511/comp1511-03-loops-functions-arrays">上一课</a> · <a href="/posts/comp1511/comp1511-05-2d-arrays-strings-structs">下一课：strings、2D arrays 与 structs</a>
别乱跳：先看第一条错误，不整题重写。</p></blockquote>
<h2 id="debugging">debugging：先分类，不要乱猜</h2><p>Debugging Guide 把问题分成 compile error、autotest error、run time error 和 logic error；你明天考试时先判断是哪一类，再决定看报错、看输出差异、还是补边界测试。[S004]</p><table><thead><tr><th> 症状 </th><th> 先查什么 </th></tr></thead><tbody><tr><td> 编译后马上报错 </td><td> 看第一条错误、行号和 dcc 解释 </td></tr><tr><td> autotest 不过 </td><td> 先挑一个失败测试，看你的输出和期望输出差异 </td></tr><tr><td> 运行中崩掉 </td><td> 检查数组下标、除以 0、输入是否读到 </td></tr><tr><td> 结果不对 </td><td> 检查条件边界、循环次数和初始化位置 </td></tr></tbody></table><h2 id="-char-array-">字符串：先当 char array 看</h2><p>Lecture 7/8 把 strings 和 arrays 放在一起讲，C reference sheet 也列出 <code>string.h</code> 中常见函数；Exam 1 急救时先掌握 <code>char</code> 数组和 <code>&#x27;\0&#x27;</code> 结束标记，再考虑库函数。<span>[S013][S014]</span>[S006]</p><pre class="language-c lang-c"><code class="language-c lang-c">char word[51];
fgets(word, 51, stdin);

int i = 0;
while (word[i] != &#x27;\0&#x27;) {
    i++;
}
</code></pre>
<p>如果题目要求逐字符处理，就用下标循环读 <code>word[i]</code>。下面是原创练习模板，用来训练“遇到某个字符就改掉”。[S014]</p><pre class="language-c lang-c"><code class="language-c lang-c">int i = 0;
while (word[i] != &#x27;\0&#x27;) {
    if (word[i] == &#x27;x&#x27;) {
        word[i] = &#x27;y&#x27;;
    }
    i++;
}
</code></pre>
<details><summary>点开：什么时候不用 scanf(&quot;%s&quot;, word)？</summary><p>如果你需要读入包含空格的一整行，<code>scanf(&quot;%s&quot;, word)</code> 会在空白处停下；<code>fgets</code> 更适合整行输入。具体考试能不能用某个函数，仍然以题目限制和 Style Guide/lecture 覆盖范围为准。<span>[S005][S006]</span>[S014]</p></details><h2 id="30-">30 分钟模拟节奏</h2><p>Lab Exam 信息页公开说明示例考试有阅读时间、工作时间、题量、分值不均和 autotest/fetch 相关命令；这里不复刻题目，只把这些高层规则转成做题节奏。[S003]</p><ol start="1"><li>5 分钟：只读题，标出每题是否要 <code>return</code>、是否禁止 <code>printf</code> / <code>scanf</code>。</li><li>10 分钟：先做最熟的数组循环题。</li><li>10 分钟：做 2D array 或 string 题，先写循环框架。</li><li>5 分钟：按 Debugging Guide 分类查错，优先修编译和输出格式。[S004]</li></ol><h2 id="">最后检查清单</h2><ul><li><input readOnly="" type="checkbox"/> 我每题都保存了文件。</li><li><input readOnly="" type="checkbox"/> 我至少重新编译过一次。</li><li><input readOnly="" type="checkbox"/> 我按公开说明使用允许的 autotest/fetch 命令，而不是把题目内容搬到公开地方。[S003]</li><li><input readOnly="" type="checkbox"/> 我检查了输出大小写、空格和换行。</li><li><input readOnly="" type="checkbox"/> 我没有使用题目或 Style Guide 不允许的语言特性。[S005]</li></ul><h2 id="">引用</h2><ul><li>[S003] COMP1511 Lab Exam public information page: <a href="https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html">https://cgi.cse.unsw.edu.au/~cs1511/current/labexam/index.html</a></li><li>[S004] COMP1511 Debugging Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/debugging_guide.html</a></li><li>[S005] COMP1511 Style Guide: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/style_guide.html</a></li><li>[S006] COMP1511 C reference sheet PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/resources/c-reference-sheet.pdf</a></li><li>[S013] Lecture 7 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture07.pdf</a></li><li>[S014] Lecture 8 PDF: <a href="https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf">https://cgi.cse.unsw.edu.au/~cs1511/26T1/slides/week_4/COMP1511_26T1_Lecture08.pdf</a></li></ul><script id="comp1511-checklist-enhancer">(() => {
  const storagePrefix = 'comp1511-checklist:v1:'
  const readText = (element) => (element?.innerText || element?.textContent || '').replace(/\s+/g, ' ').trim()
  const enhance = () => {
    const root = document.getElementById('main-content-render') || document.querySelector('article') || document
    const checkboxes = Array.from(root.querySelectorAll('input[type="checkbox"]'))

    checkboxes.forEach((checkbox, index) => {
      const item = checkbox.closest('li')
      const label = readText(item || checkbox.parentElement).slice(0, 80)
      const key = storagePrefix + location.pathname.replace(/\/+$/, '') + ':' + index + ':' + label

      if (item) {
        item.style.listStyle = 'none'
        item.style.display = 'flex'
        item.style.alignItems = 'flex-start'
        item.style.gap = '0.65em'
        item.style.marginLeft = '0'
        item.style.cursor = 'pointer'
      }

      if (!checkbox.dataset.comp1511ChecklistReady) {
        checkbox.dataset.comp1511ChecklistReady = 'true'
        checkbox.readOnly = false
        checkbox.disabled = false
        checkbox.removeAttribute('readonly')
        checkbox.style.cursor = 'pointer'
        checkbox.style.flex = '0 0 auto'
        checkbox.style.marginTop = '0.35em'
        checkbox.style.pointerEvents = 'none'

        const save = () => {
          try {
            localStorage.setItem(key, checkbox.checked ? '1' : '0')
          } catch {}
        }
        const toggle = () => {
          checkbox.checked = !checkbox.checked
          save()
        }

        checkbox.addEventListener('keydown', (event) => {
          if (event.key !== ' ' && event.key !== 'Enter') return
          event.preventDefault()
          toggle()
        })
        checkbox.addEventListener('change', save)

        item?.addEventListener('click', (event) => {
          const target = event.target
          if (target === checkbox || target.closest?.('a, button, input, summary, details, pre')) return
          toggle()
        })
      }

      try {
        const saved = localStorage.getItem(key)
        if (saved !== null) checkbox.checked = saved === '1'
      } catch {}
    })
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enhance, { once: true })
  } else {
    enhance()
  }
  setTimeout(enhance, 250)
  setTimeout(enhance, 1000)
  window.addEventListener('resize', () => setTimeout(enhance, 100), { passive: true })
})()
</script></div><p style="text-align:right"><a href="https://rakko.cn/posts/comp1511/comp1511-04-debugging-strings-exam-drill#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/comp1511/comp1511-04-debugging-strings-exam-drill</link><guid isPermaLink="true">https://rakko.cn/posts/comp1511/comp1511-04-debugging-strings-exam-drill</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 18 May 2026 15:25:00 GMT</pubDate></item><item><title><![CDATA[微积分定理秒杀关键词速记]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/mathematics/calculus-theorem-speedrun">https://rakko.cn/posts/mathematics/calculus-theorem-speedrun</a></blockquote><div><p><strong>这是最新文档</strong></p><h2 id="intermediate-value-theorem----ivt">Intermediate Value Theorem (介值定理 - IVT)</h2><p>秒杀关键词： continuous (连续), opposite signs (一正一负), root (根), exists c such that f(c) = 0 (存在c使得函数值等于某数)。</p><p>大白话： 从A点走到B点，如果一个在水面上，一个在水面下，那你肯定得穿过水面。你刚才做对的那道平面题就是这个。</p><h2 id="mean-value-theorem----mvt">Mean Value Theorem (中值定理 - MVT)</h2><p>秒杀关键词： derivative (导数), $f&#x27;(c)$, rate of change (变化率), tangent parallel to secant (切线平行于割线)。</p><p>大白话： 你开车从悉尼去堪培拉，平均时速是 $100$。那路上肯定有那么一瞬间，你的仪表盘速度刚好指在 $100$ 上。只要题目扯到导数和平均变化的关系，闭眼选它。</p><h2 id="maximum-minimum-theorem---">Maximum-Minimum Theorem (极值定理 / 最值定理)</h2><p>秒杀关键词： closed interval (闭区间 $[a,b]$), maximum / minimum (最大值/最小值), bounded (有界的)。</p><p>大白话： 一段连绵不断的山脉，只要圈定一个明确的起点和终点，里面绝对能找出一个最高峰和一个最低谷。</p><h2 id="second-fundamental-theorem-of-calculus-">Second Fundamental Theorem of Calculus (微积分基本定理第二部分)</h2><p>秒杀关键词： 题目里同时出现了积分号 $\int$ 和 求导符号 $\frac{d}{dx}$。</p><p>大白话： 积分的上限是个变量 $x$，然后让你对整个积分式子求导。这就是微积分的核心——求导和积分是逆运算。</p><h2 id="inverse-function-theorem-">Inverse Function Theorem (反函数定理)</h2><p>秒杀关键词： $f^{-1}$, one-to-one (一一映射), inverse (反函数)。</p><p>大白话： 专门用来算反函数的导数的。原函数某点的斜率如果是 $2$，反函数对应点的斜率就是 $\frac{1}{2}$。</p><h2 id="fundamental-theorem-of-algebra-">Fundamental Theorem of Algebra (代数基本定理)</h2><p>秒杀关键词： polynomial (多项式), complex roots (复数根)。</p><p>大白话： $n$ 次多项式必定有 $n$ 个复数根。这在你们这门微积分课里多半是个凑数的干扰项。</p><h2 id="split-function-theorem-">Split Function Theorem (分段函数定理)</h2><p>秒杀关键词： piecewise function (分段函数)，检查连接点 (break point)。</p><p>大白话： 就是左极限等于右极限，左导数等于右导数那套东西。</p></div><p style="text-align:right"><a href="https://rakko.cn/posts/mathematics/calculus-theorem-speedrun#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/mathematics/calculus-theorem-speedrun</link><guid isPermaLink="true">https://rakko.cn/posts/mathematics/calculus-theorem-speedrun</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Mon, 04 May 2026 23:00:00 GMT</pubDate></item><item><title><![CDATA[逻辑题真值表速通：Part a / Part b 一分钟搞定]]></title><description><![CDATA[<link rel="preload" as="image" href="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic1.png"/><link rel="preload" as="image" href="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic2.png"/><link rel="preload" as="image" href="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic3.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://rakko.cn/posts/productivity/truth-table-speedrun">https://rakko.cn/posts/productivity/truth-table-speedrun</a></blockquote><div><h2 id="">第一步：死记四个符号的“作弊规则”</h2><p><img alt="图一：第一组真值表题目截图" src="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic1.png"/></p><p>不要管它们叫什么“合取”、“析取”，你只需要记住它们像什么人：</p><ul><li>∼ <strong>（波浪号）= 杠精。</strong> 专门唱反调。看到 T 就写 F，看到 F 就写 T。</li><li>∧ <strong>（尖尖朝上）= 挑剔狂。</strong> 必须左右两个都是 T，结果才是 T。只要看到哪怕一个 F，结果直接写 F。</li><li>∨ <strong>（圆圆朝下）= 老好人。</strong> 只要左右看到哪怕一个 T，结果就是 T。只有两个都是 F 时，他才勉强写 F。</li><li>→ <strong>（箭头）= 渣男背叛。</strong> 这是唯一需要注意顺序的！<strong>只有</strong>前面是 T，后面是 F （即 T→F）时，结果才是 F（承诺了却做不到，渣男）。其他所有情况（哪怕是 F→F），结果全写 T。</li></ul><h2 id="-part-a">第二步：光速填表 (Part a)</h2><p><img alt="图二：第二组真值表题目截图" src="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic2.png"/></p><p>用上面这四个规则，你可以直接无脑填表了。我拿<strong>图一</strong>给你举个例子，考场上你就按这个步骤在草稿纸上比划：</p><ol start="1"><li><p><strong>看第一列</strong> ∼p∨q</p><ul><li>先看 p，在心里把它“杠”一下（T, T, F, F 变成 F, F, T, T）。</li><li>然后把这串新结果和 q 放在一起，用“老好人” ∨ 规则。</li><li>第一行：F∨T=T</li><li>第二行：F∨F=F</li><li>第三行：T∨T=T</li><li>第四行：T∨F=T</li><li><strong>填表答案就是：T, F, T, T</strong></li></ul></li><li><p><strong>看第二列</strong> p→∼q</p><ul><li>把 q 在心里“杠”一下（变成 F, T, F, T）。</li><li>把 p 放在前面，新 q 放在后面，找“渣男”情况（前 T 后 F）。</li><li>第一行：T→F （抓到渣男了！） =F</li><li>第二行：T→T=T</li><li>第三行：F→F=T</li><li>第四行：F→T=T</li><li><strong>填表答案就是：F, T, T, T</strong></li></ul></li></ol><p><em>(图二和图三完全是一模一样的机械动作，按规则套就完事了。)</em></p><h2 id="-part-b">第三步：秒杀 Part b（终极作弊技巧）</h2><p><img alt="图三：第三组真值表题目截图" src="https://github.com/KurisuRakko/picx-images-hosting/raw/master/yohaku/posts/truth-table-speedrun/pic3.png"/></p><p>这里有个天大的捷径，你发现了吗？<strong>Part b 下面的那串又长又恶心的公式，括号里的内容，其实就是你在 Part a 刚刚填完的那两列！</strong></p><p>你根本不需要从头算，直接把你表里的答案代进去！</p><p>你要选的三个英文单词的意思：</p><ul><li><strong>Tautology</strong> (永真式)：最后算出来四个全是 T。</li><li><strong>Contradiction</strong> (矛盾式)：最后算出来四个全是 F。</li><li><strong>Contingency</strong> (偶然式)：有 T 有 F。</li></ul><p><strong>实战演示：</strong></p><p><strong>图一的 (b)：</strong> ∼(p→∼q)→∼(∼p∨q)</p><ul><li>前半部分 (p→∼q) 就是你的第二列答案（F, T, T, T）。</li><li>后半部分 (∼p∨q) 就是你的第一列答案（T, F, T, T）。</li><li>公式翻译过来就是：∼(第二列)→∼(第一列)。</li><li>我们只测第一行：第二列是 F，第一列是 T。代进去：∼F→∼T，也就是 T→F。触发渣男规则，结果是 <strong>F</strong>。</li><li>我们再测第二行：第二列是 T，第一列是 F。代进去：∼T→∼F，也就是 F→T。不是渣男，结果是 <strong>T</strong>。</li><li><strong>出结果了！</strong> 有 F 有 T，不用再往下算了，直接选 <strong>Contingency</strong>。</li></ul><p><strong>图二的 (b)：</strong> ∼(∼p→q)∧(p∧∼q)</p><ul><li>翻译：∼(第二列)∧(第一列)。</li><li>你自己算一下第一列的结果是：F, T, F, F。第二列的结果是：T, T, T, F。</li><li>用挑剔狂 ∧ 规则代入测试。你会发现每一行算出来都是 F。</li><li>四个全 F，直接选 <strong>Contradiction</strong>。</li></ul><p><strong>图三的 (b)：</strong> (∼p∨∼q)∨∼(p∧q)</p><ul><li>翻译：(第二列)∨∼(第一列)。</li><li>第一列结果：T, F, F, F。第二列结果：F, T, T, T。</li><li>第一行代入：F∨∼T，即 F∨F=F。</li><li>第二行代入：T∨∼F，即 T∨T=T。</li><li>有 F 有 T，选 <strong>Contingency</strong>。</li></ul><p>就这么简单。把那四个小符号的性格记住，拿笔在纸上标一下，这几道题一分钟就能填完。</p></div><p style="text-align:right"><a href="https://rakko.cn/posts/productivity/truth-table-speedrun#comments">览毕，何不一言？</a></p></div>]]></description><link>https://rakko.cn/posts/productivity/truth-table-speedrun</link><guid isPermaLink="true">https://rakko.cn/posts/productivity/truth-table-speedrun</guid><dc:creator><![CDATA[KurisuRakko]]></dc:creator><pubDate>Sat, 18 Apr 2026 14:01:00 GMT</pubDate></item></channel></rss>