1
#include <iostream>
#include <string>

int main() {

    std::string s = "3a3";

    try
    {
        int i = std::stoi(s);
        std::cout << i << '\n';
    }
    catch (std::invalid_argument const &e)
    {
        std::cout << "Bad input: std::invalid_argument thrown" << '\n';
    }
    catch (std::out_of_range const &e)
    {
        std::cout << "Integer overflow: std::out_of_range thrown" << '\n';
    }

    return 0;
}

out come is "3". there is alphabet after first 3. how did it converted...? also "10 10" is 10. It cannot catch the spaces in between.

Kyo Heo
  • 141
  • 8

1 Answers1

1

Fast Response: Try:

std::stoi(s, nullptr, 16)

Explanation:

The stoi function have three parameters

  1. String: this is the string variable that contains the number in a string format.
  2. Size_t: The amount of character in the string that would be converted. Note: I always have set it to nullptr, since I used it to transform the entire string.
  3. base: This is the base in which the string number is written on.

The issue you are having is that if base is not provided, stoi would use its default value (which is 10, and is the most commonly used base format).

So the first issue is that the character 'a' is not a base 10 digit and therefore would raise an exception of invalid_argument. The second issue happens because of how stoi handles exceptions. The exceptions are only raised if stoi was unable to convert any characters from the strings. This means that while at least the first character is a valid digit (considering the base), the exception would not be raised, and instead would return the transformation ignoring any character after the first non-base digit.

In this case "3a3" would raise the exception at the character 'a' since it is not a base 10 digit. Then it would convert to an integer all previous characters, which in this case is only the first character '3' and that is why you are getting that result. The exception is not raised. However if the string is "a33", then stoi would be unable to transform 'a', since is not a decimal digit and the exception would be raised; since it was unable to transform any digit.

to avoid that I usually check if the entire string is a valid number checking character by character.

std::string myString = "265F"
for(auto ch : myString)
{
  if(!isxdigit(ch))
    {
      throw std::invalid_argument("error message")
    }
}

That code would check if the string is valid or not for hexadecimal. For decimal digits, you can use isdigit().

If for example you had "327F", then stoi("327f") would have returned 327. Also it is important to remember that bases changes the value of the strings too. For example, an hexadecimal 10 is 16 in decimal base. So conversion in any base besides decimal needs to be explicitly passed as a parameter. If base is not provided then it would assume the string is written in decimal base and 10 in decimal base is 10.

What you want is to set the base parameter to hexadecimal (16), then the calculation would accept the characters 0123456789ABCDEF and lowercase variation as digits. Which would also return the expected value if the string was written in hexadecimal instead of decimal base.