3

I tried to use:

std::string s = "-150"; unsigned int a = atoi(s.c_str()); std::cout << a; 

and

std::string s = "-150"; std::istringstream reader(s); unsigned int a; reader >> a; std::cout << a; 

I always get 4294967146. I understand that it's a U_INT_MAX - 150.
How can I get an error if number can't be converted, cause input data was invalid? Or (at least) auto-convert to 150.
P.S.
I want to find a way without my manipulation on string.

5
  • There's the abs() function, I think that's what you're looking for actually. Commented Mar 9, 2016 at 15:06
  • 3
    The input data is valid, at least as far as atoi is concerned. Commented Mar 9, 2016 at 15:07
  • 2
    If you use the std::stoi family of functions it will raise an exception if there is an invalid conversion. Commented Mar 9, 2016 at 15:12
  • @NathanOliver Thanks. Commented Mar 9, 2016 at 15:15
  • @NathanOliver No: "If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules." en.cppreference.com/w/cpp/string/basic_string/stoul Commented Sep 17, 2021 at 1:14

3 Answers 3

4

It seems that even std::stoul doesn't reject negative numbers (presumably due to the requirements of strtoul, which it uses). Here's a test program to demonstrate:

#include <iostream> // std::cout, etc. #include <string> // std::string, std::stoul #include <stdexcept> // std::invalid_argument, std::out_of_range #include <limits> // std::numeric_limits int main(int, char **argv) { while (*++argv) { std::string str(*argv); try { unsigned long u = std::stoul(str); if (u > std::numeric_limits<unsigned int>::max()) throw std::out_of_range(str); unsigned int i = u; std::cout << "Value = " << i << std::endl; } catch (const std::invalid_argument& e) { std::cout << "Input could not be parsed: " << e.what() << std::endl; } catch (const std::out_of_range& e) { std::cout << "Input out of range: " << e.what() << std::endl; } } } 

Running this with arguments 150 -150 abc gives

Value = 150 Input out of range: -150 Input could not be parsed: stoul 

But, if we remove the std::numeric_limits test, we get

Value = 150 Value = 4294967146 Input could not be parsed: stoul 

TL;DR

Read as an unsigned long and test the range yourself (wrap it up in a function - perhaps even a template function - if you find you need it in many places).

Sign up to request clarification or add additional context in comments.

Comments

3

You expect a number as input and want to check it fits in unsigned int, then do it so. Convert the string to an universal data type for numbers (signed, floating point, much room -> double) and check if it can be casted without precision lost to your wished type.

You want an integer with no sign, so your number has to be positive, is in given range (so far see std::numeric_limits) and has no decimal part.

Comments

2

How can I get an error if number can't be casted, cause input data was invalid?

You can read into a signed int variable in 1st place:

unsigned int a = 0; int a_input = atoi(s.c_str()); if(a_input < 0) { std::err << "Invalid input." << std::endl; } else { a = a_input; } 

If you need to cover the full range of unsigned int input, choose the next bigger data type available:

long a_input = atol(s.c_str()); 

Or (at least) auto-convert to 150.

That's not a matter of casting. You should simply use the std::abs() function to achieve what you want:

unsigned int a = std::abs(atoi(s.c_str())); // ^^^^^^^^ 

4 Comments

How does this "get an error if number can't be casted, cause input data was invalid?"
Then it doesn't answer the question!
atoi (or atol) is a poor choice of function if 0 might be a valid input, distinct from the error case.
@TobySpeight Feel free to give a better answer, I'm aware that's not ideal. Though the question isn't very precise about the actual requirements.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.