Unterschied zwischen scanf () und strtol () / strtod () beim Parsen von Zahlen

Hinweis: Ich habe die Frage komplett überarbeitet, um besser zu reflektieren, wofür ich das Kopfgeld setze. Bitte entschuldigen Sie etwaige Inkonsistenzen mit bereits gegebenen Antworten, die dies möglicherweise verursacht hat. Ich wollte keine neue Frage erstellen, da frühere Antworten auf diese Frage hilfreich sein könnten.

Ich arbeite an der Implementierung einer C-Standardbibliothek und bin über eine bestimmte Ecke des Standards verwirrt.

Der Standard definiert die von der akzeptierten Zahlenformatescanf Funktionsfamilie (% d,% i,% u,% o,% x) im Sinne der Definitionen fürstrtol, strtoul, undstrtod.

Der Standard sagt das auchfscanf() wird nur maximal ein Zeichen in den Eingabestream zurückgeben, und das deshalb von einigen Sequenzen akzeptiertstrtol, strtoul undstrtod sind inakzeptabelfscanf (ISO / IEC 9899: 1999, Fußnote 251).

Ich habe versucht, einige Werte zu finden, die solche Unterschiede aufweisen. Es stellt sich heraus, dass das hexadezimale Präfix "0x", gefolgt von einem Zeichen, das keine hexadezimale Ziffer ist, ein solcher Fall ist, in dem sich die beiden Funktionsfamilien unterscheiden.

Komischerweise stellte sich heraus, dass sich keine zwei verfügbaren C-Bibliotheken über die Ausgabe einig zu sein scheinen. (Siehe Testprogramm und Beispielausgabe am Ende dieser Frage.)

Was ich gerne hören würde, istWas würde als standardkonformes Verhalten beim Parsen von "0xz" angesehen werden?. Idealerweise die relevanten Teile aus der Norm zitieren, um den Punkt zu verdeutlichen.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()
{
    int i, count, rc;
    unsigned u;
    char * endptr = NULL;
    char culprit[] = "0xz";

    /* File I/O to assert fscanf == sscanf */
    FILE * fh = fopen( "testfile", "w+" );
    fprintf( fh, "%s", culprit );
    rewind( fh );

    /* fscanf base 16 */
    u = -1; count = -1;
    rc = fscanf( fh, "%x%n", &u, &count );
    printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, u, count );
    rewind( fh );

    /* strtoul base 16 */
    u = strtoul( culprit, &endptr, 16 );
    printf( "strtoul:             result %2d, consumed %d\n", u, endptr - culprit );

    puts( "" );

    /* fscanf base 0 */
    i = -1; count = -1;
    rc = fscanf( fh, "%i%n", &i, &count );
    printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, i, count );
    rewind( fh );

    /* strtol base 0 */
    i = strtol( culprit, &endptr, 0 );
    printf( "strtoul:             result %2d, consumed %d\n", i, endptr - culprit );

    fclose( fh );
    return 0;
}

/* newlib 1.14

fscanf:  Returned 1, result  0, consumed 1
strtoul:             result  0, consumed 0

fscanf:  Returned 1, result  0, consumed 1
strtoul:             result  0, consumed 0
*/

/* glibc-2.8

fscanf:  Returned 1, result  0, consumed 2
strtoul:             result  0, consumed 1

fscanf:  Returned 1, result  0, consumed 2
strtoul:             result  0, consumed 1
*/

/* Microsoft MSVC

fscanf:  Returned 0, result -1, consumed -1
strtoul:             result  0, consumed 0

fscanf:  Returned 0, result  0, consumed -1
strtoul:             result  0, consumed 0
*/

/* IBM AIX

fscanf:  Returned 0, result -1, consumed -1
strtoul:             result  0, consumed 1

fscanf:  Returned 0, result  0, consumed -1
strtoul:             result  0, consumed 1
*/

Antworten auf die Frage(7)

Ihre Antwort auf die Frage