sscanf doesn't parse strings representing non-finite floating point values with MinGW. To reproduce, I'm compiling the follwing example with gcc from the msys shell:
#include <stdio.h> #include <stdlib.h> void main() { const char s[256]; double d; float f; while (1) { d = 0.0; f = 0.0; printf("Enter value: "); scanf("%s",&s[0]); printf("s = %s\n",s); sscanf(s,"%lf",&d); printf("sscanf %%lf says d = %g\n",d); sscanf(s,"%f",&f); printf("sscanf %%f says f = %g\n",f); d = strtod(s,NULL); printf("strtod says d = %g\n",d); f = strtof(s,NULL); printf("strtof says f = %g\n\n",f); } }
compile:
$ gcc scanf.c -o scanf.exe
Run:
$ scanf.exe Enter value: 1.23 s = 1.23 sscanf %lf says d = 1.23 sscanf %f says f = 1.23 strtod says d = 1.23 strtof says f = 1.23 Enter value: 1.233 s = 1.233 sscanf %lf says d = 1.233 sscanf %f says f = 1.233 strtod says d = 1.233 strtof says f = 1.233 Enter value: nan s = nan sscanf %lf says d = 0 sscanf %f says f = 0 strtod says d = 0 strtof says f = -1.#IND Enter value: inf s = inf sscanf %lf says d = 0 sscanf %f says f = 0 strtod says d = 0 strtof says f = 1.#INF Enter value: iNfInIty s = iNfInIty sscanf %lf says d = 0 sscanf %f says f = 0 strtod says d = 0 strtof says f = 1.#INF
GCC 4.9.2 on Debian Jessie returns inf and nan in all cases as expected.
System info
OS: Windows 10
GCC:
$ gcc -v
Using built-in specs.
COLLECT_GCC=C:\MinGW\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/6.3.0/lto-wrapper.exe
Target: mingw32
Configured with: ../src/gcc-6.3.0/configure --build=x86_64-pc-linux-gnu --host=mingw32 --target=mingw32 --with-gmp=/mingw --with-mpfr --with-mpc=/mingw --with-isl=/mingw --prefix=/mingw --disable-win32-registry --with-arch=i586 --with-tune=generic --enable-languages=c,c++,objc,obj-c++,fortran,ada --with-pkgversion='MinGW.org GCC-6.3.0-1' --enable-static --enable-shared --enable-threads --with-dwarf2 --disable-sjlj-exceptions --enable-version-specific-runtime-libs --with-libiconv-prefix=/mingw --with-libintl-prefix=/mingw --enable-libstdcxx-debug --enable-libgomp --disable-libvtv --enable-nls
Thread model: win32
gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
LD:
$ ld -v
GNU ld (GNU Binutils) 2.28
$ uname -a
MINGW32_NT-6.2 AH-RLIVINGS 1.0.19(0.48/3/2) 2016-07-13 17:45 i686 Msys
I've got an errant const in the code here's what it should be and the updated attachment:
Last edit: Ryan Livingston 2017-11-29
I'm sorry, but the only error here is in your expectations. You are using Microsoft's implementation of
scanf()
, (because that is all that MinGW has ever used for this function, and its siblings), so the behaviour is as Microsoft have specified it, (and there appears to be nothing in their documentation to suggest how infinities and nans might be converted, so you cannot expect any particular result). Whatever results you see on Debian Jessie, (or any other Linux distribution, or other non-Windows platform), are completely irrelevant.You may consider Microsoft's implementation to be broken -- and you may well be right -- but good luck with trying to get them to acknowledge that, much less fix it. If you believe you can improve on Microsoft's implementation, (and contribute an enhanced implementation for MinGW), you might consider developing a replacement similar to my
pformat()
implementation for theprintf()
family; in 25 years of C programming, I don't believe I've ever felt the need to usescanf()
, (which I consider to be a poorly designed API), and I may have seen one instance of its use in other projects in which I have participated, so I don't have a great deal of incentive, (much less time), to pursue this myself.Last edit: Keith Marshall 2017-11-30
Thank you for the info Keith and apologies for the noise. I was unaware MinGW was using MSVCRT.dll. Instead, I assumed since the code worked with MSVC that it would work with the runtime used with MinGW. MSVCRT is not C99 compatible and the C89 standard for strtod makes no mention of non-finites. So there's no issue to purue with Microsoft as far as I see.
For completeness, it is probably worth mentioning that, if you define
_ISOC99_SOURCE
, or_XOPEN_SOURCE >= 600
, or_POSIX_C_SOURCE >= 200112L
, as in this example:then the MinGW replacements for
strtod()
, and forprintf()
are selected, in preference to the MSVCRT.dll versions, and these should DTRT. This will not help forscanf()
and siblings, though, because there are no MinGW replacements for these.BTW, the
1.INF
and-1.IND
results, seen in your example output forstrtof()
, are the consequence of mixing correctly interpretedINF
andNaN
with MSVCRT.dll'sprintf()
. Historically, MSVCRT.dll did not provide eitherstrtof()
orstrtold()
, so we always used our own implementations, and1.INF
and-1.IND
are MSVCRT.dllprintf()
's representations forinf
andnan
respectively.Thanks for the extra info, Keith. We may be able to switch to strtod and use the replacements as a workaround in our project.