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
似乎在我的平台上被视为long
或int/long/long long
- 没有真正的惊喜。 (我的ncount
是4/4/8字节。)将long long
保存到INT_MAX/LONG_MAX
时,保存的值不会超过ncount
。 unsigned
在分配给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;
}
}
。
答案 0 :(得分:4)
什么是ncount的类型或最小预期范围?
标准没有规定任何具体的最低要求。它断然说道
相应的参数应该是一个指向有符号整数的指针,到目前为止,通过调用fscanf函数将写入从输入流中读取的字符数。
这使得一致的实现没有空间在目标变量中存储不同的数字,除非标准指定所有转换,包括%n
,
如果无法在[destination]对象中表示转换结果,则行为未定义。
当&#34;从输入流中读取的字符数时,会发生什么或应该发生什么?很大?
如果对应于%n
指令的指针正确键入指令的长度说明符(或缺少指针),并且如果字符的真实计数由{{1}读取到该点可以在该类型的对象中表示调用,然后实际上应该存储真实计数。否则,行为未定义。