【问题标题】:C++ convert string to uint64_tC++ 将字符串转换为 uint64_t
【发布时间】:2017-02-21 01:06:26
【问题描述】:

我正在尝试从字符串转换为 uint64_t 整数。 stoi 返回一个 32 位整数,所以在我的情况下它不起作用。还有其他解决方案吗?

【问题讨论】:

    标签: c++ string uint64


    【解决方案1】:

    如果您使用的是 C++11 或更高版本,请尝试 std::stoull

    This post 也可能有帮助。我没有将此标记为重复,因为另一个问题是关于 C 的。

    【讨论】:

    • 嗯,c++11 可以被认为是几年前的当前标准。
    • 这是 a 标准,但不是 THE 标准。仍然有很多人因为工作或遗留代码或其他原因而使用 C++03。
    • 肯定 THE 标准是 C++14 吗?
    • @Gambit 您正在返回一个 unsigned long long,它不是 uint64_t,它不一定是 64 位,具体取决于它的编译位置。如果 unsigned long long 不是 64 位,为什么您的解决方案仍然有效。
    • @Cauchy 必须至少为 64 位,因此它可以容纳 64 位整数
    【解决方案2】:

    你试过了吗

    uint64_t value;
    std::istringstream iss("18446744073709551610");
    iss >> value;
    

    ?

    Live Demo


    这也可能适用于过时的标准。

    【讨论】:

    • 您可以通过对答案中的现场演示进行少量编辑来确认,如果您提供的字符串不是整数,std::istringstream 将返回 0。 std::stoull 抛出 std::invalid_argument: Live Demo
    • @davidvandebunte 您可以通过断言来自iss >> value 的返回流与true 比较来检查提取是否成功,或者您可以通过iss.exceptions(std::ios::failbit | std::ios::badbit); 在流上启用异常。
    • 实际上如果字符串以数字开头,std::istringstream 不会返回 0。它将返回数字直到第一个非数字字符。
    【解决方案3】:

    如果您使用的是 C++11 或更高版本,则可以使用 cstdlib> 中的 strtoull()。 否则,如果您在 c99 中也需要此功能,您可以在 C 中的 stdlib.h 中使用 strtoull() 函数。

    看下面的例子

    #include <iostream>
    #include <string>
    #include <cstdlib> 
    
    int main()
    {
      std::string value= "14443434343434343434";
      uint64_t a;
      char* end;
      a= strtoull( value.c_str(), &end,10 );
      std::cout << "UInt64: " << a << "\n";
    }
    

    【讨论】:

      【解决方案4】:

      如果你使用 boost,你可以使用boost::lexical_cast

      #include <iostream>
      #include <string>
      #include <boost-1_61/boost/lexical_cast.hpp> //I've multiple versions of boost installed, so this path may be different for you
      
      int main()
      {
          using boost::lexical_cast;
          using namespace std;
      
          const string s("2424242");
          uint64_t num = lexical_cast<uint64_t>(s);
          cout << num << endl;
      
          return 0;
      }
      

      现场示例:http://coliru.stacked-crooked.com/a/c593cee68dba0d72

      【讨论】:

      • 我没有使用 boost
      • @BaummitAugen Hhhhhm,lexical_cast 在这里如何发挥作用?
      • @πάνταῥεῖ 后者是答案所有者的工作,但对于前者:boost::lexical_cast 非常易于使用并且(至少根据他们自己的基准,用 gcc6.1 测量的最新数字) ,比stringstreamscanf + 朋友快很多(用于手头的转换)。因此,如果您无论如何都在使用 boost,这是一种很好的转换方法。
      • @Vada 这并不妨碍您根据自包含并展示一个良好且可重用的代码示例来改进您的答案。
      • 不需要.c_str(),可以直接使用std::string。这可能也更快。
      【解决方案5】:

      所有这些解决方案都不符合我的需要。

      • istringstream - 将字符串“123asd”解析为 123。
      • stoll - 会引发错误,我不想这样做 使用 try catch。
      • 当时没有使用 boost。

      所以我只使用了一个 for 循环:

      uint64_t val = 0;
      for (auto ch: new_str) {
          if (not isdigit(ch)) return 0;
          val = 10 * val + (ch - '0');
      }
      

      编辑: 如果字符串的数字大于 uint64_t,则另一个问题是溢出。我添加了另一个开始 if 来检查字符串中的字符数。

      【讨论】:

        【解决方案6】:

        注意:这是针对 c 而不是针对 C++ 的解决方案。所以在 C++ 中可能更难。 这里我们将 String HEX 转换为 uint64_t 十六进制值。字符串的所有单个字符都被一个一个地转换为十六进制整数。例如以 10 为基数 -> String = "123":

        • 第一个循环:值为 1
        • 第二个循环:值为 1*10 + 2 = 12
        • 第三个循环:值为 12*10 + 3 = 123

        所以像这样的逻辑是用来将 HEX 字符的 String 转换为 uint_64hex 值。

        uint64_t stringToUint_64(String value) {
          int stringLenght = value.length();
        
          uint64_t uint64Value = 0x0;
          for(int i = 0; i<=stringLenght-1; i++) {
            char charValue = value.charAt(i);
        
            uint64Value = 0x10 * uint64Value;
            uint64Value += stringToHexInt(charValue);
          }
        
          return uint64Value;
        }
        
        int stringToHexInt(char value) {
          switch(value) {
            case '0':
              return 0;
              break;
            case '1':
              return 0x1;
              break;
            case '2':
              return 0x2;
              break;
            case '3':
              return 0x3;
              break;
            case '4':
              return 0x4;
              break;
            case '5':
              return 0x5;
              break;
            case '6':
              return 0x6;
              break;
            case '7':
              return 0x7;
              break;
            case '8':
              return 0x8;
              break;
            case '9':
              return 0x9;
              break;
            case 'A':
            case 'a':
              return 0xA;
              break;
            case 'B':
            case 'b':
              return 0xB;
              break;
            case 'C':
            case 'c':
              return 0xC;
              break;
            case 'D':
            case 'd':
              return 0xD;
              break;
            case 'E':
            case 'e':
              return 0xE;
              break;
            case 'F':
            case 'f':
              return 0xF;
              break;
          }
        }
        

        【讨论】:

        • 我完全不明白这怎么可能是对已接受答案的更好解决方案。它更长,更难理解,更容易出错。
        • 请您详细说明您要实现的目标,而不是仅发布代码?
        • @ChemiCalChems 它将直接将字符串转换为 64 位。我还搜索了很多网站,找不到 esp8266 c 代码的好工作方法。所以最后我自己写了。理想情况下,只需稍作更改,它就可以将任何字符串转换为任何基数。但这里特别是它转换为 64 位。
        • @Kyrol 在这里我尝试做的是逐个将字符串的每个字符转换为十六进制整数。然后添加它的价值。如果您仔细阅读代码,您必须了解所做的工作。它对我来说很完美。经过 4 天的沮丧研究没有结果,我写了这篇文章。
        • @HiloliddinJaloliddinzoda 感谢您的解释和 cmets。 +1 因为,即使它不是 C++,它仍然是一个不错的解决方案。
        猜你喜欢
        • 1970-01-01
        • 2018-09-13
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 1970-01-01
        • 2015-02-18
        • 1970-01-01
        相关资源
        最近更新 更多