簡體   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