fscanf()指定该"%n"指令作为一种方法,用于编写"到目前为止通过对fscanf函数"C11dr§7.21.6.212的调用从输入流中读取的字符数.
我们把这个号码称为:ncount.
该"%n"指令可以在长度修饰符hh, h, l, ll, j和其他之前.例子:
FILE *stream = stdin;
int n_i;
fscanf(stream, "%*s%n", &n_i); // save as int
signed char n_hh;
fscanf(stream, "%*s%hhn", &n_hh); // save as signed char
long long n_ll;
fscanf(stream, "%*s%lln", &n_ll); // save as long long
Run Code Online (Sandbox Code Playgroud)
什么是类型或最小预期范围
ncount?
当"从输入流中读取的字符数" 很大时会发生或应该发生什么?
我的发现:
C规范在最小范围/类型的定义上显得很安静ncount. ncount通常保存通过"%n"它指定int 目的地而不是int 来源.
通过实验,ncount似乎被视为一个int或long在我的平台上 - 没有真正的惊喜.(我的int/long/long long是4/4/8字节.)保存ncount到a时long long,保存的值不会超过INT_MAX/LONG_MAX. ncount可能是unsigned指定的两倍可用范围long long,但这是一个极端的角落,也许实施者不会考虑.
我下面的测试显示无扩展范围ncount过去的int范围,甚至当保存为long long.
我的兴趣源于使用"%*[^\n]%lln"确定(极端)线长度.
实施说明:
GNU C11(GCC)版本6.4.0(i686-pc-cygwin),由GNU C版本6.4.0,GMP版本6.1.2,MPFR版本3.1.5-p10,MPC版本1.0.3编译,isl版本0.14或0.13
glibc 2.26发布.
Intel Xeon W3530,64位操作系统(Windows 7)
测试代码
#include <limits.h>
#include <stdio.h>
#include <string.h>
int print(FILE *stream, long long size, int ch) {
char buf[4096];
memset(buf, ch, sizeof buf);
while (size > 0) {
size_t len = size < (long long) sizeof buf ? (size_t) size : sizeof buf;
size_t y = fwrite(buf, 1, len, stream);
if (len != y) {
perror("printf");
return 1;
}
size -= len;
}
return 0;
}
int scan(FILE *stream) {
rewind(stream);
long long n = -42;
int cnt = fscanf(stream, "%*s%lln", &n);
printf("cnt:%d n:%lld ", cnt, n);
return cnt != 0;
}
int testf(long long n) {
printf("%10lld ", n);
FILE *f = fopen("x.txt", "w+b");
if (f == NULL) {
perror("fopen");
return 1;
}
if (print(f, n, 'x')) {
perror("print");
fclose(f);
return 2;
}
if (scan(f)) {
perror("scan");
fclose(f);
return 3;
}
fclose(f);
puts("OK");
fflush(stdout);
return 0;
}
int main(void) {
printf("%d %ld %lld\n", INT_MAX, LONG_MAX, LLONG_MAX);
testf(1000);
testf(1000000);
testf(INT_MAX);
testf(INT_MAX + 1LL);
testf(UINT_MAX);
testf(UINT_MAX + 1LL);
testf(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
测试输出
2147483647 2147483647 9223372036854775807
File length Reported bytes read
1000 cnt:0 n:1000 OK
1000000 cnt:0 n:1000000 OK
2147483647 cnt:0 n:2147483647 OK
2147483648 cnt:0 n:-2147483648 OK // implies ncount is internally an `int/long`
4294967295 cnt:0 n:-1 OK
4294967296 cnt:0 n:-1088421888 OK // This `n` value may not be consistent. -1 also seen
1 cnt:0 n:1 OK
Run Code Online (Sandbox Code Playgroud)
[编辑]
通过一些运行testf(UINT_MAX + 1LL);,我收到了其他不一致的结果,如'4294967296 cnt:0 n:1239482368 OK'.Hmmmm.
示例fscanf() 支持源代码使用intfor ncount.
什么是类型或 ncount 的最小预期范围?
该标准没有规定任何具体的最小值。它直截了当地说
相应的参数应该是一个指向有符号整数的指针,到目前为止,通过调用 fscanf 函数从输入流中读取的字符数将写入该整数。
这没有为符合要求的实现在目标变量中存储不同的数字留下空间,除非标准规定了所有转换,包括%n,
如果转换的结果不能在 [destination] 对象中表示,则行为未定义。
当“从输入流中读取的字符数”很大时会发生什么或应该发生什么?
如果%n针对指令的长度说明符(或缺少长度说明符)正确键入了与指令对应的指针,并且如果该scanf()调用在该点之前读取的字符的真实计数可以在该类型的对象中表示,则真实计数实际上应该存储。否则,行为是未定义的。