json-tutorial icon indicating copy to clipboard operation
json-tutorial copied to clipboard

T02,分享一下我的验证思路

Open chux0519 opened this issue 9 years ago • 2 comments

做完第二部分练习时,对了一下参考答案,发现我的某部分实现可能会稍微短一些,和大家分享一下

  • 1.首先考虑第一个字符如果既不满足'0'~'9',又不是'-'号,那么就说明这是一个无效的数字。
  • 2.再考虑第一个字符是'0',但第二个字符既不是'.'也不是0(代表结束),同样也说明这是一个无效的数。
  • 3.然后,我们还需要解决末尾是'.'的情况,这时候,可以根据end指针的前一个位置的字符来判断,假设end[-1]是'.',说明这是小数点在末尾的情况,该数无效。(ps:这里不知道会不会出现_越界_的情况)
  • 4.最后就是数据过大或者数据过小的考虑了。参考叶老师给的strtod参考,使用errno的值来判断是否出现数据过大或者过小的情况,同时,数据过小时会取0,这是合法的,所以当发现errno值为ERANGE的时候,同时再判断数字的值是否是零,即可区分过大和过小。
static int lept_parse_number(lept_context* c, lept_value* v) {
    char* end;
    /* validate number */
    if( !ISDIGIT(c->json[0]) && c->json[0]!='-' ) return LEPT_PARSE_INVALID_VALUE;/* 1 */
    if( c->json[0]=='0' && c->json[1]!='.' && c->json[1]!=0 ) return LEPT_PARSE_ROOT_NOT_SINGULAR; /* 2 */
    v->n = strtod(c->json, &end);
    if (c->json == NULL || end[-1] == '.') /* end为小数点后的地址 */ /* 3 */
        return LEPT_PARSE_INVALID_VALUE;
    c->json = end; 
    if( errno == ERANGE && v->n != 0 ){ /* 4 */
        errno = 0;
        return LEPT_PARSE_NUMBER_TOO_BIG;
    }
    v->type = LEPT_NUMBER;
    return LEPT_PARSE_OK;
}

chux0519 avatar Oct 14 '16 12:10 chux0519

strtod 还支持 16 进位、NAN、INFINITY 等众多输入,我认为不能依赖 strtod 做合法性检测。

miloyip avatar Oct 14 '16 14:10 miloyip

十六进制数、nan、以及inf在test.c中是有测试用例的,实际上也是可以通过的。只是我也隐隐觉得我那样写可能会出岔子

chux0519 avatar Oct 14 '16 15:10 chux0519