@billinkc, мой вопрос на самом деле не о том, как лучше всего печатать значения bool, а о конкретном спецификаторе printf. Которого, кажется, не существует. Другим углом к хорошему ответу было бы: возможно, есть способ добавить пользовательский спецификатор формата в printf, который выполняет преобразование bool ...
maxschlepzig
Справедливо, хотя у меня, похоже, нет возможности распечатать VtC, поэтому мне просто нужно подождать, пока истечет срок моего голосования.
billinkc
@maxschlepzig: единственный способ решить проблему - проверить документацию. Если вы используете GNU / Linux (например, поскольку вы не сообщили нам о своей системе), вы можете прочитать новейшее руководство по printf на [страницах man Linux] (man7.org). Если вы хотите напечатать «истинные» / «ложные» строки, вы можете создать их вручную, это довольно просто.
Булат М.
Ответы:
711
Для boolтипов нет спецификатора формата . Тем не менее, поскольку любой целочисленный тип короче, чем intпродвигается intпри printf()передаче аргументов с переменным аргументом, вы можете использовать %d:
Я бы добавил +1, если вы избавитесь от выражения, не являющегося строковым литералом, в качестве строки формата. Этот вид использования легко превращается в небезопасное использование. printf("%s", x ? "true" : "false");бы решить проблему.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
2
Для части «почему нет» этого ответа - спецификатор формата для bool позволил бы использовать форматную строку, как задумано: для создания строки со смесью литералов и значений.
noamtm
13
Как примечание, я склонен оспаривать это printf("%s", x ? "true" : "false"); это лучше , что printf(x ? "true" : "false");вы - в общем контроле строки формата здесь , поэтому нет нет опасности , что он будет получать что - то подобное , "%d"которое вызвало бы проблемы. fputs, С другой стороны, это лучший вариант.
paxdiablo
15
Почему fputs"еще лучше"? Я всегда ищу способы улучшить мой C. При каких обстоятельствах я должен использовать fputsвместо printf?
Arc676
10
@ Arc676, для строки без форматирования fputs быстрее и проще, чем printf (который должен анализировать строку в поисках символов форматирования). Использование fputs (stdout) вместо просто put () (по умолчанию это stdout) исключает символ новой строки, который приставляет () к выводу.
Чад
45
Для bool нет спецификатора формата. Вы можете распечатать его, используя некоторые из существующих спецификаторов для печати целочисленных типов или сделать что-то более причудливое:
@ H2CO3 В любом случае я предложил решение, печатающее «true» и «false» в качестве запросов OP. Я также немного изменил свою формулировку в части, которую вы упоминаете.
Ивайло Странджев
5
@IvayloStrandjev: Да, там естьbool типа в C, но только не в C89 издание - это часть языка спецификации C99. Есть новое ключевое слово _Bool, и если вы включите <stdbool.h>, то boolэто синоним для _Bool.
Адам Розенфилд
30
ANSI C99 / C11 не включает дополнительный спецификатор преобразования printf для bool .
#include<stdio.h>#include<printf.h>#include<stdbool.h>staticint bool_arginfo(conststruct printf_info *info,size_t n,int*argtypes,int*size){if(n){
argtypes[0]= PA_INT;*size =sizeof(bool);}return1;}staticint bool_printf(FILE *stream,conststruct printf_info *info,constvoid*const*args){bool b =*(constbool*)(args[0]);int r = fputs(b ?"true":"false", stream);return r == EOF ?-1:(b ?4:5);}staticint 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)return1;bool b = argc >1;
r = printf("The result is: %B\n", b);
printf("(written %d characters)\n", r);return0;}
Поскольку это расширение glibc, GCC предупреждает об этом пользовательском спецификаторе:
$ gcc -Wall -g main.c -o main
main.c: в функции 'main':
main.c: 34: 3: предупреждение: неизвестный символ типа преобразования "B" в формате [-Wformat =]
r = printf («Результат:% B \ n», b);
^
main.c: 34: 3: предупреждение: слишком много аргументов для формата [-Wformat-extra-args]
btoaявляется «строкой двоичной строки в базе 64» в нестандартном JavaScript (Gecko и WebKit), поэтому вы можете использовать другое имя.
Panzi
26
@panzi: Я не уверен, что программисту Си стоит потрудиться беспокоиться о нестандартных идентификаторах JavaScript.
Кит Томпсон
5
@KeithThompson Я думаю, что перепутал вопросы и почему-то подумал, что речь идет о JavaScript, что в любом случае не имеет смысла. Это было, вероятно, поздно ночью.
Panzi
9
Или, для более коварных среди нас: "true\0false"[(!x)*5]:-)
Этот ответ не по теме и должен быть удален, поскольку речь идет о другом языке, чем тот, который указан в вопросе.
Лундин
2
@Lundin Я не согласен, что это должно быть удалено. Цель SO - не просто помочь одному человеку, но помочь всем людям с одним и тем же вопросом. Когда я ищу sprintf print boolean как true false c ++ , это первая страница, которая появляется (хотя, возможно, эта страница могла быть лучшим результатом, если этот ответ не существовал). Поскольку C ++ является почти надмножеством C, я не думаю, что такие ответы следует так легко отбрасывать. +1 от меня.
Джефф Г
1
@JeffG Да, такие ответы должны быть удалены, у нас очень четкие правила. Прочитайте вики-теги C и C ++. Этот вопрос бесполезен для программистов на C, особенно потому, что булевы системы C и C ++ совершенно разные и вопрос помечен как C. То, что Google не может понять два конечных ++ в вашем поиске, не является проблемой SO.
Лундин
2
@Lundin Мой комментарий не должен быть истолкован как комментарий к политике SO. Это был действительно комментарий о том, добавляет ли этот ответ конструктивно к вопросу. Этот ответ сразу идентифицируется как только C ++. Никто не придет сюда за ответом только на C, и его не будут обманывать, если он будет думать, что это сработает на C, и тратит время на его попытки. Тем не менее, это отличный ответ для C ++. Если ответы полезны, даже если они не помогают ФП, их не следует хранить? Я думаю, что конструктивные ответы, в которых четко определены предостережения, никогда не следует удалять, независимо от политики.
Джефф Г
1
@JeffG Вы можете поднять это на meta.stackoverflow.com , здесь не место для этого обсуждения.
Лундин
2
Чтобы просто напечатать 1 или 0 на основе логического значения, которое я только что использовал:
Это совершенно непостижимо. Мне потребовалось некоторое время, прежде чем я понял, что на "false\0true"+6*xсамом деле. Если вы работаете в проекте с другими людьми или просто в проекте с базой кода, которую вы хотите понять спустя x лет, таких конструкций следует избегать.
Здравствуйте, до свидания,
3
Хотя я вижу, что это может быть более оптимизировано, поскольку оно не требует ответвлений. Если вам важна скорость, это может быть вариантом, просто обязательно объясните механику, стоящую за этим трюком, в комментарии. Встроенная функция или макрос с самодокументируемым именем также были бы полезны (но, вероятно, не достаточны в этом случае).
Привет, до свидания,
3
Так же как и проблемы с читабельностью, имейте в виду, что это взорвется, если кто-то передаст значение, отличное от 0 или 1.
plugwash
2
@plugwash Конечно, вы можете изменить его на printf("%s\n","false\0true"+6*(x?1:0));... только на 5% менее читабельный.
hoosierEE
static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; } То же, что и с static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; просто оберните его в описательно названную функцию и не беспокойтесь о его удобочитаемости.
Ответы:
Для
bool
типов нет спецификатора формата . Тем не менее, поскольку любой целочисленный тип короче, чемint
продвигаетсяint
приprintf()
передаче аргументов с переменным аргументом, вы можете использовать%d
:Но почему нет:
или лучше:
или даже лучше:
вместо?
источник
printf("%s", x ? "true" : "false");
бы решить проблему.printf("%s", x ? "true" : "false");
это лучше , чтоprintf(x ? "true" : "false");
вы - в общем контроле строки формата здесь , поэтому нет нет опасности , что он будет получать что - то подобное ,"%d"
которое вызвало бы проблемы.fputs
, С другой стороны, это лучший вариант.fputs
"еще лучше"? Я всегда ищу способы улучшить мой C. При каких обстоятельствах я должен использоватьfputs
вместоprintf
?Для bool нет спецификатора формата. Вы можете распечатать его, используя некоторые из существующих спецификаторов для печати целочисленных типов или сделать что-то более причудливое:
источник
bool
типа в C, но только не в C89 издание - это часть языка спецификации C99. Есть новое ключевое слово_Bool
, и если вы включите<stdbool.h>
, тоbool
это синоним для_Bool
.ANSI C99 / C11 не включает дополнительный спецификатор преобразования printf для
bool
.Но библиотека GNU C предоставляет API для добавления пользовательских спецификаторов .
Пример:
Поскольку это расширение glibc, GCC предупреждает об этом пользовательском спецификаторе:
Вывод:
источник
В традиции
itoa()
:источник
btoa
является «строкой двоичной строки в базе 64» в нестандартном JavaScript (Gecko и WebKit), поэтому вы можете использовать другое имя."true\0false"[(!x)*5]
:-)!!x*5
.Вы не можете, но вы можете напечатать 0 или 1
источник
источник
Если вам нравится C ++ лучше, чем C, вы можете попробовать это:
источник
Чтобы просто напечатать 1 или 0 на основе логического значения, которое я только что использовал:
Особенно полезно с флагами:
источник
!!
может быть оптимизированоЯ предпочитаю ответ из Best way, чтобы напечатать результат bool как «false» или «true» в c? , как
источник
"false\0true"+6*x
самом деле. Если вы работаете в проекте с другими людьми или просто в проекте с базой кода, которую вы хотите понять спустя x лет, таких конструкций следует избегать.printf("%s\n","false\0true"+6*(x?1:0));
... только на 5% менее читабельный.static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; }
То же, что и сstatic inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }
; просто оберните его в описательно названную функцию и не беспокойтесь о его удобочитаемости.