C++将字符串转换为uint64_t

29

我正在尝试将字符串转换为 uint64_t 整数。 stoi 返回一个32位整数,所以在我的情况下无法使用。是否有其他解决方案?

6个回答

46

如果你正在使用C++11或更高版本,请尝试使用std::stoull

这篇帖子也可能会有所帮助。我没有将其标记为重复,因为另一个问题是关于C的。


2
嗯,自几年前以来,C++11可以被认为是当前的标准。 - πάντα ῥεῖ
1
这是一个标准,但不是唯一的标准。仍有许多人因工作、遗留代码或其他原因而使用C++03。 - Gambit
1
当然,标准肯定是C++14吧? - Tristan Brindle
2
@Gambit,你返回的是一个unsigned long long,而不是uint64_t,这并不一定是64位,这取决于编译的位置。如果unsigned long long不是64位,为什么你的解决方案仍然有效呢? - Cauchy
@Gambit "但不是唯一的标准"。它是目前的标准,我没有说更多。我甚至点赞了你的答案,伙计! - πάντα ῥεῖ
2
@Cauchy,它必须至少为64位,因此可以容纳64位整数。 - M.M

24

试试这个:

#include <iostream>
#include <sstream>
#include <cstdint>

int main() {
    uint64_t value;
    std::istringstream iss("18446744073709551610");
    iss >> value;
    std::cout << value;
}

请查看实时演示


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


1
通过对答案中的现场演示进行微小编辑,您可以确认,如果提供的字符串不是整数,则std::istringstream将返回0。std::stoull会抛出一个std::invalid_argument异常:现场演示 - davidvandebunte
@davidvandebunte 你可以通过断言从 iss >> value 返回的流与 true 相比较来检查提取是否成功,或者你可以通过 iss.exceptions(std::ios::failbit | std::ios::badbit) 在流上启用异常。 - Darklighter
实际上,如果字符串以数字开头,std::istringstream不会返回0。它将返回数字,直到第一个非数字字符。 - Avizipi

4

如果您使用的是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";
}

3

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

  • istringstream - 将字符串 "123asd" 解析为 123。
  • stoull - 会引发错误,而我不想使用 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更大。我添加了另一个开始判断语句来检查字符串中字符的数量。

智能合约的绝佳解决方案! - Kostiantyn Ivashchenko

2
如果您正在使用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。 - Cauchy
@BaummitAugen 嗯,_lexical_cast_ 在这里如何变得有用呢? - πάντα ῥεῖ
1
@πάνταῥεῖ 后者是答案所有者的工作,但对于前者:boost::lexical_cast非常容易使用,并且(至少根据他们自己的基准测试,最新的数字与gcc6.1一起测量),比stringstreamscanf +朋友们(用于手头的转换)要快得多。因此,如果您已经在使用boost,则这是进行此转换的好方法。 - Baum mit Augen
1
@Vada,这并不妨碍您改善答案,使其自包含,并展示一个好的、可重用的代码示例。 - πάντα ῥεῖ
1
不需要使用.c_str(),你可以直接使用std::string。这样可能也更快。 - Baum mit Augen
显示剩余3条评论

-1
注意:这是针对C而不是C++的解决方案。所以可能比在C++中更难。 在这里,我们将字符串HEX转换为uint64_t十六进制值。将字符串的每个单独字符逐一转换为十六进制整数。例如,在十进制中,字符串 = "123":
  • 第一次循环:值为1
  • 第二次循环:值为1 * 10 + 2 = 12
  • 第三次循环:值为12 * 10 + 3 = 123
因此,像这样的逻辑被用来将HEX字符的字符串转换为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;
  }
}

4
我并不认为这种方法比已接受的答案更好。它更冗长、更难理解,而且容易出错。 - ChemiCalChems
你能否详细解释一下你想要实现什么,而不只是发布代码? - Kyrol
1
@ChemiCalChems 它将直接将字符串转换为64位。我还搜索了许多网站,但没有找到适用于esp8266 c代码的好方法。最后我自己写了一个。理想情况下,它可以通过改变一位来将任何字符串转换为任何基数。但在这里,它特别将其转换为64位。 - Hiloliddin Jaloliddinzoda
1
@Kyrol,我尝试的是逐个遍历字符串中的每个字符,将其转换为十六进制整数,然后将其值相加。如果你仔细阅读代码,你必须理解这是做了什么。对我来说,它完美地工作了。在四天的沮丧研究之后没有结果,我写下了这个。 - Hiloliddin Jaloliddinzoda
@HiloliddinJaloliddinzoda 感谢您的解释和评论。+1 因为,即使它不是 C++,它仍然是一个不错的解决方案。 - Kyrol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接