Was ist der printf-Formatbezeichner für bool?


457

Seit ANSI C99 gibt es _Booloder boolvia stdbool.h. Aber gibt es auch einen printfFormatbezeichner für bool?

Ich meine so etwas wie in diesem Pseudocode:

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

was drucken würde:

true

1
Sie können dies für weitere Informationen lesen. Cplusplus.com/reference/cstdio/printf Sie können es aber immer schaffen!
Varvarigos Emmanouil


3
@billinkc, meine Frage ist nicht wirklich, wie man Bool-Werte am besten druckt - es geht um einen konkreten printf-Spezifizierer. Welches scheint nicht zu existieren. Ein anderer Winkel zu einer netten Antwort wäre: Vielleicht gibt es eine Möglichkeit, printf einen benutzerdefinierten Formatbezeichner hinzuzufügen, der die Bool-Konvertierung durchführt ...
maxschlepzig

Fair genug, obwohl ich anscheinend nicht in der Lage bin, den VtC freizugeben, muss ich nur warten, bis meine Stimme abläuft.
Billinkc

@maxschlepzig: Die einzige Möglichkeit, das Problem zu lösen, besteht darin, die Dokumentation zu überprüfen. Wenn Sie GNU / Linux verwenden (da Sie uns beispielsweise nichts über Ihr System erzählt haben), können Sie ein aktuelles printf-Handbuch auf [Linux-Manpages] (man7.org) lesen. Wenn Sie möchten, dass "true" / "false" -Strings gedruckt werden, können Sie sie manuell erstellen. Dies ist ziemlich einfach.
Bulat M.

Antworten:


710

Es gibt keinen Formatbezeichner für boolTypen. Da jedoch jeder Integraltyp, der kürzer intist intals bei printf()der Übergabe an die variadischen Argumente heraufgestuft, verwendet wird, können Sie Folgendes verwenden %d:

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

Aber warum nicht:

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

oder besser:

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

oder noch besser:

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

stattdessen?


21
Ich würde dies +1, wenn Sie den Nicht-Single-String-Literal-Ausdruck als Format-String entfernen. Diese Art der Verwendung wird leicht zu einer unsicheren Verwendung. printf("%s", x ? "true" : "false");würde das Problem beheben.
R .. GitHub STOP HELPING ICE

2
Für den "Warum nicht" -Teil dieser Antwort würde ein Formatbezeichner für bool die Verwendung der Formatzeichenfolge wie vorgesehen ermöglichen: zum Erstellen einer Zeichenfolge mit einer Mischung aus Literalen und Werten.
Noamtm

13
Nur als Anmerkung, würde ich in Richtung streit neigen , das printf("%s", x ? "true" : "false");ist besser , dass printf(x ? "true" : "false");- Sie sind insgesamt die Kontrolle über das Format - String hier so gibt es keine Gefahr , dass sie etwas bekommen wie "%d"die Probleme verursachen würde. Die fputs, auf der anderen Seite, ist eine bessere Option.
Paxdiablo

15
Warum ist fputs"noch besser"? Ich bin immer auf der Suche nach Möglichkeiten, mein C zu verbessern. Unter welchen Umständen sollte ich fputsstatt verwenden printf?
Arc676

10
@ Arc676, für eine Zeichenfolge ohne Formatierung ist fputs schneller und einfacher als printf (die die Zeichenfolge analysieren muss, um nach Formatierungszeichen zu suchen). Durch die Verwendung von fputs (stdout) anstelle von put () (standardmäßig stdout) wird die neue Zeile entfernt, die put () an die Ausgabe anfügt.
Tschad

45

Es gibt keinen Formatbezeichner für bool. Sie können es mit einigen der vorhandenen Spezifizierer zum Drucken integraler Typen drucken oder etwas ausgefalleneres tun:

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

Die Besetzung wird nicht benötigt.

@ H2CO3 sowieso habe ich eine Lösung vorgeschlagen, die "wahr" und "falsch" als OP-Anforderungen druckt. Ich habe auch meinen Wortlaut in dem von Ihnen erwähnten Teil leicht geändert.
Ivaylo Strandjev

5
@IvayloStrandjev: Ja, es gibt einen boolTyp in C, nur nicht in der C89-Edition - er ist Teil der C99-Sprachspezifikation. Es gibt ein neues Schlüsselwort _Bool, und wenn Sie es einschließen <stdbool.h>, boolist es ein Synonym für _Bool.
Adam Rosenfield

30

ANSI C99 / C11 enthält keinen zusätzlichen printf-Konvertierungsspezifizierer für bool.

Die GNU C-Bibliothek bietet jedoch eine API zum Hinzufügen benutzerdefinierter Spezifizierer .

Ein Beispiel:

#include <stdio.h>
#include <printf.h>
#include <stdbool.h>

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

Da es sich um eine glibc-Erweiterung handelt, warnt der GCC vor diesem benutzerdefinierten Bezeichner:

$ gcc -Wall -g main.c -o main
main.c: In der Funktion 'main':
main.c: 34: 3: Warnung: Unbekanntes Konvertierungstypzeichen 'B' im Format [-Wformat =]
   r = printf ("Das Ergebnis ist:% B \ n", b);
   ^
main.c: 34: 3: Warnung: Zu viele Argumente für das Format [-Wformat-extra-args]

Ausgabe:

$ ./main
Das Ergebnis ist: false
(21 Zeichen geschrieben)
$ ./main 1
Das Ergebnis ist: wahr
(geschrieben 20 Zeichen)

12

In der Tradition von itoa():

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

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

5
btoaist "Binärzeichenfolge zur Basis 64 Zeichenfolge" in nicht standardmäßigem JavaScript (Gecko und WebKit), daher möchten Sie möglicherweise einen anderen Namen verwenden.
Panzi

26
@panzi: Ich bin mir nicht sicher, ob es sich für einen C-Programmierer lohnt, sich über nicht standardmäßige JavaScript-Kennungen Gedanken zu machen.
Keith Thompson

5
@KeithThompson Ich glaube, ich habe die Fragen verwirrt und irgendwie gedacht, dass es sich um JavaScript handelt, was sowieso keinen Sinn ergibt. Es war wahrscheinlich spät in der Nacht.
Panzi

9
Oder für die "true\0false"[(!x)*5]
hinterhältigeren

1
@MooingDuck: vielleicht !!x*5.
jxh

4

Sie können nicht, aber Sie können 0 oder 1 drucken

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

Quelle


2

Wenn Sie C ++ besser mögen als C, können Sie dies versuchen:

#include <ios>
#include <iostream>

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;

5
Diese Antwort ist nicht zum Thema gehörend und sollte gelöscht werden, da es sich um eine andere Sprache als die in der Frage angegebene handelt.
Lundin

2
@Lundin Ich bin nicht einverstanden, dass dies gelöscht werden sollte. Das Ziel von SO ist nicht nur, einer Person zu helfen, sondern allen Menschen mit der gleichen Frage zu helfen. Wenn ich nach sprintf print boolean als true false c ++ suche , ist dies die erste Seite, die angezeigt wird (obwohl diese Seite möglicherweise das beste Ergebnis war, wenn diese Antwort nicht vorhanden war). Da C ++ fast eine Obermenge von C ist, denke ich nicht, dass solche Antworten so einfach verworfen werden sollten. +1 von mir.
Jeff G

1
@JeffG Ja, solche Antworten sollten gelöscht werden, wir haben sehr klare Richtlinien. Lesen Sie die C- und C ++ - Tag-Wikis. Diese Frage ist für C-Programmierer nicht hilfreich, insbesondere weil die booleschen Systeme C und C ++ völlig unterschiedlich sind und die Frage mit C gekennzeichnet ist. Dass Google die beiden nachfolgenden ++ in Ihrer Suche nicht verstehen kann, ist nicht das Problem von SO.
Lundin

2
@Lundin Mein Kommentar sollte nicht als Kommentar zu den Richtlinien von SO interpretiert werden. Es war wirklich ein Kommentar darüber, ob diese Antwort die Frage konstruktiv ergänzt. Diese Antwort ist sofort nur als C ++ erkennbar. Niemand, der hierher kommt, um eine Antwort nur für C zu erhalten, würde dazu verleitet zu glauben, dass dies in C funktionieren würde, und Zeit damit verschwenden, es zu versuchen. Dies ist jedoch eine gute Antwort für C ++. Wenn Antworten nützlich sind, auch wenn sie dem OP nicht helfen, sollten sie dann nicht aufbewahrt werden? Ich denke, konstruktive Antworten, die eindeutig Vorbehalte identifiziert haben, sollten niemals gelöscht werden, unabhängig von der Politik.
Jeff G

1
@JeffG Sie können es auf meta.stackoverflow.com aufrufen , dies ist nicht der Ort, um diese Diskussion zu führen.
Lundin

2

Um nur 1 oder 0 basierend auf dem booleschen Wert zu drucken, den ich gerade verwendet habe:

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

Besonders nützlich bei Flags:

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

!!
Passen

1

Ich bevorzuge eine Antwort von Bester Weg, um das Ergebnis eines Bools als 'falsch' oder 'wahr' in c zu drucken. , so wie

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false \ 0true" + 0 "bedeutet" false ";
  • x == 1, "false \ 0true" + 6 "bedeutet" true ";

21
Das ist völlig unverständlich. Es dauerte eine Weile, bis ich herausfand, was "false\0true"+6*xwirklich geschah. Wenn Sie in einem Projekt mit anderen Personen arbeiten oder nur in einem Projekt mit einer Codebasis, die Sie x Jahre später verstehen möchten , sollten Konstruktionen wie diese vermieden werden.
HelloGoodbye

3
Obwohl ich sehe, dass dies möglicherweise optimierter ist, da es verzweigungslos ist. Wenn Geschwindigkeit Ihr Anliegen ist, könnte dies eine Option sein. Erklären Sie die Mechanik hinter dem Trick in einem Kommentar. Eine Inline-Funktion oder ein Makro mit einem selbstdokumentierenden Namen wäre ebenfalls hilfreich (aber in diesem Fall wahrscheinlich nicht ausreichend).
HelloGoodbye

3
Neben den Bedenken hinsichtlich der Lesbarkeit ist zu beachten, dass dies
explodiert

2
@plugwash Sie können es natürlich ändern, printf("%s\n","false\0true"+6*(x?1:0));was nur ... 5% weniger lesbar ist.
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; } Gleich wie mit static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; Wickeln Sie es einfach in eine beschreibende benannte Funktion und sorgen Sie sich nicht um die Lesbarkeit.
yyny
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.