C++ convert string to uint64_t
Asked Answered
A

8

31

I am trying to convert from a string to a uint64_t integer. stoi returns a 32 bit integer, so it won't work in my case. Are there other solutions?

Ambroseambrosi answered 21/2, 2017 at 1:6 Comment(0)
S
24

Try this:

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

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

See Live Demo


That may work for out of date standards too.

Sandry answered 21/2, 2017 at 1:20 Comment(3)
As you can confirm with a minor edit to the live demo in the answer, std::istringstream returns 0 if you provide a string that is not an integer. std::stoull throws an std::invalid_argument: Live Demo.Heddy
@Heddy You can either check that the extraction was successful by asserting the returned stream from iss >> value compares to true or you can enable exceptions on the stream via iss.exceptions(std::ios::failbit | std::ios::badbit);.Roseberry
actually std::istringstream will not return 0 if the string starts with digits. It will return the digits till the first non digit char.Ferric
D
51

Try std::stoull if you are using C++11 or greater.

This post may also be of help.

Doghouse answered 21/2, 2017 at 1:8 Comment(6)
Well, c++11 can be considered the current standard since several years now.Dyche
It is a standard, but not THE standard. There are still a lot of people who are working with C++03 because of work or legacy code or whatever reason.Doghouse
Surely THE standard is C++14?Corruptible
@Doghouse you are returning an unsigned long long which is not a uint64_t, which is not necessarily 64 bits depending on where it is being compiled. why is your solution still valid if unsigned long long is not 64 bits.Ambroseambrosi
@Doghouse "but not THE standard" It's the current standard, I didn't say more. I even upvoted your answer dude!Dyche
@Ambroseambrosi it must be at least 64 bits, therefore it can hold a 64-bit integerLabefaction
S
24

Try this:

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

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

See Live Demo


That may work for out of date standards too.

Sandry answered 21/2, 2017 at 1:20 Comment(3)
As you can confirm with a minor edit to the live demo in the answer, std::istringstream returns 0 if you provide a string that is not an integer. std::stoull throws an std::invalid_argument: Live Demo.Heddy
@Heddy You can either check that the extraction was successful by asserting the returned stream from iss >> value compares to true or you can enable exceptions on the stream via iss.exceptions(std::ios::failbit | std::ios::badbit);.Roseberry
actually std::istringstream will not return 0 if the string starts with digits. It will return the digits till the first non digit char.Ferric
P
4

You can use strtoull() from <cstdlib> if you are using C++11 or newer. Else if you need this with c99 as well, you can go for strtoull() function in stdlib.h from C.

See the following example

#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";
}
Panjandrum answered 23/9, 2019 at 13:36 Comment(0)
F
3

All these solutions didn't fit my need.

  • istringstream - parsing the string "123asd" to 123.
  • stoull - will raise and error and I didn't want to use try catch.
  • And boost wasn't used at the time.

So I just use a for loop:

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

edit: Another problem is over flow, if the string is a bigger number than uint64_t. I added another starting if to check the number of the chars in the string.

Ferric answered 12/10, 2021 at 13:40 Comment(1)
Great solution for smart contracts!Rockies
E
2

If you're using boost, you could make use of 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;
}

Live example: http://coliru.stacked-crooked.com/a/c593cee68dba0d72

Educate answered 21/2, 2017 at 1:10 Comment(8)
I'm not using boostAmbroseambrosi
@BaummitAugen Hhhhhm, how does lexical_cast jump in to be useful here?Dyche
@πάνταῥεῖ Are you asking me why lexical_cast is useful here or is this a request to OP to include an example?Peridotite
@Baum Both in case of doubtDyche
@πάνταῥεῖ The latter is the answer owner's job, but for the former: boost::lexical_cast is incredibly easy to use and (at least according to their own benchmark, freshest number with measured with gcc6.1), quite a lot faster than both stringstream and scanf + friends (for the conversion at hand). So if you are using boost anyways, a good method for this conversion.Peridotite
@πάνταῥεῖ Not a dead couch potato, but probably have more of a life than you. Assuming we're done with personal insults, the original link I posted had examples on that very page in case you hadn't clicked it. It looks like the answer was updated with a link to the "latest docs", which I am sure was done with good intentions, but that page does not have examples.Nineteenth
@Vada That doesn't hinder you to improve your answer according to be self contained and showing a good and reusable code example.Dyche
No need for the .c_str(), you can use the std::string directly. That's probably also faster.Peridotite
S
0
uint64_t to_uint64_t(const string& str)
{
    static_assert(is_same_v<uint64_t, unsigned long> || is_same_v<uint64_t, unsigned long long>);

    if constexpr (is_same_v<uint64_t, unsigned long>) // Linux 64
    {
        return stoul(str);
    }
    else // Linux 32 or Windows
    {
        return stoull(str);
    }
}
Stouffer answered 19/3 at 7:59 Comment(0)
A
0

I would rather use from_chars.

The advantages are:

  • is way faster than std::stoull or std::stringstream.
  • no exception are thrown
  • no local is used
  • no dynamic memory allocation.

An example here

Aksum answered 19/3 at 9:51 Comment(0)
G
-1

NOTE: This is solution for c not for C++. So it maybe harder then in C++. Here we convert String HEX to uint64_t hex value. All individual characters of string is converted to hex integer ony by one. For example in base 10 -> String = "123":

  • 1st loop : value is 1
  • 2nd loop : value is 1*10 + 2 = 12
  • 3rd loop : value is 12*10 + 3 = 123

So like this logic is used to convert String of HEX character to uint_64hex value.

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;
  }
}
Glyceric answered 23/2, 2020 at 9:43 Comment(5)
I do not at all see how this could possibly be a better solution to the accepted answer. It's longer, more complicated to understand, and more error-prone.Capita
Ca you please explain more about what are you trying to achieve instead just posting code ?Noisette
@Capita It will directly convert String to 64 bit. I also searched many websites and could not find a good working method for esp8266 c code. So lastly I wrotemyself. Ideally it can convert any string to any base just by changing a bit. But here specifically it converts to 64bit.Glyceric
@Noisette here what I tried to do is to go one by to to each individual Char of String convert it to hex integer. then ad it value. If you read carefully code you must understand what is done. It worked perfect for me. After 4 days of frustrated research without result I wrote this.Glyceric
@HiloliddinJaloliddinzoda Thanks for the explanation and the comments. +1 because, even if it's not C++, it's still a nice solution.Noisette

© 2022 - 2024 — McMap. All rights reserved.