【问题标题】:How do you get an unsigned long out of a string?如何从字符串中获得无符号长整数?
【发布时间】:2010-12-01 19:58:42
【问题描述】:

在 C++ 中从字符串中检索无符号长整数的最安全和最好的方法是什么?

我知道许多可能的方法。

首先,转换取自 atol 的有符号长整数。

char *myStr; // Initalized to some value somehow.
unsigned long n = ((unsigned)atol(myStr));

这个明显的问题是,当存储在 myStr 中的值大于有符号的 long 可以包含的值时会发生什么? atol 检索什么?

下一个可能是使用 strtoul。

char *myStr; // Initalized to some value somehow.
unsigned long n = strtoul(myStr, 0, 10);

但是,这对于我的需求来说有点过于复杂了。我想要一个简单的函数,字符串输入,无符号长基数 10 输出。此外,错误处理还有很多不足之处。

我发现的最后一种可能性是使用 sscanf。

char *myStr; // Initalized to some value somehow.
unsigned long n = 0;
if(sscanf(myStr, "%lu", n) != 1) {
    //do some error handling
}

同样,错误处理还有很多不足之处,而且比我想要的要复杂一些。

剩下的显而易见的选择是编写我自己的包装器,围绕前面的一种可能性,或者循环遍历字符串并手动转换每个数字直到达到 ULONG_MAX。

我的问题是,我的 google-fu 找不到的其他选项是什么? C++ std 库中的任何东西都可以将字符串干净地转换为无符号长整数并在失败时抛出异常?

如果这是一个骗局,我深表歉意,但我找不到任何与我完全匹配的问题。

【问题讨论】:

标签: c++ long-integer unsigned string-parsing string-conversion


【解决方案1】:

使用“atol”内置标准函数

例如 std::string input = "1024";

std::atol(input.c_str());

Atol 期望参数是 c 字符串类型,因此 c_str() 会为您执行此操作。

【讨论】:

    【解决方案2】:

    稳健的方式将是 写一个静态函数并使用它

    bool str2Ulong(const string& str,unsigned long & arValue)
    {
       char *tempptr=NULL;
       arValue=strtoul(str,tempptr,10);
    
       return ! (arValue==0 && tempptr==str.c_str());
    
    }
    

    【讨论】:

    • 示例错误,tempptr为(char*),strtoul期望为(char**)
    【解决方案3】:

    如果您可以使用 boost 库 (www.boost.org),请查看转换库 - 它只是包含头文件

    #include "boost/lexical_cast.hpp"
    

    那么你需要做的就是

    unsigned long ul = boost::lexical_cast<unsigned long>(str);
    

    【讨论】:

    • 我将研究 boost 库,我正在考虑使用 python 解释库,因此使用 boost 可能会很好地满足我的需求。不过,如果有一个简单的 clean 函数会很好,对于那些不想依赖于 boost 库的人来说。
    【解决方案4】:
    template <class T>
    T strToNum(const std::string &inputString,
               std::ios_base &(*f)(std::ios_base&) = std::dec)
    {
        T t;
        std::istringstream stringStream(inputString);
    
        if ((stringStream >> f >> t).fail())
        {
            throw runtime_error("Invalid conversion");
        }
        return t;
    }
    
    
    // Example usage
    unsigned long ulongValue = strToNum<unsigned long>(strValue);
    int intValue             = strToNum<int>(strValue);
    
    int intValueFromHex      = strToNum<int>(strHexValue,std::hex);
    unsigned long ulOctValue = strToNum<unsigned long>(strOctVal, std::oct);
    

    【讨论】:

      【解决方案5】:

      Jeffrey Stedfast has a beautiful post 关于为 Mono(用 C 语言)编写 int 解析器例程。
      它生成使用本机类型的代码(您需要 32 位来解析 32 位)和溢出的错误代码。

      【讨论】:

        【解决方案6】:

        您可以毫无问题地使用 strtoul。该函数返回一个无符号长整数。如果无法执行转换,则函数返回 0。如果正确的 long 值超出范围,则函数返回 ULONG_MAX 并且 errno 全局变量设置为 ERANGE。

        【讨论】:

        • 尽可能寻找异常风格的错误处理而不是 errno 风格。
        • 异常风格的错误处理但没有通过类的开销? imo听起来有点自相矛盾:)
        • 嗯,函数可以进行异常风格的错误处理。我只是不想在每次要转换 long 时都实例化两个不需要的类。看起来很浪费!
        【解决方案7】:

        一种方法:

        stringstream(str) >> ulongVariable;
        

        【讨论】:

        • 我编辑了这个问题,以更清楚地表明在这种情况下我正在使用 C 风格的字符串。所以这必须是 streamstream(string(myStr)) >> ulongvariable。这对我来说是一种浪费和低效的感觉:/我宁愿它是更干净、更直接的东西。
        • 实际上,这不是必需的,因为std::string 有一个隐式构造函数,它接受一个 C 风格的字符串作为参数。该构造函数允许你只写stringstream("whatever")
        • 自我打击当然。即便如此,它还是实例化了两个类——以及其中固有的所有内存管理——来完成一个带有单个内部循环的简单函数应该能够完成的事情。我希望标准库中有类似的东西。
        • 优秀的 C++ 编译器是积极的优化器。永远记住这一点。我并不是说这是最快的方式,但它应该相当快。
        • @Alcon,除非有必要,否则不要考虑性能。您确定此代码需要非常快吗?你确定这个解决方案不是很快吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 2011-08-21
        • 2011-09-10
        • 2010-09-18
        • 1970-01-01
        相关资源
        最近更新 更多