来自

从零开始的 JSON 库教程
从零开始教授如何写一个符合标准的 C 语言 JSON 库
作者 Milo Yip

https://zhuanlan.zhihu.com/json-tutorial

根据第一课教程 自己重新编写 做了一点修改 加深学习印象

//JsonParse.h
#pragma once
#include "JsonStruct.h"
#include <assert.h> void DEFParseWhitespace(MyJsonStruct& js)
{
while (js.jsonStr[js.index] == ' ' ||
js.jsonStr[js.index] == '\r' ||
js.jsonStr[js.index] == '\n') {
js.index++;
}
} DefParseResult DEFParseNull(MyJsonStruct& js)
{
assert(js.jsonStr[js.index] = 'n');
if (js.jsonStr[js.index + 1] != 'u' ||
js.jsonStr[js.index+2] != 'l' ||
js.jsonStr[js.index+3] != 'l') {
return DEF_PARSE_INVALID_VALUE;
}
js.index += 4;
js.type = DEF_NULL;
return DEF_PARSE_OK;
} DefParseResult DEFParseValue(MyJsonStruct& js)
{
switch (js.jsonStr[js.index]){
case 'n':return DEFParseNull(js);
case '\0':return DEF_PARSE_EXPECT_VALUE;
default:return DEF_PARSE_INVALID_VALUE;
}
} DefParseType GetParseType(MyJsonStruct& js)
{
return js.type;
} void ResetJsonStruct(const char* jsonBuf, MyJsonStruct& js)
{
js.jsonStr = jsonBuf;
js.index = 0;
js.type = DEF_NONE;
} MyJsonStruct InitJsonStruct(char* jsonBuf)
{
MyJsonStruct jsonStruct;
ResetJsonStruct(jsonBuf, jsonStruct);
return jsonStruct;
} DefParseResult DEFParse(MyJsonStruct& jsonStruct)
{
DefParseResult ret; DEFParseWhitespace(jsonStruct); if ((ret = DEFParseValue(jsonStruct)) == DEF_PARSE_OK) {
DEFParseWhitespace(jsonStruct);
if (jsonStruct.index < jsonStruct.jsonStr.size()) {
ret = DEF_PARSE_ROOT_NOT_SINGULAR;
jsonStruct.type = DEF_NONE;
} }
return ret;
}

  

//JsonStruct.h
#pragma once
#include <string> enum DefParseType {
DEF_NONE,
DEF_NULL,
DEF_FALSE,
DEF_TRUE,
DEF_NUMBER,
DEF_STRING,
DEF_ARRAY,
DEF_OBJECT
}; struct MyJsonStruct {
std::string jsonStr;
size_t index;
DefParseType type;
}; enum DefParseResult{
DEF_PARSE_OK = 0,
DEF_PARSE_EXPECT_VALUE,
DEF_PARSE_INVALID_VALUE,
DEF_PARSE_ROOT_NOT_SINGULAR
};

  

//MyTestUnit.h
#pragma once
#include <iostream> class MyTestClass {
static size_t testCount_;
static size_t testPass_;
public:
template<typename E,typename A>
bool ExceptEqual(E e, A a)
{
testCount_++;
if (e == a){
testPass_++;
return true;
}
return false;
} void PrintResult(){
std::cout << testPass_ << "/" << testCount_ << "\t" << "("<<(testPass_ * 100.0 / testCount_) << "%)" << " passed." << std::endl;
}
};
size_t MyTestClass::testCount_ = 0;
size_t MyTestClass::testPass_ = 0; #define ERROR_PRINT(expect,actual) \
std::cerr << __FILE__ <<":"<< __LINE__ << "\r\nexpect: " << expect << " actual: " << actual << std::endl; #define EXCEPT_EQ(expect, actual) \
do{ \
MyTestClass TEST; \
if(!TEST.ExceptEqual(expect, actual)){ \
ERROR_PRINT(expect,actual) \
} \
}while(0) #define PRINT_TEST_RESULT() \
do{ \
MyTestClass TEST; \
TEST.PrintResult(); \
}while(0)

  

// MyJson.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include "JsonParse.h"
#include <iostream>
#include "MyTestUnit.h" int main()
{
MyJsonStruct js =InitJsonStruct("null");
EXCEPT_EQ(DEF_PARSE_OK, DEFParse(js));
EXCEPT_EQ(DEF_NULL, GetParseType(js)); ResetJsonStruct("", js);
EXCEPT_EQ(DEF_PARSE_EXPECT_VALUE, DEFParse(js));
EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct(" ", js);
EXCEPT_EQ(DEF_PARSE_EXPECT_VALUE, DEFParse(js));
EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("nul", js);
EXCEPT_EQ(DEF_PARSE_INVALID_VALUE, DEFParse(js));
EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("?", js);
EXCEPT_EQ(DEF_PARSE_INVALID_VALUE, DEFParse(js));
EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("null x", js);
EXCEPT_EQ(DEF_PARSE_ROOT_NOT_SINGULAR, DEFParse(js));
EXCEPT_EQ(DEF_NONE, GetParseType(js)); PRINT_TEST_RESULT();
return 0;
}

  测试效果

12/12 (100%) passed.
请按任意键继续. . .

状态机学习(三)解析JSON1的更多相关文章

  1. Java开发学习(三十六)----SpringBoot三种配置文件解析

    一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...

  2. HTTP学习三:HTTPS

    HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...

  3. DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  4. 深入学习Python解析并解密PDF文件内容的方法

    前面学习了解析PDF文档,并写入文档的知识,那篇文章的名字为深入学习Python解析并读取PDF文件内容的方法. 链接如下:https://www.cnblogs.com/wj-1314/p/9429 ...

  5. day91 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  6. docker深入学习三

    docker学习三:network docker支持容器之间的网络通信,docker的网络通信方式有以下五种: bridge docker 默认的网络驱动,如果不指定网络驱动,docker就会创建一个 ...

  7. day 89 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  8. day 82 Vue学习三之vue组件

      Vue学习三之vue组件   本节目录 一 什么是组件 二 v-model双向数据绑定 三 组件基础 四 父子组件传值 五 平行组件传值 六 xxx 七 xxx 八 xxx 一 什么是组件 首先给 ...

  9. ElasticSearch7.3学习(三十二)----logstash三大插件(input、filter、output)及其综合示例

    1. Logstash输入插件 1.1 input介绍 logstash支持很多数据源,比如说file,http,jdbc,s3等等 图片上面只是一少部分.详情见网址:https://www.elas ...

  10. Java开发学习(三十七)----SpringBoot多环境配置及配置文件分类

    一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配 ...

随机推荐

  1. 修复回写PR时到料日期重复扣减检验周期的问题:

    问题描述: 修复回写PR时到料日期重复扣减检验周期的问题:系统回写的外购半成品PR交货日期未按采购周期回写,从8-10日开始均于10天交期回写,例以下9-5日今天回写的PR,采购周期12天,结果回写到 ...

  2. DRF的权限和频率

    DRF的权限 权限组件源码 权限和频率以及版本认证都是在initial方法里初始化的 我们的权限类一定要有has_permission方法~否则就会抛出异常~~这也是框架给我提供的钩子~~ 在rest ...

  3. ES3之closure ( 闭包 )

    词法作用域中使用的域,是变量在代码中声明的位置所决定的.嵌套的函数可以访问在其外部声明的变量. 闭包是函数和声明该函数的词法环境的组合. 1 创建单个闭包 JavaScript中的函数会形成闭包. 闭 ...

  4. 最小生成树kruskal模板

    算法思路:每次选取权值最小的边,判断这两个点是否在同一个集合内,如果在则跳过,如果不在则加上这条边的权值 可以使用并查集储存结点,可以快速判断结点是否在同一集合内. #include<iostr ...

  5. C++ 求最长递增子序列(动态规划)

    i 0 1 2 3 4 5 6 7 8 a[i] 1 4 7 2 5 8 3 6 9 lis[i] 1 2 3 2 3 4 3 4 5 时间复杂度为n^2的算法: //求最长递增子序列 //2019/ ...

  6. JDBC的学习

    JDBC —— 用Java访问数据库 一.需要用到第三方类:mysql-connector-java-5.0.8-bin.jar,并做好导包处理: 二.初始化驱动: 三.建立与数据库的链接: 四.创建 ...

  7. webstorm 打包angular Module build failed: Error: No PostCSS Config found

    angular创建项目后,在webstorm中启动时,报出如题错误,奇怪的是我从命令行启动(ng server)是没有问题的,多方寻求无果,在网上看到过说要加一个配置文件,我不信.我觉得是我配置哪里有 ...

  8. DevExpress之TreeList节点绑定图片

    最近在项目中使用到了DX中的TreeList控件绑定数据源时在每个节点前显示特点的图片:查阅相关资料实现方法如下:1.首先打开VS2010新建一个WINFROM应用程序: 2.在WINFROM应用程序 ...

  9. 12.Mysql存储过程和函数

    12.存储过程和函数12.1 什么是存储过程和函数存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输, ...

  10. css代码插入三种方式

    1.内联式 <p style="color:red;font-size: 12px">iutt</p> 2.嵌入式 <style type=" ...