Thread: stoi() fails when first letter is an alphabet

  1. #1
    Registered User
    Join Date
    Sep 2018
    Posts
    194

    stoi() fails when first letter is an alphabet

    I've noticed this just now and it took me a while to realize this trend with stoi(). It intrigues me because there was no mention of this exception on the references that I read. stoi() caused an abort() on my compiler when the first letter of the string is an alphabet.

    However it works perfectly as long as the first index is a digit. So "2a" would not have no problem but "a2" would.

    Why does this happen and what's an alternative or how to combat this? Are there any other functions that have such drawbacks?

    I guess you would have to use a while loop and cut off the first letter of the string if it's isalpha() using <algorithm>

    I currently use this:
    Code:
    try {
        taken_answer_int = stoi(taken_answer);
    }
    catch (...) {
        taken_answer_int = -1;
    }
    Since it doesn't matter if the string doesn't start with a digit for my program, it just assumes that it's an invalid input. (I mean, how do you expect a program to think typing "onehundra2" to be a valid input for how many cookies one wants to have for breakfast..)

    Thanks for reading, Cheers!

  2. #2
    Registered User
    Join Date
    Jun 2017
    Posts
    156
    There is an overloaded version of stoi that accepst the base of the number.
    Code:
    const int HEX = 16;
    stoi(num, nullptr, HEX)
    stoi - C++ Reference

  3. #3
    Registered User
    Join Date
    Sep 2018
    Posts
    194
    Quote Originally Posted by OldGuy2 View Post
    There is an overloaded version of stoi that accepst the base of the number.
    Code:
    const int HEX = 16;
    stoi(num, nullptr, HEX)
    stoi - C++ Reference
    But it still fails regardless of the radix..?
    I didn't understand what you meant.. can you please elaborate? And what is the other overloaded function? I didn't know there was an overloaded function for stoi().. is it in <string> itself?

    Remember that hexadecimals need to be preceded by 0 also. So putting a letter at the first index would still fail stoi(). If that's what you meant and also alphabets in hexadeciamls only range from a-f so this still wouldn't be a proper solution.
    Last edited by Nwb; 10-07-2018 at 06:58 AM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,498
    But it still fails regardless of the radix..?
    Exactly how does it fail?

    Remember that hexadecimals need to be preceded by 0 also.
    No, hexadecimals are preceded by "0x" an integer starting with zero is assumed to be an Octal number.

    So putting a letter at the first index would still fail stoi().
    No, as long as the letter is in the range of valid hexadecimal ( A - F or a - f) and the converted number is within the range for the type, it should still convert the number correctly.

  5. #5
    Registered User
    Join Date
    Sep 2018
    Posts
    194
    Quote Originally Posted by jimblumberg View Post
    Exactly how does it fail?


    No, hexadecimals are preceded by "0x" an integer starting with zero is assumed to be an Octal number.


    No, as long as the letter is in the range of valid hexadecimal ( A - F or a - f) and the converted number is within the range for the type, it should still convert the number correctly.
    try compiling:
    Code:
    int main() {
        std::string foo = "a0001, A Space Odyssey";
        int foo_int = std::stoi(foo, nullptr, 10);
    
        std::cout << foo_int;
        return 0;
    }
    when using hexadecimal (base 16):
    Code:
    int main() {
        std::string foo = "g0001, A Space Odyssey"; //"a0001, A Space Odyssey" does not throw that error but that's not what we want here.
        int foo_int = std::stoi(foo, nullptr, 16);
    
        std::cout << foo_int;
        return 0;
    }
    both of them give you a "Debug Error!" ... "abort() has been called"

    Turns out you're right the compiler will still treat "a0001, A Space Odyssey" as a hexadecimal, even though it is not preceded by "0x" (0x, like you mentioned and thanks for correcting me). So OldGuy2 would have been right if my question were that I was not able to pass Hexadecimal values but that's not what I want.


    By the way is there an overloaded function for stoi() that I don't know about as OldGuy2 mentioned?


    Oh and here is the error I get while trying to compile the mentioned:
    stoi() fails when first letter is an alphabet-abort-png


    Oh and I just realized there are two smiley faces representing the same symbol ([B]:p[/B] and [B]:tongue: [/B].. weird!)
    Last edited by Nwb; 10-07-2018 at 08:18 AM.

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,498
    Yes, so? They should both fail.

    The first snippet your using base 10, which only accepts the digits as valid entries, 'a' is not a decimal digit.

    The second snippet starts with the letter 'g' which is not a valid hexadecimal digit.

    And also note that the string "aaaaaaaaaaaaa1" should also cause stoi() to throw an exception, an out of range exception to be exact, since that number is not within the range of an integer.

  7. #7
    Registered User
    Join Date
    Sep 2018
    Posts
    194
    Quote Originally Posted by jimblumberg View Post
    Yes, so? They should both fail.

    The first snippet your using base 10, which only accepts the digits as valid entries, 'a' is not a decimal digit.

    The second snippet starts with the letter 'g' which is not a valid hexadecimal digit.

    And also note that the string "aaaaaaaaaaaaa1" should also cause stoi() to throw an exception, an out of range exception to be exact, since that number is not within the range of an integer.
    As long as the first index is a digit, stoi() will pick out all the digits from the string (so "0001, A S5pa6ce Odyssey" would return 000156) - this is what I want here. And I thought that's how it was supposed to work in the first place (even if the first index is an alphabet.. but it's not so). What's an easy work-around?

    And also note that the string "aaaaaaaaaaaaa1" should also cause stoi() to throw an exception, an out of range exception to be exact, since that number is not within the range of an integer.
    Just like "a2" (because a is not an integer?)? Or this is a different exception? But note that "2a" won't throw an exception, it will ignore "a" completely (if I'm not right).
    Last edited by Nwb; 10-07-2018 at 08:31 AM.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,498
    As long as the first index is a digit, stoi() will pick out all the digits from the string - this is what I want here.
    Have you read any documentation for this standard function, such as the documentation pointed to by OldGuy2 in post #2?

    There are two different (overloaded) versions of stoi() one which takes 1 string argument, one that takes three arguments, a string, an int pointer, and an int.

    The first overload will fail if the first character is not a decimal digit. It will stop converting when it encounters the end of the string or any non decimal digit.

    The second overload can be used to convert from a string to the various number bases, decimal, hexadecimal, octal, etc. It also has provision to return the number of characters processed along with being able to specify the number base.

    Just like "a2" (because a is not an integer?)? Or this is a different exception? But note that "2a" won't throw an exception, it will ignore "a" completely (if I'm not right).
    This is only true for the single argument version of stoi(). The three argument version of stoi() will properly convert "a2" into an integer, as long as you use the proper third parameter (16 for base hex).

    As long as the first index is a digit, stoi() will pick out all the digits from the string - this is what I want here. And I thought that's how it was supposed to work in the first place. What's an easy work-around?
    In this snippet you seem to be talking about the one argument version of stoi(), correct? In this case the first character must be a valid decimal digit '0' - '9' and '+' and '-' otherwise an exception will be thrown.

    If the problem is that stoi() (either overload) throws exceptions when it can't handle the input there are at least two solutions.

    Solution 1, don't use stoi(), use std::stringstream instead. By default std::stringstream doesn't throw exceptions when it encounters illegal strings, instead it just puts the stream into an error state to indicate failure.

    Solution 2, use try/catch blocks to catch the exceptions thrown by stoi().

    By the way stoi() can throw two different exceptions, read the documentation if you need to know what they are.
    Last edited by jimblumberg; 10-07-2018 at 08:45 AM.

  9. #9
    Registered User
    Join Date
    Sep 2018
    Posts
    194
    Quote Originally Posted by jimblumberg View Post
    Have you read any documentation for this standard function, such as the documentation pointed to by OldGuy2 in post #2?

    There are two different (overloaded) versions of stoi() one which takes 1 string argument, one that takes three arguments, a string, an int pointer, and an int.

    The first overload will fail if the first character is not a decimal digit. It will stop converting when it encounters the end of the string or any non decimal digit.

    The second overload can be used to convert from a string to the various number bases, decimal, hexadecimal, octal, etc. It also has provision to return the number of characters processed along with being able to specify the number base.


    This is only true for the single argument version of stoi(). The three argument version of stoi() will properly convert "a2" into an integer, as long as you use the proper third parameter (16 for base hex).


    In this snippet you seem to be talking about the one argument version of stoi(), correct? In this case the first character must be a valid decimal digit '0' - '9' and '+' and '-' otherwise an exception will be thrown.

    If the problem is that stoi() (either overload) throws exceptions when it can't handle the input there are at least two solutions.

    Solution 1, don't use stoi(), use std::stringstream instead. By default std::stringstream doesn't throw exceptions when it encounters illegal strings, instead it just puts the stream into an error state to indicate failure.

    Solution 2, use try/catch blocks to catch the exceptions thrown by stoi().

    By the way stoi() can throw two different exceptions, read the documentation if you need to know what they are.
    Hmm you're right I don't know why I thought it took all digits ignoring non-digits it seems to stop when non-digit is encountered so that would make sense.

    By the way in the example if "a2" I want decimal 2 not hexadecimal "0xA2".


    I was asking for a solution keeping in mind that stoi() can be used to extract all digits even though there are non-digits amidst the string. That solution was to prevent this exception from being thrown and continue the stoi() as it would. So "a2a" must return 2. This could be done by removing the initial 'a' (assuming that stoi() worked like I thought it did). So the solution would be removing initial alphabets.

    But since stoi() doesn't work like how I thought it did, then that solution is completely useless because it has to do with stoi() which doesn't work like how I thought it did.

    Instead I need an entirely new algorithm itself that would pick digits from a string.

    Thanks jim.

    I did read the reference (even the one OldGuy2 mentioned) but there was no clear declaration of the fact that stoi would stop when a non-valid character is reached. The second parameter was not enough a hint for me (cmon I'm a newbie at this).

    But hey you learn something new every day right?

    seriously why is there no BB code for spoilers in this forum?
    Last edited by Nwb; 10-07-2018 at 09:01 AM.

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,498
    By the way I misspoke, the overload of stoi() concerns the first argument, one overload takes a std::string, the other overload takes a std::wstring. The rest to the "magic" is because the second and third arguments have default arguments, namely a nullptr and 10 (for base 10).

  11. #11
    Registered User
    Join Date
    Sep 2018
    Posts
    194
    So OldGuy2 was wrong too. That was confusing but glad it's cleared lol I was searching for another stoi(). But the overloaded function of stoi() does the same thing also but just with wstring.

    I'm still not used to all these different data-types and why they exist!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help displaying string letter by letter
    By Robsta107 in forum C Programming
    Replies: 3
    Last Post: 03-01-2017, 04:13 PM
  2. Replies: 12
    Last Post: 11-24-2012, 04:10 AM
  3. realloc alphabet
    By ddimit02 in forum C Programming
    Replies: 2
    Last Post: 06-30-2011, 12:54 AM
  4. [help]count alphabet
    By PUI in forum C Programming
    Replies: 12
    Last Post: 09-25-2006, 07:17 AM
  5. Alphabet Program Help!!!!!!!
    By Sulaco in forum C Programming
    Replies: 3
    Last Post: 11-18-2002, 12:19 PM

Tags for this Thread