【问题标题】:stroll, strol functions not giving correct output for long_minwalk, strol 函数没有为 long_min 提供正确的输出
【发布时间】:2020-04-14 09:57:09
【问题描述】:

如下代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
   bitset<64>b(numeric_limits<long>::min());
   string s=b.to_string();
   char *ptr=new char [s.size()+1];
   strcpy(ptr,s.c_str());
   long l1=strtol(ptr,NULL,2);
   cout<<"l1= "<<l1<<endl;
  long l2=strtoul(ptr,NULL,2);
   cout<<"l2= "<<l2<<endl;
   cout<<strtoul(ptr,NULL,2)<<endl;
}

输出是

l1= 9223372036854775807
l2= -9223372036854775808
9223372036854775808

为什么l1不是long_min,为什么是l2?我读过该字符串可以包含 +/- 在 ato*,strto* 函数开头的符号。但是二进制中的负数在计算机使用的 2 补码中没有任何 - 符号。我很困惑。

【问题讨论】:

  • errno 应该设置为 ERANGE,不要忘记检查它。 And this.

标签: c++ strtol strtoull


【解决方案1】:

unsigned long int

9223372036854775808

由该语句输出

cout<<strtoul(ptr,NULL,2)<<endl;

不能在 signed long int 类型的对象中表示。

在此声明中

long l1=strtol(ptr,NULL,2);

由于该值在signed long int 类型中不可表示,因此函数strtol 返回LONG_MAX(因为字符串中没有减号)。而这个值就是这个语句输出的

cout<<"l1= "<<l1<<endl;

来自 C 标准(7.22.1.4 strtol、strtoll、strtoul 和 strtoull 函数)

8 strtol、strtoll、strtoul 和 strtoull 函数返回 转换后的价值,如果有的话。如果无法执行转换,则为零 回来。 如果正确的值超出了可表示的范围 值、LONG_MIN、LONG_MAX、LLONG_MIN、LLONG_MAX、ULONG_MAX 或 返回ULLONG_MAX(根据返回类型和符号 值,如果有),宏 ERANGE 的值存储在 errno 中。

但是,该值可以表示为unsigned long int。所以这个函数strtoul的调用返回了正确的值

long l2=strtoul(ptr,NULL,2);

但该值已分配给signed long int 类型的对象。所以它的最高位被解释为符号位和下一条语句

cout<<"l2= "<<l2<<endl;

输出值LONG_MIN

【讨论】:

    【解决方案2】:

    如果提供的正值大于 long 可以容纳的值,您会收到 ERANGE 错误。要使其与strtol 一起使用,您需要添加-

    #include <bitset>
    #include <cstring>
    #include <iostream>
    #include <limits>
    #include <string>
    
    int main()
    {
       std::bitset<64> b(std::numeric_limits<long>::min());
    
       std::string s = "-" + b.to_string();
    
       long l1=strtol(s.c_str(), NULL, 2);
       std::cout << "l1= " << l1 << '\n';
    }
    

    可能的输出:

    l1= -9223372036854775808
    

    【讨论】:

    • ptr 在我的例子中是 LONG_MIN ,一个长的可以持有。为什么基数 2 需要符号?我是否向 strtol 提供了 LONG_MAX+1LONG_MIN
    • strtol 需要 - 用于负值,否则将被解释为正值。基数无关紧要。
    猜你喜欢
    • 2018-02-27
    • 2021-04-28
    • 2021-10-06
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    相关资源
    最近更新 更多