RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1259002
Accepted
wololo
wololo
Asked:2022-03-22 03:32:28 +0000 UTC2022-03-22 03:32:28 +0000 UTC 2022-03-22 03:32:28 +0000 UTC

使用 strtol() / strtoll() 函数及其无符号对应物将字符串转换为整数的算法

  • 772

我对通过函数strtol(),strtoll() , strtoul(),strtoull()将 C 字符串转换为整数类型的算法感兴趣。

让我们从 C 语言标准(n1570, 7.22.1.4)开始:

、strtol、strtoll和函数[ strtoul... ] 5 如果主题序列具有预期的形式并且 的值为零,则根据 6.4.4.1 的规则,从第一位数字开始的字符序列被解释为整数常量. 如果主题序列具有预期的形式并且 的值介于 2 和 36 之间,则将其用作转换的基础,将其值赋予每个字母,如上所示。如果主题序列以减号开头,则转换产生的值被否定(在返回类型中)。指向最终字符串的指针存储在 指向的对象中,前提是它不是空指针。 [... ] , ,strtoull
long int strtol(const char * restrict nptr, char ** restrict endptr, int base);

basebaseendptrendptr

Returns
strtolstrtollstrtoul, 并且strtoull函数返回转换后的值(如果有)。如果无法执行转换,则返回零。如果正确的值在可表示值的范围之外,LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, 或者ULLONG_MAX返回(根据返回类型和值的符号,如果有的话),宏的值ERANGE存储在errno.

据我了解所写内容,想法如下(不考虑非十进制基数的前导空格字符和数字系统):

  1. 在源代码行中,我们将丢弃减号(如果有)。
  2. 如果字符串包含目标类型无法表示的数字,则返回 LONG_MIN,LONG_MAX依此类推。取决于目标类型和字符串中数字的符号。并且还安装errno在ERANGE.
  3. 让我们将字符串转换为目标类型。
  4. 如果源字符串中的数字以减号开头,则将减号应用于目标类型中的值。

示例 #1

errno = 0;
unsigned long long ullval = std::strtoull("-18446744073709551615", nullptr, 10);
cout << "errno:  " << errno   << endl;
cout << "ullval: " << ullval  << endl;

cout << -18446744073709551615ULL << endl;

结论:

errno:  0
ullval: 1
1

现在没关系。

  1. "-18446744073709551615"减号已从行中删除。
  2. 字符串"18446744073709551615"中的数字由 type 表示unsigned long long。
  3. 让我们将字符串转换为数字。
  4. 对结果类型中的值应用减号:-18446744073709551615ULL == 1ULL。

示例 #2

和上一个类似,只是我们转换了字符串"-18446744073709551616"。结论:

errno:  34
ullval: 18446744073709551615

我们也得到了预期的输出。

  1. "-18446744073709551616"减号已从行中删除。
  2. 字符串"18446744073709551616" 中的数字不能用type表示unsigned long long。因此,我们改变errno,并返回ULLONG_MAX。

示例#3

errno = 0;
long long llval = std::strtoll("-9223372036854775808", nullptr, 10);
cout << "errno: " << errno  << endl;
cout << "llval: " << llval  << endl;

结论:

errno: 0
llval: -9223372036854775808

现在问题出现了。

  1. "-9223372036854775808"减号已从行中删除。
  2. 字符串"9223372036854775808" 中的数字不能用type表示long long。因此,有必要安装errno并返回LLONG_MIN。

为什么函数std::strtoll()返回LLONG_MIN但没有设置errno?(代码示例的链接:g++,clang)


此外,Visual Studio 2010 中的以下代码(我现在手头没有更新的代码):

errno = 0;
unsigned long ulval = std::strtoul("-4294967296", nullptr, 10);
cout << "errno: " << errno   << endl;
cout << "ulval: " << ulval   << endl;

产生以下输出:

errno: 34
ulval: 1

"-4294967296"丢弃减号后字符串中的数字不能用类型表示unsigned long,因此必须设置errno(发生),返回值ULONG_MAX,但函数返回1。


strtol()根据语言标准,通过函数/strtoll()及其无符号对应项将字符串转换为整数的算法是什么。我试图理解标准中的内容并没有成功。


嗯,有人投票结束了这个问题,原因是“由错字引起的问题或不可重现的问题”。

可能值得关闭,但首先,如果“问题没有重现”,那么我希望看到一个编译器示例,在执行代码后std::strtoll("-9223372036854775808", nullptr, 10),它将设置errno为非零值。

如果errno不应该设置它,那么我很乐意阅读为什么不应该设置它的解释(当然,参考标准)。

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Fat-Zer
    2022-03-22T15:59:24Z2022-03-22T15:59:24Z

    该标准没有描述算法,因此,它描述了行为,即在python方面,不是鸭子的排列方式,而是鸭子应该如何嘎嘎;某些输入值的结果应该是什么(即使文本看起来像一系列动作)。

    据我了解,7.22.1.4/5 中的短语“*该值...被否定(在返回类型中)*”表示对于转换过程中获得的值,val结果必须与-val该类型等效。该语句是普遍接受的解释的基础,即无符号函数如果字符串以减号开头,则应返回一个应用一元减号的值而不是错误。是的,如果我们仅基于标准的文本,那么恕我直言,这样的解释有些牵强,并不完全符合最小意外原则,但事情就是这样发生的。在 linux mana 中,对此进行了更清楚的描述:

    男人 3 斯特图尔

    该函数strtoul()返回转换结果,或者,如果指定了减号,则返回负转换结果,表示为正数...

    此外,7.22.1.4/5要求所有函数,如果字符串中给出的有效数字超出该类型的可表示值的范围,则必须返回相应的常量和错误。


    因此,strtoul它应该返回(对于 32 位long, ULONG_MAX==4294967295):

    • 对于-∞... -4294967296→ ULONG_MAX;errno=ERANGE
    • 对于-4294967295…… -1→-val
    • 对于0…… 4294967295→val
    • 对于4294967296... ∞→ ULONG_MAX;errno=ERANGE
    • 无法解析的 → 0

    A,strtol应该返回 (when LONG_MIN==-2147483648, a LONG_MAX==2147483647):

    • 对于-∞... -2147483649→ LONG_MIN;errno=ERANGE
    • 对于-2147483648…… 2147483647→val
    • 对于2147483648... ∞→ LONG_MAX;errno=ERANGE
    • 对于无法解析的字符串 -> 0

    同样对于strtoull/ strtoll。

    哪种实现算法将实现这种行为是他们的事。例如,您可以在 BSD libc: 中看到strtoul实现strtol。


    问题中的所有示例都与这些值相匹配……当然,除了 msvc,但臭名昭著的是,它对符合标准并不十分讲究。

    • 2

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5