Open Geartz opened 3 years ago
I fixed that issue by checking if the value is an integer or a float in the function.
Has anyone encountered the same problem?
I also encountered this problem, how did you solve it?
Hi, I just added a simple check in "print_number" function.
I replace this code (line 565)
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d);
}
by this one
if(item->valuedouble == item->valueint)
{
length = sprintf((char*)number_buffer, "%d", item->valueint);
}
else
{
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d);
}
}
Please tell me if it works for you.
Hi, I just added a simple check in "print_number" function.
I replace this code (line 565)
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ length = sprintf((char*)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ length = sprintf((char*)number_buffer, "%1.17g", d); }
by this one
if(item->valuedouble == item->valueint) { length = sprintf((char*)number_buffer, "%d", item->valueint); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ length = sprintf((char*)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ length = sprintf((char*)number_buffer, "%1.17g", d); } }
Please tell me if it works for you.
It works for me , thanks so much.
Is this embedded? If using newlib, did you add -u _printf_float and potentially -u _scanf_float to your linker command line?
Some embedded c library implementations require you to specifically enable printf for floating numbers.
Same weird issue has happened to me with ESP8266 RTOS SDK version 3.4. While above workaround works, it's not needed to change cjSON code. It's enough to turn off "Enable 'nano' formatting options for printf/scanf family" option for Newlib in Menuconfig.
It would be great if the fix from @Geartz could be implemented directly into cJSON. I use cJSON on embedded software where adding support for printing float is not feasible. Also the potential overhead by implementing this fix is minimal.
Hi,
I also had the issue with ESP8266 RTOS SDK version 3.4, but instead of disabling completely the "'nano' formatting options for printf/scanf family" (namely the NEWLIB_NANO_FORMAT
configuration option) as suggested by @vitomirs, I simply added the -u_printf_float
and -u_scanf_float
to the linker options in esp-idf/components/newlib/component.mk
(as suggested by @nik-markovic)
So COMPONENT_ADD_LDFLAGS
was changed from:
COMPONENT_ADD_LDFLAGS := -lnewlib -l$(LIBC) -lm -u __errno
COMPONENT_ADD_LDFLAGS := -u_printf_float -u_scanf_float -lnewlib -l$(LIBC) -lm -u __errno
And this solved the problem, without the need for the extra check added by the merged commit (#630), which might also by wrong as pointed out in #694
I encounter an issue when I try to print JSON string with the cJSON_PrintUnformatted function.
In the sub function print_number(), i saw that "number_buffer" was filled with 5.30498947741318e-315 when item->valuedouble = 1 Is that normal ? Because it make the program crash during the following sscanf.
I used cJSON_AddNumberToObject to add number to my cJSON object.