Примечание: Я полностью переработал вопрос, чтобы более правильно отразить, для чего я назначаю вознаграждение. Пожалуйста, извините за любые несоответствия с уже предоставленными ответами, которые это могло создать. Я не хотел создавать новый вопрос, так как предыдущие ответы на него могут быть полезны.
Я работаю над реализацией стандартной библиотеки C, и меня смущает один конкретный угол стандарта.
Стандарт определяет числовые форматы, принятые семейством функций scanf
(% d,% i,% u,% o,% x) в терминах определений для strtol
, strtoul
и * 1011. *.
Стандарт также гласит, что fscanf()
вернет во входной поток максимум один символ, и поэтому некоторые последовательности, принятые strtol
, strtoul
и strtod
, неприемлемы для fscanf
( ИСО / МЭК 9899: 1999, сноска 251).
Я пытался найти некоторые значения, которые проявили бы такие различия. Оказывается, что шестнадцатеричный префикс "0x", за которым следует символ, который не является шестнадцатеричной цифрой, является одним из таких случаев, когда два семейства функций различаются.
Достаточно забавно, стало очевидно, что никакие две доступные библиотеки C, похоже, не согласны с выводом. (См. Тестовую программу и пример вывода в конце этого вопроса.)
Что мне хотелось бы услышать, так это , что будет считаться стандартом поведения при разборе "0xz"? . В идеале приводятся ссылки на соответствующие части из стандарта.
#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
*/