Примечание. Я полностью переработал вопрос, чтобы более правильно отразить то, за что я настраиваю награду. Пожалуйста, извините любые несоответствия с уже предоставленными ответами, которые могли бы быть созданы. Я не хотел создавать новый вопрос, поскольку предыдущие ответы на этот вопрос могут быть полезны.
Я работаю над реализацией стандартной библиотеки C, и я запутался в одном конкретном углу стандарта.
В стандарте определяются форматы чисел, принятые семейством функций scanf
(% d,% i,% u,% o,% x) в терминах определений для strtol
, strtoul
и strtod
.
В стандарте также говорится, что fscanf()
возвращает только один символ во входной поток, и поэтому некоторые последовательности, принятые strtol
, strtoul
и strtod
, неприемлемы для fscanf
( ISO/IEC 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
*/