Różnica między scanf () i strtol () / strtod () w parsowaniu liczb

Uwaga: Całkowicie przerobiłem pytanie, aby lepiej odzwierciedlało to, za co ustalam nagrodę. Proszę wybaczyć wszelkie niezgodności z już podanymi odpowiedziami, które mogły powstać. Nie chciałem tworzyć nowego pytania, ponieważ poprzednie odpowiedzi na to pytanie mogą być pomocne.

Pracuję nad implementacją standardowej biblioteki C i jestem zdezorientowany co do jednego określonego rogu standardu.

Standard definiuje formaty liczb akceptowane przezscanf rodzina funkcji (% d,% i,% u,% o,% x) pod względem definicji dlastrtol, strtoul, istrtod.

Standard również to mówifscanf() wrzuci tylko maksymalnie jeden znak do strumienia wejściowego, a zatem niektóre sekwencje zostaną zaakceptowane przezstrtol, strtoul istrtod są nie do przyjęciafscanf (ISO / IEC 9899: 1999, przypis 251).

Próbowałem znaleźć pewne wartości, które mogłyby wykazywać takie różnice. Okazuje się, że szesnastkowy prefiks „0x”, po którym następuje znak, który nie jest cyfrą szesnastkową, jest jednym z takich przypadków, w którym dwie rodziny funkcji różnią się.

Co ciekawe, stało się jasne, że dwie dostępne biblioteki C wydają się nie zgadzać na wyjściu. (Zobacz program testowy i przykładowe wyjście na końcu tego pytania).

Chciałbym usłyszećco byłoby uważane za zgodne ze standardem zachowanie w parsowaniu „0xz”?. Najlepiej byłoby cytować odpowiednie części ze standardu, aby podkreślić znaczenie.

#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
*/

questionAnswers(8)

yourAnswerToTheQuestion