繁体   English   中英

fscanf中“读取字符数”的范围是多少?

[英]What is the range of the “number of characters read” in fscanf?

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

什么是ncount类型或最小预期范围?
当“从输入流中读取的字符数” 很大时会发生或应该发生什么?

我的发现:
对于ncount的最小范围/类型的定义,C规范显得很安静。 ncount通常通过"%n"保存,它指定一个int 目标但不是int

通过实验, ncount似乎在我的平台上被视为intlong在那里没有真正的惊喜。 (我的int/long/long long是4/4/8字节。)将ncount保存为long long ,保存的值不会超过INT_MAX/LONG_MAX 当分配给long longncount可以是unsigned的两倍可用范围,但是,这是一个极端的角落,实现者可能不会考虑它。

我在下面的测试表明,即使long long保存,也没有超出int范围的ncount扩展范围。

我的兴趣源于使用"%*[^\\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;
}

测试输出

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

[编辑]

运行一些testf(UINT_MAX + 1LL); ,我收到了其他不一致的结果,如'4294967296 cnt:0 n:1239482368 OK'。 Hmmmm。

示例fscanf() 支持源代码ncount使用int

什么是ncount的类型或最小预期范围?

该标准没有规定任何具体的最低要求。 断然说道

相应的参数应该是一个指向有符号整数的指针,到目前为止,通过调用fscanf函数将写入从输入流中读取的字符数。

C2011,7.21.6.2/12

这使得一致的实现没有空间在目标变量中存储不同的数字,除非标准指定所有转换,包括%n

如果转换结果无法在[destination]对象中表示,则行为未定义。

C2011 7.21.6.2/10

当“从输入流中读取的字符数”很大时会发生或应该发生什么?

如果对于%n指令对应的指针正确地为指令的长度说明符(或缺少指针)键入,并且如果通过该scanf()调用读取到该点的真实字符数可以在该类型的对象中表示,那么真正的计数实际上应该存储。 否则,行为未定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM