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

时间:2017-12-12 20:51:28

标签: c scanf

fscanf()指定"%n"指令作为写入“到目前为止通过调用fscanf函数从输入流读取的字符数”的方法“C11dr§7.21.6.2 12.

我们将此号码称为: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 来源

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

我的测试显示,int范围之后的long long范围不会扩大,即使保存为"%*[^\n]%lln"也是如此。

我的兴趣源于使用#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; } 来确定(极端)线路长度。

实施说明:

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)

测试代码

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);

[编辑]

对于fscanf()的一些运行,我收到了其他不一致的结果,如'4294967296 cnt:0 n:1239482368 OK'。 Hmmmm。

示例int support source code使用ncount private void SendPushNotification(string deviceToken, string message) { try { //Get Certificate var appleCert = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath("Certificates.p12")); //Configuration(NOTE: .pfx can also be used here) var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Sandbox ,appleCert, "1234567890"); //Create a new broker var apnsBroker = new ApnsServiceBroker(config); //Wire up events apnsBroker.OnNotificationFailed += (notification, aggregateEx) => { aggregateEx.Handle(ex => { // See what kind of exception it was to further diagnose if (ex is ApnsNotificationException) { var notificationException = (ApnsNotificationException)ex; // Deal with the failed notification var apnsNotification = notificationException.Notification; var statusCode = notificationException.ErrorStatusCode; string desc = $"Apple Notification Failed: ID={apnsNotification.Identifier}, Code={statusCode}"; Console.WriteLine(desc); lblStatus.Text = desc; } else { string desc = $"Apple Notification Failed for some unknown reason : {ex.InnerException}"; // Inner exception might hold more useful information like an ApnsConnectionException Console.WriteLine(desc); lblStatus.Text = desc; } // Mark it as handled return true; }); }; apnsBroker.OnNotificationSucceeded += (notification) => { lblStatus.Text = "Apple Notification Sent successfully!"; }; var fbs = new FeedbackService(config); fbs.FeedbackReceived += (string devicToken, DateTime timestamp) => { // Remove the deviceToken from your database // timestamp is the time the token was reported as expired }; //Start Proccess apnsBroker.Start(); if (deviceToken != "") { apnsBroker.QueueNotification(new ApnsNotification { DeviceToken = deviceToken, Payload = JObject.Parse(("{\"aps\":{\"badge\":1,\"sound\":\"oven.caf\",\"alert\":\"" + (message + "\"}}"))) }); } apnsBroker.Stop(); } catch (Exception) { throw; } }

1 个答案:

答案 0 :(得分:4)

  

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

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

  

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

C2011, 7.21.6.2/12

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

  

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

C2011 7.21.6.2/10

  

当&#34;从输入流中读取的字符数时,会发生什么或应该发生什么?很大?

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