Skip to content

Commit a149562

Browse files
对C语言系统教程第6~7章添加了参考答案 (#117)
* 对C_tutorials 第六章的状态机示例代码添加了注释 * 对C_tutorials 第六章的状态机示例代码添加了注释(修正版) * docs(vol1): refine state machine comments 追加到 PR #104 的 review 修正,纯注释、零逻辑改动: - payload_len / index: 把「几个负载」改成「几个字节」, 代码实际含义如此,负载更像是完整的Payload,跟代码还是具备实际差距 - kStateHeader: 修正为「帧头已收完,接下来等长度字节」, - 顺手修了结构体注释的对齐(payload[64]) * 对C_tutorials 第二章的练习题添加了参考答案 Added example solutions for exercises on data types and overflow in C. * 对C_tutorials 第三章的练习题添加了参考答案 * fix: lint issue * 对 C 语言系统教程第四章第五章提供了参考答案 * C 语言系统教程第三章练习题答案 bug 修复 搞忘把“### 练习 1 参考答案”打上去了awa 其他.md格式修正是 VS Code 插件自动修改的格式 * Update 02B-float-char-const-cast.md * 对 C 语言系统教程的第六章和第七章添加了参考答案 第六章的第三题难度有点高,这个答案我就不写了,交给你来写。 第二题也交给你了。 awa * fix: submitted answers get possible sigfault and with implicit declarations --------- Co-authored-by: Charliechen114514 <725610365@qq.com>
1 parent 558439d commit a149562

2 files changed

Lines changed: 129 additions & 16 deletions

File tree

documents/vol1-fundamentals/c_tutorials/04-control-flow.md

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
---
22
chapter: 1
33
cpp_standard:
4-
- 11
4+
- 11
55
description: 掌握 C 语言的条件分支、循环、switch 穿透特性与状态机模式,理解 break/continue/goto 的正确用法
66
difficulty: beginner
77
order: 6
88
platform: host
99
prerequisites:
10-
- 位运算与求值顺序
10+
- 位运算与求值顺序
1111
reading_time_minutes: 11
1212
tags:
13-
- host
14-
- cpp-modern
15-
- beginner
16-
- 入门
17-
- 基础
13+
- host
14+
- cpp-modern
15+
- beginner
16+
- 入门
17+
- 基础
1818
title: 控制流:让程序学会选择和重复
1919
---
20+
2021
# 控制流:让程序学会选择和重复
2122

2223
到目前为止我们写的程序都是从第一行一路跑到最后一行。但现实世界的逻辑不是这样的——"如果温度超过阈值就开风扇"、"重复读取传感器数据直到收到停止命令"。控制流语句就是干这个的:让程序根据条件选择不同的执行路径(分支),或者反复执行某段逻辑(循环)。
@@ -36,7 +37,7 @@ title: 控制流:让程序学会选择和重复
3637

3738
我们接下来的所有实验都在这个环境下进行:
3839

39-
- 平台:Linux x86\_64(WSL2 也可以)
40+
- 平台:Linux x86_64(WSL2 也可以)
4041
- 编译器:GCC 13+ 或 Clang 17+
4142
- 编译选项:`-Wall -Wextra -std=c17`
4243

@@ -468,6 +469,27 @@ C++17 引入了 `if constexpr`,它在编译期评估条件,直接把不满
468469

469470
`switch` 实现一个函数,根据月份和是否闰年返回该月的天数。要求利用穿透特性合并同天数的月份。
470471

472+
### 练习 1 参考答案
473+
474+
```c
475+
bool is_leap_year(int year) {
476+
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
477+
}
478+
479+
int month_day(int year, int month) {
480+
switch (month) {
481+
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
482+
return 31;
483+
case 4: case 6: case 9: case 11:
484+
return 30;
485+
case 2:
486+
return is_leap_year(year) ? 29 : 28;
487+
default:
488+
return -1;
489+
}
490+
}
491+
```
492+
471493
### 练习 2:安全的矩阵搜索
472494
473495
在二维矩阵中查找目标值。找到后用两种方式跳出多层循环:一种用标志变量,一种用 `goto`。

documents/vol1-fundamentals/c_tutorials/05-function-basics.md

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
---
22
chapter: 1
33
cpp_standard:
4-
- 11
4+
- 11
55
description: 理解 C 函数的声明定义调用机制、值传递本质、指针参数、返回值策略和递归原理,为 C++ 引用传递和函数重载打好基础
66
difficulty: beginner
77
order: 7
88
platform: host
99
prerequisites:
10-
- 指针与数组、const 和空指针
10+
- 指针与数组、const 和空指针
1111
reading_time_minutes: 10
1212
tags:
13-
- host
14-
- cpp-modern
15-
- beginner
16-
- 入门
17-
- 基础
13+
- host
14+
- cpp-modern
15+
- beginner
16+
- 入门
17+
- 基础
1818
title: 函数基础与参数传递
1919
---
20+
2021
# 函数基础与参数传递
2122

2223
到现在为止我们写的代码都塞在 `main` 函数里。但现实世界的程序不会这样——一个项目动辄几万行代码,如果全挤在一个函数里,那基本没法维护。函数就是 C 语言模块化编程的基本单元:把一段逻辑封装起来,给它起个名字,需要的时候调用就行。
@@ -35,7 +36,7 @@ title: 函数基础与参数传递
3536

3637
我们接下来的所有实验都在这个环境下进行:
3738

38-
- 平台:Linux x86\_64(WSL2 也可以)
39+
- 平台:Linux x86_64(WSL2 也可以)
3940
- 编译器:GCC 13+ 或 Clang 17+
4041
- 编译选项:`-Wall -Wextra -std=c17`
4142

@@ -324,6 +325,40 @@ typedef enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR } LogLevel;
324325
void log_message(LogLevel level, const char* format, ...);
325326
```
326327
328+
### 练习 1 参考答案
329+
330+
```c
331+
void log_message(LogLevel level, const char* format, ...) {
332+
const char* level_str;
333+
switch (level) {
334+
case LOG_DEBUG:
335+
level_str = "DEBUG";
336+
break;
337+
case LOG_INFO:
338+
level_str = "INFO";
339+
break;
340+
case LOG_WARN:
341+
level_str = "WARN";
342+
break;
343+
case LOG_ERROR:
344+
level_str = "ERROR";
345+
break;
346+
default:
347+
level_str = "UNKNOWN";
348+
break;
349+
}
350+
printf("%s\n", level_str);
351+
352+
va_list args;
353+
va_start(args, format);
354+
355+
vprintf(format, args);
356+
printf("\n");
357+
358+
va_end(args);
359+
}
360+
```
361+
327362
### 练习 2:递归与迭代——二分查找
328363

329364
分别用递归和迭代实现二分查找,比较两者的性能和可读性:
@@ -333,6 +368,43 @@ int binary_search_recursive(const int* arr, size_t len, int target);
333368
int binary_search_iterative(const int* arr, size_t len, int target);
334369
```
335370
371+
### 练习 2 参考答案
372+
373+
```c
374+
int binary_search_recursive(const int* arr, size_t len, int target) {
375+
if (len < 1) {
376+
printf("%d is not found in index\n", target);
377+
return -1;
378+
}
379+
size_t mid = (len - 1) / 2;
380+
381+
if (arr[mid] == target) {return mid;}
382+
if (arr[mid] < target) {
383+
int res = binary_search_recursive(arr + mid + 1, len - mid - 1, target);
384+
return (res == -1) ? -1 : (int)(res + mid + 1);
385+
}
386+
if (arr[mid] > target) {return binary_search_recursive(arr, mid , target);}
387+
return -1;
388+
}
389+
390+
int binary_search_iterative(const int* arr, size_t len, int target) {
391+
size_t lo = 0, hi = len; // 搜索区间 [lo, hi),左闭右开
392+
while (lo < hi) {
393+
size_t mid = lo + (hi - lo) / 2;
394+
if (arr[mid] == target) {
395+
return mid;
396+
}
397+
if (arr[mid] < target) {
398+
lo = mid + 1; // 搜右半边,lo 只增不下溢
399+
} else {
400+
hi = mid; // 搜左半边,hi 收敛到 mid,不下溢
401+
}
402+
}
403+
printf("%d is not found in index\n", target);
404+
return -1;
405+
}
406+
```
407+
336408
### 练习 3:多返回值实战
337409

338410
实现一个函数,同时计算数组的最大值和最小值:
@@ -346,6 +418,25 @@ int binary_search_iterative(const int* arr, size_t len, int target);
346418
void find_min_max(const int* data, size_t len, int* min_out, int* max_out);
347419
```
348420
421+
### 练习 3 参考答案
422+
423+
```c
424+
void find_min_max(const int* data, size_t len, int* min_out, int* max_out) {
425+
if (data == NULL || min_out == NULL || max_out == NULL || len < 1) {
426+
return;
427+
}
428+
*min_out = *max_out = data[0];
429+
for (size_t i = 1; i < len; i++) {
430+
if (data[i] < *min_out) {
431+
*min_out = data[i];
432+
}
433+
if (data[i] > *max_out) {
434+
*max_out = data[i];
435+
}
436+
}
437+
}
438+
```
439+
349440
## 参考资源
350441

351442
- [cppreference: 函数声明](https://en.cppreference.com/w/c/language/function_declaration)

0 commit comments

Comments
 (0)