Converting from a std::string to bool - c++

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.

I am surprised that no one mentioned this one:
bool b;
istringstream("1") >> b;
or
bool b;
istringstream("true") >> std::boolalpha >> b;

bool to_bool(std::string const& s) {
return s != "0";
}

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

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.

There is also std::stoi in c++11:
bool value = std::stoi(someString.c_str());

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"

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";
}

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!

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

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());
}

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.

If you need "true" and "false" string support consider Boost...
BOOST_TEST(convert<bool>( "true", cnv(std::boolalpha)).value_or(false) == true);
BOOST_TEST(convert<bool>("false", cnv(std::boolalpha)).value_or( true) == false);
BOOST_TEST(convert<bool>("1", cnv(std::noboolalpha)).value_or(false) == true);
BOOST_TEST(convert<bool>("0", cnv(std::noboolalpha)).value_or( true) == false);
https://www.boost.org/doc/libs/1_71_0/libs/convert/doc/html/boost_convert/converters_detail/stream_converter.html

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

bool to_bool(std::string const &string) {
return string[0] == '1';
}

Related

If statement logic reverse

bool x = someFuncThatReturnsTrueorFalse();
if (!x && (str1.length() != str2.length()) {
// do nothing
} else {
// do something
}
How would I rearrange the code above to eliminate the else statement?
I need to do nothing if bool = false and str1 and str2 have different lengths. Otherwise, I need to do something (e.g. function call).
For the life of me, I can't think of any way to change this. Let me know if you need further details.
The simplest way is putting !() around the condition.
bool x = someFuncThatReturnsTrueorFalse();
if (!(!x && (str1.length() != str2.length())) {
// do something
}
Another way is using De Morgan's laws: !(A && B) is equivalent to !A || !B.
bool x = someFuncThatReturnsTrueorFalse();
if (x || (str1.length() == str2.length()) {
// do something
}
There is nothing wrong leaving as is. The code will still compile

Simple Word Guessing Game

bool guess(char c)
{
if (guesses[c])
{
guesses[] = c;
return true;
}
else if (c > ='a' && c <= 'z')
{
guesses[] = c;
return false;
}
}
bool guesses[255] = {};
I need to use this to see if the person has enter a char between a - z and if they haven't I return true else I will return false. either way I will also update guesses with the char. Right now I don't understand how to add char to the array, so that next time I check the it will be false and tell them it was already guessed. I understand this is using the ASCII table but beyond that I am lost. Could anyone explain why this won't work.
I currently get the error
expected primary-expression before']'
but if I take bracket out I get
incompatible type char to bool
which make sense but then how do I make it so where char c is will be mark true in the Boolean array
You've left your brackets empty, so you currently aren't providing an index:
guesses[c] = c;
But you also don't want to assign the char to guesses, you'd want to assign a bool:
guesses[c] = true;
That will compile* and fix your problem.
* Note you also have a syntax error with > =, which I assume was just a copy+paste issue from the editor to the question, but you should fix that also to be >=. Your function guess can also potentially not return (if neither the if or else if are true), which is undefined behaviour. You should ensure all control paths return a value, and you should make sure you compile at the highest warning level so you are warned about these things.
But not your design.
Since you're only dealing with characters a-z, you don't need to allocate all 255 elements like you do. You could simply minus the character to obtain the correct index:
bool guesses[26];
if (c >='a' && c <= 'z')
guesses[c-'a'] = true;
Consider instead using a std::set, a container of unique elements, to track whether a character has been pressed:
#include <set>
std::set<char> guesses;
bool guess(char c)
{
// Have we already inserted this character?
if (guesses.find(c) != std::end(guesses))
{
// Character has already been guessed:
std::cout << "This character has already been guessed";
return true;
}
else if (c >= 'a' && c <= 'z')
{
// Valid guess:
guesses.insert(c);
return false;
}
}

C++ String Length Check

bool fitsKey3(string n) {
int ncheck = str.length(n);
if (ncheck = KEY3) {
return true;
} else {
return false;
}
}
The above function uses a string "n" that is a string given to the function from an input file. I want to write this function that checks the length of this "identifier code" from the input file (it's a drone project), and if the length of the security code is equal to the constant integer "KEY3 (= 50), it returns true. Otherwise, return false.
How do I fix this setup?
= assigns the value of KEY3 to ncheck.
== compares ncheck and KEY3 for equality.
Also, unless you're being paid by lines of code, I'd suggest using the much simpler and clearer form:
return n.length() == KEY3;
(I corrected your usage of the length() member function, since I suppose it was only a typo.)
And as pointed out by Anon Mail, unless you want to make a copy of the string every time you call the function, I'd suggest only passing a reference to it (const because you're not modifying it):
bool fitsKey3(string const& n)
I would write it like this:
bool fitsKey3(string n) {
return n.length() == KEY3;
}
You do two operations:
Get string length by n.length()
Compare the length with a KEY3 (NB: use == to compare)

C++ char-by-char comparison of a string

I'm trying to work on a string comparison check for an introductory C++ course; it's an online course and unfortunately the instructor is not very responsive. For a current lab, I need to perform a number of manipulations on string data.
Currently, I'm working on a step to check if a string has any repeated characters, and if a repetition is found, to delete the repeated characters at their present spot and move one copy of the letter to the beginning of the string. This is only to be done for the first double to be found.
I've set up a basic counter to move through the string looking for matches, checking a stored character (updated on each iteration) to the current position in the string.
I tried multiple string functions (comparing the current inputString[i] to the previous such, stored as a second string tempStore), but those always gave char conversion errors. I've tried the below instead, but this is now giving an error: "invalid conversion from 'char' to 'const char*'.
inputString is given by the user, testA and testB are defined as type char
Any ideas?
while (opComplete == false) {
if (i == 0) {
i++;
}
else if (i == inputString.size()) {
//Not Found
opComplete = true;
}
else if (i > 0) {
testA = inputString[i-1];
testB = inputString[i];
if (strcmp(testA,testB) != 0) {
i++;
}
else {
inputString.insert(0,inputString[i]);
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}
Your problem is in this line:
inputString.insert(0,inputString[i]);
The std::string.insert() function the way you call it here has the following signature:
string& insert ( size_t pos1, const char* s );
so it expects a const char pointer. You, however, are giving it the inputString[i]. The return value of std::string.operator[] is a reference (as here), hence the error. However, by the time you reach your else, you already have the desired character in your testB variable, so you can just change the line to
inputString.insert(0, &testB);
You also can't pass normal chars into strcmp. You can use operator==, or, in your case, operator!= though.
You are using the insert method incorrectly, check its reference here for possible arguments.
while (opComplete == false)
{
if (i == 0)
i++;
else if (i == inputString.size())
opComplete = true;
else if (i > 0) {
char testA = inputString[i-1];
char testB = inputString[i];
if(testA!=testB)
i++;
else {
inputString.insert(0,&testB); //Problem Corrected here.
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}

Is this the right way to use recursion?

Given strings s and t compute recursively, if t is contained in s return true.
Example: bool find("Names Richard", "Richard") == true;
I have written the code below, but I'm not sure if its the right way to use recursion in C++; I just learned recursion today in class.
#include <iostream>
using namespace std;
bool find(string s, string t)
{
if (s.empty() || t.empty())
return false;
int find = static_cast<int>(s.find(t));
if (find > 0)
return true;
}
int main()
{
bool b = find("Mississippi", "sip");
string s;
if (b == 1) s = "true";
else
s = "false";
cout << s;
}
If anyone find an error in my code, please tell me so I can fix it or where I can learn/read more about this topic. I need to get ready for a test on recursion on this Wednesday.
The question has changed since I wrote my answer.
My comments are on the code that looked like this (and could recurse)...
#include <iostream>
using namespace std;
bool find(string s, string t)
{
if (s.empty() || t.empty())
return false;
string start = s.substr(0, 2);
if (start == t && find(s.substr(3), t));
return true;
}
int main()
{
bool b = find("Mississippi", "sip");
string s;
if (b == 1) s = "true";
else
s = "false";
cout << s;
}
Watch out for this:
if (start == t && find(s.substr(3), t));
return true;
This does not do what you think it does.
The ; at the end of the if-statement leaves an empty body. Your find() function will return true regardless of the outcome of that test.
I recommend you turn up the warning levels on your compiler to catch this kind of issue before you have to debug it.
As an aside, I find using braces around every code-block, even one-line blocks, helps me avoid this kind of mistake.
There are other errors in your code, too. Removing the magic numbers 2 and 3 from find() will encourage you to think about what they represent and point you on the right path.
How would you expect start == t && find(s.substr(3), t) to work? If you can express an algorithm in plain English (or your native tongue), you have a much higher chance of being able to express it in C++.
Additionally, I recommend adding test cases that should return false (such as find("satsuma", "onion")) to ensure that your code works as well as calls that should return true.
The last piece of advice is stylistic, laying your code out like this will make the boolean expression that you are testing more obvious without resorting to a temporary and comparing to 1:
int main()
{
std::string s;
if (find("Mississippi", "sip"))
{
s = "true";
}
else
{
s = "false";
}
std::cout << s << std::endl;
}
Good luck with your class!
Your recursive function needs 2 things:
Definite conditions of failure and success (may be more than 1)
a call of itself to process a simpler version of the problem (getting closer to the answer).
Here's a quick analysis:
bool find(string s, string t)
{
if (s.empty() || t.empty()) //definite condition of failure. Good
return false;
string start = s.substr(0, 2);
if (start == t && find(s.substr(3), t)); //mixed up definition of success and recursive call
return true;
}
Try this instead:
bool find(string s, string t)
{
if (s.empty() || t.empty()) //definite condition of failure. Done!
return false;
string start = s.substr(0, 2);
if (start == t) //definite condition of success. Done!
return true;
else
return find(s.substr(3), t) //simply the problem and return whatever it finds
}
You're on the right lines - so long as the function calls itself you can say that it's recursive - but even the most simple testing should tell you that your code doesn't work correctly. Change "sip" to "sipx", for example, and it still outputs true. Have you compiled and run this program? Have you tested it with various different inputs?
You are not using recursion. Using std::string::find in your function feels like cheating (this will most likely not earn points).
The only reasonable interpretation of the task is: Check if t is an infix of s without using loops or string functions.
Let's look at the trivial case: Epsilon (the empty word) is an infix of ever word, so if t.empty() holds, you must return true.
Otherwise you have two choices to make:
t might be a prefix of s which is simple to check using recursion; simply check if the first character of t equals the first character of s and call isPrefix with the remainder of the strings. If this returns true, you return true.
Otherwise you pop the first character of s (and not of t) and proceed recursively (calling find this time).
If you follow this recipe (which btw. is easier to implement with char const* than with std::string if you ask me) you get a recursive function that only uses conditionals and no library support.
Note: this is not at all the most efficient implementation, but you didn't ask for efficiency but for a recursive function.