Преобразование bool в текст в C ++

94

Может быть, это глупый вопрос, но есть ли способ преобразовать логическое значение в строку так, чтобы 1 превратилось в «истину», а 0 превратилось в «ложь»? Я мог бы просто использовать оператор if, но было бы неплохо узнать, есть ли способ сделать это с помощью языка или стандартных библиотек. Плюс я педант. :)

Джейсон Бейкер
источник
6
Возражение! А как насчет локализации? Почему сам язык должен содержать специфические для языка буквальные константы?
valdo
1
@valdo - я почти уверен, что для проекта, над которым я работал, интернационализация не была проблемой. В то время это был скорее школьный проект.
Джейсон Бейкер

Ответы:

119

Как насчет использования самого языка 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;

ОБНОВИТЬ:

Если вам нужно более 4 строк кода без вывода на консоль, перейдите на страницу cppreference.com, где рассказывается std::boolalphaи наstd::noboolalpha которой показан вывод консоли и более подробно объясняется API.

Кроме того, использование std::boolalphaизменит глобальное состояние std::cout, вы можете захотеть восстановить исходное поведение, перейдите сюда для получения дополнительной информации о восстановлении состоянияstd::cout .

graham.reeds
источник
Я новичок в C ++. Может кто-нибудь объяснить мне, как это работает?
Чаки
4
@Chucky Вы не сможете понять, как это работает, пока не поймете перегрузку оператора . Объяснение того, как это работает, выходит далеко за рамки этого вопроса. Вам нужно будет либо опубликовать его как другой вопрос, либо найти существующие ответы на этот вопрос. Я рекомендую последнее .
Майкл Дорст,
2
Это только печатает логические значения как текст, но не преобразует их в текст / строку.
atoMerz
Итак, каким образом это не соответствует критериям «преобразовать логическое значение в строку», заданным OP?
graham.reeds
2
Этот код не преобразует логическое значение в строку. Создайте переменную std::string strи сохраните в ней результат преобразования, если можете.
rozina
77

Мы ведь говорим о C ++? Почему мы все еще используем макросы !?

Встроенные функции C ++ дают вам ту же скорость, что и макрос, с дополнительным преимуществом безопасности типов и оценки параметров (что позволяет избежать проблемы, о которой упоминали Родни и dwj.

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

Помимо этого у меня есть еще несколько нареканий, особенно с принятым ответом :)

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

Ура :)


@DrPizza: Включить целую библиотеку ускорения ради такой простой функции? Ты наверное шутишь?

OJ.
источник
@NathanFellman, принятый ответ слишком медленный. Это можно улучшить, stringесли строковые константы для «истина» и «ложь» хранятся в статических константных переменных.
Серж Рогач
Это проблемный ответ, поскольку: 1. Иногда вам нужно «да» или «нет», а не «истина или ложь», а иногда «успех» или «неудача» и т. Д. 2. Иногда вам нужны строчные буквы, иногда верхние. случай, иногда заголовок
einpoklum
2
Прочтите вопрос, это именно то, что просили.
OJ.
@einpoklum Ничто не мешает вам создать столько встроенных функций для желаемых преобразований, сколько вы хотите.
rozina
2
в кранче вы можете:cout << (bool_x ? "true": "false") << endl;
Trevor Boyd Smith
22

В C ++ есть правильные строки, так что вы можете их использовать. Они находятся в стандартной строке заголовка. #include <string>, чтобы использовать их. Больше никаких переполнений буфера strcat / strcpy; больше нет пропущенных нулевых терминаторов; больше никакого беспорядочного ручного управления памятью; правильные подсчитанные строки с правильной семантикой значений.

C ++ также может преобразовывать bools в удобочитаемые представления. Мы видели намеки на это ранее в примерах iostream, но они немного ограничены, потому что они могут только выводить текст на консоль (или с fstreams, файл). К счастью, разработчики C ++ не были полными идиотами; у нас также есть iostreams, которые поддерживаются не консолью или файлом, а автоматически управляемым строковым буфером. Их называют струнными потоками. #include <sstream>, чтобы получить их. Тогда мы можем сказать:

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

Конечно, мы не хотим все это печатать. К счастью, в C ++ также есть удобная сторонняя библиотека Boost, которая может нам здесь помочь. У Boost есть замечательная функция lexical_cast. Мы можем использовать это так:

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

Верно сказать, что это больше накладных расходов, чем какой-либо макрос; строковые потоки имеют дело с языковыми стандартами, которые могут вас не беспокоить, и создают динамическую строку (с выделением памяти), тогда как макрос может выдавать буквальную строку, что позволяет избежать этого. Но с другой стороны, метод stringstream можно использовать для множества преобразований между печатным и внутренним представлениями. Вы можете запустить их назад; boost :: lexical_cast <bool> ("true"), например, поступает правильно. Вы можете использовать их с числами и фактически с любым типом с правильно отформатированными операторами ввода-вывода. Так что они довольно универсальны и полезны.

И если после всего этого ваша профилирование и бенчмаркинга показывает , что lexical_casts являются неприемлемыми узким местом, это когда вы должны рассмотреть возможность сделать некоторые макро ужас.

DrPizza
источник
3
boost :: lexical_cast <bool> ("true"), похоже, генерирует исключение bad_lexical_cast
Пользователь
3
не работает в моем приложении "isExist:" + boost :: lexical_cast <std :: string> (isExit)); результаты isExist: 0
Scott 混合 理论
8

Это должно быть нормально:


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

Но, если вы хотите сделать это больше, C ++ - иш:


#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";
}
Тень2531
источник
5

Если вы решите использовать макросы (или используете C в будущем проекте), вы должны добавить скобки вокруг «b» в раскрытии макроса (у меня пока недостаточно очков для редактирования чужого контента):

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

Это метод защитного программирования , который защищает от скрытых ошибок порядка операций; т.е. как это оценивается для всех компиляторов?

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

по сравнению с

(1 == 2) ? "true" : "false"
dwj
источник
Даже до того, как у вас появилось 2k репутации, вы действительно могли редактировать контент других людей. Он будет рассмотрен, но, конечно, можно.
SysDragon 05
2

Я использую тернар в printf вот так:

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

Если вы сделаете макрос:

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

тогда вам нужно убедиться, что все, что вы вводите 'b', не имеет побочных эффектов. И не забудьте скобки вокруг, 'b'поскольку вы можете получить ошибки компиляции.

Натан Феллман
источник
Поскольку 'b' появляется в определении макроса только один раз, почему вы предупреждаете о побочных эффектах?
постфутурист
2

В C ++ 11 вы можете использовать лямбда, чтобы получить немного более компактный код и использовать его на месте:

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

Печать:

string to print -> true
Федерико Спинелли
источник
1

Этот пост старый, но теперь вы можете использовать его std::to_stringдля преобразования большого количества переменных вstd::string .

http://en.cppreference.com/w/cpp/string/basic_string/to_string

Эрван Гуйомар
источник
1
Вы можете, но если вы сделаете это с переменной типа bool, она просто преобразует числовое значение «1» или «0», а не «истина» или «ложь».
David E
1

Не перетаскивая в него ostream:

constexpr char const* to_c_str(bool b) {
   return  
    std::array<char const*, 2>{"false", "true "}[b]
   ;
};
ewd
источник
0

Как насчет простого:

constexpr char const* toString(bool b)
{
   return b ? "true" : "false";
}
carlsb3rg
источник
0

C ++ 20 std::format("{}"

https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification утверждает, что форматом вывода по умолчанию будет строка по умолчанию:

auto s6 = std::format("{:6}", true);  // value of s6 is "true  "

а также:

Доступные типы представления bool:

  • none, s: копирует текстовое представление (истина или ложь, или форма, зависящая от локали) в вывод.
  • b, B, c, d, o, x, X: используются целочисленные типы представления со значением static_cast (value).

Связано: форматирование std :: string, например sprintf

Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
-5

Я согласен, что лучше всего подойдет макрос. Я только что создал тестовый пример (поверьте, я плохо разбираюсь в C / C ++, но это звучало весело):

#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

Пока строки можно рассматривать непосредственно как массив символов, будет очень сложно убедить меня, что std::stringстроки представляют собой первоклассных граждан в C ++.

Кроме того, комбинирование выделения и ограниченности в любом случае кажется мне плохой идеей.

Мат Ногучи
источник
-7

Попробуйте этот макрос. В любом месте, где вы хотите, чтобы отображалось значение «true» или «false», просто замените его на PRINTBOOL (var), где var - это логическое значение, для которого вы хотите ввести текст.

#define PRINTBOOL(x) x?"true":"false"
дагорым
источник
2
В этом макросе нужны круглые скобки, вероятно, поэтому вы получили отрицательный голос.
постфутурист