0x02-C语言实现通讯录
0x02-C语言实现通讯录
两个思考题
如何分离业务数据 name/phone 和数据结构层的 next/prev?
解决方案: 分层设计

如何修复 scanf 缓冲区溢出漏洞?
限制读入字符数, 超出部分污染下一次读入

使用安全的fgets
fgets(buffer, sizeof(buffer), stdin);
缺点: 需要额外处理 buffer 中被读入的换行符
<font style="color:#DF2A3F;">scanf()</font>会默认跳过换行符<font style="color:#DF2A3F;">\n</font>, 空格<font style="color:#DF2A3F;">space</font>等等, 使他们被留在缓冲区
两种 <font style="color:#DF2A3F;">fgets()</font>出现意外的场景
| 场景 | 原因 | 解决方案 |
|---|---|---|
scanf后接 fgets | scanf不读取换行符,残留的 \n会被fgets立即读取 | while(getchar() != '\n'); |
| 输入超出预期长度 | fgets / scanf只读取部分输入剩余内容会污染下次读取 | 检查输入是否完整,若不完整则清空 |
记录
C 语法不熟悉

有几次 malloc/new , 就要 free/delete 几次
函数的实现, 坚持判断每一个参数是否无意义(如指针是否为空)
所有”意义不明的常数”, 使用宏定义声明
内存初始化

清空缓冲区
while(getchar() != '\n'); // 可以直接清空缓冲区
重写接口层 ps_insert 实现按名字的字典序升序排列
int personCmp(Person* a, Person* b) {
return strcmp(a->name, b->name);
} // 辅助函数, 下面会用到
int ps_insert(Node* ps, AddrBook* contacts) {
if (ps == NULL) return -1;
if (contacts == NULL) return -2;
Node* prev = NULL;
Node* next = NULL;
Person* new_person = (Person*)ps->data;
for (Node* current = contacts->head; current != NULL; current = current->next) {
Person* current_person = (Person*)current->data;
prev = current;
if (personCmp(new_person, current_person) < 0) {
next = current;
prev = current->prev;
break;
}
}
ps->next = next;
ps->prev = prev;
if (prev != NULL) prev->next = ps;
if (next != NULL) next->prev = ps;
if (next == contacts->head) contacts->head = ps;
contacts->len++;
return 0;
}
问题
- 好像不需要二级指针? ==> 已解决: 要修改的是指针, 我传的就是指针的指针了, 而视频里也需要传
main函数最后的default:有没有把内存free干净? // 没有, 但我已经优化了