Skip to content

Commit

Permalink
Update tutorial01.md: Add serial number for headers
Browse files Browse the repository at this point in the history
  • Loading branch information
imba-tjd committed Sep 3, 2018
1 parent bb44841 commit bb48a21
Showing 1 changed file with 10 additions and 10 deletions.
20 changes: 10 additions & 10 deletions tutorial01/tutorial01.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
9. [总结与练习](#总结与练习)
10. [常见问答](#常见问答)

## JSON 是什么
## 1. JSON 是什么

JSON(JavaScript Object Notation)是一个用于数据交换的文本格式,现时的标准为[ECMA-404](https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)

Expand Down Expand Up @@ -68,7 +68,7 @@ JSON(JavaScript Object Notation)是一个用于数据交换的文本格式

我们会逐步实现这些需求。在本单元中,我们只实现最简单的 null 和 boolean 解析。

## 搭建编译环境
## 2. 搭建编译环境

我们要做的库是跨平台、跨编译器的,同学可使用任意平台进行练习。

Expand Down Expand Up @@ -126,7 +126,7 @@ $ ./leptjson_test

若看到类似以上的结果,说明已成功搭建编译环境,我们可以去看看那几个代码文件的内容了。

## 头文件与 API 设计
## 3. 头文件与 API 设计

C 语言有头文件的概念,需要使用 `#include`去引入头文件中的类型声明和函数声明。但由于头文件也可以 `#include` 其他头文件,为避免重复声明,通常会利用宏加入 include 防范(include guard):

Expand Down Expand Up @@ -193,7 +193,7 @@ enum {
lept_type lept_get_type(const lept_value* v);
~~~
## JSON 语法子集
## 4. JSON 语法子集
下面是此单元的 JSON 语法子集,使用 [RFC7159](http://rfc7159.net/rfc7159) 中的 [ABNF](https://tools.ietf.org/html/rfc5234) 表示:
Expand Down Expand Up @@ -222,7 +222,7 @@ true = "true"
* 若一个值之后,在空白之后还有其他字符,传回 `LEPT_PARSE_ROOT_NOT_SINGULAR`。
* 若值不是那三种字面值,传回 `LEPT_PARSE_INVALID_VALUE`。
## 单元测试
## 5. 单元测试
许多同学在做练习题时,都是以 `printf`/`cout` 打印结果,再用肉眼对比结果是否乎合预期。但当软件项目越来越复杂,这个做法会越来越低效。一般我们会采用自动的测试方式,例如单元测试(unit testing)。单元测试也能确保其他人修改代码后,原来的功能维持正确(这称为回归测试/regression testing)。
Expand Down Expand Up @@ -299,7 +299,7 @@ int main() {

然而,完全按照 TDD 的步骤来开发,是会减慢开发进程。所以我个人会在这两种极端的工作方式取平衡。通常会在设计 API 后,先写部分测试代码,再写满足那些测试的实现。

## 宏的编写技巧
## 6. 宏的编写技巧

有些同学可能不了解 `EXPECT_EQ_BASE` 宏的编写技巧,简单说明一下。反斜线代表该行未结束,会串接下一行。而如果宏里有多过一个语句(statement),就需要用 `do { /*...*/ } while(0)` 包裹成单个语句,否则会有如下的问题:

Expand Down Expand Up @@ -344,7 +344,7 @@ else
c();
~~~

## 实现解析器
## 7. 实现解析器

有了 API 的设计、单元测试,终于要实现解析器了。

Expand Down Expand Up @@ -419,7 +419,7 @@ static int lept_parse_value(lept_context* c, lept_value* v) {

由于 `lept_parse_whitespace()` 是不会出现错误的,返回类型为 `void`。其它的解析函数会返回错误码,传递至顶层。

## 关于断言
## 8. 关于断言

断言(assertion)是 C 语言中常用的防御式编程方式,减少编程错误。最常用的是在函数开始的地方,检测所有参数。有时候也可以在调用函数后,检查上下文是否正确。

Expand All @@ -437,15 +437,15 @@ assert(x++ == 0); /* 这是错误的! */
另一个问题是,初学者可能会难于分辨何时使用断言,何时处理运行时错误(如返回错误值或在 C++ 中抛出异常)。简单的答案是,如果那个错误是由于程序员错误编码所造成的(例如传入不合法的参数),那么应用断言;如果那个错误是程序员无法避免,而是由运行时的环境所造成的,就要处理运行时错误(例如开启文件失败)。
## 总结与练习
## 9. 总结与练习
本文介绍了如何配置一个编程环境,单元测试的重要性,以至于一个 JSON 解析器的子集实现。如果你读到这里,还未动手,建议你快点试一下。以下是本单元的练习,很容易的,但我也会在稍后发出解答篇。
1. 修正关于 `LEPT_PARSE_ROOT_NOT_SINGULAR` 的单元测试,若 json 在一个值之后,空白之后还有其它字符,则要返回 `LEPT_PARSE_ROOT_NOT_SINGULAR`。
2. 参考 `test_parse_null()`,加入 `test_parse_true()`、`test_parse_false()` 单元测试。
3. 参考 `lept_parse_null()` 的实现和调用方,解析 true 和 false 值。
## 常见问答
## 10. 常见问答
1. 为什么把例子命名为 leptjson?
Expand Down

0 comments on commit bb48a21

Please sign in to comment.