注意:我完全修改了这个问题,以更准确地反映我设置赏金的目的。请原谅与这可能已经创建的已经给出的答案的任何不一致之处。我不想创建一个新问题,因为以前对此问题的答案可能会有所帮助。
我正在实现一个 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
*/