On 2021-04-18 22:09, Keith Thompson via Cygwin wrote:
The *scanf() functions don't handle hexadecimal floating-point input
(for example "0x1p+0" representing 1.0).
A test program:
#include <stdio.h>
int main(void) {
int ok = 1;
float x = -1.0;
int result = sscanf("0x1p+0", "%f", &x);
const float expected_x = 1.0;
const int expected_result = 1;
printf("sscanf returned %d", result);
if (result != expected_result) {
ok = 0;
printf(" (expected %d)", expected_result);
}
printf(", x = %g", x);
if (x != expected_x) {
ok = 0;
printf(" (expected %g)", expected_x);
}
puts(ok ? ", PASSED" : ", FAILED");
}
On Cygwin, the output (compiled with gcc or clang) is:
sscanf returned 1, x = 0 (expected 1), FAILED
On Ubuntu, the output is:
sscanf returned 1, x = 1, PASSED
Looking through the newlib sources (git://sourceware.org/git/newlib-cygwin.git),
this might be related to the _WANT_IO_C99_FORMATS macro, but I haven't
looked into
the details.
The test case passes on Cygwin when compiled with i686-w64-mingw32-gcc
or x86_64-w64-mingw32-gcc.
This seems like an oversight as gdtoa-gethex.c was added about 2006 and scanf
and strtod support it.
See augmented STC with strtod added attached:
$ gcc -o hexfloat-scanf-test{,.c}
$ ./hexfloat-scanf-test
sscanf returned 2, unscanned 'x1p+0', x = 0 (expected 1), FAILED
strtod unscanned '', x = 1, PASSED
--
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
This email may be disturbing to some readers as it contains
too much technical detail. Reader discretion is advised.
[Data in binary units and prefixes, physical quantities in SI.]
/* hexfloat-scanf-test.c - test 0x#[Pp]# sscanf and strtod support */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const double expected_x = 0x1p+0;
double x = -0x1p+0;
const int expected_result = 2;
int result = 0;
int ok = 1;
const char * test = "0x1p+0";
char * endp = NULL;
char buff[BUFSIZ] = { 0 };
/* test sscanf() */
result = sscanf(test, "%la %s", &x, buff);
printf("sscanf returned %d", result);
if (result != expected_result) {
ok = 0;
printf(" (expected %d)", expected_result);
}
printf(", unscanned '%s', x = %g", buff, x);
if (x != expected_x) {
ok = 0;
printf(" (expected %g)", expected_x);
}
printf("%s\n", ok ? ", PASSED" : ", FAILED");
/* test strtod() */
x = strtod(test, &endp);
printf("strtod unscanned '%s'", endp);
if (!(ok = (NULL != endp && !*endp))) {
printf(" (expected '')");
}
printf(", x = %g", x);
if (x != expected_x) {
ok = 0;
printf(" (expected %g)", expected_x);
}
printf("%s\n", ok ? ", PASSED" : ", FAILED");
}
--
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple