【问题标题】:sscanf and %i / radix detection of large unsigned integerssscanf 和 %i / 大无符号整数的基数检测
【发布时间】:2020-09-11 11:12:06
【问题描述】:

我正在处理包含大量数字(磁盘偏移)的文件,并且在使用 scanf%lli 时遇到了问题 - 数字的格式为 0x... 但 scanf 没有读取所有位。

这是示例代码(我在 https://www.onlinegdb.com/online_c_compiler 上测试过)。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* str = malloc(30);
    unsigned long long l;
    sprintf(str, "0x%llx\n", 0xffffffffffffffffULL);
    printf("%s\n", str);
    sscanf(str, "%lli", &l);
    printf("%llx\n", l);

    return 0;
}

它输出:

0xffffffffffffffff

7fffffffffffffff

而我希望两个数字相等。

如果我使用 %llx 说明符,它可以正常工作,但我不想将自己限制为十六进制格式的数字。

【问题讨论】:

  • 试试strtoull()
  • @png 谢谢 - 它可以工作,但我一次扫描多个令牌。这会使我的所有代码复杂化。
  • 最好使用snprintf()而不是sprintf()来避免溢出。

标签: c scanf unsigned unsigned-integer


【解决方案1】:

不幸的是i代表有符号整数,对应的预期参数是指向int的指针;使用ll,宽度将为long long,但仍会被签名。带有基数检测的无符号整数没有scanf 格式字符。


没有完美的解决方案。您可以使用strtoull(str, &amp;endptr, 0)(甚至strtoumax),它会正确检测格式,但使用起来会比较繁琐。

但是scanf 也不是完美的——如果数字太大,那么你总是会得到最大值,就像你得到LLONG_MAX 一样,没有错误提示。

【讨论】:

  • 也许从@pmg 的评论中添加strtoull 的替代品,我会将答案标记为正确。
【解决方案2】:

%lli 用于long long signed int(在您的系统上最多只能达到 0x7fffffffffffffff)。

%llu 用于long long unsigned int(这是您要阅读的内容)。

将前者替换为后者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多