cJSON接口测试与解析

本文详细介绍了CJSON库中的关键函数,如parse_number用于解析数字、pow2gt计算大于给定数的最小2的幂次方,以及print_number和parse_hex4处理数值和十六进制转换。通过实例展示了这些函数的实际应用和处理精度问题的方法。
摘要由CSDN通过智能技术生成

接口:static const char *parse_number(cJSON *item,const char *num)

/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;

	if (*num=='-') sign=-1,num++;	/* Has sign? */
	if (*num=='0') num++;			/* is zero */
	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}	/* Fractional part? */
	if (*num=='e' || *num=='E')		/* Exponent? */
	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
	}

	//<math.h>;double pow(double x,double y);返回x的y次方的值
	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
	
	item->valuedouble=n;
	item->valueint=(int)n;
	item->type=cJSON_Number;
	return num;
}

int main(){
	const char *num = "31.4e-2";
	char * jsonStr =NULL;
	cJSON * pTest = cJSON_CreateObject();
	parse_number(pTest,num);
	jsonStr = cJSON_Print(pTest);
    cJSON_Delete(pTest);
	printf("jsonStr: %s\n",jsonStr);
	free(jsonStr);//千万注意释放
	return 0;
}
输出:jsonStr: 0.314000

接口:static int pow2gt (int x)

//返回比x大的最小的2的N次方数,运行后相当于二进制从最左边第一个非零的数开始,往右都为1,然后再加上1
static int pow2gt (int x)	{	--x;	x|=x>>1;	x|=x>>2;	x|=x>>4;	x|=x>>8;	x|=x>>16;	return x+1;	}
int main(){
	printf("Test CJson: %d\n",pow2gt(-10));
	return 0;
}
输出:0

printbuffer和ensure,从Cjson代码看printbuffer一直赋的NULL,也就是未实际使用

typedef struct {char *buffer; int length; int offset; } printbuffer;

static char* ensure(printbuffer *p,int needed)
{
	char *newbuffer;int newsize;
	if (!p || !p->buffer) return 0;  // 判断p是否存在
	needed+=p->offset;  // 所需空间 = 输入大小+偏移量(已使用)
	if (needed<=p->length) return p->buffer+p->offset;  // 所需小于容量,p中空间充足
    
    // 所需大于容量时,重新分配空间:
	newsize=pow2gt(needed);
	newbuffer=(char*)cJSON_malloc(newsize);  // 创建一个新buffer
	if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}  // 创建失败
	if (newbuffer) memcpy(newbuffer,p->buffer,p->length);  // 创建成功
	cJSON_free(p->buffer);  // 释放老buffer并将其新的作为当前可用buffer p
	p->length=newsize;
	p->buffer=newbuffer;
	return newbuffer+p->offset;
}
//使item中的数值巧妙的转换为字符串
static char *print_number(cJSON *item,printbuffer *p)
{
	char *str=0;
	double d=item->valuedouble;
	if (d==0) //对应数值为0
	{
		if (p)	str=ensure(p,2);
		else	str=(char*)cJSON_malloc(2);	/* special case for 0. */
		if (str) strcpy(str,"0");//将0赋值给字符串str
	}
	//DBL_EPSILON:            2.220446049250313080847e-16
	//#define INT_MAX 2147483647    #define INT_MIN (-INT_MAX - 1)
	//这里没有简单地将INT_MIN赋值成-2147483647,是因为-2147483648对于编译器而言是个表达式,而2147483648对于32-bit整数是无法表示的,
	//所以经过这个表达式的结果是未定义的。在GCC上直接写-2147483648后,编译器给出了警告,说结果是unsigned。
	// 若int型数据和double型数据差别足够小且数据大小在INT_MAX INT_MIN之间
	else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)//C 库函数 double fabs(double x) 返回 x 的绝对值
	{
		if (p)	str=ensure(p,21);
		else	str=(char*)cJSON_malloc(21);	/* 2^64[18,446,744,073,709,551,616] +1[结束符] can be represented in 21 chars. */
		if (str)	sprintf(str,"%d",item->valueint);
	}
	//对编程人员来说,double 和 float 的区别是 double 精度高,算上符号位有效数字 16 位[指的小数点后10进制数的个数],float 精度 7 位。
	//但 double 消耗内存是 float 的两倍,double 的运算速度比 float 慢得多,C 语言中数学函数名称 double 和 float 不同,不要写错,
	//能用单精度时不要用双精度(以省内存,加快运算速度)
	//float 是 32位, 其中有23位用于存放尾数, 带有一个固定隐含符号位.. 所以float的有24个二进制有效位位数,
	//2^24共有8个十进制位. 所以有些编译器 float的有效数字位是 8位 , 有些有效数字位是 7位.(注意不是小数的位数, 是有效数字位)
	//double也一样,是64位, 其中有52位用于存放尾数, 一个固定隐含位. 共有 53个二进制有效位位数.
	//2^53次方有15个十进制位, 所以有些编译器double的有效数字位是15位, 有些是16位
	else
	{
		if (p)	str=ensure(p,64);
		else	str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
		if (str)
		{
			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)			sprintf(str,"%e",d);
			else												sprintf(str,"%f",d);
		}
	}
	return str;
}

int main(){

	cJSON * testCJson = cJSON_CreateNumber(12.257902012398878);
	printf("testCJson: %s \n",print_number(testCJson,0));
	float a=12.257902612398877;
    double b=12.257902612398877;
	printf("float a= %f\n",a);
	printf("double b= %lf\n",b);
	return 0;
}
输出结果:
testCJson: 12.257902
float a= 12.257902
double b= 12.257903

parse_hex4:将4个字符的字符串转变为两个字节的数字:

static unsigned parse_hex4(const char *str)
{
	unsigned h=0;
	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
	h=h<<4;str++;
	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
	h=h<<4;str++;
	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
	h=h<<4;str++;
	if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
	return h;
}
int main(){
    char* a="abcd";
	printf("parse_hex4 = %x\n",parse_hex4(a));
	return 0;
}
输出:float = abcd
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值