Що таке специфікатор формату printf для bool?

Оскільки в ANSI C99 є _Bool або bool через stdbool.h . Але чи є також специфікатор формату printf для bool?

Я маю на увазі щось на зразок цього псевдокоду:

bool x = true;
printf("%B\n", x);

який буде друкувати:

true
298
@billinkc, моє запитання не зовсім про те, що найкращим способом є друк значень bool - це конкретний специфікатор printf. Що, здається, не існує. Інший кут до хорошої відповіді буде: можливо, є спосіб додати спеціальний специфікатор формату до printf, який перетворює bool ...
додано Автор maxschlepzig, джерело
@billinkc, моє запитання не зовсім про те, що найкращим способом є друк значень bool - це конкретний специфікатор printf. Що, здається, не існує. Інший кут до хорошої відповіді буде: можливо, є спосіб додати спеціальний специфікатор формату до printf, який перетворює bool ...
додано Автор maxschlepzig, джерело
Ви можете прочитати це для отримання додаткової інформації cplusplus.com/reference/cstdio/printf Ви завжди може це зробити!
додано Автор Varvarigos Emmanouil, джерело
Ви можете прочитати це для отримання додаткової інформації cplusplus.com/reference/cstdio/printf Ви завжди може це зробити!
додано Автор Varvarigos Emmanouil, джерело
додано Автор billinkc, джерело
Яскраво виражений, хоча я, здається, не маю здатності розповідати VtC, тому мені доведеться тільки чекати, поки моє голосування закінчиться.
додано Автор billinkc, джерело
Яскраво виражений, хоча я, здається, не маю здатності розповідати VtC, тому мені доведеться тільки чекати, поки моє голосування закінчиться.
додано Автор billinkc, джерело
@ maxxschlepzig: єдиним способом вирішення проблеми є перевірка документації. Якщо ви використовуєте GNU/Linux (наприклад, оскільки ви не розповіли нам про вашу систему), ви можете ознайомитись з останніми інструкціями з друку на сторінці [man pages] (man7.org). Якщо ви хочете отримати друковані рядки "true"/"false", ви можете побудувати їх вручну, це досить просто.
додано Автор Bulat M., джерело
@ maxxschlepzig: єдиним способом вирішення проблеми є перевірка документації. Якщо ви використовуєте GNU/Linux (наприклад, оскільки ви не розповіли нам про вашу систему), ви можете ознайомитись з останніми інструкціями з друку на сторінці [man pages] (man7.org). Якщо ви хочете отримати друковані рядки "true"/"false", ви можете побудувати їх вручну, це досить просто.
додано Автор Bulat M., джерело

9 Відповіді

Не існує. Але оскільки будь-який інтегральний тип, коротший за int , підвищується до int при передачі до варіаційних аргументів printf() , ви можете використовувати % d :

bool x = true;
printf("%d\n", x);//prints 1

Але чому б і ні

printf(x ? "true" : "false");

або краще

printf("%s", x ? "true" : "false");

або навіть краще

fputs(x ? "true" : "false", stdout);

замість цього?

492
додано
Чому fputs "ще краще"? Я завжди шукаю способів покращити мій С. При яких обставинах слід використовувати fputs замість printf ?
додано Автор Arc676, джерело
@r: Як це може бути небезпечним? Вона не містить будь-якого специфікатора формату в рядку форматування - незалежно від того, що повертає оператор трійчастий, рядок формату завжди ідеально зберігати чистий літерний ряд.
додано Автор Kaiserludi, джерело
Я хотів би стверджувати, що printf ("% s", x? "True": "false"); краще , що printf (x? "true": "false"); - ви перебуваєте в загальному керуванні строкою формату, тому існує не Ви отримаєте щось на зразок "% d" , що може спричинити проблеми. З іншого боку, fputs - кращий параметр .
додано Автор paxdiablo, джерело
Я б це поставив +1, якщо ви позбавите вираз, що не є одним рядком, як строку форматування. Цей вид використання легко перетворюється на небезпечне використання. printf ("% s", x? "true": "false"); виправити проблему.
додано Автор R.., джерело
У моєму випадку % d дає -1 або 0. І % ld дає MAX_INT.
додано Автор user2284570, джерело
Я зробив це +1, але я не впевнений у вашому коментарі щодо "принтів 1." Я не читав стандарт, але я, здається, нагадую з інших текстів, що читають, що false дорівнює нулю, а true є «ненульовим». Виходячи з реалізації, він може надрукувати 9, 24 або навіть негативне значення, наприклад -1. Якщо я правильний, можливо, ви захочете оновити свій коментар, щоб сказати "друкує ненульовий", щоб ще більше перешкодити цьому несприятливому методу.
додано Автор Luv2code, джерело
Внизу для "чому ні". Це як кажуть "чому не просто форматувати все самостійно?". Очевидна відповідь полягає в тому, що "я використовую форматування друку, сподіваюсь, що ви зможете розумно форматувати всі мої типи".
додано Автор GreenAsJade, джерело
Чому fputs (x? True: false, stdout) краще, ніж printf ("% s", x? "True": "false"); а останній краще, ніж printf (x? "true": "false"); ?
додано Автор HelloGoodbye, джерело
Для "чому б не" частина цієї відповіді - специфікатор формату для bool дозволить використовувати рядок формату так, як призначено: для конструювання рядка з сумішшю літералів та значень.
додано Автор noamtm, джерело
@ Arc676, для рядка без форматування, fputs є швидшим і простішим, ніж printf (який повинен аналізувати рядок, що шукає символи форматування). Використання fputs (stdout), а не просто puts() (який за умовчанням до stdout) виключає новий рядок, який додає() до виходу.
додано Автор Chad, джерело
@HelloGoodbye, передавання одного char * до printf() вважається поганою практикою, оскільки вона дійсно повинна бути рядком формату, а знак відсоткового відсотка може призвести до того, що ваша програма підірвати ( подивитися тут, щоб більше ). Таким чином, printf ("% s", ...) безпечніше. Якщо вам не потрібно робити жодного реального форматування , перш за все, функція сімейства printf є надлишковою, а puts() (або fputs() , якщо вам потрібно роздрукувати stderr ), тому що воно є більш ефективним/лаконічним.
додано Автор sevko, джерело
@R .. Або puts() , а сьогодні не виникає жодної атаки на формат moar. : П.
додано Автор user529758, джерело

Немає специфікатора формату для bool. Ви можете роздрукувати його за допомогою деяких існуючих специфікаторів для друку інтегральних типів або робити щось більше фантастичне:

 printf("%s", x?"true":"false");
32
додано
@IvayloStrandjev: Так, там це тип bool у C, а не в C89 - це частина специфікації мови C99. Існує нове ключове слово _Bool , а якщо ви включаєте , то bool є синонімом _Bool .
додано Автор Adam Rosenfield, джерело
У будь-якому випадку, @ H2CO3 я запропонував рішення, яке друкує "true" та "false" як запити OP. Я також трохи змінив свою формулювання з тієї частини, яку ви згадуєте.
додано Автор Ivaylo Strandjev, джерело
Дякую. Я виправив мою відповідь
додано Автор Ivaylo Strandjev, джерело
Кидок не потрібний.
додано Автор user529758, джерело

Немає специфікатора формату для bool. Ви можете роздрукувати його за допомогою деяких існуючих специфікаторів для друку інтегральних типів або робити щось більше фантастичне:

 printf("%s", x?"true":"false");
32
додано
@IvayloStrandjev: Так, там це тип bool у C, а не в C89 - це частина специфікації мови C99. Існує нове ключове слово _Bool , а якщо ви включаєте , то bool є синонімом _Bool .
додано Автор Adam Rosenfield, джерело
У будь-якому випадку, @ H2CO3 я запропонував рішення, яке друкує "true" та "false" як запити OP. Я також трохи змінив свою формулювання з тієї частини, яку ви згадуєте.
додано Автор Ivaylo Strandjev, джерело
Дякую. Я виправив мою відповідь
додано Автор Ivaylo Strandjev, джерело
Кидок не потрібний.
додано Автор user529758, джерело

ANSI C99/C11 не включають додатковий специфікатор перетворення printf для bool .

Але бібліотека GNU C містить API для додавання власних специфікаторів .

Приклад:

#include 
#include 
#include 

static int bool_arginfo(const struct printf_info *info, size_t n,
    int *argtypes, int *size)
{
  if (n) {
    argtypes[0] = PA_INT;
    *size = sizeof(bool);
  }
  return 1;
}
static int bool_printf(FILE *stream, const struct printf_info *info,
    const void *const *args)
{
  bool b =  *(const bool*)(args[0]);
  int r = fputs(b ? "true" : "false", stream);
  return r == EOF ? -1 : (b ? 4 : 5);
}
static int setup_bool_specifier()
{
  int r = register_printf_specifier('B', bool_printf, bool_arginfo);
  return r;
}
int main(int argc, char **argv)
{
  int r = setup_bool_specifier();
  if (r) return 1;
  bool b = argc > 1;
  r = printf("The result is: %B\n", b);
  printf("(written %d characters)\n", r);
  return 0;
}

Оскільки це розширення GLIBC, GCC попереджає про цей користувацький специфікатор:

$ gcc -Wall -g    main.c   -o main
main.c: In function ‘main’:
main.c:34:3: warning: unknown conversion type character ‘B’ in format [-Wformat=]
   r = printf("The result is: %B\n", b);
   ^
main.c:34:3: warning: too many arguments for format [-Wformat-extra-args]

Вихід:

$ ./main
The result is: false
(written 21 characters)
$ ./main 1
The result is: true
(written 20 characters)
25
додано

У традиції itoa() :

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

bool x = true;
printf("%s\n", btoa(x));
11
додано
Або для більш розбещених серед нас: "true \ 0false" [(! X) * 5] :-)
додано Автор paxdiablo, джерело
@panzi: Я не впевнений, що це коштує зусиль, щоб програміст C міг турбуватися про нестандартні ідентифікатори JavaScript.
додано Автор Keith Thompson, джерело
@paxdiablo: приємно! Але ви забули & :-)
додано Автор jxh, джерело
@ MooingDuck: може бути !! x * 5 .
додано Автор jxh, джерело
@MustafaZengin: Правильно!
додано Автор jxh, джерело
@paxdiablo: "false \ 0true" [x * 5] це простіше дотик
додано Автор Mooing Duck, джерело
@ jxh: непотрібна У кодах MOSTS, включаючи * , bool підвищується до int з значенням 1 або 0 , так що це безпечно. Поки x все одно залишається bool . Я бачу вашу точку зору.
додано Автор Mooing Duck, джерело
@panzi нестандартний JavaScript .. це не так ... насправді просто JavaScript ? :)
додано Автор Gewure, джерело
btoa - це "двійковий рядок, що базується на 64 рядках" у нестандартних JavaScript (Gecko та WebKit), тому ви можете використовувати інше ім'я.
додано Автор panzi, джерело
@ Кейт Томпсон Я думаю, що я збентежив питання і якось думав, що це про JavaScript, що взагалі не має сенсу. Ймовірно, пізно вночі.
додано Автор panzi, джерело
@ MooingDuck @jxh, чи не повинно бути це !! x * 6 , тепер що false є одним символом довший, ніж true?
додано Автор Mustafa Zengin, джерело

Ви не можете, але можете роздрукувати 0 або 1

_Bool b = 1;
printf("%d\n", b);

джерело

3
додано

Якщо вам подобається C ++ краще, ніж C, спробуйте це:

#include 
#include 

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;
2
додано

I prefer an answer from Best way to print the result of a bool as 'false' or 'true' in c?, just like

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false \ 0true" + 0 "означає" false ";
  • x == 1, "false \ 0true" + 6 "означає" true ";
2
додано
@plugwash Ви, звичайно, можете змінити його на printf ("% s \ n", "false \ 0true" + 6 * (x? 1: 0)); , який становить лише ... 5% менш читабельна
додано Автор hoosierEE, джерело
Окрім занепокоєння щодо читабельності, пам'ятайте, що це підірве, якщо хтось перейде на значення, відмінне від 0 або 1.
додано Автор plugwash, джерело
Це абсолютно незрозуміло. Мені потрібно добре, поки я зрозумів, що дійсно зробив "false \ 0true" + 6 * x . Якщо ви працюєте в проекті з іншими людьми або просто в проекті, коли базу коду ви хочете зрозуміти x років потому, слід уникати таких конструкцій.
додано Автор HelloGoodbye, джерело
Хоча я бачу, що це може бути більш оптимізованим, оскільки воно не гілкується. Якщо швидкість вашої турботи, це може бути варіант, просто обов'язково поясніть механіку трюку добре в коментарях. Також буде корисним вбудована функція або макрос із самодокументальним найменуванням (але, ймовірно, недостатньо у цьому випадку).
додано Автор HelloGoodbye, джерело
static inline char const * bool2str (_Bool b) {return "false \ 0true" + 6 * x; } int main (void) {printf ("% s! =% s", bool2str (false), bool2str (true)); повернення 0; } Те саме, що і з static inline char decimal2char (int d) {assert (d> = 0 && d <= 9); повернути "0" + d; } ; просто оберніть його в описуючою називається функцію і не турбуйтеся про його читабельність.
додано Автор YoYoYonnY, джерело

Щоб просто роздрукувати 1 або 0 на основі логічного значення, я щойно використовував:

printf("%d\n", !!(42));

Особливо корисно з прапорами:

#define MY_FLAG (1 << 4)
int flags = MY_FLAG;
printf("%d\n", !!(flags & MY_FLAG));
0
додано