2010-01-29 29 views
38

Jaki jest najlepszy sposób konwersji std :: string na bool? Wywołuję funkcję, która zwraca wartość "0" lub "1", i potrzebuję czystego rozwiązania do przekształcenia tego w wartość boolowską.Konwersja z std :: string na bool

Odpowiedz

29

To będzie prawdopodobnie overkill dla ciebie, ale użyję boost::lexical_cast

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

Ponieważ to rozwiązanie obejmuje pewien narzut, nie należy go używać, gdy wydajność jest ważna. Lub wyspecjalizuj boost :: leksykalny dla własnych potrzeb. – smerlin

+0

Jeśli możesz pozwolić sobie na konwersję łańcuchów na sygnały ... W każdym razie +1: to jak dotąd najsolidniejsza metoda. A jeśli okaże się zbyt powolny, czy nie byłoby możliwe specjalizację leksykalnej_przekładki /błagać ludzi doładowania, aby to zrobili? :) – UncleBens

+2

Jak to jest bardziej niezawodne niż cokolwiek innego? Jego zachowanie jest niejasne, na przykład przypadkowe niezerowe liczby stają się prawdziwe, "prawda", a pusty ciąg powinien generować wyjątki. (Nie wiem od ręki). – Potatoswatter

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

Napisz bezpłatną funkcję:

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

Chodzi o najprostszej rzeczy, które mogą działać, ale trzeba zadać sobie pytanie:

  • co powinno pusty zwrot ciąg? powyższa wersja zgłasza wyjątek:
  • do czego powinien się skonwertować znak inny niż "1" lub "0"?
  • to ciąg znaków składający się z więcej niż jednego znaku, ważnego wejścia dla funkcji?

Jestem pewien, że są inni - to jest radość z projektowania interfejsu API!

+0

To najlepsza metoda, jak sądzę. Używanie 'at' jako czeku jest bardzo czyste. – GManNickG

+4

@GMan: Nie jestem pewien, czy się z tym zgadzam. W C 0 oznacza fałsz, a wszystko inne jest prawdziwe. Zatem 2 jest prawdziwe, 03 jest prawdziwe, itd. Tak więc, chociaż pytanie jest niedookreślone, rozsądnie jest założyć, że wszystko, co nie jest zerem, jest prawdziwe. –

+0

@Chris Jak o "00"? Mój punkt widzenia w tej odpowiedzi brzmiał, że nawet w przypadku tak prostej funkcji, istnieje wiele problemów, które należy zbadać. –

0

Spróbuj tego:

bool value; 

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

Niestety, pozostawia to wartość w stanie nieokreślonym, jeśli łańcuch powinien zawierać coś innego. – UncleBens

+3

@UncleBens: Bardziej prawdopodobne, jego wartość będzie FileNotFound. :-P –

+1

Chris: I rofl'd. – GManNickG

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

bym zmienić brzydkie funkcję zwracającą ten ciąg w pierwszej kolejności. Po to jest bool.

+0

Nie mam kontroli nad tą funkcją, jest to biblioteka strony trzeciej. – cquillen

+0

Biblioteka wydaje się jednak trochę głupia. Czy istnieje jakikolwiek powód, dla którego powinien on używać 'std :: string' ze wszystkich rzeczy dla powrotu boolowskiego? – UncleBens

+0

@UncleBens - może używa std :: string jako typu "wariant". –

0

oto sposób podobny do Kyle'a oprócz tego, że obsługuje zer i rzeczy:

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

Ale ale ale ... "DEADBEEF" będzie traktowany jako fałszywy! :-P –

+0

A dlaczego miałaby to być prawda? –

+0

@Andreas: Tradycją C jest to, że 0 jest fałszywe, a wszystko inne jest prawdą. Idealnie chciałbym rzucić wyjątek w tym przypadku, ale jeśli to nie jest opcja, to prawda jest "mniej błędna" niż fałszywa, według mnie. –

2

I d używaj tego, co robi, co chcesz, i łapie przypadek błędu.

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

Zawsze możesz owinąć zwrócony ciąg w klasie, która obsługuje koncepcję logicznych ciągów:

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

połączeń coś takiego:

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

Która rzuci invalid_argument jeśli reguła dotycząca "0" i "1" jest naruszona.

+1

Nie wszystko musi być klasą; bezpłatna funkcja jest znacznie czystsza i bezpieczniejsza. – GManNickG

+0

@GMan, byłbym pierwszy, który to powiedziałby :) –

9

Albo zależy Ci na możliwości uzyskania nieprawidłowej wartości zwrotu, albo nie. Większość dotychczasowych odpowiedzi znajduje się w środkowej części, chwytając kilka ciągów poza "0" i "1", być może racjonalizując, jak powinny zostać przekształcone, być może rzucając wyjątek. Nieprawidłowe dane wejściowe nie mogą wygenerować prawidłowych danych wyjściowych i nie należy ich akceptować.

Jeśli nie zależy Ci na nieprawidłowych zwrotach, użyj s[0] == '1'. To bardzo proste i oczywiste. Jeśli musisz uzasadnić swoją tolerancję wobec kogoś, powiedz, że konwertuje niepoprawne dane wejściowe na fałsz, a pusty łańcuch prawdopodobnie będzie pojedynczym \0 w implementacji STL, więc jest dość stabilny. s == "1" jest również dobry, ale s != "0" wydaje mi się dla mnie rozwlekły i sprawia, że ​​jest on nieprawidłowy => true.

Jeżeli dbam o błędach (i prawdopodobnie powinno), użyj

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

Ten łapie wszystkie błędy, ale także wprost oczywiste i proste dla każdego, kto zna smidgen C, i nic nie będzie wykonywać szybciej .

61

Dziwię się, że nikt nie wspomniał o tym jednym:

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

lub

bool b; 
istringstream("true") >> std::boolalpha >> b; 
+2

Reputacja nie zawsze idzie w parze z odpowiedzią (imho). :) – gsamaras

+0

Nice! To działało dla mnie przy użyciu interfejsu Lua C API.Przypuszczam, że C nie ma typu danych boolean ; lua_toboolean() zwraca wartość int 0 lub 1, więc wydaje się, że działa to w C++. – Artorias2718

+0

Tak, to strumienie C++ https://www.cprogramming.com/tutorial/c++-iostreams.html. –

5

Istnieje również std :: Stoi w C++ 11:

wartość bool = std :: stoi (someString.c_str());