来自

从零开始的 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. JavaScript Drag处理

    [JavaScript Drag处理] 在拖动目标上触发事件 (源元素): ondragstart - 用户开始拖动元素时触发 ondrag - 元素正在拖动时触发 ondragend - 用户完成元 ...

  2. Dubbo启动过程(Spring方式)详解

    一.使用Spring xml配置方式的启动过程 1. 解析XML,注册Bean 2. 监听Spring事件 3. 启动或关闭dubbo 二.详细过程 1. 解析XML,注册Bean 利用Spring提 ...

  3. 设置,获取,删除cookie

    function setCookie(key,value,options){ if (value !== undefined ) { if(options === undefined || optio ...

  4. msf客户端渗透(三):提权、图形化payload

    对普通权限session提权 生成一个木马 开启Apache服务 将木马上传网页 被攻击者从这个网页上获取到这个木马 攻击者开启msf侦听 当被攻击者双击这个木马文件时 攻击者就获取到一个sessio ...

  5. 解题(LevenshteinInstance--Levenshtein距离)

    题目描述 Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符.编辑距离 ...

  6. sql 允许远程登录

    grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option; flush privileges ...

  7. html自定义弹框

    一.要实现的功能 1.弹框弹出时有遮罩 2.弹框内的文字过多时右侧有滚动条 3.根据执行结果变更弹框title的样式   二.具体实现 思路:定义一个有宽高的div,默认隐藏,当要显示时,设置为dis ...

  8. python中的命名元组namedtuple

    namedtuple是继承自tuple的子类.namedtuple创建一个和tuple类似的对象,而且对象拥有可访问的属性 可利用collections.namedtuple构建一个简单的类. fro ...

  9. ImportError: libcublas.so.9.0: cannot open shared object file: No such file or directory

    这是因为我装了tensorflow-gpu 1.5版本,而我用的是cuda 8.0和cudnn6.0,1.5版本要求cuda 9.0,我的做法就是回滚tensorflow版本.

  10. jsp选项过长自动换行

    自动换行前是这样的 从源码发现“打发的所发生的7”所在span跨行了,宽度为整行的宽度,不再是自身的实际宽度(一列时所占的宽度) 我的思路是要把这个换行元素前加上<br/>,使得该元素换行 ...