Разница между scanf () и strtol () / strtod () в разборе чисел

Замечания: Я полностью переработал вопрос, чтобы более правильно отразить, для чего я назначаю награду. Пожалуйста, извините за любые несоответствия с уже предоставленными ответами, которые это могло создать. Я не хотел создавать новый вопрос, так как предыдущие ответы на него могут быть полезны.

Я работаю над реализацией стандартной библиотеки C, и меня смущает один конкретный угол стандарта.

Стандарт определяет числовые форматы, принятыеscanf семейство функций (% d,% i,% u,% o,% x) в терминах определений для,strtolstrtoul, а также .strtod

Стандарт также говорит, чтоfscanf() вернет во входной поток максимум один символ, и поэтому некоторые последовательности, принятыеstrtolstrtoul а такжеstrtod неприемлемы дляfscanf (ISO / IEC 9899: 1999, сноска 251).

Я попытался найти некоторые значения, которые продемонстрировали бы такие различия. Оказывается, шестнадцатеричный префикс "0x», за которым следует символ, который не является шестнадцатеричной цифрой, является одним из таких случаев, когда два семейства функций различаются.

Как ни странно, стало очевидно, что нет двух доступных библиотек C, которые, похоже, согласны с выводом. (См. Тестовую программу и пример вывода в конце этого вопроса.)

То, что я хотел бы услышать,что будет считаться стандартом поведения при разборе "0xz "?, Идеально ссылаться на соответствующие части из стандарта, чтобы сделать точку.

#include 
#include 
#include 

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

Ответы на вопрос(8)

Ваш ответ на вопрос