Konwersja bool na tekst w C ++


93

Może to głupie pytanie, ale czy istnieje sposób na przekonwertowanie wartości logicznej na ciąg znaków w taki sposób, że 1 zamienia się w „prawda”, a 0 w „fałsz”? Mógłbym po prostu użyć instrukcji if, ale byłoby miło wiedzieć, czy można to zrobić z językiem lub standardowymi bibliotekami. Poza tym jestem pedantem. :)


6
Sprzeciw! A co z lokalizacją? Dlaczego sam język miałby zawierać stałe dosłowne specyficzne dla języka?
valdo

1
@valdo - Jestem prawie pewien, że w przypadku projektu, nad którym pracowałem, internacjonalizacja nie była problemem. W tamtym czasie był to prawdopodobnie projekt szkolny.
Jason Baker

Odpowiedzi:


119

Co powiesz na użycie samego języka C ++?

bool t = true;
bool f = false;
std::cout << std::noboolalpha << t << " == " << std::boolalpha << t << std::endl;        
std::cout << std::noboolalpha << f << " == " << std::boolalpha << f << std::endl;

AKTUALIZACJA:

Jeśli chcesz więcej niż 4 linie kodu bez wyjścia konsoli, przejdź do cppreference.com na stronie mówisz std::boolalphaistd::noboolalpha który pokazuje wyjście konsoli i wyjaśnia więcej o API.

Dodatkowo użycie std::boolalphazmodyfikuje globalny stan std::cout, możesz chcieć przywrócić oryginalne zachowanie, przejdź tutaj, aby uzyskać więcej informacji na temat przywracania stanustd::cout .


Jestem kompletnym nowicjuszem w C ++. Czy ktoś może mi wyjaśnić, jak to działa?
Chucky,

4
@Chucky Nie będziesz w stanie zrozumieć, jak to działa, dopóki nie zrozumiesz przeciążenia operatora . Wyjaśnienie, jak to działa, wykraczałoby daleko poza zakres tego pytania. Musisz albo opublikować to jako inne pytanie, albo poszukać istniejących odpowiedzi na to pytanie. Polecam to drugie .
Michael Dorst,

2
To wyświetla tylko wartości logiczne jako tekst, nie konwertuje ich na tekst / ciąg.
atoMerz

Więc w jaki sposób nie spełnia to kryterium „konwersji wartości logicznej na łańcuch” podanego przez OP?
graham.reeds

2
Ten kod nie konwertuje wartości logicznej na ciąg. Utwórz zmienną std::string stri zapisz w niej wynik konwersji, jeśli możesz.
rozina

77

Mówimy o C ++, prawda? Dlaczego u licha nadal używamy makr !?

Funkcje wbudowane C ++ zapewniają taką samą szybkość jak makra, z dodatkową zaletą bezpieczeństwa typu i oceny parametrów (co pozwala uniknąć problemu, o którym wspominali Rodney i dwj.

inline const char * const BoolToString(bool b)
{
  return b ? "true" : "false";
}

Poza tym mam kilka innych zastrzeżeń, szczególnie w odniesieniu do zaakceptowanej odpowiedzi :)

// this is used in C, not C++. if you want to use printf, instead include <cstdio>
//#include <stdio.h>
// instead you should use the iostream libs
#include <iostream>

// not only is this a C include, it's totally unnecessary!
//#include <stdarg.h>

// Macros - not type-safe, has side-effects. Use inline functions instead
//#define BOOL_STR(b) (b?"true":"false")
inline const char * const BoolToString(bool b)
{
  return b ? "true" : "false";
}

int main (int argc, char const *argv[]) {
    bool alpha = true;

    // printf? that's C, not C++
    //printf( BOOL_STR(alpha) );
    // use the iostream functionality
    std::cout << BoolToString(alpha);
    return 0;
}

Twoje zdrowie :)


@DrPizza: Dołącz całą bibliotekę doładowania ze względu na tak prostą funkcję? Chyba sobie żartujesz?


@NathanFellman, zaakceptowana odpowiedź jest zbyt wolna. Można to ulepszyć, stringjeśli stałe łańcuchowe dla „true” i „false” są przechowywane w statycznych zmiennych stałych.
Serge Rogatch

Jest to problematyczna odpowiedź, ponieważ: 1. Czasami wolisz „tak” lub „nie” zamiast „prawda lub„ fałsz ”, a czasami„ sukces ”kontra„ porażka ”itp. 2. Czasami chcesz mieć małe litery, czasem duże przypadek, czasami tytułowy.
einpoklum

2
Przeczytaj pytanie, dokładnie o to poproszono.
Dz.

@einpoklum Nic nie stoi na przeszkodzie, aby utworzyć tyle funkcji wbudowanych, ile chcesz.
rozina

2
w trudnej sytuacji możesz zrobić:cout << (bool_x ? "true": "false") << endl;
Trevor Boyd Smith

22

C ++ ma odpowiednie ciągi znaków, więc równie dobrze możesz ich używać. Znajdują się w standardowym ciągu nagłówkowym. #include <string>, aby ich użyć. Nigdy więcej przepełnień bufora strcat / strcpy; nigdy więcej brakujących terminatorów zerowych; koniec z niechlujnym ręcznym zarządzaniem pamięcią; odpowiednio policzone ciągi z odpowiednią semantyką wartości.

C ++ ma również możliwość konwertowania wartości logicznych na reprezentacje czytelne dla człowieka. Widzieliśmy wskazówki na ten temat wcześniej w przykładach iostream, ale są one nieco ograniczone, ponieważ mogą wysyłać tekst tylko do konsoli (lub za pomocą fstreams, pliku). Na szczęście projektanci C ++ nie byli kompletnymi idiotami; mamy również iostreamy, które są obsługiwane nie przez konsolę lub plik, ale przez automatycznie zarządzany bufor ciągu. Nazywają się stringstreams. #include <sstream>, aby je pobrać. Wtedy możemy powiedzieć:

std::string bool_as_text(bool b)
{
    std::stringstream converter;
    converter << std::boolalpha << b;   // flag boolalpha calls converter.setf(std::ios_base::boolalpha)
    return converter.str();
}

Oczywiście nie chcemy tego wszystkiego pisać. Na szczęście C ++ ma również wygodną bibliotekę innej firmy o nazwie Boost, która może nam tutaj pomóc. Boost ma fajną funkcję o nazwie lexical_cast. Możemy to wykorzystać w ten sposób:

boost::lexical_cast<std::string>(my_bool)

Otóż, prawdą jest, że jest to większe obciążenie niż niektóre makra; stringstreams radzą sobie z lokalizacjami, o które możesz nie dbać, i tworzą dynamiczny ciąg (z alokacją pamięci), podczas gdy makro może dać literał łańcuchowy, co pozwala uniknąć tego. Ale z drugiej strony metoda stringstream może być używana do wielu konwersji między reprezentacjami drukowanymi i wewnętrznymi. Możesz je cofnąć; boost :: lexical_cast <bool> ("true") robi na przykład właściwą rzecz. Możesz ich używać z liczbami, a właściwie z każdym typem, z odpowiednio sformatowanymi operatorami I / O. Są więc dość wszechstronne i przydatne.

A jeśli po tym wszystkim twoje profilowanie i testy porównawcze ujawnią, że lexical_casts są niedopuszczalnym wąskim gardłem, to wtedy powinieneś rozważyć zrobienie jakiegoś makrorestrora .


3
boost :: lexical_cast <bool> ("true") wydaje się zgłaszać wyjątek bad_lexical_cast
użytkownik

3
nie działa w mojej aplikacji, "isExist:" + boost :: lexical_cast <std :: string> (isExit)); wyniki isExist: 0
Scott 混合 理论

8

To powinno wystarczyć:


const char* bool_cast(const bool b) {
    return b ? "true" : "false";
}

Ale jeśli chcesz to zrobić więcej C ++ - ish:


#include <iostream>
#include <string>
#include <sstream>
using namespace std;

string bool_cast(const bool b) {
    ostringstream ss;
    ss << boolalpha << b;
    return ss.str();
}

int main() {
    cout << bool_cast(true) << "\n";
    cout << bool_cast(false) << "\n";
}

5

Jeśli zdecydujesz się użyć makr (lub używasz C w przyszłym projekcie), powinieneś dodać nawias wokół `` b '' w rozwinięciu makra (nie mam jeszcze wystarczającej liczby punktów, aby edytować zawartość innych osób):

#define BOOL_STR(b) ((b)?"true":"false")

Jest to defensywna technika programowania , która chroni przed ukrytymi błędami kolejności operacji; tj. jak to ocenia się dla wszystkich kompilatorów?

1 == 2 ? "true" : "false"

w porównaniu do

(1 == 2) ? "true" : "false"

Nawet przed uzyskaniem de 2k rep faktycznie można edytować zawartość innych osób. Zostanie sprawdzone, ale oczywiście możesz.
SysDragon,

2

Używam trójskładnika w printf takim jak ten:

printf("%s\n", b?"true":"false");

Jeśli zrobisz to makro:

B2S(b) ((b)?"true":"false")

wtedy musisz upewnić się, że wszystko, co mijasz 'b', nie ma żadnych skutków ubocznych. I nie zapomnij o nawiasach wokół znaku, 'b'ponieważ mogą wystąpić błędy kompilacji.


Ponieważ „b” pojawia się tylko raz w definicji makra, dlaczego ostrzegasz przed skutkami ubocznymi?
postfuturist

2

W C ++ 11 możesz użyć lambdy, aby uzyskać nieco bardziej zwarty kod i użycie w miejscu:

bool to_convert{true};
auto bool_to_string = [](bool b) -> std::string {
    return b ? "true" : "false";
};
std::string str{"string to print -> "};
std::cout<<str+bool_to_string(to_convert);

Wydruki:

string to print -> true


1

Bez wciągania w to ostreama:

constexpr char const* to_c_str(bool b) {
   return  
    std::array<char const*, 2>{"false", "true "}[b]
   ;
};


0

A co z prostymi:

constexpr char const* toString(bool b)
{
   return b ? "true" : "false";
}

-5

Zgadzam się, że najlepiej pasuje makro. Właśnie przygotowałem przypadek testowy (uwierz mi, nie jestem dobry z C / C ++, ale brzmiało to fajnie):

#include <stdio.h>
#include <stdarg.h>

#define BOOL_STR(b) (b?"true":"false")

int main (int argc, char const *argv[]) {
    bool alpha = true;
    printf( BOOL_STR(alpha) );
    return 0;
}

-5

Tak długo, jak ciągi znaków mogą być postrzegane bezpośrednio jako tablica std::stringznaków, naprawdę trudno będzie mnie przekonać, że reprezentują łańcuchy jako obywatele pierwszej klasy w C ++.

Poza tym połączenie alokacji i ograniczenia wydaje mi się i tak złym pomysłem.


-7

Wypróbuj to makro. Wszędzie tam, gdzie chcesz, aby pojawiło się „prawda” lub fałsz, po prostu zastąp je PRINTBOOL (zmienna), gdzie zmienna jest wartością logiczną, dla której chcesz znaleźć tekst.

#define PRINTBOOL(x) x?"true":"false"

2
Potrzebujesz nawiasów w tym makrze, prawdopodobnie dlatego otrzymałeś głos przeciw.
postfuturist
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.