68

What is the best way to convert a std::string to bool? I am calling a function that returns either "0" or "1", and I need a clean solution for turning this into a boolean value.

13 Answers 13

124

I am surprised that no one mentioned this one:

bool b; istringstream("1") >> b; 

or

bool b; istringstream("true") >> std::boolalpha >> b; 
Sign up to request clarification or add additional context in comments.

3 Comments

Reputation does not always go with the top (imho) answer. :)
Nice! This worked for me using the Lua C API. I guess C doesn't have a boolean data type; lua_toboolean() returns an int value of 0 or 1, so this seems to do the trick in C++.
52
bool to_bool(std::string const& s) { return s != "0"; } 

Comments

37

It'll probably be overkill for you, but I'd use boost::lexical_cast

boost::lexical_cast<bool>("1") // returns true boost::lexical_cast<bool>("0") // returns false 

8 Comments

Since this solution embraces some overhead, you shouldnt use this when performance is important. Or specialize boost::lexical_cast for your own needs.
If you can afford converting strings to bools... Anyway, +1: this is the most robust method so far. And if it turns out too slow, wouldn't it be possible to specialize lexical_cast<bool, string> / beg the boost people to do it? :)
How is this more robust than anything else? Its behavior is unclear, for example, random nonzero numbers become true, "true" and empty string should throw exceptions. (Not sure offhand.)
@Potatoswatter: Write a test program and see. On Boost 1.38 (which is what I tested with), 0, 00, etc. => false; 1, 01, etc. => true; anything else I've tested ("", 2, 3, true, false) throws a boost::bad_lexical_cast.
@Chris: Having to try an experiment or look it up (I did briefly check the docs and didn't see it actually specified) is itself a fault. Portability may be limited.
|
17

Either you care about the possibility of an invalid return value or you don't. Most answers so far are in the middle ground, catching some strings besides "0" and "1", perhaps rationalizing about how they should be converted, perhaps throwing an exception. Invalid input cannot produce valid output, and you shouldn't try to accept it.

If you don't care about invalid returns, use s[0] == '1'. It's super simple and obvious. If you must justify its tolerance to someone, say it converts invalid input to false, and the empty string is likely to be a single \0 in your STL implementation so it's reasonably stable. s == "1" is also good, but s != "0" seems obtuse to me and makes invalid => true.

If you do care about errors (and likely should), use

if ( s.size() != 1 || s[0] < '0' || s[0] > '1' ) throw input_exception(); b = ( s[0] == '1' ); 

This catches ALL errors, it's also bluntly obvious and simple to anyone who knows a smidgen of C, and nothing will perform any faster.

Comments

16

There is also std::stoi in c++11:

bool value = std::stoi(someString.c_str()); 

Comments

7

DavidL's answer is the best, but I find myself wanting to support both forms of boolean input at the same time. So a minor variation on the theme (named after std::stoi):

bool stob(std::string s, bool throw_on_error = true) { auto result = false; // failure to assert is false std::istringstream is(s); // first try simple integer conversion is >> result; if (is.fail()) { // simple integer failed; try boolean is.clear(); is >> std::boolalpha >> result; } if (is.fail() && throw_on_error) { throw std::invalid_argument(s.append(" is not convertable to bool")); } return result; } 

This supports "0", "1", "true", and "false" as valid inputs. Unfortunately, I can't figure out a portable way to also support "TRUE" and "FALSE"

6 Comments

Why not just convert the string to lower case before you try to parse it? Then you can support true, TRUE, True, etc.
@fuzzy the key point was portable. This also applies to different languages/locales (and area in which I lack experience/skill). One certainly could do a case-insensitive comparison to a string, but as you notice, this answer has no string literals. It relies on the std::boolalpha stream extractor (which in turn relies on your locale). If lower-casing the string works for you, great.
portable and localization are two different things, and you only asked about portable. Additionally, if the std::boolalpha extractor respects your locale, then converting the string to lower case would work everywhere. std::string lower = s; std::transform( lower.begin(), lower.end(), lower.begin(), ::tolower ); std::istringstream is( lower ); ... <continue on with your previous logic>
if you can speak authoritatively to all possible locales, then you are wiser than I. However a brief search came across this example of a mixed-case (possible) locale, so that's not a limb I'm willing to go out on.
your example only shows a mixed case value because the writer was explaining how to change the value returned by std::boolalpha to an arbitrary string.
|
5

I'd use this, which does what you want, and catches the error case.

bool to_bool(const std::string& x) { assert(x == "0" || x == "1"); return x == "1"; } 

Comments

1

Write a free function:

bool ToBool( const std::string & s ) { return s.at(0) == '1'; } 

This is about the simplest thing that might work, but you need to ask yourself:

  • what should an empty string return? the version above throws an exception
  • what should a character other than '1' or '0' convert to?
  • is a string of more than one character a valid input for the function?

I'm sure there are others - this is the joy of API design!

7 Comments

This is the best method, I think. Using at as the check is very clean.
@GMan: I'm not sure I agree with that. In C, 0 is false, and everything else is true. Hence, 2 is true, 03 is true, etc. So, even though the question is underspecified, it's reasonable to assume that everything that's not zero is true.
That's false, but that's why Kornel's solution is teh win. :-P
One part of the specification that's clear and unequivocal is that the input will be either "0" or "1", nothing else. As such, checking for "00", "2", "03", etc., falls right into YAGNI territory. Then again, so does using at().
It should be != '0', because in integers, anything else than 0 is true
|
0
bool to_bool(std::string const &string) { return string[0] == '1'; } 

1 Comment

It works for a beginner like me thanks.
0

I'd change the ugly function that returns this string in the first place. That's what bool is for.

3 Comments

I don't have control over this function, it is a third party library.
The library seems a bit stupid, though. Is there any reason why it should use std::string of all things for a boolean return?
@UncleBens - maybe it uses std::string as a "variant" type.
0

Here's a way similar to Kyle's except it handles the leading zeroes and stuff:

bool to_bool(std::string const& s) { return atoi(s.c_str()); } 

2 Comments

But but but..."DEADBEEF" would be treated as false! :-P
@Andreas: The C tradition is that 0 is false, and everything else is true. Ideally I'd like to throw an exception in that case, but if that's not an option, then true is "less wrong" than false, in my view.
0

You could always wrap the returned string in a class that handles the concept of boolean strings:

class BoolString : public string { public: BoolString(string const &s) : string(s) { if (s != "0" && s != "1") { throw invalid_argument(s); } } operator bool() { return *this == "1"; } } 

Call something like this:

BoolString bs(func_that_returns_string()); if (bs) ...; else ...; 

Which will throw invalid_argument if the rule about "0" and "1" is violated.

2 Comments

Not everything has to be a class; a free-function is much cleaner and safer.
@GMan, I'd be the first one to say that :)
-1

Try this:

bool value; if(string == "1") value = true; else if(string == "0") value = false; 

3 Comments

Unfortunately this leaves value in an undeterminated state if the string should contain something else.
@UncleBens: More likely, its value would be FileNotFound. :-P
@ChrisJester-Young Uncle Bens talked about the var value which is in that case never initialized. First line should be bool value {false};

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.