智能程序设计(C语言)


总复习

计算机学院    杨已彪

yangyibiao@nju.edu.cn

提纲

  • 全学期知识地图

  • 重点与易错点串讲

  • 考试形式与评分

  • 模拟练习


全学期知识地图

还记得开学时的「程序需要什么」吗? 一学期下来, 它们都补齐了:

需求 元素 什么时候学的
记住数据 变量、类型 第 1-2 周
计算 表达式、运算符 第 3 周
不同情况 判断 if / switch 第 4 周
重复 循环 while / for 第 5 周
一批数据 数组、排序与查找 第 6-7 周
复用与分解 函数、递归 第 8-9 周
内存与地址 指针 第 10-11 周
字符串 字符串处理、函数指针 第 12 周
复杂数据组织 结构体、链表 第 13 周
长期保存 文件、多文件 第 14 周
综合应用 期末项目 第 15 周 + 考试周答辩

易错点串讲 (1): 类型与运算

  • 整数除法: 7 / 2 = 3 不是 3.5; 7.0 / 2 才是 3.5

  • 溢出不报错: 有符号整数溢出是未定义行为,结果不可预测 (unsigned 才保证"绕回")——不要依赖溢出后的值

  • 类型转换: double 赋给 int 会截断 (3.9 → 3); (double) a / b 才能保住小数

  • 自增优先级: *p++ 是 *(p++); ++i + j++ 这种表达式不要写

  • 浮点比较: a == 0.1 往往不成立, 用 fabs(a - 0.1) < 1e-9


易错点串讲 (2): 控制与函数

  • if (a = 1) 是赋值不是比较——要写 ==; 编译器可能只给个警告

  • switch 漏写 break 会"穿透"到下一个 case

  • 循环三要素: 初值、条件、更新——少一个就是死循环或无循环

  • 数组下标从 0 开始, a[n] 是第 n+1 个 (越界了!)

  • 函数值传递: 想改实参必须传指针 (swap(int *, int *))

  • 递归两要素: 基准情形 + 每次调用规模变小


易错点串讲 (3): 指针与内存

  • 指针 = 地址; & 取地址, * 解引用, 两者互逆

  • a[i] 等价于 *(a + i); 数组名就是首元素地址

  • 指针算术按元素走: p + 1 地址加 sizeof(*p) 字节

  • 野指针: 未初始化的指针不能解引用; free 之后要把指针置 NULL

  • malloc 必须配 free; 忘了 free 就是内存泄漏

  • 字符串: strcpy / strcat 不检查长度, 目标数组要够大; 比较用 strcmp 不是 ==

高地址 低地址 栈 局部变量 · 返回地址 ↓ 堆 malloc / free ↑ 静态区 全局变量 · 字符串字面量 代码区 函数机器指令 指针 = 地址 p 里存的是字节编号 野指针 / 越界 会踩到别的区 malloc 在堆 局部变量在栈
易错点串讲 (4): 文件与结构体

  • 结构体可以整体赋值 (p1 = p2), 但不能用判等运算符比较 (p1 == p2 不合法)

  • 结构体指针用 -> 访问成员: p->x 等价于 (*p).x

  • 文件: fopen 后必须检查返回值是否为 NULL; 用完 fclose

  • fgetc 返回 int (用与 EOF 比较判断结束); fgets 返回 char * (用与 NULL 比较)——都不要靠 feof 预判

  • 多文件: 函数原型和类型定义放 .h, 实现放 .c, 头文件加保护宏


易错点串讲 (5): 链表与递归

链表四件套 (笔试高频)

  • 结点: struct node { int value; struct node *next; };

  • 头插: new_node->next = first; first = new_node; (空链表也成立)

  • 删除: 先找到 cur 与 prev; n 不存在时 cur == NULL 必须先返回

  • 释放: free(cur) 之后不能再解引用 cur

if (cur == NULL) return list;      /* 没找到 */
if (prev == NULL) list = cur->next; /* 删头 */
else prev->next = cur->next;
free(cur);

递归三问 (写之前先回答)

  1. 基准情形是什么? (n == 0 / 一位数 / 区间为空)
  2. 每次递归规模在变小吗? (n-1 / 砍一半)
  3. 相信子问题的结果, 本层要做什么?
  • 典型失分: 忘了基准情形 (栈溢出)、规模没变小 (死循环)、先打印再递归 (逆序)

  • 手写练习: 阶乘、斐波那契、二分查找、汉诺塔


考试形式与评分

总评构成: 平时 20% (课堂实操 + OJ) + 期末项目 20% + 闭卷机试 60%

闭卷机试 (60%)

  • 形式: 在线、限时、闭卷, 现场写程序并提交评测

  • 考核内容: 语法基础 + 算法设计 + 智能应用

  • 评分维度: 代码正确性、时间复杂度、内存效率

备考建议:

  • 每周 OJ 的题过一遍, 尤其是做错过的

  • 手写几个"经典小程序": 排序、查找、字符串处理、链表插入删除

  • 牢记前面第 3-6 页的易错点清单——机试最常见的失分点


模拟练习

课堂限时练习 (20 分钟, 必做第 1 题, 选做第 2 或第 3 题):

  1. 输入一行字符串 (≤100 字符, 可含空格), 统计其中大写字母、小写字母、数字、其他字符的个数
  2. 输入 n 个整数存入数组, 用指针实现: 输出最大值及其下标 (重复取第一次)。样例: 输入 5、3 9 1 9 2 → max=9 index=1
  3. 定义结构体 struct Student { char name[20]; int score; };。输入 5 个学生, 按成绩从高到低排序输出 (并列时保持输入顺序)

提示: 每题先想输入 → 处理 → 输出, 再想需要哪些循环/判断/数组


一学期的旅程

从第一个 Hello World 到今天的项目:

第1周  Hello World / 猜数字        →  让程序跑起来
第2周  变量、类型、输入输出        →  数据进得来、出得去
第3周  表达式与运算                →  算得对
第4-5周 判断与循环                 →  程序会"思考"和"重复"
第6-7周 数组、排序与查找           →  处理批量数据
第8-9周 函数与递归                 →  会分解、会复用
第10-11周 指针与内存               →  触及内存
第12周 字符串与函数指针            →  字符串处理进阶
第13周 结构体与链表                →  组织复杂数据
第14周 文件与多文件                →  数据能保存、代码能分工
第15周 项目与总复习                →  把一切拼起来做一个"聪明"的程序

这门课学的不是"背语法", 而是用计算思维解决问题的能力——它会陪你走很远


课程结语

做中学

  • 每一个知识点都走过: 为什么需要 → 是什么 → 怎么用

  • OJ 上的每一道题、项目里的每一行代码, 都是你自己的积累

接着走

  • 想深入 C: 读 K.N. King《C语言程序设计:现代方法》, 或做更复杂的系统编程

  • 想转向应用: Python / C++ / Rust——你在 C 里学的内存、指针、数据结构, 全都用得上

  • 想继续 AI: 你会发现框架的每一层都还能看到这几周写过的影子

感谢一学期的陪伴, 祝大家在后面的学习和项目里一切顺利!



考试周见!


项目答辩 + 闭卷机试

🔒 本课件尚未发布